From: Marek Olšák Date: Tue, 3 Dec 2019 23:01:31 +0000 (-0500) Subject: gallium: rename 'state tracker' to 'frontend' X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=d6287a94b697ffe12a4e576a38943cdf4e90cdb0;p=mesa.git gallium: rename 'state tracker' to 'frontend' Acked-by: Eric Anholt Acked-by: Alyssa Rosenzweig Acked-by: Pierre-Eric Pelloux-Prayer Part-of: --- diff --git a/docs/sourcetree.html b/docs/sourcetree.html index 8825cd6580b..0e726cf89b9 100644 --- a/docs/sourcetree.html +++ b/docs/sourcetree.html @@ -77,7 +77,7 @@ each directory.
  • program - Vertex/fragment shader and GLSL compiler code
  • sparc - Assembly code/optimizations for SPARC systems (not used with Gallium) -
  • state_tracker - State tracker / driver for Gallium. This +
  • state_tracker - Translator from Mesa to Gallium. This is basically a Mesa device driver that speaks to Gallium. This directory may be moved to src/mesa/drivers/gallium at some point.
  • swrast - Software rasterization module. For drawing points, @@ -127,7 +127,7 @@ each directory. vertex shaders. Geometry shaders will also be implemented in this module.
  • cso_cache - Constant State Objects Cache. Used to filter out - redundant state changes between state trackers and drivers. + redundant state changes between frontends and drivers.
  • gallivm - LLVM module for Gallium. For LLVM-based compilation, optimization and code generation for TGSI shaders. Incomplete. @@ -144,17 +144,17 @@ each directory. creation, memory management, 2D blitting, simple rendering, etc.
  • XXX more -
  • state_trackers - +
  • frontends -
      -
    • clover - OpenCL state tracker -
    • dri - Meta state tracker for DRI drivers -
    • glx - Meta state tracker for GLX -
    • wgl - Windows WGL state tracker -
    • xa - XA state tracker -
    • xvmc - XvMC state tracker -
    • vdpau - VDPAU state tracker -
    • va - VA-API state tracker -
    • omx_bellagio - OpenMAX Bellagio state tracker +
    • clover - OpenCL frontend +
    • dri - Meta frontend for DRI drivers +
    • glx - Meta frontend for GLX +
    • wgl - Windows WGL frontend +
    • xa - XA frontend +
    • xvmc - XvMC frontend +
    • vdpau - VDPAU frontend +
    • va - VA-API frontend +
    • omx_bellagio - OpenMAX Bellagio frontend
  • winsys -
      diff --git a/src/gallium/Android.mk b/src/gallium/Android.mk index 59ee0e0f68b..78e821581b9 100644 --- a/src/gallium/Android.mk +++ b/src/gallium/Android.mk @@ -46,7 +46,7 @@ SUBDIRS += winsys/vc4/drm drivers/vc4 SUBDIRS += winsys/virgl/common winsys/virgl/drm winsys/virgl/vtest drivers/virgl SUBDIRS += winsys/svga/drm drivers/svga SUBDIRS += winsys/etnaviv/drm drivers/etnaviv drivers/renderonly -SUBDIRS += state_trackers/dri +SUBDIRS += frontends/dri SUBDIRS += winsys/iris/drm drivers/iris SUBDIRS += winsys/lima/drm drivers/lima SUBDIRS += winsys/panfrost/drm drivers/panfrost diff --git a/src/gallium/SConscript b/src/gallium/SConscript index e0ffa5f4d0a..5017d5fe247 100644 --- a/src/gallium/SConscript +++ b/src/gallium/SConscript @@ -45,12 +45,12 @@ if env['platform'] == 'windows': if not env['embedded']: if env['x11']: SConscript([ - 'state_trackers/glx/xlib/SConscript', + 'frontends/glx/xlib/SConscript', 'targets/libgl-xlib/SConscript', ]) if env['platform'] == 'windows': SConscript([ - 'state_trackers/wgl/SConscript', + 'frontends/wgl/SConscript', 'targets/libgl-gdi/SConscript', ]) diff --git a/src/gallium/auxiliary/pipe-loader/pipe_loader.h b/src/gallium/auxiliary/pipe-loader/pipe_loader.h index a0d9c8a7dec..b57df804e56 100644 --- a/src/gallium/auxiliary/pipe-loader/pipe_loader.h +++ b/src/gallium/auxiliary/pipe-loader/pipe_loader.h @@ -34,7 +34,7 @@ #define PIPE_LOADER_H #include "pipe/p_compiler.h" -#include "state_tracker/drm_driver.h" +#include "frontend/drm_driver.h" #include "util/xmlconfig.h" #ifdef __cplusplus diff --git a/src/gallium/auxiliary/pipe-loader/pipe_loader_drm.c b/src/gallium/auxiliary/pipe-loader/pipe_loader_drm.c index 7d90285a484..5d6865be1b0 100644 --- a/src/gallium/auxiliary/pipe-loader/pipe_loader_drm.c +++ b/src/gallium/auxiliary/pipe-loader/pipe_loader_drm.c @@ -39,7 +39,7 @@ #include "loader.h" #include "target-helpers/drm_helper_public.h" -#include "state_tracker/drm_driver.h" +#include "frontend/drm_driver.h" #include "pipe_loader_priv.h" #include "util/u_memory.h" diff --git a/src/gallium/auxiliary/pipe-loader/pipe_loader_sw.c b/src/gallium/auxiliary/pipe-loader/pipe_loader_sw.c index c2a3896b8f7..74329e4cba9 100644 --- a/src/gallium/auxiliary/pipe-loader/pipe_loader_sw.c +++ b/src/gallium/auxiliary/pipe-loader/pipe_loader_sw.c @@ -38,9 +38,9 @@ #include "sw/null/null_sw_winsys.h" #include "sw/wrapper/wrapper_sw_winsys.h" #include "target-helpers/sw_helper_public.h" -#include "state_tracker/drisw_api.h" -#include "state_tracker/sw_driver.h" -#include "state_tracker/sw_winsys.h" +#include "frontend/drisw_api.h" +#include "frontend/sw_driver.h" +#include "frontend/sw_winsys.h" struct pipe_loader_sw_device { struct pipe_loader_device base; diff --git a/src/gallium/auxiliary/postprocess/ADDING b/src/gallium/auxiliary/postprocess/ADDING index 3735835142a..67e6bdf9c1f 100644 --- a/src/gallium/auxiliary/postprocess/ADDING +++ b/src/gallium/auxiliary/postprocess/ADDING @@ -65,7 +65,7 @@ drivers/dri/common/xmlpool/t_options.h, and regenerate options.h by running make directory. Use the name you put into filters.h as the config option name. With driconf aware of the option, make Gallium aware of it too. Add it to -state_trackers/dri/common/dri_screen.c in a proper section, specifying its default value and +frontends/dri/common/dri_screen.c in a proper section, specifying its default value and the accepted range (if applicable). Do check that __driNConfigOptions is still correct after the addition. diff --git a/src/gallium/auxiliary/renderonly/renderonly.c b/src/gallium/auxiliary/renderonly/renderonly.c index bfb6b758fbe..2daf36920c0 100644 --- a/src/gallium/auxiliary/renderonly/renderonly.c +++ b/src/gallium/auxiliary/renderonly/renderonly.c @@ -31,7 +31,7 @@ #include #include -#include "state_tracker/drm_driver.h" +#include "frontend/drm_driver.h" #include "pipe/p_screen.h" #include "util/format/u_format.h" #include "util/u_inlines.h" diff --git a/src/gallium/auxiliary/renderonly/renderonly.h b/src/gallium/auxiliary/renderonly/renderonly.h index a8d6a686ed4..fe13fea1495 100644 --- a/src/gallium/auxiliary/renderonly/renderonly.h +++ b/src/gallium/auxiliary/renderonly/renderonly.h @@ -28,7 +28,7 @@ #define RENDERONLY_H #include -#include "state_tracker/drm_driver.h" +#include "frontend/drm_driver.h" #include "pipe/p_state.h" struct renderonly_scanout { diff --git a/src/gallium/auxiliary/target-helpers/drm_helper.h b/src/gallium/auxiliary/target-helpers/drm_helper.h index 01b65d6c7f8..6010631e9a6 100644 --- a/src/gallium/auxiliary/target-helpers/drm_helper.h +++ b/src/gallium/auxiliary/target-helpers/drm_helper.h @@ -4,7 +4,7 @@ #include #include "target-helpers/inline_debug_helper.h" #include "target-helpers/drm_helper_public.h" -#include "state_tracker/drm_driver.h" +#include "frontend/drm_driver.h" #include "util/xmlpool.h" #ifdef GALLIUM_I915 diff --git a/src/gallium/auxiliary/target-helpers/inline_sw_helper.h b/src/gallium/auxiliary/target-helpers/inline_sw_helper.h index c89ef14a6fb..6106cc02044 100644 --- a/src/gallium/auxiliary/target-helpers/inline_sw_helper.h +++ b/src/gallium/auxiliary/target-helpers/inline_sw_helper.h @@ -4,7 +4,7 @@ #include "pipe/p_compiler.h" #include "util/u_debug.h" -#include "state_tracker/sw_winsys.h" +#include "frontend/sw_winsys.h" #ifdef GALLIUM_SWR #include "swr/swr_public.h" diff --git a/src/gallium/auxiliary/target-helpers/sw_helper.h b/src/gallium/auxiliary/target-helpers/sw_helper.h index e129819477d..76cfe14f1d0 100644 --- a/src/gallium/auxiliary/target-helpers/sw_helper.h +++ b/src/gallium/auxiliary/target-helpers/sw_helper.h @@ -5,7 +5,7 @@ #include "pipe/p_compiler.h" #include "util/u_debug.h" #include "target-helpers/sw_helper_public.h" -#include "state_tracker/sw_winsys.h" +#include "frontend/sw_winsys.h" /* Helper function to choose and instantiate one of the software rasterizers: diff --git a/src/gallium/auxiliary/util/u_tests.c b/src/gallium/auxiliary/util/u_tests.c index 00f75906173..a0e9561eeb6 100644 --- a/src/gallium/auxiliary/util/u_tests.c +++ b/src/gallium/auxiliary/util/u_tests.c @@ -38,7 +38,7 @@ #include "tgsi/tgsi_strings.h" #include "tgsi/tgsi_text.h" #include "cso_cache/cso_context.h" -#include "state_tracker/winsys_handle.h" +#include "frontend/winsys_handle.h" #include #define TOLERANCE 0.01 diff --git a/src/gallium/auxiliary/vl/vl_winsys_dri.c b/src/gallium/auxiliary/vl/vl_winsys_dri.c index 1905516a761..524f9f3a162 100644 --- a/src/gallium/auxiliary/vl/vl_winsys_dri.c +++ b/src/gallium/auxiliary/vl/vl_winsys_dri.c @@ -42,7 +42,7 @@ #include "pipe/p_context.h" #include "pipe/p_state.h" #include "pipe-loader/pipe_loader.h" -#include "state_tracker/drm_driver.h" +#include "frontend/drm_driver.h" #include "util/u_memory.h" #include "util/crc32.h" diff --git a/src/gallium/auxiliary/vl/vl_winsys_drm.c b/src/gallium/auxiliary/vl/vl_winsys_drm.c index 9014b97bdfd..bae0405e1f6 100644 --- a/src/gallium/auxiliary/vl/vl_winsys_drm.c +++ b/src/gallium/auxiliary/vl/vl_winsys_drm.c @@ -29,7 +29,7 @@ #include "pipe/p_screen.h" #include "pipe-loader/pipe_loader.h" -#include "state_tracker/drm_driver.h" +#include "frontend/drm_driver.h" #include "util/u_memory.h" #include "vl/vl_winsys.h" diff --git a/src/gallium/drivers/etnaviv/etnaviv_screen.c b/src/gallium/drivers/etnaviv/etnaviv_screen.c index 9fbacd3c49b..d5f445881f3 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_screen.c +++ b/src/gallium/drivers/etnaviv/etnaviv_screen.c @@ -45,7 +45,7 @@ #include "util/u_screen.h" #include "util/u_string.h" -#include "state_tracker/drm_driver.h" +#include "frontend/drm_driver.h" #include "drm-uapi/drm_fourcc.h" diff --git a/src/gallium/drivers/freedreno/freedreno_resource.c b/src/gallium/drivers/freedreno/freedreno_resource.c index 2b89d6afb1e..0586271fe6f 100644 --- a/src/gallium/drivers/freedreno/freedreno_resource.c +++ b/src/gallium/drivers/freedreno/freedreno_resource.c @@ -48,7 +48,7 @@ #include /* XXX this should go away, needed for 'struct winsys_handle' */ -#include "state_tracker/drm_driver.h" +#include "frontend/drm_driver.h" /* A private modifier for now, so we have a way to request tiled but not * compressed. It would perhaps be good to get real modifiers for the diff --git a/src/gallium/drivers/i915/i915_context.h b/src/gallium/drivers/i915/i915_context.h index 1e273260936..7db4174cb21 100644 --- a/src/gallium/drivers/i915/i915_context.h +++ b/src/gallium/drivers/i915/i915_context.h @@ -289,7 +289,7 @@ struct i915_context { struct blitter_context* blitter; }; -/* A flag for each state_tracker state object: +/* A flag for each frontend state object: */ #define I915_NEW_VIEWPORT 0x1 #define I915_NEW_RASTERIZER 0x2 diff --git a/src/gallium/drivers/i915/i915_state.c b/src/gallium/drivers/i915/i915_state.c index f3c38ae3237..e90f2dc7574 100644 --- a/src/gallium/drivers/i915/i915_state.c +++ b/src/gallium/drivers/i915/i915_state.c @@ -113,7 +113,7 @@ i915_create_blend_state(struct pipe_context *pipe, unsigned dstA = blend->rt[0].alpha_dst_factor; /* Special handling for MIN/MAX filter modes handled at - * state_tracker level. + * frontend level. */ if (srcA != srcRGB || diff --git a/src/gallium/drivers/iris/iris_screen.h b/src/gallium/drivers/iris/iris_screen.h index 5ec58f6c216..9ee111c911a 100644 --- a/src/gallium/drivers/iris/iris_screen.h +++ b/src/gallium/drivers/iris/iris_screen.h @@ -24,7 +24,7 @@ #define IRIS_SCREEN_H #include "pipe/p_screen.h" -#include "state_tracker/drm_driver.h" +#include "frontend/drm_driver.h" #include "util/disk_cache.h" #include "util/slab.h" #include "util/u_screen.h" diff --git a/src/gallium/drivers/lima/lima_bo.c b/src/gallium/drivers/lima/lima_bo.c index cccf2f64cac..9e6d46b05de 100644 --- a/src/gallium/drivers/lima/lima_bo.c +++ b/src/gallium/drivers/lima/lima_bo.c @@ -34,7 +34,7 @@ #include "util/os_time.h" #include "os/os_mman.h" -#include "state_tracker/drm_driver.h" +#include "frontend/drm_driver.h" #include "lima_screen.h" #include "lima_bo.h" diff --git a/src/gallium/drivers/lima/lima_resource.c b/src/gallium/drivers/lima/lima_resource.c index 4644ea402c9..aa5e1f21d66 100644 --- a/src/gallium/drivers/lima/lima_resource.c +++ b/src/gallium/drivers/lima/lima_resource.c @@ -35,7 +35,7 @@ #include "util/u_drm.h" #include "renderonly/renderonly.h" -#include "state_tracker/drm_driver.h" +#include "frontend/drm_driver.h" #include "drm-uapi/drm_fourcc.h" #include "drm-uapi/lima_drm.h" diff --git a/src/gallium/drivers/llvmpipe/lp_screen.c b/src/gallium/drivers/llvmpipe/lp_screen.c index a980700b16e..e3f1f70237c 100644 --- a/src/gallium/drivers/llvmpipe/lp_screen.c +++ b/src/gallium/drivers/llvmpipe/lp_screen.c @@ -52,7 +52,7 @@ #include "lp_rast.h" #include "lp_cs_tpool.h" -#include "state_tracker/sw_winsys.h" +#include "frontend/sw_winsys.h" #include "nir.h" diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c index 6b46e82756d..d7ec3591c6e 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.c +++ b/src/gallium/drivers/llvmpipe/lp_setup.c @@ -53,7 +53,7 @@ #include "lp_setup_context.h" #include "lp_screen.h" #include "lp_state.h" -#include "state_tracker/sw_winsys.h" +#include "frontend/sw_winsys.h" #include "draw/draw_context.h" #include "draw/draw_vbuf.h" diff --git a/src/gallium/drivers/llvmpipe/lp_state_cs.c b/src/gallium/drivers/llvmpipe/lp_state_cs.c index 38210d444f5..1092ea513d7 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_cs.c +++ b/src/gallium/drivers/llvmpipe/lp_state_cs.c @@ -44,7 +44,7 @@ #include "lp_screen.h" #include "lp_memory.h" #include "lp_cs_tpool.h" -#include "state_tracker/sw_winsys.h" +#include "frontend/sw_winsys.h" #include "nir/nir_to_tgsi_info.h" #include "nir_serialize.h" struct lp_cs_job_info { diff --git a/src/gallium/drivers/llvmpipe/lp_state_sampler.c b/src/gallium/drivers/llvmpipe/lp_state_sampler.c index 0851213a798..6c5511e3e81 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_sampler.c +++ b/src/gallium/drivers/llvmpipe/lp_state_sampler.c @@ -38,7 +38,7 @@ #include "lp_screen.h" #include "lp_state.h" #include "lp_debug.h" -#include "state_tracker/sw_winsys.h" +#include "frontend/sw_winsys.h" static void * diff --git a/src/gallium/drivers/llvmpipe/lp_texture.c b/src/gallium/drivers/llvmpipe/lp_texture.c index fa7a1ff1129..cbeaf3fd0ba 100644 --- a/src/gallium/drivers/llvmpipe/lp_texture.c +++ b/src/gallium/drivers/llvmpipe/lp_texture.c @@ -51,7 +51,7 @@ #include "lp_state.h" #include "lp_rast.h" -#include "state_tracker/sw_winsys.h" +#include "frontend/sw_winsys.h" #ifdef DEBUG diff --git a/src/gallium/drivers/nouveau/nouveau_screen.c b/src/gallium/drivers/nouveau/nouveau_screen.c index de9cce3812a..7f90784b8ed 100644 --- a/src/gallium/drivers/nouveau/nouveau_screen.c +++ b/src/gallium/drivers/nouveau/nouveau_screen.c @@ -26,7 +26,7 @@ #include /* XXX this should go away */ -#include "state_tracker/drm_driver.h" +#include "frontend/drm_driver.h" int nouveau_mesa_debug = 0; diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_miptree.c b/src/gallium/drivers/nouveau/nvc0/nvc0_miptree.c index c897e4e8b97..578335d7001 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_miptree.c +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_miptree.c @@ -24,7 +24,7 @@ #include "pipe/p_state.h" #include "pipe/p_defines.h" -#include "state_tracker/drm_driver.h" +#include "frontend/drm_driver.h" #include "util/u_inlines.h" #include "util/format/u_format.h" diff --git a/src/gallium/drivers/panfrost/pan_resource.c b/src/gallium/drivers/panfrost/pan_resource.c index 443df15d257..2ccbe6d7acd 100644 --- a/src/gallium/drivers/panfrost/pan_resource.c +++ b/src/gallium/drivers/panfrost/pan_resource.c @@ -33,7 +33,7 @@ #include #include "drm-uapi/drm_fourcc.h" -#include "state_tracker/winsys_handle.h" +#include "frontend/winsys_handle.h" #include "util/format/u_format.h" #include "util/u_memory.h" #include "util/u_surface.h" diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c index 84c50431cd5..be5818794c6 100644 --- a/src/gallium/drivers/r300/r300_texture.c +++ b/src/gallium/drivers/r300/r300_texture.c @@ -36,7 +36,7 @@ #include "util/u_memory.h" #include "pipe/p_screen.h" -#include "state_tracker/winsys_handle.h" +#include "frontend/winsys_handle.h" /* These formats are supported by swapping their bytes. * The swizzles must be set exactly like their non-swapped counterparts, diff --git a/src/gallium/drivers/r600/r600_texture.c b/src/gallium/drivers/r600/r600_texture.c index 6b2f5956d9d..edbe9f97efa 100644 --- a/src/gallium/drivers/r600/r600_texture.c +++ b/src/gallium/drivers/r600/r600_texture.c @@ -33,7 +33,7 @@ #include "util/u_pack_color.h" #include "util/u_surface.h" #include "util/os_time.h" -#include "state_tracker/winsys_handle.h" +#include "frontend/winsys_handle.h" #include #include diff --git a/src/gallium/drivers/radeonsi/si_texture.c b/src/gallium/drivers/radeonsi/si_texture.c index 46bdd4d5843..edb5944aec3 100644 --- a/src/gallium/drivers/radeonsi/si_texture.c +++ b/src/gallium/drivers/radeonsi/si_texture.c @@ -27,7 +27,7 @@ #include "si_pipe.h" #include "si_query.h" #include "sid.h" -#include "state_tracker/drm_driver.h" +#include "frontend/drm_driver.h" #include "util/format/u_format.h" #include "util/os_time.h" #include "util/u_log.h" diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c index 41910c10a31..f9d43bd6ea8 100644 --- a/src/gallium/drivers/softpipe/sp_screen.c +++ b/src/gallium/drivers/softpipe/sp_screen.c @@ -37,7 +37,7 @@ #include "pipe/p_screen.h" #include "draw/draw_context.h" -#include "state_tracker/sw_winsys.h" +#include "frontend/sw_winsys.h" #include "tgsi/tgsi_exec.h" #include "sp_texture.h" diff --git a/src/gallium/drivers/softpipe/sp_state_sampler.c b/src/gallium/drivers/softpipe/sp_state_sampler.c index 14e44d1de9f..2755f26bea2 100644 --- a/src/gallium/drivers/softpipe/sp_state_sampler.c +++ b/src/gallium/drivers/softpipe/sp_state_sampler.c @@ -41,7 +41,7 @@ #include "sp_tex_sample.h" #include "sp_tex_tile_cache.h" #include "sp_screen.h" -#include "state_tracker/sw_winsys.h" +#include "frontend/sw_winsys.h" /** diff --git a/src/gallium/drivers/softpipe/sp_texture.c b/src/gallium/drivers/softpipe/sp_texture.c index a8f0e6cee5a..c9a22a97891 100644 --- a/src/gallium/drivers/softpipe/sp_texture.c +++ b/src/gallium/drivers/softpipe/sp_texture.c @@ -44,7 +44,7 @@ #include "sp_texture.h" #include "sp_screen.h" -#include "state_tracker/sw_winsys.h" +#include "frontend/sw_winsys.h" /** diff --git a/src/gallium/drivers/svga/svga_context.h b/src/gallium/drivers/svga/svga_context.h index fc63ec34670..60afb2b6740 100644 --- a/src/gallium/drivers/svga/svga_context.h +++ b/src/gallium/drivers/svga/svga_context.h @@ -603,7 +603,7 @@ struct svga_context boolean disable_rasterizer; /* Set if to disable rasterization */ }; -/* A flag for each state_tracker state object: +/* A flag for each frontend state object: */ #define SVGA_NEW_BLEND 0x1 #define SVGA_NEW_DEPTH_STENCIL_ALPHA 0x2 diff --git a/src/gallium/drivers/swr/swr_screen.cpp b/src/gallium/drivers/swr/swr_screen.cpp index ef5b4524c1a..2939637f1c5 100644 --- a/src/gallium/drivers/swr/swr_screen.cpp +++ b/src/gallium/drivers/swr/swr_screen.cpp @@ -38,7 +38,7 @@ #include "util/u_string.h" #include "util/u_screen.h" -#include "state_tracker/sw_winsys.h" +#include "frontend/sw_winsys.h" #include "jit_api.h" diff --git a/src/gallium/drivers/tegra/tegra_screen.c b/src/gallium/drivers/tegra/tegra_screen.c index 9ec3f6fe1d4..73efb8e904e 100644 --- a/src/gallium/drivers/tegra/tegra_screen.c +++ b/src/gallium/drivers/tegra/tegra_screen.c @@ -37,7 +37,7 @@ #include "util/u_debug.h" #include "util/u_inlines.h" -#include "state_tracker/drm_driver.h" +#include "frontend/drm_driver.h" #include "nouveau/drm/nouveau_drm_public.h" diff --git a/src/gallium/drivers/v3d/v3d_screen.h b/src/gallium/drivers/v3d/v3d_screen.h index f9ff26f18f8..586b3925065 100644 --- a/src/gallium/drivers/v3d/v3d_screen.h +++ b/src/gallium/drivers/v3d/v3d_screen.h @@ -27,7 +27,7 @@ #include "pipe/p_screen.h" #include "renderonly/renderonly.h" #include "os/os_thread.h" -#include "state_tracker/drm_driver.h" +#include "frontend/drm_driver.h" #include "util/list.h" #include "util/slab.h" #include "broadcom/common/v3d_debug.h" diff --git a/src/gallium/drivers/v3d/v3dx_emit.c b/src/gallium/drivers/v3d/v3dx_emit.c index 18c2473955b..bcad6cddac6 100644 --- a/src/gallium/drivers/v3d/v3dx_emit.c +++ b/src/gallium/drivers/v3d/v3dx_emit.c @@ -799,7 +799,7 @@ v3dX(emit_state)(struct pipe_context *pctx) if (v3d->dirty & VC5_DIRTY_SAMPLE_STATE) { cl_emit(&job->bcl, SAMPLE_STATE, state) { /* Note: SampleCoverage was handled at the - * state_tracker level by converting to sample_mask. + * frontend level by converting to sample_mask. */ state.coverage = 1.0; state.mask = job->msaa ? v3d->sample_mask : 0xf; diff --git a/src/gallium/drivers/vc4/vc4_screen.h b/src/gallium/drivers/vc4/vc4_screen.h index fa4becd8a3c..2a5a160354e 100644 --- a/src/gallium/drivers/vc4/vc4_screen.h +++ b/src/gallium/drivers/vc4/vc4_screen.h @@ -27,7 +27,7 @@ #include "pipe/p_screen.h" #include "renderonly/renderonly.h" #include "os/os_thread.h" -#include "state_tracker/drm_driver.h" +#include "frontend/drm_driver.h" #include "util/list.h" #include "util/slab.h" diff --git a/src/gallium/drivers/zink/zink_resource.c b/src/gallium/drivers/zink/zink_resource.c index 5467fe487b9..b1ab56699f6 100644 --- a/src/gallium/drivers/zink/zink_resource.c +++ b/src/gallium/drivers/zink/zink_resource.c @@ -33,7 +33,7 @@ #include "util/u_inlines.h" #include "util/u_memory.h" -#include "state_tracker/sw_winsys.h" +#include "frontend/sw_winsys.h" static void zink_resource_destroy(struct pipe_screen *pscreen, diff --git a/src/gallium/drivers/zink/zink_screen.c b/src/gallium/drivers/zink/zink_screen.c index 92263a26eee..feb7fdb6d3a 100644 --- a/src/gallium/drivers/zink/zink_screen.c +++ b/src/gallium/drivers/zink/zink_screen.c @@ -37,7 +37,7 @@ #include "util/u_screen.h" #include "util/u_string.h" -#include "state_tracker/sw_winsys.h" +#include "frontend/sw_winsys.h" static const struct debug_named_value debug_options[] = { diff --git a/src/gallium/frontends/README b/src/gallium/frontends/README new file mode 100644 index 00000000000..28dd27bbd50 --- /dev/null +++ b/src/gallium/frontends/README @@ -0,0 +1,2 @@ +This directory is a placeholder for incubating state-trackers. Mesa's +state-tracker is in src/mesa. diff --git a/src/gallium/frontends/clover/Doxyfile b/src/gallium/frontends/clover/Doxyfile new file mode 100644 index 00000000000..19337bbd656 --- /dev/null +++ b/src/gallium/frontends/clover/Doxyfile @@ -0,0 +1,1716 @@ +# Doxyfile 1.7.4 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" "). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = Clover + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer +# a quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify an logo or icon that is +# included in the documentation. The maximum height of the logo should not +# exceed 55 pixels and the maximum width should not exceed 200 pixels. +# Doxygen will copy the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful if your file system +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = YES + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this +# tag. The format is ext=language, where ext is a file extension, and language +# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, +# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions +# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also makes the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = YES + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and +# unions are shown inside the group in which they are included (e.g. using +# @ingroup) instead of on a separate page (for HTML and Man pages) or +# section (for LaTeX and RTF). + +INLINE_GROUPED_CLASSES = NO + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penalty. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will roughly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols + +SYMBOL_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespaces are hidden. + +EXTRACT_ANON_NSPACES = YES + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to +# do proper type resolution of all parameters of a function it will reject a +# match between the prototype and the implementation of a member function even +# if there is only one candidate or it is obvious which candidate to choose +# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen +# will still accept a match between prototype and implementation in such cases. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or macro consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and macros in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = NO + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. +# This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. The create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. +# You can optionally specify a file name after the option, if omitted +# DoxygenLayout.xml will be used as the name of the layout file. + +LAYOUT_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = NO + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# The WARN_NO_PARAMDOC option can be enabled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = api/ core/ util/ + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh +# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py +# *.f90 *.f *.for *.vhd *.vhdl + +FILE_PATTERNS = + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. +# If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. +# Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. +# The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty or if +# non of the patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) +# and it is also possible to disable source filtering for a specific pattern +# using *.ext= (so without naming a filter). This option only has effect when +# FILTER_SOURCE_FILES is enabled. + +FILTER_SOURCE_PATTERNS = + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. +# Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. Note that when using a custom header you are responsible +# for the proper inclusion of any scripts and style sheets that doxygen +# needs, which is dependent on the configuration options used. +# It is adviced to generate a default header using "doxygen -w html +# header.html footer.html stylesheet.css YourConfigFile" and then modify +# that header. Note that the header is subject to change so you typically +# have to redo this when upgrading to a newer version of doxygen or when changing the value of configuration settings such as GENERATE_TREEVIEW! + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that +# the files will be copied as-is; there are no commands or markers available. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. +# Doxygen will adjust the colors in the stylesheet and background images +# according to this color. Hue is specified as an angle on a colorwheel, +# see http://en.wikipedia.org/wiki/Hue for more information. +# For instance the value 0 represents red, 60 is yellow, 120 is green, +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. +# The allowed range is 0 to 359. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of +# the colors in the HTML output. For a value of 0 the output will use +# grayscales only. A value of 255 will produce the most vivid colors. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to +# the luminance component of the colors in the HTML output. Values below +# 100 gradually make the output lighter, whereas values above 100 make +# the output darker. The value divided by 100 is the actual gamma applied, +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, +# and 100 does not change the gamma. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated +# that can be used as input for Qt's qhelpgenerator to generate a +# Qt Compressed Help (.qch) of the generated HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to +# add. For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see +# +# Qt Help Project / Custom Filters. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# +# Qt Help Project / Filter Attributes. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values +# (range [0,1..20]) that doxygen will group on one line in the generated HTML +# documentation. Note that a value of 0 will completely suppress the enum +# values from appearing in the overview section. + +ENUM_VALUES_PER_LINE = 4 + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, +# and Class Hierarchy pages using a tree view instead of an ordered list. + +USE_INLINE_TREES = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open +# links to external symbols imported via tag files in a separate window. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are +# not supported properly for IE 6.0, but are supported on all modern browsers. +# Note that when changing this option you need to delete any form_*.png files +# in the HTML output before the changes have effect. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax +# (see http://www.mathjax.org) which uses client side Javascript for the +# rendering instead of using prerendered bitmaps. Use this if you do not +# have LaTeX installed or if you want to formulas look prettier in the HTML +# output. When enabled you also need to install MathJax separately and +# configure the path to it using the MATHJAX_RELPATH option. + +USE_MATHJAX = NO + +# When MathJax is enabled you need to specify the location relative to the +# HTML output directory using the MATHJAX_RELPATH option. The destination +# directory should contain the MathJax.js script. For instance, if the mathjax +# directory is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the +# mathjax.org site, so you can quickly see the result without installing +# MathJax, but it is strongly recommended to install a local copy of MathJax +# before deployment. + +MATHJAX_RELPATH = http://www.mathjax.org/mathjax + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = YES + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a PHP enabled web server instead of at the web client +# using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server +# based approach is that it scales better to large projects and allows +# full text search. The disadvantages are that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = YES + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4 + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for +# the generated latex document. The footer should contain everything after +# the last chapter. If it is left blank doxygen will generate a +# standard footer. Notice: only use this tag if you know what you are doing! + +LATEX_FOOTER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. +# This is useful +# if you want to understand what is going on. +# On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# pointed to by INCLUDE_PATH will be searched when a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition that +# overrules the definition found in the source code. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all references to function-like macros +# that are alone on a line, have an all uppercase name, and do not end with a +# semicolon, because these will confuse the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option also works with HAVE_DOT disabled, but it is recommended to +# install and use dot, since it yields more powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is +# allowed to run in parallel. When set to 0 (the default) doxygen will +# base this on the number of processors available in the system. You can set it +# explicitly to a value larger than 0 to get control over the balance +# between CPU load and processing speed. + +DOT_NUM_THREADS = 0 + +# By default doxygen will write a font called Helvetica to the output +# directory and reference it in all dot files that doxygen generates. +# When you want a differently looking font you can specify the font name +# using DOT_FONTNAME. You need to make sure dot is able to find the font, +# which can be done by putting it in a standard location or by setting the +# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory +# containing the font. + +DOT_FONTNAME = Helvetica + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the output directory to look for the +# FreeSans.ttf font (which doxygen will put there itself). If you specify a +# different font using DOT_FONTNAME you can set the path where dot +# can find it using this tag. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will generate a graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are svg, png, jpg, or gif. +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the +# \mscfile command). + +MSCFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES diff --git a/src/gallium/frontends/clover/Makefile.sources b/src/gallium/frontends/clover/Makefile.sources new file mode 100644 index 00000000000..38f94981fb6 --- /dev/null +++ b/src/gallium/frontends/clover/Makefile.sources @@ -0,0 +1,68 @@ +CPP_SOURCES := \ + api/context.cpp \ + api/device.cpp \ + api/dispatch.cpp \ + api/dispatch.hpp \ + api/event.cpp \ + api/interop.cpp \ + api/kernel.cpp \ + api/memory.cpp \ + api/platform.cpp \ + api/program.cpp \ + api/queue.cpp \ + api/sampler.cpp \ + api/transfer.cpp \ + api/util.hpp \ + core/context.cpp \ + core/context.hpp \ + core/device.cpp \ + core/device.hpp \ + core/error.hpp \ + core/event.cpp \ + core/event.hpp \ + core/format.cpp \ + core/format.hpp \ + core/kernel.cpp \ + core/kernel.hpp \ + core/memory.cpp \ + core/memory.hpp \ + core/module.cpp \ + core/module.hpp \ + core/object.hpp \ + core/platform.cpp \ + core/platform.hpp \ + core/program.cpp \ + core/program.hpp \ + core/property.hpp \ + core/queue.cpp \ + core/queue.hpp \ + core/resource.cpp \ + core/resource.hpp \ + core/sampler.cpp \ + core/sampler.hpp \ + core/timestamp.cpp \ + core/timestamp.hpp \ + util/adaptor.hpp \ + util/algebra.hpp \ + util/algorithm.hpp \ + util/factor.hpp \ + util/functional.hpp \ + util/lazy.hpp \ + util/pointer.hpp \ + util/range.hpp \ + util/tuple.hpp + +LLVM_SOURCES := \ + llvm/codegen/bitcode.cpp \ + llvm/codegen/common.cpp \ + llvm/codegen/native.cpp \ + llvm/codegen.hpp \ + llvm/compat.hpp \ + llvm/invocation.cpp \ + llvm/invocation.hpp \ + llvm/metadata.hpp \ + llvm/util.hpp + +SPIRV_SOURCES := \ + spirv/invocation.cpp \ + spirv/invocation.hpp diff --git a/src/gallium/frontends/clover/api/context.cpp b/src/gallium/frontends/clover/api/context.cpp new file mode 100644 index 00000000000..c0cd2d32b95 --- /dev/null +++ b/src/gallium/frontends/clover/api/context.cpp @@ -0,0 +1,144 @@ +// +// Copyright 2012 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#include "api/util.hpp" +#include "core/context.hpp" +#include "core/platform.hpp" + +using namespace clover; + +CLOVER_API cl_context +clCreateContext(const cl_context_properties *d_props, cl_uint num_devs, + const cl_device_id *d_devs, + void (CL_CALLBACK *pfn_notify)(const char *, const void *, + size_t, void *), + void *user_data, cl_int *r_errcode) try { + auto props = obj(d_props); + auto devs = objs(d_devs, num_devs); + + if (!pfn_notify && user_data) + throw error(CL_INVALID_VALUE); + + for (auto &prop : props) { + if (prop.first == CL_CONTEXT_PLATFORM) + obj(prop.second.as()); + else + throw error(CL_INVALID_PROPERTY); + } + + const auto notify = (!pfn_notify ? context::notify_action() : + [=](const char *s) { + pfn_notify(s, NULL, 0, user_data); + }); + + ret_error(r_errcode, CL_SUCCESS); + return desc(new context(props, devs, notify)); + +} catch (error &e) { + ret_error(r_errcode, e); + return NULL; +} + +CLOVER_API cl_context +clCreateContextFromType(const cl_context_properties *d_props, + cl_device_type type, + void (CL_CALLBACK *pfn_notify)( + const char *, const void *, size_t, void *), + void *user_data, cl_int *r_errcode) try { + cl_platform_id d_platform; + cl_uint num_platforms; + cl_int ret; + std::vector devs; + cl_uint num_devices; + + ret = clGetPlatformIDs(1, &d_platform, &num_platforms); + if (ret || !num_platforms) + throw error(CL_INVALID_PLATFORM); + + ret = clGetDeviceIDs(d_platform, type, 0, NULL, &num_devices); + if (ret) + throw error(CL_DEVICE_NOT_FOUND); + devs.resize(num_devices); + ret = clGetDeviceIDs(d_platform, type, num_devices, devs.data(), 0); + if (ret) + throw error(CL_DEVICE_NOT_FOUND); + + return clCreateContext(d_props, num_devices, devs.data(), pfn_notify, + user_data, r_errcode); + +} catch (error &e) { + ret_error(r_errcode, e); + return NULL; +} + +CLOVER_API cl_int +clRetainContext(cl_context d_ctx) try { + obj(d_ctx).retain(); + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clReleaseContext(cl_context d_ctx) try { + if (obj(d_ctx).release()) + delete pobj(d_ctx); + + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clGetContextInfo(cl_context d_ctx, cl_context_info param, + size_t size, void *r_buf, size_t *r_size) try { + property_buffer buf { r_buf, size, r_size }; + auto &ctx = obj(d_ctx); + + switch (param) { + case CL_CONTEXT_REFERENCE_COUNT: + buf.as_scalar() = ctx.ref_count(); + break; + + case CL_CONTEXT_NUM_DEVICES: + buf.as_scalar() = ctx.devices().size(); + break; + + case CL_CONTEXT_DEVICES: + buf.as_vector() = descs(ctx.devices()); + break; + + case CL_CONTEXT_PROPERTIES: + buf.as_vector() = desc(ctx.properties()); + break; + + default: + throw error(CL_INVALID_VALUE); + } + + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} diff --git a/src/gallium/frontends/clover/api/device.cpp b/src/gallium/frontends/clover/api/device.cpp new file mode 100644 index 00000000000..042f2eda21c --- /dev/null +++ b/src/gallium/frontends/clover/api/device.cpp @@ -0,0 +1,421 @@ +// +// Copyright 2012 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#include "api/util.hpp" +#include "core/platform.hpp" +#include "core/device.hpp" +#include "git_sha1.h" + +using namespace clover; + +CLOVER_API cl_int +clGetDeviceIDs(cl_platform_id d_platform, cl_device_type device_type, + cl_uint num_entries, cl_device_id *rd_devices, + cl_uint *rnum_devices) try { + auto &platform = obj(d_platform); + std::vector d_devs; + + if ((!num_entries && rd_devices) || + (!rnum_devices && !rd_devices)) + throw error(CL_INVALID_VALUE); + + // Collect matching devices + for (device &dev : platform) { + if (((device_type & CL_DEVICE_TYPE_DEFAULT) && + dev == platform.front()) || + (device_type & dev.type())) + d_devs.push_back(desc(dev)); + } + + if (d_devs.empty()) + throw error(CL_DEVICE_NOT_FOUND); + + // ...and return the requested data. + if (rnum_devices) + *rnum_devices = d_devs.size(); + if (rd_devices) + copy(range(d_devs.begin(), + std::min((unsigned)d_devs.size(), num_entries)), + rd_devices); + + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clCreateSubDevices(cl_device_id d_dev, + const cl_device_partition_property *props, + cl_uint num_devs, cl_device_id *rd_devs, + cl_uint *rnum_devs) { + // There are no currently supported partitioning schemes. + return CL_INVALID_VALUE; +} + +CLOVER_API cl_int +clRetainDevice(cl_device_id d_dev) try { + obj(d_dev); + + // The reference count doesn't change for root devices. + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clReleaseDevice(cl_device_id d_dev) try { + obj(d_dev); + + // The reference count doesn't change for root devices. + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clGetDeviceInfo(cl_device_id d_dev, cl_device_info param, + size_t size, void *r_buf, size_t *r_size) try { + property_buffer buf { r_buf, size, r_size }; + auto &dev = obj(d_dev); + + switch (param) { + case CL_DEVICE_TYPE: + buf.as_scalar() = dev.type(); + break; + + case CL_DEVICE_VENDOR_ID: + buf.as_scalar() = dev.vendor_id(); + break; + + case CL_DEVICE_MAX_COMPUTE_UNITS: + buf.as_scalar() = dev.max_compute_units(); + break; + + case CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS: + buf.as_scalar() = dev.max_block_size().size(); + break; + + case CL_DEVICE_MAX_WORK_ITEM_SIZES: + buf.as_vector() = dev.max_block_size(); + break; + + case CL_DEVICE_MAX_WORK_GROUP_SIZE: + buf.as_scalar() = dev.max_threads_per_block(); + break; + + case CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR: + buf.as_scalar() = 16; + break; + + case CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT: + buf.as_scalar() = 8; + break; + + case CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT: + buf.as_scalar() = 4; + break; + + case CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG: + buf.as_scalar() = 2; + break; + + case CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT: + buf.as_scalar() = 4; + break; + + case CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE: + buf.as_scalar() = dev.has_doubles() ? 2 : 0; + break; + + case CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF: + buf.as_scalar() = dev.has_halves() ? 8 : 0; + break; + + case CL_DEVICE_MAX_CLOCK_FREQUENCY: + buf.as_scalar() = dev.max_clock_frequency(); + break; + + case CL_DEVICE_ADDRESS_BITS: + buf.as_scalar() = dev.address_bits(); + break; + + case CL_DEVICE_MAX_READ_IMAGE_ARGS: + buf.as_scalar() = dev.max_images_read(); + break; + + case CL_DEVICE_MAX_WRITE_IMAGE_ARGS: + buf.as_scalar() = dev.max_images_write(); + break; + + case CL_DEVICE_MAX_MEM_ALLOC_SIZE: + buf.as_scalar() = dev.max_mem_alloc_size(); + break; + + case CL_DEVICE_IMAGE2D_MAX_WIDTH: + case CL_DEVICE_IMAGE2D_MAX_HEIGHT: + buf.as_scalar() = 1 << dev.max_image_levels_2d(); + break; + + case CL_DEVICE_IMAGE3D_MAX_WIDTH: + case CL_DEVICE_IMAGE3D_MAX_HEIGHT: + case CL_DEVICE_IMAGE3D_MAX_DEPTH: + buf.as_scalar() = 1 << dev.max_image_levels_3d(); + break; + + case CL_DEVICE_IMAGE_MAX_BUFFER_SIZE: + buf.as_scalar() = dev.max_image_buffer_size(); + break; + + case CL_DEVICE_IMAGE_MAX_ARRAY_SIZE: + buf.as_scalar() = dev.max_image_array_number(); + break; + + case CL_DEVICE_IMAGE_SUPPORT: + buf.as_scalar() = dev.image_support(); + break; + + case CL_DEVICE_MAX_PARAMETER_SIZE: + buf.as_scalar() = dev.max_mem_input(); + break; + + case CL_DEVICE_MAX_SAMPLERS: + buf.as_scalar() = dev.max_samplers(); + break; + + case CL_DEVICE_MEM_BASE_ADDR_ALIGN: + buf.as_scalar() = 8 * + std::max(dev.mem_base_addr_align(), (cl_uint) sizeof(cl_long) * 16); + break; + + case CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE: + buf.as_scalar() = 128; + break; + + case CL_DEVICE_HALF_FP_CONFIG: + // This is the "mandated minimum half precision floating-point + // capability" for OpenCL 1.x. + buf.as_scalar() = + CL_FP_INF_NAN | CL_FP_ROUND_TO_NEAREST; + break; + + case CL_DEVICE_SINGLE_FP_CONFIG: + // This is the "mandated minimum single precision floating-point + // capability" for OpenCL 1.1. In OpenCL 1.2, nothing is required for + // custom devices. + buf.as_scalar() = + CL_FP_INF_NAN | CL_FP_ROUND_TO_NEAREST; + break; + + case CL_DEVICE_DOUBLE_FP_CONFIG: + if (dev.has_doubles()) + // This is the "mandated minimum double precision floating-point + // capability" + buf.as_scalar() = + CL_FP_FMA + | CL_FP_ROUND_TO_NEAREST + | CL_FP_ROUND_TO_ZERO + | CL_FP_ROUND_TO_INF + | CL_FP_INF_NAN + | CL_FP_DENORM; + else + buf.as_scalar() = 0; + break; + + case CL_DEVICE_GLOBAL_MEM_CACHE_TYPE: + buf.as_scalar() = CL_NONE; + break; + + case CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE: + buf.as_scalar() = 0; + break; + + case CL_DEVICE_GLOBAL_MEM_CACHE_SIZE: + buf.as_scalar() = 0; + break; + + case CL_DEVICE_GLOBAL_MEM_SIZE: + buf.as_scalar() = dev.max_mem_global(); + break; + + case CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE: + buf.as_scalar() = dev.max_const_buffer_size(); + break; + + case CL_DEVICE_MAX_CONSTANT_ARGS: + buf.as_scalar() = dev.max_const_buffers(); + break; + + case CL_DEVICE_LOCAL_MEM_TYPE: + buf.as_scalar() = CL_LOCAL; + break; + + case CL_DEVICE_LOCAL_MEM_SIZE: + buf.as_scalar() = dev.max_mem_local(); + break; + + case CL_DEVICE_ERROR_CORRECTION_SUPPORT: + buf.as_scalar() = CL_FALSE; + break; + + case CL_DEVICE_PROFILING_TIMER_RESOLUTION: + buf.as_scalar() = 0; + break; + + case CL_DEVICE_ENDIAN_LITTLE: + buf.as_scalar() = (dev.endianness() == PIPE_ENDIAN_LITTLE); + break; + + case CL_DEVICE_AVAILABLE: + case CL_DEVICE_COMPILER_AVAILABLE: + case CL_DEVICE_LINKER_AVAILABLE: + buf.as_scalar() = CL_TRUE; + break; + + case CL_DEVICE_EXECUTION_CAPABILITIES: + buf.as_scalar() = CL_EXEC_KERNEL; + break; + + case CL_DEVICE_QUEUE_PROPERTIES: + buf.as_scalar() = CL_QUEUE_PROFILING_ENABLE; + break; + + case CL_DEVICE_BUILT_IN_KERNELS: + buf.as_string() = ""; + break; + + case CL_DEVICE_NAME: + buf.as_string() = dev.device_name(); + break; + + case CL_DEVICE_VENDOR: + buf.as_string() = dev.vendor_name(); + break; + + case CL_DRIVER_VERSION: + buf.as_string() = PACKAGE_VERSION; + break; + + case CL_DEVICE_PROFILE: + buf.as_string() = "FULL_PROFILE"; + break; + + case CL_DEVICE_VERSION: + buf.as_string() = "OpenCL " + dev.device_version() + " Mesa " PACKAGE_VERSION MESA_GIT_SHA1; + break; + + case CL_DEVICE_EXTENSIONS: + buf.as_string() = dev.supported_extensions(); + break; + + case CL_DEVICE_PLATFORM: + buf.as_scalar() = desc(dev.platform); + break; + + case CL_DEVICE_HOST_UNIFIED_MEMORY: + buf.as_scalar() = dev.has_unified_memory(); + break; + + case CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR: + buf.as_scalar() = 16; + break; + + case CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT: + buf.as_scalar() = 8; + break; + + case CL_DEVICE_NATIVE_VECTOR_WIDTH_INT: + buf.as_scalar() = 4; + break; + + case CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG: + buf.as_scalar() = 2; + break; + + case CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT: + buf.as_scalar() = 4; + break; + + case CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE: + buf.as_scalar() = dev.has_doubles() ? 2 : 0; + break; + + case CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF: + buf.as_scalar() = dev.has_halves() ? 8 : 0; + break; + + case CL_DEVICE_OPENCL_C_VERSION: + buf.as_string() = "OpenCL C " + dev.device_clc_version() + " "; + break; + + case CL_DEVICE_PRINTF_BUFFER_SIZE: + // Per the spec, the minimum value for the FULL profile is 1 MB. + // However, clover is not ready yet to support it + buf.as_scalar() = 0 /* 1024 */; + break; + + case CL_DEVICE_PREFERRED_INTEROP_USER_SYNC: + buf.as_scalar() = CL_TRUE; + break; + + case CL_DEVICE_PARENT_DEVICE: + buf.as_scalar() = NULL; + break; + + case CL_DEVICE_PARTITION_MAX_SUB_DEVICES: + buf.as_scalar() = 0; + break; + + case CL_DEVICE_PARTITION_PROPERTIES: + buf.as_vector() = + desc(property_list()); + break; + + case CL_DEVICE_PARTITION_AFFINITY_DOMAIN: + buf.as_scalar() = 0; + break; + + case CL_DEVICE_PARTITION_TYPE: + buf.as_vector() = + desc(property_list()); + break; + + case CL_DEVICE_REFERENCE_COUNT: + buf.as_scalar() = 1; + break; + + case CL_DEVICE_SVM_CAPABILITIES: + case CL_DEVICE_SVM_CAPABILITIES_ARM: + buf.as_scalar() = dev.svm_support(); + break; + + default: + throw error(CL_INVALID_VALUE); + } + + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} diff --git a/src/gallium/frontends/clover/api/dispatch.cpp b/src/gallium/frontends/clover/api/dispatch.cpp new file mode 100644 index 00000000000..6e1b0351afa --- /dev/null +++ b/src/gallium/frontends/clover/api/dispatch.cpp @@ -0,0 +1,174 @@ +// +// Copyright 2013 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#include "api/dispatch.hpp" + +namespace clover { + const cl_icd_dispatch _dispatch = { + clGetPlatformIDs, + GetPlatformInfo, + clGetDeviceIDs, + clGetDeviceInfo, + clCreateContext, + clCreateContextFromType, + clRetainContext, + clReleaseContext, + clGetContextInfo, + clCreateCommandQueue, + clRetainCommandQueue, + clReleaseCommandQueue, + clGetCommandQueueInfo, + NULL, // clSetCommandQueueProperty + clCreateBuffer, + clCreateImage2D, + clCreateImage3D, + clRetainMemObject, + clReleaseMemObject, + clGetSupportedImageFormats, + clGetMemObjectInfo, + clGetImageInfo, + clCreateSampler, + clRetainSampler, + clReleaseSampler, + clGetSamplerInfo, + clCreateProgramWithSource, + clCreateProgramWithBinary, + clRetainProgram, + clReleaseProgram, + clBuildProgram, + clUnloadCompiler, + clGetProgramInfo, + clGetProgramBuildInfo, + clCreateKernel, + clCreateKernelsInProgram, + clRetainKernel, + clReleaseKernel, + clSetKernelArg, + clGetKernelInfo, + clGetKernelWorkGroupInfo, + clWaitForEvents, + clGetEventInfo, + clRetainEvent, + clReleaseEvent, + clGetEventProfilingInfo, + clFlush, + clFinish, + clEnqueueReadBuffer, + clEnqueueWriteBuffer, + clEnqueueCopyBuffer, + clEnqueueReadImage, + clEnqueueWriteImage, + clEnqueueCopyImage, + clEnqueueCopyImageToBuffer, + clEnqueueCopyBufferToImage, + clEnqueueMapBuffer, + clEnqueueMapImage, + clEnqueueUnmapMemObject, + clEnqueueNDRangeKernel, + clEnqueueTask, + clEnqueueNativeKernel, + clEnqueueMarker, + clEnqueueWaitForEvents, + clEnqueueBarrier, + GetExtensionFunctionAddress, + NULL, // clCreateFromGLBuffer + NULL, // clCreateFromGLTexture2D + NULL, // clCreateFromGLTexture3D + NULL, // clCreateFromGLRenderbuffer + NULL, // clGetGLObjectInfo + NULL, // clGetGLTextureInfo + NULL, // clEnqueueAcquireGLObjects + NULL, // clEnqueueReleaseGLObjects + NULL, // clGetGLContextInfoKHR + NULL, // clGetDeviceIDsFromD3D10KHR + NULL, // clCreateFromD3D10BufferKHR + NULL, // clCreateFromD3D10Texture2DKHR + NULL, // clCreateFromD3D10Texture3DKHR + NULL, // clEnqueueAcquireD3D10ObjectsKHR + NULL, // clEnqueueReleaseD3D10ObjectsKHR + clSetEventCallback, + clCreateSubBuffer, + clSetMemObjectDestructorCallback, + clCreateUserEvent, + clSetUserEventStatus, + clEnqueueReadBufferRect, + clEnqueueWriteBufferRect, + clEnqueueCopyBufferRect, + NULL, // clCreateSubDevicesEXT + NULL, // clRetainDeviceEXT + NULL, // clReleaseDeviceEXT + NULL, // clCreateEventFromGLsyncKHR + clCreateSubDevices, + clRetainDevice, + clReleaseDevice, + clCreateImage, + clCreateProgramWithBuiltInKernels, + clCompileProgram, + clLinkProgram, + clUnloadPlatformCompiler, + clGetKernelArgInfo, + clEnqueueFillBuffer, + clEnqueueFillImage, + clEnqueueMigrateMemObjects, + clEnqueueMarkerWithWaitList, + clEnqueueBarrierWithWaitList, + GetExtensionFunctionAddressForPlatform, + NULL, // clCreateFromGLTexture + NULL, // clGetDeviceIDsFromD3D11KHR + NULL, // clCreateFromD3D11BufferKHR + NULL, // clCreateFromD3D11Texture2DKHR + NULL, // clCreateFromD3D11Texture3DKHR + NULL, // clCreateFromDX9MediaSurfaceKHR + NULL, // clEnqueueAcquireD3D11ObjectsKHR + NULL, // clEnqueueReleaseD3D11ObjectsKHR + NULL, // clGetDeviceIDsFromDX9MediaAdapterKHR + NULL, // clEnqueueAcquireDX9MediaSurfacesKHR + NULL, // clEnqueueReleaseDX9MediaSurfacesKHR + NULL, // clCreateFromEGLImageKHR + NULL, // clEnqueueAcquireEGLObjectsKHR + NULL, // clEnqueueReleaseEGLObjectsKHR + NULL, // clCreateEventFromEGLSyncKHR + clCreateCommandQueueWithProperties, + NULL, // clCreatePipe + NULL, // clGetPipeInfo + clSVMAlloc, + clSVMFree, + clEnqueueSVMFree, + clEnqueueSVMMemcpy, + clEnqueueSVMMemFill, + clEnqueueSVMMap, + clEnqueueSVMUnmap, + NULL, // clCreateSamplerWithProperties + clSetKernelArgSVMPointer, + clSetKernelExecInfo, + NULL, // clGetKernelSubGroupInfoKHR + NULL, // clCloneKernel + NULL, // clCreateProgramWithIL + clEnqueueSVMMigrateMem, + NULL, // clGetDeviceAndHostTimer + NULL, // clGetHostTimer + NULL, // clGetKernelSubGroupInfo + NULL, // clSetDefaultDeviceCommandQueue + NULL, // clSetProgramReleaseCallback + NULL, // clSetProgramSpecializationConstant + }; +} diff --git a/src/gallium/frontends/clover/api/dispatch.hpp b/src/gallium/frontends/clover/api/dispatch.hpp new file mode 100644 index 00000000000..ea835ed6da4 --- /dev/null +++ b/src/gallium/frontends/clover/api/dispatch.hpp @@ -0,0 +1,105 @@ +// +// Copyright 2013 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#ifndef API_DISPATCH_HPP +#define API_DISPATCH_HPP + +#include "CL/cl.h" +#include "CL/cl_ext.h" +#include "CL/cl_egl.h" +#include "CL/cl_gl.h" +#include "CL/cl_icd.h" + +namespace clover { + extern const cl_icd_dispatch _dispatch; + + cl_int + GetPlatformInfo(cl_platform_id d_platform, cl_platform_info param, + size_t size, void *r_buf, size_t *r_size); + + void * + GetExtensionFunctionAddress(const char *p_name); + + void * + GetExtensionFunctionAddressForPlatform(cl_platform_id d_platform, + const char *p_name); + + cl_int + IcdGetPlatformIDsKHR(cl_uint num_entries, cl_platform_id *rd_platforms, + cl_uint *rnum_platforms); + + cl_int + EnqueueSVMFree(cl_command_queue command_queue, + cl_uint num_svm_pointers, + void *svm_pointers[], + void (CL_CALLBACK *pfn_free_func) ( + cl_command_queue queue, cl_uint num_svm_pointers, + void *svm_pointers[], void *user_data), + void *user_data, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event, + cl_int cmd); + + cl_int + EnqueueSVMMemcpy(cl_command_queue command_queue, + cl_bool blocking_copy, + void *dst_ptr, + const void *src_ptr, + size_t size, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event, + cl_int cmd); + + cl_int + EnqueueSVMMap(cl_command_queue command_queue, + cl_bool blocking_map, + cl_map_flags map_flags, + void *svm_ptr, + size_t size, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event, + cl_int cmd); + + cl_int + EnqueueSVMMemFill(cl_command_queue command_queue, + void *svm_ptr, + const void *pattern, + size_t pattern_size, + size_t size, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event, + cl_int cmd); + + cl_int + EnqueueSVMUnmap(cl_command_queue command_queue, + void *svm_ptr, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event, + cl_int cmd); +} + +#endif diff --git a/src/gallium/frontends/clover/api/event.cpp b/src/gallium/frontends/clover/api/event.cpp new file mode 100644 index 00000000000..3f89644d0a4 --- /dev/null +++ b/src/gallium/frontends/clover/api/event.cpp @@ -0,0 +1,309 @@ +// +// Copyright 2012 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#include "api/util.hpp" +#include "core/event.hpp" + +using namespace clover; + +CLOVER_API cl_event +clCreateUserEvent(cl_context d_ctx, cl_int *r_errcode) try { + auto &ctx = obj(d_ctx); + + ret_error(r_errcode, CL_SUCCESS); + return desc(new soft_event(ctx, {}, false)); + +} catch (error &e) { + ret_error(r_errcode, e); + return NULL; +} + +CLOVER_API cl_int +clSetUserEventStatus(cl_event d_ev, cl_int status) try { + auto &sev = obj(d_ev); + + if (status > 0) + return CL_INVALID_VALUE; + + if (sev.status() <= 0) + return CL_INVALID_OPERATION; + + if (status) + sev.abort(status); + else + sev.trigger(); + + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clWaitForEvents(cl_uint num_evs, const cl_event *d_evs) try { + auto evs = objs(d_evs, num_evs); + + for (auto &ev : evs) { + if (ev.context() != evs.front().context()) + throw error(CL_INVALID_CONTEXT); + + if (ev.status() < 0) + throw error(CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST); + } + + // Create a temporary soft event that depends on all the events in + // the wait list + auto sev = create(evs.front().context(), evs, true); + + // ...and wait on it. + sev().wait(); + + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clGetEventInfo(cl_event d_ev, cl_event_info param, + size_t size, void *r_buf, size_t *r_size) try { + property_buffer buf { r_buf, size, r_size }; + auto &ev = obj(d_ev); + + switch (param) { + case CL_EVENT_COMMAND_QUEUE: + buf.as_scalar() = desc(ev.queue()); + break; + + case CL_EVENT_CONTEXT: + buf.as_scalar() = desc(ev.context()); + break; + + case CL_EVENT_COMMAND_TYPE: + buf.as_scalar() = ev.command(); + break; + + case CL_EVENT_COMMAND_EXECUTION_STATUS: + buf.as_scalar() = ev.status(); + break; + + case CL_EVENT_REFERENCE_COUNT: + buf.as_scalar() = ev.ref_count(); + break; + + default: + throw error(CL_INVALID_VALUE); + } + + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clSetEventCallback(cl_event d_ev, cl_int type, + void (CL_CALLBACK *pfn_notify)(cl_event, cl_int, void *), + void *user_data) try { + auto &ev = obj(d_ev); + + if (!pfn_notify || + (type != CL_COMPLETE && type != CL_SUBMITTED && type != CL_RUNNING)) + throw error(CL_INVALID_VALUE); + + // Create a temporary soft event that depends on ev, with + // pfn_notify as completion action. + create(ev.context(), ref_vector { ev }, true, + [=, &ev](event &) { + ev.wait(); + pfn_notify(desc(ev), ev.status(), user_data); + }); + + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clRetainEvent(cl_event d_ev) try { + obj(d_ev).retain(); + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clReleaseEvent(cl_event d_ev) try { + if (obj(d_ev).release()) + delete pobj(d_ev); + + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clEnqueueMarker(cl_command_queue d_q, cl_event *rd_ev) try { + auto &q = obj(d_q); + + if (!rd_ev) + throw error(CL_INVALID_VALUE); + + *rd_ev = desc(new hard_event(q, CL_COMMAND_MARKER, {})); + + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clEnqueueMarkerWithWaitList(cl_command_queue d_q, cl_uint num_deps, + const cl_event *d_deps, cl_event *rd_ev) try { + auto &q = obj(d_q); + auto deps = objs(d_deps, num_deps); + + for (auto &ev : deps) { + if (ev.context() != q.context()) + throw error(CL_INVALID_CONTEXT); + } + + // Create a hard event that depends on the events in the wait list: + // previous commands in the same queue are implicitly serialized + // with respect to it -- hard events always are. + auto hev = create(q, CL_COMMAND_MARKER, deps); + + ret_object(rd_ev, hev); + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clEnqueueBarrier(cl_command_queue d_q) try { + obj(d_q); + + // No need to do anything, q preserves data ordering strictly. + + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clEnqueueBarrierWithWaitList(cl_command_queue d_q, cl_uint num_deps, + const cl_event *d_deps, cl_event *rd_ev) try { + auto &q = obj(d_q); + auto deps = objs(d_deps, num_deps); + + for (auto &ev : deps) { + if (ev.context() != q.context()) + throw error(CL_INVALID_CONTEXT); + } + + // Create a hard event that depends on the events in the wait list: + // subsequent commands in the same queue will be implicitly + // serialized with respect to it -- hard events always are. + auto hev = create(q, CL_COMMAND_BARRIER, deps); + + ret_object(rd_ev, hev); + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clEnqueueWaitForEvents(cl_command_queue d_q, cl_uint num_evs, + const cl_event *d_evs) try { + // The wait list is mandatory for clEnqueueWaitForEvents(). + objs(d_evs, num_evs); + + return clEnqueueBarrierWithWaitList(d_q, num_evs, d_evs, NULL); + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clGetEventProfilingInfo(cl_event d_ev, cl_profiling_info param, + size_t size, void *r_buf, size_t *r_size) try { + property_buffer buf { r_buf, size, r_size }; + hard_event &hev = dynamic_cast(obj(d_ev)); + + if (hev.status() != CL_COMPLETE) + throw error(CL_PROFILING_INFO_NOT_AVAILABLE); + + switch (param) { + case CL_PROFILING_COMMAND_QUEUED: + buf.as_scalar() = hev.time_queued(); + break; + + case CL_PROFILING_COMMAND_SUBMIT: + buf.as_scalar() = hev.time_submit(); + break; + + case CL_PROFILING_COMMAND_START: + buf.as_scalar() = hev.time_start(); + break; + + case CL_PROFILING_COMMAND_END: + buf.as_scalar() = hev.time_end(); + break; + + default: + throw error(CL_INVALID_VALUE); + } + + return CL_SUCCESS; + +} catch (std::bad_cast &e) { + return CL_PROFILING_INFO_NOT_AVAILABLE; + +} catch (lazy::undefined_error &e) { + return CL_PROFILING_INFO_NOT_AVAILABLE; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clFinish(cl_command_queue d_q) try { + auto &q = obj(d_q); + + // Create a temporary hard event -- it implicitly depends on all + // the previously queued hard events. + auto hev = create(q, 0, ref_vector {}); + + // And wait on it. + hev().wait(); + + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} diff --git a/src/gallium/frontends/clover/api/interop.cpp b/src/gallium/frontends/clover/api/interop.cpp new file mode 100644 index 00000000000..b96069f5167 --- /dev/null +++ b/src/gallium/frontends/clover/api/interop.cpp @@ -0,0 +1,69 @@ +// +// Copyright 2015 Advanced Micro Devices, Inc. +// All Rights Reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#include "core/event.hpp" +#include "api/util.hpp" + +using namespace clover; + +extern "C" { + +PUBLIC bool +opencl_dri_event_add_ref(cl_event event) +{ + /* This should fail if the event hasn't been created by + * clEnqueueReleaseGLObjects or clEnqueueReleaseEGLObjects. + * + * TODO: implement the CL functions + */ + return false; /*return clRetainEvent(event) == CL_SUCCESS;*/ +} + +PUBLIC bool +opencl_dri_event_release(cl_event event) +{ + return clReleaseEvent(event) == CL_SUCCESS; +} + +PUBLIC bool +opencl_dri_event_wait(cl_event event, uint64_t timeout) try { + if (!timeout) { + return obj(event).status() == CL_COMPLETE; + } + + obj(event).wait(); + return true; + +} catch (error &) { + return false; +} + +PUBLIC struct pipe_fence_handle * +opencl_dri_event_get_fence(cl_event event) try { + return obj(event).fence(); + +} catch (error &) { + return NULL; +} + +} diff --git a/src/gallium/frontends/clover/api/kernel.cpp b/src/gallium/frontends/clover/api/kernel.cpp new file mode 100644 index 00000000000..31a87b63868 --- /dev/null +++ b/src/gallium/frontends/clover/api/kernel.cpp @@ -0,0 +1,390 @@ +// +// Copyright 2012 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#include "api/util.hpp" +#include "core/kernel.hpp" +#include "core/event.hpp" + +using namespace clover; + +CLOVER_API cl_kernel +clCreateKernel(cl_program d_prog, const char *name, cl_int *r_errcode) try { + auto &prog = obj(d_prog); + + if (!name) + throw error(CL_INVALID_VALUE); + + auto &sym = find(name_equals(name), prog.symbols()); + + ret_error(r_errcode, CL_SUCCESS); + return new kernel(prog, name, range(sym.args)); + +} catch (std::out_of_range &e) { + ret_error(r_errcode, CL_INVALID_KERNEL_NAME); + return NULL; + +} catch (error &e) { + ret_error(r_errcode, e); + return NULL; +} + +CLOVER_API cl_int +clCreateKernelsInProgram(cl_program d_prog, cl_uint count, + cl_kernel *rd_kerns, cl_uint *r_count) try { + auto &prog = obj(d_prog); + auto &syms = prog.symbols(); + + if (rd_kerns && count < syms.size()) + throw error(CL_INVALID_VALUE); + + if (rd_kerns) + copy(map([&](const module::symbol &sym) { + return desc(new kernel(prog, + std::string(sym.name.begin(), + sym.name.end()), + range(sym.args))); + }, syms), + rd_kerns); + + if (r_count) + *r_count = syms.size(); + + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clRetainKernel(cl_kernel d_kern) try { + obj(d_kern).retain(); + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clReleaseKernel(cl_kernel d_kern) try { + if (obj(d_kern).release()) + delete pobj(d_kern); + + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clSetKernelArg(cl_kernel d_kern, cl_uint idx, size_t size, + const void *value) try { + obj(d_kern).args().at(idx).set(size, value); + return CL_SUCCESS; + +} catch (std::out_of_range &e) { + return CL_INVALID_ARG_INDEX; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clGetKernelInfo(cl_kernel d_kern, cl_kernel_info param, + size_t size, void *r_buf, size_t *r_size) try { + property_buffer buf { r_buf, size, r_size }; + auto &kern = obj(d_kern); + + switch (param) { + case CL_KERNEL_FUNCTION_NAME: + buf.as_string() = kern.name(); + break; + + case CL_KERNEL_NUM_ARGS: + buf.as_scalar() = kern.args().size(); + break; + + case CL_KERNEL_REFERENCE_COUNT: + buf.as_scalar() = kern.ref_count(); + break; + + case CL_KERNEL_CONTEXT: + buf.as_scalar() = desc(kern.program().context()); + break; + + case CL_KERNEL_PROGRAM: + buf.as_scalar() = desc(kern.program()); + break; + + default: + throw error(CL_INVALID_VALUE); + } + + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clGetKernelWorkGroupInfo(cl_kernel d_kern, cl_device_id d_dev, + cl_kernel_work_group_info param, + size_t size, void *r_buf, size_t *r_size) try { + property_buffer buf { r_buf, size, r_size }; + auto &kern = obj(d_kern); + auto &dev = (d_dev ? *pobj(d_dev) : unique(kern.program().devices())); + + if (!count(dev, kern.program().devices())) + throw error(CL_INVALID_DEVICE); + + switch (param) { + case CL_KERNEL_WORK_GROUP_SIZE: + buf.as_scalar() = dev.max_threads_per_block(); + break; + + case CL_KERNEL_COMPILE_WORK_GROUP_SIZE: + buf.as_vector() = kern.required_block_size(); + break; + + case CL_KERNEL_LOCAL_MEM_SIZE: + buf.as_scalar() = kern.mem_local(); + break; + + case CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE: + buf.as_scalar() = dev.subgroup_size(); + break; + + case CL_KERNEL_PRIVATE_MEM_SIZE: + buf.as_scalar() = kern.mem_private(); + break; + + default: + throw error(CL_INVALID_VALUE); + } + + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); + +} catch (std::out_of_range &e) { + return CL_INVALID_DEVICE; +} + +CLOVER_API cl_int +clGetKernelArgInfo(cl_kernel d_kern, + cl_uint idx, cl_kernel_arg_info param, + size_t size, void *r_buf, size_t *r_size) { + CLOVER_NOT_SUPPORTED_UNTIL("1.2"); + return CL_KERNEL_ARG_INFO_NOT_AVAILABLE; +} + +namespace { + /// + /// Common argument checking shared by kernel invocation commands. + /// + void + validate_common(const command_queue &q, kernel &kern, + const ref_vector &deps) { + if (kern.program().context() != q.context() || + any_of([&](const event &ev) { + return ev.context() != q.context(); + }, deps)) + throw error(CL_INVALID_CONTEXT); + + if (any_of([](kernel::argument &arg) { + return !arg.set(); + }, kern.args())) + throw error(CL_INVALID_KERNEL_ARGS); + + // If the command queue's device is not associated to the program, we get + // a module, with no sections, which will also fail the following test. + auto &m = kern.program().build(q.device()).binary; + if (!any_of(type_equals(module::section::text_executable), m.secs)) + throw error(CL_INVALID_PROGRAM_EXECUTABLE); + } + + std::vector + validate_grid_size(const command_queue &q, cl_uint dims, + const size_t *d_grid_size) { + auto grid_size = range(d_grid_size, dims); + + if (dims < 1 || dims > q.device().max_block_size().size()) + throw error(CL_INVALID_WORK_DIMENSION); + + if (!d_grid_size || any_of(is_zero(), grid_size)) + throw error(CL_INVALID_GLOBAL_WORK_SIZE); + + return grid_size; + } + + std::vector + validate_grid_offset(const command_queue &q, cl_uint dims, + const size_t *d_grid_offset) { + if (d_grid_offset) + return range(d_grid_offset, dims); + else + return std::vector(dims, 0); + } + + std::vector + validate_block_size(const command_queue &q, const kernel &kern, + cl_uint dims, const size_t *d_grid_size, + const size_t *d_block_size) { + auto grid_size = range(d_grid_size, dims); + + if (d_block_size) { + auto block_size = range(d_block_size, dims); + + if (any_of(is_zero(), block_size) || + any_of(greater(), block_size, q.device().max_block_size())) + throw error(CL_INVALID_WORK_ITEM_SIZE); + + if (any_of(modulus(), grid_size, block_size)) + throw error(CL_INVALID_WORK_GROUP_SIZE); + + if (fold(multiplies(), 1u, block_size) > + q.device().max_threads_per_block()) + throw error(CL_INVALID_WORK_GROUP_SIZE); + + return block_size; + + } else { + return kern.optimal_block_size(q, grid_size); + } + } +} + +CLOVER_API cl_int +clEnqueueNDRangeKernel(cl_command_queue d_q, cl_kernel d_kern, + cl_uint dims, const size_t *d_grid_offset, + const size_t *d_grid_size, const size_t *d_block_size, + cl_uint num_deps, const cl_event *d_deps, + cl_event *rd_ev) try { + auto &q = obj(d_q); + auto &kern = obj(d_kern); + auto deps = objs(d_deps, num_deps); + auto grid_size = validate_grid_size(q, dims, d_grid_size); + auto grid_offset = validate_grid_offset(q, dims, d_grid_offset); + auto block_size = validate_block_size(q, kern, dims, + d_grid_size, d_block_size); + + validate_common(q, kern, deps); + + auto hev = create( + q, CL_COMMAND_NDRANGE_KERNEL, deps, + [=, &kern, &q](event &) { + kern.launch(q, grid_offset, grid_size, block_size); + }); + + ret_object(rd_ev, hev); + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clEnqueueTask(cl_command_queue d_q, cl_kernel d_kern, + cl_uint num_deps, const cl_event *d_deps, + cl_event *rd_ev) try { + auto &q = obj(d_q); + auto &kern = obj(d_kern); + auto deps = objs(d_deps, num_deps); + + validate_common(q, kern, deps); + + auto hev = create( + q, CL_COMMAND_TASK, deps, + [=, &kern, &q](event &) { + kern.launch(q, { 0 }, { 1 }, { 1 }); + }); + + ret_object(rd_ev, hev); + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clEnqueueNativeKernel(cl_command_queue d_q, void (*func)(void *), + void *args, size_t args_size, + cl_uint num_mems, const cl_mem *d_mems, + const void **mem_handles, cl_uint num_deps, + const cl_event *d_deps, cl_event *rd_ev) { + return CL_INVALID_OPERATION; +} + +CLOVER_API cl_int +clSetKernelArgSVMPointer(cl_kernel d_kern, + cl_uint arg_index, + const void *arg_value) try { + obj(d_kern).args().at(arg_index).set_svm(arg_value); + return CL_SUCCESS; + +} catch (std::out_of_range &e) { + return CL_INVALID_ARG_INDEX; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clSetKernelExecInfo(cl_kernel d_kern, + cl_kernel_exec_info param_name, + size_t param_value_size, + const void *param_value) try { + auto &kern = obj(d_kern); + const bool has_system_svm = all_of(std::mem_fn(&device::has_system_svm), + kern.program().context().devices()); + + if (!param_value) + return CL_INVALID_VALUE; + + switch (param_name) { + case CL_KERNEL_EXEC_INFO_SVM_FINE_GRAIN_SYSTEM: + case CL_KERNEL_EXEC_INFO_SVM_FINE_GRAIN_SYSTEM_ARM: { + if (param_value_size != sizeof(cl_bool)) + return CL_INVALID_VALUE; + + cl_bool val = *static_cast(param_value); + if (val == CL_TRUE && !has_system_svm) + return CL_INVALID_OPERATION; + else + return CL_SUCCESS; + } + + case CL_KERNEL_EXEC_INFO_SVM_PTRS: + case CL_KERNEL_EXEC_INFO_SVM_PTRS_ARM: + if (has_system_svm) + return CL_SUCCESS; + + CLOVER_NOT_SUPPORTED_UNTIL("2.0"); + return CL_INVALID_VALUE; + + default: + return CL_INVALID_VALUE; + } + +} catch (error &e) { + return e.get(); +} diff --git a/src/gallium/frontends/clover/api/memory.cpp b/src/gallium/frontends/clover/api/memory.cpp new file mode 100644 index 00000000000..e03793339c1 --- /dev/null +++ b/src/gallium/frontends/clover/api/memory.cpp @@ -0,0 +1,497 @@ +// +// Copyright 2012 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#include "util/u_math.h" +#include "api/util.hpp" +#include "core/memory.hpp" +#include "core/format.hpp" + +using namespace clover; + +namespace { + cl_mem_flags + validate_flags(cl_mem d_parent, cl_mem_flags d_flags, bool svm) { + const cl_mem_flags dev_access_flags = + CL_MEM_READ_WRITE | CL_MEM_WRITE_ONLY | CL_MEM_READ_ONLY; + const cl_mem_flags host_ptr_flags = + CL_MEM_USE_HOST_PTR | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR; + const cl_mem_flags host_access_flags = + CL_MEM_HOST_WRITE_ONLY | CL_MEM_HOST_READ_ONLY | CL_MEM_HOST_NO_ACCESS; + const cl_mem_flags svm_flags = + CL_MEM_SVM_FINE_GRAIN_BUFFER | CL_MEM_SVM_ATOMICS; + + const cl_mem_flags valid_flags = + dev_access_flags + | (svm || d_parent ? 0 : host_ptr_flags) + | (svm ? svm_flags : host_access_flags); + + if ((d_flags & ~valid_flags) || + util_bitcount(d_flags & dev_access_flags) > 1 || + util_bitcount(d_flags & host_access_flags) > 1) + throw error(CL_INVALID_VALUE); + + if ((d_flags & CL_MEM_USE_HOST_PTR) && + (d_flags & (CL_MEM_COPY_HOST_PTR | CL_MEM_ALLOC_HOST_PTR))) + throw error(CL_INVALID_VALUE); + + if ((d_flags & CL_MEM_SVM_ATOMICS) && + !(d_flags & CL_MEM_SVM_FINE_GRAIN_BUFFER)) + throw error(CL_INVALID_VALUE); + + if (d_parent) { + const auto &parent = obj(d_parent); + const cl_mem_flags flags = (d_flags | + (d_flags & dev_access_flags ? 0 : + parent.flags() & dev_access_flags) | + (d_flags & host_access_flags ? 0 : + parent.flags() & host_access_flags) | + (parent.flags() & host_ptr_flags)); + + if (~flags & parent.flags() & (dev_access_flags & ~CL_MEM_READ_WRITE)) + throw error(CL_INVALID_VALUE); + + // Check if new host access flags cause a mismatch between + // host-read/write-only. + if (!(flags & CL_MEM_HOST_NO_ACCESS) && + (~flags & parent.flags() & host_access_flags)) + throw error(CL_INVALID_VALUE); + + return flags; + + } else { + return d_flags | (d_flags & dev_access_flags ? 0 : CL_MEM_READ_WRITE); + } + } +} + +CLOVER_API cl_mem +clCreateBuffer(cl_context d_ctx, cl_mem_flags d_flags, size_t size, + void *host_ptr, cl_int *r_errcode) try { + const cl_mem_flags flags = validate_flags(NULL, d_flags, false); + auto &ctx = obj(d_ctx); + + if (bool(host_ptr) != bool(flags & (CL_MEM_USE_HOST_PTR | + CL_MEM_COPY_HOST_PTR))) + throw error(CL_INVALID_HOST_PTR); + + if (!size || + size > fold(maximum(), cl_ulong(0), + map(std::mem_fn(&device::max_mem_alloc_size), ctx.devices()) + )) + throw error(CL_INVALID_BUFFER_SIZE); + + ret_error(r_errcode, CL_SUCCESS); + return new root_buffer(ctx, flags, size, host_ptr); + +} catch (error &e) { + ret_error(r_errcode, e); + return NULL; +} + +CLOVER_API cl_mem +clCreateSubBuffer(cl_mem d_mem, cl_mem_flags d_flags, + cl_buffer_create_type op, + const void *op_info, cl_int *r_errcode) try { + auto &parent = obj(d_mem); + const cl_mem_flags flags = validate_flags(d_mem, d_flags, false); + + if (op == CL_BUFFER_CREATE_TYPE_REGION) { + auto reg = reinterpret_cast(op_info); + + if (!reg || + reg->origin > parent.size() || + reg->origin + reg->size > parent.size()) + throw error(CL_INVALID_VALUE); + + if (!reg->size) + throw error(CL_INVALID_BUFFER_SIZE); + + ret_error(r_errcode, CL_SUCCESS); + return new sub_buffer(parent, flags, reg->origin, reg->size); + + } else { + throw error(CL_INVALID_VALUE); + } + +} catch (error &e) { + ret_error(r_errcode, e); + return NULL; +} + +CLOVER_API cl_mem +clCreateImage(cl_context d_ctx, cl_mem_flags d_flags, + const cl_image_format *format, + const cl_image_desc *desc, + void *host_ptr, cl_int *r_errcode) try { + auto &ctx = obj(d_ctx); + + if (!any_of(std::mem_fn(&device::image_support), ctx.devices())) + throw error(CL_INVALID_OPERATION); + + if (!format) + throw error(CL_INVALID_IMAGE_FORMAT_DESCRIPTOR); + + if (!desc) + throw error(CL_INVALID_IMAGE_DESCRIPTOR); + + if (desc->image_array_size == 0 && + (desc->image_type == CL_MEM_OBJECT_IMAGE1D_ARRAY || + desc->image_type == CL_MEM_OBJECT_IMAGE2D_ARRAY)) + throw error(CL_INVALID_IMAGE_DESCRIPTOR); + + if (!host_ptr && + (desc->image_row_pitch || desc->image_slice_pitch)) + throw error(CL_INVALID_IMAGE_DESCRIPTOR); + + if (desc->num_mip_levels || desc->num_samples) + throw error(CL_INVALID_IMAGE_DESCRIPTOR); + + if (bool(desc->buffer) != (desc->image_type == CL_MEM_OBJECT_IMAGE1D_BUFFER)) + throw error(CL_INVALID_IMAGE_DESCRIPTOR); + + if (bool(host_ptr) != bool(d_flags & (CL_MEM_USE_HOST_PTR | + CL_MEM_COPY_HOST_PTR))) + throw error(CL_INVALID_HOST_PTR); + + const cl_mem_flags flags = validate_flags(desc->buffer, d_flags, false); + + if (!supported_formats(ctx, desc->image_type).count(*format)) + throw error(CL_IMAGE_FORMAT_NOT_SUPPORTED); + + ret_error(r_errcode, CL_SUCCESS); + + switch (desc->image_type) { + case CL_MEM_OBJECT_IMAGE2D: + if (!desc->image_width || !desc->image_height) + throw error(CL_INVALID_IMAGE_SIZE); + + if (all_of([=](const device &dev) { + const size_t max = 1 << dev.max_image_levels_2d(); + return (desc->image_width > max || + desc->image_height > max); + }, ctx.devices())) + throw error(CL_INVALID_IMAGE_SIZE); + + return new image2d(ctx, flags, format, + desc->image_width, desc->image_height, + desc->image_row_pitch, host_ptr); + + case CL_MEM_OBJECT_IMAGE3D: + if (!desc->image_width || !desc->image_height || !desc->image_depth) + throw error(CL_INVALID_IMAGE_SIZE); + + if (all_of([=](const device &dev) { + const size_t max = 1 << dev.max_image_levels_3d(); + return (desc->image_width > max || + desc->image_height > max || + desc->image_depth > max); + }, ctx.devices())) + throw error(CL_INVALID_IMAGE_SIZE); + + return new image3d(ctx, flags, format, + desc->image_width, desc->image_height, + desc->image_depth, desc->image_row_pitch, + desc->image_slice_pitch, host_ptr); + + case CL_MEM_OBJECT_IMAGE1D: + case CL_MEM_OBJECT_IMAGE1D_ARRAY: + case CL_MEM_OBJECT_IMAGE1D_BUFFER: + case CL_MEM_OBJECT_IMAGE2D_ARRAY: + // XXX - Not implemented. + throw error(CL_IMAGE_FORMAT_NOT_SUPPORTED); + + default: + throw error(CL_INVALID_IMAGE_DESCRIPTOR); + } + +} catch (error &e) { + ret_error(r_errcode, e); + return NULL; +} + +CLOVER_API cl_mem +clCreateImage2D(cl_context d_ctx, cl_mem_flags d_flags, + const cl_image_format *format, + size_t width, size_t height, size_t row_pitch, + void *host_ptr, cl_int *r_errcode) { + const cl_image_desc desc = { CL_MEM_OBJECT_IMAGE2D, width, height, 0, 0, + row_pitch, 0, 0, 0, NULL }; + + return clCreateImage(d_ctx, d_flags, format, &desc, host_ptr, r_errcode); +} + +CLOVER_API cl_mem +clCreateImage3D(cl_context d_ctx, cl_mem_flags d_flags, + const cl_image_format *format, + size_t width, size_t height, size_t depth, + size_t row_pitch, size_t slice_pitch, + void *host_ptr, cl_int *r_errcode) { + const cl_image_desc desc = { CL_MEM_OBJECT_IMAGE3D, width, height, depth, 0, + row_pitch, slice_pitch, 0, 0, NULL }; + + return clCreateImage(d_ctx, d_flags, format, &desc, host_ptr, r_errcode); +} + +CLOVER_API cl_int +clGetSupportedImageFormats(cl_context d_ctx, cl_mem_flags flags, + cl_mem_object_type type, cl_uint count, + cl_image_format *r_buf, cl_uint *r_count) try { + auto &ctx = obj(d_ctx); + auto formats = supported_formats(ctx, type); + + validate_flags(NULL, flags, false); + + if (r_buf && !r_count) + throw error(CL_INVALID_VALUE); + + if (r_buf) + std::copy_n(formats.begin(), + std::min((cl_uint)formats.size(), count), + r_buf); + + if (r_count) + *r_count = formats.size(); + + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clGetMemObjectInfo(cl_mem d_mem, cl_mem_info param, + size_t size, void *r_buf, size_t *r_size) try { + property_buffer buf { r_buf, size, r_size }; + auto &mem = obj(d_mem); + + switch (param) { + case CL_MEM_TYPE: + buf.as_scalar() = mem.type(); + break; + + case CL_MEM_FLAGS: + buf.as_scalar() = mem.flags(); + break; + + case CL_MEM_SIZE: + buf.as_scalar() = mem.size(); + break; + + case CL_MEM_HOST_PTR: + buf.as_scalar() = mem.host_ptr(); + break; + + case CL_MEM_MAP_COUNT: + buf.as_scalar() = 0; + break; + + case CL_MEM_REFERENCE_COUNT: + buf.as_scalar() = mem.ref_count(); + break; + + case CL_MEM_CONTEXT: + buf.as_scalar() = desc(mem.context()); + break; + + case CL_MEM_ASSOCIATED_MEMOBJECT: { + sub_buffer *sub = dynamic_cast(&mem); + buf.as_scalar() = (sub ? desc(sub->parent()) : NULL); + break; + } + case CL_MEM_OFFSET: { + sub_buffer *sub = dynamic_cast(&mem); + buf.as_scalar() = (sub ? sub->offset() : 0); + break; + } + case CL_MEM_USES_SVM_POINTER: + case CL_MEM_USES_SVM_POINTER_ARM: { + // with system SVM all host ptrs are SVM pointers + // TODO: once we support devices with lower levels of SVM, we have to + // check the ptr in more detail + const bool system_svm = all_of(std::mem_fn(&device::has_system_svm), + mem.context().devices()); + buf.as_scalar() = mem.host_ptr() && system_svm; + break; + } + default: + throw error(CL_INVALID_VALUE); + } + + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clGetImageInfo(cl_mem d_mem, cl_image_info param, + size_t size, void *r_buf, size_t *r_size) try { + property_buffer buf { r_buf, size, r_size }; + auto &img = obj(d_mem); + + switch (param) { + case CL_IMAGE_FORMAT: + buf.as_scalar() = img.format(); + break; + + case CL_IMAGE_ELEMENT_SIZE: + buf.as_scalar() = 0; + break; + + case CL_IMAGE_ROW_PITCH: + buf.as_scalar() = img.row_pitch(); + break; + + case CL_IMAGE_SLICE_PITCH: + buf.as_scalar() = img.slice_pitch(); + break; + + case CL_IMAGE_WIDTH: + buf.as_scalar() = img.width(); + break; + + case CL_IMAGE_HEIGHT: + buf.as_scalar() = img.height(); + break; + + case CL_IMAGE_DEPTH: + buf.as_scalar() = img.depth(); + break; + + default: + throw error(CL_INVALID_VALUE); + } + + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clRetainMemObject(cl_mem d_mem) try { + obj(d_mem).retain(); + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clReleaseMemObject(cl_mem d_mem) try { + if (obj(d_mem).release()) + delete pobj(d_mem); + + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clSetMemObjectDestructorCallback(cl_mem d_mem, + void (CL_CALLBACK *pfn_notify)(cl_mem, void *), + void *user_data) try { + auto &mem = obj(d_mem); + + if (!pfn_notify) + return CL_INVALID_VALUE; + + mem.destroy_notify([=]{ pfn_notify(d_mem, user_data); }); + + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clEnqueueFillBuffer(cl_command_queue command_queue, cl_mem buffer, + const void *pattern, size_t pattern_size, + size_t offset, size_t size, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event) { + CLOVER_NOT_SUPPORTED_UNTIL("1.2"); + return CL_INVALID_VALUE; +} + +CLOVER_API cl_int +clEnqueueFillImage(cl_command_queue command_queue, cl_mem image, + const void *fill_color, + const size_t *origin, const size_t *region, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event) { + CLOVER_NOT_SUPPORTED_UNTIL("1.2"); + return CL_INVALID_VALUE; +} + +CLOVER_API void * +clSVMAlloc(cl_context d_ctx, + cl_svm_mem_flags flags, + size_t size, + unsigned int alignment) try { + auto &ctx = obj(d_ctx); + validate_flags(NULL, flags, true); + + if (!size || + size > fold(minimum(), cl_ulong(ULONG_MAX), + map(std::mem_fn(&device::max_mem_alloc_size), ctx.devices()))) + return nullptr; + + if (!util_is_power_of_two_or_zero(alignment)) + return nullptr; + + if (!alignment) + alignment = 0x80; // sizeof(long16) + + bool can_emulate = all_of(std::mem_fn(&device::has_system_svm), ctx.devices()); + if (can_emulate) { + // we can ignore all the flags as it's not required to honor them. + void *ptr = nullptr; + if (alignment < sizeof(void*)) + alignment = sizeof(void*); + posix_memalign(&ptr, alignment, size); + return ptr; + } + + CLOVER_NOT_SUPPORTED_UNTIL("2.0"); + return nullptr; + +} catch (error &e) { + return nullptr; +} + +CLOVER_API void +clSVMFree(cl_context d_ctx, + void *svm_pointer) try { + auto &ctx = obj(d_ctx); + bool can_emulate = all_of(std::mem_fn(&device::has_system_svm), ctx.devices()); + + if (can_emulate) + return free(svm_pointer); + + CLOVER_NOT_SUPPORTED_UNTIL("2.0"); + +} catch (error &e) { +} diff --git a/src/gallium/frontends/clover/api/platform.cpp b/src/gallium/frontends/clover/api/platform.cpp new file mode 100644 index 00000000000..7360461e62f --- /dev/null +++ b/src/gallium/frontends/clover/api/platform.cpp @@ -0,0 +1,235 @@ +// +// Copyright 2012 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#include + +#include "api/dispatch.hpp" +#include "api/util.hpp" +#include "core/platform.hpp" +#include "git_sha1.h" +#include "util/u_debug.h" + +using namespace clover; + +namespace { + platform _clover_platform; +} + +CLOVER_API cl_int +clGetPlatformIDs(cl_uint num_entries, cl_platform_id *rd_platforms, + cl_uint *rnum_platforms) { + if ((!num_entries && rd_platforms) || + (!rnum_platforms && !rd_platforms)) + return CL_INVALID_VALUE; + + if (rnum_platforms) + *rnum_platforms = 1; + if (rd_platforms) + *rd_platforms = desc(_clover_platform); + + return CL_SUCCESS; +} + +cl_int +clover::GetPlatformInfo(cl_platform_id d_platform, cl_platform_info param, + size_t size, void *r_buf, size_t *r_size) try { + property_buffer buf { r_buf, size, r_size }; + + auto &platform = obj(d_platform); + + switch (param) { + case CL_PLATFORM_PROFILE: + buf.as_string() = "FULL_PROFILE"; + break; + + case CL_PLATFORM_VERSION: { + static const std::string version_string = + debug_get_option("CLOVER_PLATFORM_VERSION_OVERRIDE", "1.1"); + + buf.as_string() = "OpenCL " + version_string + " Mesa " PACKAGE_VERSION MESA_GIT_SHA1; + break; + } + case CL_PLATFORM_NAME: + buf.as_string() = "Clover"; + break; + + case CL_PLATFORM_VENDOR: + buf.as_string() = "Mesa"; + break; + + case CL_PLATFORM_EXTENSIONS: + buf.as_string() = platform.supported_extensions(); + break; + + case CL_PLATFORM_ICD_SUFFIX_KHR: + buf.as_string() = "MESA"; + break; + + default: + throw error(CL_INVALID_VALUE); + } + + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +void * +clover::GetExtensionFunctionAddressForPlatform(cl_platform_id d_platform, + const char *p_name) try { + obj(d_platform); + return GetExtensionFunctionAddress(p_name); + +} catch (error &e) { + return NULL; +} + +namespace { + +cl_int +enqueueSVMFreeARM(cl_command_queue command_queue, + cl_uint num_svm_pointers, + void *svm_pointers[], + void (CL_CALLBACK *pfn_free_func) ( + cl_command_queue queue, cl_uint num_svm_pointers, + void *svm_pointers[], void *user_data), + void *user_data, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event) { + + return EnqueueSVMFree(command_queue, num_svm_pointers, svm_pointers, + pfn_free_func, user_data, num_events_in_wait_list, + event_wait_list, event, CL_COMMAND_SVM_FREE_ARM); +} + +cl_int +enqueueSVMMapARM(cl_command_queue command_queue, + cl_bool blocking_map, + cl_map_flags map_flags, + void *svm_ptr, + size_t size, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event) { + + return EnqueueSVMMap(command_queue, blocking_map, map_flags, svm_ptr, size, + num_events_in_wait_list, event_wait_list, event, + CL_COMMAND_SVM_MAP_ARM); +} + +cl_int +enqueueSVMMemcpyARM(cl_command_queue command_queue, + cl_bool blocking_copy, + void *dst_ptr, + const void *src_ptr, + size_t size, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event) { + + return EnqueueSVMMemcpy(command_queue, blocking_copy, dst_ptr, src_ptr, + size, num_events_in_wait_list, event_wait_list, + event, CL_COMMAND_SVM_MEMCPY_ARM); +} + +cl_int +enqueueSVMMemFillARM(cl_command_queue command_queue, + void *svm_ptr, + const void *pattern, + size_t pattern_size, + size_t size, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event) { + + return EnqueueSVMMemFill(command_queue, svm_ptr, pattern, pattern_size, + size, num_events_in_wait_list, event_wait_list, + event, CL_COMMAND_SVM_MEMFILL_ARM); +} + +cl_int +enqueueSVMUnmapARM(cl_command_queue command_queue, + void *svm_ptr, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event) { + + return EnqueueSVMUnmap(command_queue, svm_ptr, num_events_in_wait_list, + event_wait_list, event, CL_COMMAND_SVM_UNMAP_ARM); +} + +const std::unordered_map +ext_funcs = { + // cl_arm_shared_virtual_memory + { "clEnqueueSVMFreeARM", reinterpret_cast(enqueueSVMFreeARM) }, + { "clEnqueueSVMMapARM", reinterpret_cast(enqueueSVMMapARM) }, + { "clEnqueueSVMMemcpyARM", reinterpret_cast(enqueueSVMMemcpyARM) }, + { "clEnqueueSVMMemFillARM", reinterpret_cast(enqueueSVMMemFillARM) }, + { "clEnqueueSVMUnmapARM", reinterpret_cast(enqueueSVMUnmapARM) }, + { "clSetKernelArgSVMPointerARM", reinterpret_cast(clSetKernelArgSVMPointer) }, + { "clSetKernelExecInfoARM", reinterpret_cast(clSetKernelExecInfo) }, + { "clSVMAllocARM", reinterpret_cast(clSVMAlloc) }, + { "clSVMFreeARM", reinterpret_cast(clSVMFree) }, + + // cl_khr_icd + { "clIcdGetPlatformIDsKHR", reinterpret_cast(IcdGetPlatformIDsKHR) }, +}; + +} // anonymous namespace + +void * +clover::GetExtensionFunctionAddress(const char *p_name) try { + return ext_funcs.at(p_name); +} catch (...) { + return nullptr; +} + +cl_int +clover::IcdGetPlatformIDsKHR(cl_uint num_entries, cl_platform_id *rd_platforms, + cl_uint *rnum_platforms) { + return clGetPlatformIDs(num_entries, rd_platforms, rnum_platforms); +} + +CLOVER_ICD_API cl_int +clGetPlatformInfo(cl_platform_id d_platform, cl_platform_info param, + size_t size, void *r_buf, size_t *r_size) { + return GetPlatformInfo(d_platform, param, size, r_buf, r_size); +} + +CLOVER_ICD_API void * +clGetExtensionFunctionAddress(const char *p_name) { + return GetExtensionFunctionAddress(p_name); +} + +CLOVER_ICD_API void * +clGetExtensionFunctionAddressForPlatform(cl_platform_id d_platform, + const char *p_name) { + return GetExtensionFunctionAddressForPlatform(d_platform, p_name); +} + +CLOVER_ICD_API cl_int +clIcdGetPlatformIDsKHR(cl_uint num_entries, cl_platform_id *rd_platforms, + cl_uint *rnum_platforms) { + return IcdGetPlatformIDsKHR(num_entries, rd_platforms, rnum_platforms); +} diff --git a/src/gallium/frontends/clover/api/program.cpp b/src/gallium/frontends/clover/api/program.cpp new file mode 100644 index 00000000000..33f843e9c87 --- /dev/null +++ b/src/gallium/frontends/clover/api/program.cpp @@ -0,0 +1,479 @@ +// +// Copyright 2012 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#include "api/util.hpp" +#include "core/program.hpp" +#include "util/u_debug.h" + +#include + +using namespace clover; + +namespace { + void + validate_build_common(const program &prog, cl_uint num_devs, + const cl_device_id *d_devs, + void (*pfn_notify)(cl_program, void *), + void *user_data) { + if (!pfn_notify && user_data) + throw error(CL_INVALID_VALUE); + + if (prog.kernel_ref_count()) + throw error(CL_INVALID_OPERATION); + + if (any_of([&](const device &dev) { + return !count(dev, prog.devices()); + }, objs(d_devs, num_devs))) + throw error(CL_INVALID_DEVICE); + } +} + +CLOVER_API cl_program +clCreateProgramWithSource(cl_context d_ctx, cl_uint count, + const char **strings, const size_t *lengths, + cl_int *r_errcode) try { + auto &ctx = obj(d_ctx); + std::string source; + + if (!count || !strings || + any_of(is_zero(), range(strings, count))) + throw error(CL_INVALID_VALUE); + + // Concatenate all the provided fragments together + for (unsigned i = 0; i < count; ++i) + source += (lengths && lengths[i] ? + std::string(strings[i], strings[i] + lengths[i]) : + std::string(strings[i])); + + // ...and create a program object for them. + ret_error(r_errcode, CL_SUCCESS); + return new program(ctx, source); + +} catch (error &e) { + ret_error(r_errcode, e); + return NULL; +} + +CLOVER_API cl_program +clCreateProgramWithBinary(cl_context d_ctx, cl_uint n, + const cl_device_id *d_devs, + const size_t *lengths, + const unsigned char **binaries, + cl_int *r_status, cl_int *r_errcode) try { + auto &ctx = obj(d_ctx); + auto devs = objs(d_devs, n); + + if (!lengths || !binaries) + throw error(CL_INVALID_VALUE); + + if (any_of([&](const device &dev) { + return !count(dev, ctx.devices()); + }, devs)) + throw error(CL_INVALID_DEVICE); + + // Deserialize the provided binaries, + std::vector> result = map( + [](const unsigned char *p, size_t l) -> std::pair { + if (!p || !l) + return { CL_INVALID_VALUE, {} }; + + try { + std::stringbuf bin( { (char*)p, l } ); + std::istream s(&bin); + + return { CL_SUCCESS, module::deserialize(s) }; + + } catch (std::istream::failure &e) { + return { CL_INVALID_BINARY, {} }; + } + }, + range(binaries, n), + range(lengths, n)); + + // update the status array, + if (r_status) + copy(map(keys(), result), r_status); + + if (any_of(key_equals(CL_INVALID_VALUE), result)) + throw error(CL_INVALID_VALUE); + + if (any_of(key_equals(CL_INVALID_BINARY), result)) + throw error(CL_INVALID_BINARY); + + // initialize a program object with them. + ret_error(r_errcode, CL_SUCCESS); + return new program(ctx, devs, map(values(), result)); + +} catch (error &e) { + ret_error(r_errcode, e); + return NULL; +} + +CLOVER_API cl_program +clCreateProgramWithBuiltInKernels(cl_context d_ctx, cl_uint n, + const cl_device_id *d_devs, + const char *kernel_names, + cl_int *r_errcode) try { + auto &ctx = obj(d_ctx); + auto devs = objs(d_devs, n); + + if (any_of([&](const device &dev) { + return !count(dev, ctx.devices()); + }, devs)) + throw error(CL_INVALID_DEVICE); + + // No currently supported built-in kernels. + throw error(CL_INVALID_VALUE); + +} catch (error &e) { + ret_error(r_errcode, e); + return NULL; +} + + +CLOVER_API cl_int +clRetainProgram(cl_program d_prog) try { + obj(d_prog).retain(); + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clReleaseProgram(cl_program d_prog) try { + if (obj(d_prog).release()) + delete pobj(d_prog); + + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clBuildProgram(cl_program d_prog, cl_uint num_devs, + const cl_device_id *d_devs, const char *p_opts, + void (*pfn_notify)(cl_program, void *), + void *user_data) try { + auto &prog = obj(d_prog); + auto devs = + (d_devs ? objs(d_devs, num_devs) : ref_vector(prog.devices())); + const auto opts = std::string(p_opts ? p_opts : "") + " " + + debug_get_option("CLOVER_EXTRA_BUILD_OPTIONS", ""); + + validate_build_common(prog, num_devs, d_devs, pfn_notify, user_data); + + if (prog.has_source) { + prog.compile(devs, opts); + prog.link(devs, opts, { prog }); + } else if (any_of([&](const device &dev){ + return prog.build(dev).binary_type() != CL_PROGRAM_BINARY_TYPE_EXECUTABLE; + }, devs)) { + // According to the OpenCL 1.2 specification, “if program is created + // with clCreateProgramWithBinary, then the program binary must be an + // executable binary (not a compiled binary or library).” + throw error(CL_INVALID_BINARY); + } + + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clCompileProgram(cl_program d_prog, cl_uint num_devs, + const cl_device_id *d_devs, const char *p_opts, + cl_uint num_headers, const cl_program *d_header_progs, + const char **header_names, + void (*pfn_notify)(cl_program, void *), + void *user_data) try { + auto &prog = obj(d_prog); + auto devs = + (d_devs ? objs(d_devs, num_devs) : ref_vector(prog.devices())); + const auto opts = std::string(p_opts ? p_opts : "") + " " + + debug_get_option("CLOVER_EXTRA_COMPILE_OPTIONS", ""); + header_map headers; + + validate_build_common(prog, num_devs, d_devs, pfn_notify, user_data); + + if (bool(num_headers) != bool(header_names)) + throw error(CL_INVALID_VALUE); + + if (!prog.has_source) + throw error(CL_INVALID_OPERATION); + + for_each([&](const char *name, const program &header) { + if (!header.has_source) + throw error(CL_INVALID_OPERATION); + + if (!any_of(key_equals(name), headers)) + headers.push_back(std::pair( + name, header.source())); + }, + range(header_names, num_headers), + objs(d_header_progs, num_headers)); + + prog.compile(devs, opts, headers); + return CL_SUCCESS; + +} catch (invalid_build_options_error &e) { + return CL_INVALID_COMPILER_OPTIONS; + +} catch (build_error &e) { + return CL_COMPILE_PROGRAM_FAILURE; + +} catch (error &e) { + return e.get(); +} + +namespace { + ref_vector + validate_link_devices(const ref_vector &progs, + const ref_vector &all_devs, + const std::string &opts) { + std::vector devs; + const bool create_library = + opts.find("-create-library") != std::string::npos; + const bool enable_link_options = + opts.find("-enable-link-options") != std::string::npos; + const bool has_link_options = + opts.find("-cl-denorms-are-zero") != std::string::npos || + opts.find("-cl-no-signed-zeroes") != std::string::npos || + opts.find("-cl-unsafe-math-optimizations") != std::string::npos || + opts.find("-cl-finite-math-only") != std::string::npos || + opts.find("-cl-fast-relaxed-math") != std::string::npos || + opts.find("-cl-no-subgroup-ifp") != std::string::npos; + + // According to the OpenCL 1.2 specification, "[the + // -enable-link-options] option must be specified with the + // create-library option". + if (enable_link_options && !create_library) + throw error(CL_INVALID_LINKER_OPTIONS); + + // According to the OpenCL 1.2 specification, "the + // [program linking options] can be specified when linking a program + // executable". + if (has_link_options && create_library) + throw error(CL_INVALID_LINKER_OPTIONS); + + for (auto &dev : all_devs) { + const auto has_binary = [&](const program &prog) { + const auto t = prog.build(dev).binary_type(); + return t == CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT || + t == CL_PROGRAM_BINARY_TYPE_LIBRARY; + }; + + // According to the OpenCL 1.2 specification, a library is made of + // “compiled binaries specified in input_programs argument to + // clLinkProgram“; compiled binaries does not refer to libraries: + // “input_programs is an array of program objects that are compiled + // binaries or libraries that are to be linked to create the program + // executable”. + if (create_library && any_of([&](const program &prog) { + const auto t = prog.build(dev).binary_type(); + return t != CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT; + }, progs)) + throw error(CL_INVALID_OPERATION); + + // According to the CL 1.2 spec, when "all programs specified [..] + // contain a compiled binary or library for the device [..] a link is + // performed", + else if (all_of(has_binary, progs)) + devs.push_back(&dev); + + // otherwise if "none of the programs contain a compiled binary or + // library for that device [..] no link is performed. All other + // cases will return a CL_INVALID_OPERATION error." + else if (any_of(has_binary, progs)) + throw error(CL_INVALID_OPERATION); + + // According to the OpenCL 1.2 specification, "[t]he linker may apply + // [program linking options] to all compiled program objects + // specified to clLinkProgram. The linker may apply these options + // only to libraries which were created with the + // -enable-link-option." + else if (has_link_options && any_of([&](const program &prog) { + const auto t = prog.build(dev).binary_type(); + return !(t == CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT || + (t == CL_PROGRAM_BINARY_TYPE_LIBRARY && + prog.build(dev).opts.find("-enable-link-options") != + std::string::npos)); + }, progs)) + throw error(CL_INVALID_LINKER_OPTIONS); + } + + return map(derefs(), devs); + } +} + +CLOVER_API cl_program +clLinkProgram(cl_context d_ctx, cl_uint num_devs, const cl_device_id *d_devs, + const char *p_opts, cl_uint num_progs, const cl_program *d_progs, + void (*pfn_notify) (cl_program, void *), void *user_data, + cl_int *r_errcode) try { + auto &ctx = obj(d_ctx); + const auto opts = std::string(p_opts ? p_opts : "") + " " + + debug_get_option("CLOVER_EXTRA_LINK_OPTIONS", ""); + auto progs = objs(d_progs, num_progs); + auto all_devs = + (d_devs ? objs(d_devs, num_devs) : ref_vector(ctx.devices())); + auto prog = create(ctx, all_devs); + auto devs = validate_link_devices(progs, all_devs, opts); + + validate_build_common(prog, num_devs, d_devs, pfn_notify, user_data); + + try { + prog().link(devs, opts, progs); + ret_error(r_errcode, CL_SUCCESS); + + } catch (build_error &e) { + ret_error(r_errcode, CL_LINK_PROGRAM_FAILURE); + } + + return ret_object(prog); + +} catch (invalid_build_options_error &e) { + ret_error(r_errcode, CL_INVALID_LINKER_OPTIONS); + return NULL; + +} catch (error &e) { + ret_error(r_errcode, e); + return NULL; +} + +CLOVER_API cl_int +clUnloadCompiler() { + return CL_SUCCESS; +} + +CLOVER_API cl_int +clUnloadPlatformCompiler(cl_platform_id d_platform) { + return CL_SUCCESS; +} + +CLOVER_API cl_int +clGetProgramInfo(cl_program d_prog, cl_program_info param, + size_t size, void *r_buf, size_t *r_size) try { + property_buffer buf { r_buf, size, r_size }; + auto &prog = obj(d_prog); + + switch (param) { + case CL_PROGRAM_REFERENCE_COUNT: + buf.as_scalar() = prog.ref_count(); + break; + + case CL_PROGRAM_CONTEXT: + buf.as_scalar() = desc(prog.context()); + break; + + case CL_PROGRAM_NUM_DEVICES: + buf.as_scalar() = (prog.devices().size() ? + prog.devices().size() : + prog.context().devices().size()); + break; + + case CL_PROGRAM_DEVICES: + buf.as_vector() = (prog.devices().size() ? + descs(prog.devices()) : + descs(prog.context().devices())); + break; + + case CL_PROGRAM_SOURCE: + buf.as_string() = prog.source(); + break; + + case CL_PROGRAM_BINARY_SIZES: + buf.as_vector() = map([&](const device &dev) { + return prog.build(dev).binary.size(); + }, + prog.devices()); + break; + + case CL_PROGRAM_BINARIES: + buf.as_matrix() = map([&](const device &dev) { + std::stringbuf bin; + std::ostream s(&bin); + prog.build(dev).binary.serialize(s); + return bin.str(); + }, + prog.devices()); + break; + + case CL_PROGRAM_NUM_KERNELS: + buf.as_scalar() = prog.symbols().size(); + break; + + case CL_PROGRAM_KERNEL_NAMES: + buf.as_string() = fold([](const std::string &a, const module::symbol &s) { + return ((a.empty() ? "" : a + ";") + s.name); + }, std::string(), prog.symbols()); + break; + + default: + throw error(CL_INVALID_VALUE); + } + + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clGetProgramBuildInfo(cl_program d_prog, cl_device_id d_dev, + cl_program_build_info param, + size_t size, void *r_buf, size_t *r_size) try { + property_buffer buf { r_buf, size, r_size }; + auto &prog = obj(d_prog); + auto &dev = obj(d_dev); + + if (!count(dev, prog.context().devices())) + return CL_INVALID_DEVICE; + + switch (param) { + case CL_PROGRAM_BUILD_STATUS: + buf.as_scalar() = prog.build(dev).status(); + break; + + case CL_PROGRAM_BUILD_OPTIONS: + buf.as_string() = prog.build(dev).opts; + break; + + case CL_PROGRAM_BUILD_LOG: + buf.as_string() = prog.build(dev).log; + break; + + case CL_PROGRAM_BINARY_TYPE: + buf.as_scalar() = prog.build(dev).binary_type(); + break; + + default: + throw error(CL_INVALID_VALUE); + } + + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} diff --git a/src/gallium/frontends/clover/api/queue.cpp b/src/gallium/frontends/clover/api/queue.cpp new file mode 100644 index 00000000000..65b271b216f --- /dev/null +++ b/src/gallium/frontends/clover/api/queue.cpp @@ -0,0 +1,135 @@ +// +// Copyright 2012 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#include "api/util.hpp" +#include "core/queue.hpp" + +using namespace clover; + +CLOVER_API cl_command_queue +clCreateCommandQueue(cl_context d_ctx, cl_device_id d_dev, + cl_command_queue_properties props, + cl_int *r_errcode) try { + auto &ctx = obj(d_ctx); + auto &dev = obj(d_dev); + + if (!count(dev, ctx.devices())) + throw error(CL_INVALID_DEVICE); + + if (props & ~(CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE | + CL_QUEUE_PROFILING_ENABLE)) + throw error(CL_INVALID_VALUE); + + ret_error(r_errcode, CL_SUCCESS); + return new command_queue(ctx, dev, props); + +} catch (error &e) { + ret_error(r_errcode, e); + return NULL; +} + +CLOVER_API cl_int +clRetainCommandQueue(cl_command_queue d_q) try { + obj(d_q).retain(); + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clReleaseCommandQueue(cl_command_queue d_q) try { + auto &q = obj(d_q); + + q.flush(); + + if (q.release()) + delete pobj(d_q); + + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clGetCommandQueueInfo(cl_command_queue d_q, cl_command_queue_info param, + size_t size, void *r_buf, size_t *r_size) try { + property_buffer buf { r_buf, size, r_size }; + auto &q = obj(d_q); + + switch (param) { + case CL_QUEUE_CONTEXT: + buf.as_scalar() = desc(q.context()); + break; + + case CL_QUEUE_DEVICE: + buf.as_scalar() = desc(q.device()); + break; + + case CL_QUEUE_REFERENCE_COUNT: + buf.as_scalar() = q.ref_count(); + break; + + case CL_QUEUE_PROPERTIES: + buf.as_scalar() = q.properties(); + break; + + default: + throw error(CL_INVALID_VALUE); + } + + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clFlush(cl_command_queue d_q) try { + obj(d_q).flush(); + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_command_queue +clCreateCommandQueueWithProperties(cl_context context, cl_device_id device, + const cl_queue_properties *properties, + cl_int *errcode_ret) try { + cl_command_queue_properties props = 0; + if (properties) { + for (auto idx = 0; properties[idx]; idx += 2) { + if (properties[idx] == CL_QUEUE_PROPERTIES) + props |= properties[idx + 1]; + else + throw error(CL_INVALID_VALUE); + } + } + + return clCreateCommandQueue(context, device, props, errcode_ret); + +} catch (error &e) { + ret_error(errcode_ret, e); + return NULL; +} diff --git a/src/gallium/frontends/clover/api/sampler.cpp b/src/gallium/frontends/clover/api/sampler.cpp new file mode 100644 index 00000000000..482e55a9ce9 --- /dev/null +++ b/src/gallium/frontends/clover/api/sampler.cpp @@ -0,0 +1,100 @@ +// +// Copyright 2012 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#include "api/util.hpp" +#include "core/sampler.hpp" + +using namespace clover; + +CLOVER_API cl_sampler +clCreateSampler(cl_context d_ctx, cl_bool norm_mode, + cl_addressing_mode addr_mode, cl_filter_mode filter_mode, + cl_int *r_errcode) try { + auto &ctx = obj(d_ctx); + + if (!any_of(std::mem_fn(&device::image_support), ctx.devices())) + throw error(CL_INVALID_OPERATION); + + ret_error(r_errcode, CL_SUCCESS); + return new sampler(ctx, norm_mode, addr_mode, filter_mode); + +} catch (error &e) { + ret_error(r_errcode, e); + return NULL; +} + +CLOVER_API cl_int +clRetainSampler(cl_sampler d_s) try { + obj(d_s).retain(); + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clReleaseSampler(cl_sampler d_s) try { + if (obj(d_s).release()) + delete pobj(d_s); + + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clGetSamplerInfo(cl_sampler d_s, cl_sampler_info param, + size_t size, void *r_buf, size_t *r_size) try { + property_buffer buf { r_buf, size, r_size }; + auto &s = obj(d_s); + + switch (param) { + case CL_SAMPLER_REFERENCE_COUNT: + buf.as_scalar() = s.ref_count(); + break; + + case CL_SAMPLER_CONTEXT: + buf.as_scalar() = desc(s.context()); + break; + + case CL_SAMPLER_NORMALIZED_COORDS: + buf.as_scalar() = s.norm_mode(); + break; + + case CL_SAMPLER_ADDRESSING_MODE: + buf.as_scalar() = s.addr_mode(); + break; + + case CL_SAMPLER_FILTER_MODE: + buf.as_scalar() = s.filter_mode(); + break; + + default: + throw error(CL_INVALID_VALUE); + } + + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} diff --git a/src/gallium/frontends/clover/api/transfer.cpp b/src/gallium/frontends/clover/api/transfer.cpp new file mode 100644 index 00000000000..fa8741e02b4 --- /dev/null +++ b/src/gallium/frontends/clover/api/transfer.cpp @@ -0,0 +1,1059 @@ +// +// Copyright 2012 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#include + +#include "util/bitscan.h" + +#include "api/dispatch.hpp" +#include "api/util.hpp" +#include "core/event.hpp" +#include "core/memory.hpp" + +using namespace clover; + +namespace { + typedef resource::vector vector_t; + + vector_t + vector(const size_t *p) { + return range(p, 3); + } + + vector_t + pitch(const vector_t ®ion, vector_t pitch) { + for (auto x : zip(tail(pitch), + map(multiplies(), region, pitch))) { + // The spec defines a value of zero as the natural pitch, + // i.e. the unaligned size of the previous dimension. + if (std::get<0>(x) == 0) + std::get<0>(x) = std::get<1>(x); + } + + return pitch; + } + + /// + /// Size of a region in bytes. + /// + size_t + size(const vector_t &pitch, const vector_t ®ion) { + if (any_of(is_zero(), region)) + return 0; + else + return dot(pitch, region - vector_t{ 0, 1, 1 }); + } + + /// + /// Common argument checking shared by memory transfer commands. + /// + void + validate_common(command_queue &q, + const ref_vector &deps) { + if (any_of([&](const event &ev) { + return ev.context() != q.context(); + }, deps)) + throw error(CL_INVALID_CONTEXT); + } + + /// + /// Common error checking for a buffer object argument. + /// + void + validate_object(command_queue &q, buffer &mem, const vector_t &origin, + const vector_t &pitch, const vector_t ®ion) { + if (mem.context() != q.context()) + throw error(CL_INVALID_CONTEXT); + + // The region must fit within the specified pitch, + if (any_of(greater(), map(multiplies(), pitch, region), tail(pitch))) + throw error(CL_INVALID_VALUE); + + // ...and within the specified object. + if (dot(pitch, origin) + size(pitch, region) > mem.size()) + throw error(CL_INVALID_VALUE); + + if (any_of(is_zero(), region)) + throw error(CL_INVALID_VALUE); + } + + /// + /// Common error checking for an image argument. + /// + void + validate_object(command_queue &q, image &img, + const vector_t &orig, const vector_t ®ion) { + vector_t size = { img.width(), img.height(), img.depth() }; + + if (!q.device().image_support()) + throw error(CL_INVALID_OPERATION); + + if (img.context() != q.context()) + throw error(CL_INVALID_CONTEXT); + + if (any_of(greater(), orig + region, size)) + throw error(CL_INVALID_VALUE); + + if (any_of(is_zero(), region)) + throw error(CL_INVALID_VALUE); + } + + /// + /// Common error checking for a host pointer argument. + /// + void + validate_object(command_queue &q, const void *ptr, const vector_t &orig, + const vector_t &pitch, const vector_t ®ion) { + if (!ptr) + throw error(CL_INVALID_VALUE); + + // The region must fit within the specified pitch. + if (any_of(greater(), map(multiplies(), pitch, region), tail(pitch))) + throw error(CL_INVALID_VALUE); + } + + /// + /// Common argument checking for a copy between two buffer objects. + /// + void + validate_copy(command_queue &q, buffer &dst_mem, + const vector_t &dst_orig, const vector_t &dst_pitch, + buffer &src_mem, + const vector_t &src_orig, const vector_t &src_pitch, + const vector_t ®ion) { + if (dst_mem == src_mem) { + auto dst_offset = dot(dst_pitch, dst_orig); + auto src_offset = dot(src_pitch, src_orig); + + if (interval_overlaps()( + dst_offset, dst_offset + size(dst_pitch, region), + src_offset, src_offset + size(src_pitch, region))) + throw error(CL_MEM_COPY_OVERLAP); + } + } + + /// + /// Common argument checking for a copy between two image objects. + /// + void + validate_copy(command_queue &q, + image &dst_img, const vector_t &dst_orig, + image &src_img, const vector_t &src_orig, + const vector_t ®ion) { + if (dst_img.format() != src_img.format()) + throw error(CL_IMAGE_FORMAT_MISMATCH); + + if (dst_img == src_img) { + if (all_of(interval_overlaps(), + dst_orig, dst_orig + region, + src_orig, src_orig + region)) + throw error(CL_MEM_COPY_OVERLAP); + } + } + + /// + /// Checks that the host access flags of the memory object are + /// within the allowed set \a flags. + /// + void + validate_object_access(const memory_obj &mem, const cl_mem_flags flags) { + if (mem.flags() & ~flags & + (CL_MEM_HOST_READ_ONLY | CL_MEM_HOST_WRITE_ONLY | + CL_MEM_HOST_NO_ACCESS)) + throw error(CL_INVALID_OPERATION); + } + + /// + /// Checks that the mapping flags are correct. + /// + void + validate_map_flags(const memory_obj &mem, const cl_map_flags flags) { + if ((flags & (CL_MAP_WRITE | CL_MAP_READ)) && + (flags & CL_MAP_WRITE_INVALIDATE_REGION)) + throw error(CL_INVALID_VALUE); + + if (flags & CL_MAP_READ) + validate_object_access(mem, CL_MEM_HOST_READ_ONLY); + + if (flags & (CL_MAP_WRITE | CL_MAP_WRITE_INVALIDATE_REGION)) + validate_object_access(mem, CL_MEM_HOST_WRITE_ONLY); + } + + /// + /// Class that encapsulates the task of mapping an object of type + /// \a T. The return value of get() should be implicitly + /// convertible to \a void *. + /// + template + struct _map { + static mapping + get(command_queue &q, T obj, cl_map_flags flags, + size_t offset, size_t size) { + return { q, obj->resource(q), flags, true, + {{ offset }}, {{ size, 1, 1 }} }; + } + }; + + template<> + struct _map { + static void * + get(command_queue &q, void *obj, cl_map_flags flags, + size_t offset, size_t size) { + return (char *)obj + offset; + } + }; + + template<> + struct _map { + static const void * + get(command_queue &q, const void *obj, cl_map_flags flags, + size_t offset, size_t size) { + return (const char *)obj + offset; + } + }; + + /// + /// Software copy from \a src_obj to \a dst_obj. They can be + /// either pointers or memory objects. + /// + template + std::function + soft_copy_op(command_queue &q, + T dst_obj, const vector_t &dst_orig, const vector_t &dst_pitch, + S src_obj, const vector_t &src_orig, const vector_t &src_pitch, + const vector_t ®ion) { + return [=, &q](event &) { + auto dst = _map::get(q, dst_obj, CL_MAP_WRITE, + dot(dst_pitch, dst_orig), + size(dst_pitch, region)); + auto src = _map::get(q, src_obj, CL_MAP_READ, + dot(src_pitch, src_orig), + size(src_pitch, region)); + vector_t v = {}; + + for (v[2] = 0; v[2] < region[2]; ++v[2]) { + for (v[1] = 0; v[1] < region[1]; ++v[1]) { + std::memcpy( + static_cast(dst) + dot(dst_pitch, v), + static_cast(src) + dot(src_pitch, v), + src_pitch[0] * region[0]); + } + } + }; + } + + /// + /// Hardware copy from \a src_obj to \a dst_obj. + /// + template + std::function + hard_copy_op(command_queue &q, T dst_obj, const vector_t &dst_orig, + S src_obj, const vector_t &src_orig, const vector_t ®ion) { + return [=, &q](event &) { + dst_obj->resource(q).copy(q, dst_orig, region, + src_obj->resource(q), src_orig); + }; + } +} + +CLOVER_API cl_int +clEnqueueReadBuffer(cl_command_queue d_q, cl_mem d_mem, cl_bool blocking, + size_t offset, size_t size, void *ptr, + cl_uint num_deps, const cl_event *d_deps, + cl_event *rd_ev) try { + auto &q = obj(d_q); + auto &mem = obj(d_mem); + auto deps = objs(d_deps, num_deps); + vector_t region = { size, 1, 1 }; + vector_t obj_origin = { offset }; + auto obj_pitch = pitch(region, {{ 1 }}); + + validate_common(q, deps); + validate_object(q, ptr, {}, obj_pitch, region); + validate_object(q, mem, obj_origin, obj_pitch, region); + validate_object_access(mem, CL_MEM_HOST_READ_ONLY); + + auto hev = create( + q, CL_COMMAND_READ_BUFFER, deps, + soft_copy_op(q, ptr, {}, obj_pitch, + &mem, obj_origin, obj_pitch, + region)); + + if (blocking) + hev().wait_signalled(); + + ret_object(rd_ev, hev); + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clEnqueueWriteBuffer(cl_command_queue d_q, cl_mem d_mem, cl_bool blocking, + size_t offset, size_t size, const void *ptr, + cl_uint num_deps, const cl_event *d_deps, + cl_event *rd_ev) try { + auto &q = obj(d_q); + auto &mem = obj(d_mem); + auto deps = objs(d_deps, num_deps); + vector_t region = { size, 1, 1 }; + vector_t obj_origin = { offset }; + auto obj_pitch = pitch(region, {{ 1 }}); + + validate_common(q, deps); + validate_object(q, mem, obj_origin, obj_pitch, region); + validate_object(q, ptr, {}, obj_pitch, region); + validate_object_access(mem, CL_MEM_HOST_WRITE_ONLY); + + auto hev = create( + q, CL_COMMAND_WRITE_BUFFER, deps, + soft_copy_op(q, &mem, obj_origin, obj_pitch, + ptr, {}, obj_pitch, + region)); + + if (blocking) + hev().wait_signalled(); + + ret_object(rd_ev, hev); + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clEnqueueReadBufferRect(cl_command_queue d_q, cl_mem d_mem, cl_bool blocking, + const size_t *p_obj_origin, + const size_t *p_host_origin, + const size_t *p_region, + size_t obj_row_pitch, size_t obj_slice_pitch, + size_t host_row_pitch, size_t host_slice_pitch, + void *ptr, + cl_uint num_deps, const cl_event *d_deps, + cl_event *rd_ev) try { + auto &q = obj(d_q); + auto &mem = obj(d_mem); + auto deps = objs(d_deps, num_deps); + auto region = vector(p_region); + auto obj_origin = vector(p_obj_origin); + auto obj_pitch = pitch(region, {{ 1, obj_row_pitch, obj_slice_pitch }}); + auto host_origin = vector(p_host_origin); + auto host_pitch = pitch(region, {{ 1, host_row_pitch, host_slice_pitch }}); + + validate_common(q, deps); + validate_object(q, ptr, host_origin, host_pitch, region); + validate_object(q, mem, obj_origin, obj_pitch, region); + validate_object_access(mem, CL_MEM_HOST_READ_ONLY); + + auto hev = create( + q, CL_COMMAND_READ_BUFFER_RECT, deps, + soft_copy_op(q, ptr, host_origin, host_pitch, + &mem, obj_origin, obj_pitch, + region)); + + if (blocking) + hev().wait_signalled(); + + ret_object(rd_ev, hev); + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clEnqueueWriteBufferRect(cl_command_queue d_q, cl_mem d_mem, cl_bool blocking, + const size_t *p_obj_origin, + const size_t *p_host_origin, + const size_t *p_region, + size_t obj_row_pitch, size_t obj_slice_pitch, + size_t host_row_pitch, size_t host_slice_pitch, + const void *ptr, + cl_uint num_deps, const cl_event *d_deps, + cl_event *rd_ev) try { + auto &q = obj(d_q); + auto &mem = obj(d_mem); + auto deps = objs(d_deps, num_deps); + auto region = vector(p_region); + auto obj_origin = vector(p_obj_origin); + auto obj_pitch = pitch(region, {{ 1, obj_row_pitch, obj_slice_pitch }}); + auto host_origin = vector(p_host_origin); + auto host_pitch = pitch(region, {{ 1, host_row_pitch, host_slice_pitch }}); + + validate_common(q, deps); + validate_object(q, mem, obj_origin, obj_pitch, region); + validate_object(q, ptr, host_origin, host_pitch, region); + validate_object_access(mem, CL_MEM_HOST_WRITE_ONLY); + + auto hev = create( + q, CL_COMMAND_WRITE_BUFFER_RECT, deps, + soft_copy_op(q, &mem, obj_origin, obj_pitch, + ptr, host_origin, host_pitch, + region)); + + if (blocking) + hev().wait_signalled(); + + ret_object(rd_ev, hev); + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clEnqueueCopyBuffer(cl_command_queue d_q, cl_mem d_src_mem, cl_mem d_dst_mem, + size_t src_offset, size_t dst_offset, size_t size, + cl_uint num_deps, const cl_event *d_deps, + cl_event *rd_ev) try { + auto &q = obj(d_q); + auto &src_mem = obj(d_src_mem); + auto &dst_mem = obj(d_dst_mem); + auto deps = objs(d_deps, num_deps); + vector_t region = { size, 1, 1 }; + vector_t dst_origin = { dst_offset }; + auto dst_pitch = pitch(region, {{ 1 }}); + vector_t src_origin = { src_offset }; + auto src_pitch = pitch(region, {{ 1 }}); + + validate_common(q, deps); + validate_object(q, dst_mem, dst_origin, dst_pitch, region); + validate_object(q, src_mem, src_origin, src_pitch, region); + validate_copy(q, dst_mem, dst_origin, dst_pitch, + src_mem, src_origin, src_pitch, region); + + auto hev = create( + q, CL_COMMAND_COPY_BUFFER, deps, + hard_copy_op(q, &dst_mem, dst_origin, + &src_mem, src_origin, region)); + + ret_object(rd_ev, hev); + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clEnqueueCopyBufferRect(cl_command_queue d_q, cl_mem d_src_mem, + cl_mem d_dst_mem, + const size_t *p_src_origin, const size_t *p_dst_origin, + const size_t *p_region, + size_t src_row_pitch, size_t src_slice_pitch, + size_t dst_row_pitch, size_t dst_slice_pitch, + cl_uint num_deps, const cl_event *d_deps, + cl_event *rd_ev) try { + auto &q = obj(d_q); + auto &src_mem = obj(d_src_mem); + auto &dst_mem = obj(d_dst_mem); + auto deps = objs(d_deps, num_deps); + auto region = vector(p_region); + auto dst_origin = vector(p_dst_origin); + auto dst_pitch = pitch(region, {{ 1, dst_row_pitch, dst_slice_pitch }}); + auto src_origin = vector(p_src_origin); + auto src_pitch = pitch(region, {{ 1, src_row_pitch, src_slice_pitch }}); + + validate_common(q, deps); + validate_object(q, dst_mem, dst_origin, dst_pitch, region); + validate_object(q, src_mem, src_origin, src_pitch, region); + validate_copy(q, dst_mem, dst_origin, dst_pitch, + src_mem, src_origin, src_pitch, region); + + auto hev = create( + q, CL_COMMAND_COPY_BUFFER_RECT, deps, + soft_copy_op(q, &dst_mem, dst_origin, dst_pitch, + &src_mem, src_origin, src_pitch, + region)); + + ret_object(rd_ev, hev); + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clEnqueueReadImage(cl_command_queue d_q, cl_mem d_mem, cl_bool blocking, + const size_t *p_origin, const size_t *p_region, + size_t row_pitch, size_t slice_pitch, void *ptr, + cl_uint num_deps, const cl_event *d_deps, + cl_event *rd_ev) try { + auto &q = obj(d_q); + auto &img = obj(d_mem); + auto deps = objs(d_deps, num_deps); + auto region = vector(p_region); + auto dst_pitch = pitch(region, {{ img.pixel_size(), + row_pitch, slice_pitch }}); + auto src_origin = vector(p_origin); + auto src_pitch = pitch(region, {{ img.pixel_size(), + img.row_pitch(), img.slice_pitch() }}); + + validate_common(q, deps); + validate_object(q, ptr, {}, dst_pitch, region); + validate_object(q, img, src_origin, region); + validate_object_access(img, CL_MEM_HOST_READ_ONLY); + + auto hev = create( + q, CL_COMMAND_READ_IMAGE, deps, + soft_copy_op(q, ptr, {}, dst_pitch, + &img, src_origin, src_pitch, + region)); + + if (blocking) + hev().wait_signalled(); + + ret_object(rd_ev, hev); + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clEnqueueWriteImage(cl_command_queue d_q, cl_mem d_mem, cl_bool blocking, + const size_t *p_origin, const size_t *p_region, + size_t row_pitch, size_t slice_pitch, const void *ptr, + cl_uint num_deps, const cl_event *d_deps, + cl_event *rd_ev) try { + auto &q = obj(d_q); + auto &img = obj(d_mem); + auto deps = objs(d_deps, num_deps); + auto region = vector(p_region); + auto dst_origin = vector(p_origin); + auto dst_pitch = pitch(region, {{ img.pixel_size(), + img.row_pitch(), img.slice_pitch() }}); + auto src_pitch = pitch(region, {{ img.pixel_size(), + row_pitch, slice_pitch }}); + + validate_common(q, deps); + validate_object(q, img, dst_origin, region); + validate_object(q, ptr, {}, src_pitch, region); + validate_object_access(img, CL_MEM_HOST_WRITE_ONLY); + + auto hev = create( + q, CL_COMMAND_WRITE_IMAGE, deps, + soft_copy_op(q, &img, dst_origin, dst_pitch, + ptr, {}, src_pitch, + region)); + + if (blocking) + hev().wait_signalled(); + + ret_object(rd_ev, hev); + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clEnqueueCopyImage(cl_command_queue d_q, cl_mem d_src_mem, cl_mem d_dst_mem, + const size_t *p_src_origin, const size_t *p_dst_origin, + const size_t *p_region, + cl_uint num_deps, const cl_event *d_deps, + cl_event *rd_ev) try { + auto &q = obj(d_q); + auto &src_img = obj(d_src_mem); + auto &dst_img = obj(d_dst_mem); + auto deps = objs(d_deps, num_deps); + auto region = vector(p_region); + auto dst_origin = vector(p_dst_origin); + auto src_origin = vector(p_src_origin); + + validate_common(q, deps); + validate_object(q, dst_img, dst_origin, region); + validate_object(q, src_img, src_origin, region); + validate_copy(q, dst_img, dst_origin, src_img, src_origin, region); + + auto hev = create( + q, CL_COMMAND_COPY_IMAGE, deps, + hard_copy_op(q, &dst_img, dst_origin, + &src_img, src_origin, + region)); + + ret_object(rd_ev, hev); + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clEnqueueCopyImageToBuffer(cl_command_queue d_q, + cl_mem d_src_mem, cl_mem d_dst_mem, + const size_t *p_src_origin, const size_t *p_region, + size_t dst_offset, + cl_uint num_deps, const cl_event *d_deps, + cl_event *rd_ev) try { + auto &q = obj(d_q); + auto &src_img = obj(d_src_mem); + auto &dst_mem = obj(d_dst_mem); + auto deps = objs(d_deps, num_deps); + auto region = vector(p_region); + vector_t dst_origin = { dst_offset }; + auto dst_pitch = pitch(region, {{ src_img.pixel_size() }}); + auto src_origin = vector(p_src_origin); + auto src_pitch = pitch(region, {{ src_img.pixel_size(), + src_img.row_pitch(), + src_img.slice_pitch() }}); + + validate_common(q, deps); + validate_object(q, dst_mem, dst_origin, dst_pitch, region); + validate_object(q, src_img, src_origin, region); + + auto hev = create( + q, CL_COMMAND_COPY_IMAGE_TO_BUFFER, deps, + soft_copy_op(q, &dst_mem, dst_origin, dst_pitch, + &src_img, src_origin, src_pitch, + region)); + + ret_object(rd_ev, hev); + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clEnqueueCopyBufferToImage(cl_command_queue d_q, + cl_mem d_src_mem, cl_mem d_dst_mem, + size_t src_offset, + const size_t *p_dst_origin, const size_t *p_region, + cl_uint num_deps, const cl_event *d_deps, + cl_event *rd_ev) try { + auto &q = obj(d_q); + auto &src_mem = obj(d_src_mem); + auto &dst_img = obj(d_dst_mem); + auto deps = objs(d_deps, num_deps); + auto region = vector(p_region); + auto dst_origin = vector(p_dst_origin); + auto dst_pitch = pitch(region, {{ dst_img.pixel_size(), + dst_img.row_pitch(), + dst_img.slice_pitch() }}); + vector_t src_origin = { src_offset }; + auto src_pitch = pitch(region, {{ dst_img.pixel_size() }}); + + validate_common(q, deps); + validate_object(q, dst_img, dst_origin, region); + validate_object(q, src_mem, src_origin, src_pitch, region); + + auto hev = create( + q, CL_COMMAND_COPY_BUFFER_TO_IMAGE, deps, + soft_copy_op(q, &dst_img, dst_origin, dst_pitch, + &src_mem, src_origin, src_pitch, + region)); + + ret_object(rd_ev, hev); + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API void * +clEnqueueMapBuffer(cl_command_queue d_q, cl_mem d_mem, cl_bool blocking, + cl_map_flags flags, size_t offset, size_t size, + cl_uint num_deps, const cl_event *d_deps, + cl_event *rd_ev, cl_int *r_errcode) try { + auto &q = obj(d_q); + auto &mem = obj(d_mem); + auto deps = objs(d_deps, num_deps); + vector_t region = { size, 1, 1 }; + vector_t obj_origin = { offset }; + auto obj_pitch = pitch(region, {{ 1 }}); + + validate_common(q, deps); + validate_object(q, mem, obj_origin, obj_pitch, region); + validate_map_flags(mem, flags); + + void *map = mem.resource(q).add_map(q, flags, blocking, obj_origin, region); + + auto hev = create(q, CL_COMMAND_MAP_BUFFER, deps); + if (blocking) + hev().wait_signalled(); + + ret_object(rd_ev, hev); + ret_error(r_errcode, CL_SUCCESS); + return map; + +} catch (error &e) { + ret_error(r_errcode, e); + return NULL; +} + +CLOVER_API void * +clEnqueueMapImage(cl_command_queue d_q, cl_mem d_mem, cl_bool blocking, + cl_map_flags flags, + const size_t *p_origin, const size_t *p_region, + size_t *row_pitch, size_t *slice_pitch, + cl_uint num_deps, const cl_event *d_deps, + cl_event *rd_ev, cl_int *r_errcode) try { + auto &q = obj(d_q); + auto &img = obj(d_mem); + auto deps = objs(d_deps, num_deps); + auto region = vector(p_region); + auto origin = vector(p_origin); + + validate_common(q, deps); + validate_object(q, img, origin, region); + validate_map_flags(img, flags); + + void *map = img.resource(q).add_map(q, flags, blocking, origin, region); + + auto hev = create(q, CL_COMMAND_MAP_IMAGE, deps); + if (blocking) + hev().wait_signalled(); + + ret_object(rd_ev, hev); + ret_error(r_errcode, CL_SUCCESS); + return map; + +} catch (error &e) { + ret_error(r_errcode, e); + return NULL; +} + +CLOVER_API cl_int +clEnqueueUnmapMemObject(cl_command_queue d_q, cl_mem d_mem, void *ptr, + cl_uint num_deps, const cl_event *d_deps, + cl_event *rd_ev) try { + auto &q = obj(d_q); + auto &mem = obj(d_mem); + auto deps = objs(d_deps, num_deps); + + validate_common(q, deps); + + auto hev = create( + q, CL_COMMAND_UNMAP_MEM_OBJECT, deps, + [=, &q, &mem](event &) { + mem.resource(q).del_map(ptr); + }); + + ret_object(rd_ev, hev); + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clEnqueueMigrateMemObjects(cl_command_queue command_queue, + cl_uint num_mem_objects, + const cl_mem *mem_objects, + cl_mem_migration_flags flags, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event) { + CLOVER_NOT_SUPPORTED_UNTIL("1.2"); + return CL_INVALID_VALUE; +} + +cl_int +clover::EnqueueSVMFree(cl_command_queue d_q, + cl_uint num_svm_pointers, + void *svm_pointers[], + void (CL_CALLBACK *pfn_free_func) ( + cl_command_queue queue, cl_uint num_svm_pointers, + void *svm_pointers[], void *user_data), + void *user_data, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event, + cl_int cmd) try { + + if (bool(num_svm_pointers) != bool(svm_pointers)) + return CL_INVALID_VALUE; + + auto &q = obj(d_q); + bool can_emulate = q.device().has_system_svm(); + auto deps = objs(event_wait_list, num_events_in_wait_list); + + validate_common(q, deps); + + std::vector svm_pointers_cpy(svm_pointers, + svm_pointers + num_svm_pointers); + if (!pfn_free_func) { + if (!can_emulate) { + CLOVER_NOT_SUPPORTED_UNTIL("2.0"); + return CL_INVALID_VALUE; + } + pfn_free_func = [](cl_command_queue, cl_uint num_svm_pointers, + void *svm_pointers[], void *) { + for (void *p : range(svm_pointers, num_svm_pointers)) + free(p); + }; + } + + auto hev = create(q, cmd, deps, + [=](clover::event &) mutable { + pfn_free_func(d_q, num_svm_pointers, svm_pointers_cpy.data(), + user_data); + }); + + ret_object(event, hev); + return CL_SUCCESS; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clEnqueueSVMFree(cl_command_queue d_q, + cl_uint num_svm_pointers, + void *svm_pointers[], + void (CL_CALLBACK *pfn_free_func) ( + cl_command_queue queue, cl_uint num_svm_pointers, + void *svm_pointers[], void *user_data), + void *user_data, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event) { + + return EnqueueSVMFree(d_q, num_svm_pointers, svm_pointers, + pfn_free_func, user_data, num_events_in_wait_list, + event_wait_list, event, CL_COMMAND_SVM_FREE); +} + +cl_int +clover::EnqueueSVMMemcpy(cl_command_queue d_q, + cl_bool blocking_copy, + void *dst_ptr, + const void *src_ptr, + size_t size, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event, + cl_int cmd) try { + + if (dst_ptr == nullptr || src_ptr == nullptr) + return CL_INVALID_VALUE; + + if (static_cast(abs(reinterpret_cast(dst_ptr) - + reinterpret_cast(src_ptr))) < size) + return CL_MEM_COPY_OVERLAP; + + auto &q = obj(d_q); + bool can_emulate = q.device().has_system_svm(); + auto deps = objs(event_wait_list, num_events_in_wait_list); + + validate_common(q, deps); + + if (can_emulate) { + auto hev = create(q, cmd, deps, + [=](clover::event &) { + memcpy(dst_ptr, src_ptr, size); + }); + + if (blocking_copy) + hev().wait(); + ret_object(event, hev); + return CL_SUCCESS; + } + + CLOVER_NOT_SUPPORTED_UNTIL("2.0"); + return CL_INVALID_VALUE; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clEnqueueSVMMemcpy(cl_command_queue d_q, + cl_bool blocking_copy, + void *dst_ptr, + const void *src_ptr, + size_t size, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event) { + + return EnqueueSVMMemcpy(d_q, blocking_copy, dst_ptr, src_ptr, + size, num_events_in_wait_list, event_wait_list, + event, CL_COMMAND_SVM_MEMCPY); +} + +cl_int +clover::EnqueueSVMMemFill(cl_command_queue d_q, + void *svm_ptr, + const void *pattern, + size_t pattern_size, + size_t size, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event, + cl_int cmd) try { + + if (svm_ptr == nullptr || pattern == nullptr || + !util_is_power_of_two_nonzero(pattern_size) || + pattern_size > 128 || + !ptr_is_aligned(svm_ptr, pattern_size) || + size % pattern_size) + return CL_INVALID_VALUE; + + auto &q = obj(d_q); + bool can_emulate = q.device().has_system_svm(); + auto deps = objs(event_wait_list, num_events_in_wait_list); + + validate_common(q, deps); + + if (can_emulate) { + auto hev = create(q, cmd, deps, + [=](clover::event &) { + void *ptr = svm_ptr; + for (size_t s = size; s; s -= pattern_size) { + memcpy(ptr, pattern, pattern_size); + ptr = static_cast(ptr) + pattern_size; + } + }); + + ret_object(event, hev); + return CL_SUCCESS; + } + + CLOVER_NOT_SUPPORTED_UNTIL("2.0"); + return CL_INVALID_VALUE; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clEnqueueSVMMemFill(cl_command_queue d_q, + void *svm_ptr, + const void *pattern, + size_t pattern_size, + size_t size, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event) { + + return EnqueueSVMMemFill(d_q, svm_ptr, pattern, pattern_size, + size, num_events_in_wait_list, event_wait_list, + event, CL_COMMAND_SVM_MEMFILL); +} + +cl_int +clover::EnqueueSVMMap(cl_command_queue d_q, + cl_bool blocking_map, + cl_map_flags map_flags, + void *svm_ptr, + size_t size, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event, + cl_int cmd) try { + + if (svm_ptr == nullptr || size == 0) + return CL_INVALID_VALUE; + + auto &q = obj(d_q); + bool can_emulate = q.device().has_system_svm(); + auto deps = objs(event_wait_list, num_events_in_wait_list); + + validate_common(q, deps); + + if (can_emulate) { + auto hev = create(q, cmd, deps, + [](clover::event &) { }); + + ret_object(event, hev); + return CL_SUCCESS; + } + + CLOVER_NOT_SUPPORTED_UNTIL("2.0"); + return CL_INVALID_VALUE; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clEnqueueSVMMap(cl_command_queue d_q, + cl_bool blocking_map, + cl_map_flags map_flags, + void *svm_ptr, + size_t size, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event) { + + return EnqueueSVMMap(d_q, blocking_map, map_flags, svm_ptr, size, + num_events_in_wait_list, event_wait_list, event, + CL_COMMAND_SVM_MAP); +} + +cl_int +clover::EnqueueSVMUnmap(cl_command_queue d_q, + void *svm_ptr, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event, + cl_int cmd) try { + + if (svm_ptr == nullptr) + return CL_INVALID_VALUE; + + auto &q = obj(d_q); + bool can_emulate = q.device().has_system_svm(); + auto deps = objs(event_wait_list, num_events_in_wait_list); + + validate_common(q, deps); + + if (can_emulate) { + auto hev = create(q, cmd, deps, + [](clover::event &) { }); + + ret_object(event, hev); + return CL_SUCCESS; + } + + CLOVER_NOT_SUPPORTED_UNTIL("2.0"); + return CL_INVALID_VALUE; + +} catch (error &e) { + return e.get(); +} + +CLOVER_API cl_int +clEnqueueSVMUnmap(cl_command_queue d_q, + void *svm_ptr, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event) { + + return EnqueueSVMUnmap(d_q, svm_ptr, num_events_in_wait_list, + event_wait_list, event, CL_COMMAND_SVM_UNMAP); +} + +CLOVER_API cl_int +clEnqueueSVMMigrateMem(cl_command_queue d_q, + cl_uint num_svm_pointers, + const void **svm_pointers, + const size_t *sizes, + const cl_mem_migration_flags flags, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event) { + CLOVER_NOT_SUPPORTED_UNTIL("2.1"); + return CL_INVALID_VALUE; +} diff --git a/src/gallium/frontends/clover/api/util.hpp b/src/gallium/frontends/clover/api/util.hpp new file mode 100644 index 00000000000..66bd12597c6 --- /dev/null +++ b/src/gallium/frontends/clover/api/util.hpp @@ -0,0 +1,84 @@ +// +// Copyright 2012 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#ifndef CLOVER_API_UTIL_HPP +#define CLOVER_API_UTIL_HPP + +#include +#include + +#include "core/error.hpp" +#include "core/property.hpp" +#include "util/algorithm.hpp" + +#ifdef HAVE_CLOVER_ICD +#define CLOVER_API +#define CLOVER_ICD_API PUBLIC +#else +#define CLOVER_API PUBLIC +#define CLOVER_ICD_API PUBLIC +#endif + +#define CLOVER_NOT_SUPPORTED_UNTIL(version) \ + do { \ + std::cerr << "CL user error: " << __func__ \ + << "() requires OpenCL version " << (version) \ + << " or greater." << std::endl; \ + } while (0) + +namespace clover { + /// + /// Return an error code in \a p if non-zero. + /// + inline void + ret_error(cl_int *p, const clover::error &e) { + if (p) + *p = e.get(); + } + + /// + /// Return a clover object in \a p if non-zero incrementing the + /// reference count of the object. + /// + template + void + ret_object(typename T::descriptor_type **p, + const intrusive_ref &v) { + if (p) { + v().retain(); + *p = desc(v()); + } + } + + /// + /// Return an API object from an intrusive reference to a Clover object, + /// incrementing the reference count of the object. + /// + template + typename T::descriptor_type * + ret_object(const intrusive_ref &v) { + v().retain(); + return desc(v()); + } +} + +#endif diff --git a/src/gallium/frontends/clover/core/compiler.hpp b/src/gallium/frontends/clover/core/compiler.hpp new file mode 100644 index 00000000000..6ef30df9b7f --- /dev/null +++ b/src/gallium/frontends/clover/core/compiler.hpp @@ -0,0 +1,68 @@ +// +// Copyright 2019 Red Hat, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#ifndef CLOVER_CORE_COMPILER_HPP +#define CLOVER_CORE_COMPILER_HPP + +#include "core/device.hpp" +#include "core/module.hpp" +#include "llvm/invocation.hpp" +#include "nir/invocation.hpp" +#include "spirv/invocation.hpp" + +namespace clover { + namespace compiler { + static inline module + compile_program(const std::string &source, const header_map &headers, + const device &dev, const std::string &opts, + std::string &log) { + switch (dev.ir_format()) { +#ifdef HAVE_CLOVER_SPIRV + case PIPE_SHADER_IR_NIR_SERIALIZED: + return llvm::compile_to_spirv(source, headers, dev, opts, log); +#endif + case PIPE_SHADER_IR_NATIVE: + return llvm::compile_program(source, headers, dev, opts, log); + default: + unreachable("device with unsupported IR"); + throw error(CL_INVALID_VALUE); + } + } + + static inline module + link_program(const std::vector &ms, const device &dev, + const std::string &opts, std::string &log) { + switch (dev.ir_format()) { + case PIPE_SHADER_IR_NIR_SERIALIZED: + return nir::spirv_to_nir(spirv::link_program(ms, dev, opts, log), + dev, log); + case PIPE_SHADER_IR_NATIVE: + return llvm::link_program(ms, dev, opts, log); + default: + unreachable("device with unsupported IR"); + throw error(CL_INVALID_VALUE); + } + } + } +} + +#endif diff --git a/src/gallium/frontends/clover/core/context.cpp b/src/gallium/frontends/clover/core/context.cpp new file mode 100644 index 00000000000..c3e20829384 --- /dev/null +++ b/src/gallium/frontends/clover/core/context.cpp @@ -0,0 +1,51 @@ +// +// Copyright 2012 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#include "core/context.hpp" + +using namespace clover; + +context::context(const property_list &props, + const ref_vector &devs, + const notify_action ¬ify) : + notify(notify), props(props), devs(devs) { +} + +bool +context::operator==(const context &ctx) const { + return this == &ctx; +} + +bool +context::operator!=(const context &ctx) const { + return this != &ctx; +} + +const context::property_list & +context::properties() const { + return props; +} + +context::device_range +context::devices() const { + return map(evals(), devs); +} diff --git a/src/gallium/frontends/clover/core/context.hpp b/src/gallium/frontends/clover/core/context.hpp new file mode 100644 index 00000000000..7b22ccae78f --- /dev/null +++ b/src/gallium/frontends/clover/core/context.hpp @@ -0,0 +1,67 @@ +// +// Copyright 2012 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#ifndef CLOVER_CORE_CONTEXT_HPP +#define CLOVER_CORE_CONTEXT_HPP + +#include "core/object.hpp" +#include "core/device.hpp" +#include "core/property.hpp" + +namespace clover { + class context : public ref_counter, public _cl_context { + private: + typedef adaptor_range< + evals, const std::vector> & + > device_range; + typedef clover::property_list property_list; + + public: + typedef std::function notify_action; + + context(const property_list &props, const ref_vector &devs, + const notify_action ¬ify); + + context(const context &ctx) = delete; + context & + operator=(const context &ctx) = delete; + + bool + operator==(const context &ctx) const; + bool + operator!=(const context &ctx) const; + + const property_list & + properties() const; + + device_range + devices() const; + + const notify_action notify; + + private: + property_list props; + const std::vector> devs; + }; +} + +#endif diff --git a/src/gallium/frontends/clover/core/device.cpp b/src/gallium/frontends/clover/core/device.cpp new file mode 100644 index 00000000000..609885c21bc --- /dev/null +++ b/src/gallium/frontends/clover/core/device.cpp @@ -0,0 +1,337 @@ +// +// Copyright 2012 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#include +#include "core/device.hpp" +#include "core/platform.hpp" +#include "pipe/p_screen.h" +#include "pipe/p_state.h" +#include "util/bitscan.h" +#include "util/u_debug.h" + +using namespace clover; + +namespace { + template + std::vector + get_compute_param(pipe_screen *pipe, pipe_shader_ir ir_format, + pipe_compute_cap cap) { + int sz = pipe->get_compute_param(pipe, ir_format, cap, NULL); + std::vector v(sz / sizeof(T)); + + pipe->get_compute_param(pipe, ir_format, cap, &v.front()); + return v; + } +} + +device::device(clover::platform &platform, pipe_loader_device *ldev) : + platform(platform), ldev(ldev) { + pipe = pipe_loader_create_screen(ldev); + if (pipe && pipe->get_param(pipe, PIPE_CAP_COMPUTE)) { + if (supports_ir(PIPE_SHADER_IR_NATIVE)) + return; +#ifdef HAVE_CLOVER_SPIRV + if (supports_ir(PIPE_SHADER_IR_NIR_SERIALIZED)) + return; +#endif + } + if (pipe) + pipe->destroy(pipe); + throw error(CL_INVALID_DEVICE); +} + +device::~device() { + if (pipe) + pipe->destroy(pipe); + if (ldev) + pipe_loader_release(&ldev, 1); +} + +bool +device::operator==(const device &dev) const { + return this == &dev; +} + +cl_device_type +device::type() const { + switch (ldev->type) { + case PIPE_LOADER_DEVICE_SOFTWARE: + return CL_DEVICE_TYPE_CPU; + case PIPE_LOADER_DEVICE_PCI: + case PIPE_LOADER_DEVICE_PLATFORM: + return CL_DEVICE_TYPE_GPU; + default: + unreachable("Unknown device type."); + } +} + +cl_uint +device::vendor_id() const { + switch (ldev->type) { + case PIPE_LOADER_DEVICE_SOFTWARE: + case PIPE_LOADER_DEVICE_PLATFORM: + return 0; + case PIPE_LOADER_DEVICE_PCI: + return ldev->u.pci.vendor_id; + default: + unreachable("Unknown device type."); + } +} + +size_t +device::max_images_read() const { + return PIPE_MAX_SHADER_IMAGES; +} + +size_t +device::max_images_write() const { + return PIPE_MAX_SHADER_IMAGES; +} + +size_t +device::max_image_buffer_size() const { + return pipe->get_param(pipe, PIPE_CAP_MAX_TEXTURE_BUFFER_SIZE); +} + +cl_uint +device::max_image_levels_2d() const { + return util_last_bit(pipe->get_param(pipe, PIPE_CAP_MAX_TEXTURE_2D_SIZE)); +} + +cl_uint +device::max_image_levels_3d() const { + return pipe->get_param(pipe, PIPE_CAP_MAX_TEXTURE_3D_LEVELS); +} + +size_t +device::max_image_array_number() const { + return pipe->get_param(pipe, PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS); +} + +cl_uint +device::max_samplers() const { + return pipe->get_shader_param(pipe, PIPE_SHADER_COMPUTE, + PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS); +} + +cl_ulong +device::max_mem_global() const { + return get_compute_param(pipe, ir_format(), + PIPE_COMPUTE_CAP_MAX_GLOBAL_SIZE)[0]; +} + +cl_ulong +device::max_mem_local() const { + return get_compute_param(pipe, ir_format(), + PIPE_COMPUTE_CAP_MAX_LOCAL_SIZE)[0]; +} + +cl_ulong +device::max_mem_input() const { + return get_compute_param(pipe, ir_format(), + PIPE_COMPUTE_CAP_MAX_INPUT_SIZE)[0]; +} + +cl_ulong +device::max_const_buffer_size() const { + return pipe->get_shader_param(pipe, PIPE_SHADER_COMPUTE, + PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE); +} + +cl_uint +device::max_const_buffers() const { + return pipe->get_shader_param(pipe, PIPE_SHADER_COMPUTE, + PIPE_SHADER_CAP_MAX_CONST_BUFFERS); +} + +size_t +device::max_threads_per_block() const { + return get_compute_param( + pipe, ir_format(), PIPE_COMPUTE_CAP_MAX_THREADS_PER_BLOCK)[0]; +} + +cl_ulong +device::max_mem_alloc_size() const { + return get_compute_param(pipe, ir_format(), + PIPE_COMPUTE_CAP_MAX_MEM_ALLOC_SIZE)[0]; +} + +cl_uint +device::max_clock_frequency() const { + return get_compute_param(pipe, ir_format(), + PIPE_COMPUTE_CAP_MAX_CLOCK_FREQUENCY)[0]; +} + +cl_uint +device::max_compute_units() const { + return get_compute_param(pipe, ir_format(), + PIPE_COMPUTE_CAP_MAX_COMPUTE_UNITS)[0]; +} + +bool +device::image_support() const { + return get_compute_param(pipe, ir_format(), + PIPE_COMPUTE_CAP_IMAGES_SUPPORTED)[0]; +} + +bool +device::has_doubles() const { + return pipe->get_param(pipe, PIPE_CAP_DOUBLES); +} + +bool +device::has_halves() const { + return pipe->get_shader_param(pipe, PIPE_SHADER_COMPUTE, + PIPE_SHADER_CAP_FP16); +} + +bool +device::has_int64_atomics() const { + return pipe->get_shader_param(pipe, PIPE_SHADER_COMPUTE, + PIPE_SHADER_CAP_INT64_ATOMICS); +} + +bool +device::has_unified_memory() const { + return pipe->get_param(pipe, PIPE_CAP_UMA); +} + +cl_uint +device::mem_base_addr_align() const { + return sysconf(_SC_PAGESIZE); +} + +cl_device_svm_capabilities +device::svm_support() const { + // Without CAP_RESOURCE_FROM_USER_MEMORY SVM and CL_MEM_USE_HOST_PTR + // interactions won't work according to spec as clover manages a GPU side + // copy of the host data. + // + // The biggest problem are memory buffers created with CL_MEM_USE_HOST_PTR, + // but the application and/or the kernel updates the memory via SVM and not + // the cl_mem buffer. + // We can't even do proper tracking on what memory might have been accessed + // as the host ptr to the buffer could be within a SVM region, where through + // the CL API there is no reliable way of knowing if a certain cl_mem buffer + // was accessed by a kernel or not and the runtime can't reliably know from + // which side the GPU buffer content needs to be updated. + // + // Another unsolvable scenario is a cl_mem object passed by cl_mem reference + // and SVM pointer into the same kernel at the same time. + if (pipe->get_param(pipe, PIPE_CAP_RESOURCE_FROM_USER_MEMORY) && + pipe->get_param(pipe, PIPE_CAP_SYSTEM_SVM)) + // we can emulate all lower levels if we support fine grain system + return CL_DEVICE_SVM_FINE_GRAIN_SYSTEM | + CL_DEVICE_SVM_COARSE_GRAIN_BUFFER | + CL_DEVICE_SVM_FINE_GRAIN_BUFFER; + return 0; +} + +std::vector +device::max_block_size() const { + auto v = get_compute_param(pipe, ir_format(), + PIPE_COMPUTE_CAP_MAX_BLOCK_SIZE); + return { v.begin(), v.end() }; +} + +cl_uint +device::subgroup_size() const { + return get_compute_param(pipe, ir_format(), + PIPE_COMPUTE_CAP_SUBGROUP_SIZE)[0]; +} + +cl_uint +device::address_bits() const { + return get_compute_param(pipe, ir_format(), + PIPE_COMPUTE_CAP_ADDRESS_BITS)[0]; +} + +std::string +device::device_name() const { + return pipe->get_name(pipe); +} + +std::string +device::vendor_name() const { + return pipe->get_device_vendor(pipe); +} + +enum pipe_shader_ir +device::ir_format() const { + if (supports_ir(PIPE_SHADER_IR_NATIVE)) + return PIPE_SHADER_IR_NATIVE; + + assert(supports_ir(PIPE_SHADER_IR_NIR_SERIALIZED)); + return PIPE_SHADER_IR_NIR_SERIALIZED; +} + +std::string +device::ir_target() const { + std::vector target = get_compute_param( + pipe, ir_format(), PIPE_COMPUTE_CAP_IR_TARGET); + return { target.data() }; +} + +enum pipe_endian +device::endianness() const { + return (enum pipe_endian)pipe->get_param(pipe, PIPE_CAP_ENDIANNESS); +} + +std::string +device::device_version() const { + static const std::string device_version = + debug_get_option("CLOVER_DEVICE_VERSION_OVERRIDE", "1.1"); + return device_version; +} + +std::string +device::device_clc_version() const { + static const std::string device_clc_version = + debug_get_option("CLOVER_DEVICE_CLC_VERSION_OVERRIDE", "1.1"); + return device_clc_version; +} + +bool +device::supports_ir(enum pipe_shader_ir ir) const { + return pipe->get_shader_param(pipe, PIPE_SHADER_COMPUTE, + PIPE_SHADER_CAP_SUPPORTED_IRS) & (1 << ir); +} + +std::string +device::supported_extensions() const { + return + "cl_khr_byte_addressable_store" + " cl_khr_global_int32_base_atomics" + " cl_khr_global_int32_extended_atomics" + " cl_khr_local_int32_base_atomics" + " cl_khr_local_int32_extended_atomics" + + std::string(has_int64_atomics() ? " cl_khr_int64_base_atomics" : "") + + std::string(has_int64_atomics() ? " cl_khr_int64_extended_atomics" : "") + + std::string(has_doubles() ? " cl_khr_fp64" : "") + + std::string(has_halves() ? " cl_khr_fp16" : "") + + std::string(svm_support() ? " cl_arm_shared_virtual_memory" : ""); +} + +const void * +device::get_compiler_options(enum pipe_shader_ir ir) const { + return pipe->get_compiler_options(pipe, ir, PIPE_SHADER_COMPUTE); +} diff --git a/src/gallium/frontends/clover/core/device.hpp b/src/gallium/frontends/clover/core/device.hpp new file mode 100644 index 00000000000..597f9489b2c --- /dev/null +++ b/src/gallium/frontends/clover/core/device.hpp @@ -0,0 +1,109 @@ +// +// Copyright 2012 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#ifndef CLOVER_CORE_DEVICE_HPP +#define CLOVER_CORE_DEVICE_HPP + +#include +#include + +#include "core/object.hpp" +#include "core/format.hpp" +#include "pipe-loader/pipe_loader.h" + +namespace clover { + class platform; + class root_resource; + class hard_event; + + class device : public ref_counter, public _cl_device_id { + public: + device(clover::platform &platform, pipe_loader_device *ldev); + ~device(); + + device(const device &dev) = delete; + device & + operator=(const device &dev) = delete; + + bool + operator==(const device &dev) const; + + cl_device_type type() const; + cl_uint vendor_id() const; + size_t max_images_read() const; + size_t max_images_write() const; + size_t max_image_buffer_size() const; + cl_uint max_image_levels_2d() const; + cl_uint max_image_levels_3d() const; + size_t max_image_array_number() const; + cl_uint max_samplers() const; + cl_ulong max_mem_global() const; + cl_ulong max_mem_local() const; + cl_ulong max_mem_input() const; + cl_ulong max_const_buffer_size() const; + cl_uint max_const_buffers() const; + size_t max_threads_per_block() const; + cl_ulong max_mem_alloc_size() const; + cl_uint max_clock_frequency() const; + cl_uint max_compute_units() const; + bool image_support() const; + bool has_doubles() const; + bool has_halves() const; + bool has_int64_atomics() const; + bool has_unified_memory() const; + cl_uint mem_base_addr_align() const; + cl_device_svm_capabilities svm_support() const; + + std::vector max_block_size() const; + cl_uint subgroup_size() const; + cl_uint address_bits() const; + std::string device_name() const; + std::string vendor_name() const; + std::string device_version() const; + std::string device_clc_version() const; + enum pipe_shader_ir ir_format() const; + std::string ir_target() const; + enum pipe_endian endianness() const; + bool supports_ir(enum pipe_shader_ir ir) const; + std::string supported_extensions() const; + + friend class command_queue; + friend class root_resource; + friend class hard_event; + friend std::set + supported_formats(const context &, cl_mem_object_type); + const void *get_compiler_options(enum pipe_shader_ir ir) const; + + clover::platform &platform; + + inline bool + has_system_svm() const { + return svm_support() & CL_DEVICE_SVM_FINE_GRAIN_SYSTEM; + } + + private: + pipe_screen *pipe; + pipe_loader_device *ldev; + }; +} + +#endif diff --git a/src/gallium/frontends/clover/core/error.hpp b/src/gallium/frontends/clover/core/error.hpp new file mode 100644 index 00000000000..0490c19a276 --- /dev/null +++ b/src/gallium/frontends/clover/core/error.hpp @@ -0,0 +1,202 @@ +// +// Copyright 2013 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#ifndef CLOVER_CORE_ERROR_HPP +#define CLOVER_CORE_ERROR_HPP + +#include "CL/cl.h" + +#include +#include + +namespace clover { + class command_queue; + class context; + class device; + class event; + class hard_event; + class soft_event; + class kernel; + class memory_obj; + class buffer; + class root_buffer; + class sub_buffer; + class image; + class image2d; + class image3d; + class platform; + class program; + class sampler; + + /// + /// Class that represents an error that can be converted to an + /// OpenCL status code. + /// + class error : public std::runtime_error { + public: + error(cl_int code, std::string what = "") : + std::runtime_error(what), code(code) { + } + + cl_int get() const { + return code; + } + + protected: + cl_int code; + }; + + class invalid_build_options_error : public error { + public: + invalid_build_options_error(const std::string &what = "") : + error(CL_INVALID_BUILD_OPTIONS, what) {} + }; + + class build_error : public error { + public: + build_error(const std::string &what = "") : + error(CL_BUILD_PROGRAM_FAILURE, what) {} + }; + + template + class invalid_object_error; + + template<> + class invalid_object_error : public error { + public: + invalid_object_error(std::string what = "") : + error(CL_INVALID_COMMAND_QUEUE, what) {} + }; + + template<> + class invalid_object_error : public error { + public: + invalid_object_error(std::string what = "") : + error(CL_INVALID_CONTEXT, what) {} + }; + + template<> + class invalid_object_error : public error { + public: + invalid_object_error(std::string what = "") : + error(CL_INVALID_DEVICE, what) {} + }; + + template<> + class invalid_object_error : public error { + public: + invalid_object_error(std::string what = "") : + error(CL_INVALID_EVENT, what) {} + }; + + template<> + class invalid_object_error : public error { + public: + invalid_object_error(std::string what = "") : + error(CL_INVALID_EVENT, what) {} + }; + + template<> + class invalid_object_error : public error { + public: + invalid_object_error(std::string what = "") : + error(CL_INVALID_KERNEL, what) {} + }; + + template<> + class invalid_object_error : public error { + public: + invalid_object_error(std::string what = "") : + error(CL_INVALID_MEM_OBJECT, what) {} + }; + + template<> + class invalid_object_error : public error { + public: + invalid_object_error(std::string what = "") : + error(CL_INVALID_MEM_OBJECT, what) {} + }; + + template<> + class invalid_object_error : public error { + public: + invalid_object_error(std::string what = "") : + error(CL_INVALID_MEM_OBJECT, what) {} + }; + + template<> + class invalid_object_error : public error { + public: + invalid_object_error(std::string what = "") : + error(CL_INVALID_MEM_OBJECT, what) {} + }; + + template<> + class invalid_object_error : public error { + public: + invalid_object_error(std::string what = "") : + error(CL_INVALID_MEM_OBJECT, what) {} + }; + + template<> + class invalid_object_error : public error { + public: + invalid_object_error(std::string what = "") : + error(CL_INVALID_MEM_OBJECT, what) {} + }; + + template<> + class invalid_object_error : public error { + public: + invalid_object_error(std::string what = "") : + error(CL_INVALID_MEM_OBJECT, what) {} + }; + + template<> + class invalid_object_error : public error { + public: + invalid_object_error(std::string what = "") : + error(CL_INVALID_PLATFORM, what) {} + }; + + template<> + class invalid_object_error : public error { + public: + invalid_object_error(std::string what = "") : + error(CL_INVALID_PROGRAM, what) {} + }; + + template<> + class invalid_object_error : public error { + public: + invalid_object_error(std::string what = "") : + error(CL_INVALID_SAMPLER, what) {} + }; + + class invalid_wait_list_error : public error { + public: + invalid_wait_list_error(std::string what = "") : + error(CL_INVALID_EVENT_WAIT_LIST, what) {} + }; +} + +#endif diff --git a/src/gallium/frontends/clover/core/event.cpp b/src/gallium/frontends/clover/core/event.cpp new file mode 100644 index 00000000000..3d313ce8969 --- /dev/null +++ b/src/gallium/frontends/clover/core/event.cpp @@ -0,0 +1,267 @@ +// +// Copyright 2012 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#include "core/event.hpp" +#include "pipe/p_screen.h" + +using namespace clover; + +event::event(clover::context &ctx, const ref_vector &deps, + action action_ok, action action_fail) : + context(ctx), _wait_count(1), _status(0), + action_ok(action_ok), action_fail(action_fail) { + for (auto &ev : deps) + ev.chain(*this); +} + +event::~event() { +} + +std::vector> +event::trigger_self() { + std::lock_guard lock(mutex); + std::vector> evs; + + if (_wait_count && !--_wait_count) + std::swap(_chain, evs); + + cv.notify_all(); + return evs; +} + +void +event::trigger() try { + if (wait_count() == 1) + action_ok(*this); + + for (event &ev : trigger_self()) + ev.trigger(); +} catch (error &e) { + abort(e.get()); +} + +std::vector> +event::abort_self(cl_int status) { + std::lock_guard lock(mutex); + std::vector> evs; + + _status = status; + _wait_count = 0; + std::swap(_chain, evs); + + cv.notify_all(); + return evs; +} + +void +event::abort(cl_int status) { + action_fail(*this); + + for (event &ev : abort_self(status)) + ev.abort(status); +} + +unsigned +event::wait_count() const { + std::lock_guard lock(mutex); + return _wait_count; +} + +bool +event::signalled() const { + return !wait_count(); +} + +cl_int +event::status() const { + std::lock_guard lock(mutex); + return _status; +} + +void +event::chain(event &ev) { + std::unique_lock lock(mutex, std::defer_lock); + std::unique_lock lock_ev(ev.mutex, std::defer_lock); + std::lock(lock, lock_ev); + + if (_wait_count) { + ev._wait_count++; + _chain.push_back(ev); + } + ev.deps.push_back(*this); +} + +void +event::wait_signalled() const { + std::unique_lock lock(mutex); + cv.wait(lock, [=]{ return !_wait_count; }); +} + +void +event::wait() const { + for (event &ev : deps) + ev.wait(); + + wait_signalled(); +} + +hard_event::hard_event(command_queue &q, cl_command_type command, + const ref_vector &deps, action action) : + event(q.context(), deps, profile(q, action), [](event &ev){}), + _queue(q), _command(command), _fence(NULL) { + if (q.profiling_enabled()) + _time_queued = timestamp::current(q); + + q.sequence(*this); + trigger(); +} + +hard_event::~hard_event() { + pipe_screen *screen = queue()->device().pipe; + screen->fence_reference(screen, &_fence, NULL); +} + +cl_int +hard_event::status() const { + pipe_screen *screen = queue()->device().pipe; + + if (event::status() < 0) + return event::status(); + + else if (!_fence) + return CL_QUEUED; + + else if (!screen->fence_finish(screen, NULL, _fence, 0)) + return CL_SUBMITTED; + + else + return CL_COMPLETE; +} + +command_queue * +hard_event::queue() const { + return &_queue(); +} + +cl_command_type +hard_event::command() const { + return _command; +} + +void +hard_event::wait() const { + pipe_screen *screen = queue()->device().pipe; + + event::wait(); + + if (status() == CL_QUEUED) + queue()->flush(); + + if (!_fence || + !screen->fence_finish(screen, NULL, _fence, PIPE_TIMEOUT_INFINITE)) + throw error(CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST); +} + +const lazy & +hard_event::time_queued() const { + return _time_queued; +} + +const lazy & +hard_event::time_submit() const { + return _time_submit; +} + +const lazy & +hard_event::time_start() const { + return _time_start; +} + +const lazy & +hard_event::time_end() const { + return _time_end; +} + +void +hard_event::fence(pipe_fence_handle *fence) { + pipe_screen *screen = queue()->device().pipe; + screen->fence_reference(screen, &_fence, fence); +} + +event::action +hard_event::profile(command_queue &q, const action &action) const { + if (q.profiling_enabled()) { + return [&q, action] (event &ev) { + auto &hev = static_cast(ev); + + hev._time_submit = timestamp::current(q); + hev._time_start = timestamp::query(q); + + action(ev); + + hev._time_end = timestamp::query(q); + }; + + } else { + return action; + } +} + +soft_event::soft_event(clover::context &ctx, const ref_vector &deps, + bool _trigger, action action) : + event(ctx, deps, action, action) { + if (_trigger) + trigger(); +} + +cl_int +soft_event::status() const { + if (event::status() < 0) + return event::status(); + + else if (!signalled() || + any_of([](const event &ev) { + return ev.status() != CL_COMPLETE; + }, deps)) + return CL_SUBMITTED; + + else + return CL_COMPLETE; +} + +command_queue * +soft_event::queue() const { + return NULL; +} + +cl_command_type +soft_event::command() const { + return CL_COMMAND_USER; +} + +void +soft_event::wait() const { + event::wait(); + + if (status() != CL_COMPLETE) + throw error(CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST); +} diff --git a/src/gallium/frontends/clover/core/event.hpp b/src/gallium/frontends/clover/core/event.hpp new file mode 100644 index 00000000000..03c97bcf4da --- /dev/null +++ b/src/gallium/frontends/clover/core/event.hpp @@ -0,0 +1,164 @@ +// +// Copyright 2012 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#ifndef CLOVER_CORE_EVENT_HPP +#define CLOVER_CORE_EVENT_HPP + +#include +#include + +#include "core/object.hpp" +#include "core/queue.hpp" +#include "core/timestamp.hpp" +#include "util/lazy.hpp" + +namespace clover { + /// + /// Class that represents a task that might be executed + /// asynchronously at some point in the future. + /// + /// An event consists of a list of dependencies, a boolean + /// signalled() flag, and an associated task. An event is + /// considered signalled as soon as all its dependencies (if any) + /// are signalled as well, and the trigger() method is called; at + /// that point the associated task will be started through the + /// specified \a action_ok. If the abort() method is called + /// instead, the specified \a action_fail is executed and the + /// associated task will never be started. Dependent events will + /// be aborted recursively. + /// + /// The execution status of the associated task can be queried + /// using the status() method, and it can be waited for completion + /// using the wait() method. + /// + class event : public ref_counter, public _cl_event { + public: + typedef std::function action; + + event(clover::context &ctx, const ref_vector &deps, + action action_ok, action action_fail); + virtual ~event(); + + event(const event &ev) = delete; + event & + operator=(const event &ev) = delete; + + void trigger(); + void abort(cl_int status); + bool signalled() const; + + virtual cl_int status() const; + virtual command_queue *queue() const = 0; + virtual cl_command_type command() const = 0; + void wait_signalled() const; + virtual void wait() const; + + virtual struct pipe_fence_handle *fence() const { + return NULL; + } + + const intrusive_ref context; + + protected: + void chain(event &ev); + + std::vector> deps; + + private: + std::vector> trigger_self(); + std::vector> abort_self(cl_int status); + unsigned wait_count() const; + + unsigned _wait_count; + cl_int _status; + action action_ok; + action action_fail; + std::vector> _chain; + mutable std::condition_variable cv; + mutable std::mutex mutex; + }; + + /// + /// Class that represents a task executed by a command queue. + /// + /// Similar to a normal clover::event. In addition it's associated + /// with a given command queue \a q and a given OpenCL \a command. + /// hard_event instances created for the same queue are implicitly + /// ordered with respect to each other, and they are implicitly + /// triggered on construction. + /// + /// A hard_event is considered complete when the associated + /// hardware task finishes execution. + /// + class hard_event : public event { + public: + hard_event(command_queue &q, cl_command_type command, + const ref_vector &deps, + action action = [](event &){}); + ~hard_event(); + + virtual cl_int status() const; + virtual command_queue *queue() const; + virtual cl_command_type command() const; + virtual void wait() const; + + const lazy &time_queued() const; + const lazy &time_submit() const; + const lazy &time_start() const; + const lazy &time_end() const; + + friend class command_queue; + + virtual struct pipe_fence_handle *fence() const { + return _fence; + } + + private: + virtual void fence(pipe_fence_handle *fence); + action profile(command_queue &q, const action &action) const; + + const intrusive_ref _queue; + cl_command_type _command; + pipe_fence_handle *_fence; + lazy _time_queued, _time_submit, _time_start, _time_end; + }; + + /// + /// Class that represents a software event. + /// + /// A soft_event is not associated with any specific hardware task + /// or command queue. It's considered complete as soon as all its + /// dependencies finish execution. + /// + class soft_event : public event { + public: + soft_event(clover::context &ctx, const ref_vector &deps, + bool trigger, action action = [](event &){}); + + virtual cl_int status() const; + virtual command_queue *queue() const; + virtual cl_command_type command() const; + virtual void wait() const; + }; +} + +#endif diff --git a/src/gallium/frontends/clover/core/format.cpp b/src/gallium/frontends/clover/core/format.cpp new file mode 100644 index 00000000000..dee1872c829 --- /dev/null +++ b/src/gallium/frontends/clover/core/format.cpp @@ -0,0 +1,162 @@ +// +// Copyright 2012 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#include "core/format.hpp" +#include "core/memory.hpp" +#include "pipe/p_screen.h" +#include "pipe/p_context.h" + +namespace clover { + static const std::map formats { + { { CL_BGRA, CL_UNORM_INT8 }, PIPE_FORMAT_B8G8R8A8_UNORM }, + { { CL_ARGB, CL_UNORM_INT8 }, PIPE_FORMAT_A8R8G8B8_UNORM }, + { { CL_RGB, CL_UNORM_SHORT_565 }, PIPE_FORMAT_B5G6R5_UNORM }, + { { CL_LUMINANCE, CL_UNORM_INT8 }, PIPE_FORMAT_L8_UNORM }, + { { CL_A, CL_UNORM_INT8 }, PIPE_FORMAT_A8_UNORM }, + { { CL_INTENSITY, CL_UNORM_INT8 }, PIPE_FORMAT_I8_UNORM }, + { { CL_LUMINANCE, CL_UNORM_INT16 }, PIPE_FORMAT_L16_UNORM }, + { { CL_R, CL_FLOAT }, PIPE_FORMAT_R32_FLOAT }, + { { CL_RG, CL_FLOAT }, PIPE_FORMAT_R32G32_FLOAT }, + { { CL_RGB, CL_FLOAT }, PIPE_FORMAT_R32G32B32_FLOAT }, + { { CL_RGBA, CL_FLOAT }, PIPE_FORMAT_R32G32B32A32_FLOAT }, + { { CL_R, CL_UNORM_INT16 }, PIPE_FORMAT_R16_UNORM }, + { { CL_RG, CL_UNORM_INT16 }, PIPE_FORMAT_R16G16_UNORM }, + { { CL_RGB, CL_UNORM_INT16 }, PIPE_FORMAT_R16G16B16_UNORM }, + { { CL_RGBA, CL_UNORM_INT16 }, PIPE_FORMAT_R16G16B16A16_UNORM }, + { { CL_R, CL_SNORM_INT16 }, PIPE_FORMAT_R16_SNORM }, + { { CL_RG, CL_SNORM_INT16 }, PIPE_FORMAT_R16G16_SNORM }, + { { CL_RGB, CL_SNORM_INT16 }, PIPE_FORMAT_R16G16B16_SNORM }, + { { CL_RGBA, CL_SNORM_INT16 }, PIPE_FORMAT_R16G16B16A16_SNORM }, + { { CL_R, CL_UNORM_INT8 }, PIPE_FORMAT_R8_UNORM }, + { { CL_RG, CL_UNORM_INT8 }, PIPE_FORMAT_R8G8_UNORM }, + { { CL_RGB, CL_UNORM_INT8 }, PIPE_FORMAT_R8G8B8_UNORM }, + { { CL_RGBA, CL_UNORM_INT8 }, PIPE_FORMAT_R8G8B8A8_UNORM }, + { { CL_R, CL_SNORM_INT8 }, PIPE_FORMAT_R8_SNORM }, + { { CL_RG, CL_SNORM_INT8 }, PIPE_FORMAT_R8G8_SNORM }, + { { CL_RGB, CL_SNORM_INT8 }, PIPE_FORMAT_R8G8B8_SNORM }, + { { CL_RGBA, CL_SNORM_INT8 }, PIPE_FORMAT_R8G8B8A8_SNORM }, + { { CL_R, CL_HALF_FLOAT }, PIPE_FORMAT_R16_FLOAT }, + { { CL_RG, CL_HALF_FLOAT }, PIPE_FORMAT_R16G16_FLOAT }, + { { CL_RGB, CL_HALF_FLOAT }, PIPE_FORMAT_R16G16B16_FLOAT }, + { { CL_RGBA, CL_HALF_FLOAT }, PIPE_FORMAT_R16G16B16A16_FLOAT }, + { { CL_RGBx, CL_UNORM_SHORT_555 }, PIPE_FORMAT_B5G5R5X1_UNORM }, + { { CL_RGBx, CL_UNORM_INT8 }, PIPE_FORMAT_R8G8B8X8_UNORM }, + { { CL_A, CL_UNORM_INT16 }, PIPE_FORMAT_A16_UNORM }, + { { CL_INTENSITY, CL_UNORM_INT16 }, PIPE_FORMAT_I16_UNORM }, + { { CL_LUMINANCE, CL_SNORM_INT8 }, PIPE_FORMAT_L8_SNORM }, + { { CL_INTENSITY, CL_SNORM_INT8 }, PIPE_FORMAT_I8_SNORM }, + { { CL_A, CL_SNORM_INT16 }, PIPE_FORMAT_A16_SNORM }, + { { CL_LUMINANCE, CL_SNORM_INT16 }, PIPE_FORMAT_L16_SNORM }, + { { CL_INTENSITY, CL_SNORM_INT16 }, PIPE_FORMAT_I16_SNORM }, + { { CL_A, CL_HALF_FLOAT }, PIPE_FORMAT_A16_FLOAT }, + { { CL_LUMINANCE, CL_HALF_FLOAT }, PIPE_FORMAT_L16_FLOAT }, + { { CL_INTENSITY, CL_HALF_FLOAT }, PIPE_FORMAT_I16_FLOAT }, + { { CL_A, CL_FLOAT }, PIPE_FORMAT_A32_FLOAT }, + { { CL_LUMINANCE, CL_FLOAT }, PIPE_FORMAT_L32_FLOAT }, + { { CL_INTENSITY, CL_FLOAT }, PIPE_FORMAT_I32_FLOAT }, + { { CL_RA, CL_UNORM_INT8 }, PIPE_FORMAT_R8A8_UNORM }, + { { CL_R, CL_UNSIGNED_INT8 }, PIPE_FORMAT_R8_UINT }, + { { CL_RG, CL_UNSIGNED_INT8 }, PIPE_FORMAT_R8G8_UINT }, + { { CL_RGB, CL_UNSIGNED_INT8 }, PIPE_FORMAT_R8G8B8_UINT }, + { { CL_RGBA, CL_UNSIGNED_INT8 }, PIPE_FORMAT_R8G8B8A8_UINT }, + { { CL_R, CL_SIGNED_INT8 }, PIPE_FORMAT_R8_SINT }, + { { CL_RG, CL_SIGNED_INT8 }, PIPE_FORMAT_R8G8_SINT }, + { { CL_RGB, CL_SIGNED_INT8 }, PIPE_FORMAT_R8G8B8_SINT }, + { { CL_RGBA, CL_SIGNED_INT8 }, PIPE_FORMAT_R8G8B8A8_SINT }, + { { CL_R, CL_UNSIGNED_INT16 }, PIPE_FORMAT_R16_UINT }, + { { CL_RG, CL_UNSIGNED_INT16 }, PIPE_FORMAT_R16G16_UINT }, + { { CL_RGB, CL_UNSIGNED_INT16 }, PIPE_FORMAT_R16G16B16_UINT }, + { { CL_RGBA, CL_UNSIGNED_INT16 }, PIPE_FORMAT_R16G16B16A16_UINT }, + { { CL_R, CL_SIGNED_INT16 }, PIPE_FORMAT_R16_SINT }, + { { CL_RG, CL_SIGNED_INT16 }, PIPE_FORMAT_R16G16_SINT }, + { { CL_RGB, CL_SIGNED_INT16 }, PIPE_FORMAT_R16G16B16_SINT }, + { { CL_RGBA, CL_SIGNED_INT16 }, PIPE_FORMAT_R16G16B16A16_SINT }, + { { CL_R, CL_UNSIGNED_INT32 }, PIPE_FORMAT_R32_UINT }, + { { CL_RG, CL_UNSIGNED_INT32 }, PIPE_FORMAT_R32G32_UINT }, + { { CL_RGB, CL_UNSIGNED_INT32 }, PIPE_FORMAT_R32G32B32_UINT }, + { { CL_RGBA, CL_UNSIGNED_INT32 }, PIPE_FORMAT_R32G32B32A32_UINT }, + { { CL_R, CL_SIGNED_INT32 }, PIPE_FORMAT_R32_SINT }, + { { CL_RG, CL_SIGNED_INT32 }, PIPE_FORMAT_R32G32_SINT }, + { { CL_RGB, CL_SIGNED_INT32 }, PIPE_FORMAT_R32G32B32_SINT }, + { { CL_RGBA, CL_SIGNED_INT32 }, PIPE_FORMAT_R32G32B32A32_SINT }, + { { CL_A, CL_UNSIGNED_INT8 }, PIPE_FORMAT_A8_UINT }, + { { CL_INTENSITY, CL_UNSIGNED_INT8 }, PIPE_FORMAT_I8_UINT }, + { { CL_LUMINANCE, CL_UNSIGNED_INT8 }, PIPE_FORMAT_L8_UINT }, + { { CL_A, CL_SIGNED_INT8 }, PIPE_FORMAT_A8_SINT }, + { { CL_INTENSITY, CL_SIGNED_INT8 }, PIPE_FORMAT_I8_SINT }, + { { CL_LUMINANCE, CL_SIGNED_INT8 }, PIPE_FORMAT_L8_SINT }, + { { CL_A, CL_UNSIGNED_INT16 }, PIPE_FORMAT_A16_UINT }, + { { CL_INTENSITY, CL_UNSIGNED_INT16 }, PIPE_FORMAT_I16_UINT }, + { { CL_LUMINANCE, CL_UNSIGNED_INT16 }, PIPE_FORMAT_L16_UINT }, + { { CL_A, CL_SIGNED_INT16 }, PIPE_FORMAT_A16_SINT }, + { { CL_INTENSITY, CL_SIGNED_INT16 }, PIPE_FORMAT_I16_SINT }, + { { CL_LUMINANCE, CL_SIGNED_INT16 }, PIPE_FORMAT_L16_SINT }, + { { CL_A, CL_UNSIGNED_INT32 }, PIPE_FORMAT_A32_UINT }, + { { CL_INTENSITY, CL_UNSIGNED_INT32 }, PIPE_FORMAT_I32_UINT }, + { { CL_LUMINANCE, CL_UNSIGNED_INT32 }, PIPE_FORMAT_L32_UINT }, + { { CL_A, CL_SIGNED_INT32 }, PIPE_FORMAT_A32_SINT }, + { { CL_INTENSITY, CL_SIGNED_INT32 }, PIPE_FORMAT_I32_SINT }, + { { CL_LUMINANCE, CL_SIGNED_INT32 }, PIPE_FORMAT_L32_SINT } + }; + + pipe_texture_target + translate_target(cl_mem_object_type type) { + switch (type) { + case CL_MEM_OBJECT_BUFFER: + return PIPE_BUFFER; + case CL_MEM_OBJECT_IMAGE2D: + return PIPE_TEXTURE_2D; + case CL_MEM_OBJECT_IMAGE3D: + return PIPE_TEXTURE_3D; + default: + throw error(CL_INVALID_VALUE); + } + } + + pipe_format + translate_format(const cl_image_format &format) { + auto it = formats.find(format); + + if (it == formats.end()) + throw error(CL_IMAGE_FORMAT_NOT_SUPPORTED); + + return it->second; + } + + std::set + supported_formats(const context &ctx, cl_mem_object_type type) { + std::set s; + pipe_texture_target target = translate_target(type); + unsigned bindings = (PIPE_BIND_SAMPLER_VIEW | + PIPE_BIND_COMPUTE_RESOURCE); + + for (auto f : formats) { + if (all_of([=](const device &dev) { + return dev.pipe->is_format_supported( + dev.pipe, f.second, target, 1, 1, bindings); + }, ctx.devices())) + s.insert(f.first); + } + + return s; + } +} diff --git a/src/gallium/frontends/clover/core/format.hpp b/src/gallium/frontends/clover/core/format.hpp new file mode 100644 index 00000000000..a8b7053c5dc --- /dev/null +++ b/src/gallium/frontends/clover/core/format.hpp @@ -0,0 +1,62 @@ +// +// Copyright 2012 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#ifndef CLOVER_CORE_FORMAT_HPP +#define CLOVER_CORE_FORMAT_HPP + +#include + +#include "core/object.hpp" +#include "pipe/p_defines.h" +#include "pipe/p_format.h" + +namespace clover { + pipe_texture_target translate_target(cl_mem_object_type type); + pipe_format translate_format(const cl_image_format &format); + + /// + /// Return all the image formats supported by a given context for + /// the given memory object type. + /// + std::set supported_formats(const context &ctx, + cl_mem_object_type type); +} + +static inline bool +operator<(const cl_image_format &a, const cl_image_format &b) { + return (a.image_channel_order != b.image_channel_order ? + a.image_channel_order < b.image_channel_order : + a.image_channel_data_type < b.image_channel_data_type); +} + +static inline bool +operator==(const cl_image_format &a, const cl_image_format &b) { + return (a.image_channel_order == b.image_channel_order && + a.image_channel_data_type == b.image_channel_data_type); +} + +static inline bool +operator!=(const cl_image_format &a, const cl_image_format &b) { + return !(a == b); +} + +#endif diff --git a/src/gallium/frontends/clover/core/kernel.cpp b/src/gallium/frontends/clover/core/kernel.cpp new file mode 100644 index 00000000000..7d839767aa0 --- /dev/null +++ b/src/gallium/frontends/clover/core/kernel.cpp @@ -0,0 +1,610 @@ +// +// Copyright 2012 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#include "core/kernel.hpp" +#include "core/resource.hpp" +#include "util/factor.hpp" +#include "util/u_math.h" +#include "pipe/p_context.h" + +using namespace clover; + +kernel::kernel(clover::program &prog, const std::string &name, + const std::vector &margs) : + program(prog), _name(name), exec(*this), + program_ref(prog._kernel_ref_counter) { + for (auto &marg : margs) { + if (marg.semantic == module::argument::general) + _args.emplace_back(argument::create(marg)); + } +} + +template +static inline std::vector +pad_vector(command_queue &q, const V &v, uint x) { + std::vector w { v.begin(), v.end() }; + w.resize(q.device().max_block_size().size(), x); + return w; +} + +void +kernel::launch(command_queue &q, + const std::vector &grid_offset, + const std::vector &grid_size, + const std::vector &block_size) { + const auto m = program().build(q.device()).binary; + const auto reduced_grid_size = + map(divides(), grid_size, block_size); + void *st = exec.bind(&q, grid_offset); + struct pipe_grid_info info = {}; + + // The handles are created during exec_context::bind(), so we need make + // sure to call exec_context::bind() before retrieving them. + std::vector g_handles = map([&](size_t h) { + return (uint32_t *)&exec.input[h]; + }, exec.g_handles); + + q.pipe->bind_compute_state(q.pipe, st); + q.pipe->bind_sampler_states(q.pipe, PIPE_SHADER_COMPUTE, + 0, exec.samplers.size(), + exec.samplers.data()); + + q.pipe->set_sampler_views(q.pipe, PIPE_SHADER_COMPUTE, 0, + exec.sviews.size(), exec.sviews.data()); + q.pipe->set_compute_resources(q.pipe, 0, exec.resources.size(), + exec.resources.data()); + q.pipe->set_global_binding(q.pipe, 0, exec.g_buffers.size(), + exec.g_buffers.data(), g_handles.data()); + + // Fill information for the launch_grid() call. + info.work_dim = grid_size.size(); + copy(pad_vector(q, block_size, 1), info.block); + copy(pad_vector(q, reduced_grid_size, 1), info.grid); + info.pc = find(name_equals(_name), m.syms).offset; + info.input = exec.input.data(); + + q.pipe->launch_grid(q.pipe, &info); + + q.pipe->set_global_binding(q.pipe, 0, exec.g_buffers.size(), NULL, NULL); + q.pipe->set_compute_resources(q.pipe, 0, exec.resources.size(), NULL); + q.pipe->set_sampler_views(q.pipe, PIPE_SHADER_COMPUTE, 0, + exec.sviews.size(), NULL); + q.pipe->bind_sampler_states(q.pipe, PIPE_SHADER_COMPUTE, 0, + exec.samplers.size(), NULL); + + q.pipe->memory_barrier(q.pipe, PIPE_BARRIER_GLOBAL_BUFFER); + exec.unbind(); +} + +size_t +kernel::mem_local() const { + size_t sz = 0; + + for (auto &arg : args()) { + if (dynamic_cast(&arg)) + sz += arg.storage(); + } + + return sz; +} + +size_t +kernel::mem_private() const { + return 0; +} + +const std::string & +kernel::name() const { + return _name; +} + +std::vector +kernel::optimal_block_size(const command_queue &q, + const std::vector &grid_size) const { + return factor::find_grid_optimal_factor( + q.device().max_threads_per_block(), q.device().max_block_size(), + grid_size); +} + +std::vector +kernel::required_block_size() const { + return { 0, 0, 0 }; +} + +kernel::argument_range +kernel::args() { + return map(derefs(), _args); +} + +kernel::const_argument_range +kernel::args() const { + return map(derefs(), _args); +} + +const module & +kernel::module(const command_queue &q) const { + return program().build(q.device()).binary; +} + +kernel::exec_context::exec_context(kernel &kern) : + kern(kern), q(NULL), mem_local(0), st(NULL), cs() { +} + +kernel::exec_context::~exec_context() { + if (st) + q->pipe->delete_compute_state(q->pipe, st); +} + +void * +kernel::exec_context::bind(intrusive_ptr _q, + const std::vector &grid_offset) { + std::swap(q, _q); + + // Bind kernel arguments. + auto &m = kern.program().build(q->device()).binary; + auto msym = find(name_equals(kern.name()), m.syms); + auto margs = msym.args; + auto msec = find(id_equals(msym.section), m.secs); + auto explicit_arg = kern._args.begin(); + + for (auto &marg : margs) { + switch (marg.semantic) { + case module::argument::general: + (*(explicit_arg++))->bind(*this, marg); + break; + + case module::argument::grid_dimension: { + const cl_uint dimension = grid_offset.size(); + auto arg = argument::create(marg); + + arg->set(sizeof(dimension), &dimension); + arg->bind(*this, marg); + break; + } + case module::argument::grid_offset: { + for (cl_uint x : pad_vector(*q, grid_offset, 0)) { + auto arg = argument::create(marg); + + arg->set(sizeof(x), &x); + arg->bind(*this, marg); + } + break; + } + case module::argument::image_size: { + auto img = dynamic_cast(**(explicit_arg - 1)).get(); + std::vector image_size{ + static_cast(img->width()), + static_cast(img->height()), + static_cast(img->depth())}; + for (auto x : image_size) { + auto arg = argument::create(marg); + + arg->set(sizeof(x), &x); + arg->bind(*this, marg); + } + break; + } + case module::argument::image_format: { + auto img = dynamic_cast(**(explicit_arg - 1)).get(); + cl_image_format fmt = img->format(); + std::vector image_format{ + static_cast(fmt.image_channel_data_type), + static_cast(fmt.image_channel_order)}; + for (auto x : image_format) { + auto arg = argument::create(marg); + + arg->set(sizeof(x), &x); + arg->bind(*this, marg); + } + break; + } + } + } + + // Create a new compute state if anything changed. + if (!st || q != _q || + cs.req_local_mem != mem_local || + cs.req_input_mem != input.size()) { + if (st) + _q->pipe->delete_compute_state(_q->pipe, st); + + cs.ir_type = q->device().ir_format(); + cs.prog = &(msec.data[0]); + cs.req_local_mem = mem_local; + cs.req_input_mem = input.size(); + st = q->pipe->create_compute_state(q->pipe, &cs); + if (!st) { + unbind(); // Cleanup + throw error(CL_OUT_OF_RESOURCES); + } + } + + return st; +} + +void +kernel::exec_context::unbind() { + for (auto &arg : kern.args()) + arg.unbind(*this); + + input.clear(); + samplers.clear(); + sviews.clear(); + resources.clear(); + g_buffers.clear(); + g_handles.clear(); + mem_local = 0; +} + +namespace { + template + std::vector + bytes(const T& x) { + return { (uint8_t *)&x, (uint8_t *)&x + sizeof(x) }; + } + + /// + /// Transform buffer \a v from the native byte order into the byte + /// order specified by \a e. + /// + template + void + byteswap(T &v, pipe_endian e) { + if (PIPE_ENDIAN_NATIVE != e) + std::reverse(v.begin(), v.end()); + } + + /// + /// Pad buffer \a v to the next multiple of \a n. + /// + template + void + align(T &v, size_t n) { + v.resize(util_align_npot(v.size(), n)); + } + + bool + msb(const std::vector &s) { + if (PIPE_ENDIAN_NATIVE == PIPE_ENDIAN_LITTLE) + return s.back() & 0x80; + else + return s.front() & 0x80; + } + + /// + /// Resize buffer \a v to size \a n using sign or zero extension + /// according to \a ext. + /// + template + void + extend(T &v, enum module::argument::ext_type ext, size_t n) { + const size_t m = std::min(v.size(), n); + const bool sign_ext = (ext == module::argument::sign_ext); + const uint8_t fill = (sign_ext && msb(v) ? ~0 : 0); + T w(n, fill); + + if (PIPE_ENDIAN_NATIVE == PIPE_ENDIAN_LITTLE) + std::copy_n(v.begin(), m, w.begin()); + else + std::copy_n(v.end() - m, m, w.end() - m); + + std::swap(v, w); + } + + /// + /// Append buffer \a w to \a v. + /// + template + void + insert(T &v, const T &w) { + v.insert(v.end(), w.begin(), w.end()); + } + + /// + /// Append \a n elements to the end of buffer \a v. + /// + template + size_t + allocate(T &v, size_t n) { + size_t pos = v.size(); + v.resize(pos + n); + return pos; + } +} + +std::unique_ptr +kernel::argument::create(const module::argument &marg) { + switch (marg.type) { + case module::argument::scalar: + return std::unique_ptr(new scalar_argument(marg.size)); + + case module::argument::global: + return std::unique_ptr(new global_argument); + + case module::argument::local: + return std::unique_ptr(new local_argument); + + case module::argument::constant: + return std::unique_ptr(new constant_argument); + + case module::argument::image2d_rd: + case module::argument::image3d_rd: + return std::unique_ptr(new image_rd_argument); + + case module::argument::image2d_wr: + case module::argument::image3d_wr: + return std::unique_ptr(new image_wr_argument); + + case module::argument::sampler: + return std::unique_ptr(new sampler_argument); + + } + throw error(CL_INVALID_KERNEL_DEFINITION); +} + +kernel::argument::argument() : _set(false) { +} + +bool +kernel::argument::set() const { + return _set; +} + +size_t +kernel::argument::storage() const { + return 0; +} + +kernel::scalar_argument::scalar_argument(size_t size) : size(size) { +} + +void +kernel::scalar_argument::set(size_t size, const void *value) { + if (!value) + throw error(CL_INVALID_ARG_VALUE); + + if (size != this->size) + throw error(CL_INVALID_ARG_SIZE); + + v = { (uint8_t *)value, (uint8_t *)value + size }; + _set = true; +} + +void +kernel::scalar_argument::bind(exec_context &ctx, + const module::argument &marg) { + auto w = v; + + extend(w, marg.ext_type, marg.target_size); + byteswap(w, ctx.q->device().endianness()); + align(ctx.input, marg.target_align); + insert(ctx.input, w); +} + +void +kernel::scalar_argument::unbind(exec_context &ctx) { +} + +void +kernel::global_argument::set(size_t size, const void *value) { + if (size != sizeof(cl_mem)) + throw error(CL_INVALID_ARG_SIZE); + + buf = pobj(value ? *(cl_mem *)value : NULL); + svm = nullptr; + _set = true; +} + +void +kernel::global_argument::set_svm(const void *value) { + svm = value; + buf = nullptr; + _set = true; +} + +void +kernel::global_argument::bind(exec_context &ctx, + const module::argument &marg) { + align(ctx.input, marg.target_align); + + if (buf) { + const resource &r = buf->resource(*ctx.q); + ctx.g_handles.push_back(ctx.input.size()); + ctx.g_buffers.push_back(r.pipe); + + // How to handle multi-demensional offsets? + // We don't need to. Buffer offsets are always + // one-dimensional. + auto v = bytes(r.offset[0]); + extend(v, marg.ext_type, marg.target_size); + byteswap(v, ctx.q->device().endianness()); + insert(ctx.input, v); + } else if (svm) { + auto v = bytes(svm); + extend(v, marg.ext_type, marg.target_size); + byteswap(v, ctx.q->device().endianness()); + insert(ctx.input, v); + } else { + // Null pointer. + allocate(ctx.input, marg.target_size); + } +} + +void +kernel::global_argument::unbind(exec_context &ctx) { +} + +size_t +kernel::local_argument::storage() const { + return _storage; +} + +void +kernel::local_argument::set(size_t size, const void *value) { + if (value) + throw error(CL_INVALID_ARG_VALUE); + + if (!size) + throw error(CL_INVALID_ARG_SIZE); + + _storage = size; + _set = true; +} + +void +kernel::local_argument::bind(exec_context &ctx, + const module::argument &marg) { + auto v = bytes(ctx.mem_local); + + extend(v, module::argument::zero_ext, marg.target_size); + byteswap(v, ctx.q->device().endianness()); + align(ctx.input, marg.target_align); + insert(ctx.input, v); + + ctx.mem_local += _storage; +} + +void +kernel::local_argument::unbind(exec_context &ctx) { +} + +void +kernel::constant_argument::set(size_t size, const void *value) { + if (size != sizeof(cl_mem)) + throw error(CL_INVALID_ARG_SIZE); + + buf = pobj(value ? *(cl_mem *)value : NULL); + _set = true; +} + +void +kernel::constant_argument::bind(exec_context &ctx, + const module::argument &marg) { + align(ctx.input, marg.target_align); + + if (buf) { + resource &r = buf->resource(*ctx.q); + auto v = bytes(ctx.resources.size() << 24 | r.offset[0]); + + extend(v, module::argument::zero_ext, marg.target_size); + byteswap(v, ctx.q->device().endianness()); + insert(ctx.input, v); + + st = r.bind_surface(*ctx.q, false); + ctx.resources.push_back(st); + } else { + // Null pointer. + allocate(ctx.input, marg.target_size); + } +} + +void +kernel::constant_argument::unbind(exec_context &ctx) { + if (buf) + buf->resource(*ctx.q).unbind_surface(*ctx.q, st); +} + +void +kernel::image_rd_argument::set(size_t size, const void *value) { + if (!value) + throw error(CL_INVALID_ARG_VALUE); + + if (size != sizeof(cl_mem)) + throw error(CL_INVALID_ARG_SIZE); + + img = &obj(*(cl_mem *)value); + _set = true; +} + +void +kernel::image_rd_argument::bind(exec_context &ctx, + const module::argument &marg) { + auto v = bytes(ctx.sviews.size()); + + extend(v, module::argument::zero_ext, marg.target_size); + byteswap(v, ctx.q->device().endianness()); + align(ctx.input, marg.target_align); + insert(ctx.input, v); + + st = img->resource(*ctx.q).bind_sampler_view(*ctx.q); + ctx.sviews.push_back(st); +} + +void +kernel::image_rd_argument::unbind(exec_context &ctx) { + img->resource(*ctx.q).unbind_sampler_view(*ctx.q, st); +} + +void +kernel::image_wr_argument::set(size_t size, const void *value) { + if (!value) + throw error(CL_INVALID_ARG_VALUE); + + if (size != sizeof(cl_mem)) + throw error(CL_INVALID_ARG_SIZE); + + img = &obj(*(cl_mem *)value); + _set = true; +} + +void +kernel::image_wr_argument::bind(exec_context &ctx, + const module::argument &marg) { + auto v = bytes(ctx.resources.size()); + + extend(v, module::argument::zero_ext, marg.target_size); + byteswap(v, ctx.q->device().endianness()); + align(ctx.input, marg.target_align); + insert(ctx.input, v); + + st = img->resource(*ctx.q).bind_surface(*ctx.q, true); + ctx.resources.push_back(st); +} + +void +kernel::image_wr_argument::unbind(exec_context &ctx) { + img->resource(*ctx.q).unbind_surface(*ctx.q, st); +} + +void +kernel::sampler_argument::set(size_t size, const void *value) { + if (!value) + throw error(CL_INVALID_SAMPLER); + + if (size != sizeof(cl_sampler)) + throw error(CL_INVALID_ARG_SIZE); + + s = &obj(*(cl_sampler *)value); + _set = true; +} + +void +kernel::sampler_argument::bind(exec_context &ctx, + const module::argument &marg) { + st = s->bind(*ctx.q); + ctx.samplers.push_back(st); +} + +void +kernel::sampler_argument::unbind(exec_context &ctx) { + s->unbind(*ctx.q, st); +} diff --git a/src/gallium/frontends/clover/core/kernel.hpp b/src/gallium/frontends/clover/core/kernel.hpp new file mode 100644 index 00000000000..4441091f300 --- /dev/null +++ b/src/gallium/frontends/clover/core/kernel.hpp @@ -0,0 +1,251 @@ +// +// Copyright 2012 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#ifndef CLOVER_CORE_KERNEL_HPP +#define CLOVER_CORE_KERNEL_HPP + +#include + +#include "core/object.hpp" +#include "core/program.hpp" +#include "core/memory.hpp" +#include "core/sampler.hpp" +#include "pipe/p_state.h" + +namespace clover { + class kernel : public ref_counter, public _cl_kernel { + private: + /// + /// Class containing all the state required to execute a compute + /// kernel. + /// + struct exec_context { + exec_context(kernel &kern); + ~exec_context(); + + exec_context(const exec_context &) = delete; + exec_context & + operator=(const exec_context &) = delete; + + void *bind(intrusive_ptr _q, + const std::vector &grid_offset); + void unbind(); + + kernel &kern; + intrusive_ptr q; + + std::vector input; + std::vector samplers; + std::vector sviews; + std::vector resources; + std::vector g_buffers; + std::vector g_handles; + size_t mem_local; + + private: + void *st; + pipe_compute_state cs; + }; + + public: + class argument { + public: + static std::unique_ptr + create(const module::argument &marg); + + argument(const argument &arg) = delete; + argument & + operator=(const argument &arg) = delete; + + /// \a true if the argument has been set. + bool set() const; + + /// Storage space required for the referenced object. + virtual size_t storage() const; + + /// Set this argument to some object. + virtual void set(size_t size, const void *value) = 0; + + /// Set this argument to an SVM pointer. + virtual void set_svm(const void *value) { + throw error(CL_INVALID_ARG_INDEX); + }; + + /// Allocate the necessary resources to bind the specified + /// object to this argument, and update \a ctx accordingly. + virtual void bind(exec_context &ctx, + const module::argument &marg) = 0; + + /// Free any resources that were allocated in bind(). + virtual void unbind(exec_context &ctx) = 0; + + virtual ~argument() {}; + protected: + argument(); + + bool _set; + }; + + private: + typedef adaptor_range< + derefs, std::vector> & + > argument_range; + + typedef adaptor_range< + derefs, const std::vector> & + > const_argument_range; + + public: + kernel(clover::program &prog, const std::string &name, + const std::vector &margs); + + kernel(const kernel &kern) = delete; + kernel & + operator=(const kernel &kern) = delete; + + void launch(command_queue &q, + const std::vector &grid_offset, + const std::vector &grid_size, + const std::vector &block_size); + + size_t mem_local() const; + size_t mem_private() const; + + const std::string &name() const; + + std::vector + optimal_block_size(const command_queue &q, + const std::vector &grid_size) const; + std::vector + required_block_size() const; + + argument_range args(); + const_argument_range args() const; + + const intrusive_ref program; + + private: + const clover::module &module(const command_queue &q) const; + + class scalar_argument : public argument { + public: + scalar_argument(size_t size); + + virtual void set(size_t size, const void *value); + virtual void bind(exec_context &ctx, + const module::argument &marg); + virtual void unbind(exec_context &ctx); + + private: + size_t size; + std::vector v; + }; + + class global_argument : public argument { + public: + virtual void set(size_t size, const void *value); + virtual void set_svm(const void *value); + virtual void bind(exec_context &ctx, + const module::argument &marg); + virtual void unbind(exec_context &ctx); + + private: + buffer *buf; + const void *svm; + }; + + class local_argument : public argument { + public: + virtual size_t storage() const; + + virtual void set(size_t size, const void *value); + virtual void bind(exec_context &ctx, + const module::argument &marg); + virtual void unbind(exec_context &ctx); + + private: + size_t _storage = 0; + }; + + class constant_argument : public argument { + public: + virtual void set(size_t size, const void *value); + virtual void bind(exec_context &ctx, + const module::argument &marg); + virtual void unbind(exec_context &ctx); + + private: + buffer *buf; + pipe_surface *st; + }; + + class image_argument : public argument { + public: + const image *get() const { + return img; + } + protected: + image *img; + }; + + class image_rd_argument : public image_argument { + public: + virtual void set(size_t size, const void *value); + virtual void bind(exec_context &ctx, + const module::argument &marg); + virtual void unbind(exec_context &ctx); + + private: + pipe_sampler_view *st; + }; + + class image_wr_argument : public image_argument { + public: + virtual void set(size_t size, const void *value); + virtual void bind(exec_context &ctx, + const module::argument &marg); + virtual void unbind(exec_context &ctx); + + private: + pipe_surface *st; + }; + + class sampler_argument : public argument { + public: + virtual void set(size_t size, const void *value); + virtual void bind(exec_context &ctx, + const module::argument &marg); + virtual void unbind(exec_context &ctx); + + private: + sampler *s; + void *st; + }; + + std::vector> _args; + std::string _name; + exec_context exec; + const ref_holder program_ref; + }; +} + +#endif diff --git a/src/gallium/frontends/clover/core/memory.cpp b/src/gallium/frontends/clover/core/memory.cpp new file mode 100644 index 00000000000..ed13d92c281 --- /dev/null +++ b/src/gallium/frontends/clover/core/memory.cpp @@ -0,0 +1,214 @@ +// +// Copyright 2012 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#include "core/memory.hpp" +#include "core/resource.hpp" +#include "util/format/u_format.h" + +using namespace clover; + +memory_obj::memory_obj(clover::context &ctx, cl_mem_flags flags, + size_t size, void *host_ptr) : + context(ctx), _flags(flags), + _size(size), _host_ptr(host_ptr) { + if (flags & CL_MEM_COPY_HOST_PTR) + data.append((char *)host_ptr, size); +} + +memory_obj::~memory_obj() { + while (_destroy_notify.size()) { + _destroy_notify.top()(); + _destroy_notify.pop(); + } +} + +bool +memory_obj::operator==(const memory_obj &obj) const { + return this == &obj; +} + +void +memory_obj::destroy_notify(std::function f) { + _destroy_notify.push(f); +} + +cl_mem_flags +memory_obj::flags() const { + return _flags; +} + +size_t +memory_obj::size() const { + return _size; +} + +void * +memory_obj::host_ptr() const { + return _host_ptr; +} + +buffer::buffer(clover::context &ctx, cl_mem_flags flags, + size_t size, void *host_ptr) : + memory_obj(ctx, flags, size, host_ptr) { +} + +cl_mem_object_type +buffer::type() const { + return CL_MEM_OBJECT_BUFFER; +} + +root_buffer::root_buffer(clover::context &ctx, cl_mem_flags flags, + size_t size, void *host_ptr) : + buffer(ctx, flags, size, host_ptr) { +} + +resource & +root_buffer::resource(command_queue &q) { + // Create a new resource if there's none for this device yet. + if (!resources.count(&q.device())) { + auto r = (!resources.empty() ? + new root_resource(q.device(), *this, + *resources.begin()->second) : + new root_resource(q.device(), *this, q, data)); + + resources.insert(std::make_pair(&q.device(), + std::unique_ptr(r))); + data.clear(); + } + + return *resources.find(&q.device())->second; +} + +sub_buffer::sub_buffer(root_buffer &parent, cl_mem_flags flags, + size_t offset, size_t size) : + buffer(parent.context(), flags, size, + (char *)parent.host_ptr() + offset), + parent(parent), _offset(offset) { +} + +resource & +sub_buffer::resource(command_queue &q) { + // Create a new resource if there's none for this device yet. + if (!resources.count(&q.device())) { + auto r = new sub_resource(parent().resource(q), {{ offset() }}); + + resources.insert(std::make_pair(&q.device(), + std::unique_ptr(r))); + } + + return *resources.find(&q.device())->second; +} + +size_t +sub_buffer::offset() const { + return _offset; +} + +image::image(clover::context &ctx, cl_mem_flags flags, + const cl_image_format *format, + size_t width, size_t height, size_t depth, + size_t row_pitch, size_t slice_pitch, size_t size, + void *host_ptr) : + memory_obj(ctx, flags, size, host_ptr), + _format(*format), _width(width), _height(height), _depth(depth), + _row_pitch(row_pitch), _slice_pitch(slice_pitch) { +} + +resource & +image::resource(command_queue &q) { + // Create a new resource if there's none for this device yet. + if (!resources.count(&q.device())) { + auto r = (!resources.empty() ? + new root_resource(q.device(), *this, + *resources.begin()->second) : + new root_resource(q.device(), *this, q, data)); + + resources.insert(std::make_pair(&q.device(), + std::unique_ptr(r))); + data.clear(); + } + + return *resources.find(&q.device())->second; +} + +cl_image_format +image::format() const { + return _format; +} + +size_t +image::width() const { + return _width; +} + +size_t +image::height() const { + return _height; +} + +size_t +image::depth() const { + return _depth; +} + +size_t +image::pixel_size() const { + return util_format_get_blocksize(translate_format(_format)); +} + +size_t +image::row_pitch() const { + return _row_pitch; +} + +size_t +image::slice_pitch() const { + return _slice_pitch; +} + +image2d::image2d(clover::context &ctx, cl_mem_flags flags, + const cl_image_format *format, size_t width, + size_t height, size_t row_pitch, + void *host_ptr) : + image(ctx, flags, format, width, height, 1, + row_pitch, 0, height * row_pitch, host_ptr) { +} + +cl_mem_object_type +image2d::type() const { + return CL_MEM_OBJECT_IMAGE2D; +} + +image3d::image3d(clover::context &ctx, cl_mem_flags flags, + const cl_image_format *format, + size_t width, size_t height, size_t depth, + size_t row_pitch, size_t slice_pitch, + void *host_ptr) : + image(ctx, flags, format, width, height, depth, + row_pitch, slice_pitch, depth * slice_pitch, + host_ptr) { +} + +cl_mem_object_type +image3d::type() const { + return CL_MEM_OBJECT_IMAGE3D; +} diff --git a/src/gallium/frontends/clover/core/memory.hpp b/src/gallium/frontends/clover/core/memory.hpp new file mode 100644 index 00000000000..bd6da6be4d1 --- /dev/null +++ b/src/gallium/frontends/clover/core/memory.hpp @@ -0,0 +1,159 @@ +// +// Copyright 2012 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#ifndef CLOVER_CORE_MEMORY_HPP +#define CLOVER_CORE_MEMORY_HPP + +#include +#include +#include +#include + +#include "core/object.hpp" +#include "core/queue.hpp" +#include "core/resource.hpp" + +namespace clover { + class memory_obj : public ref_counter, public _cl_mem { + protected: + memory_obj(clover::context &ctx, cl_mem_flags flags, + size_t size, void *host_ptr); + + memory_obj(const memory_obj &obj) = delete; + memory_obj & + operator=(const memory_obj &obj) = delete; + + public: + virtual ~memory_obj(); + + bool + operator==(const memory_obj &obj) const; + + virtual cl_mem_object_type type() const = 0; + virtual clover::resource &resource(command_queue &q) = 0; + + void destroy_notify(std::function f); + cl_mem_flags flags() const; + size_t size() const; + void *host_ptr() const; + + const intrusive_ref context; + + private: + cl_mem_flags _flags; + size_t _size; + void *_host_ptr; + std::stack> _destroy_notify; + + protected: + std::string data; + }; + + class buffer : public memory_obj { + protected: + buffer(clover::context &ctx, cl_mem_flags flags, + size_t size, void *host_ptr); + + public: + virtual cl_mem_object_type type() const; + }; + + class root_buffer : public buffer { + public: + root_buffer(clover::context &ctx, cl_mem_flags flags, + size_t size, void *host_ptr); + + virtual clover::resource &resource(command_queue &q); + + private: + std::map> resources; + }; + + class sub_buffer : public buffer { + public: + sub_buffer(root_buffer &parent, cl_mem_flags flags, + size_t offset, size_t size); + + virtual clover::resource &resource(command_queue &q); + size_t offset() const; + + const intrusive_ref parent; + + private: + size_t _offset; + std::map> resources; + }; + + class image : public memory_obj { + protected: + image(clover::context &ctx, cl_mem_flags flags, + const cl_image_format *format, + size_t width, size_t height, size_t depth, + size_t row_pitch, size_t slice_pitch, size_t size, + void *host_ptr); + + public: + virtual clover::resource &resource(command_queue &q); + cl_image_format format() const; + size_t width() const; + size_t height() const; + size_t depth() const; + size_t pixel_size() const; + size_t row_pitch() const; + size_t slice_pitch() const; + + private: + cl_image_format _format; + size_t _width; + size_t _height; + size_t _depth; + size_t _row_pitch; + size_t _slice_pitch; + std::map> resources; + }; + + class image2d : public image { + public: + image2d(clover::context &ctx, cl_mem_flags flags, + const cl_image_format *format, size_t width, + size_t height, size_t row_pitch, + void *host_ptr); + + virtual cl_mem_object_type type() const; + }; + + class image3d : public image { + public: + image3d(clover::context &ctx, cl_mem_flags flags, + const cl_image_format *format, + size_t width, size_t height, size_t depth, + size_t row_pitch, size_t slice_pitch, + void *host_ptr); + + virtual cl_mem_object_type type() const; + }; +} + +#endif diff --git a/src/gallium/frontends/clover/core/module.cpp b/src/gallium/frontends/clover/core/module.cpp new file mode 100644 index 00000000000..a6c5b98d8e0 --- /dev/null +++ b/src/gallium/frontends/clover/core/module.cpp @@ -0,0 +1,228 @@ +// +// Copyright 2012 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#include +#include + +#include "core/module.hpp" + +using namespace clover; + +namespace { + template + struct _serializer; + + /// Serialize the specified object. + template + void + _proc(std::ostream &os, const T &x) { + _serializer::proc(os, x); + } + + /// Deserialize the specified object. + template + void + _proc(std::istream &is, T &x) { + _serializer::proc(is, x); + } + + template + T + _proc(std::istream &is) { + T x; + _serializer::proc(is, x); + return x; + } + + /// Calculate the size of the specified object. + template + void + _proc(module::size_t &sz, const T &x) { + _serializer::proc(sz, x); + } + + /// (De)serialize a scalar value. + template + struct _serializer::value>::type> { + static void + proc(std::ostream &os, const T &x) { + os.write(reinterpret_cast(&x), sizeof(x)); + } + + static void + proc(std::istream &is, T &x) { + is.read(reinterpret_cast(&x), sizeof(x)); + } + + static void + proc(module::size_t &sz, const T &x) { + sz += sizeof(x); + } + }; + + /// (De)serialize a vector. + template + struct _serializer, + typename std::enable_if< + !std::is_scalar::value>::type> { + static void + proc(std::ostream &os, const std::vector &v) { + _proc(os, v.size()); + + for (size_t i = 0; i < v.size(); i++) + _proc(os, v[i]); + } + + static void + proc(std::istream &is, std::vector &v) { + v.resize(_proc(is)); + + for (size_t i = 0; i < v.size(); i++) + new(&v[i]) T(_proc(is)); + } + + static void + proc(module::size_t &sz, const std::vector &v) { + sz += sizeof(uint32_t); + + for (size_t i = 0; i < v.size(); i++) + _proc(sz, v[i]); + } + }; + + template + struct _serializer, + typename std::enable_if< + std::is_scalar::value>::type> { + static void + proc(std::ostream &os, const std::vector &v) { + _proc(os, v.size()); + os.write(reinterpret_cast(&v[0]), + v.size() * sizeof(T)); + } + + static void + proc(std::istream &is, std::vector &v) { + v.resize(_proc(is)); + is.read(reinterpret_cast(&v[0]), + v.size() * sizeof(T)); + } + + static void + proc(module::size_t &sz, const std::vector &v) { + sz += sizeof(uint32_t) + sizeof(T) * v.size(); + } + }; + + /// (De)serialize a string. + template<> + struct _serializer { + static void + proc(std::ostream &os, const std::string &s) { + _proc(os, s.size()); + os.write(&s[0], s.size() * sizeof(std::string::value_type)); + } + + static void + proc(std::istream &is, std::string &s) { + s.resize(_proc(is)); + is.read(&s[0], s.size() * sizeof(std::string::value_type)); + } + + static void + proc(module::size_t &sz, const std::string &s) { + sz += sizeof(uint32_t) + sizeof(std::string::value_type) * s.size(); + } + }; + + /// (De)serialize a module::section. + template<> + struct _serializer { + template + static void + proc(S &s, QT &x) { + _proc(s, x.id); + _proc(s, x.type); + _proc(s, x.size); + _proc(s, x.data); + } + }; + + /// (De)serialize a module::argument. + template<> + struct _serializer { + template + static void + proc(S &s, QT &x) { + _proc(s, x.type); + _proc(s, x.size); + _proc(s, x.target_size); + _proc(s, x.target_align); + _proc(s, x.ext_type); + _proc(s, x.semantic); + } + }; + + /// (De)serialize a module::symbol. + template<> + struct _serializer { + template + static void + proc(S &s, QT &x) { + _proc(s, x.name); + _proc(s, x.section); + _proc(s, x.offset); + _proc(s, x.args); + } + }; + + /// (De)serialize a module. + template<> + struct _serializer { + template + static void + proc(S &s, QT &x) { + _proc(s, x.syms); + _proc(s, x.secs); + } + }; +}; + +namespace clover { + void + module::serialize(std::ostream &os) const { + _proc(os, *this); + } + + module + module::deserialize(std::istream &is) { + return _proc(is); + } + + module::size_t + module::size() const { + size_t sz = 0; + _proc(sz, *this); + return sz; + } +} diff --git a/src/gallium/frontends/clover/core/module.hpp b/src/gallium/frontends/clover/core/module.hpp new file mode 100644 index 00000000000..2ddd26426fb --- /dev/null +++ b/src/gallium/frontends/clover/core/module.hpp @@ -0,0 +1,128 @@ +// +// Copyright 2012 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#ifndef CLOVER_CORE_MODULE_HPP +#define CLOVER_CORE_MODULE_HPP + +#include +#include + +namespace clover { + struct module { + typedef uint32_t resource_id; + typedef uint32_t size_t; + + struct section { + enum type { + text_intermediate, + text_library, + text_executable, + data_constant, + data_global, + data_local, + data_private + }; + + section(resource_id id, enum type type, size_t size, + const std::vector &data) : + id(id), type(type), size(size), data(data) { } + section() : id(0), type(text_intermediate), size(0), data() { } + + resource_id id; + type type; + size_t size; + std::vector data; + }; + + struct argument { + enum type { + scalar, + constant, + global, + local, + image2d_rd, + image2d_wr, + image3d_rd, + image3d_wr, + sampler + }; + + enum ext_type { + zero_ext, + sign_ext + }; + + enum semantic { + general, + grid_dimension, + grid_offset, + image_size, + image_format + }; + + argument(enum type type, size_t size, + size_t target_size, size_t target_align, + enum ext_type ext_type, + enum semantic semantic = general) : + type(type), size(size), + target_size(target_size), target_align(target_align), + ext_type(ext_type), semantic(semantic) { } + + argument(enum type type, size_t size) : + type(type), size(size), + target_size(size), target_align(1), + ext_type(zero_ext), semantic(general) { } + + argument() : type(scalar), size(0), + target_size(0), target_align(1), + ext_type(zero_ext), semantic(general) { } + + type type; + size_t size; + size_t target_size; + size_t target_align; + ext_type ext_type; + semantic semantic; + }; + + struct symbol { + symbol(const std::string &name, resource_id section, + size_t offset, const std::vector &args) : + name(name), section(section), offset(offset), args(args) { } + symbol() : name(), section(0), offset(0), args() { } + + std::string name; + resource_id section; + size_t offset; + std::vector args; + }; + + void serialize(std::ostream &os) const; + static module deserialize(std::istream &is); + size_t size() const; + + std::vector syms; + std::vector
      secs; + }; +} + +#endif diff --git a/src/gallium/frontends/clover/core/object.hpp b/src/gallium/frontends/clover/core/object.hpp new file mode 100644 index 00000000000..8fc2175d236 --- /dev/null +++ b/src/gallium/frontends/clover/core/object.hpp @@ -0,0 +1,239 @@ +// +// Copyright 2013 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#ifndef CLOVER_CORE_OBJECT_HPP +#define CLOVER_CORE_OBJECT_HPP + +#include +#include +#include + +#include "CL/cl.h" + +#include "core/error.hpp" +#include "core/property.hpp" +#include "api/dispatch.hpp" +#include "util/macros.h" + +/// +/// Main namespace of the CL state tracker. +/// +namespace clover { + /// + /// Class that represents a CL API object. + /// + template + struct descriptor { + typedef T object_type; + typedef S descriptor_type; + + descriptor() : dispatch(&_dispatch) { + static_assert(std::is_standard_layout::value, + "ICD requires CL API objects to be standard layout."); + } + + const cl_icd_dispatch *dispatch; + }; + + struct default_tag; + struct allow_empty_tag; + struct wait_list_tag; + struct property_list_tag; + + namespace detail { + template + struct descriptor_traits { + typedef T object_type; + + static void + validate(D *d) { + auto o = static_cast(d); + if (!o || o->dispatch != &_dispatch || + !dynamic_cast(o)) + throw invalid_object_error(); + } + + static void + validate_list(D * const *ds, size_t n) { + if (!ds || !n) + throw error(CL_INVALID_VALUE); + } + }; + + template + struct descriptor_traits { + typedef typename D::object_type object_type; + + static void + validate(D *d) { + if (!d || d->dispatch != &_dispatch) + throw invalid_object_error(); + } + + static void + validate_list(D *const *ds, size_t n) { + if (!ds || !n) + throw error(CL_INVALID_VALUE); + } + }; + + template + struct descriptor_traits { + typedef typename D::object_type object_type; + + static void + validate(D *d) { + if (!d || d->dispatch != &_dispatch) + throw invalid_object_error(); + } + + static void + validate_list(D *const *ds, size_t n) { + if (bool(ds) != bool(n)) + throw error(CL_INVALID_VALUE); + } + }; + + template + struct descriptor_traits { + typedef typename D::object_type object_type; + + static void + validate(D *d) { + if (!d || d->dispatch != &_dispatch) + throw invalid_wait_list_error(); + } + + static void + validate_list(D *const *ds, size_t n) { + if (bool(ds) != bool(n)) + throw invalid_wait_list_error(); + } + }; + } + + /// + /// Get a Clover object from an API object performing object + /// validation. + /// + /// \a T can either be the Clover object type to return or a \a tag + /// object to select some special validation behavior by means of a + /// specialization of the detail::descriptor_traits template. The + /// default behavior is to infer the most general Clover object + /// type for the given API object. + /// + template + typename detail::descriptor_traits::object_type & + obj(D *d) { + detail::descriptor_traits::validate(d); + + return static_cast< + typename detail::descriptor_traits::object_type &>(*d); + } + + /// + /// Get a pointer to a Clover object from an API object performing + /// object validation. Returns \c NULL if its argument is \c NULL. + /// + /// \sa obj + /// + template + typename detail::descriptor_traits::object_type * + pobj(D *d) { + if (d) + detail::descriptor_traits::validate(d); + + return static_cast< + typename detail::descriptor_traits::object_type *>(d); + } + + /// + /// Get an API object from a Clover object. + /// + template + typename O::descriptor_type * + desc(O &o) { + return static_cast(&o); + } + + /// + /// Get an API object from a pointer to a Clover object. + /// + template + typename O::descriptor_type * + desc(O *o) { + return static_cast(o); + } + + /// + /// Get a range of Clover objects from a range of API objects + /// performing object validation. + /// + /// \sa obj + /// + template + ref_vector::object_type> + objs(D *const *ds, size_t n) { + detail::descriptor_traits::validate_list(ds, n); + return map(obj, range(ds, n)); + } + + /// + /// Get a range of API objects from a range of Clover objects. + /// + template + std::vector + descs(const Os &os) { + return map([](typename Os::value_type &o) { + return desc(o); + }, os); + } +} + +struct _cl_context : + public clover::descriptor {}; + +struct _cl_device_id : + public clover::descriptor {}; + +struct _cl_event : + public clover::descriptor {}; + +struct _cl_kernel : + public clover::descriptor {}; + +struct _cl_mem : + public clover::descriptor {}; + +struct _cl_platform_id : + public clover::descriptor {}; + +struct _cl_program : + public clover::descriptor {}; + +struct _cl_command_queue : + public clover::descriptor {}; + +struct _cl_sampler : + public clover::descriptor {}; + +#endif diff --git a/src/gallium/frontends/clover/core/platform.cpp b/src/gallium/frontends/clover/core/platform.cpp new file mode 100644 index 00000000000..ddd63fc5a0d --- /dev/null +++ b/src/gallium/frontends/clover/core/platform.cpp @@ -0,0 +1,46 @@ +// +// Copyright 2012 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#include "core/platform.hpp" + +using namespace clover; + +platform::platform() : adaptor_range(evals(), devs) { + int n = pipe_loader_probe(NULL, 0); + std::vector ldevs(n); + + pipe_loader_probe(&ldevs.front(), n); + + for (pipe_loader_device *ldev : ldevs) { + try { + if (ldev) + devs.push_back(create(*this, ldev)); + } catch (error &) { + pipe_loader_release(&ldev, 1); + } + } +} + +std::string +platform::supported_extensions() const { + return "cl_khr_icd"; +} diff --git a/src/gallium/frontends/clover/core/platform.hpp b/src/gallium/frontends/clover/core/platform.hpp new file mode 100644 index 00000000000..b94434c983c --- /dev/null +++ b/src/gallium/frontends/clover/core/platform.hpp @@ -0,0 +1,50 @@ +// +// Copyright 2013 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#ifndef CLOVER_CORE_PLATFORM_HPP +#define CLOVER_CORE_PLATFORM_HPP + +#include + +#include "core/object.hpp" +#include "core/device.hpp" +#include "util/range.hpp" + +namespace clover { + class platform : public _cl_platform_id, + public adaptor_range< + evals, std::vector> &> { + public: + platform(); + + platform(const platform &platform) = delete; + platform & + operator=(const platform &platform) = delete; + + std::string supported_extensions() const; + + protected: + std::vector> devs; + }; +} + +#endif diff --git a/src/gallium/frontends/clover/core/program.cpp b/src/gallium/frontends/clover/core/program.cpp new file mode 100644 index 00000000000..526e06a26c3 --- /dev/null +++ b/src/gallium/frontends/clover/core/program.cpp @@ -0,0 +1,135 @@ +// +// Copyright 2012 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#include "core/compiler.hpp" +#include "core/program.hpp" + +using namespace clover; + +program::program(clover::context &ctx, const std::string &source) : + has_source(true), context(ctx), _devices(ctx.devices()), _source(source), + _kernel_ref_counter(0) { +} + +program::program(clover::context &ctx, + const ref_vector &devs, + const std::vector &binaries) : + has_source(false), context(ctx), + _devices(devs), _kernel_ref_counter(0) { + for_each([&](device &dev, const module &bin) { + _builds[&dev] = { bin }; + }, + devs, binaries); +} + +void +program::compile(const ref_vector &devs, const std::string &opts, + const header_map &headers) { + if (has_source) { + _devices = devs; + + for (auto &dev : devs) { + std::string log; + + try { + const module m = + compiler::compile_program(_source, headers, dev, opts, log); + _builds[&dev] = { m, opts, log }; + } catch (...) { + _builds[&dev] = { module(), opts, log }; + throw; + } + } + } +} + +void +program::link(const ref_vector &devs, const std::string &opts, + const ref_vector &progs) { + _devices = devs; + + for (auto &dev : devs) { + const std::vector ms = map([&](const program &prog) { + return prog.build(dev).binary; + }, progs); + std::string log = _builds[&dev].log; + + try { + const module m = compiler::link_program(ms, dev, opts, log); + _builds[&dev] = { m, opts, log }; + } catch (...) { + _builds[&dev] = { module(), opts, log }; + throw; + } + } +} + +const std::string & +program::source() const { + return _source; +} + +program::device_range +program::devices() const { + return map(evals(), _devices); +} + +cl_build_status +program::build::status() const { + if (!binary.secs.empty()) + return CL_BUILD_SUCCESS; + else if (log.size()) + return CL_BUILD_ERROR; + else + return CL_BUILD_NONE; +} + +cl_program_binary_type +program::build::binary_type() const { + if (any_of(type_equals(module::section::text_intermediate), binary.secs)) + return CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT; + else if (any_of(type_equals(module::section::text_library), binary.secs)) + return CL_PROGRAM_BINARY_TYPE_LIBRARY; + else if (any_of(type_equals(module::section::text_executable), binary.secs)) + return CL_PROGRAM_BINARY_TYPE_EXECUTABLE; + else + return CL_PROGRAM_BINARY_TYPE_NONE; +} + +const struct program::build & +program::build(const device &dev) const { + static const struct build null; + return _builds.count(&dev) ? _builds.find(&dev)->second : null; +} + +const std::vector & +program::symbols() const { + if (_builds.empty()) + throw error(CL_INVALID_PROGRAM_EXECUTABLE); + + return _builds.begin()->second.binary.syms; +} + +unsigned +program::kernel_ref_count() const { + return _kernel_ref_counter.ref_count(); +} diff --git a/src/gallium/frontends/clover/core/program.hpp b/src/gallium/frontends/clover/core/program.hpp new file mode 100644 index 00000000000..05964e78a79 --- /dev/null +++ b/src/gallium/frontends/clover/core/program.hpp @@ -0,0 +1,91 @@ +// +// Copyright 2012 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#ifndef CLOVER_CORE_PROGRAM_HPP +#define CLOVER_CORE_PROGRAM_HPP + +#include + +#include "core/object.hpp" +#include "core/context.hpp" +#include "core/module.hpp" + +namespace clover { + typedef std::vector> header_map; + + class program : public ref_counter, public _cl_program { + private: + typedef adaptor_range< + evals, const std::vector> &> device_range; + + public: + program(clover::context &ctx, + const std::string &source); + program(clover::context &ctx, + const ref_vector &devs = {}, + const std::vector &binaries = {}); + + program(const program &prog) = delete; + program & + operator=(const program &prog) = delete; + + void compile(const ref_vector &devs, const std::string &opts, + const header_map &headers = {}); + void link(const ref_vector &devs, const std::string &opts, + const ref_vector &progs); + + const bool has_source; + const std::string &source() const; + + device_range devices() const; + + struct build { + build(const module &m = {}, const std::string &opts = {}, + const std::string &log = {}) : binary(m), opts(opts), log(log) {} + + cl_build_status status() const; + cl_program_binary_type binary_type() const; + + module binary; + std::string opts; + std::string log; + }; + + const build &build(const device &dev) const; + + const std::vector &symbols() const; + + unsigned kernel_ref_count() const; + + const intrusive_ref context; + + friend class kernel; + + private: + std::vector> _devices; + std::map _builds; + std::string _source; + ref_counter _kernel_ref_counter; + }; +} + +#endif diff --git a/src/gallium/frontends/clover/core/property.hpp b/src/gallium/frontends/clover/core/property.hpp new file mode 100644 index 00000000000..7f8e17684d9 --- /dev/null +++ b/src/gallium/frontends/clover/core/property.hpp @@ -0,0 +1,261 @@ +// +// Copyright 2013 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#ifndef CLOVER_CORE_PROPERTY_HPP +#define CLOVER_CORE_PROPERTY_HPP + +#include + +#include "util/range.hpp" +#include "util/algorithm.hpp" + +namespace clover { + class property_buffer; + + namespace detail { + template + class property_scalar { + public: + property_scalar(property_buffer &buf) : buf(buf) { + } + + inline property_scalar & + operator=(const T &x); + + private: + property_buffer &buf; + }; + + template + class property_vector { + public: + property_vector(property_buffer &buf) : buf(buf) { + } + + template + inline property_vector & + operator=(const S &v); + + private: + property_buffer &buf; + }; + + template + class property_matrix { + public: + property_matrix(property_buffer &buf) : buf(buf) { + } + + template + inline property_matrix & + operator=(const S &v); + + private: + property_buffer &buf; + }; + + class property_string { + public: + property_string(property_buffer &buf) : buf(buf) { + } + + inline property_string & + operator=(const std::string &v); + + private: + property_buffer &buf; + }; + }; + + /// + /// Return value buffer used by the CL property query functions. + /// + class property_buffer { + public: + property_buffer(void *r_buf, size_t size, size_t *r_size) : + r_buf(r_buf), size(size), r_size(r_size) { + } + + template + detail::property_scalar + as_scalar() { + return { *this }; + } + + template + detail::property_vector + as_vector() { + return { *this }; + } + + template + detail::property_matrix + as_matrix() { + return { *this }; + } + + detail::property_string + as_string() { + return { *this }; + } + + template + iterator_range + allocate(size_t n) { + if (r_buf && size < n * sizeof(T)) + throw error(CL_INVALID_VALUE); + + if (r_size) + *r_size = n * sizeof(T); + + if (r_buf) + return range((T *)r_buf, n); + else + return { }; + } + + private: + void *const r_buf; + const size_t size; + size_t *const r_size; + }; + + namespace detail { + template + inline property_scalar & + property_scalar::operator=(const T &x) { + auto r = buf.allocate(1); + + if (!r.empty()) + r.front() = x; + + return *this; + } + + template + template + inline property_vector & + property_vector::operator=(const S &v) { + auto r = buf.allocate(v.size()); + + if (!r.empty()) + copy(v, r.begin()); + + return *this; + } + + template + template + inline property_matrix & + property_matrix::operator=(const S &v) { + auto r = buf.allocate(v.size()); + + if (!r.empty()) + for_each([](typename S::value_type src, T *dst) { + if (dst) + copy(src, dst); + }, v, r); + + return *this; + } + + inline property_string & + property_string::operator=(const std::string &v) { + auto r = buf.allocate(v.size() + 1); + + if (!r.empty()) + copy(range(v.begin(), r.size()), r.begin()); + + return *this; + } + }; + + template + class property_element { + public: + property_element() : x() { + } + + property_element(T x) : x(x) { + } + + template + S + as() const { + assert(sizeof(S) <= sizeof(T)); + return reinterpret_cast(x); + } + + private: + T x; + }; + + template + using property_list = std::map>; + + struct property_list_tag; + + /// + /// Create a clover::property_list object from a zero-terminated + /// CL property list. + /// + template::value>::type> + property_list + obj(const D *d_props) { + property_list props; + + while (d_props && *d_props) { + auto key = *d_props++; + auto value = *d_props++; + + if (props.count(key)) + throw error(CL_INVALID_PROPERTY); + + props.insert({ key, value }); + } + + return props; + } + + /// + /// Create a zero-terminated CL property list from a + /// clover::property_list object. + /// + template + std::vector + desc(const property_list &props) { + std::vector d_props; + + for (auto &prop : props) { + d_props.push_back(prop.first); + d_props.push_back(prop.second.template as()); + } + + d_props.push_back(0); + + return d_props; + } +} + +#endif diff --git a/src/gallium/frontends/clover/core/queue.cpp b/src/gallium/frontends/clover/core/queue.cpp new file mode 100644 index 00000000000..c91b97ad15e --- /dev/null +++ b/src/gallium/frontends/clover/core/queue.cpp @@ -0,0 +1,102 @@ +// +// Copyright 2012 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#include "core/queue.hpp" +#include "core/event.hpp" +#include "pipe/p_screen.h" +#include "pipe/p_context.h" +#include "pipe/p_state.h" + +using namespace clover; + +namespace { + void + debug_notify_callback(void *data, + unsigned *id, + enum pipe_debug_type type, + const char *fmt, + va_list args) { + const command_queue *queue = (const command_queue *)data; + char buffer[1024]; + vsnprintf(buffer, sizeof(buffer), fmt, args); + queue->context().notify(buffer); + } +} + +command_queue::command_queue(clover::context &ctx, clover::device &dev, + cl_command_queue_properties props) : + context(ctx), device(dev), props(props) { + pipe = dev.pipe->context_create(dev.pipe, NULL, PIPE_CONTEXT_COMPUTE_ONLY); + if (!pipe) + throw error(CL_INVALID_DEVICE); + + if (ctx.notify) { + struct pipe_debug_callback cb; + memset(&cb, 0, sizeof(cb)); + cb.debug_message = &debug_notify_callback; + cb.data = this; + if (pipe->set_debug_callback) + pipe->set_debug_callback(pipe, &cb); + } +} + +command_queue::~command_queue() { + pipe->destroy(pipe); +} + +void +command_queue::flush() { + pipe_screen *screen = device().pipe; + pipe_fence_handle *fence = NULL; + + std::lock_guard lock(queued_events_mutex); + if (!queued_events.empty()) { + pipe->flush(pipe, &fence, 0); + + while (!queued_events.empty() && + queued_events.front()().signalled()) { + queued_events.front()().fence(fence); + queued_events.pop_front(); + } + + screen->fence_reference(screen, &fence, NULL); + } +} + +cl_command_queue_properties +command_queue::properties() const { + return props; +} + +bool +command_queue::profiling_enabled() const { + return props & CL_QUEUE_PROFILING_ENABLE; +} + +void +command_queue::sequence(hard_event &ev) { + std::lock_guard lock(queued_events_mutex); + if (!queued_events.empty()) + queued_events.back()().chain(ev); + + queued_events.push_back(ev); +} diff --git a/src/gallium/frontends/clover/core/queue.hpp b/src/gallium/frontends/clover/core/queue.hpp new file mode 100644 index 00000000000..bddb86c0e4c --- /dev/null +++ b/src/gallium/frontends/clover/core/queue.hpp @@ -0,0 +1,78 @@ +// +// Copyright 2012 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#ifndef CLOVER_CORE_QUEUE_HPP +#define CLOVER_CORE_QUEUE_HPP + +#include +#include + +#include "core/object.hpp" +#include "core/context.hpp" +#include "core/timestamp.hpp" +#include "pipe/p_context.h" + +namespace clover { + class resource; + class mapping; + class hard_event; + + class command_queue : public ref_counter, public _cl_command_queue { + public: + command_queue(clover::context &ctx, clover::device &dev, + cl_command_queue_properties props); + ~command_queue(); + + command_queue(const command_queue &q) = delete; + command_queue & + operator=(const command_queue &q) = delete; + + void flush(); + + cl_command_queue_properties properties() const; + bool profiling_enabled() const; + + const intrusive_ref context; + const intrusive_ref device; + + friend class resource; + friend class root_resource; + friend class mapping; + friend class hard_event; + friend class sampler; + friend class kernel; + friend class clover::timestamp::query; + friend class clover::timestamp::current; + + private: + /// Serialize a hardware event with respect to the previous ones, + /// and push it to the pending list. + void sequence(hard_event &ev); + + cl_command_queue_properties props; + pipe_context *pipe; + std::mutex queued_events_mutex; + std::deque> queued_events; + }; +} + +#endif diff --git a/src/gallium/frontends/clover/core/resource.cpp b/src/gallium/frontends/clover/core/resource.cpp new file mode 100644 index 00000000000..dd207982588 --- /dev/null +++ b/src/gallium/frontends/clover/core/resource.cpp @@ -0,0 +1,231 @@ +// +// Copyright 2012 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#include "core/resource.hpp" +#include "core/memory.hpp" +#include "pipe/p_screen.h" +#include "util/u_sampler.h" +#include "util/format/u_format.h" +#include "util/u_inlines.h" + +using namespace clover; + +namespace { + class box { + public: + box(const resource::vector &origin, const resource::vector &size) : + pipe({ (int)origin[0], (int16_t)origin[1], + (int16_t)origin[2], (int)size[0], + (int16_t)size[1], (int16_t)size[2] }) { + } + + operator const pipe_box *() { + return &pipe; + } + + protected: + pipe_box pipe; + }; +} + +resource::resource(clover::device &dev, memory_obj &obj) : + device(dev), obj(obj), pipe(NULL), offset() { +} + +resource::~resource() { +} + +void +resource::copy(command_queue &q, const vector &origin, const vector ®ion, + resource &src_res, const vector &src_origin) { + auto p = offset + origin; + + q.pipe->resource_copy_region(q.pipe, pipe, 0, p[0], p[1], p[2], + src_res.pipe, 0, + box(src_res.offset + src_origin, region)); +} + +void * +resource::add_map(command_queue &q, cl_map_flags flags, bool blocking, + const vector &origin, const vector ®ion) { + maps.emplace_back(q, *this, flags, blocking, origin, region); + return maps.back(); +} + +void +resource::del_map(void *p) { + erase_if([&](const mapping &m) { + return static_cast(m) == p; + }, maps); +} + +unsigned +resource::map_count() const { + return maps.size(); +} + +pipe_sampler_view * +resource::bind_sampler_view(command_queue &q) { + pipe_sampler_view info; + + u_sampler_view_default_template(&info, pipe, pipe->format); + return q.pipe->create_sampler_view(q.pipe, pipe, &info); +} + +void +resource::unbind_sampler_view(command_queue &q, + pipe_sampler_view *st) { + q.pipe->sampler_view_destroy(q.pipe, st); +} + +pipe_surface * +resource::bind_surface(command_queue &q, bool rw) { + pipe_surface info {}; + + info.format = pipe->format; + info.writable = rw; + + if (pipe->target == PIPE_BUFFER) + info.u.buf.last_element = pipe->width0 - 1; + + return q.pipe->create_surface(q.pipe, pipe, &info); +} + +void +resource::unbind_surface(command_queue &q, pipe_surface *st) { + q.pipe->surface_destroy(q.pipe, st); +} + +root_resource::root_resource(clover::device &dev, memory_obj &obj, + command_queue &q, const std::string &data) : + resource(dev, obj) { + pipe_resource info {}; + const bool user_ptr_support = dev.pipe->get_param(dev.pipe, + PIPE_CAP_RESOURCE_FROM_USER_MEMORY); + + if (image *img = dynamic_cast(&obj)) { + info.format = translate_format(img->format()); + info.width0 = img->width(); + info.height0 = img->height(); + info.depth0 = img->depth(); + } else { + info.width0 = obj.size(); + info.height0 = 1; + info.depth0 = 1; + } + + info.array_size = 1; + info.target = translate_target(obj.type()); + info.bind = (PIPE_BIND_SAMPLER_VIEW | + PIPE_BIND_COMPUTE_RESOURCE | + PIPE_BIND_GLOBAL); + + if (obj.flags() & CL_MEM_USE_HOST_PTR && user_ptr_support) { + // Page alignment is normally required for this, just try, hope for the + // best and fall back if it fails. + pipe = dev.pipe->resource_from_user_memory(dev.pipe, &info, obj.host_ptr()); + if (pipe) + return; + } + + if (obj.flags() & (CL_MEM_ALLOC_HOST_PTR | CL_MEM_USE_HOST_PTR)) { + info.usage = PIPE_USAGE_STAGING; + } + + pipe = dev.pipe->resource_create(dev.pipe, &info); + if (!pipe) + throw error(CL_OUT_OF_RESOURCES); + + if (obj.flags() & (CL_MEM_USE_HOST_PTR | CL_MEM_COPY_HOST_PTR)) { + const void *data_ptr = !data.empty() ? data.data() : obj.host_ptr(); + box rect { {{ 0, 0, 0 }}, {{ info.width0, info.height0, info.depth0 }} }; + unsigned cpp = util_format_get_blocksize(info.format); + + if (pipe->target == PIPE_BUFFER) + q.pipe->buffer_subdata(q.pipe, pipe, PIPE_TRANSFER_WRITE, + 0, info.width0, data_ptr); + else + q.pipe->texture_subdata(q.pipe, pipe, 0, PIPE_TRANSFER_WRITE, + rect, data_ptr, cpp * info.width0, + cpp * info.width0 * info.height0); + } +} + +root_resource::root_resource(clover::device &dev, memory_obj &obj, + root_resource &r) : + resource(dev, obj) { + assert(0); // XXX -- resource shared among dev and r.dev +} + +root_resource::~root_resource() { + pipe_resource_reference(&this->pipe, NULL); +} + +sub_resource::sub_resource(resource &r, const vector &offset) : + resource(r.device(), r.obj) { + this->pipe = r.pipe; + this->offset = r.offset + offset; +} + +mapping::mapping(command_queue &q, resource &r, + cl_map_flags flags, bool blocking, + const resource::vector &origin, + const resource::vector ®ion) : + pctx(q.pipe), pres(NULL) { + unsigned usage = ((flags & CL_MAP_WRITE ? PIPE_TRANSFER_WRITE : 0 ) | + (flags & CL_MAP_READ ? PIPE_TRANSFER_READ : 0 ) | + (flags & CL_MAP_WRITE_INVALIDATE_REGION ? + PIPE_TRANSFER_DISCARD_RANGE : 0) | + (!blocking ? PIPE_TRANSFER_UNSYNCHRONIZED : 0)); + + p = pctx->transfer_map(pctx, r.pipe, 0, usage, + box(origin + r.offset, region), &pxfer); + if (!p) { + pxfer = NULL; + throw error(CL_OUT_OF_RESOURCES); + } + pipe_resource_reference(&pres, r.pipe); +} + +mapping::mapping(mapping &&m) : + pctx(m.pctx), pxfer(m.pxfer), pres(m.pres), p(m.p) { + m.pctx = NULL; + m.pxfer = NULL; + m.pres = NULL; + m.p = NULL; +} + +mapping::~mapping() { + if (pxfer) { + pctx->transfer_unmap(pctx, pxfer); + } + pipe_resource_reference(&pres, NULL); +} + +mapping & +mapping::operator=(mapping m) { + std::swap(pctx, m.pctx); + std::swap(pxfer, m.pxfer); + std::swap(pres, m.pres); + std::swap(p, m.p); + return *this; +} diff --git a/src/gallium/frontends/clover/core/resource.hpp b/src/gallium/frontends/clover/core/resource.hpp new file mode 100644 index 00000000000..3b994b4008b --- /dev/null +++ b/src/gallium/frontends/clover/core/resource.hpp @@ -0,0 +1,133 @@ +// +// Copyright 2012 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#ifndef CLOVER_CORE_RESOURCE_HPP +#define CLOVER_CORE_RESOURCE_HPP + +#include + +#include "core/queue.hpp" +#include "util/algebra.hpp" +#include "pipe/p_state.h" + +namespace clover { + class memory_obj; + class mapping; + + /// + /// Class that represents a device-specific instance of some memory + /// object. + /// + class resource { + public: + typedef std::array vector; + + virtual ~resource(); + + resource(const resource &r) = delete; + resource & + operator=(const resource &r) = delete; + + void copy(command_queue &q, const vector &origin, const vector ®ion, + resource &src_resource, const vector &src_origin); + + void *add_map(command_queue &q, cl_map_flags flags, bool blocking, + const vector &origin, const vector ®ion); + void del_map(void *p); + unsigned map_count() const; + + const intrusive_ref device; + memory_obj &obj; + + friend class sub_resource; + friend class mapping; + friend class kernel; + + protected: + resource(clover::device &dev, memory_obj &obj); + + pipe_sampler_view *bind_sampler_view(command_queue &q); + void unbind_sampler_view(command_queue &q, + pipe_sampler_view *st); + + pipe_surface *bind_surface(command_queue &q, bool rw); + void unbind_surface(command_queue &q, pipe_surface *st); + + pipe_resource *pipe; + vector offset; + + private: + std::list maps; + }; + + /// + /// Resource associated with its own top-level data storage + /// allocated in some device. + /// + class root_resource : public resource { + public: + root_resource(clover::device &dev, memory_obj &obj, + command_queue &q, const std::string &data); + root_resource(clover::device &dev, memory_obj &obj, root_resource &r); + virtual ~root_resource(); + }; + + /// + /// Resource that reuses a portion of some other resource as data + /// storage. + /// + class sub_resource : public resource { + public: + sub_resource(resource &r, const vector &offset); + }; + + /// + /// Class that represents a mapping of some resource into the CPU + /// memory space. + /// + class mapping { + public: + mapping(command_queue &q, resource &r, cl_map_flags flags, + bool blocking, const resource::vector &origin, + const resource::vector ®ion); + mapping(mapping &&m); + ~mapping(); + + mapping & + operator=(mapping m); + + mapping(const mapping &m) = delete; + + template + operator T *() const { + return (T *)p; + } + + private: + pipe_context *pctx; + pipe_transfer *pxfer; + pipe_resource *pres; + void *p; + }; +} + +#endif diff --git a/src/gallium/frontends/clover/core/sampler.cpp b/src/gallium/frontends/clover/core/sampler.cpp new file mode 100644 index 00000000000..6f2784b538e --- /dev/null +++ b/src/gallium/frontends/clover/core/sampler.cpp @@ -0,0 +1,73 @@ +// +// Copyright 2012 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#include "core/sampler.hpp" +#include "pipe/p_state.h" + +using namespace clover; + +sampler::sampler(clover::context &ctx, bool norm_mode, + cl_addressing_mode addr_mode, + cl_filter_mode filter_mode) : + context(ctx), _norm_mode(norm_mode), + _addr_mode(addr_mode), _filter_mode(filter_mode) { +} + +bool +sampler::norm_mode() { + return _norm_mode; +} + +cl_addressing_mode +sampler::addr_mode() { + return _addr_mode; +} + +cl_filter_mode +sampler::filter_mode() { + return _filter_mode; +} + +void * +sampler::bind(command_queue &q) { + struct pipe_sampler_state info {}; + + info.normalized_coords = norm_mode(); + + info.wrap_s = info.wrap_t = info.wrap_r = + (addr_mode() == CL_ADDRESS_CLAMP_TO_EDGE ? PIPE_TEX_WRAP_CLAMP_TO_EDGE : + addr_mode() == CL_ADDRESS_CLAMP ? PIPE_TEX_WRAP_CLAMP_TO_BORDER : + addr_mode() == CL_ADDRESS_REPEAT ? PIPE_TEX_WRAP_REPEAT : + addr_mode() == CL_ADDRESS_MIRRORED_REPEAT ? PIPE_TEX_WRAP_MIRROR_REPEAT : + PIPE_TEX_WRAP_CLAMP_TO_EDGE); + + info.min_img_filter = info.mag_img_filter = + (filter_mode() == CL_FILTER_LINEAR ? PIPE_TEX_FILTER_LINEAR : + PIPE_TEX_FILTER_NEAREST); + + return q.pipe->create_sampler_state(q.pipe, &info); +} + +void +sampler::unbind(command_queue &q, void *st) { + q.pipe->delete_sampler_state(q.pipe, st); +} diff --git a/src/gallium/frontends/clover/core/sampler.hpp b/src/gallium/frontends/clover/core/sampler.hpp new file mode 100644 index 00000000000..2632c3067fa --- /dev/null +++ b/src/gallium/frontends/clover/core/sampler.hpp @@ -0,0 +1,58 @@ +// +// Copyright 2012 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#ifndef CLOVER_CORE_SAMPLER_HPP +#define CLOVER_CORE_SAMPLER_HPP + +#include "core/object.hpp" +#include "core/queue.hpp" + +namespace clover { + class sampler : public ref_counter, public _cl_sampler { + public: + sampler(clover::context &ctx, bool norm_mode, + cl_addressing_mode addr_mode, + cl_filter_mode filter_mode); + + sampler(const sampler &s) = delete; + sampler & + operator=(const sampler &s) = delete; + + bool norm_mode(); + cl_addressing_mode addr_mode(); + cl_filter_mode filter_mode(); + + const intrusive_ref context; + + friend class kernel; + + private: + void *bind(command_queue &q); + void unbind(command_queue &q, void *st); + + bool _norm_mode; + cl_addressing_mode _addr_mode; + cl_filter_mode _filter_mode; + }; +} + +#endif diff --git a/src/gallium/frontends/clover/core/timestamp.cpp b/src/gallium/frontends/clover/core/timestamp.cpp new file mode 100644 index 00000000000..3fd341f30da --- /dev/null +++ b/src/gallium/frontends/clover/core/timestamp.cpp @@ -0,0 +1,64 @@ +// +// Copyright 2013 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#include "core/timestamp.hpp" +#include "core/queue.hpp" +#include "pipe/p_screen.h" +#include "pipe/p_context.h" + +using namespace clover; + +timestamp::query::query(command_queue &q) : + q(q), + _query(q.pipe->create_query(q.pipe, PIPE_QUERY_TIMESTAMP, 0)) { + q.pipe->end_query(q.pipe, _query); +} + +timestamp::query::query(query &&other) : + q(other.q), + _query(other._query) { + other._query = NULL; +} + +timestamp::query::~query() { + if (_query) + q().pipe->destroy_query(q().pipe, _query); +} + +cl_ulong +timestamp::query::operator()() const { + pipe_query_result result; + + if (!q().pipe->get_query_result(q().pipe, _query, false, &result)) + throw error(CL_PROFILING_INFO_NOT_AVAILABLE); + + return result.u64; +} + +timestamp::current::current(command_queue &q) : + result(q.pipe->screen->get_timestamp(q.pipe->screen)) { +} + +cl_ulong +timestamp::current::operator()() const { + return result; +} diff --git a/src/gallium/frontends/clover/core/timestamp.hpp b/src/gallium/frontends/clover/core/timestamp.hpp new file mode 100644 index 00000000000..b4b2c83eb92 --- /dev/null +++ b/src/gallium/frontends/clover/core/timestamp.hpp @@ -0,0 +1,74 @@ +// +// Copyright 2013 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#ifndef CLOVER_CORE_TIMESTAMP_HPP +#define CLOVER_CORE_TIMESTAMP_HPP + +#include "core/object.hpp" + +struct pipe_query; + +namespace clover { + class command_queue; + + namespace timestamp { + /// + /// Emit a timestamp query that is executed asynchronously by + /// the command queue \a q. + /// + class query { + public: + query(command_queue &q); + query(query &&other); + ~query(); + + query &operator=(const query &) = delete; + + /// + /// Retrieve the query results. + /// + cl_ulong operator()() const; + + private: + const intrusive_ref q; + pipe_query *_query; + }; + + /// + /// Get the current timestamp value. + /// + class current { + public: + current(command_queue &q); + + /// + /// Retrieve the query results. + /// + cl_ulong operator()() const; + + private: + cl_ulong result; + }; + } +} + +#endif diff --git a/src/gallium/frontends/clover/llvm/codegen.hpp b/src/gallium/frontends/clover/llvm/codegen.hpp new file mode 100644 index 00000000000..e35627c4729 --- /dev/null +++ b/src/gallium/frontends/clover/llvm/codegen.hpp @@ -0,0 +1,68 @@ +// +// Copyright 2016 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +/// +/// \file +/// Tools to generate various forms of binary code from existing LLVM IR in +/// the given llvm::Module object and output the result as a clover::module. +/// + +#ifndef CLOVER_LLVM_CODEGEN_HPP +#define CLOVER_LLVM_CODEGEN_HPP + +#include "llvm/util.hpp" +#include "core/module.hpp" + +#include + +#include + +namespace clover { + namespace llvm { + std::string + print_module_bitcode(const ::llvm::Module &mod); + + module + build_module_library(const ::llvm::Module &mod, + enum module::section::type section_type); + + std::unique_ptr< ::llvm::Module> + parse_module_library(const module &m, ::llvm::LLVMContext &ctx, + std::string &r_log); + + module + build_module_native(::llvm::Module &mod, const target &target, + const clang::CompilerInstance &c, + std::string &r_log); + + std::string + print_module_native(const ::llvm::Module &mod, const target &target); + + module + build_module_common(const ::llvm::Module &mod, + const std::vector &code, + const std::map &offsets, + const clang::CompilerInstance &c); + } +} + +#endif diff --git a/src/gallium/frontends/clover/llvm/codegen/bitcode.cpp b/src/gallium/frontends/clover/llvm/codegen/bitcode.cpp new file mode 100644 index 00000000000..7434e8cf6c9 --- /dev/null +++ b/src/gallium/frontends/clover/llvm/codegen/bitcode.cpp @@ -0,0 +1,91 @@ +// +// Copyright 2012-2016 Francisco Jerez +// Copyright 2012-2016 Advanced Micro Devices, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +/// +/// \file +/// Trivial codegen back-end that simply passes through the existing LLVM IR +/// and either formats it so it can be consumed by pipe drivers (if +/// build_module_bitcode() is used) or serializes so it can be deserialized at +/// a later point and passed to the actual codegen back-end (if +/// build_module_library() / parse_module_library() is used), potentially +/// after linking against other bitcode object files. +/// + +#include "llvm/codegen.hpp" +#include "llvm/compat.hpp" +#include "llvm/metadata.hpp" +#include "core/error.hpp" +#include "util/algorithm.hpp" + +#include +#include +#if LLVM_VERSION_MAJOR < 4 +#include +#else +#include +#include +#endif +#include + +using namespace clover; +using namespace clover::llvm; + +namespace { + std::vector + emit_code(const ::llvm::Module &mod) { + ::llvm::SmallVector data; + ::llvm::raw_svector_ostream os { data }; + compat::write_bitcode_to_file(mod, os); + return { os.str().begin(), os.str().end() }; + } +} + +std::string +clover::llvm::print_module_bitcode(const ::llvm::Module &mod) { + std::string s; + ::llvm::raw_string_ostream os { s }; + mod.print(os, NULL); + return os.str(); +} + +module +clover::llvm::build_module_library(const ::llvm::Module &mod, + enum module::section::type section_type) { + module m; + const auto code = emit_code(mod); + m.secs.emplace_back(0, section_type, code.size(), code); + return m; +} + +std::unique_ptr< ::llvm::Module> +clover::llvm::parse_module_library(const module &m, ::llvm::LLVMContext &ctx, + std::string &r_log) { + auto mod = ::llvm::parseBitcodeFile(::llvm::MemoryBufferRef( + as_string(m.secs[0].data), " "), ctx); + + compat::handle_module_error(mod, [&](const std::string &s) { + fail(r_log, error(CL_INVALID_PROGRAM), s); + }); + + return std::unique_ptr< ::llvm::Module>(std::move(*mod)); +} diff --git a/src/gallium/frontends/clover/llvm/codegen/common.cpp b/src/gallium/frontends/clover/llvm/codegen/common.cpp new file mode 100644 index 00000000000..730ba5a2ff7 --- /dev/null +++ b/src/gallium/frontends/clover/llvm/codegen/common.cpp @@ -0,0 +1,209 @@ +// +// Copyright 2012-2016 Francisco Jerez +// Copyright 2012-2016 Advanced Micro Devices, Inc. +// Copyright 2015 Zoltan Gilian +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +/// +/// \file +/// Codegen back-end-independent part of the construction of an executable +/// clover::module, including kernel argument metadata extraction and +/// formatting of the pre-generated binary code in a form that can be +/// understood by pipe drivers. +/// + +#include "llvm/codegen.hpp" +#include "llvm/metadata.hpp" + +#include "CL/cl.h" + +#include "pipe/p_state.h" +#include "util/u_math.h" + +#include + +using namespace clover; +using namespace clover::llvm; + +using ::llvm::Module; +using ::llvm::Function; +using ::llvm::Type; +using ::llvm::isa; +using ::llvm::cast; +using ::llvm::dyn_cast; + +namespace { + enum module::argument::type + get_image_type(const std::string &type, + const std::string &qual) { + if (type == "image2d_t" && qual == "read_only") + return module::argument::image2d_rd; + else if (type == "image2d_t" && qual == "write_only") + return module::argument::image2d_wr; + else if (type == "image3d_t" && qual == "read_only") + return module::argument::image3d_rd; + else if (type == "image3d_t" && qual == "write_only") + return module::argument::image3d_wr; + else + unreachable("Unknown image type"); + } + + std::vector + make_kernel_args(const Module &mod, const std::string &kernel_name, + const clang::CompilerInstance &c) { + std::vector args; + const Function &f = *mod.getFunction(kernel_name); + ::llvm::DataLayout dl(&mod); + const auto size_type = + dl.getSmallestLegalIntType(mod.getContext(), sizeof(cl_uint) * 8); + + for (const auto &arg : f.args()) { + const auto arg_type = arg.getType(); + + // OpenCL 1.2 specification, Ch. 6.1.5: "A built-in data + // type that is not a power of two bytes in size must be + // aligned to the next larger power of two. + // This rule applies to built-in types only, not structs or unions." + const unsigned arg_store_size = dl.getTypeStoreSize(arg_type); + const unsigned arg_api_size = dl.getTypeAllocSize(arg_type); + + const auto target_type = compat::get_abi_type(arg_type, mod); + const unsigned target_size = dl.getTypeStoreSize(target_type); + const unsigned target_align = dl.getABITypeAlignment(target_type); + + const auto type_name = get_argument_metadata(f, arg, + "kernel_arg_type"); + + if (type_name == "image2d_t" || type_name == "image3d_t") { + // Image. + const auto access_qual = get_argument_metadata( + f, arg, "kernel_arg_access_qual"); + args.emplace_back(get_image_type(type_name, access_qual), + arg_store_size, target_size, + target_align, module::argument::zero_ext); + + } else if (type_name == "__llvm_image_size") { + // Image size implicit argument. + args.emplace_back(module::argument::scalar, sizeof(cl_uint), + dl.getTypeStoreSize(size_type), + dl.getABITypeAlignment(size_type), + module::argument::zero_ext, + module::argument::image_size); + + } else if (type_name == "__llvm_image_format") { + // Image format implicit argument. + args.emplace_back(module::argument::scalar, sizeof(cl_uint), + dl.getTypeStoreSize(size_type), + dl.getABITypeAlignment(size_type), + module::argument::zero_ext, + module::argument::image_format); + + } else { + // Other types. + const auto actual_type = + isa< ::llvm::PointerType>(arg_type) && arg.hasByValAttr() ? + cast< ::llvm::PointerType>(arg_type)->getElementType() : arg_type; + + if (actual_type->isPointerTy()) { + const unsigned address_space = + cast< ::llvm::PointerType>(actual_type)->getAddressSpace(); + + if (address_space == compat::target_address_space( + c.getTarget(), clang::LangAS::opencl_local)) { + args.emplace_back(module::argument::local, arg_api_size, + target_size, target_align, + module::argument::zero_ext); + } else { + // XXX: Correctly handle constant address space. There is no + // way for r600g to pass a handle for constant buffers back + // to clover like it can for global buffers, so + // creating constant arguments will break r600g. For now, + // continue treating constant buffers as global buffers + // until we can come up with a way to create handles for + // constant buffers. + args.emplace_back(module::argument::global, arg_api_size, + target_size, target_align, + module::argument::zero_ext); + } + + } else { + const bool needs_sign_ext = f.getAttributes().hasAttribute( + arg.getArgNo() + 1, ::llvm::Attribute::SExt); + + args.emplace_back(module::argument::scalar, arg_api_size, + target_size, target_align, + (needs_sign_ext ? module::argument::sign_ext : + module::argument::zero_ext)); + } + } + } + + // Append implicit arguments. XXX - The types, ordering and + // vector size of the implicit arguments should depend on the + // target according to the selected calling convention. + args.emplace_back(module::argument::scalar, sizeof(cl_uint), + dl.getTypeStoreSize(size_type), + dl.getABITypeAlignment(size_type), + module::argument::zero_ext, + module::argument::grid_dimension); + + args.emplace_back(module::argument::scalar, sizeof(cl_uint), + dl.getTypeStoreSize(size_type), + dl.getABITypeAlignment(size_type), + module::argument::zero_ext, + module::argument::grid_offset); + + return args; + } + + module::section + make_text_section(const std::vector &code) { + const pipe_binary_program_header header { uint32_t(code.size()) }; + module::section text { 0, module::section::text_executable, + header.num_bytes, {} }; + + text.data.insert(text.data.end(), reinterpret_cast(&header), + reinterpret_cast(&header) + sizeof(header)); + text.data.insert(text.data.end(), code.begin(), code.end()); + + return text; + } +} + +module +clover::llvm::build_module_common(const Module &mod, + const std::vector &code, + const std::map &offsets, + const clang::CompilerInstance &c) { + module m; + + for (const auto &llvm_name : map(std::mem_fn(&Function::getName), + get_kernels(mod))) { + const ::std::string name(llvm_name); + if (offsets.count(name)) + m.syms.emplace_back(name, 0, offsets.at(name), + make_kernel_args(mod, name, c)); + } + + m.secs.push_back(make_text_section(code)); + return m; +} diff --git a/src/gallium/frontends/clover/llvm/codegen/native.cpp b/src/gallium/frontends/clover/llvm/codegen/native.cpp new file mode 100644 index 00000000000..52346131200 --- /dev/null +++ b/src/gallium/frontends/clover/llvm/codegen/native.cpp @@ -0,0 +1,163 @@ +// +// Copyright 2012-2016 Francisco Jerez +// Copyright 2012-2016 Advanced Micro Devices, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +/// +/// \file +/// Generate code using an arbitrary LLVM back-end capable of emitting +/// executable code as an ELF object file. +/// + +#include "llvm/codegen.hpp" +#include "llvm/compat.hpp" +#include "llvm/util.hpp" +#include "core/error.hpp" + +#include +#include +#include + +#include +#include + +using namespace clover; +using namespace clover::llvm; +using ::llvm::TargetMachine; + +namespace { + namespace elf { + std::unique_ptr + get(const std::vector &code) { + // One of the libelf implementations + // (http://www.mr511.de/software/english.htm) requires calling + // elf_version() before elf_memory(). + elf_version(EV_CURRENT); + return { elf_memory(const_cast(code.data()), code.size()), + elf_end }; + } + + Elf_Scn * + get_symbol_table(Elf *elf) { + size_t section_str_index; + elf_getshdrstrndx(elf, §ion_str_index); + + for (Elf_Scn *s = elf_nextscn(elf, NULL); s; s = elf_nextscn(elf, s)) { + GElf_Shdr header; + if (gelf_getshdr(s, &header) != &header) + return nullptr; + + if (!std::strcmp(elf_strptr(elf, section_str_index, header.sh_name), + ".symtab")) + return s; + } + + return nullptr; + } + + std::map + get_symbol_offsets(Elf *elf, Elf_Scn *symtab) { + Elf_Data *const symtab_data = elf_getdata(symtab, NULL); + GElf_Shdr header; + if (gelf_getshdr(symtab, &header) != &header) + return {}; + + std::map symbol_offsets; + GElf_Sym symbol; + unsigned i = 0; + + while (GElf_Sym *s = gelf_getsym(symtab_data, i++, &symbol)) { + const char *name = elf_strptr(elf, header.sh_link, s->st_name); + symbol_offsets[name] = s->st_value; + } + + return symbol_offsets; + } + } + + std::map + get_symbol_offsets(const std::vector &code, std::string &r_log) { + const auto elf = elf::get(code); + const auto symtab = elf::get_symbol_table(elf.get()); + if (!symtab) + fail(r_log, build_error(), "Unable to find symbol table."); + + return elf::get_symbol_offsets(elf.get(), symtab); + } + + std::vector + emit_code(::llvm::Module &mod, const target &target, + compat::CodeGenFileType ft, + std::string &r_log) { + std::string err; + auto t = ::llvm::TargetRegistry::lookupTarget(target.triple, err); + if (!t) + fail(r_log, build_error(), err); + + std::unique_ptr tm { + t->createTargetMachine(target.triple, target.cpu, "", {}, + ::llvm::None, compat::default_code_model, + ::llvm::CodeGenOpt::Default) }; + if (!tm) + fail(r_log, build_error(), + "Could not create TargetMachine: " + target.triple); + + ::llvm::SmallVector data; + + { + ::llvm::legacy::PassManager pm; + ::llvm::raw_svector_ostream os { data }; + + mod.setDataLayout(tm->createDataLayout()); + tm->Options.MCOptions.AsmVerbose = + (ft == compat::CGFT_AssemblyFile); + + if (compat::add_passes_to_emit_file(*tm, pm, os, ft)) + fail(r_log, build_error(), "TargetMachine can't emit this file"); + + pm.run(mod); + } + + return { data.begin(), data.end() }; + } +} + +module +clover::llvm::build_module_native(::llvm::Module &mod, const target &target, + const clang::CompilerInstance &c, + std::string &r_log) { + const auto code = emit_code(mod, target, + compat::CGFT_ObjectFile, r_log); + return build_module_common(mod, code, get_symbol_offsets(code, r_log), c); +} + +std::string +clover::llvm::print_module_native(const ::llvm::Module &mod, + const target &target) { + std::string log; + try { + std::unique_ptr< ::llvm::Module> cmod { compat::clone_module(mod) }; + return as_string(emit_code(*cmod, target, + compat::CGFT_AssemblyFile, log)); + } catch (...) { + return "Couldn't output native disassembly: " + log; + } +} diff --git a/src/gallium/frontends/clover/llvm/compat.hpp b/src/gallium/frontends/clover/llvm/compat.hpp new file mode 100644 index 00000000000..51902739acc --- /dev/null +++ b/src/gallium/frontends/clover/llvm/compat.hpp @@ -0,0 +1,216 @@ +// +// Copyright 2016 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +/// +/// \file +/// Some thin wrappers around the Clang/LLVM API used to preserve +/// compatibility with older API versions while keeping the ifdef clutter low +/// in the rest of the clover::llvm subtree. In case of an API break please +/// consider whether it's possible to preserve backwards compatibility by +/// introducing a new one-liner inline function or typedef here under the +/// compat namespace in order to keep the running code free from preprocessor +/// conditionals. +/// + +#ifndef CLOVER_LLVM_COMPAT_HPP +#define CLOVER_LLVM_COMPAT_HPP + +#include "util/algorithm.hpp" + +#include +#if LLVM_VERSION_MAJOR < 4 +#include +#else +#include +#include +#endif + +#include +#include +#include +#include +#include +#if LLVM_VERSION_MAJOR >= 4 +#include +#else +#include +#endif + +#include +#include + +#include +#include + +#if LLVM_VERSION_MAJOR >= 8 +#include +#else +#include +#endif + +#if LLVM_VERSION_MAJOR >= 10 +#include +#endif + +namespace clover { + namespace llvm { + namespace compat { + +#if LLVM_VERSION_MAJOR >= 10 + const auto CGFT_ObjectFile = ::llvm::CGFT_ObjectFile; + const auto CGFT_AssemblyFile = ::llvm::CGFT_AssemblyFile; + typedef ::llvm::CodeGenFileType CodeGenFileType; +#else + const auto CGFT_ObjectFile = ::llvm::TargetMachine::CGFT_ObjectFile; + const auto CGFT_AssemblyFile = + ::llvm::TargetMachine::CGFT_AssemblyFile; + typedef ::llvm::TargetMachine::CodeGenFileType CodeGenFileType; +#endif + + template + unsigned target_address_space(const T &target, const AS lang_as) { + const auto &map = target.getAddressSpaceMap(); +#if LLVM_VERSION_MAJOR >= 5 + return map[static_cast(lang_as)]; +#else + return map[lang_as - clang::LangAS::Offset]; +#endif + } + +#if LLVM_VERSION_MAJOR >= 10 + const clang::InputKind ik_opencl = clang::Language::OpenCL; +#elif LLVM_VERSION_MAJOR >= 5 + const clang::InputKind ik_opencl = clang::InputKind::OpenCL; +#else + const clang::InputKind ik_opencl = clang::IK_OpenCL; +#endif + +#if LLVM_VERSION_MAJOR >= 5 + const clang::LangStandard::Kind lang_opencl10 = clang::LangStandard::lang_opencl10; +#else + const clang::LangStandard::Kind lang_opencl10 = clang::LangStandard::lang_opencl; +#endif + + inline void + add_link_bitcode_file(clang::CodeGenOptions &opts, + const std::string &path) { +#if LLVM_VERSION_MAJOR >= 5 + clang::CodeGenOptions::BitcodeFileToLink F; + + F.Filename = path; + F.PropagateAttrs = true; + F.LinkFlags = ::llvm::Linker::Flags::None; + opts.LinkBitcodeFiles.emplace_back(F); +#else + opts.LinkBitcodeFiles.emplace_back(::llvm::Linker::Flags::None, path); +#endif + } + +#if LLVM_VERSION_MAJOR >= 6 + const auto default_code_model = ::llvm::None; +#else + const auto default_code_model = ::llvm::CodeModel::Default; +#endif + + template void + handle_module_error(M &mod, const F &f) { +#if LLVM_VERSION_MAJOR >= 4 + if (::llvm::Error err = mod.takeError()) + ::llvm::handleAllErrors(std::move(err), [&](::llvm::ErrorInfoBase &eib) { + f(eib.message()); + }); +#else + if (!mod) + f(mod.getError().message()); +#endif + } + + template void + set_diagnostic_handler(::llvm::LLVMContext &ctx, + T *diagnostic_handler, void *data) { +#if LLVM_VERSION_MAJOR >= 6 + ctx.setDiagnosticHandlerCallBack(diagnostic_handler, data); +#else + ctx.setDiagnosticHandler(diagnostic_handler, data); +#endif + } + + inline std::unique_ptr< ::llvm::Module> + clone_module(const ::llvm::Module &mod) + { +#if LLVM_VERSION_MAJOR >= 7 + return ::llvm::CloneModule(mod); +#else + return ::llvm::CloneModule(&mod); +#endif + } + + template void + write_bitcode_to_file(const ::llvm::Module &mod, T &os) + { +#if LLVM_VERSION_MAJOR >= 7 + ::llvm::WriteBitcodeToFile(mod, os); +#else + ::llvm::WriteBitcodeToFile(&mod, os); +#endif + } + + template + bool add_passes_to_emit_file(TM &tm, PM &pm, OS &os, FT &ft) + { +#if LLVM_VERSION_MAJOR >= 7 + return tm.addPassesToEmitFile(pm, os, nullptr, ft); +#else + return tm.addPassesToEmitFile(pm, os, ft); +#endif + } + + template inline bool + create_compiler_invocation_from_args(clang::CompilerInvocation &cinv, + T copts, + clang::DiagnosticsEngine &diag) + { +#if LLVM_VERSION_MAJOR >= 10 + return clang::CompilerInvocation::CreateFromArgs( + cinv, copts, diag); +#else + return clang::CompilerInvocation::CreateFromArgs( + cinv, copts.data(), copts.data() + copts.size(), diag); +#endif + } + + template + T get_abi_type(const T &arg_type, const M &mod) { +#if LLVM_VERSION_MAJOR >= 7 + return arg_type; +#else + ::llvm::DataLayout dl(&mod); + const unsigned arg_store_size = dl.getTypeStoreSize(arg_type); + return !arg_type->isIntegerTy() ? arg_type : + dl.getSmallestLegalIntType(mod.getContext(), arg_store_size * 8); +#endif + } + } + } +} + +#endif diff --git a/src/gallium/frontends/clover/llvm/invocation.cpp b/src/gallium/frontends/clover/llvm/invocation.cpp new file mode 100644 index 00000000000..95a9d036622 --- /dev/null +++ b/src/gallium/frontends/clover/llvm/invocation.cpp @@ -0,0 +1,465 @@ +// +// Copyright 2012-2016 Francisco Jerez +// Copyright 2012-2016 Advanced Micro Devices, Inc. +// Copyright 2014-2016 Jan Vesely +// Copyright 2014-2015 Serge Martin +// Copyright 2015 Zoltan Gilian +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#include +#include +#include +#include +#include +#include +#ifdef HAVE_CLOVER_SPIRV +#include +#endif + +#include +#include +#include +#include +#include + +// We need to include internal headers last, because the internal headers +// include CL headers which have #define's like: +// +//#define cl_khr_gl_sharing 1 +//#define cl_khr_icd 1 +// +// Which will break the compilation of clang/Basic/OpenCLOptions.h + +#include "core/error.hpp" +#include "llvm/codegen.hpp" +#include "llvm/compat.hpp" +#include "llvm/invocation.hpp" +#include "llvm/metadata.hpp" +#include "llvm/util.hpp" +#ifdef HAVE_CLOVER_SPIRV +#include "spirv/invocation.hpp" +#endif +#include "util/algorithm.hpp" + + +using namespace clover; +using namespace clover::llvm; + +using ::llvm::Function; +using ::llvm::LLVMContext; +using ::llvm::Module; +using ::llvm::raw_string_ostream; + +namespace { + + struct cl_version { + std::string version_str; // CL Version + unsigned version_number; // Numeric CL Version + }; + + static const unsigned ANY_VERSION = 999; + const cl_version cl_versions[] = { + { "1.0", 100}, + { "1.1", 110}, + { "1.2", 120}, + { "2.0", 200}, + { "2.1", 210}, + { "2.2", 220}, + }; + + struct clc_version_lang_std { + unsigned version_number; // CLC Version + clang::LangStandard::Kind clc_lang_standard; + }; + + const clc_version_lang_std cl_version_lang_stds[] = { + { 100, compat::lang_opencl10}, + { 110, clang::LangStandard::lang_opencl11}, + { 120, clang::LangStandard::lang_opencl12}, + { 200, clang::LangStandard::lang_opencl20}, + }; + + void + init_targets() { + static bool targets_initialized = false; + if (!targets_initialized) { + LLVMInitializeAllTargets(); + LLVMInitializeAllTargetInfos(); + LLVMInitializeAllTargetMCs(); + LLVMInitializeAllAsmParsers(); + LLVMInitializeAllAsmPrinters(); + targets_initialized = true; + } + } + + void + diagnostic_handler(const ::llvm::DiagnosticInfo &di, void *data) { + if (di.getSeverity() == ::llvm::DS_Error) { + raw_string_ostream os { *reinterpret_cast(data) }; + ::llvm::DiagnosticPrinterRawOStream printer { os }; + di.print(printer); + throw build_error(); + } + } + + std::unique_ptr + create_context(std::string &r_log) { + init_targets(); + std::unique_ptr ctx { new LLVMContext }; + compat::set_diagnostic_handler(*ctx, diagnostic_handler, &r_log); + return ctx; + } + + const struct clc_version_lang_std& + get_cl_lang_standard(unsigned requested, unsigned max = ANY_VERSION) { + for (const struct clc_version_lang_std &version : cl_version_lang_stds) { + if (version.version_number == max || + version.version_number == requested) { + return version; + } + } + throw build_error("Unknown/Unsupported language version"); + } + + const struct cl_version& + get_cl_version(const std::string &version_str, + unsigned max = ANY_VERSION) { + for (const struct cl_version &version : cl_versions) { + if (version.version_number == max || version.version_str == version_str) { + return version; + } + } + throw build_error("Unknown/Unsupported language version"); + } + + clang::LangStandard::Kind + get_lang_standard_from_version_str(const std::string &version_str, + bool is_build_opt = false) { + + //Per CL 2.0 spec, section 5.8.4.5: + // If it's an option, use the value directly. + // If it's a device version, clamp to max 1.x version, a.k.a. 1.2 + const cl_version version = + get_cl_version(version_str, is_build_opt ? ANY_VERSION : 120); + + const struct clc_version_lang_std standard = + get_cl_lang_standard(version.version_number); + + return standard.clc_lang_standard; + } + + clang::LangStandard::Kind + get_language_version(const std::vector &opts, + const std::string &device_version) { + + const std::string search = "-cl-std=CL"; + + for (auto &opt: opts) { + auto pos = opt.find(search); + if (pos == 0){ + const auto ver = opt.substr(pos + search.size()); + const auto device_ver = get_cl_version(device_version); + const auto requested = get_cl_version(ver); + if (requested.version_number > device_ver.version_number) { + throw build_error(); + } + return get_lang_standard_from_version_str(ver, true); + } + } + + return get_lang_standard_from_version_str(device_version); + } + + std::unique_ptr + create_compiler_instance(const device &dev, const std::string& ir_target, + const std::vector &opts, + std::string &r_log) { + std::unique_ptr c { new clang::CompilerInstance }; + clang::TextDiagnosticBuffer *diag_buffer = new clang::TextDiagnosticBuffer; + clang::DiagnosticsEngine diag { new clang::DiagnosticIDs, + new clang::DiagnosticOptions, diag_buffer }; + + // Parse the compiler options. A file name should be present at the end + // and must have the .cl extension in order for the CompilerInvocation + // class to recognize it as an OpenCL source file. + const std::vector copts = + map(std::mem_fn(&std::string::c_str), opts); + + const target &target = ir_target; + const std::string &device_clc_version = dev.device_clc_version(); + + if (!compat::create_compiler_invocation_from_args( + c->getInvocation(), copts, diag)) + throw invalid_build_options_error(); + + diag_buffer->FlushDiagnostics(diag); + if (diag.hasErrorOccurred()) + throw invalid_build_options_error(); + + c->getTargetOpts().CPU = target.cpu; + c->getTargetOpts().Triple = target.triple; + c->getLangOpts().NoBuiltin = true; + + // This is a workaround for a Clang bug which causes the number + // of warnings and errors to be printed to stderr. + // http://www.llvm.org/bugs/show_bug.cgi?id=19735 + c->getDiagnosticOpts().ShowCarets = false; + + c->getInvocation().setLangDefaults(c->getLangOpts(), + compat::ik_opencl, ::llvm::Triple(target.triple), + c->getPreprocessorOpts(), + get_language_version(opts, device_clc_version)); + + c->createDiagnostics(new clang::TextDiagnosticPrinter( + *new raw_string_ostream(r_log), + &c->getDiagnosticOpts(), true)); + + c->setTarget(clang::TargetInfo::CreateTargetInfo( + c->getDiagnostics(), c->getInvocation().TargetOpts)); + + return c; + } + + std::unique_ptr + compile(LLVMContext &ctx, clang::CompilerInstance &c, + const std::string &name, const std::string &source, + const header_map &headers, const device &dev, + const std::string &opts, bool use_libclc, std::string &r_log) { + c.getFrontendOpts().ProgramAction = clang::frontend::EmitLLVMOnly; + c.getHeaderSearchOpts().UseBuiltinIncludes = true; + c.getHeaderSearchOpts().UseStandardSystemIncludes = true; + c.getHeaderSearchOpts().ResourceDir = CLANG_RESOURCE_DIR; + + if (use_libclc) { + // Add libclc generic search path + c.getHeaderSearchOpts().AddPath(LIBCLC_INCLUDEDIR, + clang::frontend::Angled, + false, false); + + // Add libclc include + c.getPreprocessorOpts().Includes.push_back("clc/clc.h"); + } else { + // Add opencl-c generic search path + c.getHeaderSearchOpts().AddPath(CLANG_RESOURCE_DIR, + clang::frontend::Angled, + false, false); + + // Add opencl include + c.getPreprocessorOpts().Includes.push_back("opencl-c.h"); + } + + // Add definition for the OpenCL version + c.getPreprocessorOpts().addMacroDef("__OPENCL_VERSION__=" + + std::to_string(get_cl_version( + dev.device_version()).version_number)); + + // clc.h requires that this macro be defined: + c.getPreprocessorOpts().addMacroDef("cl_clang_storage_class_specifiers"); + c.getPreprocessorOpts().addRemappedFile( + name, ::llvm::MemoryBuffer::getMemBuffer(source).release()); + + if (headers.size()) { + const std::string tmp_header_path = "/tmp/clover/"; + + c.getHeaderSearchOpts().AddPath(tmp_header_path, + clang::frontend::Angled, + false, false); + + for (const auto &header : headers) + c.getPreprocessorOpts().addRemappedFile( + tmp_header_path + header.first, + ::llvm::MemoryBuffer::getMemBuffer(header.second).release()); + } + + // Tell clang to link this file before performing any + // optimizations. This is required so that we can replace calls + // to the OpenCL C barrier() builtin with calls to target + // intrinsics that have the noduplicate attribute. This + // attribute will prevent Clang from creating illegal uses of + // barrier() (e.g. Moving barrier() inside a conditional that is + // no executed by all threads) during its optimizaton passes. + if (use_libclc) + compat::add_link_bitcode_file(c.getCodeGenOpts(), + LIBCLC_LIBEXECDIR + dev.ir_target() + ".bc"); + + // Compile the code + clang::EmitLLVMOnlyAction act(&ctx); + if (!c.ExecuteAction(act)) + throw build_error(); + + return act.takeModule(); + } +} + +module +clover::llvm::compile_program(const std::string &source, + const header_map &headers, + const device &dev, + const std::string &opts, + std::string &r_log) { + if (has_flag(debug::clc)) + debug::log(".cl", "// Options: " + opts + '\n' + source); + + auto ctx = create_context(r_log); + auto c = create_compiler_instance(dev, dev.ir_target(), + tokenize(opts + " input.cl"), r_log); + auto mod = compile(*ctx, *c, "input.cl", source, headers, dev, opts, true, + r_log); + + if (has_flag(debug::llvm)) + debug::log(".ll", print_module_bitcode(*mod)); + + return build_module_library(*mod, module::section::text_intermediate); +} + +namespace { + void + optimize(Module &mod, unsigned optimization_level, + bool internalize_symbols) { + ::llvm::legacy::PassManager pm; + + // By default, the function internalizer pass will look for a function + // called "main" and then mark all other functions as internal. Marking + // functions as internal enables the optimizer to perform optimizations + // like function inlining and global dead-code elimination. + // + // When there is no "main" function in a module, the internalize pass will + // treat the module like a library, and it won't internalize any functions. + // Since there is no "main" function in our kernels, we need to tell + // the internalizer pass that this module is not a library by passing a + // list of kernel functions to the internalizer. The internalizer will + // treat the functions in the list as "main" functions and internalize + // all of the other functions. + if (internalize_symbols) { + std::vector names = + map(std::mem_fn(&Function::getName), get_kernels(mod)); + pm.add(::llvm::createInternalizePass( + [=](const ::llvm::GlobalValue &gv) { + return std::find(names.begin(), names.end(), + gv.getName()) != names.end(); + })); + } + + ::llvm::PassManagerBuilder pmb; + pmb.OptLevel = optimization_level; + pmb.LibraryInfo = new ::llvm::TargetLibraryInfoImpl( + ::llvm::Triple(mod.getTargetTriple())); + pmb.populateModulePassManager(pm); + pm.run(mod); + } + + std::unique_ptr + link(LLVMContext &ctx, const clang::CompilerInstance &c, + const std::vector &modules, std::string &r_log) { + std::unique_ptr mod { new Module("link", ctx) }; + std::unique_ptr< ::llvm::Linker> linker { new ::llvm::Linker(*mod) }; + + for (auto &m : modules) { + if (linker->linkInModule(parse_module_library(m, ctx, r_log))) + throw build_error(); + } + + return mod; + } +} + +module +clover::llvm::link_program(const std::vector &modules, + const device &dev, const std::string &opts, + std::string &r_log) { + std::vector options = tokenize(opts + " input.cl"); + const bool create_library = count("-create-library", options); + erase_if(equals("-create-library"), options); + + auto ctx = create_context(r_log); + auto c = create_compiler_instance(dev, dev.ir_target(), options, r_log); + auto mod = link(*ctx, *c, modules, r_log); + + optimize(*mod, c->getCodeGenOpts().OptimizationLevel, !create_library); + + static std::atomic_uint seq(0); + const std::string id = "." + mod->getModuleIdentifier() + "-" + + std::to_string(seq++); + + if (has_flag(debug::llvm)) + debug::log(id + ".ll", print_module_bitcode(*mod)); + + if (create_library) { + return build_module_library(*mod, module::section::text_library); + + } else if (dev.ir_format() == PIPE_SHADER_IR_NATIVE) { + if (has_flag(debug::native)) + debug::log(id + ".asm", print_module_native(*mod, dev.ir_target())); + + return build_module_native(*mod, dev.ir_target(), *c, r_log); + + } else { + unreachable("Unsupported IR."); + } +} + +#ifdef HAVE_CLOVER_SPIRV +module +clover::llvm::compile_to_spirv(const std::string &source, + const header_map &headers, + const device &dev, + const std::string &opts, + std::string &r_log) { + if (has_flag(debug::clc)) + debug::log(".cl", "// Options: " + opts + '\n' + source); + + auto ctx = create_context(r_log); + const std::string target = dev.address_bits() == 32u ? + "-spir-unknown-unknown" : + "-spir64-unknown-unknown"; + auto c = create_compiler_instance(dev, target, + tokenize(opts + " input.cl"), r_log); + auto mod = compile(*ctx, *c, "input.cl", source, headers, dev, opts, false, + r_log); + + if (has_flag(debug::llvm)) + debug::log(".ll", print_module_bitcode(*mod)); + + std::string error_msg; + if (!::llvm::regularizeLlvmForSpirv(mod.get(), error_msg)) { + r_log += "Failed to regularize LLVM IR for SPIR-V: " + error_msg + ".\n"; + throw error(CL_INVALID_VALUE); + } + + std::ostringstream os; + if (!::llvm::writeSpirv(mod.get(), os, error_msg)) { + r_log += "Translation from LLVM IR to SPIR-V failed: " + error_msg + ".\n"; + throw error(CL_INVALID_VALUE); + } + + const std::string osContent = os.str(); + std::vector binary(osContent.begin(), osContent.end()); + if (binary.empty()) { + r_log += "Failed to retrieve SPIR-V binary.\n"; + throw error(CL_INVALID_VALUE); + } + + if (has_flag(debug::spirv)) + debug::log(".spvasm", spirv::print_module(binary, dev.device_version())); + + return spirv::compile_program(binary, dev, r_log); +} +#endif diff --git a/src/gallium/frontends/clover/llvm/invocation.hpp b/src/gallium/frontends/clover/llvm/invocation.hpp new file mode 100644 index 00000000000..1f0e9db2cf7 --- /dev/null +++ b/src/gallium/frontends/clover/llvm/invocation.hpp @@ -0,0 +1,54 @@ +// +// Copyright 2016 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#ifndef CLOVER_LLVM_INVOCATION_HPP +#define CLOVER_LLVM_INVOCATION_HPP + +#include "core/error.hpp" +#include "core/module.hpp" +#include "core/program.hpp" +#include "pipe/p_defines.h" + +namespace clover { + namespace llvm { + module compile_program(const std::string &source, + const header_map &headers, + const device &device, + const std::string &opts, + std::string &r_log); + + module link_program(const std::vector &modules, + const device &device, + const std::string &opts, + std::string &r_log); + +#ifdef HAVE_CLOVER_SPIRV + module compile_to_spirv(const std::string &source, + const header_map &headers, + const device &dev, + const std::string &opts, + std::string &r_log); +#endif + } +} + +#endif diff --git a/src/gallium/frontends/clover/llvm/metadata.hpp b/src/gallium/frontends/clover/llvm/metadata.hpp new file mode 100644 index 00000000000..58042f4b4da --- /dev/null +++ b/src/gallium/frontends/clover/llvm/metadata.hpp @@ -0,0 +1,86 @@ +// +// Copyright 2016 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +/// +/// \file +/// Utility functions for LLVM IR metadata introspection. +/// + +#ifndef CLOVER_LLVM_METADATA_HPP +#define CLOVER_LLVM_METADATA_HPP + +#include "llvm/compat.hpp" +#include "util/algorithm.hpp" + +#include +#include +#include +#include + +namespace clover { + namespace llvm { + namespace detail { + inline bool + is_kernel(const ::llvm::Function &f) { + return f.getMetadata("kernel_arg_type"); + } + + inline iterator_range< ::llvm::MDNode::op_iterator> + get_kernel_metadata_operands(const ::llvm::Function &f, + const std::string &name) { + const auto data_node = f.getMetadata(name); + return range(data_node->op_begin(), data_node->op_end()); + } + } + + /// + /// Extract the string metadata node \p name corresponding to the kernel + /// argument given by \p arg. + /// + inline std::string + get_argument_metadata(const ::llvm::Function &f, + const ::llvm::Argument &arg, + const std::string &name) { + return ::llvm::cast< ::llvm::MDString>( + detail::get_kernel_metadata_operands(f, name)[arg.getArgNo()]) + ->getString().str(); + } + + /// + /// Return a vector with all CL kernel functions found in the LLVM + /// module \p mod. + /// + inline std::vector + get_kernels(const ::llvm::Module &mod) { + std::vector fs; + + for (auto &f : mod.getFunctionList()) { + if (detail::is_kernel(f)) + fs.push_back(&f); + } + + return fs; + } + } +} + +#endif diff --git a/src/gallium/frontends/clover/llvm/util.hpp b/src/gallium/frontends/clover/llvm/util.hpp new file mode 100644 index 00000000000..02e73e65071 --- /dev/null +++ b/src/gallium/frontends/clover/llvm/util.hpp @@ -0,0 +1,137 @@ +// +// Copyright 2012-2016 Francisco Jerez +// Copyright 2012-2016 Advanced Micro Devices, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#ifndef CLOVER_LLVM_UTIL_HPP +#define CLOVER_LLVM_UTIL_HPP + +#include "core/error.hpp" +#include "util/u_debug.h" + +#include +#include +#include +#include + +namespace clover { + namespace llvm { + template void + fail(std::string &r_log, E &&e, const std::string &s) { + r_log += s; + throw e; + } + + inline std::vector + tokenize(const std::string &s) { + std::vector ss; + std::ostringstream oss; + + // OpenCL programs can pass a quoted argument, most frequently the + // include path. This is useful so that path containing spaces is + // treated as a single argument instead of being split by the spaces. + // Additionally, the argument should also be unquoted before being + // passed to the compiler. We avoid using std::string::replace here to + // remove quotes, as the single and double quote characters can be a + // part of the file name. + bool escape_next = false; + bool in_quote_double = false; + bool in_quote_single = false; + + for (auto c : s) { + if (escape_next) { + oss.put(c); + escape_next = false; + } else if (c == '\\') { + escape_next = true; + } else if (c == '"' && !in_quote_single) { + in_quote_double = !in_quote_double; + } else if (c == '\'' && !in_quote_double) { + in_quote_single = !in_quote_single; + } else if (c != ' ' || in_quote_single || in_quote_double) { + oss.put(c); + } else if (oss.tellp() > 0) { + ss.emplace_back(oss.str()); + oss.str(""); + } + } + + if (oss.tellp() > 0) + ss.emplace_back(oss.str()); + + if (in_quote_double || in_quote_single) + throw invalid_build_options_error(); + + return ss; + } + + inline std::string + as_string(const std::vector &v) { + return { v.begin(), v.end() }; + } + + struct target { + target(const std::string &s) : + cpu(s.begin(), s.begin() + s.find_first_of("-")), + triple(s.begin() + s.find_first_of("-") + 1, s.end()) {} + + std::string cpu; + std::string triple; + }; + + namespace debug { + enum flag { + clc = 1 << 0, + llvm = 1 << 1, + native = 1 << 2, + spirv = 1 << 3, + }; + + inline bool + has_flag(flag f) { + static const struct debug_named_value debug_options[] = { + { "clc", clc, "Dump the OpenCL C code for all kernels." }, + { "llvm", llvm, "Dump the generated LLVM IR for all kernels." }, + { "native", native, "Dump kernel assembly code for targets " + "specifying PIPE_SHADER_IR_NATIVE" }, + { "spirv", spirv, "Dump the generated SPIR-V for all kernels." }, + DEBUG_NAMED_VALUE_END + }; + static const unsigned flags = + debug_get_flags_option("CLOVER_DEBUG", debug_options, 0); + + return flags & f; + } + + inline void + log(const std::string &suffix, const std::string &s) { + const std::string path = debug_get_option("CLOVER_DEBUG_FILE", + "stderr"); + if (path == "stderr") + std::cerr << s; + else + std::ofstream(path + suffix, std::ios::app) << s; + } + } + } +} + +#endif diff --git a/src/gallium/frontends/clover/meson.build b/src/gallium/frontends/clover/meson.build new file mode 100644 index 00000000000..7606a6beaf6 --- /dev/null +++ b/src/gallium/frontends/clover/meson.build @@ -0,0 +1,164 @@ +# Copyright © 2017-2018 Intel Corporation + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +clover_cpp_args = [] +clover_opencl_cpp_args = [ + '-DCL_TARGET_OPENCL_VERSION=220', + '-DCL_USE_DEPRECATED_OPENCL_1_0_APIS', + '-DCL_USE_DEPRECATED_OPENCL_1_1_APIS', + '-DCL_USE_DEPRECATED_OPENCL_1_2_APIS', + '-DCL_USE_DEPRECATED_OPENCL_2_0_APIS', + '-DCL_USE_DEPRECATED_OPENCL_2_1_APIS' +] +clover_spirv_cpp_args = [] +clover_incs = [inc_include, inc_src, inc_gallium, inc_gallium_aux] + +# the CL header files declare attributes on the CL types. Compilers warn if +# we use them as template arguments. Disable the warning as there isn't +# anything we can do about it +if cpp.has_argument('-Wno-ignored-attributes') + clover_cpp_args += '-Wno-ignored-attributes' +endif + +if with_opencl_icd + clover_cpp_args += '-DHAVE_CLOVER_ICD' +endif + +if with_opencl_spirv + clover_spirv_cpp_args += '-DHAVE_CLOVER_SPIRV' +endif + +libclllvm = static_library( + 'clllvm', + files( + 'llvm/codegen/bitcode.cpp', + 'llvm/codegen/common.cpp', + 'llvm/codegen/native.cpp', + 'llvm/codegen.hpp', + 'llvm/compat.hpp', + 'llvm/invocation.cpp', + 'llvm/invocation.hpp', + 'llvm/metadata.hpp', + 'llvm/util.hpp', + ), + include_directories : clover_incs, + cpp_args : [ + clover_cpp_args, + clover_opencl_cpp_args, + clover_spirv_cpp_args, + cpp_vis_args, + '-DLIBCLC_INCLUDEDIR="@0@/"'.format(dep_clc.get_pkgconfig_variable('includedir')), + '-DLIBCLC_LIBEXECDIR="@0@/"'.format(dep_clc.get_pkgconfig_variable('libexecdir')), + '-DCLANG_RESOURCE_DIR="@0@"'.format(join_paths( + dep_llvm.get_configtool_variable('libdir'), 'clang', + dep_llvm.version(), 'include', + )), + ], + dependencies : [dep_llvm, dep_elf, dep_llvmspirvlib], + override_options : clover_cpp_std, +) + +libclspirv = static_library( + 'clspirv', + files('spirv/invocation.cpp', 'spirv/invocation.hpp'), + include_directories : clover_incs, + cpp_args : [clover_opencl_cpp_args, clover_spirv_cpp_args, cpp_vis_args], + dependencies : [dep_spirv_tools], + override_options : clover_cpp_std, +) + +libclnir = static_library( + 'clnir', + files('nir/invocation.cpp', 'nir/invocation.hpp'), + include_directories : [clover_incs, inc_mesa], + dependencies : idep_nir, + cpp_args : [clover_opencl_cpp_args, clover_spirv_cpp_args, cpp_vis_args], + override_options : clover_cpp_std, +) + +clover_files = files( + 'api/context.cpp', + 'api/device.cpp', + 'api/dispatch.cpp', + 'api/dispatch.hpp', + 'api/event.cpp', + 'api/interop.cpp', + 'api/kernel.cpp', + 'api/memory.cpp', + 'api/platform.cpp', + 'api/program.cpp', + 'api/queue.cpp', + 'api/sampler.cpp', + 'api/transfer.cpp', + 'api/util.hpp', + 'core/compiler.hpp', + 'core/context.cpp', + 'core/context.hpp', + 'core/device.cpp', + 'core/device.hpp', + 'core/error.hpp', + 'core/event.cpp', + 'core/event.hpp', + 'core/format.cpp', + 'core/format.hpp', + 'core/kernel.cpp', + 'core/kernel.hpp', + 'core/memory.cpp', + 'core/memory.hpp', + 'core/module.cpp', + 'core/module.hpp', + 'core/object.hpp', + 'core/platform.cpp', + 'core/platform.hpp', + 'core/program.cpp', + 'core/program.hpp', + 'core/property.hpp', + 'core/queue.cpp', + 'core/queue.hpp', + 'core/resource.cpp', + 'core/resource.hpp', + 'core/sampler.cpp', + 'core/sampler.hpp', + 'core/timestamp.cpp', + 'core/timestamp.hpp', + 'util/adaptor.hpp', + 'util/algebra.hpp', + 'util/algorithm.hpp', + 'util/factor.hpp', + 'util/functional.hpp', + 'util/lazy.hpp', + 'util/pointer.hpp', + 'util/range.hpp', + 'util/tuple.hpp', +) + +libclover = static_library( + 'clover', + [clover_files, sha1_h], + include_directories : clover_incs, + cpp_args : [ + clover_opencl_cpp_args, + clover_spirv_cpp_args, + clover_cpp_args, + cpp_vis_args + ], + link_with : [libclllvm, libclspirv, libclnir], + override_options : clover_cpp_std, +) diff --git a/src/gallium/frontends/clover/nir/invocation.cpp b/src/gallium/frontends/clover/nir/invocation.cpp new file mode 100644 index 00000000000..46440d96e09 --- /dev/null +++ b/src/gallium/frontends/clover/nir/invocation.cpp @@ -0,0 +1,173 @@ +// +// Copyright 2019 Karol Herbst +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#include "invocation.hpp" + +#include + +#include "core/device.hpp" +#include "core/error.hpp" +#include "pipe/p_state.h" +#include "util/algorithm.hpp" +#include "util/functional.hpp" + +#include +#include +#include +#include + +using namespace clover; + +#ifdef HAVE_CLOVER_SPIRV + +// Refs and unrefs the glsl_type_singleton. +static class glsl_type_ref { +public: + glsl_type_ref() { + glsl_type_singleton_init_or_ref(); + } + + ~glsl_type_ref() { + glsl_type_singleton_decref(); + } +} glsl_type_ref; + +static const nir_shader_compiler_options * +dev_get_nir_compiler_options(const device &dev) +{ + const void *co = dev.get_compiler_options(PIPE_SHADER_IR_NIR); + return static_cast(co); +} + +module clover::nir::spirv_to_nir(const module &mod, const device &dev, + std::string &r_log) +{ + struct spirv_to_nir_options spirv_options = {}; + spirv_options.environment = NIR_SPIRV_OPENCL; + spirv_options.caps.address = true; + spirv_options.caps.float64 = true; + spirv_options.caps.int8 = true; + spirv_options.caps.int16 = true; + spirv_options.caps.int64 = true; + spirv_options.caps.kernel = true; + spirv_options.constant_as_global = true; + + module m; + // We only insert one section. + assert(mod.secs.size() == 1); + auto §ion = mod.secs[0]; + + module::resource_id section_id = 0; + for (const auto &sym : mod.syms) { + assert(sym.section == 0); + + const auto *binary = + reinterpret_cast(section.data.data()); + const uint32_t *data = reinterpret_cast(binary->blob); + const size_t num_words = binary->num_bytes / 4; + const char *name = sym.name.c_str(); + auto *compiler_options = dev_get_nir_compiler_options(dev); + + nir_shader *nir = spirv_to_nir(data, num_words, nullptr, 0, + MESA_SHADER_KERNEL, name, + &spirv_options, compiler_options); + if (!nir) { + r_log += "Translation from SPIR-V to NIR for kernel \"" + sym.name + + "\" failed.\n"; + throw build_error(); + } + + nir->info.cs.local_size_variable = true; + nir_validate_shader(nir, "clover"); + + // Calculate input offsets. + unsigned offset = 0; + nir_foreach_variable_safe(var, &nir->inputs) { + offset = align(offset, glsl_get_cl_alignment(var->type)); + var->data.driver_location = offset; + offset += glsl_get_cl_size(var->type); + } + + // Inline all functions first. + // according to the comment on nir_inline_functions + NIR_PASS_V(nir, nir_lower_variable_initializers, nir_var_function_temp); + NIR_PASS_V(nir, nir_lower_returns); + NIR_PASS_V(nir, nir_inline_functions); + NIR_PASS_V(nir, nir_opt_deref); + + // Pick off the single entrypoint that we want. + foreach_list_typed_safe(nir_function, func, node, &nir->functions) { + if (!func->is_entrypoint) + exec_node_remove(&func->node); + } + assert(exec_list_length(&nir->functions) == 1); + + nir_validate_shader(nir, "clover after function inlining"); + + NIR_PASS_V(nir, nir_lower_variable_initializers, + static_cast(~nir_var_function_temp)); + + // copy propagate to prepare for lower_explicit_io + NIR_PASS_V(nir, nir_split_var_copies); + NIR_PASS_V(nir, nir_opt_copy_prop_vars); + NIR_PASS_V(nir, nir_lower_var_copies); + NIR_PASS_V(nir, nir_lower_vars_to_ssa); + NIR_PASS_V(nir, nir_opt_dce); + + nir_variable_mode modes = (nir_variable_mode)( + nir_var_shader_in | + nir_var_mem_global | + nir_var_mem_shared); + nir_address_format format = nir->info.cs.ptr_size == 64 ? + nir_address_format_64bit_global : nir_address_format_32bit_global; + NIR_PASS_V(nir, nir_lower_explicit_io, modes, format); + + NIR_PASS_V(nir, nir_lower_system_values); + if (compiler_options->lower_int64_options) + NIR_PASS_V(nir, nir_lower_int64, + compiler_options->lower_int64_options); + + NIR_PASS_V(nir, nir_opt_dce); + + struct blob blob; + blob_init(&blob); + nir_serialize(&blob, nir, false); + + const pipe_binary_program_header header { uint32_t(blob.size) }; + module::section text { section_id, module::section::text_executable, header.num_bytes, {} }; + text.data.insert(text.data.end(), reinterpret_cast(&header), + reinterpret_cast(&header) + sizeof(header)); + text.data.insert(text.data.end(), blob.data, blob.data + blob.size); + + m.syms.emplace_back(sym.name, section_id, 0, sym.args); + m.secs.push_back(text); + section_id++; + } + return m; +} +#else +module clover::nir::spirv_to_nir(const module &mod, const device &dev, std::string &r_log) +{ + r_log += "SPIR-V support in clover is not enabled.\n"; + throw error(CL_LINKER_NOT_AVAILABLE); +} +#endif diff --git a/src/gallium/frontends/clover/nir/invocation.hpp b/src/gallium/frontends/clover/nir/invocation.hpp new file mode 100644 index 00000000000..41407a79765 --- /dev/null +++ b/src/gallium/frontends/clover/nir/invocation.hpp @@ -0,0 +1,36 @@ +// +// Copyright 2019 Karol Herbst +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#ifndef CLOVER_NIR_INVOCATION_HPP +#define CLOVER_NIR_INVOCATION_HPP + +#include "core/module.hpp" + +namespace clover { + class device; + namespace nir { + // converts a given spirv module to nir + module spirv_to_nir(const module &mod, const device &dev, std::string &r_log); + } +} + +#endif diff --git a/src/gallium/frontends/clover/spirv/invocation.cpp b/src/gallium/frontends/clover/spirv/invocation.cpp new file mode 100644 index 00000000000..01ced45c13b --- /dev/null +++ b/src/gallium/frontends/clover/spirv/invocation.cpp @@ -0,0 +1,740 @@ +// +// Copyright 2018 Pierre Moreau +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#include "invocation.hpp" + +#include +#include +#include +#include + +#ifdef HAVE_CLOVER_SPIRV +#include +#include +#endif + +#include "core/error.hpp" +#include "core/platform.hpp" +#include "invocation.hpp" +#include "llvm/util.hpp" +#include "pipe/p_state.h" +#include "util/algorithm.hpp" +#include "util/functional.hpp" +#include "util/u_math.h" + +#include "compiler/spirv/spirv.h" + +#define SPIRV_HEADER_WORD_SIZE 5 + +using namespace clover; + +#ifdef HAVE_CLOVER_SPIRV +namespace { + + template + T get(const char *source, size_t index) { + const uint32_t *word_ptr = reinterpret_cast(source); + return static_cast(word_ptr[index]); + } + + enum module::argument::type + convert_storage_class(SpvStorageClass storage_class, std::string &err) { + switch (storage_class) { + case SpvStorageClassFunction: + return module::argument::scalar; + case SpvStorageClassUniformConstant: + return module::argument::global; + case SpvStorageClassWorkgroup: + return module::argument::local; + case SpvStorageClassCrossWorkgroup: + return module::argument::global; + default: + err += "Invalid storage type " + std::to_string(storage_class) + "\n"; + throw build_error(); + } + } + + enum module::argument::type + convert_image_type(SpvId id, SpvDim dim, SpvAccessQualifier access, + std::string &err) { + if (dim == SpvDim2D && access == SpvAccessQualifierReadOnly) + return module::argument::image2d_rd; + else if (dim == SpvDim2D && access == SpvAccessQualifierWriteOnly) + return module::argument::image2d_wr; + else if (dim == SpvDim3D && access == SpvAccessQualifierReadOnly) + return module::argument::image3d_rd; + else if (dim == SpvDim3D && access == SpvAccessQualifierWriteOnly) + return module::argument::image3d_wr; + else { + err += "Unknown access qualifier " + std::to_string(access) + + " or dimension " + std::to_string(dim) + " for image " + + std::to_string(id) + ".\n"; + throw build_error(); + } + } + + module::section + make_text_section(const std::vector &code, + enum module::section::type section_type) { + const pipe_binary_program_header header { uint32_t(code.size()) }; + module::section text { 0, section_type, header.num_bytes, {} }; + + text.data.insert(text.data.end(), reinterpret_cast(&header), + reinterpret_cast(&header) + sizeof(header)); + text.data.insert(text.data.end(), code.begin(), code.end()); + + return text; + } + + module + create_module_from_spirv(const std::vector &source, + size_t pointer_byte_size, + std::string &err) { + const size_t length = source.size() / sizeof(uint32_t); + size_t i = SPIRV_HEADER_WORD_SIZE; // Skip header + + std::string kernel_name; + size_t kernel_nb = 0u; + std::vector args; + + module m; + + std::unordered_map kernels; + std::unordered_map types; + std::unordered_map pointer_types; + std::unordered_map constants; + std::unordered_set packed_structures; + std::unordered_map> + func_param_attr_map; + + while (i < length) { + const auto inst = &source[i * sizeof(uint32_t)]; + const auto desc_word = get(inst, 0); + const auto opcode = static_cast(desc_word & SpvOpCodeMask); + const unsigned int num_operands = desc_word >> SpvWordCountShift; + + switch (opcode) { + case SpvOpEntryPoint: + if (get(inst, 1) == SpvExecutionModelKernel) + kernels.emplace(get(inst, 2), + source.data() + (i + 3u) * sizeof(uint32_t)); + break; + + case SpvOpDecorate: { + const auto id = get(inst, 1); + const auto decoration = get(inst, 2); + if (decoration == SpvDecorationCPacked) + packed_structures.emplace(id); + else if (decoration == SpvDecorationFuncParamAttr) { + const auto attribute = + get(inst, 3u); + func_param_attr_map[id].push_back(attribute); + } + break; + } + + case SpvOpGroupDecorate: { + const auto group_id = get(inst, 1); + if (packed_structures.count(group_id)) { + for (unsigned int i = 2u; i < num_operands; ++i) + packed_structures.emplace(get(inst, i)); + } + const auto func_param_attr_iter = + func_param_attr_map.find(group_id); + if (func_param_attr_iter != func_param_attr_map.end()) { + for (unsigned int i = 2u; i < num_operands; ++i) + func_param_attr_map.emplace(get(inst, i), + func_param_attr_iter->second); + } + break; + } + + case SpvOpConstant: + // We only care about constants that represent the size of arrays. + // If they are passed as argument, they will never be more than + // 4GB-wide, and even if they did, a clover::module::argument size + // is represented by an int. + constants[get(inst, 2)] = get(inst, 3u); + break; + + case SpvOpTypeInt: // FALLTHROUGH + case SpvOpTypeFloat: { + const auto size = get(inst, 2) / 8u; + types[get(inst, 1)] = { module::argument::scalar, size, + size, size, + module::argument::zero_ext }; + break; + } + + case SpvOpTypeArray: { + const auto id = get(inst, 1); + const auto type_id = get(inst, 2); + const auto types_iter = types.find(type_id); + if (types_iter == types.end()) + break; + + const auto constant_id = get(inst, 3); + const auto constants_iter = constants.find(constant_id); + if (constants_iter == constants.end()) { + err += "Constant " + std::to_string(constant_id) + + " is missing\n"; + throw build_error(); + } + const auto elem_size = types_iter->second.size; + const auto elem_nbs = constants_iter->second; + const auto size = elem_size * elem_nbs; + types[id] = { module::argument::scalar, size, size, + types_iter->second.target_align, + module::argument::zero_ext }; + break; + } + + case SpvOpTypeStruct: { + const auto id = get(inst, 1); + const bool is_packed = packed_structures.count(id); + + unsigned struct_size = 0u; + unsigned struct_align = 1u; + for (unsigned j = 2u; j < num_operands; ++j) { + const auto type_id = get(inst, j); + const auto types_iter = types.find(type_id); + + // If a type was not found, that means it is not one of the + // types allowed as kernel arguments. And since the module has + // been validated, this means this type is not used for kernel + // arguments, and therefore can be ignored. + if (types_iter == types.end()) + break; + + const auto alignment = is_packed ? 1u + : types_iter->second.target_align; + const auto padding = (-struct_size) & (alignment - 1u); + struct_size += padding + types_iter->second.target_size; + struct_align = std::max(struct_align, alignment); + } + struct_size += (-struct_size) & (struct_align - 1u); + types[id] = { module::argument::scalar, struct_size, struct_size, + struct_align, module::argument::zero_ext }; + break; + } + + case SpvOpTypeVector: { + const auto id = get(inst, 1); + const auto type_id = get(inst, 2); + const auto types_iter = types.find(type_id); + + // If a type was not found, that means it is not one of the + // types allowed as kernel arguments. And since the module has + // been validated, this means this type is not used for kernel + // arguments, and therefore can be ignored. + if (types_iter == types.end()) + break; + + const auto elem_size = types_iter->second.size; + const auto elem_nbs = get(inst, 3); + const auto size = elem_size * elem_nbs; + types[id] = { module::argument::scalar, size, size, size, + module::argument::zero_ext }; + break; + } + + case SpvOpTypeForwardPointer: // FALLTHROUGH + case SpvOpTypePointer: { + const auto id = get(inst, 1); + const auto storage_class = get(inst, 2); + // Input means this is for a builtin variable, which can not be + // passed as an argument to a kernel. + if (storage_class == SpvStorageClassInput) + break; + types[id] = { convert_storage_class(storage_class, err), + sizeof(cl_mem), + static_cast(pointer_byte_size), + static_cast(pointer_byte_size), + module::argument::zero_ext }; + if (opcode == SpvOpTypePointer) + pointer_types[id] = get(inst, 3); + break; + } + + case SpvOpTypeSampler: + types[get(inst, 1)] = { module::argument::sampler, + sizeof(cl_sampler) }; + break; + + case SpvOpTypeImage: { + const auto id = get(inst, 1); + const auto dim = get(inst, 3); + const auto access = get(inst, 9); + types[id] = { convert_image_type(id, dim, access, err), + sizeof(cl_mem), sizeof(cl_mem), sizeof(cl_mem), + module::argument::zero_ext }; + break; + } + + case SpvOpTypePipe: // FALLTHROUGH + case SpvOpTypeQueue: { + err += "TypePipe and TypeQueue are valid SPIR-V 1.0 types, but are " + "not available in the currently supported OpenCL C version." + "\n"; + throw build_error(); + } + + case SpvOpFunction: { + const auto kernels_iter = kernels.find(get(inst, 2)); + if (kernels_iter != kernels.end()) + kernel_name = kernels_iter->second; + break; + } + + case SpvOpFunctionParameter: { + if (kernel_name.empty()) + break; + + const auto type_id = get(inst, 1); + auto arg = types.find(type_id)->second; + const auto &func_param_attr_iter = + func_param_attr_map.find(get(inst, 2)); + if (func_param_attr_iter != func_param_attr_map.end()) { + for (auto &i : func_param_attr_iter->second) { + switch (i) { + case SpvFunctionParameterAttributeSext: + arg.ext_type = module::argument::sign_ext; + break; + case SpvFunctionParameterAttributeZext: + arg.ext_type = module::argument::zero_ext; + break; + case SpvFunctionParameterAttributeByVal: { + const SpvId ptr_type_id = + pointer_types.find(type_id)->second; + arg = types.find(ptr_type_id)->second; + break; + } + default: + break; + } + } + } + args.emplace_back(arg); + break; + } + + case SpvOpFunctionEnd: + if (kernel_name.empty()) + break; + m.syms.emplace_back(kernel_name, 0, kernel_nb, args); + ++kernel_nb; + kernel_name.clear(); + args.clear(); + break; + + default: + break; + } + + i += num_operands; + } + + m.secs.push_back(make_text_section(source, + module::section::text_intermediate)); + return m; + } + + bool + check_capabilities(const device &dev, const std::vector &source, + std::string &r_log) { + const size_t length = source.size() / sizeof(uint32_t); + size_t i = SPIRV_HEADER_WORD_SIZE; // Skip header + + while (i < length) { + const auto desc_word = get(source.data(), i); + const auto opcode = static_cast(desc_word & SpvOpCodeMask); + const unsigned int num_operands = desc_word >> SpvWordCountShift; + + if (opcode != SpvOpCapability) + break; + + const auto capability = get(source.data(), i + 1u); + switch (capability) { + // Mandatory capabilities + case SpvCapabilityAddresses: + case SpvCapabilityFloat16Buffer: + case SpvCapabilityGroups: + case SpvCapabilityInt64: + case SpvCapabilityInt16: + case SpvCapabilityInt8: + case SpvCapabilityKernel: + case SpvCapabilityLinkage: + case SpvCapabilityVector16: + break; + // Optional capabilities + case SpvCapabilityImageBasic: + case SpvCapabilityLiteralSampler: + case SpvCapabilitySampled1D: + case SpvCapabilityImage1D: + case SpvCapabilitySampledBuffer: + case SpvCapabilityImageBuffer: + if (!dev.image_support()) { + r_log += "Capability 'ImageBasic' is not supported.\n"; + return false; + } + break; + case SpvCapabilityFloat64: + if (!dev.has_doubles()) { + r_log += "Capability 'Float64' is not supported.\n"; + return false; + } + break; + // Enabled through extensions + case SpvCapabilityFloat16: + if (!dev.has_halves()) { + r_log += "Capability 'Float16' is not supported.\n"; + return false; + } + break; + case SpvCapabilityInt64Atomics: + if (!dev.has_int64_atomics()) { + r_log += "Capability 'Int64Atomics' is not supported.\n"; + return false; + } + break; + default: + r_log += "Capability '" + std::to_string(capability) + + "' is not supported.\n"; + return false; + } + + i += num_operands; + } + + return true; + } + + bool + check_extensions(const device &dev, const std::vector &source, + std::string &r_log) { + const size_t length = source.size() / sizeof(uint32_t); + size_t i = SPIRV_HEADER_WORD_SIZE; // Skip header + + while (i < length) { + const auto desc_word = get(source.data(), i); + const auto opcode = static_cast(desc_word & SpvOpCodeMask); + const unsigned int num_operands = desc_word >> SpvWordCountShift; + + if (opcode == SpvOpCapability) { + i += num_operands; + continue; + } + if (opcode != SpvOpExtension) + break; + + const char *extension = source.data() + (i + 1u) * sizeof(uint32_t); + const std::string device_extensions = dev.supported_extensions(); + const std::string platform_extensions = + dev.platform.supported_extensions(); + if (device_extensions.find(extension) == std::string::npos && + platform_extensions.find(extension) == std::string::npos) { + r_log += "Extension '" + std::string(extension) + + "' is not supported.\n"; + return false; + } + + i += num_operands; + } + + return true; + } + + bool + check_memory_model(const device &dev, const std::vector &source, + std::string &r_log) { + const size_t length = source.size() / sizeof(uint32_t); + size_t i = SPIRV_HEADER_WORD_SIZE; // Skip header + + while (i < length) { + const auto desc_word = get(source.data(), i); + const auto opcode = static_cast(desc_word & SpvOpCodeMask); + const unsigned int num_operands = desc_word >> SpvWordCountShift; + + switch (opcode) { + case SpvOpMemoryModel: + switch (get(source.data(), i + 1u)) { + case SpvAddressingModelPhysical32: + return dev.address_bits() == 32; + case SpvAddressingModelPhysical64: + return dev.address_bits() == 64; + default: + unreachable("Only Physical32 and Physical64 are valid for OpenCL, and the binary was already validated"); + return false; + } + break; + default: + break; + } + + i += num_operands; + } + + return false; + } + + // Copies the input binary and convert it to the endianness of the host CPU. + std::vector + spirv_to_cpu(const std::vector &binary) + { + const uint32_t first_word = get(binary.data(), 0u); + if (first_word == SpvMagicNumber) + return binary; + + std::vector cpu_endianness_binary(binary.size()); + for (size_t i = 0; i < (binary.size() / 4u); ++i) { + const uint32_t word = get(binary.data(), i); + reinterpret_cast(cpu_endianness_binary.data())[i] = + util_bswap32(word); + } + + return cpu_endianness_binary; + } + +#ifdef HAVE_CLOVER_SPIRV + std::string + format_validator_msg(spv_message_level_t level, const char * /* source */, + const spv_position_t &position, const char *message) { + std::string level_str; + switch (level) { + case SPV_MSG_FATAL: + level_str = "Fatal"; + break; + case SPV_MSG_INTERNAL_ERROR: + level_str = "Internal error"; + break; + case SPV_MSG_ERROR: + level_str = "Error"; + break; + case SPV_MSG_WARNING: + level_str = "Warning"; + break; + case SPV_MSG_INFO: + level_str = "Info"; + break; + case SPV_MSG_DEBUG: + level_str = "Debug"; + break; + } + return "[" + level_str + "] At word No." + + std::to_string(position.index) + ": \"" + message + "\"\n"; + } + + spv_target_env + convert_opencl_str_to_target_env(const std::string &opencl_version) { + if (opencl_version == "2.2") { + return SPV_ENV_OPENCL_2_2; + } else if (opencl_version == "2.1") { + return SPV_ENV_OPENCL_2_1; + } else if (opencl_version == "2.0") { + return SPV_ENV_OPENCL_2_0; + } else if (opencl_version == "1.2" || + opencl_version == "1.1" || + opencl_version == "1.0") { + // SPIR-V is only defined for OpenCL >= 1.2, however some drivers + // might use it with OpenCL 1.0 and 1.1. + return SPV_ENV_OPENCL_1_2; + } else { + throw build_error("Invalid OpenCL version"); + } + } +#endif + +} + +module +clover::spirv::compile_program(const std::vector &binary, + const device &dev, std::string &r_log) { + std::vector source = spirv_to_cpu(binary); + + if (!is_valid_spirv(source, dev.device_version(), r_log)) + throw build_error(); + + if (!check_capabilities(dev, source, r_log)) + throw build_error(); + if (!check_extensions(dev, source, r_log)) + throw build_error(); + if (!check_memory_model(dev, source, r_log)) + throw build_error(); + + return create_module_from_spirv(source, + dev.address_bits() == 32 ? 4u : 8u, r_log); +} + +module +clover::spirv::link_program(const std::vector &modules, + const device &dev, const std::string &opts, + std::string &r_log) { + std::vector options = clover::llvm::tokenize(opts); + + bool create_library = false; + + std::string ignored_options; + for (const std::string &option : options) { + if (option == "-create-library") { + create_library = true; + } else { + ignored_options += "'" + option + "' "; + } + } + if (!ignored_options.empty()) { + r_log += "Ignoring the following link options: " + ignored_options + + "\n"; + } + + spvtools::LinkerOptions linker_options; + linker_options.SetCreateLibrary(create_library); + + module m; + + const auto section_type = create_library ? module::section::text_library : + module::section::text_executable; + + std::vector sections; + sections.reserve(modules.size()); + std::vector lengths; + lengths.reserve(modules.size()); + + auto const validator_consumer = [&r_log](spv_message_level_t level, + const char *source, + const spv_position_t &position, + const char *message) { + r_log += format_validator_msg(level, source, position, message); + }; + + for (const auto &mod : modules) { + const auto &msec = find([](const module::section &sec) { + return sec.type == module::section::text_intermediate || + sec.type == module::section::text_library; + }, mod.secs); + + const auto c_il = ((struct pipe_binary_program_header*)msec.data.data())->blob; + const auto length = msec.size; + + sections.push_back(reinterpret_cast(c_il)); + lengths.push_back(length / sizeof(uint32_t)); + } + + std::vector linked_binary; + + const std::string opencl_version = dev.device_version(); + const spv_target_env target_env = + convert_opencl_str_to_target_env(opencl_version); + + const spvtools::MessageConsumer consumer = validator_consumer; + spvtools::Context context(target_env); + context.SetMessageConsumer(std::move(consumer)); + + if (Link(context, sections.data(), lengths.data(), sections.size(), + &linked_binary, linker_options) != SPV_SUCCESS) + throw error(CL_LINK_PROGRAM_FAILURE); + + std::vector final_binary{ + reinterpret_cast(linked_binary.data()), + reinterpret_cast(linked_binary.data() + + linked_binary.size()) }; + if (!is_valid_spirv(final_binary, opencl_version, r_log)) + throw error(CL_LINK_PROGRAM_FAILURE); + + for (const auto &mod : modules) + m.syms.insert(m.syms.end(), mod.syms.begin(), mod.syms.end()); + + m.secs.emplace_back(make_text_section(final_binary, section_type)); + + return m; +} + +bool +clover::spirv::is_valid_spirv(const std::vector &binary, + const std::string &opencl_version, + std::string &r_log) { + auto const validator_consumer = + [&r_log](spv_message_level_t level, const char *source, + const spv_position_t &position, const char *message) { + r_log += format_validator_msg(level, source, position, message); + }; + + const spv_target_env target_env = + convert_opencl_str_to_target_env(opencl_version); + spvtools::SpirvTools spvTool(target_env); + spvTool.SetMessageConsumer(validator_consumer); + + return spvTool.Validate(reinterpret_cast(binary.data()), + binary.size() / 4u); +} + +std::string +clover::spirv::print_module(const std::vector &binary, + const std::string &opencl_version) { + const spv_target_env target_env = + convert_opencl_str_to_target_env(opencl_version); + spvtools::SpirvTools spvTool(target_env); + spv_context spvContext = spvContextCreate(target_env); + if (!spvContext) + return "Failed to create an spv_context for disassembling the module."; + + spv_text disassembly; + spvBinaryToText(spvContext, + reinterpret_cast(binary.data()), + binary.size() / 4u, SPV_BINARY_TO_TEXT_OPTION_NONE, + &disassembly, nullptr); + spvContextDestroy(spvContext); + + const std::string disassemblyStr = disassembly->str; + spvTextDestroy(disassembly); + + return disassemblyStr; +} + +#else +bool +clover::spirv::is_valid_spirv(const std::vector &/*binary*/, + const std::string &/*opencl_version*/, + std::string &/*r_log*/) { + return false; +} + +module +clover::spirv::compile_program(const std::vector &binary, + const device &dev, std::string &r_log) { + r_log += "SPIR-V support in clover is not enabled.\n"; + throw build_error(); +} + +module +clover::spirv::link_program(const std::vector &/*modules*/, + const device &/*dev*/, const std::string &/*opts*/, + std::string &r_log) { + r_log += "SPIR-V support in clover is not enabled.\n"; + throw error(CL_LINKER_NOT_AVAILABLE); +} + +std::string +clover::spirv::print_module(const std::vector &binary, + const std::string &opencl_version) { + return std::string(); +} +#endif diff --git a/src/gallium/frontends/clover/spirv/invocation.hpp b/src/gallium/frontends/clover/spirv/invocation.hpp new file mode 100644 index 00000000000..472d8c0de71 --- /dev/null +++ b/src/gallium/frontends/clover/spirv/invocation.hpp @@ -0,0 +1,56 @@ +// +// Copyright 2018 Pierre Moreau +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#ifndef CLOVER_SPIRV_INVOCATION_HPP +#define CLOVER_SPIRV_INVOCATION_HPP + +#include "core/context.hpp" +#include "core/module.hpp" +#include "core/program.hpp" + +namespace clover { + namespace spirv { + // Returns whether the given binary is considered valid for the given + // OpenCL version. + // + // It uses SPIRV-Tools validator to do the validation, and potential + // warnings and errors are appended to |r_log|. + bool is_valid_spirv(const std::vector &binary, + const std::string &opencl_version, + std::string &r_log); + + // Creates a clover module out of the given SPIR-V binary. + module compile_program(const std::vector &binary, + const device &dev, std::string &r_log); + + // Combines multiple clover modules into a single one, resolving + // link dependencies between them. + module link_program(const std::vector &modules, const device &dev, + const std::string &opts, std::string &r_log); + + // Returns a textual representation of the given binary. + std::string print_module(const std::vector &binary, + const std::string &opencl_version); + } +} + +#endif diff --git a/src/gallium/frontends/clover/util/adaptor.hpp b/src/gallium/frontends/clover/util/adaptor.hpp new file mode 100644 index 00000000000..e9035968573 --- /dev/null +++ b/src/gallium/frontends/clover/util/adaptor.hpp @@ -0,0 +1,183 @@ +// +// Copyright 2013 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#ifndef CLOVER_UTIL_ADAPTOR_HPP +#define CLOVER_UTIL_ADAPTOR_HPP + +#include + +#include "util/tuple.hpp" +#include "util/pointer.hpp" +#include "util/functional.hpp" + +namespace clover { + namespace detail { + /// + /// Implementation of the iterator concept that transforms the + /// value of the source iterators \a Is on dereference by use of + /// a functor \a F. + /// + /// The exact category of the resulting iterator should be the + /// least common denominator of the source iterator categories. + /// + template + class iterator_adaptor { + public: + typedef std::forward_iterator_tag iterator_category; + typedef typename std::result_of< + F(typename std::iterator_traits::reference...) + >::type reference; + typedef typename std::remove_reference::type value_type; + typedef pseudo_ptr pointer; + typedef std::ptrdiff_t difference_type; + + iterator_adaptor() { + } + + iterator_adaptor(F f, std::tuple &&its) : + f(f), its(std::move(its)) { + } + + reference + operator*() const { + return tuple::apply(f, tuple::map(derefs(), its)); + } + + iterator_adaptor & + operator++() { + tuple::map(preincs(), its); + return *this; + } + + iterator_adaptor + operator++(int) { + auto jt = *this; + ++*this; + return jt; + } + + bool + operator==(const iterator_adaptor &jt) const { + return its == jt.its; + } + + bool + operator!=(const iterator_adaptor &jt) const { + return its != jt.its; + } + + pointer + operator->() const { + return { **this }; + } + + iterator_adaptor & + operator--() { + tuple::map(predecs(), its); + return *this; + } + + iterator_adaptor + operator--(int) { + auto jt = *this; + --*this; + return jt; + } + + iterator_adaptor & + operator+=(difference_type n) { + tuple::map(advances_by(n), its); + return *this; + } + + iterator_adaptor & + operator-=(difference_type n) { + tuple::map(advances_by(-n), its); + return *this; + } + + iterator_adaptor + operator+(difference_type n) const { + auto jt = *this; + jt += n; + return jt; + } + + iterator_adaptor + operator-(difference_type n) const { + auto jt = *this; + jt -= n; + return jt; + } + + difference_type + operator-(const iterator_adaptor &jt) const { + return std::get<0>(its) - std::get<0>(jt.its); + } + + reference + operator[](difference_type n) const { + return *(*this + n); + } + + bool + operator<(iterator_adaptor &jt) const { + return *this - jt < 0; + } + + bool + operator>(iterator_adaptor &jt) const { + return *this - jt > 0; + } + + bool + operator>=(iterator_adaptor &jt) const { + return !(*this < jt); + } + + bool + operator<=(iterator_adaptor &jt) const { + return !(*this > jt); + } + + protected: + F f; + std::tuple its; + }; + + template + iterator_adaptor + operator+(typename iterator_adaptor::difference_type n, + const iterator_adaptor &jt) { + return (jt + n); + } + + template + iterator_adaptor + operator-(typename iterator_adaptor::difference_type n, + const iterator_adaptor &jt) { + return (jt - n); + } + } +} + +#endif diff --git a/src/gallium/frontends/clover/util/algebra.hpp b/src/gallium/frontends/clover/util/algebra.hpp new file mode 100644 index 00000000000..43a9d8bbf5f --- /dev/null +++ b/src/gallium/frontends/clover/util/algebra.hpp @@ -0,0 +1,160 @@ +// +// Copyright 2013 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#ifndef CLOVER_UTIL_ALGEBRA_HPP +#define CLOVER_UTIL_ALGEBRA_HPP + +#include + +#include "util/range.hpp" +#include "util/functional.hpp" + +namespace clover { + /// + /// Class that identifies vectors (in the linear-algebraic sense). + /// + /// There should be a definition of this class for each type that + /// makes sense as vector arithmetic operand. + /// + template + struct vector_traits; + + /// + /// References of vectors are vectors. + /// + template + struct vector_traits::enable> { + typedef void enable; + }; + + /// + /// Constant vectors are vectors. + /// + template + struct vector_traits::enable> { + typedef void enable; + }; + + /// + /// Arrays of arithmetic types are vectors. + /// + template + struct vector_traits, + typename std::enable_if< + std::is_arithmetic::value>::type> { + typedef void enable; + }; + + namespace detail { + template + struct are_defined { + typedef void enable; + }; + } + + /// + /// The result of mapping a vector is a vector. + /// + template + struct vector_traits, + typename detail::are_defined< + typename vector_traits::enable...>::enable> { + typedef void enable; + }; + + /// + /// Vector sum. + /// + template::enable, + typename = typename vector_traits::enable> + adaptor_range + operator+(U &&u, V &&v) { + return map(plus(), std::forward(u), std::forward(v)); + } + + /// + /// Vector difference. + /// + template::enable, + typename = typename vector_traits::enable> + adaptor_range + operator-(U &&u, V &&v) { + return map(minus(), std::forward(u), std::forward(v)); + } + + /// + /// Scalar multiplication. + /// + template::enable> + adaptor_range, U> + operator*(U &&u, T &&a) { + return map(multiplies_by(std::forward(a)), std::forward(u)); + } + + /// + /// Scalar multiplication. + /// + template::enable> + adaptor_range, U> + operator*(T &&a, U &&u) { + return map(multiplies_by(std::forward(a)), std::forward(u)); + } + + /// + /// Additive inverse. + /// + template::enable> + adaptor_range + operator-(U &&u) { + return map(negate(), std::forward(u)); + } + + namespace detail { + template + using dot_type = typename std::common_type< + typename std::remove_reference::type::value_type, + typename std::remove_reference::type::value_type + >::type; + } + + /// + /// Dot product of two vectors. + /// + /// It can also do matrix multiplication if \a u or \a v is a + /// vector of vectors. + /// + template::enable, + typename = typename vector_traits::enable> + detail::dot_type + dot(U &&u, V &&v) { + return fold(plus(), detail::dot_type(), + map(multiplies(), u, v)); + } +} + +#endif diff --git a/src/gallium/frontends/clover/util/algorithm.hpp b/src/gallium/frontends/clover/util/algorithm.hpp new file mode 100644 index 00000000000..1658458ee18 --- /dev/null +++ b/src/gallium/frontends/clover/util/algorithm.hpp @@ -0,0 +1,218 @@ +// +// Copyright 2013 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#ifndef CLOVER_UTIL_ALGORITHM_HPP +#define CLOVER_UTIL_ALGORITHM_HPP + +#include +#include + +#include "util/range.hpp" +#include "util/functional.hpp" + +namespace clover { + namespace detail { + template + using preferred_reference_type = decltype(*std::declval().begin()); + } + + /// + /// Return the first element in a range. + /// + template + detail::preferred_reference_type + head(R &&r) { + assert(!r.empty()); + return r.front(); + } + + /// + /// Return all elements in a range but the first. + /// + template + slice_range + tail(R &&r) { + assert(!r.empty()); + return { std::forward(r), 1, r.size() }; + } + + /// + /// Return the only element in a range. + /// + template + detail::preferred_reference_type + unique(R &&r) { + if (r.size() != 1) + throw std::out_of_range(""); + + return r.front(); + } + + /// + /// Combine a variable number of ranges element-wise in a single + /// range of tuples. + /// + template + adaptor_range + zip(Rs &&... rs) { + return map(zips(), std::forward(rs)...); + } + + /// + /// Evaluate the elements of a range. + /// + /// Useful because most of the range algorithms evaluate their + /// result lazily. + /// + template + void + eval(R &&r) { + for (auto i = r.begin(), e = r.end(); i != e; ++i) + *i; + } + + /// + /// Apply functor \a f element-wise on a variable number of ranges + /// \a rs. + /// + /// The functor \a f should take as many arguments as ranges are + /// provided. + /// + template + void + for_each(F &&f, Rs &&... rs) { + eval(map(std::forward(f), std::forward(rs)...)); + } + + /// + /// Copy all elements from range \a r into an output container + /// starting from iterator \a i. + /// + template + void + copy(R &&r, I i) { + for (detail::preferred_reference_type x : r) + *(i++) = x; + } + + /// + /// Reduce the elements of range \a r by applying functor \a f + /// element by element. + /// + /// \a f should take an accumulator value (which is initialized to + /// \a a) and an element value as arguments, and return an updated + /// accumulator value. + /// + /// \returns The final value of the accumulator. + /// + template + A + fold(F &&f, A a, R &&r) { + for (detail::preferred_reference_type x : r) + a = f(a, x); + + return a; + } + + /// + /// Return how many elements of range \a r are equal to \a x. + /// + template + typename std::remove_reference::type::size_type + count(T &&x, R &&r) { + typename std::remove_reference::type::size_type n = 0; + + for (detail::preferred_reference_type y : r) { + if (x == y) + n++; + } + + return n; + } + + /// + /// Return the first element in range \a r for which predicate \a f + /// evaluates to true. + /// + template + detail::preferred_reference_type + find(F &&f, R &&r) { + for (detail::preferred_reference_type x : r) { + if (f(x)) + return x; + } + + throw std::out_of_range(""); + } + + /// + /// Return true if the element-wise application of predicate \a f + /// on \a rs evaluates to true for all elements. + /// + template + bool + all_of(F &&f, Rs &&... rs) { + for (auto b : map(f, rs...)) { + if (!b) + return false; + } + + return true; + } + + /// + /// Return true if the element-wise application of predicate \a f + /// on \a rs evaluates to true for any element. + /// + template + bool + any_of(F &&f, Rs &&... rs) { + for (auto b : map(f, rs...)) { + if (b) + return true; + } + + return false; + } + + /// + /// Erase elements for which predicate \a f evaluates to true from + /// container \a r. + /// + template + void + erase_if(F &&f, R &&r) { + auto i = r.begin(), e = r.end(); + + for (auto j = r.begin(); j != e; ++j) { + if (!f(*j)) { + if (j != i) + *i = std::move(*j); + ++i; + } + } + + r.erase(i, e); + } +} + +#endif diff --git a/src/gallium/frontends/clover/util/factor.hpp b/src/gallium/frontends/clover/util/factor.hpp new file mode 100644 index 00000000000..76d3bfe343f --- /dev/null +++ b/src/gallium/frontends/clover/util/factor.hpp @@ -0,0 +1,131 @@ +// +// Copyright 2013 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#ifndef CLOVER_UTIL_FACTOR_HPP +#define CLOVER_UTIL_FACTOR_HPP + +#include "util/range.hpp" + +namespace clover { + namespace factor { + /// + /// Calculate all prime integer factors of \p x. + /// + /// If \p limit is non-zero, terminate early as soon as enough + /// factors have been collected to reach the product \p limit. + /// + template + std::vector + find_integer_prime_factors(T x, T limit = 0) + { + const T max_d = (limit > 0 && limit < x ? limit : x); + const T min_x = x / max_d; + std::vector factors; + + for (T d = 2; d <= max_d && x > min_x; d++) { + if (x % d == 0) { + for (; x % d == 0; x /= d); + factors.push_back(d); + } + } + + return factors; + } + + namespace detail { + /// + /// Walk the power set of prime factors of the n-dimensional + /// integer array \p grid subject to the constraints given by + /// \p limits. + /// + template + std::pair> + next_grid_factor(const std::pair> &limits, + const std::vector &grid, + const std::vector> &factors, + std::pair> block, + unsigned d = 0, unsigned i = 0) { + if (d >= factors.size()) { + // We're done. + return {}; + + } else if (i >= factors[d].size()) { + // We're done with this grid dimension, try the next. + return next_grid_factor(limits, grid, factors, + std::move(block), d + 1, 0); + + } else { + T f = factors[d][i]; + + // Try the next power of this factor. + block.first *= f; + block.second[d] *= f; + + if (block.first <= limits.first && + block.second[d] <= limits.second[d] && + grid[d] % block.second[d] == 0) { + // We've found a valid grid divisor. + return block; + + } else { + // Overflow, back off to the zeroth power, + while (block.second[d] % f == 0) { + block.second[d] /= f; + block.first /= f; + } + + // ...and carry to the next factor. + return next_grid_factor(limits, grid, factors, + std::move(block), d, i + 1); + } + } + } + } + + /// + /// Find the divisor of the integer array \p grid that gives the + /// highest possible product not greater than \p product_limit + /// subject to the constraints given by \p coord_limit. + /// + template + std::vector + find_grid_optimal_factor(T product_limit, + const std::vector &coord_limit, + const std::vector &grid) { + const std::vector> factors = + map(find_integer_prime_factors, grid, coord_limit); + const auto limits = std::make_pair(product_limit, coord_limit); + auto best = std::make_pair(T(1), std::vector(grid.size(), T(1))); + + for (auto block = best; + block.first != 0 && best.first != product_limit; + block = detail::next_grid_factor(limits, grid, factors, block)) { + if (block.first > best.first) + best = block; + } + + return best.second; + } + } +} + +#endif diff --git a/src/gallium/frontends/clover/util/functional.hpp b/src/gallium/frontends/clover/util/functional.hpp new file mode 100644 index 00000000000..fc281c5c79a --- /dev/null +++ b/src/gallium/frontends/clover/util/functional.hpp @@ -0,0 +1,419 @@ +// +// Copyright 2013 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#ifndef CLOVER_UTIL_FUNCTIONAL_HPP +#define CLOVER_UTIL_FUNCTIONAL_HPP + +#include + +namespace clover { + struct identity { + template + typename std::remove_reference::type + operator()(T &&x) const { + return x; + } + }; + + struct plus { + template + typename std::common_type::type + operator()(T x, S y) const { + return x + y; + } + }; + + struct minus { + template + typename std::common_type::type + operator()(T x, S y) const { + return x - y; + } + }; + + struct negate { + template + T + operator()(T x) const { + return -x; + } + }; + + struct multiplies { + template + typename std::common_type::type + operator()(T x, S y) const { + return x * y; + } + }; + + struct divides { + template + typename std::common_type::type + operator()(T x, S y) const { + return x / y; + } + }; + + struct modulus { + template + typename std::common_type::type + operator()(T x, S y) const { + return x % y; + } + }; + + struct minimum { + template + T + operator()(T x) const { + return x; + } + + template + T + operator()(T x, Ts... xs) const { + T y = minimum()(xs...); + return x < y ? x : y; + } + }; + + struct maximum { + template + T + operator()(T x) const { + return x; + } + + template + T + operator()(T x, Ts... xs) const { + T y = maximum()(xs...); + return x < y ? y : x; + } + }; + + struct preincs { + template + T & + operator()(T &x) const { + return ++x; + } + }; + + struct predecs { + template + T & + operator()(T &x) const { + return --x; + } + }; + + template + class multiplies_by_t { + public: + multiplies_by_t(T x) : x(x) { + } + + template + typename std::common_type::type + operator()(S y) const { + return x * y; + } + + private: + T x; + }; + + template + multiplies_by_t + multiplies_by(T x) { + return { x }; + } + + template + class preincs_by_t { + public: + preincs_by_t(T n) : n(n) { + } + + template + S & + operator()(S &x) const { + return x += n; + } + + private: + T n; + }; + + template + preincs_by_t + preincs_by(T n) { + return { n }; + } + + template + class predecs_by_t { + public: + predecs_by_t(T n) : n(n) { + } + + template + S & + operator()(S &x) const { + return x -= n; + } + + private: + T n; + }; + + template + predecs_by_t + predecs_by(T n) { + return { n }; + } + + struct greater { + template + bool + operator()(T x, S y) const { + return x > y; + } + }; + + struct evals { + template + auto + operator()(T &&x) const -> decltype(x()) { + return x(); + } + }; + + struct derefs { + template + auto + operator()(T &&x) const -> decltype(*x) { + return *x; + } + }; + + struct addresses { + template + T * + operator()(T &x) const { + return &x; + } + + template + T * + operator()(std::reference_wrapper x) const { + return &x.get(); + } + }; + + struct begins { + template + auto + operator()(T &x) const -> decltype(x.begin()) { + return x.begin(); + } + }; + + struct ends { + template + auto + operator()(T &x) const -> decltype(x.end()) { + return x.end(); + } + }; + + struct sizes { + template + auto + operator()(T &x) const -> decltype(x.size()) { + return x.size(); + } + }; + + template + class advances_by_t { + public: + advances_by_t(T n) : n(n) { + } + + template + S + operator()(S &&it) const { + std::advance(it, n); + return it; + } + + private: + T n; + }; + + template + advances_by_t + advances_by(T n) { + return { n }; + } + + struct zips { + template + std::tuple + operator()(Ts &&... xs) const { + return std::tuple(std::forward(xs)...); + } + }; + + struct is_zero { + template + bool + operator()(const T &x) const { + return x == 0; + } + }; + + struct keys { + template + auto + operator()(P &&p) const -> decltype(std::get<0>(std::forward

      (p))) { + return std::get<0>(std::forward

      (p)); + } + }; + + struct values { + template + auto + operator()(P &&p) const -> decltype(std::get<1>(std::forward

      (p))) { + return std::get<1>(std::forward

      (p)); + } + }; + + template + class equals_t { + public: + equals_t(T &&x) : x(x) {} + + template + bool + operator()(S &&y) const { + return x == y; + } + + private: + T x; + }; + + template + equals_t + equals(T &&x) { + return { std::forward(x) }; + } + + class name_equals { + public: + name_equals(const std::string &name) : name(name) { + } + + template + bool + operator()(const T &x) const { + return std::string(x.name.begin(), x.name.end()) == name; + } + + private: + const std::string &name; + }; + + class id_equals { + public: + id_equals(const uint32_t id) : id(id) { + } + + template + bool + operator()(const T &x) const { + return x.id == id; + } + + private: + const uint32_t id; + }; + + template + class key_equals_t { + public: + key_equals_t(T &&x) : x(x) { + } + + template + bool + operator()(const P &p) const { + return p.first == x; + } + + private: + T x; + }; + + template + key_equals_t + key_equals(T &&x) { + return { std::forward(x) }; + } + + template + class type_equals_t { + public: + type_equals_t(T type) : type(type) { + } + + template + bool + operator()(const S &x) const { + return x.type == type; + } + + private: + T type; + }; + + template + type_equals_t + type_equals(T x) { + return { x }; + } + + struct interval_overlaps { + template + bool + operator()(T x0, T x1, T y0, T y1) { + return ((x0 <= y0 && y0 < x1) || + (y0 <= x0 && x0 < y1)); + } + }; +} + +#endif diff --git a/src/gallium/frontends/clover/util/lazy.hpp b/src/gallium/frontends/clover/util/lazy.hpp new file mode 100644 index 00000000000..e32a8f8b1b9 --- /dev/null +++ b/src/gallium/frontends/clover/util/lazy.hpp @@ -0,0 +1,161 @@ +// +// Copyright 2013 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#ifndef CLOVER_UTIL_LAZY_HPP +#define CLOVER_UTIL_LAZY_HPP + +#include +#include +#include + +namespace clover { + namespace detail { + template + class basic_lazy { + public: + virtual + ~basic_lazy() { + } + + virtual basic_lazy * + clone() const = 0; + + virtual + operator T() const = 0; + }; + + template + class deferred_lazy : public basic_lazy { + public: + template + deferred_lazy(G &&f) : f(new F(std::forward(f))) { + } + + virtual basic_lazy * + clone() const { + return new deferred_lazy(*this); + } + + operator T() const { + if (f) { + x = (*f)(); + f = {}; + } + + return x; + } + + private: + mutable std::shared_ptr f; + mutable T x; + }; + + template + class strict_lazy : public basic_lazy { + public: + template + strict_lazy(S &&x) : x(std::forward(x)) { + } + + virtual basic_lazy * + clone() const { + return new strict_lazy(*this); + } + + operator T() const { + return x; + } + + private: + T x; + }; + } + + /// + /// Object that represents a value of type \a T that is calculated + /// lazily as soon as it is required. + /// + template + class lazy { + public: + class undefined_error : std::logic_error { + public: + undefined_error() : std::logic_error("") { + } + }; + + /// + /// Initialize to some fixed value \a x which isn't calculated + /// lazily. + /// + lazy(T x) : obj(new detail::strict_lazy(x)) { + } + + /// + /// Initialize by providing a functor \a f that will calculate + /// the value on-demand. + /// + template + lazy(F &&f) : obj(new detail::deferred_lazy< + T, typename std::remove_reference::type + >(std::forward(f))) { + } + + /// + /// Initialize to undefined. + /// + lazy() : lazy([]() { + throw undefined_error(); + return T(); + }) { + } + + lazy(const lazy &other) : obj(obj->clone()) { + } + + lazy(lazy &&other) : obj(NULL) { + std::swap(obj, other.obj); + } + + ~lazy() { + delete obj; + } + + lazy & + operator=(lazy other) { + std::swap(obj, other.obj); + return *this; + } + + /// + /// Evaluate the value. + /// + operator T() const { + return *obj; + } + + private: + detail::basic_lazy *obj; + }; +} + +#endif diff --git a/src/gallium/frontends/clover/util/pointer.hpp b/src/gallium/frontends/clover/util/pointer.hpp new file mode 100644 index 00000000000..7bb9951aef6 --- /dev/null +++ b/src/gallium/frontends/clover/util/pointer.hpp @@ -0,0 +1,284 @@ +// +// Copyright 2013 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#ifndef CLOVER_UTIL_POINTER_HPP +#define CLOVER_UTIL_POINTER_HPP + +#include + +namespace clover { + /// + /// Some helper functions for raw pointer operations + /// + template + static bool + ptr_is_aligned(const T *ptr, uintptr_t a) noexcept { + assert(a == (a & -a)); + uintptr_t ptr_value = reinterpret_cast(ptr); + return (ptr_value & (a - 1)) == 0; + } + + /// + /// Base class for objects that support reference counting. + /// + class ref_counter { + public: + ref_counter(unsigned value = 1) : _ref_count(value) {} + + unsigned + ref_count() const { + return _ref_count; + } + + void + retain() { + _ref_count++; + } + + bool + release() { + return (--_ref_count) == 0; + } + + private: + std::atomic _ref_count; + }; + + /// + /// Simple reference to a clover::ref_counter object. Unlike + /// clover::intrusive_ptr and clover::intrusive_ref, it does nothing + /// special when the reference count drops to zero. + /// + class ref_holder { + public: + ref_holder(ref_counter &o) : p(&o) { + p->retain(); + } + + ref_holder(const ref_holder &ref) : + ref_holder(*ref.p) { + } + + ref_holder(ref_holder &&ref) : + p(ref.p) { + ref.p = NULL; + } + + ~ref_holder() { + if (p) + p->release(); + } + + ref_holder & + operator=(ref_holder ref) { + std::swap(ref.p, p); + return *this; + } + + bool + operator==(const ref_holder &ref) const { + return p == ref.p; + } + + bool + operator!=(const ref_holder &ref) const { + return p != ref.p; + } + + private: + ref_counter *p; + }; + + /// + /// Intrusive smart pointer for objects that implement the + /// clover::ref_counter interface. + /// + template + class intrusive_ptr { + public: + intrusive_ptr(T *q = NULL) : p(q) { + if (p) + p->retain(); + } + + intrusive_ptr(const intrusive_ptr &ptr) : + intrusive_ptr(ptr.p) { + } + + intrusive_ptr(intrusive_ptr &&ptr) : + p(ptr.p) { + ptr.p = NULL; + } + + ~intrusive_ptr() { + if (p && p->release()) + delete p; + } + + intrusive_ptr & + operator=(intrusive_ptr ptr) { + std::swap(ptr.p, p); + return *this; + } + + bool + operator==(const intrusive_ptr &ref) const { + return p == ref.p; + } + + bool + operator!=(const intrusive_ptr &ref) const { + return p != ref.p; + } + + T & + operator*() const { + return *p; + } + + T * + operator->() const { + return p; + } + + T * + operator()() const { + return p; + } + + explicit operator bool() const { + return p; + } + + explicit operator T *() const { + return p; + } + + private: + T *p; + }; + + /// + /// Intrusive smart reference for objects that implement the + /// clover::ref_counter interface. + /// + template + class intrusive_ref { + public: + intrusive_ref(T &o) : p(&o) { + p->retain(); + } + + intrusive_ref(const intrusive_ref &ref) : + intrusive_ref(*ref.p) { + } + + intrusive_ref(intrusive_ref &&ref) : + p(ref.p) { + ref.p = NULL; + } + + ~intrusive_ref() { + if (p && p->release()) + delete p; + } + + intrusive_ref & + operator=(intrusive_ref ref) { + std::swap(ref.p, p); + return *this; + } + + bool + operator==(const intrusive_ref &ref) const { + return p == ref.p; + } + + bool + operator!=(const intrusive_ref &ref) const { + return p != ref.p; + } + + T & + operator()() const { + return *p; + } + + operator T &() const { + return *p; + } + + private: + T *p; + }; + + /// + /// Initialize a clover::intrusive_ref from a newly created object + /// using the specified constructor arguments. + /// + template + intrusive_ref + create(As &&... as) { + intrusive_ref ref { *new T(std::forward(as)...) }; + ref().release(); + return ref; + } + + /// + /// Class that implements the usual pointer interface but in fact + /// contains the object it seems to be pointing to. + /// + template + class pseudo_ptr { + public: + pseudo_ptr(T x) : x(x) { + } + + pseudo_ptr(const pseudo_ptr &p) : x(p.x) { + } + + pseudo_ptr & + operator=(const pseudo_ptr &p) { + x = p.x; + return *this; + } + + T & + operator*() { + return x; + } + + T * + operator->() { + return &x; + } + + explicit operator bool() const { + return true; + } + + private: + T x; + }; +} + +#endif diff --git a/src/gallium/frontends/clover/util/range.hpp b/src/gallium/frontends/clover/util/range.hpp new file mode 100644 index 00000000000..b082359ee86 --- /dev/null +++ b/src/gallium/frontends/clover/util/range.hpp @@ -0,0 +1,419 @@ +// +// Copyright 2013 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#ifndef CLOVER_UTIL_RANGE_HPP +#define CLOVER_UTIL_RANGE_HPP + +#include +#include + +#include "util/adaptor.hpp" + +namespace clover { + /// + /// Class that identifies container types where the elements of a + /// range can be stored by the type conversion operator. + /// + /// \a T identifies the range element type. + /// + template + struct range_store_traits; + + template + struct range_store_traits> { + typedef void enable; + + template + static std::vector + create(const R &r) { + return { r.begin(), r.end() }; + } + }; + + template + struct range_store_traits> { + typedef void enable; + + template + static std::array + create(const R &r) { + std::array v; + assert(r.size() == v.size()); + copy(r, v.begin()); + return v; + } + }; + + namespace detail { + /// + /// Common functionality that is shared by other implementations + /// of the container concept. + /// + template + class basic_range { + public: + typedef I iterator; + typedef CI const_iterator; + typedef typename std::iterator_traits::value_type value_type; + typedef typename std::iterator_traits::reference + reference; + typedef typename std::iterator_traits::reference + const_reference; + typedef typename std::iterator_traits::difference_type + difference_type; + typedef std::size_t size_type; + + bool + operator==(const basic_range &r) const { + return *static_cast(this) == r; + } + + bool + operator!=(const basic_range &r) const { + return !(*this == r); + } + + iterator + begin() { + return static_cast(this)->begin(); + } + + iterator + end() { + return static_cast(this)->end(); + } + + const_iterator + begin() const { + return static_cast(this)->begin(); + } + + const_iterator + end() const { + return static_cast(this)->end(); + } + + std::reverse_iterator + rbegin() { + return { begin() }; + } + + std::reverse_iterator + rend() { + return { end() }; + } + + reference + front() { + return *begin(); + } + + reference + back() { + return *(end() - 1); + } + + bool + empty() const { + return begin() == end(); + } + + reference + at(size_type i) { + if (i >= static_cast(this)->size()) + throw std::out_of_range(""); + + return begin()[i]; + } + + const_reference + at(size_type i) const { + if (i >= static_cast(this)->size()) + throw std::out_of_range(""); + + return begin()[i]; + } + + reference + operator[](size_type i) { + return begin()[i]; + } + + const_reference + operator[](size_type i) const { + return begin()[i]; + } + + template + using store_traits = range_store_traits< + typename std::remove_cv::type, V + >; + + template::enable> + operator V() const { + return store_traits::create(*static_cast(this)); + } + }; + } + + /// + /// Range that contains all elements delimited by an iterator pair + /// (\a i, \a j). Use range() as convenience constructor. + /// + template + class iterator_range : public detail::basic_range, I, I> { + public: + typedef detail::basic_range, I, I> super; + + iterator_range() : i(), j() { + } + + iterator_range(I i, I j) : i(i), j(j) { + } + + bool + operator==(const iterator_range &r) const { + return i == r.i && j == r.j; + } + + I + begin() const { + return i; + } + + I + end() const { + return j; + } + + typename super::size_type + size() const { + return end() - begin(); + } + + private: + I i, j; + }; + + namespace detail { + template + using preferred_iterator_type = decltype(std::declval().begin()); + } + + /// + /// Range that transforms the contents of a number of source ranges + /// \a os element-wise by using the provided functor \a f. Use + /// map() as convenience constructor. + /// + template + class adaptor_range : + public detail::basic_range, + detail::iterator_adaptor< + F, detail::preferred_iterator_type...>, + detail::iterator_adaptor< + F, detail::preferred_iterator_type...> + > { + public: + typedef detail::basic_range, + detail::iterator_adaptor< + F, detail::preferred_iterator_type...>, + detail::iterator_adaptor< + F, detail::preferred_iterator_type...> + > super; + + template + adaptor_range(G &&f, Rs &&... os) : + f(std::forward(f)), os(std::forward(os)...) { + } + + bool + operator==(const adaptor_range &r) const { + return f == r.f && os == r.os; + } + + typename super::iterator + begin() { + return { f, tuple::map(begins(), os) }; + } + + typename super::iterator + end() { + return { f, tuple::map(advances_by(size()), + tuple::map(begins(), os)) }; + } + + typename super::const_iterator + begin() const { + return { f, tuple::map(begins(), os) }; + } + + typename super::const_iterator + end() const { + return { f, tuple::map(advances_by(size()), + tuple::map(begins(), os)) }; + } + + typename super::size_type + size() const { + return tuple::apply(minimum(), tuple::map(sizes(), os)); + } + + private: + F f; + std::tuple os; + }; + + /// + /// Range that contains all elements delimited by the index pair + /// (\a i, \a j) in the source range \a r. Use slice() as + /// convenience constructor. + /// + template + class slice_range : + public detail::basic_range, + detail::preferred_iterator_type, + detail::preferred_iterator_type> { + public: + typedef detail::basic_range, + detail::preferred_iterator_type, + detail::preferred_iterator_type + > super; + + template + slice_range(R &&r, typename super::size_type i, + typename super::size_type j) : + o(std::forward(r)), i(i), j(j) { + } + + bool + operator==(const slice_range &r) const { + return o == r.o && i == r.i && j == r.j; + } + + typename super::iterator + begin() { + return std::next(o.begin(), i); + } + + typename super::iterator + end() { + return std::next(o.begin(), j); + } + + typename super::const_iterator + begin() const { + return std::next(o.begin(), i); + } + + typename super::const_iterator + end() const { + return std::next(o.begin(), j); + } + + typename super::size_type + size() const { + return j - i; + } + + private: + O o; + typename super::size_type i, j; + }; + + /// + /// Create a range from an iterator pair (\a i, \a j). + /// + /// \sa iterator_range. + /// + template + iterator_range + range(T i, T j) { + return { i, j }; + } + + /// + /// Create a range of \a n elements starting from iterator \a i. + /// + /// \sa iterator_range. + /// + template + iterator_range + range(T i, typename std::iterator_traits::difference_type n) { + return { i, i + n }; + } + + /// + /// Create a range by transforming the contents of a number of + /// source ranges \a rs element-wise using a provided functor \a f. + /// + /// \sa adaptor_range. + /// + template + adaptor_range + map(F &&f, Rs &&... rs) { + return { std::forward(f), std::forward(rs)... }; + } + + /// + /// Create a range identical to another range \a r. + /// + template + adaptor_range + range(R &&r) { + return { identity(), std::forward(r) }; + } + + /// + /// Create a range by taking the elements delimited by the index + /// pair (\a i, \a j) in a source range \a r. + /// + /// \sa slice_range. + /// + template + slice_range + slice(R &&r, typename slice_range::size_type i, + typename slice_range::size_type j) { + return { std::forward(r), i, j }; + } + + /// + /// Range that behaves as a vector of references of type \a T. + /// + /// Useful because STL containers cannot contain references to + /// objects as elements. + /// + template + class ref_vector : public adaptor_range> { + public: + ref_vector(std::initializer_list> il) : + adaptor_range>(derefs(), map(addresses(), il)) { + } + + template + ref_vector(R &&r) : adaptor_range>( + derefs(), map(addresses(), std::forward(r))) { + } + }; +} + +#endif diff --git a/src/gallium/frontends/clover/util/tuple.hpp b/src/gallium/frontends/clover/util/tuple.hpp new file mode 100644 index 00000000000..bd49684a314 --- /dev/null +++ b/src/gallium/frontends/clover/util/tuple.hpp @@ -0,0 +1,117 @@ +// +// Copyright 2013 Francisco Jerez +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#ifndef CLOVER_UTIL_TUPLE_HPP +#define CLOVER_UTIL_TUPLE_HPP + +#include + +namespace clover { + namespace tuple { + /// + /// Static sequence of integers. + /// + template + struct integral_sequence; + + /// + /// Static sequence containing all integers from 0 to N-1. + /// + template + struct enumerate { + typedef typename enumerate::type + type; + }; + + template + struct enumerate<0, Is...> { + typedef integral_sequence type; + }; + + namespace detail { + template::type>::value + >::type> + struct _apply; + + template + struct _apply> { + typedef typename std::remove_reference::type func_type; + typedef decltype( + std::declval()(std::get(std::declval())...) + ) value_type; + + static value_type + eval(F &&f, T &&t) { + return f(std::get(std::forward(t))...); + } + }; + } + + /// + /// Evaluate function \a f with the elements of tuple \a t + /// expanded as arguments. + /// + template + typename detail::_apply::value_type + apply(F &&f, T &&t) { + return detail::_apply::eval(std::forward(f), + std::forward(t)); + } + + namespace detail { + template::type>::value + >::type> + struct _map; + + template + struct _map> { + typedef typename std::remove_reference::type func_type; + typedef std::tuple< + decltype(std::declval()( + std::get(std::declval())))... + > value_type; + + static value_type + eval(F &&f, T &&t) { + return value_type(f(std::get(std::forward(t)))...); + } + }; + } + + /// + /// Evaluate function \a f on each element of the tuple \a t and + /// return the resulting values as a new tuple. + /// + template + typename detail::_map::value_type + map(F &&f, T &&t) { + return detail::_map::eval(std::forward(f), + std::forward(t)); + } + } +} + +#endif diff --git a/src/gallium/frontends/dri/Android.mk b/src/gallium/frontends/dri/Android.mk new file mode 100644 index 00000000000..d6f8a6ed247 --- /dev/null +++ b/src/gallium/frontends/dri/Android.mk @@ -0,0 +1,55 @@ +# Mesa 3-D graphics library +# +# Copyright (C) 2015 Chih-Wei Huang +# Copyright (C) 2015 Android-x86 Open Source Project +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. + +LOCAL_PATH := $(call my-dir) + +include $(LOCAL_PATH)/Makefile.sources + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + $(common_SOURCES) \ + $(dri2_SOURCES) + +LOCAL_C_INCLUDES := \ + $(MESA_TOP)/src/mapi \ + $(MESA_TOP)/src/mesa + +LOCAL_EXPORT_C_INCLUDE_DIRS := \ + $(LOCAL_PATH) \ + $(LOCAL_C_INCLUDES) + +LOCAL_STATIC_LIBRARIES := \ + libmesa_dri_common + +ifneq ($(HAVE_GALLIUM_SOFTPIPE),) +LOCAL_SRC_FILES += $(drisw_SOURCES) +LOCAL_CFLAGS += -DGALLIUM_SOFTPIPE +endif + +LOCAL_MODULE := libmesa_st_dri + +LOCAL_GENERATED_SOURCES := $(MESA_DRI_OPTIONS_H) + +include $(GALLIUM_COMMON_MK) +include $(BUILD_STATIC_LIBRARY) diff --git a/src/gallium/frontends/dri/Makefile.sources b/src/gallium/frontends/dri/Makefile.sources new file mode 100644 index 00000000000..a610293bb11 --- /dev/null +++ b/src/gallium/frontends/dri/Makefile.sources @@ -0,0 +1,17 @@ +common_SOURCES := \ + dri_context.c \ + dri_context.h \ + dri_drawable.c \ + dri_drawable.h \ + dri_helpers.c \ + dri_helpers.h \ + dri_query_renderer.c \ + dri_query_renderer.h \ + dri_screen.c \ + dri_screen.h + +dri2_SOURCES := \ + dri2.c + +drisw_SOURCES := \ + drisw.c diff --git a/src/gallium/frontends/dri/SConscript b/src/gallium/frontends/dri/SConscript new file mode 100644 index 00000000000..fa48fb8a0d7 --- /dev/null +++ b/src/gallium/frontends/dri/SConscript @@ -0,0 +1,30 @@ +####################################################################### +# SConscript for dri state_tracker + +Import('*') + +env = env.Clone() + +env.PkgUseModules(['DRM']) + +env.Append(CPPPATH = [ + '#/src', + '#/src/mapi', + '#/src/mesa', + '#/src/mesa/drivers/dri/common', + xmlpool_options.dir.dir, # Dir to generated xmlpool/options.h +]) + +sources = env.ParseSourceList('Makefile.sources', 'common_SOURCES') + +# XXX: if HAVE_DRISW +sources.append(env.ParseSourceList('Makefile.sources', 'drisw_SOURCES')) + +# XXX: if HAVE_DRI2 +sources.append(env.ParseSourceList('Makefile.sources', 'dri2_SOURCES')) + +st_dri = env.ConvenienceLibrary( + target = 'st_dri', + source = sources +) +Export('st_dri') diff --git a/src/gallium/frontends/dri/dri2.c b/src/gallium/frontends/dri/dri2.c new file mode 100644 index 00000000000..334934b85c7 --- /dev/null +++ b/src/gallium/frontends/dri/dri2.c @@ -0,0 +1,2275 @@ +/* + * Mesa 3-D graphics library + * + * Copyright 2009, VMware, Inc. + * All Rights Reserved. + * Copyright (C) 2010 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell Jakob Bornecrantz + * Chia-I Wu + */ + +#include +#include "GL/mesa_glinterop.h" +#include "util/disk_cache.h" +#include "util/u_memory.h" +#include "util/u_inlines.h" +#include "util/format/u_format.h" +#include "util/u_debug.h" +#include "frontend/drm_driver.h" +#include "state_tracker/st_cb_bufferobjects.h" +#include "state_tracker/st_cb_fbo.h" +#include "state_tracker/st_cb_texture.h" +#include "state_tracker/st_texture.h" +#include "state_tracker/st_context.h" +#include "pipe-loader/pipe_loader.h" +#include "main/bufferobj.h" +#include "main/texobj.h" + +#include "dri_util.h" + +#include "dri_helpers.h" +#include "dri_drawable.h" +#include "dri_query_renderer.h" + +#include "drm-uapi/drm_fourcc.h" + +struct dri2_buffer +{ + __DRIbuffer base; + struct pipe_resource *resource; +}; + +static inline struct dri2_buffer * +dri2_buffer(__DRIbuffer * driBufferPriv) +{ + return (struct dri2_buffer *) driBufferPriv; +} + +/** + * DRI2 flush extension. + */ +static void +dri2_flush_drawable(__DRIdrawable *dPriv) +{ + dri_flush(dPriv->driContextPriv, dPriv, __DRI2_FLUSH_DRAWABLE, -1); +} + +static void +dri2_invalidate_drawable(__DRIdrawable *dPriv) +{ + struct dri_drawable *drawable = dri_drawable(dPriv); + + dri2InvalidateDrawable(dPriv); + drawable->dPriv->lastStamp = drawable->dPriv->dri2.stamp; + drawable->texture_mask = 0; + + p_atomic_inc(&drawable->base.stamp); +} + +static const __DRI2flushExtension dri2FlushExtension = { + .base = { __DRI2_FLUSH, 4 }, + + .flush = dri2_flush_drawable, + .invalidate = dri2_invalidate_drawable, + .flush_with_flags = dri_flush, +}; + +/** + * Retrieve __DRIbuffer from the DRI loader. + */ +static __DRIbuffer * +dri2_drawable_get_buffers(struct dri_drawable *drawable, + const enum st_attachment_type *atts, + unsigned *count) +{ + __DRIdrawable *dri_drawable = drawable->dPriv; + const __DRIdri2LoaderExtension *loader = drawable->sPriv->dri2.loader; + boolean with_format; + __DRIbuffer *buffers; + int num_buffers; + unsigned attachments[10]; + unsigned num_attachments, i; + + assert(loader); + with_format = dri_with_format(drawable->sPriv); + + num_attachments = 0; + + /* for Xserver 1.6.0 (DRI2 version 1) we always need to ask for the front */ + if (!with_format) + attachments[num_attachments++] = __DRI_BUFFER_FRONT_LEFT; + + for (i = 0; i < *count; i++) { + enum pipe_format format; + unsigned bind; + int att, depth; + + dri_drawable_get_format(drawable, atts[i], &format, &bind); + if (format == PIPE_FORMAT_NONE) + continue; + + switch (atts[i]) { + case ST_ATTACHMENT_FRONT_LEFT: + /* already added */ + if (!with_format) + continue; + att = __DRI_BUFFER_FRONT_LEFT; + break; + case ST_ATTACHMENT_BACK_LEFT: + att = __DRI_BUFFER_BACK_LEFT; + break; + case ST_ATTACHMENT_FRONT_RIGHT: + att = __DRI_BUFFER_FRONT_RIGHT; + break; + case ST_ATTACHMENT_BACK_RIGHT: + att = __DRI_BUFFER_BACK_RIGHT; + break; + default: + continue; + } + + /* + * In this switch statement we must support all formats that + * may occur as the stvis->color_format. + */ + switch(format) { + case PIPE_FORMAT_R16G16B16A16_FLOAT: + depth = 64; + break; + case PIPE_FORMAT_R16G16B16X16_FLOAT: + depth = 48; + break; + case PIPE_FORMAT_B10G10R10A2_UNORM: + case PIPE_FORMAT_R10G10B10A2_UNORM: + case PIPE_FORMAT_BGRA8888_UNORM: + case PIPE_FORMAT_RGBA8888_UNORM: + depth = 32; + break; + case PIPE_FORMAT_R10G10B10X2_UNORM: + case PIPE_FORMAT_B10G10R10X2_UNORM: + depth = 30; + break; + case PIPE_FORMAT_BGRX8888_UNORM: + case PIPE_FORMAT_RGBX8888_UNORM: + depth = 24; + break; + case PIPE_FORMAT_B5G6R5_UNORM: + depth = 16; + break; + default: + depth = util_format_get_blocksizebits(format); + assert(!"Unexpected format in dri2_drawable_get_buffers()"); + } + + attachments[num_attachments++] = att; + if (with_format) { + attachments[num_attachments++] = depth; + } + } + + if (with_format) { + num_attachments /= 2; + buffers = loader->getBuffersWithFormat(dri_drawable, + &dri_drawable->w, &dri_drawable->h, + attachments, num_attachments, + &num_buffers, dri_drawable->loaderPrivate); + } + else { + buffers = loader->getBuffers(dri_drawable, + &dri_drawable->w, &dri_drawable->h, + attachments, num_attachments, + &num_buffers, dri_drawable->loaderPrivate); + } + + if (buffers) + *count = num_buffers; + + return buffers; +} + +static bool +dri_image_drawable_get_buffers(struct dri_drawable *drawable, + struct __DRIimageList *images, + const enum st_attachment_type *statts, + unsigned statts_count) +{ + __DRIdrawable *dPriv = drawable->dPriv; + __DRIscreen *sPriv = drawable->sPriv; + unsigned int image_format = __DRI_IMAGE_FORMAT_NONE; + enum pipe_format pf; + uint32_t buffer_mask = 0; + unsigned i, bind; + + for (i = 0; i < statts_count; i++) { + dri_drawable_get_format(drawable, statts[i], &pf, &bind); + if (pf == PIPE_FORMAT_NONE) + continue; + + switch (statts[i]) { + case ST_ATTACHMENT_FRONT_LEFT: + buffer_mask |= __DRI_IMAGE_BUFFER_FRONT; + break; + case ST_ATTACHMENT_BACK_LEFT: + buffer_mask |= __DRI_IMAGE_BUFFER_BACK; + break; + default: + continue; + } + + switch (pf) { + case PIPE_FORMAT_R16G16B16A16_FLOAT: + image_format = __DRI_IMAGE_FORMAT_ABGR16161616F; + break; + case PIPE_FORMAT_R16G16B16X16_FLOAT: + image_format = __DRI_IMAGE_FORMAT_XBGR16161616F; + break; + case PIPE_FORMAT_B5G5R5A1_UNORM: + image_format = __DRI_IMAGE_FORMAT_ARGB1555; + break; + case PIPE_FORMAT_B5G6R5_UNORM: + image_format = __DRI_IMAGE_FORMAT_RGB565; + break; + case PIPE_FORMAT_BGRX8888_UNORM: + image_format = __DRI_IMAGE_FORMAT_XRGB8888; + break; + case PIPE_FORMAT_BGRA8888_UNORM: + image_format = __DRI_IMAGE_FORMAT_ARGB8888; + break; + case PIPE_FORMAT_RGBX8888_UNORM: + image_format = __DRI_IMAGE_FORMAT_XBGR8888; + break; + case PIPE_FORMAT_RGBA8888_UNORM: + image_format = __DRI_IMAGE_FORMAT_ABGR8888; + break; + case PIPE_FORMAT_B10G10R10X2_UNORM: + image_format = __DRI_IMAGE_FORMAT_XRGB2101010; + break; + case PIPE_FORMAT_B10G10R10A2_UNORM: + image_format = __DRI_IMAGE_FORMAT_ARGB2101010; + break; + case PIPE_FORMAT_R10G10B10X2_UNORM: + image_format = __DRI_IMAGE_FORMAT_XBGR2101010; + break; + case PIPE_FORMAT_R10G10B10A2_UNORM: + image_format = __DRI_IMAGE_FORMAT_ABGR2101010; + break; + default: + image_format = __DRI_IMAGE_FORMAT_NONE; + break; + } + } + + return (*sPriv->image.loader->getBuffers) (dPriv, image_format, + (uint32_t *) &drawable->base.stamp, + dPriv->loaderPrivate, buffer_mask, + images); +} + +static __DRIbuffer * +dri2_allocate_buffer(__DRIscreen *sPriv, + unsigned attachment, unsigned format, + int width, int height) +{ + struct dri_screen *screen = dri_screen(sPriv); + struct dri2_buffer *buffer; + struct pipe_resource templ; + enum pipe_format pf; + unsigned bind = 0; + struct winsys_handle whandle; + + switch (attachment) { + case __DRI_BUFFER_FRONT_LEFT: + case __DRI_BUFFER_FAKE_FRONT_LEFT: + bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; + break; + case __DRI_BUFFER_BACK_LEFT: + bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; + break; + case __DRI_BUFFER_DEPTH: + case __DRI_BUFFER_DEPTH_STENCIL: + case __DRI_BUFFER_STENCIL: + bind = PIPE_BIND_DEPTH_STENCIL; /* XXX sampler? */ + break; + } + + /* because we get the handle and stride */ + bind |= PIPE_BIND_SHARED; + + switch (format) { + case 64: + pf = PIPE_FORMAT_R16G16B16A16_FLOAT; + break; + case 48: + pf = PIPE_FORMAT_R16G16B16X16_FLOAT; + break; + case 32: + pf = PIPE_FORMAT_BGRA8888_UNORM; + break; + case 30: + pf = PIPE_FORMAT_B10G10R10X2_UNORM; + break; + case 24: + pf = PIPE_FORMAT_BGRX8888_UNORM; + break; + case 16: + pf = PIPE_FORMAT_Z16_UNORM; + break; + default: + return NULL; + } + + buffer = CALLOC_STRUCT(dri2_buffer); + if (!buffer) + return NULL; + + memset(&templ, 0, sizeof(templ)); + templ.bind = bind; + templ.format = pf; + templ.target = PIPE_TEXTURE_2D; + templ.last_level = 0; + templ.width0 = width; + templ.height0 = height; + templ.depth0 = 1; + templ.array_size = 1; + + buffer->resource = + screen->base.screen->resource_create(screen->base.screen, &templ); + if (!buffer->resource) { + FREE(buffer); + return NULL; + } + + memset(&whandle, 0, sizeof(whandle)); + if (screen->can_share_buffer) + whandle.type = WINSYS_HANDLE_TYPE_SHARED; + else + whandle.type = WINSYS_HANDLE_TYPE_KMS; + + screen->base.screen->resource_get_handle(screen->base.screen, NULL, + buffer->resource, &whandle, + PIPE_HANDLE_USAGE_EXPLICIT_FLUSH); + + buffer->base.attachment = attachment; + buffer->base.name = whandle.handle; + buffer->base.cpp = util_format_get_blocksize(pf); + buffer->base.pitch = whandle.stride; + + return &buffer->base; +} + +static void +dri2_release_buffer(__DRIscreen *sPriv, __DRIbuffer *bPriv) +{ + struct dri2_buffer *buffer = dri2_buffer(bPriv); + + pipe_resource_reference(&buffer->resource, NULL); + FREE(buffer); +} + +/* + * Backend functions for st_framebuffer interface. + */ + +static void +dri2_allocate_textures(struct dri_context *ctx, + struct dri_drawable *drawable, + const enum st_attachment_type *statts, + unsigned statts_count) +{ + __DRIscreen *sPriv = drawable->sPriv; + __DRIdrawable *dri_drawable = drawable->dPriv; + struct dri_screen *screen = dri_screen(sPriv); + struct pipe_resource templ; + boolean alloc_depthstencil = FALSE; + unsigned i, j, bind; + const __DRIimageLoaderExtension *image = sPriv->image.loader; + /* Image specific variables */ + struct __DRIimageList images; + /* Dri2 specific variables */ + __DRIbuffer *buffers = NULL; + struct winsys_handle whandle; + unsigned num_buffers = statts_count; + + /* First get the buffers from the loader */ + if (image) { + if (!dri_image_drawable_get_buffers(drawable, &images, + statts, statts_count)) + return; + } + else { + buffers = dri2_drawable_get_buffers(drawable, statts, &num_buffers); + if (!buffers || (drawable->old_num == num_buffers && + drawable->old_w == dri_drawable->w && + drawable->old_h == dri_drawable->h && + memcmp(drawable->old, buffers, + sizeof(__DRIbuffer) * num_buffers) == 0)) + return; + } + + /* Second clean useless resources*/ + + /* See if we need a depth-stencil buffer. */ + for (i = 0; i < statts_count; i++) { + if (statts[i] == ST_ATTACHMENT_DEPTH_STENCIL) { + alloc_depthstencil = TRUE; + break; + } + } + + /* Delete the resources we won't need. */ + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { + /* Don't delete the depth-stencil buffer, we can reuse it. */ + if (i == ST_ATTACHMENT_DEPTH_STENCIL && alloc_depthstencil) + continue; + + /* Flush the texture before unreferencing, so that other clients can + * see what the driver has rendered. + */ + if (i != ST_ATTACHMENT_DEPTH_STENCIL && drawable->textures[i]) { + struct pipe_context *pipe = ctx->st->pipe; + pipe->flush_resource(pipe, drawable->textures[i]); + } + + pipe_resource_reference(&drawable->textures[i], NULL); + } + + if (drawable->stvis.samples > 1) { + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { + boolean del = TRUE; + + /* Don't delete MSAA resources for the attachments which are enabled, + * we can reuse them. */ + for (j = 0; j < statts_count; j++) { + if (i == statts[j]) { + del = FALSE; + break; + } + } + + if (del) { + pipe_resource_reference(&drawable->msaa_textures[i], NULL); + } + } + } + + /* Third use the buffers retrieved to fill the drawable info */ + + memset(&templ, 0, sizeof(templ)); + templ.target = screen->target; + templ.last_level = 0; + templ.depth0 = 1; + templ.array_size = 1; + + if (image) { + if (images.image_mask & __DRI_IMAGE_BUFFER_FRONT) { + struct pipe_resource **buf = + &drawable->textures[ST_ATTACHMENT_FRONT_LEFT]; + struct pipe_resource *texture = images.front->texture; + + dri_drawable->w = texture->width0; + dri_drawable->h = texture->height0; + + pipe_resource_reference(buf, texture); + } + + if (images.image_mask & __DRI_IMAGE_BUFFER_BACK) { + struct pipe_resource **buf = + &drawable->textures[ST_ATTACHMENT_BACK_LEFT]; + struct pipe_resource *texture = images.back->texture; + + dri_drawable->w = texture->width0; + dri_drawable->h = texture->height0; + + pipe_resource_reference(buf, texture); + } + + /* Note: if there is both a back and a front buffer, + * then they have the same size. + */ + templ.width0 = dri_drawable->w; + templ.height0 = dri_drawable->h; + } + else { + memset(&whandle, 0, sizeof(whandle)); + + /* Process DRI-provided buffers and get pipe_resources. */ + for (i = 0; i < num_buffers; i++) { + __DRIbuffer *buf = &buffers[i]; + enum st_attachment_type statt; + enum pipe_format format; + + switch (buf->attachment) { + case __DRI_BUFFER_FRONT_LEFT: + if (!screen->auto_fake_front) { + continue; /* invalid attachment */ + } + /* fallthrough */ + case __DRI_BUFFER_FAKE_FRONT_LEFT: + statt = ST_ATTACHMENT_FRONT_LEFT; + break; + case __DRI_BUFFER_BACK_LEFT: + statt = ST_ATTACHMENT_BACK_LEFT; + break; + default: + continue; /* invalid attachment */ + } + + dri_drawable_get_format(drawable, statt, &format, &bind); + if (format == PIPE_FORMAT_NONE) + continue; + + /* dri2_drawable_get_buffers has already filled dri_drawable->w + * and dri_drawable->h */ + templ.width0 = dri_drawable->w; + templ.height0 = dri_drawable->h; + templ.format = format; + templ.bind = bind; + whandle.handle = buf->name; + whandle.stride = buf->pitch; + whandle.offset = 0; + whandle.format = format; + whandle.modifier = DRM_FORMAT_MOD_INVALID; + if (screen->can_share_buffer) + whandle.type = WINSYS_HANDLE_TYPE_SHARED; + else + whandle.type = WINSYS_HANDLE_TYPE_KMS; + drawable->textures[statt] = + screen->base.screen->resource_from_handle(screen->base.screen, + &templ, &whandle, + PIPE_HANDLE_USAGE_EXPLICIT_FLUSH); + assert(drawable->textures[statt]); + } + } + + /* Allocate private MSAA colorbuffers. */ + if (drawable->stvis.samples > 1) { + for (i = 0; i < statts_count; i++) { + enum st_attachment_type statt = statts[i]; + + if (statt == ST_ATTACHMENT_DEPTH_STENCIL) + continue; + + if (drawable->textures[statt]) { + templ.format = drawable->textures[statt]->format; + templ.bind = drawable->textures[statt]->bind & + ~(PIPE_BIND_SCANOUT | PIPE_BIND_SHARED); + templ.nr_samples = drawable->stvis.samples; + templ.nr_storage_samples = drawable->stvis.samples; + + /* Try to reuse the resource. + * (the other resource parameters should be constant) + */ + if (!drawable->msaa_textures[statt] || + drawable->msaa_textures[statt]->width0 != templ.width0 || + drawable->msaa_textures[statt]->height0 != templ.height0) { + /* Allocate a new one. */ + pipe_resource_reference(&drawable->msaa_textures[statt], NULL); + + drawable->msaa_textures[statt] = + screen->base.screen->resource_create(screen->base.screen, + &templ); + assert(drawable->msaa_textures[statt]); + + /* If there are any MSAA resources, we should initialize them + * such that they contain the same data as the single-sample + * resources we just got from the X server. + * + * The reason for this is that the state tracker (and + * therefore the app) can access the MSAA resources only. + * The single-sample resources are not exposed + * to the state tracker. + * + */ + dri_pipe_blit(ctx->st->pipe, + drawable->msaa_textures[statt], + drawable->textures[statt]); + } + } + else { + pipe_resource_reference(&drawable->msaa_textures[statt], NULL); + } + } + } + + /* Allocate a private depth-stencil buffer. */ + if (alloc_depthstencil) { + enum st_attachment_type statt = ST_ATTACHMENT_DEPTH_STENCIL; + struct pipe_resource **zsbuf; + enum pipe_format format; + unsigned bind; + + dri_drawable_get_format(drawable, statt, &format, &bind); + + if (format) { + templ.format = format; + templ.bind = bind & ~PIPE_BIND_SHARED; + + if (drawable->stvis.samples > 1) { + templ.nr_samples = drawable->stvis.samples; + templ.nr_storage_samples = drawable->stvis.samples; + zsbuf = &drawable->msaa_textures[statt]; + } + else { + templ.nr_samples = 0; + templ.nr_storage_samples = 0; + zsbuf = &drawable->textures[statt]; + } + + /* Try to reuse the resource. + * (the other resource parameters should be constant) + */ + if (!*zsbuf || + (*zsbuf)->width0 != templ.width0 || + (*zsbuf)->height0 != templ.height0) { + /* Allocate a new one. */ + pipe_resource_reference(zsbuf, NULL); + *zsbuf = screen->base.screen->resource_create(screen->base.screen, + &templ); + assert(*zsbuf); + } + } + else { + pipe_resource_reference(&drawable->msaa_textures[statt], NULL); + pipe_resource_reference(&drawable->textures[statt], NULL); + } + } + + /* For DRI2, we may get the same buffers again from the server. + * To prevent useless imports of gem names, drawable->old* is used + * to bypass the import if we get the same buffers. This doesn't apply + * to DRI3/Wayland, users of image.loader, since the buffer is managed + * by the client (no import), and the back buffer is going to change + * at every redraw. + */ + if (!image) { + drawable->old_num = num_buffers; + drawable->old_w = dri_drawable->w; + drawable->old_h = dri_drawable->h; + memcpy(drawable->old, buffers, sizeof(__DRIbuffer) * num_buffers); + } +} + +static void +dri2_flush_frontbuffer(struct dri_context *ctx, + struct dri_drawable *drawable, + enum st_attachment_type statt) +{ + __DRIdrawable *dri_drawable = drawable->dPriv; + const __DRIimageLoaderExtension *image = drawable->sPriv->image.loader; + const __DRIdri2LoaderExtension *loader = drawable->sPriv->dri2.loader; + struct pipe_context *pipe = ctx->st->pipe; + + if (statt != ST_ATTACHMENT_FRONT_LEFT) + return; + + if (drawable->stvis.samples > 1) { + /* Resolve the front buffer. */ + dri_pipe_blit(ctx->st->pipe, + drawable->textures[ST_ATTACHMENT_FRONT_LEFT], + drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT]); + } + + if (drawable->textures[ST_ATTACHMENT_FRONT_LEFT]) { + pipe->flush_resource(pipe, drawable->textures[ST_ATTACHMENT_FRONT_LEFT]); + } + + pipe->flush(pipe, NULL, 0); + + if (image) { + image->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate); + } + else if (loader->flushFrontBuffer) { + loader->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate); + } +} + +/** + * The struct dri_drawable flush_swapbuffers callback + */ +static void +dri2_flush_swapbuffers(struct dri_context *ctx, + struct dri_drawable *drawable) +{ + __DRIdrawable *dri_drawable = drawable->dPriv; + const __DRIimageLoaderExtension *image = drawable->sPriv->image.loader; + + if (image && image->base.version >= 3 && image->flushSwapBuffers) { + image->flushSwapBuffers(dri_drawable, dri_drawable->loaderPrivate); + } +} + +static void +dri2_update_tex_buffer(struct dri_drawable *drawable, + struct dri_context *ctx, + struct pipe_resource *res) +{ + /* no-op */ +} + +static __DRIimage * +dri2_create_image_from_winsys(__DRIscreen *_screen, + int width, int height, const struct dri2_format_mapping *map, + int num_handles, struct winsys_handle *whandle, + void *loaderPrivate) +{ + struct dri_screen *screen = dri_screen(_screen); + struct pipe_screen *pscreen = screen->base.screen; + __DRIimage *img; + struct pipe_resource templ; + unsigned tex_usage = 0; + int i; + bool use_lowered = false; + + if (pscreen->is_format_supported(pscreen, map->pipe_format, screen->target, 0, 0, + PIPE_BIND_RENDER_TARGET)) + tex_usage |= PIPE_BIND_RENDER_TARGET; + if (pscreen->is_format_supported(pscreen, map->pipe_format, screen->target, 0, 0, + PIPE_BIND_SAMPLER_VIEW)) + tex_usage |= PIPE_BIND_SAMPLER_VIEW; + + if (!tex_usage && util_format_is_yuv(map->pipe_format)) { + /* YUV format sampling can be emulated by the Mesa state tracker by + * using multiple samplers of varying formats. + * If no tex_usage is set and we detect a YUV format, + * test for support of all planes' sampler formats and + * add sampler view usage. + */ + use_lowered = true; + if (dri2_yuv_dma_buf_supported(screen, map)) + tex_usage |= PIPE_BIND_SAMPLER_VIEW; + } + + if (!tex_usage) + return NULL; + + img = CALLOC_STRUCT(__DRIimageRec); + if (!img) + return NULL; + + memset(&templ, 0, sizeof(templ)); + templ.bind = tex_usage; + templ.target = screen->target; + templ.last_level = 0; + templ.depth0 = 1; + templ.array_size = 1; + + for (i = (use_lowered ? map->nplanes : num_handles) - 1; i >= 0; i--) { + struct pipe_resource *tex; + + templ.next = img->texture; + templ.width0 = width >> map->planes[i].width_shift; + templ.height0 = height >> map->planes[i].height_shift; + if (use_lowered) + templ.format = dri2_get_pipe_format_for_dri_format(map->planes[i].dri_format); + else + templ.format = map->pipe_format; + assert(templ.format != PIPE_FORMAT_NONE); + + tex = pscreen->resource_from_handle(pscreen, + &templ, &whandle[use_lowered ? map->planes[i].buffer_index : i], + PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE); + if (!tex) { + pipe_resource_reference(&img->texture, NULL); + FREE(img); + return NULL; + } + + img->texture = tex; + } + + img->level = 0; + img->layer = 0; + img->use = 0; + img->loader_private = loaderPrivate; + + return img; +} + +static __DRIimage * +dri2_create_image_from_name(__DRIscreen *_screen, + int width, int height, int format, + int name, int pitch, void *loaderPrivate) +{ + const struct dri2_format_mapping *map = dri2_get_mapping_by_format(format); + struct winsys_handle whandle; + __DRIimage *img; + + if (!map) + return NULL; + + memset(&whandle, 0, sizeof(whandle)); + whandle.type = WINSYS_HANDLE_TYPE_SHARED; + whandle.handle = name; + whandle.format = map->pipe_format; + whandle.modifier = DRM_FORMAT_MOD_INVALID; + + whandle.stride = pitch * util_format_get_blocksize(map->pipe_format); + + img = dri2_create_image_from_winsys(_screen, width, height, map, + 1, &whandle, loaderPrivate); + + if (!img) + return NULL; + + img->dri_components = map->dri_components; + img->dri_fourcc = map->dri_fourcc; + img->dri_format = map->dri_format; + + return img; +} + +static unsigned +dri2_get_modifier_num_planes(uint64_t modifier, int fourcc) +{ + const struct dri2_format_mapping *map = dri2_get_mapping_by_fourcc(fourcc); + + if (!map) + return 0; + + switch (modifier) { + case I915_FORMAT_MOD_Y_TILED_CCS: + return 2; + case DRM_FORMAT_MOD_BROADCOM_UIF: + case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED: + case DRM_FORMAT_MOD_LINEAR: + /* DRM_FORMAT_MOD_NONE is the same as LINEAR */ + case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_EIGHT_GOB: + case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_FOUR_GOB: + case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_ONE_GOB: + case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_SIXTEEN_GOB: + case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_THIRTYTWO_GOB: + case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_TWO_GOB: + case DRM_FORMAT_MOD_QCOM_COMPRESSED: + case DRM_FORMAT_MOD_VIVANTE_SPLIT_SUPER_TILED: + case DRM_FORMAT_MOD_VIVANTE_SPLIT_TILED: + case DRM_FORMAT_MOD_VIVANTE_SUPER_TILED: + case DRM_FORMAT_MOD_VIVANTE_TILED: + /* FD_FORMAT_MOD_QCOM_TILED is not in drm_fourcc.h */ + case I915_FORMAT_MOD_X_TILED: + case I915_FORMAT_MOD_Y_TILED: + case DRM_FORMAT_MOD_INVALID: + return map->nplanes; + default: + return 0; + } +} + +static __DRIimage * +dri2_create_image_from_fd(__DRIscreen *_screen, + int width, int height, int fourcc, + uint64_t modifier, int *fds, int num_fds, + int *strides, int *offsets, unsigned *error, + void *loaderPrivate) +{ + struct winsys_handle whandles[3]; + const struct dri2_format_mapping *map = dri2_get_mapping_by_fourcc(fourcc); + __DRIimage *img = NULL; + unsigned err = __DRI_IMAGE_ERROR_SUCCESS; + int i, expected_num_fds; + int num_handles = dri2_get_modifier_num_planes(modifier, fourcc); + + if (!map || num_handles == 0) { + err = __DRI_IMAGE_ERROR_BAD_MATCH; + goto exit; + } + + switch (fourcc) { + case DRM_FORMAT_YUYV: + case DRM_FORMAT_UYVY: + expected_num_fds = 1; + break; + default: + expected_num_fds = num_handles; + break; + } + + if (num_fds != expected_num_fds) { + err = __DRI_IMAGE_ERROR_BAD_MATCH; + goto exit; + } + + memset(whandles, 0, sizeof(whandles)); + + for (i = 0; i < num_fds; i++) { + if (fds[i] < 0) { + err = __DRI_IMAGE_ERROR_BAD_ALLOC; + goto exit; + } + + whandles[i].type = WINSYS_HANDLE_TYPE_FD; + whandles[i].handle = (unsigned)fds[i]; + whandles[i].stride = (unsigned)strides[i]; + whandles[i].offset = (unsigned)offsets[i]; + whandles[i].format = map->pipe_format; + whandles[i].modifier = modifier; + whandles[i].plane = i; + } + + img = dri2_create_image_from_winsys(_screen, width, height, map, + num_fds, whandles, loaderPrivate); + if(img == NULL) { + err = __DRI_IMAGE_ERROR_BAD_ALLOC; + goto exit; + } + + img->dri_components = map->dri_components; + img->dri_fourcc = fourcc; + img->dri_format = map->dri_format; + img->imported_dmabuf = TRUE; + +exit: + if (error) + *error = err; + + return img; +} + +static __DRIimage * +dri2_create_image_common(__DRIscreen *_screen, + int width, int height, + int format, unsigned int use, + const uint64_t *modifiers, + const unsigned count, + void *loaderPrivate) +{ + const struct dri2_format_mapping *map = dri2_get_mapping_by_format(format); + struct dri_screen *screen = dri_screen(_screen); + __DRIimage *img; + struct pipe_resource templ; + unsigned tex_usage; + + if (!map) + return NULL; + + tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; + + if (use & __DRI_IMAGE_USE_SCANOUT) + tex_usage |= PIPE_BIND_SCANOUT; + if (use & __DRI_IMAGE_USE_SHARE) + tex_usage |= PIPE_BIND_SHARED; + if (use & __DRI_IMAGE_USE_LINEAR) + tex_usage |= PIPE_BIND_LINEAR; + if (use & __DRI_IMAGE_USE_CURSOR) { + if (width != 64 || height != 64) + return NULL; + tex_usage |= PIPE_BIND_CURSOR; + } + + img = CALLOC_STRUCT(__DRIimageRec); + if (!img) + return NULL; + + memset(&templ, 0, sizeof(templ)); + templ.bind = tex_usage; + templ.format = map->pipe_format; + templ.target = PIPE_TEXTURE_2D; + templ.last_level = 0; + templ.width0 = width; + templ.height0 = height; + templ.depth0 = 1; + templ.array_size = 1; + + if (modifiers) + img->texture = + screen->base.screen + ->resource_create_with_modifiers(screen->base.screen, + &templ, + modifiers, + count); + else + img->texture = + screen->base.screen->resource_create(screen->base.screen, &templ); + if (!img->texture) { + FREE(img); + return NULL; + } + + img->level = 0; + img->layer = 0; + img->dri_format = format; + img->dri_fourcc = map->dri_fourcc; + img->dri_components = 0; + img->use = use; + + img->loader_private = loaderPrivate; + return img; +} + +static __DRIimage * +dri2_create_image(__DRIscreen *_screen, + int width, int height, int format, + unsigned int use, void *loaderPrivate) +{ + return dri2_create_image_common(_screen, width, height, format, use, + NULL /* modifiers */, 0 /* count */, + loaderPrivate); +} + +static __DRIimage * +dri2_create_image_with_modifiers(__DRIscreen *dri_screen, + int width, int height, int format, + const uint64_t *modifiers, + const unsigned count, + void *loaderPrivate) +{ + return dri2_create_image_common(dri_screen, width, height, format, + __DRI_IMAGE_USE_SHARE, modifiers, count, + loaderPrivate); +} + +static bool +dri2_query_image_common(__DRIimage *image, int attrib, int *value) +{ + switch (attrib) { + case __DRI_IMAGE_ATTRIB_FORMAT: + *value = image->dri_format; + return true; + case __DRI_IMAGE_ATTRIB_WIDTH: + *value = image->texture->width0; + return true; + case __DRI_IMAGE_ATTRIB_HEIGHT: + *value = image->texture->height0; + return true; + case __DRI_IMAGE_ATTRIB_COMPONENTS: + if (image->dri_components == 0) + return false; + *value = image->dri_components; + return true; + case __DRI_IMAGE_ATTRIB_FOURCC: + if (image->dri_fourcc) { + *value = image->dri_fourcc; + } else { + const struct dri2_format_mapping *map; + + map = dri2_get_mapping_by_format(image->dri_format); + if (!map) + return false; + + *value = map->dri_fourcc; + } + return true; + default: + return false; + } +} + +static bool +dri2_query_image_by_resource_handle(__DRIimage *image, int attrib, int *value) +{ + struct pipe_screen *pscreen = image->texture->screen; + struct winsys_handle whandle; + unsigned usage; + memset(&whandle, 0, sizeof(whandle)); + whandle.plane = image->plane; + + switch (attrib) { + case __DRI_IMAGE_ATTRIB_STRIDE: + case __DRI_IMAGE_ATTRIB_OFFSET: + case __DRI_IMAGE_ATTRIB_HANDLE: + whandle.type = WINSYS_HANDLE_TYPE_KMS; + break; + case __DRI_IMAGE_ATTRIB_NAME: + whandle.type = WINSYS_HANDLE_TYPE_SHARED; + break; + case __DRI_IMAGE_ATTRIB_FD: + whandle.type = WINSYS_HANDLE_TYPE_FD; + break; + case __DRI_IMAGE_ATTRIB_NUM_PLANES: + *value = 1; + return true; + case __DRI_IMAGE_ATTRIB_MODIFIER_UPPER: + case __DRI_IMAGE_ATTRIB_MODIFIER_LOWER: + whandle.type = WINSYS_HANDLE_TYPE_KMS; + whandle.modifier = DRM_FORMAT_MOD_INVALID; + break; + default: + return false; + } + + usage = PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE; + + if (image->use & __DRI_IMAGE_USE_BACKBUFFER) + usage |= PIPE_HANDLE_USAGE_EXPLICIT_FLUSH; + + if (!pscreen->resource_get_handle(pscreen, NULL, image->texture, + &whandle, usage)) + return false; + + switch (attrib) { + case __DRI_IMAGE_ATTRIB_STRIDE: + *value = whandle.stride; + return true; + case __DRI_IMAGE_ATTRIB_OFFSET: + *value = whandle.offset; + return true; + case __DRI_IMAGE_ATTRIB_HANDLE: + case __DRI_IMAGE_ATTRIB_NAME: + case __DRI_IMAGE_ATTRIB_FD: + *value = whandle.handle; + return true; + case __DRI_IMAGE_ATTRIB_MODIFIER_UPPER: + if (whandle.modifier == DRM_FORMAT_MOD_INVALID) + return false; + *value = (whandle.modifier >> 32) & 0xffffffff; + return true; + case __DRI_IMAGE_ATTRIB_MODIFIER_LOWER: + if (whandle.modifier == DRM_FORMAT_MOD_INVALID) + return false; + *value = whandle.modifier & 0xffffffff; + return true; + default: + return false; + } +} + +static bool +dri2_resource_get_param(__DRIimage *image, enum pipe_resource_param param, + unsigned handle_usage, uint64_t *value) +{ + struct pipe_screen *pscreen = image->texture->screen; + if (!pscreen->resource_get_param) + return false; + + return pscreen->resource_get_param(pscreen, NULL, image->texture, + image->plane, 0, param, handle_usage, + value); +} + +static bool +dri2_query_image_by_resource_param(__DRIimage *image, int attrib, int *value) +{ + enum pipe_resource_param param; + uint64_t res_param; + unsigned handle_usage; + + if (!image->texture->screen->resource_get_param) + return false; + + switch (attrib) { + case __DRI_IMAGE_ATTRIB_STRIDE: + param = PIPE_RESOURCE_PARAM_STRIDE; + break; + case __DRI_IMAGE_ATTRIB_OFFSET: + param = PIPE_RESOURCE_PARAM_OFFSET; + break; + case __DRI_IMAGE_ATTRIB_NUM_PLANES: + param = PIPE_RESOURCE_PARAM_NPLANES; + break; + case __DRI_IMAGE_ATTRIB_MODIFIER_UPPER: + case __DRI_IMAGE_ATTRIB_MODIFIER_LOWER: + param = PIPE_RESOURCE_PARAM_MODIFIER; + break; + case __DRI_IMAGE_ATTRIB_HANDLE: + param = PIPE_RESOURCE_PARAM_HANDLE_TYPE_KMS; + break; + case __DRI_IMAGE_ATTRIB_NAME: + param = PIPE_RESOURCE_PARAM_HANDLE_TYPE_SHARED; + break; + case __DRI_IMAGE_ATTRIB_FD: + param = PIPE_RESOURCE_PARAM_HANDLE_TYPE_FD; + break; + default: + return false; + } + + handle_usage = PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE; + + if (image->use & __DRI_IMAGE_USE_BACKBUFFER) + handle_usage |= PIPE_HANDLE_USAGE_EXPLICIT_FLUSH; + + if (!dri2_resource_get_param(image, param, handle_usage, &res_param)) + return false; + + switch (attrib) { + case __DRI_IMAGE_ATTRIB_STRIDE: + case __DRI_IMAGE_ATTRIB_OFFSET: + case __DRI_IMAGE_ATTRIB_NUM_PLANES: + if (res_param > INT_MAX) + return false; + *value = (int)res_param; + return true; + case __DRI_IMAGE_ATTRIB_HANDLE: + case __DRI_IMAGE_ATTRIB_NAME: + case __DRI_IMAGE_ATTRIB_FD: + if (res_param > UINT_MAX) + return false; + *value = (int)res_param; + return true; + case __DRI_IMAGE_ATTRIB_MODIFIER_UPPER: + if (res_param == DRM_FORMAT_MOD_INVALID) + return false; + *value = (res_param >> 32) & 0xffffffff; + return true; + case __DRI_IMAGE_ATTRIB_MODIFIER_LOWER: + if (res_param == DRM_FORMAT_MOD_INVALID) + return false; + *value = res_param & 0xffffffff; + return true; + default: + return false; + } +} + +static GLboolean +dri2_query_image(__DRIimage *image, int attrib, int *value) +{ + if (dri2_query_image_common(image, attrib, value)) + return GL_TRUE; + else if (dri2_query_image_by_resource_param(image, attrib, value)) + return GL_TRUE; + else if (dri2_query_image_by_resource_handle(image, attrib, value)) + return GL_TRUE; + else + return GL_FALSE; +} + +static __DRIimage * +dri2_dup_image(__DRIimage *image, void *loaderPrivate) +{ + __DRIimage *img; + + img = CALLOC_STRUCT(__DRIimageRec); + if (!img) + return NULL; + + img->texture = NULL; + pipe_resource_reference(&img->texture, image->texture); + img->level = image->level; + img->layer = image->layer; + img->dri_format = image->dri_format; + /* This should be 0 for sub images, but dup is also used for base images. */ + img->dri_components = image->dri_components; + img->loader_private = loaderPrivate; + + return img; +} + +static GLboolean +dri2_validate_usage(__DRIimage *image, unsigned int use) +{ + if (!image || !image->texture) + return false; + + struct pipe_screen *screen = image->texture->screen; + if (!screen->check_resource_capability) + return true; + + /* We don't want to check these: + * __DRI_IMAGE_USE_SHARE (all images are shareable) + * __DRI_IMAGE_USE_BACKBUFFER (all images support this) + */ + unsigned bind = 0; + if (use & __DRI_IMAGE_USE_SCANOUT) + bind |= PIPE_BIND_SCANOUT; + if (use & __DRI_IMAGE_USE_LINEAR) + bind |= PIPE_BIND_LINEAR; + if (use & __DRI_IMAGE_USE_CURSOR) + bind |= PIPE_BIND_CURSOR; + + if (!bind) + return true; + + return screen->check_resource_capability(screen, image->texture, bind); +} + +static __DRIimage * +dri2_from_names(__DRIscreen *screen, int width, int height, int format, + int *names, int num_names, int *strides, int *offsets, + void *loaderPrivate) +{ + const struct dri2_format_mapping *map = dri2_get_mapping_by_format(format); + __DRIimage *img; + struct winsys_handle whandle; + + if (!map) + return NULL; + + if (num_names != 1) + return NULL; + + memset(&whandle, 0, sizeof(whandle)); + whandle.type = WINSYS_HANDLE_TYPE_SHARED; + whandle.handle = names[0]; + whandle.stride = strides[0]; + whandle.offset = offsets[0]; + whandle.format = map->pipe_format; + whandle.modifier = DRM_FORMAT_MOD_INVALID; + + img = dri2_create_image_from_winsys(screen, width, height, map, + 1, &whandle, loaderPrivate); + if (img == NULL) + return NULL; + + img->dri_components = map->dri_components; + img->dri_fourcc = map->dri_fourcc; + img->dri_format = map->pipe_format; + + return img; +} + +static __DRIimage * +dri2_from_planar(__DRIimage *image, int plane, void *loaderPrivate) +{ + __DRIimage *img; + + if (plane < 0) { + return NULL; + } else if (plane > 0) { + uint64_t planes; + if (!dri2_resource_get_param(image, PIPE_RESOURCE_PARAM_NPLANES, 0, + &planes) || + plane >= planes) { + return NULL; + } + } + + if (image->dri_components == 0) { + uint64_t modifier; + if (!dri2_resource_get_param(image, PIPE_RESOURCE_PARAM_MODIFIER, 0, + &modifier) || + modifier == DRM_FORMAT_MOD_INVALID) { + return NULL; + } + } + + img = dri2_dup_image(image, loaderPrivate); + if (img == NULL) + return NULL; + + if (img->texture->screen->resource_changed) + img->texture->screen->resource_changed(img->texture->screen, + img->texture); + + /* set this to 0 for sub images. */ + img->dri_components = 0; + img->plane = plane; + return img; +} + +static __DRIimage * +dri2_from_fds(__DRIscreen *screen, int width, int height, int fourcc, + int *fds, int num_fds, int *strides, int *offsets, + void *loaderPrivate) +{ + return dri2_create_image_from_fd(screen, width, height, fourcc, + DRM_FORMAT_MOD_INVALID, fds, num_fds, + strides, offsets, NULL, loaderPrivate); +} + +static boolean +dri2_query_dma_buf_modifiers(__DRIscreen *_screen, int fourcc, int max, + uint64_t *modifiers, unsigned int *external_only, + int *count) +{ + struct dri_screen *screen = dri_screen(_screen); + struct pipe_screen *pscreen = screen->base.screen; + const struct dri2_format_mapping *map = dri2_get_mapping_by_fourcc(fourcc); + enum pipe_format format; + + if (!map) + return false; + + format = map->pipe_format; + + if (pscreen->is_format_supported(pscreen, format, screen->target, 0, 0, + PIPE_BIND_RENDER_TARGET) || + pscreen->is_format_supported(pscreen, format, screen->target, 0, 0, + PIPE_BIND_SAMPLER_VIEW) || + dri2_yuv_dma_buf_supported(screen, map)) { + if (pscreen->query_dmabuf_modifiers != NULL) + pscreen->query_dmabuf_modifiers(pscreen, format, max, modifiers, + external_only, count); + else + *count = 0; + return true; + } + return false; +} + +static boolean +dri2_query_dma_buf_format_modifier_attribs(__DRIscreen *_screen, + uint32_t fourcc, uint64_t modifier, + int attrib, uint64_t *value) +{ + struct dri_screen *screen = dri_screen(_screen); + struct pipe_screen *pscreen = screen->base.screen; + + if (!pscreen->query_dmabuf_modifiers) + return false; + + switch (attrib) { + case __DRI_IMAGE_FORMAT_MODIFIER_ATTRIB_PLANE_COUNT: { + uint64_t mod_planes = dri2_get_modifier_num_planes(modifier, fourcc); + if (mod_planes > 0) + *value = mod_planes; + return mod_planes > 0; + } + default: + return false; + } +} + +static __DRIimage * +dri2_from_dma_bufs(__DRIscreen *screen, + int width, int height, int fourcc, + int *fds, int num_fds, + int *strides, int *offsets, + enum __DRIYUVColorSpace yuv_color_space, + enum __DRISampleRange sample_range, + enum __DRIChromaSiting horizontal_siting, + enum __DRIChromaSiting vertical_siting, + unsigned *error, + void *loaderPrivate) +{ + __DRIimage *img; + + img = dri2_create_image_from_fd(screen, width, height, fourcc, + DRM_FORMAT_MOD_INVALID, fds, num_fds, + strides, offsets, error, loaderPrivate); + if (img == NULL) + return NULL; + + img->yuv_color_space = yuv_color_space; + img->sample_range = sample_range; + img->horizontal_siting = horizontal_siting; + img->vertical_siting = vertical_siting; + + *error = __DRI_IMAGE_ERROR_SUCCESS; + return img; +} + +static __DRIimage * +dri2_from_dma_bufs2(__DRIscreen *screen, + int width, int height, int fourcc, + uint64_t modifier, int *fds, int num_fds, + int *strides, int *offsets, + enum __DRIYUVColorSpace yuv_color_space, + enum __DRISampleRange sample_range, + enum __DRIChromaSiting horizontal_siting, + enum __DRIChromaSiting vertical_siting, + unsigned *error, + void *loaderPrivate) +{ + __DRIimage *img; + + img = dri2_create_image_from_fd(screen, width, height, fourcc, + modifier, fds, num_fds, strides, offsets, + error, loaderPrivate); + if (img == NULL) + return NULL; + + img->yuv_color_space = yuv_color_space; + img->sample_range = sample_range; + img->horizontal_siting = horizontal_siting; + img->vertical_siting = vertical_siting; + + *error = __DRI_IMAGE_ERROR_SUCCESS; + return img; +} + +static void +dri2_blit_image(__DRIcontext *context, __DRIimage *dst, __DRIimage *src, + int dstx0, int dsty0, int dstwidth, int dstheight, + int srcx0, int srcy0, int srcwidth, int srcheight, + int flush_flag) +{ + struct dri_context *ctx = dri_context(context); + struct pipe_context *pipe = ctx->st->pipe; + struct pipe_screen *screen; + struct pipe_fence_handle *fence; + struct pipe_blit_info blit; + + if (!dst || !src) + return; + + memset(&blit, 0, sizeof(blit)); + blit.dst.resource = dst->texture; + blit.dst.box.x = dstx0; + blit.dst.box.y = dsty0; + blit.dst.box.width = dstwidth; + blit.dst.box.height = dstheight; + blit.dst.box.depth = 1; + blit.dst.format = dst->texture->format; + blit.src.resource = src->texture; + blit.src.box.x = srcx0; + blit.src.box.y = srcy0; + blit.src.box.width = srcwidth; + blit.src.box.height = srcheight; + blit.src.box.depth = 1; + blit.src.format = src->texture->format; + blit.mask = PIPE_MASK_RGBA; + blit.filter = PIPE_TEX_FILTER_NEAREST; + + pipe->blit(pipe, &blit); + + if (flush_flag == __BLIT_FLAG_FLUSH) { + pipe->flush_resource(pipe, dst->texture); + ctx->st->flush(ctx->st, 0, NULL, NULL, NULL); + } else if (flush_flag == __BLIT_FLAG_FINISH) { + screen = dri_screen(ctx->sPriv)->base.screen; + pipe->flush_resource(pipe, dst->texture); + ctx->st->flush(ctx->st, 0, &fence, NULL, NULL); + (void) screen->fence_finish(screen, NULL, fence, PIPE_TIMEOUT_INFINITE); + screen->fence_reference(screen, &fence, NULL); + } +} + +static void * +dri2_map_image(__DRIcontext *context, __DRIimage *image, + int x0, int y0, int width, int height, + unsigned int flags, int *stride, void **data) +{ + struct dri_context *ctx = dri_context(context); + struct pipe_context *pipe = ctx->st->pipe; + enum pipe_transfer_usage pipe_access = 0; + struct pipe_transfer *trans; + void *map; + + if (!image || !data || *data) + return NULL; + + if (flags & __DRI_IMAGE_TRANSFER_READ) + pipe_access |= PIPE_TRANSFER_READ; + if (flags & __DRI_IMAGE_TRANSFER_WRITE) + pipe_access |= PIPE_TRANSFER_WRITE; + + map = pipe_transfer_map(pipe, image->texture, + 0, 0, pipe_access, x0, y0, width, height, + &trans); + if (map) { + *data = trans; + *stride = trans->stride; + } + + return map; +} + +static void +dri2_unmap_image(__DRIcontext *context, __DRIimage *image, void *data) +{ + struct dri_context *ctx = dri_context(context); + struct pipe_context *pipe = ctx->st->pipe; + + pipe_transfer_unmap(pipe, (struct pipe_transfer *)data); +} + +static int +dri2_get_capabilities(__DRIscreen *_screen) +{ + struct dri_screen *screen = dri_screen(_screen); + + return (screen->can_share_buffer ? __DRI_IMAGE_CAP_GLOBAL_NAMES : 0); +} + +/* The extension is modified during runtime if DRI_PRIME is detected */ +static __DRIimageExtension dri2ImageExtension = { + .base = { __DRI_IMAGE, 17 }, + + .createImageFromName = dri2_create_image_from_name, + .createImageFromRenderbuffer = dri2_create_image_from_renderbuffer, + .destroyImage = dri2_destroy_image, + .createImage = dri2_create_image, + .queryImage = dri2_query_image, + .dupImage = dri2_dup_image, + .validateUsage = dri2_validate_usage, + .createImageFromNames = dri2_from_names, + .fromPlanar = dri2_from_planar, + .createImageFromTexture = dri2_create_from_texture, + .createImageFromFds = NULL, + .createImageFromDmaBufs = NULL, + .blitImage = dri2_blit_image, + .getCapabilities = dri2_get_capabilities, + .mapImage = dri2_map_image, + .unmapImage = dri2_unmap_image, + .createImageWithModifiers = NULL, + .createImageFromDmaBufs2 = NULL, + .queryDmaBufFormats = NULL, + .queryDmaBufModifiers = NULL, + .queryDmaBufFormatModifierAttribs = NULL, + .createImageFromRenderbuffer2 = dri2_create_image_from_renderbuffer2, +}; + +static const __DRIrobustnessExtension dri2Robustness = { + .base = { __DRI2_ROBUSTNESS, 1 } +}; + +static int +dri2_interop_query_device_info(__DRIcontext *_ctx, + struct mesa_glinterop_device_info *out) +{ + struct pipe_screen *screen = dri_context(_ctx)->st->pipe->screen; + + /* There is no version 0, thus we do not support it */ + if (out->version == 0) + return MESA_GLINTEROP_INVALID_VERSION; + + out->pci_segment_group = screen->get_param(screen, PIPE_CAP_PCI_GROUP); + out->pci_bus = screen->get_param(screen, PIPE_CAP_PCI_BUS); + out->pci_device = screen->get_param(screen, PIPE_CAP_PCI_DEVICE); + out->pci_function = screen->get_param(screen, PIPE_CAP_PCI_FUNCTION); + + out->vendor_id = screen->get_param(screen, PIPE_CAP_VENDOR_ID); + out->device_id = screen->get_param(screen, PIPE_CAP_DEVICE_ID); + + /* Instruct the caller that we support up-to version one of the interface */ + out->version = 1; + + return MESA_GLINTEROP_SUCCESS; +} + +static int +dri2_interop_export_object(__DRIcontext *_ctx, + struct mesa_glinterop_export_in *in, + struct mesa_glinterop_export_out *out) +{ + struct st_context_iface *st = dri_context(_ctx)->st; + struct pipe_screen *screen = st->pipe->screen; + struct gl_context *ctx = ((struct st_context *)st)->ctx; + struct pipe_resource *res = NULL; + struct winsys_handle whandle; + unsigned target, usage; + boolean success; + + /* There is no version 0, thus we do not support it */ + if (in->version == 0 || out->version == 0) + return MESA_GLINTEROP_INVALID_VERSION; + + /* Validate the target. */ + switch (in->target) { + case GL_TEXTURE_BUFFER: + case GL_TEXTURE_1D: + case GL_TEXTURE_2D: + case GL_TEXTURE_3D: + case GL_TEXTURE_RECTANGLE: + case GL_TEXTURE_1D_ARRAY: + case GL_TEXTURE_2D_ARRAY: + case GL_TEXTURE_CUBE_MAP_ARRAY: + case GL_TEXTURE_CUBE_MAP: + case GL_TEXTURE_2D_MULTISAMPLE: + case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: + case GL_TEXTURE_EXTERNAL_OES: + case GL_RENDERBUFFER: + case GL_ARRAY_BUFFER: + target = in->target; + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + target = GL_TEXTURE_CUBE_MAP; + break; + default: + return MESA_GLINTEROP_INVALID_TARGET; + } + + /* Validate the simple case of miplevel. */ + if ((target == GL_RENDERBUFFER || target == GL_ARRAY_BUFFER) && + in->miplevel != 0) + return MESA_GLINTEROP_INVALID_MIP_LEVEL; + + /* Validate the OpenGL object and get pipe_resource. */ + simple_mtx_lock(&ctx->Shared->Mutex); + + if (target == GL_ARRAY_BUFFER) { + /* Buffer objects. + * + * The error checking is based on the documentation of + * clCreateFromGLBuffer from OpenCL 2.0 SDK. + */ + struct gl_buffer_object *buf = _mesa_lookup_bufferobj(ctx, in->obj); + + /* From OpenCL 2.0 SDK, clCreateFromGLBuffer: + * "CL_INVALID_GL_OBJECT if bufobj is not a GL buffer object or is + * a GL buffer object but does not have an existing data store or + * the size of the buffer is 0." + */ + if (!buf || buf->Size == 0) { + simple_mtx_unlock(&ctx->Shared->Mutex); + return MESA_GLINTEROP_INVALID_OBJECT; + } + + res = st_buffer_object(buf)->buffer; + if (!res) { + /* this shouldn't happen */ + simple_mtx_unlock(&ctx->Shared->Mutex); + return MESA_GLINTEROP_INVALID_OBJECT; + } + + out->buf_offset = 0; + out->buf_size = buf->Size; + + buf->UsageHistory |= USAGE_DISABLE_MINMAX_CACHE; + } else if (target == GL_RENDERBUFFER) { + /* Renderbuffers. + * + * The error checking is based on the documentation of + * clCreateFromGLRenderbuffer from OpenCL 2.0 SDK. + */ + struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, in->obj); + + /* From OpenCL 2.0 SDK, clCreateFromGLRenderbuffer: + * "CL_INVALID_GL_OBJECT if renderbuffer is not a GL renderbuffer + * object or if the width or height of renderbuffer is zero." + */ + if (!rb || rb->Width == 0 || rb->Height == 0) { + simple_mtx_unlock(&ctx->Shared->Mutex); + return MESA_GLINTEROP_INVALID_OBJECT; + } + + /* From OpenCL 2.0 SDK, clCreateFromGLRenderbuffer: + * "CL_INVALID_OPERATION if renderbuffer is a multi-sample GL + * renderbuffer object." + */ + if (rb->NumSamples > 1) { + simple_mtx_unlock(&ctx->Shared->Mutex); + return MESA_GLINTEROP_INVALID_OPERATION; + } + + /* From OpenCL 2.0 SDK, clCreateFromGLRenderbuffer: + * "CL_OUT_OF_RESOURCES if there is a failure to allocate resources + * required by the OpenCL implementation on the device." + */ + res = st_renderbuffer(rb)->texture; + if (!res) { + simple_mtx_unlock(&ctx->Shared->Mutex); + return MESA_GLINTEROP_OUT_OF_RESOURCES; + } + + out->internal_format = rb->InternalFormat; + out->view_minlevel = 0; + out->view_numlevels = 1; + out->view_minlayer = 0; + out->view_numlayers = 1; + } else { + /* Texture objects. + * + * The error checking is based on the documentation of + * clCreateFromGLTexture from OpenCL 2.0 SDK. + */ + struct gl_texture_object *obj = _mesa_lookup_texture(ctx, in->obj); + + if (obj) + _mesa_test_texobj_completeness(ctx, obj); + + /* From OpenCL 2.0 SDK, clCreateFromGLTexture: + * "CL_INVALID_GL_OBJECT if texture is not a GL texture object whose + * type matches texture_target, if the specified miplevel of texture + * is not defined, or if the width or height of the specified + * miplevel is zero or if the GL texture object is incomplete." + */ + if (!obj || + obj->Target != target || + !obj->_BaseComplete || + (in->miplevel > 0 && !obj->_MipmapComplete)) { + simple_mtx_unlock(&ctx->Shared->Mutex); + return MESA_GLINTEROP_INVALID_OBJECT; + } + + if (target == GL_TEXTURE_BUFFER) { + struct st_buffer_object *stBuf = + st_buffer_object(obj->BufferObject); + + if (!stBuf || !stBuf->buffer) { + /* this shouldn't happen */ + simple_mtx_unlock(&ctx->Shared->Mutex); + return MESA_GLINTEROP_INVALID_OBJECT; + } + res = stBuf->buffer; + + out->internal_format = obj->BufferObjectFormat; + out->buf_offset = obj->BufferOffset; + out->buf_size = obj->BufferSize == -1 ? obj->BufferObject->Size : + obj->BufferSize; + + obj->BufferObject->UsageHistory |= USAGE_DISABLE_MINMAX_CACHE; + } else { + /* From OpenCL 2.0 SDK, clCreateFromGLTexture: + * "CL_INVALID_MIP_LEVEL if miplevel is less than the value of + * levelbase (for OpenGL implementations) or zero (for OpenGL ES + * implementations); or greater than the value of q (for both OpenGL + * and OpenGL ES). levelbase and q are defined for the texture in + * section 3.8.10 (Texture Completeness) of the OpenGL 2.1 + * specification and section 3.7.10 of the OpenGL ES 2.0." + */ + if (in->miplevel < obj->BaseLevel || in->miplevel > obj->_MaxLevel) { + simple_mtx_unlock(&ctx->Shared->Mutex); + return MESA_GLINTEROP_INVALID_MIP_LEVEL; + } + + if (!st_finalize_texture(ctx, st->pipe, obj, 0)) { + simple_mtx_unlock(&ctx->Shared->Mutex); + return MESA_GLINTEROP_OUT_OF_RESOURCES; + } + + res = st_get_texobj_resource(obj); + if (!res) { + /* Incomplete texture buffer object? This shouldn't really occur. */ + simple_mtx_unlock(&ctx->Shared->Mutex); + return MESA_GLINTEROP_INVALID_OBJECT; + } + + out->internal_format = obj->Image[0][0]->InternalFormat; + out->view_minlevel = obj->MinLevel; + out->view_numlevels = obj->NumLevels; + out->view_minlayer = obj->MinLayer; + out->view_numlayers = obj->NumLayers; + } + } + + /* Get the handle. */ + switch (in->access) { + case MESA_GLINTEROP_ACCESS_READ_ONLY: + usage = 0; + break; + case MESA_GLINTEROP_ACCESS_READ_WRITE: + case MESA_GLINTEROP_ACCESS_WRITE_ONLY: + usage = PIPE_HANDLE_USAGE_SHADER_WRITE; + break; + default: + usage = 0; + } + + memset(&whandle, 0, sizeof(whandle)); + whandle.type = WINSYS_HANDLE_TYPE_FD; + + success = screen->resource_get_handle(screen, st->pipe, res, &whandle, + usage); + simple_mtx_unlock(&ctx->Shared->Mutex); + + if (!success) + return MESA_GLINTEROP_OUT_OF_HOST_MEMORY; + + out->dmabuf_fd = whandle.handle; + out->out_driver_data_written = 0; + + if (res->target == PIPE_BUFFER) + out->buf_offset += whandle.offset; + + /* Instruct the caller that we support up-to version one of the interface */ + in->version = 1; + out->version = 1; + + return MESA_GLINTEROP_SUCCESS; +} + +static const __DRI2interopExtension dri2InteropExtension = { + .base = { __DRI2_INTEROP, 1 }, + .query_device_info = dri2_interop_query_device_info, + .export_object = dri2_interop_export_object +}; + +/** + * \brief the DRI2bufferDamageExtension set_damage_region method + */ +static void +dri2_set_damage_region(__DRIdrawable *dPriv, unsigned int nrects, int *rects) +{ + struct dri_drawable *drawable = dri_drawable(dPriv); + struct pipe_box *boxes = NULL; + + if (nrects) { + boxes = CALLOC(nrects, sizeof(*boxes)); + assert(boxes); + + for (unsigned int i = 0; i < nrects; i++) { + int *rect = &rects[i * 4]; + + u_box_2d(rect[0], rect[1], rect[2], rect[3], &boxes[i]); + } + } + + FREE(drawable->damage_rects); + drawable->damage_rects = boxes; + drawable->num_damage_rects = nrects; + + /* Only apply the damage region if the BACK_LEFT texture is up-to-date. */ + if (drawable->texture_stamp == drawable->dPriv->lastStamp && + (drawable->texture_mask & (1 << ST_ATTACHMENT_BACK_LEFT))) { + struct pipe_screen *screen = drawable->screen->base.screen; + struct pipe_resource *resource; + + if (drawable->stvis.samples > 1) + resource = drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT]; + else + resource = drawable->textures[ST_ATTACHMENT_BACK_LEFT]; + + screen->set_damage_region(screen, resource, + drawable->num_damage_rects, + drawable->damage_rects); + } +} + +static __DRI2bufferDamageExtension dri2BufferDamageExtension = { + .base = { __DRI2_BUFFER_DAMAGE, 1 }, +}; + +/** + * \brief the DRI2ConfigQueryExtension configQueryb method + */ +static int +dri2GalliumConfigQueryb(__DRIscreen *sPriv, const char *var, + unsigned char *val) +{ + struct dri_screen *screen = dri_screen(sPriv); + + if (!driCheckOption(&screen->dev->option_cache, var, DRI_BOOL)) + return dri2ConfigQueryExtension.configQueryb(sPriv, var, val); + + *val = driQueryOptionb(&screen->dev->option_cache, var); + + return 0; +} + +/** + * \brief the DRI2ConfigQueryExtension configQueryi method + */ +static int +dri2GalliumConfigQueryi(__DRIscreen *sPriv, const char *var, int *val) +{ + struct dri_screen *screen = dri_screen(sPriv); + + if (!driCheckOption(&screen->dev->option_cache, var, DRI_INT) && + !driCheckOption(&screen->dev->option_cache, var, DRI_ENUM)) + return dri2ConfigQueryExtension.configQueryi(sPriv, var, val); + + *val = driQueryOptioni(&screen->dev->option_cache, var); + + return 0; +} + +/** + * \brief the DRI2ConfigQueryExtension configQueryf method + */ +static int +dri2GalliumConfigQueryf(__DRIscreen *sPriv, const char *var, float *val) +{ + struct dri_screen *screen = dri_screen(sPriv); + + if (!driCheckOption(&screen->dev->option_cache, var, DRI_FLOAT)) + return dri2ConfigQueryExtension.configQueryf(sPriv, var, val); + + *val = driQueryOptionf(&screen->dev->option_cache, var); + + return 0; +} + +/** + * \brief the DRI2ConfigQueryExtension struct. + * + * We first query the driver option cache. Then the dri2 option cache. + */ +static const __DRI2configQueryExtension dri2GalliumConfigQueryExtension = { + .base = { __DRI2_CONFIG_QUERY, 1 }, + + .configQueryb = dri2GalliumConfigQueryb, + .configQueryi = dri2GalliumConfigQueryi, + .configQueryf = dri2GalliumConfigQueryf, +}; + +/** + * \brief the DRI2blobExtension set_cache_funcs method + */ +static void +set_blob_cache_funcs(__DRIscreen *sPriv, __DRIblobCacheSet set, + __DRIblobCacheGet get) +{ + struct dri_screen *screen = dri_screen(sPriv); + struct pipe_screen *pscreen = screen->base.screen; + + if (!pscreen->get_disk_shader_cache) + return; + + struct disk_cache *cache = pscreen->get_disk_shader_cache(pscreen); + + if (!cache) + return; + + disk_cache_set_callbacks(cache, set, get); +} + +static const __DRI2blobExtension driBlobExtension = { + .base = { __DRI2_BLOB, 1 }, + .set_cache_funcs = set_blob_cache_funcs +}; + +/* + * Backend function init_screen. + */ + +static const __DRIextension *dri_screen_extensions[] = { + &driTexBufferExtension.base, + &dri2FlushExtension.base, + &dri2ImageExtension.base, + &dri2RendererQueryExtension.base, + &dri2GalliumConfigQueryExtension.base, + &dri2ThrottleExtension.base, + &dri2FenceExtension.base, + &dri2BufferDamageExtension.base, + &dri2InteropExtension.base, + &dri2NoErrorExtension.base, + &driBlobExtension.base, + NULL +}; + +static const __DRIextension *dri_robust_screen_extensions[] = { + &driTexBufferExtension.base, + &dri2FlushExtension.base, + &dri2ImageExtension.base, + &dri2RendererQueryExtension.base, + &dri2GalliumConfigQueryExtension.base, + &dri2ThrottleExtension.base, + &dri2FenceExtension.base, + &dri2InteropExtension.base, + &dri2BufferDamageExtension.base, + &dri2Robustness.base, + &dri2NoErrorExtension.base, + &driBlobExtension.base, + NULL +}; + +/** + * This is the driver specific part of the createNewScreen entry point. + * + * Returns the struct gl_config supported by this driver. + */ +static const __DRIconfig ** +dri2_init_screen(__DRIscreen * sPriv) +{ + const __DRIconfig **configs; + struct dri_screen *screen; + struct pipe_screen *pscreen = NULL; + + screen = CALLOC_STRUCT(dri_screen); + if (!screen) + return NULL; + + screen->sPriv = sPriv; + screen->fd = sPriv->fd; + (void) mtx_init(&screen->opencl_func_mutex, mtx_plain); + + sPriv->driverPrivate = (void *)screen; + + if (pipe_loader_drm_probe_fd(&screen->dev, screen->fd)) { + dri_init_options(screen); + + pscreen = pipe_loader_create_screen(screen->dev); + } + + if (!pscreen) + goto release_pipe; + + screen->throttle = pscreen->get_param(pscreen, PIPE_CAP_THROTTLE); + + if (pscreen->resource_create_with_modifiers) + dri2ImageExtension.createImageWithModifiers = + dri2_create_image_with_modifiers; + + if (pscreen->get_param(pscreen, PIPE_CAP_DMABUF)) { + uint64_t cap; + + if (drmGetCap(sPriv->fd, DRM_CAP_PRIME, &cap) == 0 && + (cap & DRM_PRIME_CAP_IMPORT)) { + dri2ImageExtension.createImageFromFds = dri2_from_fds; + dri2ImageExtension.createImageFromDmaBufs = dri2_from_dma_bufs; + dri2ImageExtension.createImageFromDmaBufs2 = dri2_from_dma_bufs2; + dri2ImageExtension.queryDmaBufFormats = dri2_query_dma_buf_formats; + dri2ImageExtension.queryDmaBufModifiers = + dri2_query_dma_buf_modifiers; + dri2ImageExtension.queryDmaBufFormatModifierAttribs = + dri2_query_dma_buf_format_modifier_attribs; + } + } + + if (pscreen->set_damage_region) + dri2BufferDamageExtension.set_damage_region = dri2_set_damage_region; + + if (pscreen->get_param(pscreen, PIPE_CAP_DEVICE_RESET_STATUS_QUERY)) { + sPriv->extensions = dri_robust_screen_extensions; + screen->has_reset_status_query = true; + } + else + sPriv->extensions = dri_screen_extensions; + + configs = dri_init_screen_helper(screen, pscreen); + if (!configs) + goto destroy_screen; + + screen->can_share_buffer = true; + screen->auto_fake_front = dri_with_format(sPriv); + screen->broken_invalidate = !sPriv->dri2.useInvalidate; + screen->lookup_egl_image = dri2_lookup_egl_image; + + return configs; + +destroy_screen: + dri_destroy_screen_helper(screen); + +release_pipe: + if (screen->dev) + pipe_loader_release(&screen->dev, 1); + + FREE(screen); + return NULL; +} + +/** + * This is the driver specific part of the createNewScreen entry point. + * + * Returns the struct gl_config supported by this driver. + */ +static const __DRIconfig ** +dri_kms_init_screen(__DRIscreen * sPriv) +{ +#if defined(GALLIUM_SOFTPIPE) + const __DRIconfig **configs; + struct dri_screen *screen; + struct pipe_screen *pscreen = NULL; + uint64_t cap; + + screen = CALLOC_STRUCT(dri_screen); + if (!screen) + return NULL; + + screen->sPriv = sPriv; + screen->fd = sPriv->fd; + + sPriv->driverPrivate = (void *)screen; + + if (pipe_loader_sw_probe_kms(&screen->dev, screen->fd)) { + dri_init_options(screen); + pscreen = pipe_loader_create_screen(screen->dev); + } + + if (!pscreen) + goto release_pipe; + + if (pscreen->resource_create_with_modifiers) + dri2ImageExtension.createImageWithModifiers = + dri2_create_image_with_modifiers; + + if (drmGetCap(sPriv->fd, DRM_CAP_PRIME, &cap) == 0 && + (cap & DRM_PRIME_CAP_IMPORT)) { + dri2ImageExtension.createImageFromFds = dri2_from_fds; + dri2ImageExtension.createImageFromDmaBufs = dri2_from_dma_bufs; + dri2ImageExtension.createImageFromDmaBufs2 = dri2_from_dma_bufs2; + dri2ImageExtension.queryDmaBufFormats = dri2_query_dma_buf_formats; + dri2ImageExtension.queryDmaBufModifiers = dri2_query_dma_buf_modifiers; + } + + sPriv->extensions = dri_screen_extensions; + + configs = dri_init_screen_helper(screen, pscreen); + if (!configs) + goto destroy_screen; + + screen->can_share_buffer = false; + screen->auto_fake_front = dri_with_format(sPriv); + screen->broken_invalidate = !sPriv->dri2.useInvalidate; + screen->lookup_egl_image = dri2_lookup_egl_image; + + return configs; + +destroy_screen: + dri_destroy_screen_helper(screen); + +release_pipe: + if (screen->dev) + pipe_loader_release(&screen->dev, 1); + + FREE(screen); +#endif // GALLIUM_SOFTPIPE + return NULL; +} + +static boolean +dri2_create_buffer(__DRIscreen * sPriv, + __DRIdrawable * dPriv, + const struct gl_config * visual, boolean isPixmap) +{ + struct dri_drawable *drawable = NULL; + + if (!dri_create_buffer(sPriv, dPriv, visual, isPixmap)) + return FALSE; + + drawable = dPriv->driverPrivate; + + drawable->allocate_textures = dri2_allocate_textures; + drawable->flush_frontbuffer = dri2_flush_frontbuffer; + drawable->update_tex_buffer = dri2_update_tex_buffer; + drawable->flush_swapbuffers = dri2_flush_swapbuffers; + + return TRUE; +} + +/** + * DRI driver virtual function table. + * + * DRI versions differ in their implementation of init_screen and swap_buffers. + */ +const struct __DriverAPIRec galliumdrm_driver_api = { + .InitScreen = dri2_init_screen, + .DestroyScreen = dri_destroy_screen, + .CreateContext = dri_create_context, + .DestroyContext = dri_destroy_context, + .CreateBuffer = dri2_create_buffer, + .DestroyBuffer = dri_destroy_buffer, + .MakeCurrent = dri_make_current, + .UnbindContext = dri_unbind_context, + + .AllocateBuffer = dri2_allocate_buffer, + .ReleaseBuffer = dri2_release_buffer, +}; + +/** + * DRI driver virtual function table. + * + * KMS/DRM version of the DriverAPI above sporting a different InitScreen + * hook. The latter is used to explicitly initialise the kms_swrast driver + * rather than selecting the approapriate driver as suggested by the loader. + */ +const struct __DriverAPIRec dri_kms_driver_api = { + .InitScreen = dri_kms_init_screen, + .DestroyScreen = dri_destroy_screen, + .CreateContext = dri_create_context, + .DestroyContext = dri_destroy_context, + .CreateBuffer = dri2_create_buffer, + .DestroyBuffer = dri_destroy_buffer, + .MakeCurrent = dri_make_current, + .UnbindContext = dri_unbind_context, + + .AllocateBuffer = dri2_allocate_buffer, + .ReleaseBuffer = dri2_release_buffer, +}; + +/* This is the table of extensions that the loader will dlsym() for. */ +const __DRIextension *galliumdrm_driver_extensions[] = { + &driCoreExtension.base, + &driImageDriverExtension.base, + &driDRI2Extension.base, + &gallium_config_options.base, + NULL +}; + +/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/frontends/dri/dri_context.c b/src/gallium/frontends/dri/dri_context.c new file mode 100644 index 00000000000..6e53ca90ad4 --- /dev/null +++ b/src/gallium/frontends/dri/dri_context.c @@ -0,0 +1,325 @@ +/************************************************************************** + * + * Copyright 2009, VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ +/* + * Author: Keith Whitwell + * Author: Jakob Bornecrantz + */ + +#include "utils.h" + +#include "dri_screen.h" +#include "dri_drawable.h" +#include "dri_context.h" +#include "frontend/drm_driver.h" + +#include "pipe/p_context.h" +#include "pipe-loader/pipe_loader.h" +#include "state_tracker/st_context.h" + +#include "util/u_memory.h" + +GLboolean +dri_create_context(gl_api api, const struct gl_config * visual, + __DRIcontext * cPriv, + const struct __DriverContextConfig *ctx_config, + unsigned *error, + void *sharedContextPrivate) +{ + __DRIscreen *sPriv = cPriv->driScreenPriv; + struct dri_screen *screen = dri_screen(sPriv); + struct st_api *stapi = screen->st_api; + struct dri_context *ctx = NULL; + struct st_context_iface *st_share = NULL; + struct st_context_attribs attribs; + enum st_context_error ctx_err = 0; + unsigned allowed_flags = __DRI_CTX_FLAG_DEBUG | + __DRI_CTX_FLAG_FORWARD_COMPATIBLE | + __DRI_CTX_FLAG_NO_ERROR; + unsigned allowed_attribs = + __DRIVER_CONTEXT_ATTRIB_PRIORITY | + __DRIVER_CONTEXT_ATTRIB_RELEASE_BEHAVIOR; + const __DRIbackgroundCallableExtension *backgroundCallable = + screen->sPriv->dri2.backgroundCallable; + const struct driOptionCache *optionCache = &screen->dev->option_cache; + + if (screen->has_reset_status_query) { + allowed_flags |= __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS; + allowed_attribs |= __DRIVER_CONTEXT_ATTRIB_RESET_STRATEGY; + } + + if (ctx_config->flags & ~allowed_flags) { + *error = __DRI_CTX_ERROR_UNKNOWN_FLAG; + goto fail; + } + + if (ctx_config->attribute_mask & ~allowed_attribs) { + *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE; + goto fail; + } + + memset(&attribs, 0, sizeof(attribs)); + switch (api) { + case API_OPENGLES: + attribs.profile = ST_PROFILE_OPENGL_ES1; + break; + case API_OPENGLES2: + attribs.profile = ST_PROFILE_OPENGL_ES2; + break; + case API_OPENGL_COMPAT: + case API_OPENGL_CORE: + if (driQueryOptionb(optionCache, "force_compat_profile")) { + attribs.profile = ST_PROFILE_DEFAULT; + } else { + attribs.profile = api == API_OPENGL_COMPAT ? ST_PROFILE_DEFAULT + : ST_PROFILE_OPENGL_CORE; + } + + attribs.major = ctx_config->major_version; + attribs.minor = ctx_config->minor_version; + + if ((ctx_config->flags & __DRI_CTX_FLAG_FORWARD_COMPATIBLE) != 0) + attribs.flags |= ST_CONTEXT_FLAG_FORWARD_COMPATIBLE; + break; + default: + *error = __DRI_CTX_ERROR_BAD_API; + goto fail; + } + + if ((ctx_config->flags & __DRI_CTX_FLAG_DEBUG) != 0) + attribs.flags |= ST_CONTEXT_FLAG_DEBUG; + + if (ctx_config->flags & __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS) + attribs.flags |= ST_CONTEXT_FLAG_ROBUST_ACCESS; + + if (ctx_config->attribute_mask & __DRIVER_CONTEXT_ATTRIB_RESET_STRATEGY) + if (ctx_config->reset_strategy != __DRI_CTX_RESET_NO_NOTIFICATION) + attribs.flags |= ST_CONTEXT_FLAG_RESET_NOTIFICATION_ENABLED; + + if (ctx_config->flags & __DRI_CTX_FLAG_NO_ERROR) + attribs.flags |= ST_CONTEXT_FLAG_NO_ERROR; + + if (ctx_config->attribute_mask & __DRIVER_CONTEXT_ATTRIB_PRIORITY) { + switch (ctx_config->priority) { + case __DRI_CTX_PRIORITY_LOW: + attribs.flags |= ST_CONTEXT_FLAG_LOW_PRIORITY; + break; + case __DRI_CTX_PRIORITY_HIGH: + attribs.flags |= ST_CONTEXT_FLAG_HIGH_PRIORITY; + break; + default: + break; + } + } + + if ((ctx_config->attribute_mask & __DRIVER_CONTEXT_ATTRIB_RELEASE_BEHAVIOR) + && (ctx_config->release_behavior == __DRI_CTX_RELEASE_BEHAVIOR_NONE)) + attribs.flags |= ST_CONTEXT_FLAG_RELEASE_NONE; + + struct dri_context *share_ctx = NULL; + if (sharedContextPrivate) { + share_ctx = (struct dri_context *)sharedContextPrivate; + st_share = share_ctx->st; + } + + ctx = CALLOC_STRUCT(dri_context); + if (ctx == NULL) { + *error = __DRI_CTX_ERROR_NO_MEMORY; + goto fail; + } + + cPriv->driverPrivate = ctx; + ctx->cPriv = cPriv; + ctx->sPriv = sPriv; + + if (driQueryOptionb(&screen->dev->option_cache, "mesa_no_error")) + attribs.flags |= ST_CONTEXT_FLAG_NO_ERROR; + + attribs.options = screen->options; + dri_fill_st_visual(&attribs.visual, screen, visual); + ctx->st = stapi->create_context(stapi, &screen->base, &attribs, &ctx_err, + st_share); + if (ctx->st == NULL) { + switch (ctx_err) { + case ST_CONTEXT_SUCCESS: + *error = __DRI_CTX_ERROR_SUCCESS; + break; + case ST_CONTEXT_ERROR_NO_MEMORY: + *error = __DRI_CTX_ERROR_NO_MEMORY; + break; + case ST_CONTEXT_ERROR_BAD_API: + *error = __DRI_CTX_ERROR_BAD_API; + break; + case ST_CONTEXT_ERROR_BAD_VERSION: + *error = __DRI_CTX_ERROR_BAD_VERSION; + break; + case ST_CONTEXT_ERROR_BAD_FLAG: + *error = __DRI_CTX_ERROR_BAD_FLAG; + break; + case ST_CONTEXT_ERROR_UNKNOWN_ATTRIBUTE: + *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE; + break; + case ST_CONTEXT_ERROR_UNKNOWN_FLAG: + *error = __DRI_CTX_ERROR_UNKNOWN_FLAG; + break; + } + goto fail; + } + ctx->st->st_manager_private = (void *) ctx; + ctx->stapi = stapi; + + if (ctx->st->cso_context) { + ctx->pp = pp_init(ctx->st->pipe, screen->pp_enabled, ctx->st->cso_context); + ctx->hud = hud_create(ctx->st->cso_context, + share_ctx ? share_ctx->hud : NULL); + } + + /* Do this last. */ + if (ctx->st->start_thread && + driQueryOptionb(&screen->dev->option_cache, "mesa_glthread")) { + + if (backgroundCallable && backgroundCallable->base.version >= 2 && + backgroundCallable->isThreadSafe) { + + if (backgroundCallable->isThreadSafe(cPriv->loaderPrivate)) + ctx->st->start_thread(ctx->st); + else + fprintf(stderr, "dri_create_context: glthread isn't thread safe " + "- missing call XInitThreads\n"); + } else { + fprintf(stderr, "dri_create_context: requested glthread but driver " + "is missing backgroundCallable V2 extension\n"); + } + } + + *error = __DRI_CTX_ERROR_SUCCESS; + return GL_TRUE; + + fail: + if (ctx && ctx->st) + ctx->st->destroy(ctx->st); + + free(ctx); + return GL_FALSE; +} + +void +dri_destroy_context(__DRIcontext * cPriv) +{ + struct dri_context *ctx = dri_context(cPriv); + + if (ctx->hud) { + hud_destroy(ctx->hud, ctx->st->cso_context); + } + + if (ctx->pp) + pp_free(ctx->pp); + + /* No particular reason to wait for command completion before + * destroying a context, but we flush the context here + * to avoid having to add code elsewhere to cope with flushing a + * partially destroyed context. + */ + ctx->st->flush(ctx->st, 0, NULL, NULL, NULL); + ctx->st->destroy(ctx->st); + free(ctx); +} + +/* This is called inside MakeCurrent to unbind the context. */ +GLboolean +dri_unbind_context(__DRIcontext * cPriv) +{ + /* dri_util.c ensures cPriv is not null */ + struct dri_screen *screen = dri_screen(cPriv->driScreenPriv); + struct dri_context *ctx = dri_context(cPriv); + struct st_context_iface *st = ctx->st; + struct st_api *stapi = screen->st_api; + + if (--ctx->bind_count == 0) { + if (st == stapi->get_current(stapi)) { + if (st->thread_finish) + st->thread_finish(st); + + /* Record HUD queries for the duration the context was "current". */ + if (ctx->hud) + hud_record_only(ctx->hud, st->pipe); + + stapi->make_current(stapi, NULL, NULL, NULL); + } + } + + return GL_TRUE; +} + +GLboolean +dri_make_current(__DRIcontext * cPriv, + __DRIdrawable * driDrawPriv, + __DRIdrawable * driReadPriv) +{ + /* dri_util.c ensures cPriv is not null */ + struct dri_context *ctx = dri_context(cPriv); + struct dri_drawable *draw = dri_drawable(driDrawPriv); + struct dri_drawable *read = dri_drawable(driReadPriv); + + ++ctx->bind_count; + + if (!draw && !read) + return ctx->stapi->make_current(ctx->stapi, ctx->st, NULL, NULL); + else if (!draw || !read) + return GL_FALSE; + + if (ctx->dPriv != driDrawPriv) { + ctx->dPriv = driDrawPriv; + draw->texture_stamp = driDrawPriv->lastStamp - 1; + } + if (ctx->rPriv != driReadPriv) { + ctx->rPriv = driReadPriv; + read->texture_stamp = driReadPriv->lastStamp - 1; + } + + ctx->stapi->make_current(ctx->stapi, ctx->st, &draw->base, &read->base); + + /* This is ok to call here. If they are already init, it's a no-op. */ + if (ctx->pp && draw->textures[ST_ATTACHMENT_BACK_LEFT]) + pp_init_fbos(ctx->pp, draw->textures[ST_ATTACHMENT_BACK_LEFT]->width0, + draw->textures[ST_ATTACHMENT_BACK_LEFT]->height0); + + return GL_TRUE; +} + +struct dri_context * +dri_get_current(__DRIscreen *sPriv) +{ + struct dri_screen *screen = dri_screen(sPriv); + struct st_api *stapi = screen->st_api; + struct st_context_iface *st; + + st = stapi->get_current(stapi); + + return (struct dri_context *) st ? st->st_manager_private : NULL; +} + +/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/frontends/dri/dri_context.h b/src/gallium/frontends/dri/dri_context.h new file mode 100644 index 00000000000..96e21e0695c --- /dev/null +++ b/src/gallium/frontends/dri/dri_context.h @@ -0,0 +1,95 @@ +/************************************************************************** + * + * Copyright (C) 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ +/* + * Author: Keith Whitwell + * Author: Jakob Bornecrantz + */ + +#ifndef DRI_CONTEXT_H +#define DRI_CONTEXT_H + +#include "dri_util.h" +#include "pipe/p_compiler.h" +#include "hud/hud_context.h" + +struct pipe_context; +struct pipe_fence; +struct st_api; +struct st_context_iface; +struct dri_drawable; + +struct dri_context +{ + /* dri */ + __DRIscreen *sPriv; + __DRIcontext *cPriv; + __DRIdrawable *dPriv; + __DRIdrawable *rPriv; + + unsigned int bind_count; + + /* gallium */ + struct st_api *stapi; + struct st_context_iface *st; + struct pp_queue_t *pp; + struct hud_context *hud; +}; + +static inline struct dri_context * +dri_context(__DRIcontext * driContextPriv) +{ + if (!driContextPriv) + return NULL; + return (struct dri_context *)driContextPriv->driverPrivate; +} + +/*********************************************************************** + * dri_context.c + */ +void dri_destroy_context(__DRIcontext * driContextPriv); + +boolean dri_unbind_context(__DRIcontext * driContextPriv); + +boolean +dri_make_current(__DRIcontext * driContextPriv, + __DRIdrawable * driDrawPriv, + __DRIdrawable * driReadPriv); + +struct dri_context * +dri_get_current(__DRIscreen * driScreenPriv); + +boolean +dri_create_context(gl_api api, + const struct gl_config * visual, + __DRIcontext * driContextPriv, + const struct __DriverContextConfig *ctx_config, + unsigned *error, + void *sharedContextPrivate); + +#endif + +/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/frontends/dri/dri_drawable.c b/src/gallium/frontends/dri/dri_drawable.c new file mode 100644 index 00000000000..2ee4f185537 --- /dev/null +++ b/src/gallium/frontends/dri/dri_drawable.c @@ -0,0 +1,580 @@ +/************************************************************************** + * + * Copyright 2009, VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ +/* + * Author: Keith Whitwell + * Author: Jakob Bornecrantz + */ + +#include "dri_screen.h" +#include "dri_context.h" +#include "dri_drawable.h" + +#include "pipe/p_screen.h" +#include "util/format/u_format.h" +#include "util/u_memory.h" +#include "util/u_inlines.h" + +static uint32_t drifb_ID = 0; + +static bool +dri_st_framebuffer_validate(struct st_context_iface *stctx, + struct st_framebuffer_iface *stfbi, + const enum st_attachment_type *statts, + unsigned count, + struct pipe_resource **out) +{ + struct dri_context *ctx = (struct dri_context *)stctx->st_manager_private; + struct dri_drawable *drawable = + (struct dri_drawable *) stfbi->st_manager_private; + struct dri_screen *screen = dri_screen(drawable->sPriv); + unsigned statt_mask, new_mask; + bool new_stamp; + int i; + unsigned int lastStamp; + struct pipe_resource **textures = + drawable->stvis.samples > 1 ? drawable->msaa_textures + : drawable->textures; + + statt_mask = 0x0; + for (i = 0; i < count; i++) + statt_mask |= (1 << statts[i]); + + /* record newly allocated textures */ + new_mask = (statt_mask & ~drawable->texture_mask); + + /* + * dPriv->dri2.stamp is the server stamp. dPriv->lastStamp is the + * client stamp. It has the value of the server stamp when last + * checked. + */ + do { + lastStamp = drawable->dPriv->lastStamp; + new_stamp = (drawable->texture_stamp != lastStamp); + + if (new_stamp || new_mask || screen->broken_invalidate) { + if (new_stamp && drawable->update_drawable_info) + drawable->update_drawable_info(drawable); + + drawable->allocate_textures(ctx, drawable, statts, count); + + /* add existing textures */ + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { + if (textures[i]) + statt_mask |= (1 << i); + } + + drawable->texture_stamp = lastStamp; + drawable->texture_mask = statt_mask; + } + } while (lastStamp != drawable->dPriv->lastStamp); + + /* Flush the pending set_damage_region request. */ + struct pipe_screen *pscreen = screen->base.screen; + + if (new_mask & (1 << ST_ATTACHMENT_BACK_LEFT) && + pscreen->set_damage_region) { + struct pipe_resource *resource = textures[ST_ATTACHMENT_BACK_LEFT]; + + pscreen->set_damage_region(pscreen, resource, + drawable->num_damage_rects, + drawable->damage_rects); + } + + if (!out) + return true; + + /* Set the window-system buffers for the state tracker. */ + for (i = 0; i < count; i++) + pipe_resource_reference(&out[i], textures[statts[i]]); + + return true; +} + +static bool +dri_st_framebuffer_flush_front(struct st_context_iface *stctx, + struct st_framebuffer_iface *stfbi, + enum st_attachment_type statt) +{ + struct dri_context *ctx = (struct dri_context *)stctx->st_manager_private; + struct dri_drawable *drawable = + (struct dri_drawable *) stfbi->st_manager_private; + + /* XXX remove this and just set the correct one on the framebuffer */ + drawable->flush_frontbuffer(ctx, drawable, statt); + + return true; +} + +/** + * The state tracker framebuffer interface flush_swapbuffers callback + */ +static bool +dri_st_framebuffer_flush_swapbuffers(struct st_context_iface *stctx, + struct st_framebuffer_iface *stfbi) +{ + struct dri_context *ctx = (struct dri_context *)stctx->st_manager_private; + struct dri_drawable *drawable = + (struct dri_drawable *) stfbi->st_manager_private; + + if (drawable->flush_swapbuffers) + drawable->flush_swapbuffers(ctx, drawable); + + return true; +} + +/** + * This is called when we need to set up GL rendering to a new X window. + */ +bool +dri_create_buffer(__DRIscreen * sPriv, + __DRIdrawable * dPriv, + const struct gl_config * visual, bool isPixmap) +{ + struct dri_screen *screen = sPriv->driverPrivate; + struct dri_drawable *drawable = NULL; + + if (isPixmap) + goto fail; /* not implemented */ + + drawable = CALLOC_STRUCT(dri_drawable); + if (drawable == NULL) + goto fail; + + dri_fill_st_visual(&drawable->stvis, screen, visual); + + /* setup the st_framebuffer_iface */ + drawable->base.visual = &drawable->stvis; + drawable->base.flush_front = dri_st_framebuffer_flush_front; + drawable->base.validate = dri_st_framebuffer_validate; + drawable->base.flush_swapbuffers = dri_st_framebuffer_flush_swapbuffers; + drawable->base.st_manager_private = (void *) drawable; + + drawable->screen = screen; + drawable->sPriv = sPriv; + drawable->dPriv = dPriv; + + dPriv->driverPrivate = (void *)drawable; + p_atomic_set(&drawable->base.stamp, 1); + drawable->base.ID = p_atomic_inc_return(&drifb_ID); + drawable->base.state_manager = &screen->base; + + return true; +fail: + FREE(drawable); + return false; +} + +void +dri_destroy_buffer(__DRIdrawable * dPriv) +{ + struct dri_drawable *drawable = dri_drawable(dPriv); + struct dri_screen *screen = drawable->screen; + struct st_api *stapi = screen->st_api; + int i; + + pipe_surface_reference(&drawable->drisw_surface, NULL); + + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) + pipe_resource_reference(&drawable->textures[i], NULL); + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) + pipe_resource_reference(&drawable->msaa_textures[i], NULL); + + screen->base.screen->fence_reference(screen->base.screen, + &drawable->throttle_fence, NULL); + + /* Notify the st manager that this drawable is no longer valid */ + stapi->destroy_drawable(stapi, &drawable->base); + + FREE(drawable->damage_rects); + FREE(drawable); +} + +/** + * Validate the texture at an attachment. Allocate the texture if it does not + * exist. Used by the TFP extension. + */ +static void +dri_drawable_validate_att(struct dri_context *ctx, + struct dri_drawable *drawable, + enum st_attachment_type statt) +{ + enum st_attachment_type statts[ST_ATTACHMENT_COUNT]; + unsigned i, count = 0; + + /* check if buffer already exists */ + if (drawable->texture_mask & (1 << statt)) + return; + + /* make sure DRI2 does not destroy existing buffers */ + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { + if (drawable->texture_mask & (1 << i)) { + statts[count++] = i; + } + } + statts[count++] = statt; + + drawable->texture_stamp = drawable->dPriv->lastStamp - 1; + + drawable->base.validate(ctx->st, &drawable->base, statts, count, NULL); +} + +/** + * These are used for GLX_EXT_texture_from_pixmap + */ +static void +dri_set_tex_buffer2(__DRIcontext *pDRICtx, GLint target, + GLint format, __DRIdrawable *dPriv) +{ + struct dri_context *ctx = dri_context(pDRICtx); + struct st_context_iface *st = ctx->st; + struct dri_drawable *drawable = dri_drawable(dPriv); + struct pipe_resource *pt; + + if (st->thread_finish) + st->thread_finish(st); + + dri_drawable_validate_att(ctx, drawable, ST_ATTACHMENT_FRONT_LEFT); + + /* Use the pipe resource associated with the X drawable */ + pt = drawable->textures[ST_ATTACHMENT_FRONT_LEFT]; + + if (pt) { + enum pipe_format internal_format = pt->format; + + if (format == __DRI_TEXTURE_FORMAT_RGB) { + /* only need to cover the formats recognized by dri_fill_st_visual */ + switch (internal_format) { + case PIPE_FORMAT_R16G16B16A16_FLOAT: + internal_format = PIPE_FORMAT_R16G16B16X16_FLOAT; + break; + case PIPE_FORMAT_B10G10R10A2_UNORM: + internal_format = PIPE_FORMAT_B10G10R10X2_UNORM; + break; + case PIPE_FORMAT_R10G10B10A2_UNORM: + internal_format = PIPE_FORMAT_R10G10B10X2_UNORM; + break; + case PIPE_FORMAT_BGRA8888_UNORM: + internal_format = PIPE_FORMAT_BGRX8888_UNORM; + break; + case PIPE_FORMAT_ARGB8888_UNORM: + internal_format = PIPE_FORMAT_XRGB8888_UNORM; + break; + default: + break; + } + } + + drawable->update_tex_buffer(drawable, ctx, pt); + + ctx->st->teximage(ctx->st, + (target == GL_TEXTURE_2D) ? ST_TEXTURE_2D : ST_TEXTURE_RECT, + 0, internal_format, pt, false); + } +} + +static void +dri_set_tex_buffer(__DRIcontext *pDRICtx, GLint target, + __DRIdrawable *dPriv) +{ + dri_set_tex_buffer2(pDRICtx, target, __DRI_TEXTURE_FORMAT_RGBA, dPriv); +} + +const __DRItexBufferExtension driTexBufferExtension = { + .base = { __DRI_TEX_BUFFER, 2 }, + + .setTexBuffer = dri_set_tex_buffer, + .setTexBuffer2 = dri_set_tex_buffer2, + .releaseTexBuffer = NULL, +}; + +/** + * Get the format and binding of an attachment. + */ +void +dri_drawable_get_format(struct dri_drawable *drawable, + enum st_attachment_type statt, + enum pipe_format *format, + unsigned *bind) +{ + switch (statt) { + case ST_ATTACHMENT_FRONT_LEFT: + case ST_ATTACHMENT_BACK_LEFT: + case ST_ATTACHMENT_FRONT_RIGHT: + case ST_ATTACHMENT_BACK_RIGHT: + /* Other pieces of the driver stack get confused and behave incorrectly + * when they get an sRGB drawable. st/mesa receives "drawable->stvis" + * though other means and handles it correctly, so we don't really need + * to use an sRGB format here. + */ + *format = util_format_linear(drawable->stvis.color_format); + *bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; + break; + case ST_ATTACHMENT_DEPTH_STENCIL: + *format = drawable->stvis.depth_stencil_format; + *bind = PIPE_BIND_DEPTH_STENCIL; /* XXX sampler? */ + break; + default: + *format = PIPE_FORMAT_NONE; + *bind = 0; + break; + } +} + +void +dri_pipe_blit(struct pipe_context *pipe, + struct pipe_resource *dst, + struct pipe_resource *src) +{ + struct pipe_blit_info blit; + + if (!dst || !src) + return; + + /* From the GL spec, version 4.2, section 4.1.11 (Additional Multisample + * Fragment Operations): + * + * If a framebuffer object is not bound, after all operations have + * been completed on the multisample buffer, the sample values for + * each color in the multisample buffer are combined to produce a + * single color value, and that value is written into the + * corresponding color buffers selected by DrawBuffer or + * DrawBuffers. An implementation may defer the writing of the color + * buffers until a later time, but the state of the framebuffer must + * behave as if the color buffers were updated as each fragment was + * processed. The method of combination is not specified. If the + * framebuffer contains sRGB values, then it is recommended that the + * an average of sample values is computed in a linearized space, as + * for blending (see section 4.1.7). + * + * In other words, to do a resolve operation in a linear space, we have + * to set sRGB formats if the original resources were sRGB, so don't use + * util_format_linear. + */ + + memset(&blit, 0, sizeof(blit)); + blit.dst.resource = dst; + blit.dst.box.width = dst->width0; + blit.dst.box.height = dst->height0; + blit.dst.box.depth = 1; + blit.dst.format = dst->format; + blit.src.resource = src; + blit.src.box.width = src->width0; + blit.src.box.height = src->height0; + blit.src.box.depth = 1; + blit.src.format = src->format; + blit.mask = PIPE_MASK_RGBA; + blit.filter = PIPE_TEX_FILTER_NEAREST; + + pipe->blit(pipe, &blit); +} + +static void +dri_postprocessing(struct dri_context *ctx, + struct dri_drawable *drawable, + enum st_attachment_type att) +{ + struct pipe_resource *src = drawable->textures[att]; + struct pipe_resource *zsbuf = drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]; + + if (ctx->pp && src) + pp_run(ctx->pp, src, src, zsbuf); +} + +struct notify_before_flush_cb_args { + struct dri_context *ctx; + struct dri_drawable *drawable; + unsigned flags; + enum __DRI2throttleReason reason; + bool swap_msaa_buffers; +}; + +static void +notify_before_flush_cb(void* _args) +{ + struct notify_before_flush_cb_args *args = (struct notify_before_flush_cb_args *) _args; + struct st_context_iface *st = args->ctx->st; + struct pipe_context *pipe = st->pipe; + + if (args->drawable->stvis.samples > 1 && + (args->reason == __DRI2_THROTTLE_SWAPBUFFER || + args->reason == __DRI2_THROTTLE_COPYSUBBUFFER)) { + /* Resolve the MSAA back buffer. */ + dri_pipe_blit(st->pipe, + args->drawable->textures[ST_ATTACHMENT_BACK_LEFT], + args->drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT]); + + if (args->reason == __DRI2_THROTTLE_SWAPBUFFER && + args->drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT] && + args->drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT]) { + args->swap_msaa_buffers = true; + } + + /* FRONT_LEFT is resolved in drawable->flush_frontbuffer. */ + } + + dri_postprocessing(args->ctx, args->drawable, ST_ATTACHMENT_BACK_LEFT); + + if (pipe->invalidate_resource && + (args->flags & __DRI2_FLUSH_INVALIDATE_ANCILLARY)) { + if (args->drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]) + pipe->invalidate_resource(pipe, args->drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]); + if (args->drawable->msaa_textures[ST_ATTACHMENT_DEPTH_STENCIL]) + pipe->invalidate_resource(pipe, args->drawable->msaa_textures[ST_ATTACHMENT_DEPTH_STENCIL]); + } + + if (args->ctx->hud) { + hud_run(args->ctx->hud, args->ctx->st->cso_context, + args->drawable->textures[ST_ATTACHMENT_BACK_LEFT]); + } + + pipe->flush_resource(pipe, args->drawable->textures[ST_ATTACHMENT_BACK_LEFT]); +} + +/** + * DRI2 flush extension, the flush_with_flags function. + * + * \param context the context + * \param drawable the drawable to flush + * \param flags a combination of _DRI2_FLUSH_xxx flags + * \param throttle_reason the reason for throttling, 0 = no throttling + */ +void +dri_flush(__DRIcontext *cPriv, + __DRIdrawable *dPriv, + unsigned flags, + enum __DRI2throttleReason reason) +{ + struct dri_context *ctx = dri_context(cPriv); + struct dri_drawable *drawable = dri_drawable(dPriv); + struct st_context_iface *st; + unsigned flush_flags; + struct notify_before_flush_cb_args args = { 0 }; + + if (!ctx) { + assert(0); + return; + } + + st = ctx->st; + if (st->thread_finish) + st->thread_finish(st); + + if (drawable) { + /* prevent recursion */ + if (drawable->flushing) + return; + + drawable->flushing = true; + } + else { + flags &= ~__DRI2_FLUSH_DRAWABLE; + } + + if ((flags & __DRI2_FLUSH_DRAWABLE) && + drawable->textures[ST_ATTACHMENT_BACK_LEFT]) { + /* We can't do operations on the back buffer here, because there + * may be some pending operations that will get flushed by the + * call to st->flush (eg: FLUSH_VERTICES). + * Instead we register a callback to be notified when all operations + * have been submitted but before the call to st_flush. + */ + args.ctx = ctx; + args.drawable = drawable; + args.flags = flags; + args.reason = reason; + } + + flush_flags = 0; + if (flags & __DRI2_FLUSH_CONTEXT) + flush_flags |= ST_FLUSH_FRONT; + if (reason == __DRI2_THROTTLE_SWAPBUFFER) + flush_flags |= ST_FLUSH_END_OF_FRAME; + + /* Flush the context and throttle if needed. */ + if (dri_screen(ctx->sPriv)->throttle && + drawable && + (reason == __DRI2_THROTTLE_SWAPBUFFER || + reason == __DRI2_THROTTLE_FLUSHFRONT)) { + + struct pipe_screen *screen = drawable->screen->base.screen; + struct pipe_fence_handle *new_fence = NULL; + + st->flush(st, flush_flags, &new_fence, args.ctx ? notify_before_flush_cb : NULL, &args); + + /* throttle on the previous fence */ + if (drawable->throttle_fence) { + screen->fence_finish(screen, NULL, drawable->throttle_fence, PIPE_TIMEOUT_INFINITE); + screen->fence_reference(screen, &drawable->throttle_fence, NULL); + } + drawable->throttle_fence = new_fence; + } + else if (flags & (__DRI2_FLUSH_DRAWABLE | __DRI2_FLUSH_CONTEXT)) { + st->flush(st, flush_flags, NULL, args.ctx ? notify_before_flush_cb : NULL, &args); + } + + if (drawable) { + drawable->flushing = false; + } + + /* Swap the MSAA front and back buffers, so that reading + * from the front buffer after SwapBuffers returns what was + * in the back buffer. + */ + if (args.swap_msaa_buffers) { + struct pipe_resource *tmp = + drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT]; + + drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT] = + drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT]; + drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT] = tmp; + + /* Now that we have swapped the buffers, this tells the state + * tracker to revalidate the framebuffer. + */ + p_atomic_inc(&drawable->base.stamp); + } +} + +/** + * dri_throttle - A DRI2ThrottleExtension throttling function. + */ +static void +dri_throttle(__DRIcontext *cPriv, __DRIdrawable *dPriv, + enum __DRI2throttleReason reason) +{ + dri_flush(cPriv, dPriv, 0, reason); +} + + +const __DRI2throttleExtension dri2ThrottleExtension = { + .base = { __DRI2_THROTTLE, 1 }, + + .throttle = dri_throttle, +}; + + +/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/frontends/dri/dri_drawable.h b/src/gallium/frontends/dri/dri_drawable.h new file mode 100644 index 00000000000..71cc6070090 --- /dev/null +++ b/src/gallium/frontends/dri/dri_drawable.h @@ -0,0 +1,125 @@ +/************************************************************************** + * + * Copyright 2009, VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef DRI_DRAWABLE_H +#define DRI_DRAWABLE_H + +#include "pipe/p_compiler.h" +#include "pipe/p_format.h" +#include "frontend/api.h" + +struct pipe_surface; +struct st_framebuffer; +struct dri_context; + +struct dri_drawable +{ + struct st_framebuffer_iface base; + struct st_visual stvis; + + struct dri_screen *screen; + + /* dri */ + __DRIdrawable *dPriv; + __DRIscreen *sPriv; + + __DRIbuffer old[8]; + unsigned old_num; + unsigned old_w; + unsigned old_h; + + struct pipe_box *damage_rects; + unsigned int num_damage_rects; + + struct pipe_resource *textures[ST_ATTACHMENT_COUNT]; + struct pipe_resource *msaa_textures[ST_ATTACHMENT_COUNT]; + unsigned int texture_mask, texture_stamp; + + struct pipe_fence_handle *throttle_fence; + bool flushing; /* prevents recursion in dri_flush */ + + /* used only by DRISW */ + struct pipe_surface *drisw_surface; + + /* hooks filled in by dri2 & drisw */ + void (*allocate_textures)(struct dri_context *ctx, + struct dri_drawable *drawable, + const enum st_attachment_type *statts, + unsigned count); + + void (*update_drawable_info)(struct dri_drawable *drawable); + + void (*flush_frontbuffer)(struct dri_context *ctx, + struct dri_drawable *drawable, + enum st_attachment_type statt); + + void (*update_tex_buffer)(struct dri_drawable *drawable, + struct dri_context *ctx, + struct pipe_resource *res); + void (*flush_swapbuffers)(struct dri_context *ctx, + struct dri_drawable *drawable); +}; + +static inline struct dri_drawable * +dri_drawable(__DRIdrawable * driDrawPriv) +{ + return (struct dri_drawable *) (driDrawPriv) + ? driDrawPriv->driverPrivate : NULL; +} + +/*********************************************************************** + * dri_drawable.c + */ +bool +dri_create_buffer(__DRIscreen * sPriv, + __DRIdrawable * dPriv, + const struct gl_config * visual, bool isPixmap); + +void dri_destroy_buffer(__DRIdrawable * dPriv); + +void +dri_drawable_get_format(struct dri_drawable *drawable, + enum st_attachment_type statt, + enum pipe_format *format, + unsigned *bind); + +void +dri_pipe_blit(struct pipe_context *pipe, + struct pipe_resource *dst, + struct pipe_resource *src); + +void +dri_flush(__DRIcontext *cPriv, + __DRIdrawable *dPriv, + unsigned flags, + enum __DRI2throttleReason reason); + +extern const __DRItexBufferExtension driTexBufferExtension; +extern const __DRI2throttleExtension dri2ThrottleExtension; +#endif + +/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/frontends/dri/dri_helpers.c b/src/gallium/frontends/dri/dri_helpers.c new file mode 100644 index 00000000000..90a8a392fad --- /dev/null +++ b/src/gallium/frontends/dri/dri_helpers.c @@ -0,0 +1,618 @@ +/* + * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "drm-uapi/drm_fourcc.h" +#include "util/u_memory.h" +#include "pipe/p_screen.h" +#include "state_tracker/st_texture.h" +#include "state_tracker/st_context.h" +#include "state_tracker/st_cb_fbo.h" +#include "main/texobj.h" + +#include "dri_helpers.h" + +static bool +dri2_is_opencl_interop_loaded_locked(struct dri_screen *screen) +{ + return screen->opencl_dri_event_add_ref && + screen->opencl_dri_event_release && + screen->opencl_dri_event_wait && + screen->opencl_dri_event_get_fence; +} + +static bool +dri2_load_opencl_interop(struct dri_screen *screen) +{ +#if defined(RTLD_DEFAULT) + bool success; + + mtx_lock(&screen->opencl_func_mutex); + + if (dri2_is_opencl_interop_loaded_locked(screen)) { + mtx_unlock(&screen->opencl_func_mutex); + return true; + } + + screen->opencl_dri_event_add_ref = + dlsym(RTLD_DEFAULT, "opencl_dri_event_add_ref"); + screen->opencl_dri_event_release = + dlsym(RTLD_DEFAULT, "opencl_dri_event_release"); + screen->opencl_dri_event_wait = + dlsym(RTLD_DEFAULT, "opencl_dri_event_wait"); + screen->opencl_dri_event_get_fence = + dlsym(RTLD_DEFAULT, "opencl_dri_event_get_fence"); + + success = dri2_is_opencl_interop_loaded_locked(screen); + mtx_unlock(&screen->opencl_func_mutex); + return success; +#else + return false; +#endif +} + +struct dri2_fence { + struct dri_screen *driscreen; + struct pipe_fence_handle *pipe_fence; + void *cl_event; +}; + +static unsigned dri2_fence_get_caps(__DRIscreen *_screen) +{ + struct dri_screen *driscreen = dri_screen(_screen); + struct pipe_screen *screen = driscreen->base.screen; + unsigned caps = 0; + + if (screen->get_param(screen, PIPE_CAP_NATIVE_FENCE_FD)) + caps |= __DRI_FENCE_CAP_NATIVE_FD; + + return caps; +} + +static void * +dri2_create_fence(__DRIcontext *_ctx) +{ + struct st_context_iface *stapi = dri_context(_ctx)->st; + struct dri2_fence *fence = CALLOC_STRUCT(dri2_fence); + + if (!fence) + return NULL; + + stapi->flush(stapi, 0, &fence->pipe_fence, NULL, NULL); + + if (!fence->pipe_fence) { + FREE(fence); + return NULL; + } + + fence->driscreen = dri_screen(_ctx->driScreenPriv); + return fence; +} + +static void * +dri2_create_fence_fd(__DRIcontext *_ctx, int fd) +{ + struct st_context_iface *stapi = dri_context(_ctx)->st; + struct pipe_context *ctx = stapi->pipe; + struct dri2_fence *fence = CALLOC_STRUCT(dri2_fence); + + if (fd == -1) { + /* exporting driver created fence, flush: */ + stapi->flush(stapi, ST_FLUSH_FENCE_FD, &fence->pipe_fence, NULL, NULL); + } else { + /* importing a foreign fence fd: */ + ctx->create_fence_fd(ctx, &fence->pipe_fence, fd, PIPE_FD_TYPE_NATIVE_SYNC); + } + if (!fence->pipe_fence) { + FREE(fence); + return NULL; + } + + fence->driscreen = dri_screen(_ctx->driScreenPriv); + return fence; +} + +static int +dri2_get_fence_fd(__DRIscreen *_screen, void *_fence) +{ + struct dri_screen *driscreen = dri_screen(_screen); + struct pipe_screen *screen = driscreen->base.screen; + struct dri2_fence *fence = (struct dri2_fence*)_fence; + + return screen->fence_get_fd(screen, fence->pipe_fence); +} + +static void * +dri2_get_fence_from_cl_event(__DRIscreen *_screen, intptr_t cl_event) +{ + struct dri_screen *driscreen = dri_screen(_screen); + struct dri2_fence *fence; + + if (!dri2_load_opencl_interop(driscreen)) + return NULL; + + fence = CALLOC_STRUCT(dri2_fence); + if (!fence) + return NULL; + + fence->cl_event = (void*)cl_event; + + if (!driscreen->opencl_dri_event_add_ref(fence->cl_event)) { + free(fence); + return NULL; + } + + fence->driscreen = driscreen; + return fence; +} + +static void +dri2_destroy_fence(__DRIscreen *_screen, void *_fence) +{ + struct dri_screen *driscreen = dri_screen(_screen); + struct pipe_screen *screen = driscreen->base.screen; + struct dri2_fence *fence = (struct dri2_fence*)_fence; + + if (fence->pipe_fence) + screen->fence_reference(screen, &fence->pipe_fence, NULL); + else if (fence->cl_event) + driscreen->opencl_dri_event_release(fence->cl_event); + else + assert(0); + + FREE(fence); +} + +static GLboolean +dri2_client_wait_sync(__DRIcontext *_ctx, void *_fence, unsigned flags, + uint64_t timeout) +{ + struct dri2_fence *fence = (struct dri2_fence*)_fence; + struct dri_screen *driscreen = fence->driscreen; + struct pipe_screen *screen = driscreen->base.screen; + + /* No need to flush. The context was flushed when the fence was created. */ + + if (fence->pipe_fence) + return screen->fence_finish(screen, NULL, fence->pipe_fence, timeout); + else if (fence->cl_event) { + struct pipe_fence_handle *pipe_fence = + driscreen->opencl_dri_event_get_fence(fence->cl_event); + + if (pipe_fence) + return screen->fence_finish(screen, NULL, pipe_fence, timeout); + else + return driscreen->opencl_dri_event_wait(fence->cl_event, timeout); + } + else { + assert(0); + return false; + } +} + +static void +dri2_server_wait_sync(__DRIcontext *_ctx, void *_fence, unsigned flags) +{ + struct pipe_context *ctx = dri_context(_ctx)->st->pipe; + struct dri2_fence *fence = (struct dri2_fence*)_fence; + + /* We might be called here with a NULL fence as a result of WaitSyncKHR + * on a EGL_KHR_reusable_sync fence. Nothing to do here in such case. + */ + if (!fence) + return; + + if (ctx->fence_server_sync) + ctx->fence_server_sync(ctx, fence->pipe_fence); +} + +const __DRI2fenceExtension dri2FenceExtension = { + .base = { __DRI2_FENCE, 2 }, + + .create_fence = dri2_create_fence, + .get_fence_from_cl_event = dri2_get_fence_from_cl_event, + .destroy_fence = dri2_destroy_fence, + .client_wait_sync = dri2_client_wait_sync, + .server_wait_sync = dri2_server_wait_sync, + .get_capabilities = dri2_fence_get_caps, + .create_fence_fd = dri2_create_fence_fd, + .get_fence_fd = dri2_get_fence_fd, +}; + +__DRIimage * +dri2_lookup_egl_image(struct dri_screen *screen, void *handle) +{ + const __DRIimageLookupExtension *loader = screen->sPriv->dri2.image; + __DRIimage *img; + + if (!loader->lookupEGLImage) + return NULL; + + img = loader->lookupEGLImage(screen->sPriv, + handle, screen->sPriv->loaderPrivate); + + return img; +} + +__DRIimage * +dri2_create_image_from_renderbuffer2(__DRIcontext *context, + int renderbuffer, void *loaderPrivate, + unsigned *error) +{ + struct gl_context *ctx = ((struct st_context *)dri_context(context)->st)->ctx; + struct gl_renderbuffer *rb; + struct pipe_resource *tex; + __DRIimage *img; + + /* Section 3.9 (EGLImage Specification and Management) of the EGL 1.5 + * specification says: + * + * "If target is EGL_GL_RENDERBUFFER and buffer is not the name of a + * renderbuffer object, or if buffer is the name of a multisampled + * renderbuffer object, the error EGL_BAD_PARAMETER is generated." + * + * "If target is EGL_GL_TEXTURE_2D , EGL_GL_TEXTURE_CUBE_MAP_*, + * EGL_GL_RENDERBUFFER or EGL_GL_TEXTURE_3D and buffer refers to the + * default GL texture object (0) for the corresponding GL target, the + * error EGL_BAD_PARAMETER is generated." + * (rely on _mesa_lookup_renderbuffer returning NULL in this case) + */ + rb = _mesa_lookup_renderbuffer(ctx, renderbuffer); + if (!rb || rb->NumSamples > 0) { + *error = __DRI_IMAGE_ERROR_BAD_PARAMETER; + return NULL; + } + + tex = st_get_renderbuffer_resource(rb); + if (!tex) { + *error = __DRI_IMAGE_ERROR_BAD_PARAMETER; + return NULL; + } + + img = CALLOC_STRUCT(__DRIimageRec); + if (!img) { + *error = __DRI_IMAGE_ERROR_BAD_ALLOC; + return NULL; + } + + img->dri_format = driGLFormatToImageFormat(rb->Format); + img->loader_private = loaderPrivate; + + pipe_resource_reference(&img->texture, tex); + + *error = __DRI_IMAGE_ERROR_SUCCESS; + return img; +} + +__DRIimage * +dri2_create_image_from_renderbuffer(__DRIcontext *context, + int renderbuffer, void *loaderPrivate) +{ + unsigned error; + return dri2_create_image_from_renderbuffer2(context, renderbuffer, + loaderPrivate, &error); +} + +void +dri2_destroy_image(__DRIimage *img) +{ + pipe_resource_reference(&img->texture, NULL); + FREE(img); +} + + +__DRIimage * +dri2_create_from_texture(__DRIcontext *context, int target, unsigned texture, + int depth, int level, unsigned *error, + void *loaderPrivate) +{ + __DRIimage *img; + struct gl_context *ctx = ((struct st_context *)dri_context(context)->st)->ctx; + struct gl_texture_object *obj; + struct pipe_resource *tex; + GLuint face = 0; + + obj = _mesa_lookup_texture(ctx, texture); + if (!obj || obj->Target != target) { + *error = __DRI_IMAGE_ERROR_BAD_PARAMETER; + return NULL; + } + + tex = st_get_texobj_resource(obj); + if (!tex) { + *error = __DRI_IMAGE_ERROR_BAD_PARAMETER; + return NULL; + } + + if (target == GL_TEXTURE_CUBE_MAP) + face = depth; + + _mesa_test_texobj_completeness(ctx, obj); + if (!obj->_BaseComplete || (level > 0 && !obj->_MipmapComplete)) { + *error = __DRI_IMAGE_ERROR_BAD_PARAMETER; + return NULL; + } + + if (level < obj->BaseLevel || level > obj->_MaxLevel) { + *error = __DRI_IMAGE_ERROR_BAD_MATCH; + return NULL; + } + + if (target == GL_TEXTURE_3D && obj->Image[face][level]->Depth < depth) { + *error = __DRI_IMAGE_ERROR_BAD_MATCH; + return NULL; + } + + img = CALLOC_STRUCT(__DRIimageRec); + if (!img) { + *error = __DRI_IMAGE_ERROR_BAD_ALLOC; + return NULL; + } + + img->level = level; + img->layer = depth; + img->dri_format = driGLFormatToImageFormat(obj->Image[face][level]->TexFormat); + + img->loader_private = loaderPrivate; + + pipe_resource_reference(&img->texture, tex); + + *error = __DRI_IMAGE_ERROR_SUCCESS; + return img; +} + +static const struct dri2_format_mapping dri2_format_table[] = { + { DRM_FORMAT_ABGR16161616F, __DRI_IMAGE_FORMAT_ABGR16161616F, + __DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_R16G16B16A16_FLOAT, 1, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_ABGR16161616F, 4 } } }, + { DRM_FORMAT_XBGR16161616F, __DRI_IMAGE_FORMAT_XBGR16161616F, + __DRI_IMAGE_COMPONENTS_RGB, PIPE_FORMAT_R16G16B16X16_FLOAT, 1, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_XBGR16161616F, 4 } } }, + { DRM_FORMAT_ARGB2101010, __DRI_IMAGE_FORMAT_ARGB2101010, + __DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_B10G10R10A2_UNORM, 1, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_ARGB2101010, 4 } } }, + { DRM_FORMAT_XRGB2101010, __DRI_IMAGE_FORMAT_XRGB2101010, + __DRI_IMAGE_COMPONENTS_RGB, PIPE_FORMAT_B10G10R10X2_UNORM, 1, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_XRGB2101010, 4 } } }, + { DRM_FORMAT_ABGR2101010, __DRI_IMAGE_FORMAT_ABGR2101010, + __DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_R10G10B10A2_UNORM, 1, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_ABGR2101010, 4 } } }, + { DRM_FORMAT_XBGR2101010, __DRI_IMAGE_FORMAT_XBGR2101010, + __DRI_IMAGE_COMPONENTS_RGB, PIPE_FORMAT_R10G10B10X2_UNORM, 1, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_XBGR2101010, 4 } } }, + { DRM_FORMAT_ARGB8888, __DRI_IMAGE_FORMAT_ARGB8888, + __DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_BGRA8888_UNORM, 1, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_ARGB8888, 4 } } }, + { DRM_FORMAT_ABGR8888, __DRI_IMAGE_FORMAT_ABGR8888, + __DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_RGBA8888_UNORM, 1, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_ABGR8888, 4 } } }, + { __DRI_IMAGE_FOURCC_SARGB8888, __DRI_IMAGE_FORMAT_SARGB8, + __DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_BGRA8888_SRGB, 1, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_SARGB8, 4 } } }, + { DRM_FORMAT_XRGB8888, __DRI_IMAGE_FORMAT_XRGB8888, + __DRI_IMAGE_COMPONENTS_RGB, PIPE_FORMAT_BGRX8888_UNORM, 1, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_XRGB8888, 4 }, } }, + { DRM_FORMAT_XBGR8888, __DRI_IMAGE_FORMAT_XBGR8888, + __DRI_IMAGE_COMPONENTS_RGB, PIPE_FORMAT_RGBX8888_UNORM, 1, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_XBGR8888, 4 }, } }, + { DRM_FORMAT_ARGB1555, __DRI_IMAGE_FORMAT_ARGB1555, + __DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_B5G5R5A1_UNORM, 1, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_ARGB1555, 2 } } }, + { DRM_FORMAT_RGB565, __DRI_IMAGE_FORMAT_RGB565, + __DRI_IMAGE_COMPONENTS_RGB, PIPE_FORMAT_B5G6R5_UNORM, 1, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_RGB565, 2 } } }, + { DRM_FORMAT_R8, __DRI_IMAGE_FORMAT_R8, + __DRI_IMAGE_COMPONENTS_R, PIPE_FORMAT_R8_UNORM, 1, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, } }, + { DRM_FORMAT_R16, __DRI_IMAGE_FORMAT_R16, + __DRI_IMAGE_COMPONENTS_R, PIPE_FORMAT_R16_UNORM, 1, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_R16, 1 }, } }, + { DRM_FORMAT_GR88, __DRI_IMAGE_FORMAT_GR88, + __DRI_IMAGE_COMPONENTS_RG, PIPE_FORMAT_RG88_UNORM, 1, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88, 2 }, } }, + { DRM_FORMAT_GR1616, __DRI_IMAGE_FORMAT_GR1616, + __DRI_IMAGE_COMPONENTS_RG, PIPE_FORMAT_RG1616_UNORM, 1, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR1616, 2 }, } }, + + { DRM_FORMAT_YUV410, __DRI_IMAGE_FORMAT_NONE, + __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, + { 1, 2, 2, __DRI_IMAGE_FORMAT_R8, 1 }, + { 2, 2, 2, __DRI_IMAGE_FORMAT_R8, 1 } } }, + { DRM_FORMAT_YUV411, __DRI_IMAGE_FORMAT_NONE, + __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, + { 1, 2, 0, __DRI_IMAGE_FORMAT_R8, 1 }, + { 2, 2, 0, __DRI_IMAGE_FORMAT_R8, 1 } } }, + { DRM_FORMAT_YUV420, __DRI_IMAGE_FORMAT_NONE, + __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, + { 1, 1, 1, __DRI_IMAGE_FORMAT_R8, 1 }, + { 2, 1, 1, __DRI_IMAGE_FORMAT_R8, 1 } } }, + { DRM_FORMAT_YUV422, __DRI_IMAGE_FORMAT_NONE, + __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, + { 1, 1, 0, __DRI_IMAGE_FORMAT_R8, 1 }, + { 2, 1, 0, __DRI_IMAGE_FORMAT_R8, 1 } } }, + { DRM_FORMAT_YUV444, __DRI_IMAGE_FORMAT_NONE, + __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, + { 1, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, + { 2, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 } } }, + + { DRM_FORMAT_YVU410, __DRI_IMAGE_FORMAT_NONE, + __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, + { 2, 2, 2, __DRI_IMAGE_FORMAT_R8, 1 }, + { 1, 2, 2, __DRI_IMAGE_FORMAT_R8, 1 } } }, + { DRM_FORMAT_YVU411, __DRI_IMAGE_FORMAT_NONE, + __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, + { 2, 2, 0, __DRI_IMAGE_FORMAT_R8, 1 }, + { 1, 2, 0, __DRI_IMAGE_FORMAT_R8, 1 } } }, + { DRM_FORMAT_YVU420, __DRI_IMAGE_FORMAT_NONE, + __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, + { 2, 1, 1, __DRI_IMAGE_FORMAT_R8, 1 }, + { 1, 1, 1, __DRI_IMAGE_FORMAT_R8, 1 } } }, + { DRM_FORMAT_YVU422, __DRI_IMAGE_FORMAT_NONE, + __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, + { 2, 1, 0, __DRI_IMAGE_FORMAT_R8, 1 }, + { 1, 1, 0, __DRI_IMAGE_FORMAT_R8, 1 } } }, + { DRM_FORMAT_YVU444, __DRI_IMAGE_FORMAT_NONE, + __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, + { 2, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, + { 1, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 } } }, + + { DRM_FORMAT_NV12, __DRI_IMAGE_FORMAT_NONE, + __DRI_IMAGE_COMPONENTS_Y_UV, PIPE_FORMAT_NV12, 2, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, + { 1, 1, 1, __DRI_IMAGE_FORMAT_GR88, 2 } } }, + + { DRM_FORMAT_P010, __DRI_IMAGE_FORMAT_NONE, + __DRI_IMAGE_COMPONENTS_Y_UV, PIPE_FORMAT_P016, 2, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_R16, 2 }, + { 1, 1, 1, __DRI_IMAGE_FORMAT_GR1616, 4 } } }, + { DRM_FORMAT_P012, __DRI_IMAGE_FORMAT_NONE, + __DRI_IMAGE_COMPONENTS_Y_UV, PIPE_FORMAT_P016, 2, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_R16, 2 }, + { 1, 1, 1, __DRI_IMAGE_FORMAT_GR1616, 4 } } }, + { DRM_FORMAT_P016, __DRI_IMAGE_FORMAT_NONE, + __DRI_IMAGE_COMPONENTS_Y_UV, PIPE_FORMAT_P016, 2, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_R16, 2 }, + { 1, 1, 1, __DRI_IMAGE_FORMAT_GR1616, 4 } } }, + + { DRM_FORMAT_NV16, __DRI_IMAGE_FORMAT_NONE, + __DRI_IMAGE_COMPONENTS_Y_UV, PIPE_FORMAT_NV12, 2, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, + { 1, 1, 0, __DRI_IMAGE_FORMAT_GR88, 2 } } }, + + { DRM_FORMAT_AYUV, __DRI_IMAGE_FORMAT_ABGR8888, + __DRI_IMAGE_COMPONENTS_AYUV, PIPE_FORMAT_AYUV, 1, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_ABGR8888, 4 } } }, + { DRM_FORMAT_XYUV8888, __DRI_IMAGE_FORMAT_XBGR8888, + __DRI_IMAGE_COMPONENTS_XYUV, PIPE_FORMAT_XYUV, 1, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_XBGR8888, 4 } } }, + + /* For YUYV and UYVY buffers, we set up two overlapping DRI images + * and treat them as planar buffers in the compositors. + * Plane 0 is GR88 and samples YU or YV pairs and places Y into + * the R component, while plane 1 is ARGB/ABGR and samples YUYV/UYVY + * clusters and places pairs and places U into the G component and + * V into A. This lets the texture sampler interpolate the Y + * components correctly when sampling from plane 0, and interpolate + * U and V correctly when sampling from plane 1. */ + { DRM_FORMAT_YUYV, __DRI_IMAGE_FORMAT_NONE, + __DRI_IMAGE_COMPONENTS_Y_XUXV, PIPE_FORMAT_YUYV, 2, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88, 2 }, + { 0, 1, 0, __DRI_IMAGE_FORMAT_ARGB8888, 4 } } }, + { DRM_FORMAT_UYVY, __DRI_IMAGE_FORMAT_NONE, + __DRI_IMAGE_COMPONENTS_Y_UXVX, PIPE_FORMAT_UYVY, 2, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88, 2 }, + { 0, 1, 0, __DRI_IMAGE_FORMAT_ABGR8888, 4 } } } +}; + +const struct dri2_format_mapping * +dri2_get_mapping_by_fourcc(int fourcc) +{ + for (unsigned i = 0; i < ARRAY_SIZE(dri2_format_table); i++) { + if (dri2_format_table[i].dri_fourcc == fourcc) + return &dri2_format_table[i]; + } + + return NULL; +} + +const struct dri2_format_mapping * +dri2_get_mapping_by_format(int format) +{ + for (unsigned i = 0; i < ARRAY_SIZE(dri2_format_table); i++) { + if (dri2_format_table[i].dri_format == format) + return &dri2_format_table[i]; + } + + return NULL; +} + +enum pipe_format +dri2_get_pipe_format_for_dri_format(int format) +{ + for (unsigned i = 0; i < ARRAY_SIZE(dri2_format_table); i++) { + if (dri2_format_table[i].dri_format == format) + return dri2_format_table[i].pipe_format; + } + + return PIPE_FORMAT_NONE; +} + +boolean +dri2_yuv_dma_buf_supported(struct dri_screen *screen, + const struct dri2_format_mapping *map) +{ + struct pipe_screen *pscreen = screen->base.screen; + + for (unsigned i = 0; i < map->nplanes; i++) { + if (!pscreen->is_format_supported(pscreen, + dri2_get_pipe_format_for_dri_format(map->planes[i].dri_format), + screen->target, 0, 0, PIPE_BIND_SAMPLER_VIEW)) + return false; + } + return true; +} + +boolean +dri2_query_dma_buf_formats(__DRIscreen *_screen, int max, int *formats, + int *count) +{ + struct dri_screen *screen = dri_screen(_screen); + struct pipe_screen *pscreen = screen->base.screen; + int i, j; + + for (i = 0, j = 0; (i < ARRAY_SIZE(dri2_format_table)) && + (j < max || max == 0); i++) { + const struct dri2_format_mapping *map = &dri2_format_table[i]; + + /* The sRGB format is not a real FourCC as defined by drm_fourcc.h, so we + * must not leak it out to clients. + */ + if (dri2_format_table[i].dri_fourcc == __DRI_IMAGE_FOURCC_SARGB8888) + continue; + + if (pscreen->is_format_supported(pscreen, map->pipe_format, + screen->target, 0, 0, + PIPE_BIND_RENDER_TARGET) || + pscreen->is_format_supported(pscreen, map->pipe_format, + screen->target, 0, 0, + PIPE_BIND_SAMPLER_VIEW) || + dri2_yuv_dma_buf_supported(screen, map)) { + if (j < max) + formats[j] = map->dri_fourcc; + j++; + } + } + *count = j; + return true; +} + +/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/frontends/dri/dri_helpers.h b/src/gallium/frontends/dri/dri_helpers.h new file mode 100644 index 00000000000..0393a48a8ee --- /dev/null +++ b/src/gallium/frontends/dri/dri_helpers.h @@ -0,0 +1,84 @@ +/* + * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef DRI_HELPERS_H +#define DRI_HELPERS_H + +#include "dri_context.h" +#include "dri_screen.h" + + +struct dri2_format_mapping { + int dri_fourcc; + int dri_format; /* image format */ + int dri_components; + enum pipe_format pipe_format; + int nplanes; + struct { + int buffer_index; + int width_shift; + int height_shift; + uint32_t dri_format; /* plane format */ + int cpp; + } planes[3]; +}; + +extern const __DRI2fenceExtension dri2FenceExtension; + +const struct dri2_format_mapping * +dri2_get_mapping_by_fourcc(int fourcc); + +const struct dri2_format_mapping * +dri2_get_mapping_by_format(int format); + +enum pipe_format +dri2_get_pipe_format_for_dri_format(int format); + +boolean +dri2_query_dma_buf_formats(__DRIscreen *_screen, int max, int *formats, + int *count); +boolean +dri2_yuv_dma_buf_supported(struct dri_screen *screen, + const struct dri2_format_mapping *map); + +__DRIimage * +dri2_lookup_egl_image(struct dri_screen *screen, void *handle); + +__DRIimage * +dri2_create_image_from_renderbuffer(__DRIcontext *context, + int renderbuffer, void *loaderPrivate); + +__DRIimage * +dri2_create_image_from_renderbuffer2(__DRIcontext *context, + int renderbuffer, void *loaderPrivate, + unsigned *error); + +void +dri2_destroy_image(__DRIimage *img); + +__DRIimage * +dri2_create_from_texture(__DRIcontext *context, int target, unsigned texture, + int depth, int level, unsigned *error, + void *loaderPrivate); +#endif + +/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/frontends/dri/dri_query_renderer.c b/src/gallium/frontends/dri/dri_query_renderer.c new file mode 100644 index 00000000000..9a78fa38da6 --- /dev/null +++ b/src/gallium/frontends/dri/dri_query_renderer.c @@ -0,0 +1,93 @@ +#include "dri_query_renderer.h" + +#include "util/u_inlines.h" +#include "frontend/drm_driver.h" + +#include "utils.h" +#include "dri_screen.h" +#include "dri_query_renderer.h" + +static int +dri2_query_renderer_integer(__DRIscreen *_screen, int param, + unsigned int *value) +{ + struct dri_screen *screen = dri_screen(_screen); + + switch (param) { + case __DRI2_RENDERER_VENDOR_ID: + value[0] = + (unsigned int)screen->base.screen->get_param(screen->base.screen, + PIPE_CAP_VENDOR_ID); + return 0; + case __DRI2_RENDERER_DEVICE_ID: + value[0] = + (unsigned int)screen->base.screen->get_param(screen->base.screen, + PIPE_CAP_DEVICE_ID); + return 0; + case __DRI2_RENDERER_ACCELERATED: + value[0] = + (unsigned int)screen->base.screen->get_param(screen->base.screen, + PIPE_CAP_ACCELERATED); + return 0; + + case __DRI2_RENDERER_VIDEO_MEMORY: + value[0] = + (unsigned int)screen->base.screen->get_param(screen->base.screen, + PIPE_CAP_VIDEO_MEMORY); + return 0; + + case __DRI2_RENDERER_UNIFIED_MEMORY_ARCHITECTURE: + value[0] = + (unsigned int)screen->base.screen->get_param(screen->base.screen, + PIPE_CAP_UMA); + return 0; + + case __DRI2_RENDERER_HAS_TEXTURE_3D: + value[0] = + screen->base.screen->get_param(screen->base.screen, + PIPE_CAP_MAX_TEXTURE_3D_LEVELS) != 0; + return 0; + + case __DRI2_RENDERER_HAS_FRAMEBUFFER_SRGB: + value[0] = + screen->base.screen->is_format_supported(screen->base.screen, + PIPE_FORMAT_B8G8R8A8_SRGB, + PIPE_TEXTURE_2D, 0, 0, + PIPE_BIND_RENDER_TARGET); + return 0; + case __DRI2_RENDERER_HAS_CONTEXT_PRIORITY: + value[0] = + screen->base.screen->get_param(screen->base.screen, + PIPE_CAP_CONTEXT_PRIORITY_MASK); + if (!value[0]) + return -1; + return 0; + default: + return driQueryRendererIntegerCommon(_screen, param, value); + } +} + +static int +dri2_query_renderer_string(__DRIscreen *_screen, int param, + const char **value) +{ + struct dri_screen *screen = dri_screen(_screen); + + switch (param) { + case __DRI2_RENDERER_VENDOR_ID: + value[0] = screen->base.screen->get_vendor(screen->base.screen); + return 0; + case __DRI2_RENDERER_DEVICE_ID: + value[0] = screen->base.screen->get_name(screen->base.screen); + return 0; + default: + return -1; + } +} + +const __DRI2rendererQueryExtension dri2RendererQueryExtension = { + .base = { __DRI2_RENDERER_QUERY, 1 }, + + .queryInteger = dri2_query_renderer_integer, + .queryString = dri2_query_renderer_string +}; diff --git a/src/gallium/frontends/dri/dri_query_renderer.h b/src/gallium/frontends/dri/dri_query_renderer.h new file mode 100644 index 00000000000..59b3ff8e5b3 --- /dev/null +++ b/src/gallium/frontends/dri/dri_query_renderer.h @@ -0,0 +1,9 @@ +#ifndef DRI_QUERY_RENDERER_H +#define DRI_QUERY_RENDERER_H + +#include "dri_util.h" + +extern const +__DRI2rendererQueryExtension dri2RendererQueryExtension; + +#endif diff --git a/src/gallium/frontends/dri/dri_screen.c b/src/gallium/frontends/dri/dri_screen.c new file mode 100644 index 00000000000..fee392bba31 --- /dev/null +++ b/src/gallium/frontends/dri/dri_screen.c @@ -0,0 +1,605 @@ +/************************************************************************** + * + * Copyright 2009, VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ +/* + * Author: Keith Whitwell + * Author: Jakob Bornecrantz + */ + +#include "utils.h" + +#include "dri_screen.h" +#include "dri_context.h" +#include "dri_helpers.h" + +#include "util/u_inlines.h" +#include "pipe/p_screen.h" +#include "pipe/p_format.h" +#include "pipe-loader/pipe_loader.h" +#include "state_tracker/st_gl_api.h" /* for st_gl_api_create */ +#include "frontend/drm_driver.h" + +#include "util/u_debug.h" +#include "util/format/u_format_s3tc.h" + +#define MSAA_VISUAL_MAX_SAMPLES 32 + +#undef false + +const __DRIconfigOptionsExtension gallium_config_options = { + .base = { __DRI_CONFIG_OPTIONS, 2 }, + .xml = gallium_driinfo_xml, + .getXml = pipe_loader_get_driinfo_xml +}; + +#define false 0 + +static void +dri_fill_st_options(struct dri_screen *screen) +{ + struct st_config_options *options = &screen->options; + const struct driOptionCache *optionCache = &screen->dev->option_cache; + + options->disable_blend_func_extended = + driQueryOptionb(optionCache, "disable_blend_func_extended"); + options->disable_arb_gpu_shader5 = + driQueryOptionb(optionCache, "disable_arb_gpu_shader5"); + options->disable_glsl_line_continuations = + driQueryOptionb(optionCache, "disable_glsl_line_continuations"); + options->force_glsl_extensions_warn = + driQueryOptionb(optionCache, "force_glsl_extensions_warn"); + options->force_glsl_version = + driQueryOptioni(optionCache, "force_glsl_version"); + options->allow_glsl_extension_directive_midshader = + driQueryOptionb(optionCache, "allow_glsl_extension_directive_midshader"); + options->allow_glsl_builtin_const_expression = + driQueryOptionb(optionCache, "allow_glsl_builtin_const_expression"); + options->allow_glsl_relaxed_es = + driQueryOptionb(optionCache, "allow_glsl_relaxed_es"); + options->allow_glsl_builtin_variable_redeclaration = + driQueryOptionb(optionCache, "allow_glsl_builtin_variable_redeclaration"); + options->allow_higher_compat_version = + driQueryOptionb(optionCache, "allow_higher_compat_version"); + options->glsl_zero_init = driQueryOptionb(optionCache, "glsl_zero_init"); + options->force_integer_tex_nearest = + driQueryOptionb(optionCache, "force_integer_tex_nearest"); + options->vs_position_always_invariant = + driQueryOptionb(optionCache, "vs_position_always_invariant"); + options->force_glsl_abs_sqrt = + driQueryOptionb(optionCache, "force_glsl_abs_sqrt"); + options->allow_glsl_cross_stage_interpolation_mismatch = + driQueryOptionb(optionCache, "allow_glsl_cross_stage_interpolation_mismatch"); + options->allow_glsl_layout_qualifier_on_function_parameters = + driQueryOptionb(optionCache, "allow_glsl_layout_qualifier_on_function_parameters"); + options->allow_draw_out_of_order = + driQueryOptionb(optionCache, "allow_draw_out_of_order"); + + char *vendor_str = driQueryOptionstr(optionCache, "force_gl_vendor"); + /* not an empty string */ + if (*vendor_str) + options->force_gl_vendor = strdup(vendor_str); + + driComputeOptionsSha1(optionCache, options->config_options_sha1); +} + +static unsigned +dri_loader_get_cap(struct dri_screen *screen, enum dri_loader_cap cap) +{ + const __DRIdri2LoaderExtension *dri2_loader = screen->sPriv->dri2.loader; + const __DRIimageLoaderExtension *image_loader = screen->sPriv->image.loader; + + if (dri2_loader && dri2_loader->base.version >= 4 && + dri2_loader->getCapability) + return dri2_loader->getCapability(screen->sPriv->loaderPrivate, cap); + + if (image_loader && image_loader->base.version >= 2 && + image_loader->getCapability) + return image_loader->getCapability(screen->sPriv->loaderPrivate, cap); + + return 0; +} + +static const __DRIconfig ** +dri_fill_in_modes(struct dri_screen *screen) +{ + static const mesa_format mesa_formats[] = { + MESA_FORMAT_B10G10R10A2_UNORM, + MESA_FORMAT_B10G10R10X2_UNORM, + MESA_FORMAT_R10G10B10A2_UNORM, + MESA_FORMAT_R10G10B10X2_UNORM, + MESA_FORMAT_B8G8R8A8_UNORM, + MESA_FORMAT_B8G8R8X8_UNORM, + MESA_FORMAT_B8G8R8A8_SRGB, + MESA_FORMAT_B8G8R8X8_SRGB, + MESA_FORMAT_B5G6R5_UNORM, + MESA_FORMAT_RGBA_FLOAT16, + MESA_FORMAT_RGBX_FLOAT16, + + /* The 32-bit RGBA format must not precede the 32-bit BGRA format. + * Likewise for RGBX and BGRX. Otherwise, the GLX client and the GLX + * server may disagree on which format the GLXFBConfig represents, + * resulting in swapped color channels. + * + * The problem, as of 2017-05-30: + * When matching a GLXFBConfig to a __DRIconfig, GLX ignores the channel + * order and chooses the first __DRIconfig with the expected channel + * sizes. Specifically, GLX compares the GLXFBConfig's and __DRIconfig's + * __DRI_ATTRIB_{CHANNEL}_SIZE but ignores __DRI_ATTRIB_{CHANNEL}_MASK. + * + * EGL does not suffer from this problem. It correctly compares the + * channel masks when matching EGLConfig to __DRIconfig. + */ + + /* Required by Android, for HAL_PIXEL_FORMAT_RGBA_8888. */ + MESA_FORMAT_R8G8B8A8_UNORM, + + /* Required by Android, for HAL_PIXEL_FORMAT_RGBX_8888. */ + MESA_FORMAT_R8G8B8X8_UNORM, + }; + static const enum pipe_format pipe_formats[] = { + PIPE_FORMAT_B10G10R10A2_UNORM, + PIPE_FORMAT_B10G10R10X2_UNORM, + PIPE_FORMAT_R10G10B10A2_UNORM, + PIPE_FORMAT_R10G10B10X2_UNORM, + PIPE_FORMAT_BGRA8888_UNORM, + PIPE_FORMAT_BGRX8888_UNORM, + PIPE_FORMAT_BGRA8888_SRGB, + PIPE_FORMAT_BGRX8888_SRGB, + PIPE_FORMAT_B5G6R5_UNORM, + PIPE_FORMAT_R16G16B16A16_FLOAT, + PIPE_FORMAT_R16G16B16X16_FLOAT, + PIPE_FORMAT_RGBA8888_UNORM, + PIPE_FORMAT_RGBX8888_UNORM, + }; + mesa_format format; + __DRIconfig **configs = NULL; + uint8_t depth_bits_array[5]; + uint8_t stencil_bits_array[5]; + unsigned depth_buffer_factor; + unsigned msaa_samples_max; + unsigned i; + struct pipe_screen *p_screen = screen->base.screen; + bool pf_z16, pf_x8z24, pf_z24x8, pf_s8z24, pf_z24s8, pf_z32; + bool mixed_color_depth; + bool allow_rgba_ordering; + bool allow_rgb10; + bool allow_fp16; + + static const GLenum back_buffer_modes[] = { + __DRI_ATTRIB_SWAP_NONE, __DRI_ATTRIB_SWAP_UNDEFINED, + __DRI_ATTRIB_SWAP_COPY + }; + + if (driQueryOptionb(&screen->dev->option_cache, "always_have_depth_buffer")) { + /* all visuals will have a depth buffer */ + depth_buffer_factor = 0; + } + else { + depth_bits_array[0] = 0; + stencil_bits_array[0] = 0; + depth_buffer_factor = 1; + } + + allow_rgba_ordering = dri_loader_get_cap(screen, DRI_LOADER_CAP_RGBA_ORDERING); + allow_rgb10 = driQueryOptionb(&screen->dev->option_cache, "allow_rgb10_configs"); + allow_fp16 = driQueryOptionb(&screen->dev->option_cache, "allow_fp16_configs"); + allow_fp16 &= dri_loader_get_cap(screen, DRI_LOADER_CAP_FP16); + + msaa_samples_max = (screen->st_api->feature_mask & ST_API_FEATURE_MS_VISUALS_MASK) + ? MSAA_VISUAL_MAX_SAMPLES : 1; + + pf_x8z24 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z24X8_UNORM, + PIPE_TEXTURE_2D, 0, 0, + PIPE_BIND_DEPTH_STENCIL); + pf_z24x8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_X8Z24_UNORM, + PIPE_TEXTURE_2D, 0, 0, + PIPE_BIND_DEPTH_STENCIL); + pf_s8z24 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z24_UNORM_S8_UINT, + PIPE_TEXTURE_2D, 0, 0, + PIPE_BIND_DEPTH_STENCIL); + pf_z24s8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_S8_UINT_Z24_UNORM, + PIPE_TEXTURE_2D, 0, 0, + PIPE_BIND_DEPTH_STENCIL); + pf_z16 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z16_UNORM, + PIPE_TEXTURE_2D, 0, 0, + PIPE_BIND_DEPTH_STENCIL); + pf_z32 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z32_UNORM, + PIPE_TEXTURE_2D, 0, 0, + PIPE_BIND_DEPTH_STENCIL); + + if (pf_z16) { + depth_bits_array[depth_buffer_factor] = 16; + stencil_bits_array[depth_buffer_factor++] = 0; + } + if (pf_x8z24 || pf_z24x8) { + depth_bits_array[depth_buffer_factor] = 24; + stencil_bits_array[depth_buffer_factor++] = 0; + screen->d_depth_bits_last = pf_x8z24; + } + if (pf_s8z24 || pf_z24s8) { + depth_bits_array[depth_buffer_factor] = 24; + stencil_bits_array[depth_buffer_factor++] = 8; + screen->sd_depth_bits_last = pf_s8z24; + } + if (pf_z32) { + depth_bits_array[depth_buffer_factor] = 32; + stencil_bits_array[depth_buffer_factor++] = 0; + } + + mixed_color_depth = + p_screen->get_param(p_screen, PIPE_CAP_MIXED_COLOR_DEPTH_BITS); + + assert(ARRAY_SIZE(mesa_formats) == ARRAY_SIZE(pipe_formats)); + + /* Add configs. */ + for (format = 0; format < ARRAY_SIZE(mesa_formats); format++) { + __DRIconfig **new_configs = NULL; + unsigned num_msaa_modes = 0; /* includes a single-sample mode */ + uint8_t msaa_modes[MSAA_VISUAL_MAX_SAMPLES]; + + /* Expose only BGRA ordering if the loader doesn't support RGBA ordering. */ + if (!allow_rgba_ordering && + (mesa_formats[format] == MESA_FORMAT_R8G8B8A8_UNORM || + mesa_formats[format] == MESA_FORMAT_R8G8B8X8_UNORM)) + continue; + + if (!allow_rgb10 && + (mesa_formats[format] == MESA_FORMAT_B10G10R10A2_UNORM || + mesa_formats[format] == MESA_FORMAT_B10G10R10X2_UNORM || + mesa_formats[format] == MESA_FORMAT_R10G10B10A2_UNORM || + mesa_formats[format] == MESA_FORMAT_R10G10B10X2_UNORM)) + continue; + + if (!allow_fp16 && + (mesa_formats[format] == MESA_FORMAT_RGBA_FLOAT16 || + mesa_formats[format] == MESA_FORMAT_RGBX_FLOAT16)) + continue; + + if (!p_screen->is_format_supported(p_screen, pipe_formats[format], + PIPE_TEXTURE_2D, 0, 0, + PIPE_BIND_RENDER_TARGET | + PIPE_BIND_DISPLAY_TARGET)) + continue; + + for (i = 1; i <= msaa_samples_max; i++) { + int samples = i > 1 ? i : 0; + + if (p_screen->is_format_supported(p_screen, pipe_formats[format], + PIPE_TEXTURE_2D, samples, samples, + PIPE_BIND_RENDER_TARGET)) { + msaa_modes[num_msaa_modes++] = samples; + } + } + + if (num_msaa_modes) { + /* Single-sample configs with an accumulation buffer. */ + new_configs = driCreateConfigs(mesa_formats[format], + depth_bits_array, stencil_bits_array, + depth_buffer_factor, back_buffer_modes, + ARRAY_SIZE(back_buffer_modes), + msaa_modes, 1, + GL_TRUE, !mixed_color_depth, GL_FALSE); + configs = driConcatConfigs(configs, new_configs); + + /* Multi-sample configs without an accumulation buffer. */ + if (num_msaa_modes > 1) { + new_configs = driCreateConfigs(mesa_formats[format], + depth_bits_array, stencil_bits_array, + depth_buffer_factor, back_buffer_modes, + ARRAY_SIZE(back_buffer_modes), + msaa_modes+1, num_msaa_modes-1, + GL_FALSE, !mixed_color_depth, GL_FALSE); + configs = driConcatConfigs(configs, new_configs); + } + } + } + + if (configs == NULL) { + debug_printf("%s: driCreateConfigs failed\n", __FUNCTION__); + return NULL; + } + + return (const __DRIconfig **)configs; +} + +/** + * Roughly the converse of dri_fill_in_modes. + */ +void +dri_fill_st_visual(struct st_visual *stvis, + const struct dri_screen *screen, + const struct gl_config *mode) +{ + memset(stvis, 0, sizeof(*stvis)); + + if (!mode) { + stvis->no_config = true; + return; + } + + /* Deduce the color format. */ + switch (mode->redMask) { + case 0: + /* Formats > 32 bpp */ + assert(mode->floatMode); + if (mode->alphaShift > -1) { + assert(mode->alphaShift == 48); + stvis->color_format = PIPE_FORMAT_R16G16B16A16_FLOAT; + } else { + stvis->color_format = PIPE_FORMAT_R16G16B16X16_FLOAT; + } + break; + + case 0x3FF00000: + if (mode->alphaMask) { + assert(mode->alphaMask == 0xC0000000); + stvis->color_format = PIPE_FORMAT_B10G10R10A2_UNORM; + } else { + stvis->color_format = PIPE_FORMAT_B10G10R10X2_UNORM; + } + break; + + case 0x000003FF: + if (mode->alphaMask) { + assert(mode->alphaMask == 0xC0000000); + stvis->color_format = PIPE_FORMAT_R10G10B10A2_UNORM; + } else { + stvis->color_format = PIPE_FORMAT_R10G10B10X2_UNORM; + } + break; + + case 0x00FF0000: + if (mode->alphaMask) { + assert(mode->alphaMask == 0xFF000000); + stvis->color_format = mode->sRGBCapable ? + PIPE_FORMAT_BGRA8888_SRGB : + PIPE_FORMAT_BGRA8888_UNORM; + } else { + stvis->color_format = mode->sRGBCapable ? + PIPE_FORMAT_BGRX8888_SRGB : + PIPE_FORMAT_BGRX8888_UNORM; + } + break; + + case 0x000000FF: + if (mode->alphaMask) { + assert(mode->alphaMask == 0xFF000000); + stvis->color_format = mode->sRGBCapable ? + PIPE_FORMAT_RGBA8888_SRGB : + PIPE_FORMAT_RGBA8888_UNORM; + } else { + stvis->color_format = mode->sRGBCapable ? + PIPE_FORMAT_RGBX8888_SRGB : + PIPE_FORMAT_RGBX8888_UNORM; + } + break; + + case 0x0000F800: + stvis->color_format = PIPE_FORMAT_B5G6R5_UNORM; + break; + + default: + assert(!"unsupported visual: invalid red mask"); + return; + } + + if (mode->sampleBuffers) { + stvis->samples = mode->samples; + } + + switch (mode->depthBits) { + default: + case 0: + stvis->depth_stencil_format = PIPE_FORMAT_NONE; + break; + case 16: + stvis->depth_stencil_format = PIPE_FORMAT_Z16_UNORM; + break; + case 24: + if (mode->stencilBits == 0) { + stvis->depth_stencil_format = (screen->d_depth_bits_last) ? + PIPE_FORMAT_Z24X8_UNORM: + PIPE_FORMAT_X8Z24_UNORM; + } else { + stvis->depth_stencil_format = (screen->sd_depth_bits_last) ? + PIPE_FORMAT_Z24_UNORM_S8_UINT: + PIPE_FORMAT_S8_UINT_Z24_UNORM; + } + break; + case 32: + stvis->depth_stencil_format = PIPE_FORMAT_Z32_UNORM; + break; + } + + stvis->accum_format = (mode->accumRedBits > 0) ? + PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE; + + stvis->buffer_mask |= ST_ATTACHMENT_FRONT_LEFT_MASK; + stvis->render_buffer = ST_ATTACHMENT_FRONT_LEFT; + if (mode->doubleBufferMode) { + stvis->buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK; + stvis->render_buffer = ST_ATTACHMENT_BACK_LEFT; + } + if (mode->stereoMode) { + stvis->buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK; + if (mode->doubleBufferMode) + stvis->buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK; + } + + if (mode->depthBits > 0 || mode->stencilBits > 0) + stvis->buffer_mask |= ST_ATTACHMENT_DEPTH_STENCIL_MASK; + /* let the state tracker allocate the accum buffer */ +} + +static bool +dri_get_egl_image(struct st_manager *smapi, + void *egl_image, + struct st_egl_image *stimg) +{ + struct dri_screen *screen = (struct dri_screen *)smapi; + __DRIimage *img = NULL; + const struct dri2_format_mapping *map; + + if (screen->lookup_egl_image) { + img = screen->lookup_egl_image(screen, egl_image); + } + + if (!img) + return FALSE; + + stimg->texture = NULL; + pipe_resource_reference(&stimg->texture, img->texture); + map = dri2_get_mapping_by_fourcc(img->dri_fourcc); + stimg->format = map ? map->pipe_format : img->texture->format; + stimg->level = img->level; + stimg->layer = img->layer; + + if (img->imported_dmabuf && map) { + /* Guess sized internal format for dma-bufs. Could be used + * by EXT_EGL_image_storage. + */ + mesa_format mesa_format = driImageFormatToGLFormat(map->dri_format); + stimg->internalformat = driGLFormatToSizedInternalGLFormat(mesa_format); + } + + return TRUE; +} + +static int +dri_get_param(struct st_manager *smapi, + enum st_manager_param param) +{ + struct dri_screen *screen = (struct dri_screen *)smapi; + + switch(param) { + case ST_MANAGER_BROKEN_INVALIDATE: + return screen->broken_invalidate; + default: + return 0; + } +} + +void +dri_destroy_screen_helper(struct dri_screen * screen) +{ + if (screen->base.destroy) + screen->base.destroy(&screen->base); + + if (screen->st_api && screen->st_api->destroy) + screen->st_api->destroy(screen->st_api); + + if (screen->base.screen) + screen->base.screen->destroy(screen->base.screen); + + mtx_destroy(&screen->opencl_func_mutex); +} + +void +dri_destroy_screen(__DRIscreen * sPriv) +{ + struct dri_screen *screen = dri_screen(sPriv); + + dri_destroy_screen_helper(screen); + + pipe_loader_release(&screen->dev, 1); + + free(screen->options.force_gl_vendor); + + /* The caller in dri_util preserves the fd ownership */ + free(screen); + sPriv->driverPrivate = NULL; + sPriv->extensions = NULL; +} + +static void +dri_postprocessing_init(struct dri_screen *screen) +{ + unsigned i; + + for (i = 0; i < PP_FILTERS; i++) { + screen->pp_enabled[i] = driQueryOptioni(&screen->dev->option_cache, + pp_filters[i].name); + } +} + +static void +dri_set_background_context(struct st_context_iface *st, + struct util_queue_monitoring *queue_info) +{ + struct dri_context *ctx = (struct dri_context *)st->st_manager_private; + const __DRIbackgroundCallableExtension *backgroundCallable = + ctx->sPriv->dri2.backgroundCallable; + + /* Note: Mesa will only call this function if GL multithreading is enabled + * We only do that if the loader exposed the __DRI_BACKGROUND_CALLABLE + * extension. So we know that backgroundCallable is not NULL. + */ + assert(backgroundCallable); + backgroundCallable->setBackgroundContext(ctx->cPriv->loaderPrivate); + + if (ctx->hud) + hud_add_queue_for_monitoring(ctx->hud, queue_info); +} + +void +dri_init_options(struct dri_screen *screen) +{ + pipe_loader_load_options(screen->dev); + + dri_fill_st_options(screen); +} + +const __DRIconfig ** +dri_init_screen_helper(struct dri_screen *screen, + struct pipe_screen *pscreen) +{ + screen->base.screen = pscreen; + screen->base.get_egl_image = dri_get_egl_image; + screen->base.get_param = dri_get_param; + screen->base.set_background_context = dri_set_background_context; + + screen->st_api = st_gl_api_create(); + if (!screen->st_api) + return NULL; + + if(pscreen->get_param(pscreen, PIPE_CAP_NPOT_TEXTURES)) + screen->target = PIPE_TEXTURE_2D; + else + screen->target = PIPE_TEXTURE_RECT; + + dri_postprocessing_init(screen); + + screen->st_api->query_versions(screen->st_api, &screen->base, + &screen->options, + &screen->sPriv->max_gl_core_version, + &screen->sPriv->max_gl_compat_version, + &screen->sPriv->max_gl_es1_version, + &screen->sPriv->max_gl_es2_version); + + return dri_fill_in_modes(screen); +} + +/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/frontends/dri/dri_screen.h b/src/gallium/frontends/dri/dri_screen.h new file mode 100644 index 00000000000..e330aa1f2ac --- /dev/null +++ b/src/gallium/frontends/dri/dri_screen.h @@ -0,0 +1,161 @@ +/************************************************************************** + * + * Copyright 2009, VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ +/* + * Author: Keith Whitwell + * Author: Jakob Bornecrantz + */ + +#ifndef DRI_SCREEN_H +#define DRI_SCREEN_H + +#include "dri_util.h" + +#include "pipe/p_compiler.h" +#include "pipe/p_context.h" +#include "pipe/p_state.h" +#include "frontend/api.h" +#include "frontend/opencl_interop.h" +#include "os/os_thread.h" +#include "postprocess/filters.h" + +struct dri_context; +struct dri_drawable; +struct pipe_loader_device; + +struct dri_screen +{ + /* st_api */ + struct st_manager base; + struct st_api *st_api; + + /* on old libGL's invalidate doesn't get called as it should */ + boolean broken_invalidate; + + /* dri */ + __DRIscreen *sPriv; + boolean throttle; + + struct st_config_options options; + + /* Which postprocessing filters are enabled. */ + unsigned pp_enabled[PP_FILTERS]; + + /* drm */ + int fd; + boolean can_share_buffer; + + struct pipe_loader_device *dev; + + /* gallium */ + boolean d_depth_bits_last; + boolean sd_depth_bits_last; + boolean auto_fake_front; + boolean has_reset_status_query; + enum pipe_texture_target target; + + boolean swrast_no_present; + + /* hooks filled in by dri2 & drisw */ + __DRIimage * (*lookup_egl_image)(struct dri_screen *ctx, void *handle); + + /* OpenCL interop */ + mtx_t opencl_func_mutex; + opencl_dri_event_add_ref_t opencl_dri_event_add_ref; + opencl_dri_event_release_t opencl_dri_event_release; + opencl_dri_event_wait_t opencl_dri_event_wait; + opencl_dri_event_get_fence_t opencl_dri_event_get_fence; +}; + +/** cast wrapper */ +static inline struct dri_screen * +dri_screen(__DRIscreen * sPriv) +{ + return (struct dri_screen *)sPriv->driverPrivate; +} + +struct __DRIimageRec { + struct pipe_resource *texture; + unsigned level; + unsigned layer; + uint32_t dri_format; + uint32_t dri_fourcc; + uint32_t dri_components; + unsigned use; + unsigned plane; + + void *loader_private; + + boolean imported_dmabuf; + /** + * Provided by EGL_EXT_image_dma_buf_import. + */ + enum __DRIYUVColorSpace yuv_color_space; + enum __DRISampleRange sample_range; + enum __DRIChromaSiting horizontal_siting; + enum __DRIChromaSiting vertical_siting; + +}; + +static inline boolean +dri_with_format(__DRIscreen * sPriv) +{ + const __DRIdri2LoaderExtension *loader = sPriv->dri2.loader; + + return loader + && (loader->base.version >= 3) + && (loader->getBuffersWithFormat != NULL); +} + +void +dri_fill_st_visual(struct st_visual *stvis, + const struct dri_screen *screen, + const struct gl_config *mode); + +void +dri_init_options(struct dri_screen *screen); + +const __DRIconfig ** +dri_init_screen_helper(struct dri_screen *screen, + struct pipe_screen *pscreen); + +void +dri_destroy_screen_helper(struct dri_screen * screen); + +void +dri_destroy_screen(__DRIscreen * sPriv); + +extern const struct __DriverAPIRec dri_kms_driver_api; + +extern const struct __DriverAPIRec galliumdrm_driver_api; +extern const __DRIextension *galliumdrm_driver_extensions[]; +extern const struct __DriverAPIRec galliumsw_driver_api; +extern const __DRIextension *galliumsw_driver_extensions[]; +extern const __DRIconfigOptionsExtension gallium_config_options; + +#endif + +/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/frontends/dri/drisw.c b/src/gallium/frontends/dri/drisw.c new file mode 100644 index 00000000000..fcdc59ceec8 --- /dev/null +++ b/src/gallium/frontends/dri/drisw.c @@ -0,0 +1,576 @@ +/************************************************************************** + * + * Copyright 2009, VMware, Inc. + * All Rights Reserved. + * Copyright 2010 George Sapountzis + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "util/format/u_format.h" +#include "util/u_memory.h" +#include "util/u_inlines.h" +#include "util/u_box.h" +#include "pipe/p_context.h" +#include "pipe-loader/pipe_loader.h" +#include "frontend/drisw_api.h" +#include "state_tracker/st_context.h" + +#include "dri_screen.h" +#include "dri_context.h" +#include "dri_drawable.h" +#include "dri_helpers.h" +#include "dri_query_renderer.h" + +DEBUG_GET_ONCE_BOOL_OPTION(swrast_no_present, "SWRAST_NO_PRESENT", FALSE); + +static inline void +get_drawable_info(__DRIdrawable *dPriv, int *x, int *y, int *w, int *h) +{ + __DRIscreen *sPriv = dPriv->driScreenPriv; + const __DRIswrastLoaderExtension *loader = sPriv->swrast_loader; + + loader->getDrawableInfo(dPriv, + x, y, w, h, + dPriv->loaderPrivate); +} + +static inline void +put_image(__DRIdrawable *dPriv, void *data, unsigned width, unsigned height) +{ + __DRIscreen *sPriv = dPriv->driScreenPriv; + const __DRIswrastLoaderExtension *loader = sPriv->swrast_loader; + + loader->putImage(dPriv, __DRI_SWRAST_IMAGE_OP_SWAP, + 0, 0, width, height, + data, dPriv->loaderPrivate); +} + +static inline void +put_image2(__DRIdrawable *dPriv, void *data, int x, int y, + unsigned width, unsigned height, unsigned stride) +{ + __DRIscreen *sPriv = dPriv->driScreenPriv; + const __DRIswrastLoaderExtension *loader = sPriv->swrast_loader; + + loader->putImage2(dPriv, __DRI_SWRAST_IMAGE_OP_SWAP, + x, y, width, height, stride, + data, dPriv->loaderPrivate); +} + +static inline void +put_image_shm(__DRIdrawable *dPriv, int shmid, char *shmaddr, + unsigned offset, unsigned offset_x, int x, int y, + unsigned width, unsigned height, unsigned stride) +{ + __DRIscreen *sPriv = dPriv->driScreenPriv; + const __DRIswrastLoaderExtension *loader = sPriv->swrast_loader; + + /* if we have the newer interface, don't have to add the offset_x here. */ + if (loader->base.version > 4 && loader->putImageShm2) + loader->putImageShm2(dPriv, __DRI_SWRAST_IMAGE_OP_SWAP, + x, y, width, height, stride, + shmid, shmaddr, offset, dPriv->loaderPrivate); + else + loader->putImageShm(dPriv, __DRI_SWRAST_IMAGE_OP_SWAP, + x, y, width, height, stride, + shmid, shmaddr, offset + offset_x, dPriv->loaderPrivate); +} + +static inline void +get_image(__DRIdrawable *dPriv, int x, int y, int width, int height, void *data) +{ + __DRIscreen *sPriv = dPriv->driScreenPriv; + const __DRIswrastLoaderExtension *loader = sPriv->swrast_loader; + + loader->getImage(dPriv, + x, y, width, height, + data, dPriv->loaderPrivate); +} + +static inline void +get_image2(__DRIdrawable *dPriv, int x, int y, int width, int height, int stride, void *data) +{ + __DRIscreen *sPriv = dPriv->driScreenPriv; + const __DRIswrastLoaderExtension *loader = sPriv->swrast_loader; + + /* getImage2 support is only in version 3 or newer */ + if (loader->base.version < 3) + return; + + loader->getImage2(dPriv, + x, y, width, height, stride, + data, dPriv->loaderPrivate); +} + +static inline bool +get_image_shm(__DRIdrawable *dPriv, int x, int y, int width, int height, + struct pipe_resource *res) +{ + __DRIscreen *sPriv = dPriv->driScreenPriv; + const __DRIswrastLoaderExtension *loader = sPriv->swrast_loader; + struct winsys_handle whandle; + + whandle.type = WINSYS_HANDLE_TYPE_SHMID; + + if (loader->base.version < 4 || !loader->getImageShm) + return FALSE; + + if (!res->screen->resource_get_handle(res->screen, NULL, res, &whandle, PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE)) + return FALSE; + + if (loader->base.version > 5 && loader->getImageShm2) + return loader->getImageShm2(dPriv, x, y, width, height, whandle.handle, dPriv->loaderPrivate); + + loader->getImageShm(dPriv, x, y, width, height, whandle.handle, dPriv->loaderPrivate); + return TRUE; +} + +static void +drisw_update_drawable_info(struct dri_drawable *drawable) +{ + __DRIdrawable *dPriv = drawable->dPriv; + int x, y; + + get_drawable_info(dPriv, &x, &y, &dPriv->w, &dPriv->h); +} + +static void +drisw_get_image(struct dri_drawable *drawable, + int x, int y, unsigned width, unsigned height, unsigned stride, + void *data) +{ + __DRIdrawable *dPriv = drawable->dPriv; + int draw_x, draw_y, draw_w, draw_h; + + get_drawable_info(dPriv, &draw_x, &draw_y, &draw_w, &draw_h); + get_image2(dPriv, x, y, draw_w, draw_h, stride, data); +} + +static void +drisw_put_image(struct dri_drawable *drawable, + void *data, unsigned width, unsigned height) +{ + __DRIdrawable *dPriv = drawable->dPriv; + + put_image(dPriv, data, width, height); +} + +static void +drisw_put_image2(struct dri_drawable *drawable, + void *data, int x, int y, unsigned width, unsigned height, + unsigned stride) +{ + __DRIdrawable *dPriv = drawable->dPriv; + + put_image2(dPriv, data, x, y, width, height, stride); +} + +static inline void +drisw_put_image_shm(struct dri_drawable *drawable, + int shmid, char *shmaddr, unsigned offset, + unsigned offset_x, + int x, int y, unsigned width, unsigned height, + unsigned stride) +{ + __DRIdrawable *dPriv = drawable->dPriv; + + put_image_shm(dPriv, shmid, shmaddr, offset, offset_x, x, y, width, height, stride); +} + +static inline void +drisw_present_texture(__DRIdrawable *dPriv, + struct pipe_resource *ptex, struct pipe_box *sub_box) +{ + struct dri_drawable *drawable = dri_drawable(dPriv); + struct dri_screen *screen = dri_screen(drawable->sPriv); + + if (screen->swrast_no_present) + return; + + screen->base.screen->flush_frontbuffer(screen->base.screen, ptex, 0, 0, drawable, sub_box); +} + +static inline void +drisw_invalidate_drawable(__DRIdrawable *dPriv) +{ + struct dri_drawable *drawable = dri_drawable(dPriv); + + drawable->texture_stamp = dPriv->lastStamp - 1; + + p_atomic_inc(&drawable->base.stamp); +} + +static inline void +drisw_copy_to_front(__DRIdrawable * dPriv, + struct pipe_resource *ptex) +{ + drisw_present_texture(dPriv, ptex, NULL); + + drisw_invalidate_drawable(dPriv); +} + +/* + * Backend functions for st_framebuffer interface and swap_buffers. + */ + +static void +drisw_swap_buffers(__DRIdrawable *dPriv) +{ + struct dri_context *ctx = dri_get_current(dPriv->driScreenPriv); + struct dri_drawable *drawable = dri_drawable(dPriv); + struct pipe_resource *ptex; + + if (!ctx) + return; + + ptex = drawable->textures[ST_ATTACHMENT_BACK_LEFT]; + + if (ptex) { + if (ctx->pp) + pp_run(ctx->pp, ptex, ptex, drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]); + + if (ctx->hud) + hud_run(ctx->hud, ctx->st->cso_context, ptex); + + ctx->st->flush(ctx->st, ST_FLUSH_FRONT, NULL, NULL, NULL); + + if (drawable->stvis.samples > 1) { + /* Resolve the back buffer. */ + dri_pipe_blit(ctx->st->pipe, + drawable->textures[ST_ATTACHMENT_BACK_LEFT], + drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT]); + } + + drisw_copy_to_front(dPriv, ptex); + } +} + +static void +drisw_copy_sub_buffer(__DRIdrawable *dPriv, int x, int y, + int w, int h) +{ + struct dri_context *ctx = dri_get_current(dPriv->driScreenPriv); + struct dri_drawable *drawable = dri_drawable(dPriv); + struct pipe_resource *ptex; + struct pipe_box box; + if (!ctx) + return; + + ptex = drawable->textures[ST_ATTACHMENT_BACK_LEFT]; + + if (ptex) { + if (ctx->pp && drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]) + pp_run(ctx->pp, ptex, ptex, drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]); + + ctx->st->flush(ctx->st, ST_FLUSH_FRONT, NULL, NULL, NULL); + + u_box_2d(x, dPriv->h - y - h, w, h, &box); + drisw_present_texture(dPriv, ptex, &box); + } +} + +static void +drisw_flush_frontbuffer(struct dri_context *ctx, + struct dri_drawable *drawable, + enum st_attachment_type statt) +{ + struct pipe_resource *ptex; + + if (!ctx) + return; + + if (drawable->stvis.samples > 1) { + /* Resolve the front buffer. */ + dri_pipe_blit(ctx->st->pipe, + drawable->textures[ST_ATTACHMENT_FRONT_LEFT], + drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT]); + } + ptex = drawable->textures[statt]; + + if (ptex) { + drisw_copy_to_front(ctx->dPriv, ptex); + } +} + +/** + * Allocate framebuffer attachments. + * + * During fixed-size operation, the function keeps allocating new attachments + * as they are requested. Unused attachments are not removed, not until the + * framebuffer is resized or destroyed. + */ +static void +drisw_allocate_textures(struct dri_context *stctx, + struct dri_drawable *drawable, + const enum st_attachment_type *statts, + unsigned count) +{ + struct dri_screen *screen = dri_screen(drawable->sPriv); + const __DRIswrastLoaderExtension *loader = drawable->dPriv->driScreenPriv->swrast_loader; + struct pipe_resource templ; + unsigned width, height; + boolean resized; + unsigned i; + + width = drawable->dPriv->w; + height = drawable->dPriv->h; + + resized = (drawable->old_w != width || + drawable->old_h != height); + + /* remove outdated textures */ + if (resized) { + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { + pipe_resource_reference(&drawable->textures[i], NULL); + pipe_resource_reference(&drawable->msaa_textures[i], NULL); + } + } + + memset(&templ, 0, sizeof(templ)); + templ.target = screen->target; + templ.width0 = width; + templ.height0 = height; + templ.depth0 = 1; + templ.array_size = 1; + templ.last_level = 0; + + for (i = 0; i < count; i++) { + enum pipe_format format; + unsigned bind; + + /* the texture already exists or not requested */ + if (drawable->textures[statts[i]]) + continue; + + dri_drawable_get_format(drawable, statts[i], &format, &bind); + + /* if we don't do any present, no need for display targets */ + if (statts[i] != ST_ATTACHMENT_DEPTH_STENCIL && !screen->swrast_no_present) + bind |= PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_LINEAR; + + if (format == PIPE_FORMAT_NONE) + continue; + + templ.format = format; + templ.bind = bind; + templ.nr_samples = 0; + templ.nr_storage_samples = 0; + + if (statts[i] == ST_ATTACHMENT_FRONT_LEFT && + screen->base.screen->resource_create_front && + loader->base.version >= 3) { + drawable->textures[statts[i]] = + screen->base.screen->resource_create_front(screen->base.screen, &templ, (const void *)drawable); + } else + drawable->textures[statts[i]] = + screen->base.screen->resource_create(screen->base.screen, &templ); + + if (drawable->stvis.samples > 1) { + templ.bind = templ.bind & + ~(PIPE_BIND_SCANOUT | PIPE_BIND_SHARED | PIPE_BIND_DISPLAY_TARGET); + templ.nr_samples = drawable->stvis.samples; + templ.nr_storage_samples = drawable->stvis.samples; + drawable->msaa_textures[statts[i]] = + screen->base.screen->resource_create(screen->base.screen, &templ); + + dri_pipe_blit(stctx->st->pipe, + drawable->msaa_textures[statts[i]], + drawable->textures[statts[i]]); + } + } + + drawable->old_w = width; + drawable->old_h = height; +} + +static void +drisw_update_tex_buffer(struct dri_drawable *drawable, + struct dri_context *ctx, + struct pipe_resource *res) +{ + __DRIdrawable *dPriv = drawable->dPriv; + + struct st_context *st_ctx = (struct st_context *)ctx->st; + struct pipe_context *pipe = st_ctx->pipe; + struct pipe_transfer *transfer; + char *map; + int x, y, w, h; + int ximage_stride, line; + int cpp = util_format_get_blocksize(res->format); + + get_drawable_info(dPriv, &x, &y, &w, &h); + + map = pipe_transfer_map(pipe, res, + 0, 0, // level, layer, + PIPE_TRANSFER_WRITE, + x, y, w, h, &transfer); + + /* Copy the Drawable content to the mapped texture buffer */ + if (!get_image_shm(dPriv, x, y, w, h, res)) + get_image(dPriv, x, y, w, h, map); + + /* The pipe transfer has a pitch rounded up to the nearest 64 pixels. + get_image() has a pitch rounded up to 4 bytes. */ + ximage_stride = ((w * cpp) + 3) & -4; + for (line = h-1; line; --line) { + memmove(&map[line * transfer->stride], + &map[line * ximage_stride], + ximage_stride); + } + + pipe_transfer_unmap(pipe, transfer); +} + +static __DRIimageExtension driSWImageExtension = { + .base = { __DRI_IMAGE, 6 }, + + .createImageFromRenderbuffer = dri2_create_image_from_renderbuffer, + .createImageFromTexture = dri2_create_from_texture, + .destroyImage = dri2_destroy_image, +}; + +/* + * Backend function for init_screen. + */ + +static const __DRIextension *drisw_screen_extensions[] = { + &driTexBufferExtension.base, + &dri2RendererQueryExtension.base, + &dri2ConfigQueryExtension.base, + &dri2FenceExtension.base, + &dri2NoErrorExtension.base, + &driSWImageExtension.base, + &dri2FlushControlExtension.base, + NULL +}; + +static const struct drisw_loader_funcs drisw_lf = { + .get_image = drisw_get_image, + .put_image = drisw_put_image, + .put_image2 = drisw_put_image2 +}; + +static const struct drisw_loader_funcs drisw_shm_lf = { + .get_image = drisw_get_image, + .put_image = drisw_put_image, + .put_image2 = drisw_put_image2, + .put_image_shm = drisw_put_image_shm +}; + +static const __DRIconfig ** +drisw_init_screen(__DRIscreen * sPriv) +{ + const __DRIswrastLoaderExtension *loader = sPriv->swrast_loader; + const __DRIconfig **configs; + struct dri_screen *screen; + struct pipe_screen *pscreen = NULL; + const struct drisw_loader_funcs *lf = &drisw_lf; + + screen = CALLOC_STRUCT(dri_screen); + if (!screen) + return NULL; + + screen->sPriv = sPriv; + screen->fd = -1; + + screen->swrast_no_present = debug_get_option_swrast_no_present(); + + sPriv->driverPrivate = (void *)screen; + sPriv->extensions = drisw_screen_extensions; + if (loader->base.version >= 4) { + if (loader->putImageShm) + lf = &drisw_shm_lf; + } + + if (pipe_loader_sw_probe_dri(&screen->dev, lf)) { + dri_init_options(screen); + + pscreen = pipe_loader_create_screen(screen->dev); + } + + if (!pscreen) + goto fail; + + configs = dri_init_screen_helper(screen, pscreen); + if (!configs) + goto fail; + + screen->lookup_egl_image = dri2_lookup_egl_image; + + return configs; +fail: + dri_destroy_screen_helper(screen); + if (screen->dev) + pipe_loader_release(&screen->dev, 1); + FREE(screen); + return NULL; +} + +static boolean +drisw_create_buffer(__DRIscreen * sPriv, + __DRIdrawable * dPriv, + const struct gl_config * visual, boolean isPixmap) +{ + struct dri_drawable *drawable = NULL; + + if (!dri_create_buffer(sPriv, dPriv, visual, isPixmap)) + return FALSE; + + drawable = dPriv->driverPrivate; + + drawable->allocate_textures = drisw_allocate_textures; + drawable->update_drawable_info = drisw_update_drawable_info; + drawable->flush_frontbuffer = drisw_flush_frontbuffer; + drawable->update_tex_buffer = drisw_update_tex_buffer; + + return TRUE; +} + +/** + * DRI driver virtual function table. + * + * DRI versions differ in their implementation of init_screen and swap_buffers. + */ +const struct __DriverAPIRec galliumsw_driver_api = { + .InitScreen = drisw_init_screen, + .DestroyScreen = dri_destroy_screen, + .CreateContext = dri_create_context, + .DestroyContext = dri_destroy_context, + .CreateBuffer = drisw_create_buffer, + .DestroyBuffer = dri_destroy_buffer, + .SwapBuffers = drisw_swap_buffers, + .MakeCurrent = dri_make_current, + .UnbindContext = dri_unbind_context, + .CopySubBuffer = drisw_copy_sub_buffer, +}; + +/* This is the table of extensions that the loader will dlsym() for. */ +const __DRIextension *galliumsw_driver_extensions[] = { + &driCoreExtension.base, + &driSWRastExtension.base, + &driCopySubBufferExtension.base, + &gallium_config_options.base, + NULL +}; + +/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/frontends/dri/meson.build b/src/gallium/frontends/dri/meson.build new file mode 100644 index 00000000000..4bb41157e42 --- /dev/null +++ b/src/gallium/frontends/dri/meson.build @@ -0,0 +1,58 @@ +# Copyright © 2017 Dylan Baker + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +inc_st_dri = include_directories('.') + +files_libdri = files( + 'dri_context.c', + 'dri_context.h', + 'dri_drawable.c', + 'dri_drawable.h', + 'dri_helpers.c', + 'dri_helpers.h', + 'dri_query_renderer.c', + 'dri_query_renderer.h', + 'dri_screen.c', + 'dri_screen.h', +) + +if with_dri + files_libdri += files('drisw.c') +endif + +if with_dri2 + files_libdri += files('dri2.c') +endif + +libdri_c_args = [] +if with_gallium_softpipe + libdri_c_args += '-DGALLIUM_SOFTPIPE' +endif + +libdri = static_library( + 'dri', + files_libdri, + include_directories : [ + inc_include, inc_util, inc_mesa, inc_mapi, inc_src, inc_gallium, + inc_gallium_aux, inc_dri_common, + ], + c_args : [c_vis_args, libdri_c_args], + dependencies : dep_libdrm, +) diff --git a/src/gallium/frontends/glx/xlib/Makefile.sources b/src/gallium/frontends/glx/xlib/Makefile.sources new file mode 100644 index 00000000000..9e31a70eb3e --- /dev/null +++ b/src/gallium/frontends/glx/xlib/Makefile.sources @@ -0,0 +1,9 @@ +C_SOURCES := \ + glx_api.c \ + glx_getproc.c \ + glx_usefont.c \ + xm_api.c \ + xm_api.h \ + xm_public.h \ + xm_st.c \ + xm_st.h diff --git a/src/gallium/frontends/glx/xlib/SConscript b/src/gallium/frontends/glx/xlib/SConscript new file mode 100644 index 00000000000..1d5dd1df4fd --- /dev/null +++ b/src/gallium/frontends/glx/xlib/SConscript @@ -0,0 +1,18 @@ +####################################################################### +# SConscript for xlib state_tracker + +Import('*') + +env = env.Clone() + +env.Append(CPPPATH = [ + '#/src', + '#/src/mapi', + '#/src/mesa', +]) + +st_xlib = env.ConvenienceLibrary( + target = 'st_xlib', + source = env.ParseSourceList('Makefile.sources', 'C_SOURCES') +) +Export('st_xlib') diff --git a/src/gallium/frontends/glx/xlib/glx_api.c b/src/gallium/frontends/glx/xlib/glx_api.c new file mode 100644 index 00000000000..281111bdfb0 --- /dev/null +++ b/src/gallium/frontends/glx/xlib/glx_api.c @@ -0,0 +1,2777 @@ +/* + * Mesa 3-D graphics library + * + * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. + * Copyright (C) 2009 VMware, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + + +/** + * "Fake" GLX API implemented in terms of the XMesa*() functions. + */ + + + +#define GLX_GLXEXT_PROTOTYPES +#include "GL/glx.h" + +#include +#include +#include +#include + +#include "xm_api.h" +#include "main/errors.h" +#include "util/u_math.h" +#include "util/u_memory.h" + +/* An "Atrribs/Attribs" typo was fixed in glxproto.h in Nov 2014. + * This is in case we don't have the updated header. + */ +#if !defined(X_GLXCreateContextAttribsARB) && \ + defined(X_GLXCreateContextAtrribsARB) +#define X_GLXCreateContextAttribsARB X_GLXCreateContextAtrribsARB +#endif + +/* This indicates the client-side GLX API and GLX encoder version. */ +#define CLIENT_MAJOR_VERSION 1 +#define CLIENT_MINOR_VERSION 4 /* but don't have 1.3's pbuffers, etc yet */ + +/* This indicates the server-side GLX decoder version. + * GLX 1.4 indicates OpenGL 1.3 support + */ +#define SERVER_MAJOR_VERSION 1 +#define SERVER_MINOR_VERSION 4 + +/* Who implemented this GLX? */ +#define VENDOR "Brian Paul" + +#define EXTENSIONS \ + "GLX_MESA_copy_sub_buffer " \ + "GLX_MESA_pixmap_colormap " \ + "GLX_MESA_release_buffers " \ + "GLX_ARB_create_context " \ + "GLX_ARB_create_context_profile " \ + "GLX_ARB_get_proc_address " \ + "GLX_EXT_create_context_es_profile " \ + "GLX_EXT_create_context_es2_profile " \ + "GLX_EXT_texture_from_pixmap " \ + "GLX_EXT_visual_info " \ + "GLX_EXT_visual_rating " \ + /*"GLX_SGI_video_sync "*/ \ + "GLX_SGIX_fbconfig " \ + "GLX_SGIX_pbuffer " + +#define DEFAULT_DIRECT GL_TRUE + + +/** XXX this could be based on gallium's max texture size */ +#define PBUFFER_MAX_SIZE 16384 + + +/** + * The GLXContext typedef is defined as a pointer to this structure. + */ +struct __GLXcontextRec +{ + Display *currentDpy; + GLboolean isDirect; + GLXDrawable currentDrawable; + GLXDrawable currentReadable; + XID xid; + + XMesaContext xmesaContext; +}; + + + +static pipe_tsd ContextTSD; + +/** Set current context for calling thread */ +static void +SetCurrentContext(GLXContext c) +{ + pipe_tsd_set(&ContextTSD, c); +} + +/** Get current context for calling thread */ +static GLXContext +GetCurrentContext(void) +{ + return pipe_tsd_get(&ContextTSD); +} + + + +/**********************************************************************/ +/*** GLX Visual Code ***/ +/**********************************************************************/ + +#define DONT_CARE -1 + + +static XMesaVisual *VisualTable = NULL; +static int NumVisuals = 0; + + + +/* Macro to handle c_class vs class field name in XVisualInfo struct */ +#if defined(__cplusplus) || defined(c_plusplus) +#define CLASS c_class +#else +#define CLASS class +#endif + + + +/* + * Test if the given XVisualInfo is usable for Mesa rendering. + */ +static GLboolean +is_usable_visual( XVisualInfo *vinfo ) +{ + switch (vinfo->CLASS) { + case StaticGray: + case GrayScale: + /* Any StaticGray/GrayScale visual works in RGB or CI mode */ + return GL_TRUE; + case StaticColor: + case PseudoColor: + /* Any StaticColor/PseudoColor visual of at least 4 bits */ + if (vinfo->depth>=4) { + return GL_TRUE; + } + else { + return GL_FALSE; + } + case TrueColor: + case DirectColor: + /* Any depth of TrueColor or DirectColor works in RGB mode */ + return GL_TRUE; + default: + /* This should never happen */ + return GL_FALSE; + } +} + + +/* + * Given an XVisualInfo and RGB, Double, and Depth buffer flags, save the + * configuration in our list of GLX visuals. + */ +static XMesaVisual +save_glx_visual( Display *dpy, XVisualInfo *vinfo, + GLboolean rgbFlag, GLboolean alphaFlag, GLboolean dbFlag, + GLboolean stereoFlag, + GLint depth_size, GLint stencil_size, + GLint accumRedSize, GLint accumGreenSize, + GLint accumBlueSize, GLint accumAlphaSize, + GLint level, GLint numAuxBuffers, GLuint num_samples ) +{ + GLboolean ximageFlag = GL_TRUE; + XMesaVisual xmvis; + GLint i; + GLboolean comparePointers; + + if (!rgbFlag) + return NULL; + + if (dbFlag) { + /* Check if the MESA_BACK_BUFFER env var is set */ + char *backbuffer = getenv("MESA_BACK_BUFFER"); + if (backbuffer) { + if (backbuffer[0]=='p' || backbuffer[0]=='P') { + ximageFlag = GL_FALSE; + } + else if (backbuffer[0]=='x' || backbuffer[0]=='X') { + ximageFlag = GL_TRUE; + } + else { + _mesa_warning(NULL, "Mesa: invalid value for MESA_BACK_BUFFER environment variable, using an XImage."); + } + } + } + + if (stereoFlag) { + /* stereo not supported */ + return NULL; + } + + if (stencil_size > 0 && depth_size > 0) + depth_size = 24; + + /* Comparing IDs uses less memory but sometimes fails. */ + /* XXX revisit this after 3.0 is finished. */ + if (getenv("MESA_GLX_VISUAL_HACK")) + comparePointers = GL_TRUE; + else + comparePointers = GL_FALSE; + + /* Force the visual to have an alpha channel */ + if (rgbFlag && getenv("MESA_GLX_FORCE_ALPHA")) + alphaFlag = GL_TRUE; + + /* First check if a matching visual is already in the list */ + for (i=0; idisplay == dpy + && v->mesa_visual.level == level + && v->mesa_visual.numAuxBuffers == numAuxBuffers + && v->mesa_visual.samples == num_samples + && v->ximage_flag == ximageFlag + && v->mesa_visual.doubleBufferMode == dbFlag + && v->mesa_visual.stereoMode == stereoFlag + && (v->mesa_visual.alphaBits > 0) == alphaFlag + && (v->mesa_visual.depthBits >= depth_size || depth_size == 0) + && (v->mesa_visual.stencilBits >= stencil_size || stencil_size == 0) + && (v->mesa_visual.accumRedBits >= accumRedSize || accumRedSize == 0) + && (v->mesa_visual.accumGreenBits >= accumGreenSize || accumGreenSize == 0) + && (v->mesa_visual.accumBlueBits >= accumBlueSize || accumBlueSize == 0) + && (v->mesa_visual.accumAlphaBits >= accumAlphaSize || accumAlphaSize == 0)) { + /* now either compare XVisualInfo pointers or visual IDs */ + if ((!comparePointers && v->visinfo->visualid == vinfo->visualid) + || (comparePointers && v->vishandle == vinfo)) { + return v; + } + } + } + + /* Create a new visual and add it to the list. */ + + xmvis = XMesaCreateVisual( dpy, vinfo, rgbFlag, alphaFlag, dbFlag, + stereoFlag, ximageFlag, + depth_size, stencil_size, + accumRedSize, accumBlueSize, + accumBlueSize, accumAlphaSize, num_samples, level, + GLX_NONE_EXT ); + if (xmvis) { + /* Save a copy of the pointer now so we can find this visual again + * if we need to search for it in find_glx_visual(). + */ + xmvis->vishandle = vinfo; + /* Allocate more space for additional visual */ + VisualTable = realloc(VisualTable, sizeof(XMesaVisual) * (NumVisuals + 1)); + /* add xmvis to the list */ + VisualTable[NumVisuals] = xmvis; + NumVisuals++; + /* XXX minor hack, because XMesaCreateVisual doesn't support an + * aux buffers parameter. + */ + xmvis->mesa_visual.numAuxBuffers = numAuxBuffers; + } + return xmvis; +} + + +/** + * Return the default number of bits for the Z buffer. + * If defined, use the MESA_GLX_DEPTH_BITS env var value. + * Otherwise, use the DEFAULT_SOFTWARE_DEPTH_BITS constant. + * XXX probably do the same thing for stencil, accum, etc. + */ +static GLint +default_depth_bits(void) +{ + int zBits; + const char *zEnv = getenv("MESA_GLX_DEPTH_BITS"); + if (zEnv) + zBits = atoi(zEnv); + else + zBits = 24; + return zBits; +} + +static GLint +default_alpha_bits(void) +{ + int aBits; + const char *aEnv = getenv("MESA_GLX_ALPHA_BITS"); + if (aEnv) + aBits = atoi(aEnv); + else + aBits = 0; + return aBits; +} + +static GLint +default_accum_bits(void) +{ + return 16; +} + + + +/* + * Create a GLX visual from a regular XVisualInfo. + * This is called when Fake GLX is given an XVisualInfo which wasn't + * returned by glXChooseVisual. Since this is the first time we're + * considering this visual we'll take a guess at reasonable values + * for depth buffer size, stencil size, accum size, etc. + * This is the best we can do with a client-side emulation of GLX. + */ +static XMesaVisual +create_glx_visual( Display *dpy, XVisualInfo *visinfo ) +{ + GLint zBits = default_depth_bits(); + GLint accBits = default_accum_bits(); + GLboolean alphaFlag = default_alpha_bits() > 0; + + if (is_usable_visual( visinfo )) { + /* Configure this visual as RGB, double-buffered, depth-buffered. */ + /* This is surely wrong for some people's needs but what else */ + /* can be done? They should use glXChooseVisual(). */ + return save_glx_visual( dpy, visinfo, + GL_TRUE, /* rgb */ + alphaFlag, /* alpha */ + GL_TRUE, /* double */ + GL_FALSE, /* stereo */ + zBits, + 8, /* stencil bits */ + accBits, /* r */ + accBits, /* g */ + accBits, /* b */ + accBits, /* a */ + 0, /* level */ + 0, /* numAux */ + 0 /* numSamples */ + ); + } + else { + _mesa_warning(NULL, "Mesa: error in glXCreateContext: bad visual\n"); + return NULL; + } +} + + + +/* + * Find the GLX visual associated with an XVisualInfo. + */ +static XMesaVisual +find_glx_visual( Display *dpy, XVisualInfo *vinfo ) +{ + int i; + + /* try to match visual id */ + for (i=0;idisplay==dpy + && VisualTable[i]->visinfo->visualid == vinfo->visualid) { + return VisualTable[i]; + } + } + + /* if that fails, try to match pointers */ + for (i=0;idisplay==dpy && VisualTable[i]->vishandle==vinfo) { + return VisualTable[i]; + } + } + + return NULL; +} + + +/** + * Try to get an X visual which matches the given arguments. + */ +static XVisualInfo * +get_visual( Display *dpy, int scr, unsigned int depth, int xclass ) +{ + XVisualInfo temp, *vis; + long mask; + int n; + unsigned int default_depth; + int default_class; + + mask = VisualScreenMask | VisualDepthMask | VisualClassMask; + temp.screen = scr; + temp.depth = depth; + temp.CLASS = xclass; + + default_depth = DefaultDepth(dpy,scr); + default_class = DefaultVisual(dpy,scr)->CLASS; + + if (depth==default_depth && xclass==default_class) { + /* try to get root window's visual */ + temp.visualid = DefaultVisual(dpy,scr)->visualid; + mask |= VisualIDMask; + } + + vis = XGetVisualInfo( dpy, mask, &temp, &n ); + + /* In case bits/pixel > 24, make sure color channels are still <=8 bits. + * An SGI Infinite Reality system, for example, can have 30bpp pixels: + * 10 bits per color channel. Mesa's limited to a max of 8 bits/channel. + */ + if (vis && depth > 24 && (xclass==TrueColor || xclass==DirectColor)) { + if (util_bitcount((GLuint) vis->red_mask ) <= 8 && + util_bitcount((GLuint) vis->green_mask) <= 8 && + util_bitcount((GLuint) vis->blue_mask ) <= 8) { + return vis; + } + else { + free((void *) vis); + return NULL; + } + } + + return vis; +} + + +/* + * Retrieve the value of the given environment variable and find + * the X visual which matches it. + * Input: dpy - the display + * screen - the screen number + * varname - the name of the environment variable + * Return: an XVisualInfo pointer to NULL if error. + */ +static XVisualInfo * +get_env_visual(Display *dpy, int scr, const char *varname) +{ + char value[100], type[100]; + int depth, xclass = -1; + XVisualInfo *vis; + + if (!getenv( varname )) { + return NULL; + } + + strncpy( value, getenv(varname), 100 ); + value[99] = 0; + + sscanf( value, "%s %d", type, &depth ); + + if (strcmp(type,"TrueColor")==0) xclass = TrueColor; + else if (strcmp(type,"DirectColor")==0) xclass = DirectColor; + else if (strcmp(type,"PseudoColor")==0) xclass = PseudoColor; + else if (strcmp(type,"StaticColor")==0) xclass = StaticColor; + else if (strcmp(type,"GrayScale")==0) xclass = GrayScale; + else if (strcmp(type,"StaticGray")==0) xclass = StaticGray; + + if (xclass>-1 && depth>0) { + vis = get_visual( dpy, scr, depth, xclass ); + if (vis) { + return vis; + } + } + + _mesa_warning(NULL, "GLX unable to find visual class=%s, depth=%d.", + type, depth); + + return NULL; +} + + + +/* + * Select an X visual which satisfies the RGBA flag and minimum depth. + * Input: dpy, + * screen - X display and screen number + * min_depth - minimum visual depth + * preferred_class - preferred GLX visual class or DONT_CARE + * Return: pointer to an XVisualInfo or NULL. + */ +static XVisualInfo * +choose_x_visual( Display *dpy, int screen, int min_depth, + int preferred_class ) +{ + XVisualInfo *vis; + int xclass, visclass = 0; + int depth; + + /* First see if the MESA_RGB_VISUAL env var is defined */ + vis = get_env_visual( dpy, screen, "MESA_RGB_VISUAL" ); + if (vis) { + return vis; + } + /* Otherwise, search for a suitable visual */ + if (preferred_class==DONT_CARE) { + for (xclass=0;xclass<6;xclass++) { + switch (xclass) { + case 0: visclass = TrueColor; break; + case 1: visclass = DirectColor; break; + case 2: visclass = PseudoColor; break; + case 3: visclass = StaticColor; break; + case 4: visclass = GrayScale; break; + case 5: visclass = StaticGray; break; + } + if (min_depth==0) { + /* start with shallowest */ + for (depth=0;depth<=32;depth++) { + if (visclass==TrueColor && depth==8) { + /* Special case: try to get 8-bit PseudoColor before */ + /* 8-bit TrueColor */ + vis = get_visual( dpy, screen, 8, PseudoColor ); + if (vis) { + return vis; + } + } + vis = get_visual( dpy, screen, depth, visclass ); + if (vis) { + return vis; + } + } + } + else { + /* start with deepest */ + for (depth=32;depth>=min_depth;depth--) { + if (visclass==TrueColor && depth==8) { + /* Special case: try to get 8-bit PseudoColor before */ + /* 8-bit TrueColor */ + vis = get_visual( dpy, screen, 8, PseudoColor ); + if (vis) { + return vis; + } + } + vis = get_visual( dpy, screen, depth, visclass ); + if (vis) { + return vis; + } + } + } + } + } + else { + /* search for a specific visual class */ + switch (preferred_class) { + case GLX_TRUE_COLOR_EXT: visclass = TrueColor; break; + case GLX_DIRECT_COLOR_EXT: visclass = DirectColor; break; + case GLX_PSEUDO_COLOR_EXT: visclass = PseudoColor; break; + case GLX_STATIC_COLOR_EXT: visclass = StaticColor; break; + case GLX_GRAY_SCALE_EXT: visclass = GrayScale; break; + case GLX_STATIC_GRAY_EXT: visclass = StaticGray; break; + default: return NULL; + } + if (min_depth==0) { + /* start with shallowest */ + for (depth=0;depth<=32;depth++) { + vis = get_visual( dpy, screen, depth, visclass ); + if (vis) { + return vis; + } + } + } + else { + /* start with deepest */ + for (depth=32;depth>=min_depth;depth--) { + vis = get_visual( dpy, screen, depth, visclass ); + if (vis) { + return vis; + } + } + } + } + + /* didn't find a visual */ + return NULL; +} + + + + +/**********************************************************************/ +/*** Display-related functions ***/ +/**********************************************************************/ + + +/** + * Free all XMesaVisuals which are associated with the given display. + */ +static void +destroy_visuals_on_display(Display *dpy) +{ + int i; + for (i = 0; i < NumVisuals; i++) { + if (VisualTable[i]->display == dpy) { + /* remove this visual */ + int j; + free(VisualTable[i]); + for (j = i; j < NumVisuals - 1; j++) + VisualTable[j] = VisualTable[j + 1]; + NumVisuals--; + } + } +} + + +/** + * Called from XCloseDisplay() to let us free our display-related data. + */ +static int +close_display_callback(Display *dpy, XExtCodes *codes) +{ + xmesa_destroy_buffers_on_display(dpy); + destroy_visuals_on_display(dpy); + xmesa_close_display(dpy); + return 0; +} + + +/** + * Look for the named extension on given display and return a pointer + * to the _XExtension data, or NULL if extension not found. + */ +static _XExtension * +lookup_extension(Display *dpy, const char *extName) +{ + _XExtension *ext; + for (ext = dpy->ext_procs; ext; ext = ext->next) { + if (ext->name && strcmp(ext->name, extName) == 0) { + return ext; + } + } + return NULL; +} + + +/** + * Whenever we're given a new Display pointer, call this function to + * register our close_display_callback function. + */ +static void +register_with_display(Display *dpy) +{ + const char *extName = "MesaGLX"; + _XExtension *ext; + + ext = lookup_extension(dpy, extName); + if (!ext) { + XExtCodes *c = XAddExtension(dpy); + ext = dpy->ext_procs; /* new extension is at head of list */ + assert(c->extension == ext->codes.extension); + (void) c; + ext->name = strdup(extName); + ext->close_display = close_display_callback; + } +} + + +/** + * Fake an error. + */ +static int +generate_error(Display *dpy, + unsigned char error_code, + XID resourceid, + unsigned char minor_code, + Bool core) +{ + XErrorHandler handler; + int major_opcode; + int first_event; + int first_error; + XEvent event; + + handler = XSetErrorHandler(NULL); + XSetErrorHandler(handler); + if (!handler) { + return 0; + } + + if (!XQueryExtension(dpy, GLX_EXTENSION_NAME, &major_opcode, &first_event, &first_error)) { + major_opcode = 0; + first_event = 0; + first_error = 0; + } + + if (!core) { + error_code += first_error; + } + + memset(&event, 0, sizeof event); + + event.xerror.type = X_Error; + event.xerror.display = dpy; + event.xerror.resourceid = resourceid; + event.xerror.serial = NextRequest(dpy) - 1; + event.xerror.error_code = error_code; + event.xerror.request_code = major_opcode; + event.xerror.minor_code = minor_code; + + return handler(dpy, &event.xerror); +} + + +/**********************************************************************/ +/*** Begin Fake GLX API Functions ***/ +/**********************************************************************/ + + +/** + * Helper used by glXChooseVisual and glXChooseFBConfig. + * The fbConfig parameter must be GL_FALSE for the former and GL_TRUE for + * the later. + * In either case, the attribute list is terminated with the value 'None'. + */ +static XMesaVisual +choose_visual( Display *dpy, int screen, const int *list, GLboolean fbConfig ) +{ + const GLboolean rgbModeDefault = fbConfig; + const int *parselist; + XVisualInfo *vis; + int min_red=0, min_green=0, min_blue=0; + GLboolean rgb_flag = rgbModeDefault; + GLboolean alpha_flag = GL_FALSE; + GLboolean double_flag = GL_FALSE; + GLboolean stereo_flag = GL_FALSE; + GLint depth_size = 0; + GLint stencil_size = 0; + GLint accumRedSize = 0; + GLint accumGreenSize = 0; + GLint accumBlueSize = 0; + GLint accumAlphaSize = 0; + int level = 0; + int visual_type = DONT_CARE; + GLint caveat = DONT_CARE; + XMesaVisual xmvis = NULL; + int desiredVisualID = -1; + int numAux = 0; + GLint num_samples = 0; + + if (xmesa_init( dpy ) != 0) { + _mesa_warning(NULL, "Failed to initialize display"); + return NULL; + } + + parselist = list; + + while (*parselist) { + + if (fbConfig && + parselist[1] == GLX_DONT_CARE && + parselist[0] != GLX_LEVEL) { + /* For glXChooseFBConfig(), skip attributes whose value is + * GLX_DONT_CARE, unless it's GLX_LEVEL (which can legitimately be + * a negative value). + * + * From page 17 (23 of the pdf) of the GLX 1.4 spec: + * GLX DONT CARE may be specified for all attributes except GLX LEVEL. + */ + parselist += 2; + continue; + } + + switch (*parselist) { + case GLX_USE_GL: + if (fbConfig) { + /* invalid token */ + return NULL; + } + else { + /* skip */ + parselist++; + } + break; + case GLX_BUFFER_SIZE: + parselist++; + parselist++; + break; + case GLX_LEVEL: + parselist++; + level = *parselist++; + break; + case GLX_RGBA: + if (fbConfig) { + /* invalid token */ + return NULL; + } + else { + rgb_flag = GL_TRUE; + parselist++; + } + break; + case GLX_DOUBLEBUFFER: + parselist++; + if (fbConfig) { + double_flag = *parselist++; + } + else { + double_flag = GL_TRUE; + } + break; + case GLX_STEREO: + parselist++; + if (fbConfig) { + stereo_flag = *parselist++; + } + else { + stereo_flag = GL_TRUE; + } + break; + case GLX_AUX_BUFFERS: + parselist++; + numAux = *parselist++; + if (numAux > MAX_AUX_BUFFERS) + return NULL; + break; + case GLX_RED_SIZE: + parselist++; + min_red = *parselist++; + break; + case GLX_GREEN_SIZE: + parselist++; + min_green = *parselist++; + break; + case GLX_BLUE_SIZE: + parselist++; + min_blue = *parselist++; + break; + case GLX_ALPHA_SIZE: + parselist++; + { + GLint size = *parselist++; + alpha_flag = size ? GL_TRUE : GL_FALSE; + } + break; + case GLX_DEPTH_SIZE: + parselist++; + depth_size = *parselist++; + break; + case GLX_STENCIL_SIZE: + parselist++; + stencil_size = *parselist++; + break; + case GLX_ACCUM_RED_SIZE: + parselist++; + { + GLint size = *parselist++; + accumRedSize = MAX2( accumRedSize, size ); + } + break; + case GLX_ACCUM_GREEN_SIZE: + parselist++; + { + GLint size = *parselist++; + accumGreenSize = MAX2( accumGreenSize, size ); + } + break; + case GLX_ACCUM_BLUE_SIZE: + parselist++; + { + GLint size = *parselist++; + accumBlueSize = MAX2( accumBlueSize, size ); + } + break; + case GLX_ACCUM_ALPHA_SIZE: + parselist++; + { + GLint size = *parselist++; + accumAlphaSize = MAX2( accumAlphaSize, size ); + } + break; + + /* + * GLX_EXT_visual_info extension + */ + case GLX_X_VISUAL_TYPE_EXT: + parselist++; + visual_type = *parselist++; + break; + case GLX_TRANSPARENT_TYPE_EXT: + parselist++; + parselist++; + break; + case GLX_TRANSPARENT_INDEX_VALUE_EXT: + parselist++; + parselist++; + break; + case GLX_TRANSPARENT_RED_VALUE_EXT: + case GLX_TRANSPARENT_GREEN_VALUE_EXT: + case GLX_TRANSPARENT_BLUE_VALUE_EXT: + case GLX_TRANSPARENT_ALPHA_VALUE_EXT: + /* ignore */ + parselist++; + parselist++; + break; + + /* + * GLX_EXT_visual_info extension + */ + case GLX_VISUAL_CAVEAT_EXT: + parselist++; + caveat = *parselist++; /* ignored for now */ + break; + + /* + * GLX_ARB_multisample + */ + case GLX_SAMPLE_BUFFERS_ARB: + /* ignore */ + parselist++; + parselist++; + break; + case GLX_SAMPLES_ARB: + parselist++; + num_samples = *parselist++; + break; + + /* + * FBConfig attribs. + */ + case GLX_RENDER_TYPE: + if (!fbConfig) + return NULL; + parselist++; + if (*parselist & GLX_RGBA_BIT) { + rgb_flag = GL_TRUE; + } + else if (*parselist & GLX_COLOR_INDEX_BIT) { + rgb_flag = GL_FALSE; + } + else if (*parselist == 0) { + rgb_flag = GL_TRUE; + } + parselist++; + break; + case GLX_DRAWABLE_TYPE: + if (!fbConfig) + return NULL; + parselist++; + if (*parselist & ~(GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT)) { + return NULL; /* bad bit */ + } + parselist++; + break; + case GLX_FBCONFIG_ID: + case GLX_VISUAL_ID: + if (!fbConfig) + return NULL; + parselist++; + desiredVisualID = *parselist++; + break; + case GLX_X_RENDERABLE: + case GLX_MAX_PBUFFER_WIDTH: + case GLX_MAX_PBUFFER_HEIGHT: + case GLX_MAX_PBUFFER_PIXELS: + if (!fbConfig) + return NULL; /* invalid config option */ + parselist += 2; /* ignore the parameter */ + break; + + case GLX_BIND_TO_TEXTURE_RGB_EXT: + parselist++; /*skip*/ + break; + case GLX_BIND_TO_TEXTURE_RGBA_EXT: + parselist++; /*skip*/ + break; + case GLX_BIND_TO_MIPMAP_TEXTURE_EXT: + parselist++; /*skip*/ + break; + case GLX_BIND_TO_TEXTURE_TARGETS_EXT: + parselist++; + if (*parselist & ~(GLX_TEXTURE_1D_BIT_EXT | + GLX_TEXTURE_2D_BIT_EXT | + GLX_TEXTURE_RECTANGLE_BIT_EXT)) { + /* invalid bit */ + return NULL; + } + break; + case GLX_Y_INVERTED_EXT: + parselist++; /*skip*/ + break; + + case None: + /* end of list */ + break; + + default: + /* undefined attribute */ + _mesa_warning(NULL, "unexpected attrib 0x%x in choose_visual()", + *parselist); + return NULL; + } + } + + (void) caveat; + + if (num_samples < 0) { + _mesa_warning(NULL, "GLX_SAMPLES_ARB: number of samples must not be negative"); + return NULL; + } + + /* + * Since we're only simulating the GLX extension this function will never + * find any real GL visuals. Instead, all we can do is try to find an RGB + * or CI visual of appropriate depth. Other requested attributes such as + * double buffering, depth buffer, etc. will be associated with the X + * visual and stored in the VisualTable[]. + */ + if (desiredVisualID != -1) { + /* try to get a specific visual, by visualID */ + XVisualInfo temp; + int n; + temp.visualid = desiredVisualID; + temp.screen = screen; + vis = XGetVisualInfo(dpy, VisualIDMask | VisualScreenMask, &temp, &n); + if (vis) { + /* give the visual some useful GLX attributes */ + double_flag = GL_TRUE; + rgb_flag = GL_TRUE; + } + } + else if (level==0) { + /* normal color planes */ + /* Get an RGB visual */ + int min_rgb = min_red + min_green + min_blue; + if (min_rgb>1 && min_rgb<8) { + /* a special case to be sure we can get a monochrome visual */ + min_rgb = 1; + } + vis = choose_x_visual( dpy, screen, min_rgb, visual_type ); + } + else { + _mesa_warning(NULL, "overlay not supported"); + return NULL; + } + + if (vis) { + /* Note: we're not exactly obeying the glXChooseVisual rules here. + * When GLX_DEPTH_SIZE = 1 is specified we're supposed to choose the + * largest depth buffer size, which is 32bits/value. Instead, we + * return 16 to maintain performance with earlier versions of Mesa. + */ + if (stencil_size > 0) + depth_size = 24; /* if Z and stencil, always use 24+8 format */ + else if (depth_size > 24) + depth_size = 32; + else if (depth_size > 16) + depth_size = 24; + else if (depth_size > 0) { + depth_size = default_depth_bits(); + } + + if (!alpha_flag) { + alpha_flag = default_alpha_bits() > 0; + } + + /* we only support one size of stencil and accum buffers. */ + if (stencil_size > 0) + stencil_size = 8; + + if (accumRedSize > 0 || + accumGreenSize > 0 || + accumBlueSize > 0 || + accumAlphaSize > 0) { + + accumRedSize = + accumGreenSize = + accumBlueSize = default_accum_bits(); + + accumAlphaSize = alpha_flag ? accumRedSize : 0; + } + + xmvis = save_glx_visual( dpy, vis, rgb_flag, alpha_flag, double_flag, + stereo_flag, depth_size, stencil_size, + accumRedSize, accumGreenSize, + accumBlueSize, accumAlphaSize, level, numAux, + num_samples ); + } + + return xmvis; +} + + +PUBLIC XVisualInfo * +glXChooseVisual( Display *dpy, int screen, int *list ) +{ + XMesaVisual xmvis; + + /* register ourselves as an extension on this display */ + register_with_display(dpy); + + xmvis = choose_visual(dpy, screen, list, GL_FALSE); + if (xmvis) { + /* create a new vishandle - the cached one may be stale */ + xmvis->vishandle = malloc(sizeof(XVisualInfo)); + if (xmvis->vishandle) { + memcpy(xmvis->vishandle, xmvis->visinfo, sizeof(XVisualInfo)); + } + return xmvis->vishandle; + } + else + return NULL; +} + + +/** + * Helper function used by other glXCreateContext functions. + */ +static GLXContext +create_context(Display *dpy, XMesaVisual xmvis, + XMesaContext shareCtx, Bool direct, + unsigned major, unsigned minor, + unsigned profileMask, unsigned contextFlags) +{ + GLXContext glxCtx; + + if (!dpy || !xmvis) + return 0; + + glxCtx = CALLOC_STRUCT(__GLXcontextRec); + if (!glxCtx) + return 0; + + /* deallocate unused windows/buffers */ +#if 0 + XMesaGarbageCollect(); +#endif + + glxCtx->xmesaContext = XMesaCreateContext(xmvis, shareCtx, major, minor, + profileMask, contextFlags); + if (!glxCtx->xmesaContext) { + free(glxCtx); + return NULL; + } + + glxCtx->isDirect = DEFAULT_DIRECT; + glxCtx->currentDpy = dpy; + glxCtx->xid = (XID) glxCtx; /* self pointer */ + + return glxCtx; +} + + +PUBLIC GLXContext +glXCreateContext( Display *dpy, XVisualInfo *visinfo, + GLXContext shareCtx, Bool direct ) +{ + XMesaVisual xmvis; + + xmvis = find_glx_visual( dpy, visinfo ); + if (!xmvis) { + /* This visual wasn't found with glXChooseVisual() */ + xmvis = create_glx_visual( dpy, visinfo ); + if (!xmvis) { + /* unusable visual */ + return NULL; + } + } + + return create_context(dpy, xmvis, + shareCtx ? shareCtx->xmesaContext : NULL, + direct, + 1, 0, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, 0x0); +} + + +/* GLX 1.3 and later */ +PUBLIC Bool +glXMakeContextCurrent( Display *dpy, GLXDrawable draw, + GLXDrawable read, GLXContext ctx ) +{ + GLXContext glxCtx = ctx; + GLXContext current = GetCurrentContext(); + static boolean firsttime = 1, no_rast = 0; + + if (firsttime) { + no_rast = getenv("SP_NO_RAST") != NULL; + firsttime = 0; + } + + if (ctx) { + XMesaBuffer drawBuffer = NULL, readBuffer = NULL; + XMesaContext xmctx = glxCtx->xmesaContext; + + /* either both must be null, or both must be non-null */ + if (!draw != !read) + return False; + + if (draw) { + /* Find the XMesaBuffer which corresponds to 'draw' */ + drawBuffer = XMesaFindBuffer( dpy, draw ); + if (!drawBuffer) { + /* drawable must be a new window! */ + drawBuffer = XMesaCreateWindowBuffer( xmctx->xm_visual, draw ); + if (!drawBuffer) { + /* Out of memory, or context/drawable depth mismatch */ + return False; + } + } + } + + if (read) { + /* Find the XMesaBuffer which corresponds to 'read' */ + readBuffer = XMesaFindBuffer( dpy, read ); + if (!readBuffer) { + /* drawable must be a new window! */ + readBuffer = XMesaCreateWindowBuffer( xmctx->xm_visual, read ); + if (!readBuffer) { + /* Out of memory, or context/drawable depth mismatch */ + return False; + } + } + } + + if (no_rast && current == ctx) + return True; + + /* Now make current! */ + if (XMesaMakeCurrent2(xmctx, drawBuffer, readBuffer)) { + ctx->currentDpy = dpy; + ctx->currentDrawable = draw; + ctx->currentReadable = read; + SetCurrentContext(ctx); + return True; + } + else { + return False; + } + } + else if (!ctx && !draw && !read) { + /* release current context w/out assigning new one. */ + XMesaMakeCurrent2( NULL, NULL, NULL ); + SetCurrentContext(NULL); + return True; + } + else { + /* We were given an invalid set of arguments */ + return False; + } +} + + +PUBLIC Bool +glXMakeCurrent( Display *dpy, GLXDrawable drawable, GLXContext ctx ) +{ + return glXMakeContextCurrent( dpy, drawable, drawable, ctx ); +} + + +PUBLIC GLXContext +glXGetCurrentContext(void) +{ + return GetCurrentContext(); +} + + +PUBLIC Display * +glXGetCurrentDisplay(void) +{ + GLXContext glxCtx = glXGetCurrentContext(); + + return glxCtx ? glxCtx->currentDpy : NULL; +} + + +PUBLIC Display * +glXGetCurrentDisplayEXT(void) +{ + return glXGetCurrentDisplay(); +} + + +PUBLIC GLXDrawable +glXGetCurrentDrawable(void) +{ + GLXContext gc = glXGetCurrentContext(); + return gc ? gc->currentDrawable : 0; +} + + +PUBLIC GLXDrawable +glXGetCurrentReadDrawable(void) +{ + GLXContext gc = glXGetCurrentContext(); + return gc ? gc->currentReadable : 0; +} + + +PUBLIC GLXDrawable +glXGetCurrentReadDrawableSGI(void) +{ + return glXGetCurrentReadDrawable(); +} + + +PUBLIC GLXPixmap +glXCreateGLXPixmap( Display *dpy, XVisualInfo *visinfo, Pixmap pixmap ) +{ + XMesaVisual v; + XMesaBuffer b; + + v = find_glx_visual( dpy, visinfo ); + if (!v) { + v = create_glx_visual( dpy, visinfo ); + if (!v) { + /* unusable visual */ + return 0; + } + } + + b = XMesaCreatePixmapBuffer( v, pixmap, 0 ); + if (!b) { + return 0; + } + return b->ws.drawable; +} + + +/*** GLX_MESA_pixmap_colormap ***/ + +PUBLIC GLXPixmap +glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visinfo, + Pixmap pixmap, Colormap cmap ) +{ + XMesaVisual v; + XMesaBuffer b; + + v = find_glx_visual( dpy, visinfo ); + if (!v) { + v = create_glx_visual( dpy, visinfo ); + if (!v) { + /* unusable visual */ + return 0; + } + } + + b = XMesaCreatePixmapBuffer( v, pixmap, cmap ); + if (!b) { + return 0; + } + return b->ws.drawable; +} + + +PUBLIC void +glXDestroyGLXPixmap( Display *dpy, GLXPixmap pixmap ) +{ + XMesaBuffer b = XMesaFindBuffer(dpy, pixmap); + if (b) { + XMesaDestroyBuffer(b); + } + else if (getenv("MESA_DEBUG")) { + _mesa_warning(NULL, "Mesa: glXDestroyGLXPixmap: invalid pixmap\n"); + } +} + + +PUBLIC void +glXCopyContext( Display *dpy, GLXContext src, GLXContext dst, + unsigned long mask ) +{ + XMesaContext xm_src = src->xmesaContext; + XMesaContext xm_dst = dst->xmesaContext; + (void) dpy; + if (GetCurrentContext() == src) { + glFlush(); + } + XMesaCopyContext(xm_src, xm_dst, mask); +} + + +PUBLIC Bool +glXQueryExtension( Display *dpy, int *errorBase, int *eventBase ) +{ + int op, ev, err; + /* Mesa's GLX isn't really an X extension but we try to act like one. */ + if (!XQueryExtension(dpy, GLX_EXTENSION_NAME, &op, &ev, &err)) + ev = err = 0; + if (errorBase) + *errorBase = err; + if (eventBase) + *eventBase = ev; + return True; /* we're faking GLX so always return success */ +} + + +PUBLIC void +glXDestroyContext( Display *dpy, GLXContext ctx ) +{ + if (ctx) { + GLXContext glxCtx = ctx; + (void) dpy; + XMesaDestroyContext( glxCtx->xmesaContext ); + XMesaGarbageCollect(); + free(glxCtx); + } +} + + +PUBLIC Bool +glXIsDirect( Display *dpy, GLXContext ctx ) +{ + return ctx ? ctx->isDirect : False; +} + + + +PUBLIC void +glXSwapBuffers( Display *dpy, GLXDrawable drawable ) +{ + XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable ); + static boolean firsttime = 1, no_rast = 0; + + if (firsttime) { + no_rast = getenv("SP_NO_RAST") != NULL; + firsttime = 0; + } + + if (no_rast) + return; + + if (buffer) { + XMesaSwapBuffers(buffer); + } + else if (getenv("MESA_DEBUG")) { + _mesa_warning(NULL, "glXSwapBuffers: invalid drawable 0x%x\n", + (int) drawable); + } +} + + + +/*** GLX_MESA_copy_sub_buffer ***/ + +PUBLIC void +glXCopySubBufferMESA(Display *dpy, GLXDrawable drawable, + int x, int y, int width, int height) +{ + XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable ); + if (buffer) { + XMesaCopySubBuffer(buffer, x, y, width, height); + } + else if (getenv("MESA_DEBUG")) { + _mesa_warning(NULL, "Mesa: glXCopySubBufferMESA: invalid drawable\n"); + } +} + + +PUBLIC Bool +glXQueryVersion( Display *dpy, int *maj, int *min ) +{ + (void) dpy; + /* Return GLX version, not Mesa version */ + assert(CLIENT_MAJOR_VERSION == SERVER_MAJOR_VERSION); + *maj = CLIENT_MAJOR_VERSION; + *min = MIN2( CLIENT_MINOR_VERSION, SERVER_MINOR_VERSION ); + return True; +} + + +/* + * Query the GLX attributes of the given XVisualInfo. + */ +static int +get_config( XMesaVisual xmvis, int attrib, int *value, GLboolean fbconfig ) +{ + assert(xmvis); + switch(attrib) { + case GLX_USE_GL: + if (fbconfig) + return GLX_BAD_ATTRIBUTE; + *value = (int) True; + return 0; + case GLX_BUFFER_SIZE: + *value = xmvis->visinfo->depth; + return 0; + case GLX_LEVEL: + *value = xmvis->mesa_visual.level; + return 0; + case GLX_RGBA: + if (fbconfig) + return GLX_BAD_ATTRIBUTE; + *value = True; + return 0; + case GLX_DOUBLEBUFFER: + *value = (int) xmvis->mesa_visual.doubleBufferMode; + return 0; + case GLX_STEREO: + *value = (int) xmvis->mesa_visual.stereoMode; + return 0; + case GLX_AUX_BUFFERS: + *value = xmvis->mesa_visual.numAuxBuffers; + return 0; + case GLX_RED_SIZE: + *value = xmvis->mesa_visual.redBits; + return 0; + case GLX_GREEN_SIZE: + *value = xmvis->mesa_visual.greenBits; + return 0; + case GLX_BLUE_SIZE: + *value = xmvis->mesa_visual.blueBits; + return 0; + case GLX_ALPHA_SIZE: + *value = xmvis->mesa_visual.alphaBits; + return 0; + case GLX_DEPTH_SIZE: + *value = xmvis->mesa_visual.depthBits; + return 0; + case GLX_STENCIL_SIZE: + *value = xmvis->mesa_visual.stencilBits; + return 0; + case GLX_ACCUM_RED_SIZE: + *value = xmvis->mesa_visual.accumRedBits; + return 0; + case GLX_ACCUM_GREEN_SIZE: + *value = xmvis->mesa_visual.accumGreenBits; + return 0; + case GLX_ACCUM_BLUE_SIZE: + *value = xmvis->mesa_visual.accumBlueBits; + return 0; + case GLX_ACCUM_ALPHA_SIZE: + *value = xmvis->mesa_visual.accumAlphaBits; + return 0; + + /* + * GLX_EXT_visual_info extension + */ + case GLX_X_VISUAL_TYPE_EXT: + switch (xmvis->visinfo->CLASS) { + case StaticGray: *value = GLX_STATIC_GRAY_EXT; return 0; + case GrayScale: *value = GLX_GRAY_SCALE_EXT; return 0; + case StaticColor: *value = GLX_STATIC_GRAY_EXT; return 0; + case PseudoColor: *value = GLX_PSEUDO_COLOR_EXT; return 0; + case TrueColor: *value = GLX_TRUE_COLOR_EXT; return 0; + case DirectColor: *value = GLX_DIRECT_COLOR_EXT; return 0; + } + return 0; + case GLX_TRANSPARENT_TYPE_EXT: + /* normal planes */ + *value = GLX_NONE_EXT; + return 0; + case GLX_TRANSPARENT_INDEX_VALUE_EXT: + /* undefined */ + return 0; + case GLX_TRANSPARENT_RED_VALUE_EXT: + /* undefined */ + return 0; + case GLX_TRANSPARENT_GREEN_VALUE_EXT: + /* undefined */ + return 0; + case GLX_TRANSPARENT_BLUE_VALUE_EXT: + /* undefined */ + return 0; + case GLX_TRANSPARENT_ALPHA_VALUE_EXT: + /* undefined */ + return 0; + + /* + * GLX_EXT_visual_info extension + */ + case GLX_VISUAL_CAVEAT_EXT: + /* test for zero, just in case */ + if (xmvis->mesa_visual.visualRating > 0) + *value = xmvis->mesa_visual.visualRating; + else + *value = GLX_NONE_EXT; + return 0; + + /* + * GLX_ARB_multisample + */ + case GLX_SAMPLE_BUFFERS_ARB: + *value = xmvis->mesa_visual.sampleBuffers; + return 0; + case GLX_SAMPLES_ARB: + *value = xmvis->mesa_visual.samples; + return 0; + + /* + * For FBConfigs: + */ + case GLX_SCREEN_EXT: + if (!fbconfig) + return GLX_BAD_ATTRIBUTE; + *value = xmvis->visinfo->screen; + break; + case GLX_DRAWABLE_TYPE: /*SGIX too */ + if (!fbconfig) + return GLX_BAD_ATTRIBUTE; + *value = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT; + break; + case GLX_RENDER_TYPE_SGIX: + if (!fbconfig) + return GLX_BAD_ATTRIBUTE; + *value = GLX_RGBA_BIT; + break; + case GLX_X_RENDERABLE_SGIX: + if (!fbconfig) + return GLX_BAD_ATTRIBUTE; + *value = True; /* XXX really? */ + break; + case GLX_FBCONFIG_ID_SGIX: + if (!fbconfig) + return GLX_BAD_ATTRIBUTE; + *value = xmvis->visinfo->visualid; + break; + case GLX_MAX_PBUFFER_WIDTH: + if (!fbconfig) + return GLX_BAD_ATTRIBUTE; + /* XXX should be same as ctx->Const.MaxRenderbufferSize */ + *value = DisplayWidth(xmvis->display, xmvis->visinfo->screen); + break; + case GLX_MAX_PBUFFER_HEIGHT: + if (!fbconfig) + return GLX_BAD_ATTRIBUTE; + *value = DisplayHeight(xmvis->display, xmvis->visinfo->screen); + break; + case GLX_MAX_PBUFFER_PIXELS: + if (!fbconfig) + return GLX_BAD_ATTRIBUTE; + *value = DisplayWidth(xmvis->display, xmvis->visinfo->screen) * + DisplayHeight(xmvis->display, xmvis->visinfo->screen); + break; + case GLX_VISUAL_ID: + if (!fbconfig) + return GLX_BAD_ATTRIBUTE; + *value = xmvis->visinfo->visualid; + break; + + case GLX_BIND_TO_TEXTURE_RGB_EXT: + *value = True; /*XXX*/ + break; + case GLX_BIND_TO_TEXTURE_RGBA_EXT: + /* XXX review */ + *value = xmvis->mesa_visual.alphaBits > 0 ? True : False; + break; + case GLX_BIND_TO_MIPMAP_TEXTURE_EXT: + *value = True; /*XXX*/ + break; + case GLX_BIND_TO_TEXTURE_TARGETS_EXT: + *value = (GLX_TEXTURE_1D_BIT_EXT | + GLX_TEXTURE_2D_BIT_EXT | + GLX_TEXTURE_RECTANGLE_BIT_EXT); /*XXX*/ + break; + case GLX_Y_INVERTED_EXT: + *value = True; /*XXX*/ + break; + + default: + return GLX_BAD_ATTRIBUTE; + } + return Success; +} + + +PUBLIC int +glXGetConfig( Display *dpy, XVisualInfo *visinfo, + int attrib, int *value ) +{ + XMesaVisual xmvis; + int k; + if (!dpy || !visinfo) + return GLX_BAD_ATTRIBUTE; + + xmvis = find_glx_visual( dpy, visinfo ); + if (!xmvis) { + /* this visual wasn't obtained with glXChooseVisual */ + xmvis = create_glx_visual( dpy, visinfo ); + if (!xmvis) { + /* this visual can't be used for GL rendering */ + if (attrib==GLX_USE_GL) { + *value = (int) False; + return 0; + } + else { + return GLX_BAD_VISUAL; + } + } + } + + k = get_config(xmvis, attrib, value, GL_FALSE); + return k; +} + + +PUBLIC void +glXWaitGL( void ) +{ + XMesaContext xmesa = XMesaGetCurrentContext(); + XMesaFlush( xmesa ); +} + + + +PUBLIC void +glXWaitX( void ) +{ + XMesaContext xmesa = XMesaGetCurrentContext(); + XMesaFlush( xmesa ); +} + + +static const char * +get_extensions( void ) +{ + return EXTENSIONS; +} + + + +/* GLX 1.1 and later */ +PUBLIC const char * +glXQueryExtensionsString( Display *dpy, int screen ) +{ + (void) dpy; + (void) screen; + return get_extensions(); +} + + + +/* GLX 1.1 and later */ +PUBLIC const char * +glXQueryServerString( Display *dpy, int screen, int name ) +{ + static char version[1000]; + sprintf(version, "%d.%d %s", + SERVER_MAJOR_VERSION, SERVER_MINOR_VERSION, xmesa_get_name()); + + (void) dpy; + (void) screen; + + switch (name) { + case GLX_EXTENSIONS: + return get_extensions(); + case GLX_VENDOR: + return VENDOR; + case GLX_VERSION: + return version; + default: + return NULL; + } +} + + + +/* GLX 1.1 and later */ +PUBLIC const char * +glXGetClientString( Display *dpy, int name ) +{ + static char version[1000]; + sprintf(version, "%d.%d %s", CLIENT_MAJOR_VERSION, + CLIENT_MINOR_VERSION, xmesa_get_name()); + + (void) dpy; + + switch (name) { + case GLX_EXTENSIONS: + return get_extensions(); + case GLX_VENDOR: + return VENDOR; + case GLX_VERSION: + return version; + default: + return NULL; + } +} + + + +/* + * GLX 1.3 and later + */ + + +PUBLIC int +glXGetFBConfigAttrib(Display *dpy, GLXFBConfig config, + int attribute, int *value) +{ + XMesaVisual v = (XMesaVisual) config; + (void) dpy; + (void) config; + + if (!dpy || !config || !value) + return -1; + + return get_config(v, attribute, value, GL_TRUE); +} + + +PUBLIC GLXFBConfig * +glXGetFBConfigs( Display *dpy, int screen, int *nelements ) +{ + XVisualInfo *visuals, visTemplate; + const long visMask = VisualScreenMask; + int i; + + /* Get list of all X visuals */ + visTemplate.screen = screen; + visuals = XGetVisualInfo(dpy, visMask, &visTemplate, nelements); + if (*nelements > 0) { + XMesaVisual *results = malloc(*nelements * sizeof(XMesaVisual)); + if (!results) { + *nelements = 0; + return NULL; + } + for (i = 0; i < *nelements; i++) { + results[i] = create_glx_visual(dpy, visuals + i); + if (!results[i]) { + *nelements = i; + break; + } + } + return (GLXFBConfig *) results; + } + return NULL; +} + + +PUBLIC GLXFBConfig * +glXChooseFBConfig(Display *dpy, int screen, + const int *attribList, int *nitems) +{ + XMesaVisual xmvis; + + /* register ourselves as an extension on this display */ + register_with_display(dpy); + + if (!attribList || !attribList[0]) { + /* return list of all configs (per GLX_SGIX_fbconfig spec) */ + return glXGetFBConfigs(dpy, screen, nitems); + } + + xmvis = choose_visual(dpy, screen, attribList, GL_TRUE); + if (xmvis) { + GLXFBConfig *config = malloc(sizeof(XMesaVisual)); + if (!config) { + *nitems = 0; + return NULL; + } + *nitems = 1; + config[0] = (GLXFBConfig) xmvis; + return (GLXFBConfig *) config; + } + else { + *nitems = 0; + return NULL; + } +} + + +PUBLIC XVisualInfo * +glXGetVisualFromFBConfig( Display *dpy, GLXFBConfig config ) +{ + if (dpy && config) { + XMesaVisual xmvis = (XMesaVisual) config; +#if 0 + return xmvis->vishandle; +#else + /* create a new vishandle - the cached one may be stale */ + xmvis->vishandle = malloc(sizeof(XVisualInfo)); + if (xmvis->vishandle) { + memcpy(xmvis->vishandle, xmvis->visinfo, sizeof(XVisualInfo)); + } + return xmvis->vishandle; +#endif + } + else { + return NULL; + } +} + + +PUBLIC GLXWindow +glXCreateWindow(Display *dpy, GLXFBConfig config, Window win, + const int *attribList) +{ + XMesaVisual xmvis = (XMesaVisual) config; + XMesaBuffer xmbuf; + if (!xmvis) + return 0; + + xmbuf = XMesaCreateWindowBuffer(xmvis, win); + if (!xmbuf) + return 0; + + (void) dpy; + (void) attribList; /* Ignored in GLX 1.3 */ + + return win; /* A hack for now */ +} + + +PUBLIC void +glXDestroyWindow( Display *dpy, GLXWindow window ) +{ + XMesaBuffer b = XMesaFindBuffer(dpy, (Drawable) window); + if (b) + XMesaDestroyBuffer(b); + /* don't destroy X window */ +} + + +/* XXX untested */ +PUBLIC GLXPixmap +glXCreatePixmap(Display *dpy, GLXFBConfig config, Pixmap pixmap, + const int *attribList) +{ + XMesaVisual v = (XMesaVisual) config; + XMesaBuffer b; + const int *attr; + int target = 0, format = 0, mipmap = 0; + int value; + + if (!dpy || !config || !pixmap) + return 0; + + for (attr = attribList; attr && *attr; attr++) { + switch (*attr) { + case GLX_TEXTURE_FORMAT_EXT: + attr++; + switch (*attr) { + case GLX_TEXTURE_FORMAT_NONE_EXT: + case GLX_TEXTURE_FORMAT_RGB_EXT: + case GLX_TEXTURE_FORMAT_RGBA_EXT: + format = *attr; + break; + default: + /* error */ + return 0; + } + break; + case GLX_TEXTURE_TARGET_EXT: + attr++; + switch (*attr) { + case GLX_TEXTURE_1D_EXT: + case GLX_TEXTURE_2D_EXT: + case GLX_TEXTURE_RECTANGLE_EXT: + target = *attr; + break; + default: + /* error */ + return 0; + } + break; + case GLX_MIPMAP_TEXTURE_EXT: + attr++; + if (*attr) + mipmap = 1; + break; + default: + /* error */ + return 0; + } + } + + if (format == GLX_TEXTURE_FORMAT_RGB_EXT) { + if (get_config(v, GLX_BIND_TO_TEXTURE_RGB_EXT, + &value, GL_TRUE) != Success + || !value) { + return 0; /* error! */ + } + } + else if (format == GLX_TEXTURE_FORMAT_RGBA_EXT) { + if (get_config(v, GLX_BIND_TO_TEXTURE_RGBA_EXT, + &value, GL_TRUE) != Success + || !value) { + return 0; /* error! */ + } + } + if (mipmap) { + if (get_config(v, GLX_BIND_TO_MIPMAP_TEXTURE_EXT, + &value, GL_TRUE) != Success + || !value) { + return 0; /* error! */ + } + } + if (target == GLX_TEXTURE_1D_EXT) { + if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT, + &value, GL_TRUE) != Success + || (value & GLX_TEXTURE_1D_BIT_EXT) == 0) { + return 0; /* error! */ + } + } + else if (target == GLX_TEXTURE_2D_EXT) { + if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT, + &value, GL_TRUE) != Success + || (value & GLX_TEXTURE_2D_BIT_EXT) == 0) { + return 0; /* error! */ + } + } + if (target == GLX_TEXTURE_RECTANGLE_EXT) { + if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT, + &value, GL_TRUE) != Success + || (value & GLX_TEXTURE_RECTANGLE_BIT_EXT) == 0) { + return 0; /* error! */ + } + } + + if (format || target || mipmap) { + /* texture from pixmap */ + b = XMesaCreatePixmapTextureBuffer(v, pixmap, 0, format, target, mipmap); + } + else { + b = XMesaCreatePixmapBuffer( v, pixmap, 0 ); + } + if (!b) { + return 0; + } + + return pixmap; +} + + +PUBLIC void +glXDestroyPixmap( Display *dpy, GLXPixmap pixmap ) +{ + XMesaBuffer b = XMesaFindBuffer(dpy, (Drawable)pixmap); + if (b) + XMesaDestroyBuffer(b); + /* don't destroy X pixmap */ +} + + +PUBLIC GLXPbuffer +glXCreatePbuffer(Display *dpy, GLXFBConfig config, const int *attribList) +{ + XMesaVisual xmvis = (XMesaVisual) config; + XMesaBuffer xmbuf; + const int *attrib; + int width = 0, height = 0; + GLboolean useLargest = GL_FALSE, preserveContents = GL_FALSE; + + (void) dpy; + + for (attrib = attribList; *attrib; attrib++) { + switch (*attrib) { + case GLX_PBUFFER_WIDTH: + attrib++; + width = *attrib; + break; + case GLX_PBUFFER_HEIGHT: + attrib++; + height = *attrib; + break; + case GLX_PRESERVED_CONTENTS: + attrib++; + preserveContents = *attrib; + break; + case GLX_LARGEST_PBUFFER: + attrib++; + useLargest = *attrib; + break; + default: + return 0; + } + } + + if (width == 0 || height == 0) + return 0; + + if (width > PBUFFER_MAX_SIZE || height > PBUFFER_MAX_SIZE) { + /* If allocation would have failed and GLX_LARGEST_PBUFFER is set, + * allocate the largest possible buffer. + */ + if (useLargest) { + width = PBUFFER_MAX_SIZE; + height = PBUFFER_MAX_SIZE; + } + } + + xmbuf = XMesaCreatePBuffer( xmvis, 0, width, height); + /* A GLXPbuffer handle must be an X Drawable because that's what + * glXMakeCurrent takes. + */ + if (xmbuf) { + xmbuf->largestPbuffer = useLargest; + xmbuf->preservedContents = preserveContents; + return (GLXPbuffer) xmbuf->ws.drawable; + } + else { + return 0; + } +} + + +PUBLIC void +glXDestroyPbuffer( Display *dpy, GLXPbuffer pbuf ) +{ + XMesaBuffer b = XMesaFindBuffer(dpy, pbuf); + if (b) { + XMesaDestroyBuffer(b); + } +} + + +PUBLIC void +glXQueryDrawable(Display *dpy, GLXDrawable draw, int attribute, + unsigned int *value) +{ + GLuint width, height; + XMesaBuffer xmbuf = XMesaFindBuffer(dpy, draw); + if (!xmbuf) { + generate_error(dpy, GLXBadDrawable, draw, X_GLXGetDrawableAttributes, False); + return; + } + + /* make sure buffer's dimensions are up to date */ + xmesa_get_window_size(dpy, xmbuf, &width, &height); + + switch (attribute) { + case GLX_WIDTH: + *value = width; + break; + case GLX_HEIGHT: + *value = height; + break; + case GLX_PRESERVED_CONTENTS: + *value = xmbuf->preservedContents; + break; + case GLX_LARGEST_PBUFFER: + *value = xmbuf->largestPbuffer; + break; + case GLX_FBCONFIG_ID: + *value = xmbuf->xm_visual->visinfo->visualid; + return; + case GLX_TEXTURE_FORMAT_EXT: + *value = xmbuf->TextureFormat; + break; + case GLX_TEXTURE_TARGET_EXT: + *value = xmbuf->TextureTarget; + break; + case GLX_MIPMAP_TEXTURE_EXT: + *value = xmbuf->TextureMipmap; + break; + + default: + generate_error(dpy, BadValue, 0, X_GLXCreateContextAttribsARB, true); + return; + } +} + + +PUBLIC GLXContext +glXCreateNewContext( Display *dpy, GLXFBConfig config, + int renderType, GLXContext shareCtx, Bool direct ) +{ + XMesaVisual xmvis = (XMesaVisual) config; + + if (!dpy || !config || + (renderType != GLX_RGBA_TYPE && renderType != GLX_COLOR_INDEX_TYPE)) + return 0; + + return create_context(dpy, xmvis, + shareCtx ? shareCtx->xmesaContext : NULL, + direct, + 1, 0, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, 0x0); +} + + +PUBLIC int +glXQueryContext( Display *dpy, GLXContext ctx, int attribute, int *value ) +{ + GLXContext glxCtx = ctx; + XMesaContext xmctx = glxCtx->xmesaContext; + + (void) dpy; + (void) ctx; + + switch (attribute) { + case GLX_FBCONFIG_ID: + *value = xmctx->xm_visual->visinfo->visualid; + break; + case GLX_RENDER_TYPE: + *value = GLX_RGBA_TYPE; + break; + case GLX_SCREEN: + *value = 0; + return Success; + default: + return GLX_BAD_ATTRIBUTE; + } + return 0; +} + + +PUBLIC void +glXSelectEvent( Display *dpy, GLXDrawable drawable, unsigned long mask ) +{ + XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable); + if (xmbuf) + xmbuf->selectedEvents = mask; +} + + +PUBLIC void +glXGetSelectedEvent(Display *dpy, GLXDrawable drawable, unsigned long *mask) +{ + XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable); + if (xmbuf) + *mask = xmbuf->selectedEvents; + else + *mask = 0; +} + + + +/*** GLX_SGI_swap_control ***/ + +PUBLIC int +glXSwapIntervalSGI(int interval) +{ + (void) interval; + return 0; +} + + + +/*** GLX_SGI_video_sync ***/ + +static unsigned int FrameCounter = 0; + +PUBLIC int +glXGetVideoSyncSGI(unsigned int *count) +{ + /* this is a bogus implementation */ + *count = FrameCounter++; + return 0; +} + +PUBLIC int +glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count) +{ + if (divisor <= 0 || remainder < 0) + return GLX_BAD_VALUE; + /* this is a bogus implementation */ + FrameCounter++; + while (FrameCounter % divisor != remainder) + FrameCounter++; + *count = FrameCounter; + return 0; +} + + + +/*** GLX_SGI_make_current_read ***/ + +PUBLIC Bool +glXMakeCurrentReadSGI(Display *dpy, GLXDrawable draw, GLXDrawable read, + GLXContext ctx) +{ + return glXMakeContextCurrent( dpy, draw, read, ctx ); +} + +/* not used +static GLXDrawable +glXGetCurrentReadDrawableSGI(void) +{ + return 0; +} +*/ + + +/*** GLX_SGIX_video_source ***/ +#if defined(_VL_H) + +PUBLIC GLXVideoSourceSGIX +glXCreateGLXVideoSourceSGIX(Display *dpy, int screen, VLServer server, + VLPath path, int nodeClass, VLNode drainNode) +{ + (void) dpy; + (void) screen; + (void) server; + (void) path; + (void) nodeClass; + (void) drainNode; + return 0; +} + +PUBLIC void +glXDestroyGLXVideoSourceSGIX(Display *dpy, GLXVideoSourceSGIX src) +{ + (void) dpy; + (void) src; +} + +#endif + + +/*** GLX_EXT_import_context ***/ + +PUBLIC void +glXFreeContextEXT(Display *dpy, GLXContext context) +{ + (void) dpy; + (void) context; +} + +PUBLIC GLXContextID +glXGetContextIDEXT(const GLXContext context) +{ + (void) context; + return 0; +} + +PUBLIC GLXContext +glXImportContextEXT(Display *dpy, GLXContextID contextID) +{ + (void) dpy; + (void) contextID; + return 0; +} + +PUBLIC int +glXQueryContextInfoEXT(Display *dpy, GLXContext context, int attribute, + int *value) +{ + (void) dpy; + (void) context; + (void) attribute; + (void) value; + return 0; +} + + + +/*** GLX_SGIX_fbconfig ***/ + +PUBLIC int +glXGetFBConfigAttribSGIX(Display *dpy, GLXFBConfigSGIX config, + int attribute, int *value) +{ + return glXGetFBConfigAttrib(dpy, config, attribute, value); +} + +PUBLIC GLXFBConfigSGIX * +glXChooseFBConfigSGIX(Display *dpy, int screen, int *attrib_list, + int *nelements) +{ + return (GLXFBConfig *) glXChooseFBConfig(dpy, screen, + attrib_list, nelements); +} + + +PUBLIC GLXPixmap +glXCreateGLXPixmapWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, + Pixmap pixmap) +{ + XMesaVisual xmvis = (XMesaVisual) config; + XMesaBuffer xmbuf = XMesaCreatePixmapBuffer(xmvis, pixmap, 0); + return xmbuf->ws.drawable; /* need to return an X ID */ +} + + +PUBLIC GLXContext +glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, + int renderType, GLXContext shareCtx, + Bool direct) +{ + XMesaVisual xmvis = (XMesaVisual) config; + + if (!dpy || !config || + (renderType != GLX_RGBA_TYPE && renderType != GLX_COLOR_INDEX_TYPE)) + return 0; + + return create_context(dpy, xmvis, + shareCtx ? shareCtx->xmesaContext : NULL, + direct, + 1, 0, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, 0x0); +} + + +PUBLIC XVisualInfo * +glXGetVisualFromFBConfigSGIX(Display *dpy, GLXFBConfigSGIX config) +{ + return glXGetVisualFromFBConfig(dpy, config); +} + + +PUBLIC GLXFBConfigSGIX +glXGetFBConfigFromVisualSGIX(Display *dpy, XVisualInfo *vis) +{ + XMesaVisual xmvis = find_glx_visual(dpy, vis); + if (!xmvis) { + /* This visual wasn't found with glXChooseVisual() */ + xmvis = create_glx_visual(dpy, vis); + } + + return (GLXFBConfigSGIX) xmvis; +} + + + +/*** GLX_SGIX_pbuffer ***/ + +PUBLIC GLXPbufferSGIX +glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfigSGIX config, + unsigned int width, unsigned int height, + int *attribList) +{ + XMesaVisual xmvis = (XMesaVisual) config; + XMesaBuffer xmbuf; + const int *attrib; + GLboolean useLargest = GL_FALSE, preserveContents = GL_FALSE; + + (void) dpy; + + for (attrib = attribList; attrib && *attrib; attrib++) { + switch (*attrib) { + case GLX_PRESERVED_CONTENTS_SGIX: + attrib++; + preserveContents = *attrib; /* ignored */ + break; + case GLX_LARGEST_PBUFFER_SGIX: + attrib++; + useLargest = *attrib; /* ignored */ + break; + default: + return 0; + } + } + + /* not used at this time */ + (void) useLargest; + (void) preserveContents; + + xmbuf = XMesaCreatePBuffer( xmvis, 0, width, height); + /* A GLXPbuffer handle must be an X Drawable because that's what + * glXMakeCurrent takes. + */ + return (GLXPbuffer) xmbuf->ws.drawable; +} + + +PUBLIC void +glXDestroyGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf) +{ + XMesaBuffer xmbuf = XMesaFindBuffer(dpy, pbuf); + if (xmbuf) { + XMesaDestroyBuffer(xmbuf); + } +} + + +PUBLIC void +glXQueryGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf, int attribute, + unsigned int *value) +{ + const XMesaBuffer xmbuf = XMesaFindBuffer(dpy, pbuf); + + if (!xmbuf) { + /* Generate GLXBadPbufferSGIX for bad pbuffer */ + return; + } + + switch (attribute) { + case GLX_PRESERVED_CONTENTS_SGIX: + *value = True; + break; + case GLX_LARGEST_PBUFFER_SGIX: + *value = xmesa_buffer_width(xmbuf) * xmesa_buffer_height(xmbuf); + break; + case GLX_WIDTH_SGIX: + *value = xmesa_buffer_width(xmbuf); + break; + case GLX_HEIGHT_SGIX: + *value = xmesa_buffer_height(xmbuf); + break; + case GLX_EVENT_MASK_SGIX: + *value = 0; /* XXX might be wrong */ + break; + default: + *value = 0; + } +} + + +PUBLIC void +glXSelectEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long mask) +{ + XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable); + if (xmbuf) { + /* Note: we'll never generate clobber events */ + xmbuf->selectedEvents = mask; + } +} + + +PUBLIC void +glXGetSelectedEventSGIX(Display *dpy, GLXDrawable drawable, + unsigned long *mask) +{ + XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable); + if (xmbuf) { + *mask = xmbuf->selectedEvents; + } + else { + *mask = 0; + } +} + + + +/*** GLX_SGI_cushion ***/ + +PUBLIC void +glXCushionSGI(Display *dpy, Window win, float cushion) +{ + (void) dpy; + (void) win; + (void) cushion; +} + + + +/*** GLX_SGIX_video_resize ***/ + +PUBLIC int +glXBindChannelToWindowSGIX(Display *dpy, int screen, int channel, + Window window) +{ + (void) dpy; + (void) screen; + (void) channel; + (void) window; + return 0; +} + +PUBLIC int +glXChannelRectSGIX(Display *dpy, int screen, int channel, + int x, int y, int w, int h) +{ + (void) dpy; + (void) screen; + (void) channel; + (void) x; + (void) y; + (void) w; + (void) h; + return 0; +} + +PUBLIC int +glXQueryChannelRectSGIX(Display *dpy, int screen, int channel, + int *x, int *y, int *w, int *h) +{ + (void) dpy; + (void) screen; + (void) channel; + (void) x; + (void) y; + (void) w; + (void) h; + return 0; +} + +PUBLIC int +glXQueryChannelDeltasSGIX(Display *dpy, int screen, int channel, + int *dx, int *dy, int *dw, int *dh) +{ + (void) dpy; + (void) screen; + (void) channel; + (void) dx; + (void) dy; + (void) dw; + (void) dh; + return 0; +} + +PUBLIC int +glXChannelRectSyncSGIX(Display *dpy, int screen, int channel, GLenum synctype) +{ + (void) dpy; + (void) screen; + (void) channel; + (void) synctype; + return 0; +} + + + +/*** GLX_SGIX_dmbuffer **/ + +#if defined(_DM_BUFFER_H_) +PUBLIC Bool +glXAssociateDMPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuffer, + DMparams *params, DMbuffer dmbuffer) +{ + (void) dpy; + (void) pbuffer; + (void) params; + (void) dmbuffer; + return False; +} +#endif + + +/*** GLX_SUN_get_transparent_index ***/ + +PUBLIC Status +glXGetTransparentIndexSUN(Display *dpy, Window overlay, Window underlay, + unsigned long *pTransparent) +{ + (void) dpy; + (void) overlay; + (void) underlay; + (void) pTransparent; + return 0; +} + + + +/*** GLX_MESA_release_buffers ***/ + +/* + * Release the depth, stencil, accum buffers attached to a GLXDrawable + * (a window or pixmap) prior to destroying the GLXDrawable. + */ +PUBLIC Bool +glXReleaseBuffersMESA( Display *dpy, GLXDrawable d ) +{ + XMesaBuffer b = XMesaFindBuffer(dpy, d); + if (b) { + XMesaDestroyBuffer(b); + return True; + } + return False; +} + +/*** GLX_EXT_texture_from_pixmap ***/ + +PUBLIC void +glXBindTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer, + const int *attrib_list) +{ + XMesaBuffer b = XMesaFindBuffer(dpy, drawable); + if (b) + XMesaBindTexImage(dpy, b, buffer, attrib_list); +} + +PUBLIC void +glXReleaseTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer) +{ + XMesaBuffer b = XMesaFindBuffer(dpy, drawable); + if (b) + XMesaReleaseTexImage(dpy, b, buffer); +} + + + +/*** GLX_ARB_create_context ***/ + + +GLXContext +glXCreateContextAttribsARB(Display *dpy, GLXFBConfig config, + GLXContext shareCtx, Bool direct, + const int *attrib_list) +{ + XMesaVisual xmvis = (XMesaVisual) config; + int majorVersion = 1, minorVersion = 0; + int contextFlags = 0x0; + int profileMask = GLX_CONTEXT_CORE_PROFILE_BIT_ARB; + int renderType = GLX_RGBA_TYPE; + unsigned i; + Bool done = False; + const int contextFlagsAll = (GLX_CONTEXT_DEBUG_BIT_ARB | + GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB); + GLXContext ctx; + + /* parse attrib_list */ + for (i = 0; !done && attrib_list && attrib_list[i]; i++) { + switch (attrib_list[i]) { + case GLX_CONTEXT_MAJOR_VERSION_ARB: + majorVersion = attrib_list[++i]; + break; + case GLX_CONTEXT_MINOR_VERSION_ARB: + minorVersion = attrib_list[++i]; + break; + case GLX_CONTEXT_FLAGS_ARB: + contextFlags = attrib_list[++i]; + break; + case GLX_CONTEXT_PROFILE_MASK_ARB: + profileMask = attrib_list[++i]; + break; + case GLX_RENDER_TYPE: + renderType = attrib_list[++i]; + break; + case 0: + /* end of list */ + done = True; + break; + default: + /* bad attribute */ + generate_error(dpy, BadValue, 0, X_GLXCreateContextAttribsARB, True); + return NULL; + } + } + + /* check contextFlags */ + if (contextFlags & ~contextFlagsAll) { + generate_error(dpy, BadValue, 0, X_GLXCreateContextAttribsARB, True); + return NULL; + } + + /* check profileMask */ + if (profileMask != GLX_CONTEXT_CORE_PROFILE_BIT_ARB && + profileMask != GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB && + profileMask != GLX_CONTEXT_ES_PROFILE_BIT_EXT) { + generate_error(dpy, GLXBadProfileARB, 0, X_GLXCreateContextAttribsARB, False); + return NULL; + } + + /* check renderType */ + if (renderType != GLX_RGBA_TYPE && + renderType != GLX_COLOR_INDEX_TYPE) { + generate_error(dpy, BadValue, 0, X_GLXCreateContextAttribsARB, True); + return NULL; + } + + /* check version */ + if (majorVersion <= 0 || + minorVersion < 0 || + (profileMask != GLX_CONTEXT_ES_PROFILE_BIT_EXT && + ((majorVersion == 1 && minorVersion > 5) || + (majorVersion == 2 && minorVersion > 1) || + (majorVersion == 3 && minorVersion > 3) || + (majorVersion == 4 && minorVersion > 5) || + majorVersion > 4))) { + generate_error(dpy, BadMatch, 0, X_GLXCreateContextAttribsARB, True); + return NULL; + } + if (profileMask == GLX_CONTEXT_ES_PROFILE_BIT_EXT && + ((majorVersion == 1 && minorVersion > 1) || + (majorVersion == 2 && minorVersion > 0) || + (majorVersion == 3 && minorVersion > 1) || + majorVersion > 3)) { + /* GLX_EXT_create_context_es2_profile says nothing to justifying a + * different error code for invalid ES versions, but this is what NVIDIA + * does and piglit expects. + */ + generate_error(dpy, GLXBadProfileARB, 0, X_GLXCreateContextAttribsARB, False); + return NULL; + } + + if ((contextFlags & GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB) && + majorVersion < 3) { + generate_error(dpy, BadMatch, 0, X_GLXCreateContextAttribsARB, True); + return NULL; + } + + if (renderType == GLX_COLOR_INDEX_TYPE && majorVersion >= 3) { + generate_error(dpy, BadMatch, 0, X_GLXCreateContextAttribsARB, True); + return NULL; + } + + ctx = create_context(dpy, xmvis, + shareCtx ? shareCtx->xmesaContext : NULL, + direct, + majorVersion, minorVersion, + profileMask, contextFlags); + if (!ctx) { + generate_error(dpy, GLXBadFBConfig, 0, X_GLXCreateContextAttribsARB, False); + } + + return ctx; +} diff --git a/src/gallium/frontends/glx/xlib/glx_getproc.c b/src/gallium/frontends/glx/xlib/glx_getproc.c new file mode 100644 index 00000000000..6b94f2c1960 --- /dev/null +++ b/src/gallium/frontends/glx/xlib/glx_getproc.c @@ -0,0 +1,212 @@ +/* + * Mesa 3-D graphics library + * + * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. + * Copyright (C) 2009 VMware, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + + +/** + * glXGetProcAddress() + */ + + +#define GLX_GLXEXT_PROTOTYPES + +#include +#include "pipe/p_compiler.h" +#include "GL/glx.h" +#include "glapi/glapi.h" + + +struct name_address_pair { + const char *Name; + __GLXextFuncPtr Address; +}; + + +static const struct name_address_pair GLX_functions[] = { + /*** GLX_VERSION_1_0 ***/ + { "glXChooseVisual", (__GLXextFuncPtr) glXChooseVisual }, + { "glXCopyContext", (__GLXextFuncPtr) glXCopyContext }, + { "glXCreateContext", (__GLXextFuncPtr) glXCreateContext }, + { "glXCreateGLXPixmap", (__GLXextFuncPtr) glXCreateGLXPixmap }, + { "glXDestroyContext", (__GLXextFuncPtr) glXDestroyContext }, + { "glXDestroyGLXPixmap", (__GLXextFuncPtr) glXDestroyGLXPixmap }, + { "glXGetConfig", (__GLXextFuncPtr) glXGetConfig }, + { "glXGetCurrentContext", (__GLXextFuncPtr) glXGetCurrentContext }, + { "glXGetCurrentDrawable", (__GLXextFuncPtr) glXGetCurrentDrawable }, + { "glXIsDirect", (__GLXextFuncPtr) glXIsDirect }, + { "glXMakeCurrent", (__GLXextFuncPtr) glXMakeCurrent }, + { "glXQueryExtension", (__GLXextFuncPtr) glXQueryExtension }, + { "glXQueryVersion", (__GLXextFuncPtr) glXQueryVersion }, + { "glXSwapBuffers", (__GLXextFuncPtr) glXSwapBuffers }, + { "glXUseXFont", (__GLXextFuncPtr) glXUseXFont }, + { "glXWaitGL", (__GLXextFuncPtr) glXWaitGL }, + { "glXWaitX", (__GLXextFuncPtr) glXWaitX }, + + /*** GLX_VERSION_1_1 ***/ + { "glXGetClientString", (__GLXextFuncPtr) glXGetClientString }, + { "glXQueryExtensionsString", (__GLXextFuncPtr) glXQueryExtensionsString }, + { "glXQueryServerString", (__GLXextFuncPtr) glXQueryServerString }, + + /*** GLX_VERSION_1_2 ***/ + { "glXGetCurrentDisplay", (__GLXextFuncPtr) glXGetCurrentDisplay }, + + /*** GLX_VERSION_1_3 ***/ + { "glXChooseFBConfig", (__GLXextFuncPtr) glXChooseFBConfig }, + { "glXCreateNewContext", (__GLXextFuncPtr) glXCreateNewContext }, + { "glXCreatePbuffer", (__GLXextFuncPtr) glXCreatePbuffer }, + { "glXCreatePixmap", (__GLXextFuncPtr) glXCreatePixmap }, + { "glXCreateWindow", (__GLXextFuncPtr) glXCreateWindow }, + { "glXDestroyPbuffer", (__GLXextFuncPtr) glXDestroyPbuffer }, + { "glXDestroyPixmap", (__GLXextFuncPtr) glXDestroyPixmap }, + { "glXDestroyWindow", (__GLXextFuncPtr) glXDestroyWindow }, + { "glXGetCurrentReadDrawable", (__GLXextFuncPtr) glXGetCurrentReadDrawable }, + { "glXGetFBConfigAttrib", (__GLXextFuncPtr) glXGetFBConfigAttrib }, + { "glXGetFBConfigs", (__GLXextFuncPtr) glXGetFBConfigs }, + { "glXGetSelectedEvent", (__GLXextFuncPtr) glXGetSelectedEvent }, + { "glXGetVisualFromFBConfig", (__GLXextFuncPtr) glXGetVisualFromFBConfig }, + { "glXMakeContextCurrent", (__GLXextFuncPtr) glXMakeContextCurrent }, + { "glXQueryContext", (__GLXextFuncPtr) glXQueryContext }, + { "glXQueryDrawable", (__GLXextFuncPtr) glXQueryDrawable }, + { "glXSelectEvent", (__GLXextFuncPtr) glXSelectEvent }, + + /*** GLX_VERSION_1_4 ***/ + { "glXGetProcAddress", (__GLXextFuncPtr) glXGetProcAddress }, + + /*** GLX_SGI_swap_control ***/ + { "glXSwapIntervalSGI", (__GLXextFuncPtr) glXSwapIntervalSGI }, + + /*** GLX_SGI_video_sync ***/ + { "glXGetVideoSyncSGI", (__GLXextFuncPtr) glXGetVideoSyncSGI }, + { "glXWaitVideoSyncSGI", (__GLXextFuncPtr) glXWaitVideoSyncSGI }, + + /*** GLX_SGI_make_current_read ***/ + { "glXMakeCurrentReadSGI", (__GLXextFuncPtr) glXMakeCurrentReadSGI }, + { "glXGetCurrentReadDrawableSGI", (__GLXextFuncPtr) glXGetCurrentReadDrawableSGI }, + + /*** GLX_SGIX_video_source ***/ +#if defined(_VL_H) + { "glXCreateGLXVideoSourceSGIX", (__GLXextFuncPtr) glXCreateGLXVideoSourceSGIX }, + { "glXDestroyGLXVideoSourceSGIX", (__GLXextFuncPtr) glXDestroyGLXVideoSourceSGIX }, +#endif + + /*** GLX_EXT_import_context ***/ + { "glXFreeContextEXT", (__GLXextFuncPtr) glXFreeContextEXT }, + { "glXGetContextIDEXT", (__GLXextFuncPtr) glXGetContextIDEXT }, + { "glXGetCurrentDisplayEXT", (__GLXextFuncPtr) glXGetCurrentDisplayEXT }, + { "glXImportContextEXT", (__GLXextFuncPtr) glXImportContextEXT }, + { "glXQueryContextInfoEXT", (__GLXextFuncPtr) glXQueryContextInfoEXT }, + + /*** GLX_SGIX_fbconfig ***/ + { "glXGetFBConfigAttribSGIX", (__GLXextFuncPtr) glXGetFBConfigAttribSGIX }, + { "glXChooseFBConfigSGIX", (__GLXextFuncPtr) glXChooseFBConfigSGIX }, + { "glXCreateGLXPixmapWithConfigSGIX", (__GLXextFuncPtr) glXCreateGLXPixmapWithConfigSGIX }, + { "glXCreateContextWithConfigSGIX", (__GLXextFuncPtr) glXCreateContextWithConfigSGIX }, + { "glXGetVisualFromFBConfigSGIX", (__GLXextFuncPtr) glXGetVisualFromFBConfigSGIX }, + { "glXGetFBConfigFromVisualSGIX", (__GLXextFuncPtr) glXGetFBConfigFromVisualSGIX }, + + /*** GLX_SGIX_pbuffer ***/ + { "glXCreateGLXPbufferSGIX", (__GLXextFuncPtr) glXCreateGLXPbufferSGIX }, + { "glXDestroyGLXPbufferSGIX", (__GLXextFuncPtr) glXDestroyGLXPbufferSGIX }, + { "glXQueryGLXPbufferSGIX", (__GLXextFuncPtr) glXQueryGLXPbufferSGIX }, + { "glXSelectEventSGIX", (__GLXextFuncPtr) glXSelectEventSGIX }, + { "glXGetSelectedEventSGIX", (__GLXextFuncPtr) glXGetSelectedEventSGIX }, + + /*** GLX_SGI_cushion ***/ + { "glXCushionSGI", (__GLXextFuncPtr) glXCushionSGI }, + + /*** GLX_SGIX_video_resize ***/ + { "glXBindChannelToWindowSGIX", (__GLXextFuncPtr) glXBindChannelToWindowSGIX }, + { "glXChannelRectSGIX", (__GLXextFuncPtr) glXChannelRectSGIX }, + { "glXQueryChannelRectSGIX", (__GLXextFuncPtr) glXQueryChannelRectSGIX }, + { "glXQueryChannelDeltasSGIX", (__GLXextFuncPtr) glXQueryChannelDeltasSGIX }, + { "glXChannelRectSyncSGIX", (__GLXextFuncPtr) glXChannelRectSyncSGIX }, + + /*** GLX_SGIX_dmbuffer **/ +#if defined(_DM_BUFFER_H_) + { "glXAssociateDMPbufferSGIX", (__GLXextFuncPtr) glXAssociateDMPbufferSGIX }, +#endif + + /*** GLX_SUN_get_transparent_index ***/ + { "glXGetTransparentIndexSUN", (__GLXextFuncPtr) glXGetTransparentIndexSUN }, + + /*** GLX_MESA_copy_sub_buffer ***/ + { "glXCopySubBufferMESA", (__GLXextFuncPtr) glXCopySubBufferMESA }, + + /*** GLX_MESA_pixmap_colormap ***/ + { "glXCreateGLXPixmapMESA", (__GLXextFuncPtr) glXCreateGLXPixmapMESA }, + + /*** GLX_MESA_release_buffers ***/ + { "glXReleaseBuffersMESA", (__GLXextFuncPtr) glXReleaseBuffersMESA }, + + /*** GLX_ARB_get_proc_address ***/ + { "glXGetProcAddressARB", (__GLXextFuncPtr) glXGetProcAddressARB }, + + /*** GLX_ARB_create_context ***/ + { "glXCreateContextAttribsARB", (__GLXextFuncPtr) glXCreateContextAttribsARB }, + + /*** GLX_EXT_texture_from_pixmap ***/ + { "glXBindTexImageEXT", (__GLXextFuncPtr) glXBindTexImageEXT }, + { "glXReleaseTexImageEXT", (__GLXextFuncPtr) glXReleaseTexImageEXT }, + + { NULL, NULL } /* end of list */ +}; + + + +/** + * Return address of named glX function, or NULL if not found. + */ +static __GLXextFuncPtr +_glxapi_get_proc_address(const char *funcName) +{ + GLuint i; + for (i = 0; GLX_functions[i].Name; i++) { + if (strcmp(GLX_functions[i].Name, funcName) == 0) + return GLX_functions[i].Address; + } + return NULL; +} + + +PUBLIC __GLXextFuncPtr +glXGetProcAddressARB(const GLubyte *procName) +{ + __GLXextFuncPtr f; + + f = _glxapi_get_proc_address((const char *) procName); + if (f) { + return f; + } + + f = (__GLXextFuncPtr) _glapi_get_proc_address((const char *) procName); + return f; +} + + +/* GLX 1.4 */ +PUBLIC +void (*glXGetProcAddress(const GLubyte *procName))() +{ + return glXGetProcAddressARB(procName); +} diff --git a/src/gallium/frontends/glx/xlib/glx_usefont.c b/src/gallium/frontends/glx/xlib/glx_usefont.c new file mode 100644 index 00000000000..9d35054b44d --- /dev/null +++ b/src/gallium/frontends/glx/xlib/glx_usefont.c @@ -0,0 +1,373 @@ +/* + * Mesa 3-D graphics library + * + * Copyright (C) 1995 Thorsten.Ohl @ Physik.TH-Darmstadt.de + * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. + * Copyright (C) 2009 VMware, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + + +/** + * Fake implementation of glXUseXFont(). + */ + +#include +#include +#include +#include +#include "main/errors.h" + + +/* Some debugging info. */ + +#ifdef DEBUG +#include + +int debug_xfonts = 0; + +static void +dump_char_struct(XCharStruct * ch, char *prefix) +{ + printf("%slbearing = %d, rbearing = %d, width = %d\n", + prefix, ch->lbearing, ch->rbearing, ch->width); + printf("%sascent = %d, descent = %d, attributes = %u\n", + prefix, ch->ascent, ch->descent, (unsigned int) ch->attributes); +} + +static void +dump_font_struct(XFontStruct * font) +{ + printf("ascent = %d, descent = %d\n", font->ascent, font->descent); + printf("char_or_byte2 = (%u,%u)\n", + font->min_char_or_byte2, font->max_char_or_byte2); + printf("byte1 = (%u,%u)\n", font->min_byte1, font->max_byte1); + printf("all_chars_exist = %s\n", font->all_chars_exist ? "True" : "False"); + printf("default_char = %c (\\%03o)\n", + (char) (isprint(font->default_char) ? font->default_char : ' '), + font->default_char); + dump_char_struct(&font->min_bounds, "min> "); + dump_char_struct(&font->max_bounds, "max> "); +#if 0 + for (c = font->min_char_or_byte2; c <= font->max_char_or_byte2; c++) { + char prefix[8]; + sprintf(prefix, "%d> ", c); + dump_char_struct(&font->per_char[c], prefix); + } +#endif +} + +static void +dump_bitmap(unsigned int width, unsigned int height, GLubyte * bitmap) +{ + unsigned int x, y; + + printf(" "); + for (x = 0; x < 8 * width; x++) + printf("%o", 7 - (x % 8)); + putchar('\n'); + for (y = 0; y < height; y++) { + printf("%3o:", y); + for (x = 0; x < 8 * width; x++) + putchar((bitmap[width * (height - y - 1) + x / 8] & (1 << (7 - (x % + 8)))) + ? '*' : '.'); + printf(" "); + for (x = 0; x < width; x++) + printf("0x%02x, ", bitmap[width * (height - y - 1) + x]); + putchar('\n'); + } +} +#endif /* DEBUG */ + + +/* Implementation. */ + +/* Fill a BITMAP with a character C from thew current font + in the graphics context GC. WIDTH is the width in bytes + and HEIGHT is the height in bits. + + Note that the generated bitmaps must be used with + + glPixelStorei (GL_UNPACK_SWAP_BYTES, GL_FALSE); + glPixelStorei (GL_UNPACK_LSB_FIRST, GL_FALSE); + glPixelStorei (GL_UNPACK_ROW_LENGTH, 0); + glPixelStorei (GL_UNPACK_SKIP_ROWS, 0); + glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0); + glPixelStorei (GL_UNPACK_ALIGNMENT, 1); + + Possible optimizations: + + * use only one reusable pixmap with the maximum dimensions. + * draw the entire font into a single pixmap (careful with + proportional fonts!). +*/ + + +/* + * Generate OpenGL-compatible bitmap. + */ +static void +fill_bitmap(Display * dpy, Window win, GC gc, + unsigned int width, unsigned int height, + int x0, int y0, unsigned int c, GLubyte * bitmap) +{ + XImage *image; + unsigned int x, y; + Pixmap pixmap; + XChar2b char2b; + + pixmap = XCreatePixmap(dpy, win, 8 * width, height, 1); + XSetForeground(dpy, gc, 0); + XFillRectangle(dpy, pixmap, gc, 0, 0, 8 * width, height); + XSetForeground(dpy, gc, 1); + + char2b.byte1 = (c >> 8) & 0xff; + char2b.byte2 = (c & 0xff); + + XDrawString16(dpy, pixmap, gc, x0, y0, &char2b, 1); + + image = XGetImage(dpy, pixmap, 0, 0, 8 * width, height, 1, XYPixmap); + if (image) { + /* Fill the bitmap (X11 and OpenGL are upside down wrt each other). */ + for (y = 0; y < height; y++) + for (x = 0; x < 8 * width; x++) + if (XGetPixel(image, x, y)) + bitmap[width * (height - y - 1) + x / 8] |= + (1 << (7 - (x % 8))); + XDestroyImage(image); + } + + XFreePixmap(dpy, pixmap); +} + +/* + * determine if a given glyph is valid and return the + * corresponding XCharStruct. + */ +static XCharStruct * +isvalid(XFontStruct * fs, unsigned int which) +{ + unsigned int rows, pages; + unsigned int byte1 = 0, byte2 = 0; + int i, valid = 1; + + rows = fs->max_byte1 - fs->min_byte1 + 1; + pages = fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1; + + if (rows == 1) { + /* "linear" fonts */ + if ((fs->min_char_or_byte2 > which) || (fs->max_char_or_byte2 < which)) + valid = 0; + } + else { + /* "matrix" fonts */ + byte2 = which & 0xff; + byte1 = which >> 8; + if ((fs->min_char_or_byte2 > byte2) || + (fs->max_char_or_byte2 < byte2) || + (fs->min_byte1 > byte1) || (fs->max_byte1 < byte1)) + valid = 0; + } + + if (valid) { + if (fs->per_char) { + if (rows == 1) { + /* "linear" fonts */ + return (fs->per_char + (which - fs->min_char_or_byte2)); + } + else { + /* "matrix" fonts */ + i = ((byte1 - fs->min_byte1) * pages) + + (byte2 - fs->min_char_or_byte2); + return (fs->per_char + i); + } + } + else { + return (&fs->min_bounds); + } + } + return (NULL); +} + + +PUBLIC void +glXUseXFont(Font font, int first, int count, int listbase) +{ + Display *dpy; + Window win; + Pixmap pixmap; + GC gc; + XGCValues values; + unsigned long valuemask; + XFontStruct *fs; + GLint swapbytes, lsbfirst, rowlength; + GLint skiprows, skippixels, alignment; + unsigned int max_width, max_height, max_bm_width, max_bm_height; + GLubyte *bm; + int i; + + dpy = glXGetCurrentDisplay(); + if (!dpy) + return; /* I guess glXMakeCurrent wasn't called */ + i = DefaultScreen(dpy); + win = RootWindow(dpy, i); + + fs = XQueryFont(dpy, font); + if (!fs) { + _mesa_error(NULL, GL_INVALID_VALUE, + "Couldn't get font structure information"); + return; + } + + /* Allocate a bitmap that can fit all characters. */ + max_width = fs->max_bounds.rbearing - fs->min_bounds.lbearing; + max_height = fs->max_bounds.ascent + fs->max_bounds.descent; + max_bm_width = (max_width + 7) / 8; + max_bm_height = max_height; + + bm = malloc((max_bm_width * max_bm_height) * sizeof(GLubyte)); + if (!bm) { + XFreeFontInfo(NULL, fs, 1); + _mesa_error(NULL, GL_OUT_OF_MEMORY, + "Couldn't allocate bitmap in glXUseXFont()"); + return; + } + +#if 0 + /* get the page info */ + pages = fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1; + firstchar = (fs->min_byte1 << 8) + fs->min_char_or_byte2; + lastchar = (fs->max_byte1 << 8) + fs->max_char_or_byte2; + rows = fs->max_byte1 - fs->min_byte1 + 1; + unsigned int first_char, last_char, pages, rows; +#endif + + /* Save the current packing mode for bitmaps. */ + glGetIntegerv(GL_UNPACK_SWAP_BYTES, &swapbytes); + glGetIntegerv(GL_UNPACK_LSB_FIRST, &lsbfirst); + glGetIntegerv(GL_UNPACK_ROW_LENGTH, &rowlength); + glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skiprows); + glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skippixels); + glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment); + + /* Enforce a standard packing mode which is compatible with + fill_bitmap() from above. This is actually the default mode, + except for the (non)alignment. */ + glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); + glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + pixmap = XCreatePixmap(dpy, win, 10, 10, 1); + values.foreground = BlackPixel(dpy, DefaultScreen(dpy)); + values.background = WhitePixel(dpy, DefaultScreen(dpy)); + values.font = fs->fid; + valuemask = GCForeground | GCBackground | GCFont; + gc = XCreateGC(dpy, pixmap, valuemask, &values); + XFreePixmap(dpy, pixmap); + +#ifdef DEBUG + if (debug_xfonts) + dump_font_struct(fs); +#endif + + for (i = 0; i < count; i++) { + unsigned int width, height, bm_width, bm_height; + GLfloat x0, y0, dx, dy; + XCharStruct *ch; + int x, y; + unsigned int c = first + i; + int list = listbase + i; + int valid; + + /* check on index validity and get the bounds */ + ch = isvalid(fs, c); + if (!ch) { + ch = &fs->max_bounds; + valid = 0; + } + else { + valid = 1; + } + +#ifdef DEBUG + if (debug_xfonts) { + char s[7]; + sprintf(s, isprint(c) ? "%c> " : "\\%03o> ", c); + dump_char_struct(ch, s); + } +#endif + + /* glBitmap()' parameters: + straight from the glXUseXFont(3) manpage. */ + width = ch->rbearing - ch->lbearing; + height = ch->ascent + ch->descent; + x0 = -ch->lbearing; + y0 = ch->descent - 0; /* XXX used to subtract 1 here */ + /* but that caused a conformace failure */ + dx = ch->width; + dy = 0; + + /* X11's starting point. */ + x = -ch->lbearing; + y = ch->ascent; + + /* Round the width to a multiple of eight. We will use this also + for the pixmap for capturing the X11 font. This is slightly + inefficient, but it makes the OpenGL part real easy. */ + bm_width = (width + 7) / 8; + bm_height = height; + + glNewList(list, GL_COMPILE); + if (valid && (bm_width > 0) && (bm_height > 0)) { + + memset(bm, '\0', bm_width * bm_height); + fill_bitmap(dpy, win, gc, bm_width, bm_height, x, y, c, bm); + + glBitmap(width, height, x0, y0, dx, dy, bm); +#ifdef DEBUG + if (debug_xfonts) { + printf("width/height = %u/%u\n", width, height); + printf("bm_width/bm_height = %u/%u\n", bm_width, bm_height); + dump_bitmap(bm_width, bm_height, bm); + } +#endif + } + else { + glBitmap(0, 0, 0.0, 0.0, dx, dy, NULL); + } + glEndList(); + } + + free(bm); + XFreeFontInfo(NULL, fs, 1); + XFreeGC(dpy, gc); + + /* Restore saved packing modes. */ + glPixelStorei(GL_UNPACK_SWAP_BYTES, swapbytes); + glPixelStorei(GL_UNPACK_LSB_FIRST, lsbfirst); + glPixelStorei(GL_UNPACK_ROW_LENGTH, rowlength); + glPixelStorei(GL_UNPACK_SKIP_ROWS, skiprows); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, skippixels); + glPixelStorei(GL_UNPACK_ALIGNMENT, alignment); +} diff --git a/src/gallium/frontends/glx/xlib/meson.build b/src/gallium/frontends/glx/xlib/meson.build new file mode 100644 index 00000000000..7b1fdb34ffe --- /dev/null +++ b/src/gallium/frontends/glx/xlib/meson.build @@ -0,0 +1,27 @@ +# Copyright © 2017 Intel Corporation + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +libxlib = static_library( + 'xlib', + files('glx_api.c', 'glx_getproc.c', 'glx_usefont.c', 'xm_api.c', 'xm_st.c'), + c_args : c_vis_args, + include_directories : [inc_include, inc_src, inc_gallium, inc_gallium_aux, inc_mapi, inc_mesa], + dependencies : [dep_x11, dep_xext, dep_xcb, dep_glproto], +) diff --git a/src/gallium/frontends/glx/xlib/xm_api.c b/src/gallium/frontends/glx/xlib/xm_api.c new file mode 100644 index 00000000000..e0e0b2d992c --- /dev/null +++ b/src/gallium/frontends/glx/xlib/xm_api.c @@ -0,0 +1,1561 @@ +/* + * Mesa 3-D graphics library + * + * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file xm_api.c + * + * All the XMesa* API functions. + * + * + * NOTES: + * + * The window coordinate system origin (0,0) is in the lower-left corner + * of the window. X11's window coordinate origin is in the upper-left + * corner of the window. Therefore, most drawing functions in this + * file have to flip Y coordinates. + * + * + * Byte swapping: If the Mesa host and the X display use a different + * byte order then there's some trickiness to be aware of when using + * XImages. The byte ordering used for the XImage is that of the X + * display, not the Mesa host. + * The color-to-pixel encoding for True/DirectColor must be done + * according to the display's visual red_mask, green_mask, and blue_mask. + * If XPutPixel is used to put a pixel into an XImage then XPutPixel will + * do byte swapping if needed. If one wants to directly "poke" the pixel + * into the XImage's buffer then the pixel must be byte swapped first. + * + */ + +#ifdef __CYGWIN__ +#undef WIN32 +#undef __WIN32__ +#endif + +#include +#include "xm_api.h" +#include "xm_st.h" + +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_screen.h" +#include "pipe/p_state.h" +#include "frontend/api.h" + +#include "util/u_atomic.h" +#include "util/u_inlines.h" +#include "util/u_math.h" +#include "util/u_memory.h" + +#include "hud/hud_context.h" + +#include "main/errors.h" + +#include "xm_public.h" +#include + + +/* Driver interface routines, set up by xlib backend on library + * _init(). These are global in the same way that function names are + * global. + */ +static struct xm_driver driver; +static struct st_api *stapi; + +/* Default strict invalidate to false. This means we will not call + * XGetGeometry after every swapbuffers, which allows swapbuffers to + * remain asynchronous. For apps running at 100fps with synchronous + * swapping, a 10% boost is typical. For gears, I see closer to 20% + * speedup. + * + * Note that the work of copying data on swapbuffers doesn't disappear + * - this change just allows the X server to execute the PutImage + * asynchronously without us effectively blocked until its completion. + * + * This speeds up even llvmpipe's threaded rasterization as the + * swapbuffers operation was a large part of the serial component of + * an llvmpipe frame. + * + * The downside of this is correctness - applications which don't call + * glViewport on window resizes will get incorrect rendering. A + * better solution would be to have per-frame but asynchronous + * invalidation. Xcb almost looks as if it could provide this, but + * the API doesn't seem to quite be there. + */ +boolean xmesa_strict_invalidate = FALSE; + +void xmesa_set_driver( const struct xm_driver *templ ) +{ + driver = *templ; + stapi = driver.create_st_api(); + + xmesa_strict_invalidate = + debug_get_bool_option("XMESA_STRICT_INVALIDATE", FALSE); +} + + +static int +xmesa_get_param(struct st_manager *smapi, + enum st_manager_param param) +{ + switch(param) { + case ST_MANAGER_BROKEN_INVALIDATE: + return !xmesa_strict_invalidate; + default: + return 0; + } +} + +/* linked list of XMesaDisplay hooks per display */ +typedef struct _XMesaExtDisplayInfo { + struct _XMesaExtDisplayInfo *next; + Display *display; + struct xmesa_display mesaDisplay; +} XMesaExtDisplayInfo; + +typedef struct _XMesaExtInfo { + XMesaExtDisplayInfo *head; + int ndisplays; +} XMesaExtInfo; + +static XMesaExtInfo MesaExtInfo; + +/* hook to delete XMesaDisplay on XDestroyDisplay */ +extern void +xmesa_close_display(Display *display) +{ + XMesaExtDisplayInfo *info, *prev; + + /* These assertions are not valid since screen creation can fail and result + * in an empty list + assert(MesaExtInfo.ndisplays > 0); + assert(MesaExtInfo.head); + */ + + _XLockMutex(_Xglobal_lock); + /* first find display */ + prev = NULL; + for (info = MesaExtInfo.head; info; info = info->next) { + if (info->display == display) { + prev = info; + break; + } + } + + if (info == NULL) { + /* no display found */ + _XUnlockMutex(_Xglobal_lock); + return; + } + + /* remove display entry from list */ + if (prev != MesaExtInfo.head) { + prev->next = info->next; + } else { + MesaExtInfo.head = info->next; + } + MesaExtInfo.ndisplays--; + + _XUnlockMutex(_Xglobal_lock); + + /* don't forget to clean up mesaDisplay */ + XMesaDisplay xmdpy = &info->mesaDisplay; + + /** + * XXX: Don't destroy the screens here, since there may still + * be some dangling screen pointers that are used after this point + * if (xmdpy->screen) { + * xmdpy->screen->destroy(xmdpy->screen); + * } + */ + + if (xmdpy->smapi->destroy) + xmdpy->smapi->destroy(xmdpy->smapi); + free(xmdpy->smapi); + + XFree((char *) info); +} + +static XMesaDisplay +xmesa_init_display( Display *display ) +{ + static mtx_t init_mutex = _MTX_INITIALIZER_NP; + XMesaDisplay xmdpy; + XMesaExtDisplayInfo *info; + + if (display == NULL) { + return NULL; + } + + mtx_lock(&init_mutex); + + /* Look for XMesaDisplay which corresponds to this display */ + info = MesaExtInfo.head; + while(info) { + if (info->display == display) { + /* Found it */ + mtx_unlock(&init_mutex); + return &info->mesaDisplay; + } + info = info->next; + } + + /* Not found. Create new XMesaDisplay */ + /* first allocate X-related resources and hook destroy callback */ + + /* allocate mesa display info */ + info = (XMesaExtDisplayInfo *) Xmalloc(sizeof(XMesaExtDisplayInfo)); + if (info == NULL) { + mtx_unlock(&init_mutex); + return NULL; + } + info->display = display; + + xmdpy = &info->mesaDisplay; /* to be filled out below */ + xmdpy->display = display; + xmdpy->pipe = NULL; + + xmdpy->smapi = CALLOC_STRUCT(st_manager); + if (!xmdpy->smapi) { + Xfree(info); + mtx_unlock(&init_mutex); + return NULL; + } + + xmdpy->screen = driver.create_pipe_screen(display); + if (!xmdpy->screen) { + free(xmdpy->smapi); + Xfree(info); + mtx_unlock(&init_mutex); + return NULL; + } + + /* At this point, both smapi and screen are known to be valid */ + xmdpy->smapi->screen = xmdpy->screen; + xmdpy->smapi->get_param = xmesa_get_param; + (void) mtx_init(&xmdpy->mutex, mtx_plain); + + /* chain to the list of displays */ + _XLockMutex(_Xglobal_lock); + info->next = MesaExtInfo.head; + MesaExtInfo.head = info; + MesaExtInfo.ndisplays++; + _XUnlockMutex(_Xglobal_lock); + + mtx_unlock(&init_mutex); + + return xmdpy; +} + + +/**********************************************************************/ +/***** X Utility Functions *****/ +/**********************************************************************/ + + +/** + * Return the host's byte order as LSBFirst or MSBFirst ala X. + */ +static int host_byte_order( void ) +{ + int i = 1; + char *cptr = (char *) &i; + return (*cptr==1) ? LSBFirst : MSBFirst; +} + + + + +/** + * Return the true number of bits per pixel for XImages. + * For example, if we request a 24-bit deep visual we may actually need/get + * 32bpp XImages. This function returns the appropriate bpp. + * Input: dpy - the X display + * visinfo - desribes the visual to be used for XImages + * Return: true number of bits per pixel for XImages + */ +static int +bits_per_pixel( XMesaVisual xmv ) +{ + Display *dpy = xmv->display; + XVisualInfo * visinfo = xmv->visinfo; + XImage *img; + int bitsPerPixel; + /* Create a temporary XImage */ + img = XCreateImage( dpy, visinfo->visual, visinfo->depth, + ZPixmap, 0, /*format, offset*/ + malloc(8), /*data*/ + 1, 1, /*width, height*/ + 32, /*bitmap_pad*/ + 0 /*bytes_per_line*/ + ); + assert(img); + /* grab the bits/pixel value */ + bitsPerPixel = img->bits_per_pixel; + /* free the XImage */ + free( img->data ); + img->data = NULL; + XDestroyImage( img ); + return bitsPerPixel; +} + + + +/* + * Determine if a given X window ID is valid (window exists). + * Do this by calling XGetWindowAttributes() for the window and + * checking if we catch an X error. + * Input: dpy - the display + * win - the window to check for existence + * Return: GL_TRUE - window exists + * GL_FALSE - window doesn't exist + */ +static GLboolean WindowExistsFlag; + +static int window_exists_err_handler( Display* dpy, XErrorEvent* xerr ) +{ + (void) dpy; + if (xerr->error_code == BadWindow) { + WindowExistsFlag = GL_FALSE; + } + return 0; +} + +static GLboolean window_exists( Display *dpy, Window win ) +{ + XWindowAttributes wa; + int (*old_handler)( Display*, XErrorEvent* ); + WindowExistsFlag = GL_TRUE; + old_handler = XSetErrorHandler(window_exists_err_handler); + XGetWindowAttributes( dpy, win, &wa ); /* dummy request */ + XSetErrorHandler(old_handler); + return WindowExistsFlag; +} + +static Status +get_drawable_size( Display *dpy, Drawable d, uint *width, uint *height ) +{ + Window root; + Status stat; + int xpos, ypos; + unsigned int w, h, bw, depth; + stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth); + *width = w; + *height = h; + return stat; +} + + +/** + * Return the size of the window (or pixmap) that corresponds to the + * given XMesaBuffer. + * \param width returns width in pixels + * \param height returns height in pixels + */ +void +xmesa_get_window_size(Display *dpy, XMesaBuffer b, + GLuint *width, GLuint *height) +{ + XMesaDisplay xmdpy = xmesa_init_display(dpy); + Status stat; + + mtx_lock(&xmdpy->mutex); + stat = get_drawable_size(dpy, b->ws.drawable, width, height); + mtx_unlock(&xmdpy->mutex); + + if (!stat) { + /* probably querying a window that's recently been destroyed */ + _mesa_warning(NULL, "XGetGeometry failed!\n"); + *width = *height = 1; + } +} + +#define GET_REDMASK(__v) __v->mesa_visual.redMask +#define GET_GREENMASK(__v) __v->mesa_visual.greenMask +#define GET_BLUEMASK(__v) __v->mesa_visual.blueMask + + +/** + * Choose the pixel format for the given visual. + * This will tell the gallium driver how to pack pixel data into + * drawing surfaces. + */ +static GLuint +choose_pixel_format(XMesaVisual v) +{ + boolean native_byte_order = (host_byte_order() == + ImageByteOrder(v->display)); + + if ( GET_REDMASK(v) == 0x0000ff + && GET_GREENMASK(v) == 0x00ff00 + && GET_BLUEMASK(v) == 0xff0000 + && v->BitsPerPixel == 32) { + if (native_byte_order) { + /* no byteswapping needed */ + return PIPE_FORMAT_RGBA8888_UNORM; + } + else { + return PIPE_FORMAT_ABGR8888_UNORM; + } + } + else if ( GET_REDMASK(v) == 0xff0000 + && GET_GREENMASK(v) == 0x00ff00 + && GET_BLUEMASK(v) == 0x0000ff + && v->BitsPerPixel == 32) { + if (native_byte_order) { + /* no byteswapping needed */ + return PIPE_FORMAT_BGRA8888_UNORM; + } + else { + return PIPE_FORMAT_ARGB8888_UNORM; + } + } + else if ( GET_REDMASK(v) == 0x0000ff00 + && GET_GREENMASK(v) == 0x00ff0000 + && GET_BLUEMASK(v) == 0xff000000 + && v->BitsPerPixel == 32) { + if (native_byte_order) { + /* no byteswapping needed */ + return PIPE_FORMAT_ARGB8888_UNORM; + } + else { + return PIPE_FORMAT_BGRA8888_UNORM; + } + } + else if ( GET_REDMASK(v) == 0xf800 + && GET_GREENMASK(v) == 0x07e0 + && GET_BLUEMASK(v) == 0x001f + && native_byte_order + && v->BitsPerPixel == 16) { + /* 5-6-5 RGB */ + return PIPE_FORMAT_B5G6R5_UNORM; + } + + return PIPE_FORMAT_NONE; +} + + +/** + * Choose a depth/stencil format that satisfies the given depth and + * stencil sizes. + */ +static enum pipe_format +choose_depth_stencil_format(XMesaDisplay xmdpy, int depth, int stencil, + int sample_count) +{ + const enum pipe_texture_target target = PIPE_TEXTURE_2D; + const unsigned tex_usage = PIPE_BIND_DEPTH_STENCIL; + enum pipe_format formats[8], fmt; + int count, i; + + count = 0; + + if (depth <= 16 && stencil == 0) { + formats[count++] = PIPE_FORMAT_Z16_UNORM; + } + if (depth <= 24 && stencil == 0) { + formats[count++] = PIPE_FORMAT_X8Z24_UNORM; + formats[count++] = PIPE_FORMAT_Z24X8_UNORM; + } + if (depth <= 24 && stencil <= 8) { + formats[count++] = PIPE_FORMAT_S8_UINT_Z24_UNORM; + formats[count++] = PIPE_FORMAT_Z24_UNORM_S8_UINT; + } + if (depth <= 32 && stencil == 0) { + formats[count++] = PIPE_FORMAT_Z32_UNORM; + } + + fmt = PIPE_FORMAT_NONE; + for (i = 0; i < count; i++) { + if (xmdpy->screen->is_format_supported(xmdpy->screen, formats[i], + target, sample_count, + sample_count, tex_usage)) { + fmt = formats[i]; + break; + } + } + + return fmt; +} + + + +/**********************************************************************/ +/***** Linked list of XMesaBuffers *****/ +/**********************************************************************/ + +static XMesaBuffer XMesaBufferList = NULL; + + +/** + * Allocate a new XMesaBuffer object which corresponds to the given drawable. + * Note that XMesaBuffer is derived from struct gl_framebuffer. + * The new XMesaBuffer will not have any size (Width=Height=0). + * + * \param d the corresponding X drawable (window or pixmap) + * \param type either WINDOW, PIXMAP or PBUFFER, describing d + * \param vis the buffer's visual + * \param cmap the window's colormap, if known. + * \return new XMesaBuffer or NULL if any problem + */ +static XMesaBuffer +create_xmesa_buffer(Drawable d, BufferType type, + XMesaVisual vis, Colormap cmap) +{ + XMesaDisplay xmdpy = xmesa_init_display(vis->display); + XMesaBuffer b; + + assert(type == WINDOW || type == PIXMAP || type == PBUFFER); + + if (!xmdpy) + return NULL; + + b = (XMesaBuffer) CALLOC_STRUCT(xmesa_buffer); + if (!b) + return NULL; + + b->ws.drawable = d; + b->ws.visual = vis->visinfo->visual; + b->ws.depth = vis->visinfo->depth; + + b->xm_visual = vis; + b->type = type; + b->cmap = cmap; + + get_drawable_size(vis->display, d, &b->width, &b->height); + + /* + * Create framebuffer, but we'll plug in our own renderbuffers below. + */ + b->stfb = xmesa_create_st_framebuffer(xmdpy, b); + + /* GLX_EXT_texture_from_pixmap */ + b->TextureTarget = 0; + b->TextureFormat = GLX_TEXTURE_FORMAT_NONE_EXT; + b->TextureMipmap = 0; + + /* insert buffer into linked list */ + b->Next = XMesaBufferList; + XMesaBufferList = b; + + return b; +} + + +/** + * Find an XMesaBuffer by matching X display and colormap but NOT matching + * the notThis buffer. + */ +XMesaBuffer +xmesa_find_buffer(Display *dpy, Colormap cmap, XMesaBuffer notThis) +{ + XMesaBuffer b; + for (b = XMesaBufferList; b; b = b->Next) { + if (b->xm_visual->display == dpy && + b->cmap == cmap && + b != notThis) { + return b; + } + } + return NULL; +} + + +/** + * Remove buffer from linked list, delete if no longer referenced. + */ +static void +xmesa_free_buffer(XMesaBuffer buffer) +{ + XMesaBuffer prev = NULL, b; + + for (b = XMesaBufferList; b; b = b->Next) { + if (b == buffer) { + /* unlink buffer from list */ + if (prev) + prev->Next = buffer->Next; + else + XMesaBufferList = buffer->Next; + + /* Since the X window for the XMesaBuffer is going away, we don't + * want to dereference this pointer in the future. + */ + b->ws.drawable = 0; + + /* Notify the st manager that the associated framebuffer interface + * object is no longer valid. + */ + stapi->destroy_drawable(stapi, buffer->stfb); + + /* XXX we should move the buffer to a delete-pending list and destroy + * the buffer until it is no longer current. + */ + xmesa_destroy_st_framebuffer(buffer->stfb); + + free(buffer); + + return; + } + /* continue search */ + prev = b; + } + /* buffer not found in XMesaBufferList */ + _mesa_problem(NULL,"xmesa_free_buffer() - buffer not found\n"); +} + + + +/**********************************************************************/ +/***** Misc Private Functions *****/ +/**********************************************************************/ + + +/** + * When a context is bound for the first time, we can finally finish + * initializing the context's visual and buffer information. + * \param v the XMesaVisual to initialize + * \param b the XMesaBuffer to initialize (may be NULL) + * \param window the window/pixmap we're rendering into + * \param cmap the colormap associated with the window/pixmap + * \return GL_TRUE=success, GL_FALSE=failure + */ +static GLboolean +initialize_visual_and_buffer(XMesaVisual v, XMesaBuffer b, + Drawable window, Colormap cmap) +{ + assert(!b || b->xm_visual == v); + + /* Save true bits/pixel */ + v->BitsPerPixel = bits_per_pixel(v); + assert(v->BitsPerPixel > 0); + + /* RGB WINDOW: + * We support RGB rendering into almost any kind of visual. + */ + const int xclass = v->visualType; + if (xclass != GLX_TRUE_COLOR && xclass != GLX_DIRECT_COLOR) { + _mesa_warning(NULL, + "XMesa: RGB mode rendering not supported in given visual.\n"); + return GL_FALSE; + } + + if (v->BitsPerPixel == 32) { + /* We use XImages for all front/back buffers. If an X Window or + * X Pixmap is 32bpp, there's no guarantee that the alpha channel + * will be preserved. For XImages we're in luck. + */ + v->mesa_visual.alphaBits = 8; + } + + /* + * If MESA_INFO env var is set print out some debugging info + * which can help Brian figure out what's going on when a user + * reports bugs. + */ + if (getenv("MESA_INFO")) { + printf("X/Mesa visual = %p\n", (void *) v); + printf("X/Mesa level = %d\n", v->mesa_visual.level); + printf("X/Mesa depth = %d\n", v->visinfo->depth); + printf("X/Mesa bits per pixel = %d\n", v->BitsPerPixel); + } + + return GL_TRUE; +} + + + +#define NUM_VISUAL_TYPES 6 + +/** + * Convert an X visual type to a GLX visual type. + * + * \param visualType X visual type (i.e., \c TrueColor, \c StaticGray, etc.) + * to be converted. + * \return If \c visualType is a valid X visual type, a GLX visual type will + * be returned. Otherwise \c GLX_NONE will be returned. + * + * \note + * This code was lifted directly from lib/GL/glx/glcontextmodes.c in the + * DRI CVS tree. + */ +static GLint +xmesa_convert_from_x_visual_type( int visualType ) +{ + static const int glx_visual_types[ NUM_VISUAL_TYPES ] = { + GLX_STATIC_GRAY, GLX_GRAY_SCALE, + GLX_STATIC_COLOR, GLX_PSEUDO_COLOR, + GLX_TRUE_COLOR, GLX_DIRECT_COLOR + }; + + return ( (unsigned) visualType < NUM_VISUAL_TYPES ) + ? glx_visual_types[ visualType ] : GLX_NONE; +} + + +/**********************************************************************/ +/***** Public Functions *****/ +/**********************************************************************/ + + +/* + * Create a new X/Mesa visual. + * Input: display - X11 display + * visinfo - an XVisualInfo pointer + * rgb_flag - GL_TRUE = RGB mode, + * GL_FALSE = color index mode + * alpha_flag - alpha buffer requested? + * db_flag - GL_TRUE = double-buffered, + * GL_FALSE = single buffered + * stereo_flag - stereo visual? + * ximage_flag - GL_TRUE = use an XImage for back buffer, + * GL_FALSE = use an off-screen pixmap for back buffer + * depth_size - requested bits/depth values, or zero + * stencil_size - requested bits/stencil values, or zero + * accum_red_size - requested bits/red accum values, or zero + * accum_green_size - requested bits/green accum values, or zero + * accum_blue_size - requested bits/blue accum values, or zero + * accum_alpha_size - requested bits/alpha accum values, or zero + * num_samples - number of samples/pixel if multisampling, or zero + * level - visual level, usually 0 + * visualCaveat - ala the GLX extension, usually GLX_NONE + * Return; a new XMesaVisual or 0 if error. + */ +PUBLIC +XMesaVisual XMesaCreateVisual( Display *display, + XVisualInfo * visinfo, + GLboolean rgb_flag, + GLboolean alpha_flag, + GLboolean db_flag, + GLboolean stereo_flag, + GLboolean ximage_flag, + GLint depth_size, + GLint stencil_size, + GLint accum_red_size, + GLint accum_green_size, + GLint accum_blue_size, + GLint accum_alpha_size, + GLint num_samples, + GLint level, + GLint visualCaveat ) +{ + XMesaDisplay xmdpy = xmesa_init_display(display); + XMesaVisual v; + GLint red_bits, green_bits, blue_bits, alpha_bits; + + if (!xmdpy) + return NULL; + + if (!rgb_flag) + return NULL; + + /* For debugging only */ + if (getenv("MESA_XSYNC")) { + /* This makes debugging X easier. + * In your debugger, set a breakpoint on _XError to stop when an + * X protocol error is generated. + */ + XSynchronize( display, 1 ); + } + + v = (XMesaVisual) CALLOC_STRUCT(xmesa_visual); + if (!v) { + return NULL; + } + + v->display = display; + + /* Save a copy of the XVisualInfo struct because the user may Xfree() + * the struct but we may need some of the information contained in it + * at a later time. + */ + v->visinfo = malloc(sizeof(*visinfo)); + if (!v->visinfo) { + free(v); + return NULL; + } + memcpy(v->visinfo, visinfo, sizeof(*visinfo)); + + v->ximage_flag = ximage_flag; + + v->mesa_visual.redMask = visinfo->red_mask; + v->mesa_visual.greenMask = visinfo->green_mask; + v->mesa_visual.blueMask = visinfo->blue_mask; + v->visualID = visinfo->visualid; + v->screen = visinfo->screen; + +#if !(defined(__cplusplus) || defined(c_plusplus)) + v->visualType = xmesa_convert_from_x_visual_type(visinfo->class); +#else + v->visualType = xmesa_convert_from_x_visual_type(visinfo->c_class); +#endif + + v->mesa_visual.visualRating = visualCaveat; + + if (alpha_flag) + v->mesa_visual.alphaBits = 8; + + (void) initialize_visual_and_buffer( v, NULL, 0, 0 ); + + { + const int xclass = v->visualType; + if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) { + red_bits = util_bitcount(GET_REDMASK(v)); + green_bits = util_bitcount(GET_GREENMASK(v)); + blue_bits = util_bitcount(GET_BLUEMASK(v)); + } + else { + /* this is an approximation */ + int depth; + depth = v->visinfo->depth; + red_bits = depth / 3; + depth -= red_bits; + green_bits = depth / 2; + depth -= green_bits; + blue_bits = depth; + alpha_bits = 0; + assert( red_bits + green_bits + blue_bits == v->visinfo->depth ); + } + alpha_bits = v->mesa_visual.alphaBits; + } + + /* initialize visual */ + { + struct gl_config *vis = &v->mesa_visual; + + vis->doubleBufferMode = db_flag; + vis->stereoMode = stereo_flag; + + vis->redBits = red_bits; + vis->greenBits = green_bits; + vis->blueBits = blue_bits; + vis->alphaBits = alpha_bits; + vis->rgbBits = red_bits + green_bits + blue_bits; + + vis->depthBits = depth_size; + vis->stencilBits = stencil_size; + + vis->accumRedBits = accum_red_size; + vis->accumGreenBits = accum_green_size; + vis->accumBlueBits = accum_blue_size; + vis->accumAlphaBits = accum_alpha_size; + + vis->numAuxBuffers = 0; + vis->level = 0; + vis->sampleBuffers = num_samples > 1; + vis->samples = num_samples; + } + + v->stvis.buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK; + if (db_flag) + v->stvis.buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK; + if (stereo_flag) { + v->stvis.buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK; + if (db_flag) + v->stvis.buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK; + } + + v->stvis.color_format = choose_pixel_format(v); + + /* Check format support at requested num_samples (for multisample) */ + if (!xmdpy->screen->is_format_supported(xmdpy->screen, + v->stvis.color_format, + PIPE_TEXTURE_2D, num_samples, + num_samples, + PIPE_BIND_RENDER_TARGET)) + v->stvis.color_format = PIPE_FORMAT_NONE; + + if (v->stvis.color_format == PIPE_FORMAT_NONE) { + free(v->visinfo); + free(v); + return NULL; + } + + v->stvis.depth_stencil_format = + choose_depth_stencil_format(xmdpy, depth_size, stencil_size, + num_samples); + + v->stvis.accum_format = (accum_red_size + + accum_green_size + accum_blue_size + accum_alpha_size) ? + PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE; + + v->stvis.samples = num_samples; + v->stvis.render_buffer = ST_ATTACHMENT_INVALID; + + /* XXX minor hack */ + v->mesa_visual.level = level; + return v; +} + + +PUBLIC +void XMesaDestroyVisual( XMesaVisual v ) +{ + free(v->visinfo); + free(v); +} + + +/** + * Return the informative name. + */ +const char * +xmesa_get_name(void) +{ + return stapi->name; +} + + +/** + * Do per-display initializations. + */ +int +xmesa_init( Display *display ) +{ + return xmesa_init_display(display) ? 0 : 1; +} + + +/** + * Create a new XMesaContext. + * \param v the XMesaVisual + * \param share_list another XMesaContext with which to share display + * lists or NULL if no sharing is wanted. + * \return an XMesaContext or NULL if error. + */ +PUBLIC +XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list, + GLuint major, GLuint minor, + GLuint profileMask, GLuint contextFlags) +{ + XMesaDisplay xmdpy = xmesa_init_display(v->display); + struct st_context_attribs attribs; + enum st_context_error ctx_err = 0; + XMesaContext c; + + if (!xmdpy) + goto no_xmesa_context; + + /* Note: the XMesaContext contains a Mesa struct gl_context struct (inheritance) */ + c = (XMesaContext) CALLOC_STRUCT(xmesa_context); + if (!c) + goto no_xmesa_context; + + c->xm_visual = v; + c->xm_buffer = NULL; /* set later by XMesaMakeCurrent */ + c->xm_read_buffer = NULL; + + memset(&attribs, 0, sizeof(attribs)); + attribs.visual = v->stvis; + attribs.major = major; + attribs.minor = minor; + if (contextFlags & GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB) + attribs.flags |= ST_CONTEXT_FLAG_FORWARD_COMPATIBLE; + if (contextFlags & GLX_CONTEXT_DEBUG_BIT_ARB) + attribs.flags |= ST_CONTEXT_FLAG_DEBUG; + if (contextFlags & GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB) + attribs.flags |= ST_CONTEXT_FLAG_ROBUST_ACCESS; + + switch (profileMask) { + case GLX_CONTEXT_CORE_PROFILE_BIT_ARB: + /* There are no profiles before OpenGL 3.2. The + * GLX_ARB_create_context_profile spec says: + * + * "If the requested OpenGL version is less than 3.2, + * GLX_CONTEXT_PROFILE_MASK_ARB is ignored and the functionality + * of the context is determined solely by the requested version." + */ + if (major > 3 || (major == 3 && minor >= 2)) { + attribs.profile = ST_PROFILE_OPENGL_CORE; + break; + } + /* fall-through */ + case GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB: + /* + * The spec also says: + * + * "If version 3.1 is requested, the context returned may implement + * any of the following versions: + * + * * Version 3.1. The GL_ARB_compatibility extension may or may not + * be implemented, as determined by the implementation. + * * The core profile of version 3.2 or greater." + * + * and because Mesa doesn't support GL_ARB_compatibility, the only chance to + * honour a 3.1 context is through core profile. + */ + if (major == 3 && minor == 1) { + attribs.profile = ST_PROFILE_OPENGL_CORE; + } else { + attribs.profile = ST_PROFILE_DEFAULT; + } + break; + case GLX_CONTEXT_ES_PROFILE_BIT_EXT: + if (major >= 2) { + attribs.profile = ST_PROFILE_OPENGL_ES2; + } else { + attribs.profile = ST_PROFILE_OPENGL_ES1; + } + break; + default: + assert(0); + goto no_st; + } + + c->st = stapi->create_context(stapi, xmdpy->smapi, &attribs, + &ctx_err, (share_list) ? share_list->st : NULL); + if (c->st == NULL) + goto no_st; + + c->st->st_manager_private = (void *) c; + + c->hud = hud_create(c->st->cso_context, NULL); + + return c; + +no_st: + free(c); +no_xmesa_context: + return NULL; +} + + + +PUBLIC +void XMesaDestroyContext( XMesaContext c ) +{ + if (c->hud) { + hud_destroy(c->hud, NULL); + } + + c->st->destroy(c->st); + + /* FIXME: We should destroy the screen here, but if we do so, surfaces may + * outlive it, causing segfaults + struct pipe_screen *screen = c->st->pipe->screen; + screen->destroy(screen); + */ + + free(c); +} + + + +/** + * Private function for creating an XMesaBuffer which corresponds to an + * X window or pixmap. + * \param v the window's XMesaVisual + * \param w the window we're wrapping + * \return new XMesaBuffer or NULL if error + */ +PUBLIC XMesaBuffer +XMesaCreateWindowBuffer(XMesaVisual v, Window w) +{ + XWindowAttributes attr; + XMesaBuffer b; + Colormap cmap; + int depth; + + assert(v); + assert(w); + + /* Check that window depth matches visual depth */ + XGetWindowAttributes( v->display, w, &attr ); + depth = attr.depth; + if (v->visinfo->depth != depth) { + _mesa_warning(NULL, "XMesaCreateWindowBuffer: depth mismatch between visual (%d) and window (%d)!\n", + v->visinfo->depth, depth); + return NULL; + } + + /* Find colormap */ + if (attr.colormap) { + cmap = attr.colormap; + } + else { + _mesa_warning(NULL, "Window %u has no colormap!\n", (unsigned int) w); + /* this is weird, a window w/out a colormap!? */ + /* OK, let's just allocate a new one and hope for the best */ + cmap = XCreateColormap(v->display, w, attr.visual, AllocNone); + } + + b = create_xmesa_buffer((Drawable) w, WINDOW, v, cmap); + if (!b) + return NULL; + + if (!initialize_visual_and_buffer( v, b, (Drawable) w, cmap )) { + xmesa_free_buffer(b); + return NULL; + } + + return b; +} + + + +/** + * Create a new XMesaBuffer from an X pixmap. + * + * \param v the XMesaVisual + * \param p the pixmap + * \param cmap the colormap, may be 0 if using a \c GLX_TRUE_COLOR or + * \c GLX_DIRECT_COLOR visual for the pixmap + * \returns new XMesaBuffer or NULL if error + */ +PUBLIC XMesaBuffer +XMesaCreatePixmapBuffer(XMesaVisual v, Pixmap p, Colormap cmap) +{ + XMesaBuffer b; + + assert(v); + + b = create_xmesa_buffer((Drawable) p, PIXMAP, v, cmap); + if (!b) + return NULL; + + if (!initialize_visual_and_buffer(v, b, (Drawable) p, cmap)) { + xmesa_free_buffer(b); + return NULL; + } + + return b; +} + + +/** + * For GLX_EXT_texture_from_pixmap + */ +XMesaBuffer +XMesaCreatePixmapTextureBuffer(XMesaVisual v, Pixmap p, + Colormap cmap, + int format, int target, int mipmap) +{ + GET_CURRENT_CONTEXT(ctx); + XMesaBuffer b; + + assert(v); + + b = create_xmesa_buffer((Drawable) p, PIXMAP, v, cmap); + if (!b) + return NULL; + + /* get pixmap size */ + xmesa_get_window_size(v->display, b, &b->width, &b->height); + + if (target == 0) { + /* examine dims */ + if (ctx->Extensions.ARB_texture_non_power_of_two) { + target = GLX_TEXTURE_2D_EXT; + } + else if ( util_bitcount(b->width) == 1 + && util_bitcount(b->height) == 1) { + /* power of two size */ + if (b->height == 1) { + target = GLX_TEXTURE_1D_EXT; + } + else { + target = GLX_TEXTURE_2D_EXT; + } + } + else if (ctx->Extensions.NV_texture_rectangle) { + target = GLX_TEXTURE_RECTANGLE_EXT; + } + else { + /* non power of two textures not supported */ + XMesaDestroyBuffer(b); + return 0; + } + } + + b->TextureTarget = target; + b->TextureFormat = format; + b->TextureMipmap = mipmap; + + if (!initialize_visual_and_buffer(v, b, (Drawable) p, cmap)) { + xmesa_free_buffer(b); + return NULL; + } + + return b; +} + + + +XMesaBuffer +XMesaCreatePBuffer(XMesaVisual v, Colormap cmap, + unsigned int width, unsigned int height) +{ + Window root; + Drawable drawable; /* X Pixmap Drawable */ + XMesaBuffer b; + + /* allocate pixmap for front buffer */ + root = RootWindow( v->display, v->visinfo->screen ); + drawable = XCreatePixmap(v->display, root, width, height, + v->visinfo->depth); + if (!drawable) + return NULL; + + b = create_xmesa_buffer(drawable, PBUFFER, v, cmap); + if (!b) + return NULL; + + if (!initialize_visual_and_buffer(v, b, drawable, cmap)) { + xmesa_free_buffer(b); + return NULL; + } + + return b; +} + + + +/* + * Deallocate an XMesaBuffer structure and all related info. + */ +PUBLIC void +XMesaDestroyBuffer(XMesaBuffer b) +{ + xmesa_free_buffer(b); +} + + +/** + * Notify the binding context to validate the buffer. + */ +void +xmesa_notify_invalid_buffer(XMesaBuffer b) +{ + p_atomic_inc(&b->stfb->stamp); +} + + +/** + * Query the current drawable size and notify the binding context. + */ +void +xmesa_check_buffer_size(XMesaBuffer b) +{ + GLuint old_width, old_height; + + if (!b) + return; + + if (b->type == PBUFFER) + return; + + old_width = b->width; + old_height = b->height; + + xmesa_get_window_size(b->xm_visual->display, b, &b->width, &b->height); + + if (b->width != old_width || b->height != old_height) + xmesa_notify_invalid_buffer(b); +} + + +/* + * Bind buffer b to context c and make c the current rendering context. + */ +PUBLIC +GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer, + XMesaBuffer readBuffer ) +{ + XMesaContext old_ctx = XMesaGetCurrentContext(); + + if (old_ctx && old_ctx != c) { + XMesaFlush(old_ctx); + old_ctx->xm_buffer = NULL; + old_ctx->xm_read_buffer = NULL; + } + + if (c) { + if (!drawBuffer != !readBuffer) { + return GL_FALSE; /* must specify zero or two buffers! */ + } + + if (c == old_ctx && + c->xm_buffer == drawBuffer && + c->xm_read_buffer == readBuffer) + return GL_TRUE; + + xmesa_check_buffer_size(drawBuffer); + if (readBuffer != drawBuffer) + xmesa_check_buffer_size(readBuffer); + + c->xm_buffer = drawBuffer; + c->xm_read_buffer = readBuffer; + + stapi->make_current(stapi, c->st, + drawBuffer ? drawBuffer->stfb : NULL, + readBuffer ? readBuffer->stfb : NULL); + + /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */ + if (drawBuffer) + drawBuffer->wasCurrent = GL_TRUE; + } + else { + /* Detach */ + stapi->make_current(stapi, NULL, NULL, NULL); + + } + return GL_TRUE; +} + + +/* + * Unbind the context c from its buffer. + */ +GLboolean XMesaUnbindContext( XMesaContext c ) +{ + /* A no-op for XFree86 integration purposes */ + return GL_TRUE; +} + + +XMesaContext XMesaGetCurrentContext( void ) +{ + struct st_context_iface *st = stapi->get_current(stapi); + return (XMesaContext) (st) ? st->st_manager_private : NULL; +} + + + +/** + * Swap front and back color buffers and have winsys display front buffer. + * If there's no front color buffer no swap actually occurs. + */ +PUBLIC +void XMesaSwapBuffers( XMesaBuffer b ) +{ + XMesaContext xmctx = XMesaGetCurrentContext(); + + /* Need to draw HUD before flushing */ + if (xmctx && xmctx->hud) { + struct pipe_resource *back = + xmesa_get_framebuffer_resource(b->stfb, ST_ATTACHMENT_BACK_LEFT); + hud_run(xmctx->hud, NULL, back); + } + + if (xmctx && xmctx->xm_buffer == b) { + xmctx->st->flush( xmctx->st, ST_FLUSH_FRONT, NULL, NULL, NULL); + } + + xmesa_swap_st_framebuffer(b->stfb); +} + + + +/* + * Copy sub-region of back buffer to front buffer + */ +void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height ) +{ + XMesaContext xmctx = XMesaGetCurrentContext(); + + xmctx->st->flush( xmctx->st, ST_FLUSH_FRONT, NULL, NULL, NULL); + + xmesa_copy_st_framebuffer(b->stfb, + ST_ATTACHMENT_BACK_LEFT, ST_ATTACHMENT_FRONT_LEFT, + x, b->height - y - height, width, height); +} + + + +void XMesaFlush( XMesaContext c ) +{ + if (c && c->xm_visual->display) { + XMesaDisplay xmdpy = xmesa_init_display(c->xm_visual->display); + struct pipe_fence_handle *fence = NULL; + + c->st->flush(c->st, ST_FLUSH_FRONT, &fence, NULL, NULL); + if (fence) { + xmdpy->screen->fence_finish(xmdpy->screen, NULL, fence, + PIPE_TIMEOUT_INFINITE); + xmdpy->screen->fence_reference(xmdpy->screen, &fence, NULL); + } + XFlush( c->xm_visual->display ); + } +} + + + + + +XMesaBuffer XMesaFindBuffer( Display *dpy, Drawable d ) +{ + XMesaBuffer b; + for (b = XMesaBufferList; b; b = b->Next) { + if (b->ws.drawable == d && b->xm_visual->display == dpy) { + return b; + } + } + return NULL; +} + + +/** + * Free/destroy all XMesaBuffers associated with given display. + */ +void xmesa_destroy_buffers_on_display(Display *dpy) +{ + XMesaBuffer b, next; + for (b = XMesaBufferList; b; b = next) { + next = b->Next; + if (b->xm_visual->display == dpy) { + xmesa_free_buffer(b); + /* delete head of list? */ + if (XMesaBufferList == b) { + XMesaBufferList = next; + } + } + } +} + + +/* + * Look for XMesaBuffers whose X window has been destroyed. + * Deallocate any such XMesaBuffers. + */ +void XMesaGarbageCollect( void ) +{ + XMesaBuffer b, next; + for (b=XMesaBufferList; b; b=next) { + next = b->Next; + if (b->xm_visual && + b->xm_visual->display && + b->ws.drawable && + b->type == WINDOW) { + XSync(b->xm_visual->display, False); + if (!window_exists( b->xm_visual->display, b->ws.drawable )) { + /* found a dead window, free the ancillary info */ + XMesaDestroyBuffer( b ); + } + } + } +} + + +static enum st_attachment_type xmesa_attachment_type(int glx_attachment) +{ + switch(glx_attachment) { + case GLX_FRONT_LEFT_EXT: + return ST_ATTACHMENT_FRONT_LEFT; + case GLX_FRONT_RIGHT_EXT: + return ST_ATTACHMENT_FRONT_RIGHT; + case GLX_BACK_LEFT_EXT: + return ST_ATTACHMENT_BACK_LEFT; + case GLX_BACK_RIGHT_EXT: + return ST_ATTACHMENT_BACK_RIGHT; + default: + assert(0); + return ST_ATTACHMENT_FRONT_LEFT; + } +} + + +PUBLIC void +XMesaBindTexImage(Display *dpy, XMesaBuffer drawable, int buffer, + const int *attrib_list) +{ + struct st_context_iface *st = stapi->get_current(stapi); + struct st_framebuffer_iface* stfbi = drawable->stfb; + struct pipe_resource *res; + int x, y, w, h; + enum st_attachment_type st_attachment = xmesa_attachment_type(buffer); + + x = 0; + y = 0; + w = drawable->width; + h = drawable->height; + + /* We need to validate our attachments before using them, + * in case the texture doesn't exist yet. */ + xmesa_st_framebuffer_validate_textures(stfbi, w, h, 1 << st_attachment); + res = xmesa_get_attachment(stfbi, st_attachment); + + if (res) { + struct pipe_context* pipe = xmesa_get_context(stfbi); + enum pipe_format internal_format = res->format; + struct pipe_transfer *tex_xfer; + char *map; + int line, byte_width; + XImage *img; + + internal_format = choose_pixel_format(drawable->xm_visual); + + map = pipe_transfer_map(pipe, res, + 0, 0, /* level, layer */ + PIPE_TRANSFER_WRITE, + x, y, + w, h, &tex_xfer); + if (!map) + return; + + /* Grab the XImage that we want to turn into a texture. */ + img = XGetImage(dpy, + drawable->ws.drawable, + x, y, + w, h, + AllPlanes, + ZPixmap); + + if (!img) { + pipe_transfer_unmap(pipe, tex_xfer); + return; + } + + /* The pipe transfer has a pitch rounded up to the nearest 64 pixels. */ + byte_width = w * ((img->bits_per_pixel + 7) / 8); + + for (line = 0; line < h; line++) + memcpy(&map[line * tex_xfer->stride], + &img->data[line * img->bytes_per_line], + byte_width); + + pipe_transfer_unmap(pipe, tex_xfer); + + st->teximage(st, + ST_TEXTURE_2D, + 0, /* level */ + internal_format, + res, + FALSE /* no mipmap */); + + } +} + + + +PUBLIC void +XMesaReleaseTexImage(Display *dpy, XMesaBuffer drawable, int buffer) +{ +} + + +void +XMesaCopyContext(XMesaContext src, XMesaContext dst, unsigned long mask) +{ + if (dst->st->copy) + dst->st->copy(dst->st, src->st, mask); +} diff --git a/src/gallium/frontends/glx/xlib/xm_api.h b/src/gallium/frontends/glx/xlib/xm_api.h new file mode 100644 index 00000000000..04eefda0b07 --- /dev/null +++ b/src/gallium/frontends/glx/xlib/xm_api.h @@ -0,0 +1,398 @@ +/* + * Mesa 3-D graphics library + * + * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + + + +/* Sample Usage: + +In addition to the usual X calls to select a visual, create a colormap +and create a window, you must do the following to use the X/Mesa interface: + +1. Call XMesaCreateVisual() to make an XMesaVisual from an XVisualInfo. + +2. Call XMesaCreateContext() to create an X/Mesa rendering context, given + the XMesaVisual. + +3. Call XMesaCreateWindowBuffer() to create an XMesaBuffer from an X window + and XMesaVisual. + +4. Call XMesaMakeCurrent() to bind the XMesaBuffer to an XMesaContext and + to make the context the current one. + +5. Make gl* calls to render your graphics. + +6. Use XMesaSwapBuffers() when double buffering to swap front/back buffers. + +7. Before the X window is destroyed, call XMesaDestroyBuffer(). + +8. Before exiting, call XMesaDestroyVisual and XMesaDestroyContext. + +*/ + + + + +#ifndef XM_API_H +#define XM_API_H + + +#include "main/mtypes.h" /* for gl_config */ +#include "frontend/api.h" +#include "os/os_thread.h" + +#include "frontend/xlibsw_api.h" + +# include +# include +# include + +struct hud_context; + +typedef struct xmesa_display *XMesaDisplay; +typedef struct xmesa_buffer *XMesaBuffer; +typedef struct xmesa_context *XMesaContext; +typedef struct xmesa_visual *XMesaVisual; + + +struct xmesa_display { + mtx_t mutex; + + Display *display; + struct pipe_screen *screen; + struct st_manager *smapi; + + struct pipe_context *pipe; +}; + + +/* + * Create a new X/Mesa visual. + * Input: display - X11 display + * visinfo - an XVisualInfo pointer + * rgb_flag - GL_TRUE = RGB mode, + * GL_FALSE = color index mode + * alpha_flag - alpha buffer requested? + * db_flag - GL_TRUE = double-buffered, + * GL_FALSE = single buffered + * stereo_flag - stereo visual? + * ximage_flag - GL_TRUE = use an XImage for back buffer, + * GL_FALSE = use an off-screen pixmap for back buffer + * depth_size - requested bits/depth values, or zero + * stencil_size - requested bits/stencil values, or zero + * accum_red_size - requested bits/red accum values, or zero + * accum_green_size - requested bits/green accum values, or zero + * accum_blue_size - requested bits/blue accum values, or zero + * accum_alpha_size - requested bits/alpha accum values, or zero + * num_samples - number of samples/pixel if multisampling, or zero + * level - visual level, usually 0 + * visualCaveat - ala the GLX extension, usually GLX_NONE_EXT + * Return; a new XMesaVisual or 0 if error. + */ +extern XMesaVisual XMesaCreateVisual( Display *display, + XVisualInfo * visinfo, + GLboolean rgb_flag, + GLboolean alpha_flag, + GLboolean db_flag, + GLboolean stereo_flag, + GLboolean ximage_flag, + GLint depth_size, + GLint stencil_size, + GLint accum_red_size, + GLint accum_green_size, + GLint accum_blue_size, + GLint accum_alpha_size, + GLint num_samples, + GLint level, + GLint visualCaveat ); + +/* + * Destroy an XMesaVisual, but not the associated XVisualInfo. + */ +extern void XMesaDestroyVisual( XMesaVisual v ); + + + +/* + * Create a new XMesaContext for rendering into an X11 window. + * + * Input: visual - an XMesaVisual + * share_list - another XMesaContext with which to share display + * lists or NULL if no sharing is wanted. + * Return: an XMesaContext or NULL if error. + */ +extern XMesaContext XMesaCreateContext( XMesaVisual v, + XMesaContext share_list, + GLuint major, GLuint minor, + GLuint profileMask, + GLuint contextFlags); + + +/* + * Destroy a rendering context as returned by XMesaCreateContext() + */ +extern void XMesaDestroyContext( XMesaContext c ); + + + +/* + * Create an XMesaBuffer from an X window. + */ +extern XMesaBuffer XMesaCreateWindowBuffer( XMesaVisual v, Window w ); + + +/* + * Create an XMesaBuffer from an X pixmap. + */ +extern XMesaBuffer XMesaCreatePixmapBuffer( XMesaVisual v, + Pixmap p, + Colormap cmap ); + + +/* + * Destroy an XMesaBuffer, but not the corresponding window or pixmap. + */ +extern void XMesaDestroyBuffer( XMesaBuffer b ); + + +/* + * Return the XMesaBuffer handle which corresponds to an X drawable, if any. + * + * New in Mesa 2.3. + */ +extern XMesaBuffer XMesaFindBuffer( Display *dpy, + Drawable d ); + + + +/* + * Bind two buffers (read and draw) to a context and make the + * context the current one. + * New in Mesa 3.3 + */ +extern GLboolean XMesaMakeCurrent2( XMesaContext c, + XMesaBuffer drawBuffer, + XMesaBuffer readBuffer ); + + +/* + * Unbind the current context from its buffer. + */ +extern GLboolean XMesaUnbindContext( XMesaContext c ); + + +/* + * Return a handle to the current context. + */ +extern XMesaContext XMesaGetCurrentContext( void ); + + +/* + * Swap the front and back buffers for the given buffer. No action is + * taken if the buffer is not double buffered. + */ +extern void XMesaSwapBuffers( XMesaBuffer b ); + + +/* + * Copy a sub-region of the back buffer to the front buffer. + * + * New in Mesa 2.6 + */ +extern void XMesaCopySubBuffer( XMesaBuffer b, + int x, + int y, + int width, + int height ); + + + + + +/* + * Flush/sync a context + */ +extern void XMesaFlush( XMesaContext c ); + + + +/* + * Scan for XMesaBuffers whose window/pixmap has been destroyed, then free + * any memory used by that buffer. + * + * New in Mesa 2.3. + */ +extern void XMesaGarbageCollect( void ); + + + +/* + * Create a pbuffer. + * New in Mesa 4.1 + */ +extern XMesaBuffer XMesaCreatePBuffer(XMesaVisual v, Colormap cmap, + unsigned int width, unsigned int height); + + + +/* + * Texture from Pixmap + * New in Mesa 7.1 + */ +extern void +XMesaBindTexImage(Display *dpy, XMesaBuffer drawable, int buffer, + const int *attrib_list); + +extern void +XMesaReleaseTexImage(Display *dpy, XMesaBuffer drawable, int buffer); + + +extern XMesaBuffer +XMesaCreatePixmapTextureBuffer(XMesaVisual v, Pixmap p, + Colormap cmap, + int format, int target, int mipmap); + + +extern void +XMesaCopyContext(XMesaContext src, XMesaContext dst, unsigned long mask); + + +/*********************************************************************** + */ + +/** + * Visual inforation, derived from GLvisual. + * Basically corresponds to an XVisualInfo. + */ +struct xmesa_visual { + struct gl_config mesa_visual;/* Device independent visual parameters */ + int screen, visualID, visualType; + Display *display; /* The X11 display */ + XVisualInfo * visinfo; /* X's visual info (pointer to private copy) */ + XVisualInfo *vishandle; /* Only used in fakeglx.c */ + GLint BitsPerPixel; /* True bits per pixel for XImages */ + + GLboolean ximage_flag; /* Use XImage for back buffer (not pixmap)? */ + + struct st_visual stvis; +}; + + +/** + * Context info, derived from st_context. + * Basically corresponds to a GLXContext. + */ +struct xmesa_context { + struct st_context_iface *st; + XMesaVisual xm_visual; /** pixel format info */ + XMesaBuffer xm_buffer; /** current drawbuffer */ + XMesaBuffer xm_read_buffer; /** current readbuffer */ + struct hud_context *hud; +}; + + +/** + * Types of X/GLX drawables we might render into. + */ +typedef enum { + WINDOW, /* An X window */ + GLXWINDOW, /* GLX window */ + PIXMAP, /* GLX pixmap */ + PBUFFER /* GLX Pbuffer */ +} BufferType; + + +/** + * Framebuffer information, derived from. + * Basically corresponds to a GLXDrawable. + */ +struct xmesa_buffer { + struct st_framebuffer_iface *stfb; + struct xlib_drawable ws; + + GLboolean wasCurrent; /* was ever the current buffer? */ + XMesaVisual xm_visual; /* the X/Mesa visual */ + Colormap cmap; /* the X colormap */ + BufferType type; /* window, pixmap, pbuffer or glxwindow */ + + GLboolean largestPbuffer; /**< for pbuffers */ + GLboolean preservedContents; /**< for pbuffers */ + + XImage *tempImage; + unsigned long selectedEvents;/* for pbuffers only */ + + + GC gc; /* scratch GC for span, line, tri drawing */ + + /* GLX_EXT_texture_from_pixmap */ + GLint TextureTarget; /** GLX_TEXTURE_1D_EXT, for example */ + GLint TextureFormat; /** GLX_TEXTURE_FORMAT_RGB_EXT, for example */ + GLint TextureMipmap; /** 0 or 1 */ + + struct xmesa_buffer *Next; /* Linked list pointer: */ + + unsigned width, height; +}; + + + +extern const char * +xmesa_get_name(void); + +extern int +xmesa_init(Display *dpy); + +extern XMesaBuffer +xmesa_find_buffer(Display *dpy, Colormap cmap, XMesaBuffer notThis); + +extern void +xmesa_get_window_size(Display *dpy, XMesaBuffer b, + GLuint *width, GLuint *height); + +extern void +xmesa_notify_invalid_buffer(XMesaBuffer b); + +extern void +xmesa_check_buffer_size(XMesaBuffer b); + +extern void +xmesa_destroy_buffers_on_display(Display *dpy); + +extern void +xmesa_close_display(Display *dpy); + +static inline GLuint +xmesa_buffer_width(XMesaBuffer b) +{ + return b->width; +} + +static inline GLuint +xmesa_buffer_height(XMesaBuffer b) +{ + return b->height; +} + +extern boolean xmesa_strict_invalidate; + +#endif diff --git a/src/gallium/frontends/glx/xlib/xm_public.h b/src/gallium/frontends/glx/xlib/xm_public.h new file mode 100644 index 00000000000..9afc5f5d7cf --- /dev/null +++ b/src/gallium/frontends/glx/xlib/xm_public.h @@ -0,0 +1,48 @@ + +/************************************************************************** + * + * Copyright 2006 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef XM_PUBLIC_H +#define XM_PUBLIC_H + +#include + +struct pipe_screen; +struct st_api; + +/* This is the driver interface required by the glx/xlib state tracker. + */ +struct xm_driver { + struct pipe_screen *(*create_pipe_screen)( Display *display ); + struct st_api *(*create_st_api)( void ); +}; + +extern void +xmesa_set_driver( const struct xm_driver *driver ); + + +#endif /* XM_PUBLIC_H */ diff --git a/src/gallium/frontends/glx/xlib/xm_st.c b/src/gallium/frontends/glx/xlib/xm_st.c new file mode 100644 index 00000000000..4fe7b57f24c --- /dev/null +++ b/src/gallium/frontends/glx/xlib/xm_st.c @@ -0,0 +1,411 @@ +/* + * Mesa 3-D graphics library + * + * Copyright (C) 2010 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu + */ + +#include "xm_api.h" +#include "xm_st.h" + +#include "util/u_inlines.h" +#include "util/u_atomic.h" +#include "util/u_memory.h" + +struct xmesa_st_framebuffer { + XMesaDisplay display; + XMesaBuffer buffer; + struct pipe_screen *screen; + + struct st_visual stvis; + enum pipe_texture_target target; + + unsigned texture_width, texture_height, texture_mask; + struct pipe_resource *textures[ST_ATTACHMENT_COUNT]; + + struct pipe_resource *display_resource; +}; + + +static inline struct xmesa_st_framebuffer * +xmesa_st_framebuffer(struct st_framebuffer_iface *stfbi) +{ + return (struct xmesa_st_framebuffer *) stfbi->st_manager_private; +} + + +/** + * Display (present) an attachment to the xlib_drawable of the framebuffer. + */ +static bool +xmesa_st_framebuffer_display(struct st_framebuffer_iface *stfbi, + enum st_attachment_type statt) +{ + struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); + struct pipe_resource *ptex = xstfb->textures[statt]; + struct pipe_resource *pres; + + if (!ptex) + return true; + + pres = xstfb->display_resource; + /* (re)allocate the surface for the texture to be displayed */ + if (!pres || pres != ptex) { + pipe_resource_reference(&xstfb->display_resource, ptex); + pres = xstfb->display_resource; + } + + xstfb->screen->flush_frontbuffer(xstfb->screen, pres, 0, 0, &xstfb->buffer->ws, NULL); + return true; +} + + +/** + * Copy the contents between the attachments. + */ +static void +xmesa_st_framebuffer_copy_textures(struct st_framebuffer_iface *stfbi, + enum st_attachment_type src_statt, + enum st_attachment_type dst_statt, + unsigned x, unsigned y, + unsigned width, unsigned height) +{ + struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); + struct pipe_resource *src_ptex = xstfb->textures[src_statt]; + struct pipe_resource *dst_ptex = xstfb->textures[dst_statt]; + struct pipe_box src_box; + struct pipe_context *pipe; + + if (!src_ptex || !dst_ptex) + return; + + pipe = xmesa_get_context(stfbi); + + u_box_2d(x, y, width, height, &src_box); + + if (src_ptex && dst_ptex) + pipe->resource_copy_region(pipe, dst_ptex, 0, x, y, 0, + src_ptex, 0, &src_box); +} + + +/** + * Remove outdated textures and create the requested ones. + * This is a helper used during framebuffer validation. + */ +bool +xmesa_st_framebuffer_validate_textures(struct st_framebuffer_iface *stfbi, + unsigned width, unsigned height, + unsigned mask) +{ + struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); + struct pipe_resource templ; + enum st_attachment_type i; + + /* remove outdated textures */ + if (xstfb->texture_width != width || xstfb->texture_height != height) { + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) + pipe_resource_reference(&xstfb->textures[i], NULL); + } + + memset(&templ, 0, sizeof(templ)); + templ.target = xstfb->target; + templ.width0 = width; + templ.height0 = height; + templ.depth0 = 1; + templ.array_size = 1; + templ.last_level = 0; + templ.nr_samples = xstfb->stvis.samples; + templ.nr_storage_samples = xstfb->stvis.samples; + + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { + enum pipe_format format; + unsigned bind; + + /* the texture already exists or not requested */ + if (xstfb->textures[i] || !(mask & (1 << i))) { + /* remember the texture */ + if (xstfb->textures[i]) + mask |= (1 << i); + continue; + } + + switch (i) { + case ST_ATTACHMENT_FRONT_LEFT: + case ST_ATTACHMENT_BACK_LEFT: + case ST_ATTACHMENT_FRONT_RIGHT: + case ST_ATTACHMENT_BACK_RIGHT: + format = xstfb->stvis.color_format; + bind = PIPE_BIND_DISPLAY_TARGET | + PIPE_BIND_RENDER_TARGET; + break; + case ST_ATTACHMENT_DEPTH_STENCIL: + format = xstfb->stvis.depth_stencil_format; + bind = PIPE_BIND_DEPTH_STENCIL; + break; + default: + format = PIPE_FORMAT_NONE; + break; + } + + if (format != PIPE_FORMAT_NONE) { + templ.format = format; + templ.bind = bind; + + xstfb->textures[i] = + xstfb->screen->resource_create(xstfb->screen, &templ); + if (!xstfb->textures[i]) + return FALSE; + } + } + + xstfb->texture_width = width; + xstfb->texture_height = height; + xstfb->texture_mask = mask; + + return true; +} + + +/** + * Check that a framebuffer's attachments match the window's size. + * + * Called via st_framebuffer_iface::validate() + * + * \param statts array of framebuffer attachments + * \param count number of framebuffer attachments in statts[] + * \param out returns resources for each of the attachments + */ +static bool +xmesa_st_framebuffer_validate(struct st_context_iface *stctx, + struct st_framebuffer_iface *stfbi, + const enum st_attachment_type *statts, + unsigned count, + struct pipe_resource **out) +{ + struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); + unsigned statt_mask, new_mask, i; + bool resized; + bool ret; + + /* build mask of ST_ATTACHMENT bits */ + statt_mask = 0x0; + for (i = 0; i < count; i++) + statt_mask |= 1 << statts[i]; + + /* record newly allocated textures */ + new_mask = statt_mask & ~xstfb->texture_mask; + + /* If xmesa_strict_invalidate is not set, we will not yet have + * called XGetGeometry(). Do so here: + */ + if (!xmesa_strict_invalidate) + xmesa_check_buffer_size(xstfb->buffer); + + resized = (xstfb->buffer->width != xstfb->texture_width || + xstfb->buffer->height != xstfb->texture_height); + + /* revalidate textures */ + if (resized || new_mask) { + ret = xmesa_st_framebuffer_validate_textures(stfbi, + xstfb->buffer->width, xstfb->buffer->height, statt_mask); + if (!ret) + return ret; + + if (!resized) { + enum st_attachment_type back, front; + + back = ST_ATTACHMENT_BACK_LEFT; + front = ST_ATTACHMENT_FRONT_LEFT; + /* copy the contents if front is newly allocated and back is not */ + if ((statt_mask & (1 << back)) && + (new_mask & (1 << front)) && + !(new_mask & (1 << back))) { + xmesa_st_framebuffer_copy_textures(stfbi, back, front, + 0, 0, xstfb->texture_width, xstfb->texture_height); + } + } + } + + for (i = 0; i < count; i++) + pipe_resource_reference(&out[i], xstfb->textures[statts[i]]); + + return true; +} + + +/** + * Called via st_framebuffer_iface::flush_front() + */ +static bool +xmesa_st_framebuffer_flush_front(struct st_context_iface *stctx, + struct st_framebuffer_iface *stfbi, + enum st_attachment_type statt) +{ + struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); + bool ret; + + ret = xmesa_st_framebuffer_display(stfbi, statt); + + if (ret && xmesa_strict_invalidate) + xmesa_check_buffer_size(xstfb->buffer); + + return ret; +} + +static uint32_t xmesa_stfbi_ID = 0; + +struct st_framebuffer_iface * +xmesa_create_st_framebuffer(XMesaDisplay xmdpy, XMesaBuffer b) +{ + struct st_framebuffer_iface *stfbi; + struct xmesa_st_framebuffer *xstfb; + + assert(xmdpy->display == b->xm_visual->display); + + stfbi = CALLOC_STRUCT(st_framebuffer_iface); + xstfb = CALLOC_STRUCT(xmesa_st_framebuffer); + if (!stfbi || !xstfb) { + free(stfbi); + free(xstfb); + return NULL; + } + + xstfb->display = xmdpy; + xstfb->buffer = b; + xstfb->screen = xmdpy->screen; + xstfb->stvis = b->xm_visual->stvis; + if (xstfb->screen->get_param(xstfb->screen, PIPE_CAP_NPOT_TEXTURES)) + xstfb->target = PIPE_TEXTURE_2D; + else + xstfb->target = PIPE_TEXTURE_RECT; + + stfbi->visual = &xstfb->stvis; + stfbi->flush_front = xmesa_st_framebuffer_flush_front; + stfbi->validate = xmesa_st_framebuffer_validate; + stfbi->ID = p_atomic_inc_return(&xmesa_stfbi_ID); + stfbi->state_manager = xmdpy->smapi; + p_atomic_set(&stfbi->stamp, 1); + stfbi->st_manager_private = (void *) xstfb; + + return stfbi; +} + + +void +xmesa_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi) +{ + struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); + int i; + + pipe_resource_reference(&xstfb->display_resource, NULL); + + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) + pipe_resource_reference(&xstfb->textures[i], NULL); + + free(xstfb); + free(stfbi); +} + + +/** + * Return the pipe_surface which corresponds to the given + * framebuffer attachment. + */ +struct pipe_resource * +xmesa_get_framebuffer_resource(struct st_framebuffer_iface *stfbi, + enum st_attachment_type att) +{ + struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); + return xstfb->textures[att]; +} + + +void +xmesa_swap_st_framebuffer(struct st_framebuffer_iface *stfbi) +{ + struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); + bool ret; + + ret = xmesa_st_framebuffer_display(stfbi, ST_ATTACHMENT_BACK_LEFT); + if (ret) { + struct pipe_resource **front, **back, *tmp; + + front = &xstfb->textures[ST_ATTACHMENT_FRONT_LEFT]; + back = &xstfb->textures[ST_ATTACHMENT_BACK_LEFT]; + /* swap textures only if the front texture has been allocated */ + if (*front) { + tmp = *front; + *front = *back; + *back = tmp; + + /* the current context should validate the buffer after swapping */ + if (!xmesa_strict_invalidate) + xmesa_notify_invalid_buffer(xstfb->buffer); + } + + if (xmesa_strict_invalidate) + xmesa_check_buffer_size(xstfb->buffer); + } +} + + +void +xmesa_copy_st_framebuffer(struct st_framebuffer_iface *stfbi, + enum st_attachment_type src, + enum st_attachment_type dst, + int x, int y, int w, int h) +{ + xmesa_st_framebuffer_copy_textures(stfbi, src, dst, x, y, w, h); + if (dst == ST_ATTACHMENT_FRONT_LEFT) + xmesa_st_framebuffer_display(stfbi, dst); +} + + +struct pipe_resource* +xmesa_get_attachment(struct st_framebuffer_iface *stfbi, + enum st_attachment_type st_attachment) +{ + struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); + struct pipe_resource *res; + + res = xstfb->textures[st_attachment]; + return res; +} + + +struct pipe_context* +xmesa_get_context(struct st_framebuffer_iface *stfbi) +{ + struct pipe_context *pipe; + struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); + + pipe = xstfb->display->pipe; + if (!pipe) { + pipe = xstfb->screen->context_create(xstfb->screen, NULL, 0); + if (!pipe) + return NULL; + xstfb->display->pipe = pipe; + } + return pipe; +} diff --git a/src/gallium/frontends/glx/xlib/xm_st.h b/src/gallium/frontends/glx/xlib/xm_st.h new file mode 100644 index 00000000000..6d92a38e0dd --- /dev/null +++ b/src/gallium/frontends/glx/xlib/xm_st.h @@ -0,0 +1,66 @@ +/* + * Mesa 3-D graphics library + * + * Copyright (C) 2010 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu + */ + +#ifndef _XM_ST_H_ +#define _XM_ST_H_ + +#include "pipe/p_compiler.h" +#include "frontend/api.h" + +#include "xm_api.h" + +struct st_framebuffer_iface * +xmesa_create_st_framebuffer(XMesaDisplay xmdpy, XMesaBuffer b); + +void +xmesa_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi); + +struct pipe_resource * +xmesa_get_framebuffer_resource(struct st_framebuffer_iface *stfbi, + enum st_attachment_type att); + +void +xmesa_swap_st_framebuffer(struct st_framebuffer_iface *stfbi); + +void +xmesa_copy_st_framebuffer(struct st_framebuffer_iface *stfbi, + enum st_attachment_type src, + enum st_attachment_type dst, + int x, int y, int w, int h); + +struct pipe_resource* +xmesa_get_attachment(struct st_framebuffer_iface *stfbi, + enum st_attachment_type st_attachment); + +struct pipe_context* +xmesa_get_context(struct st_framebuffer_iface* stfbi); + +bool +xmesa_st_framebuffer_validate_textures(struct st_framebuffer_iface *stfbi, + unsigned width, unsigned height, + unsigned mask); +#endif /* _XM_ST_H_ */ diff --git a/src/gallium/frontends/hgl/.editorconfig b/src/gallium/frontends/hgl/.editorconfig new file mode 100644 index 00000000000..f391def61c9 --- /dev/null +++ b/src/gallium/frontends/hgl/.editorconfig @@ -0,0 +1,2 @@ +[*.{c,h,cpp,hpp}] +indent_style = tab diff --git a/src/gallium/frontends/hgl/SConscript b/src/gallium/frontends/hgl/SConscript new file mode 100644 index 00000000000..d2389c80802 --- /dev/null +++ b/src/gallium/frontends/hgl/SConscript @@ -0,0 +1,24 @@ +####################################################################### +# SConscript for Haiku state_tracker + +Import('*') + +env = env.Clone() + +env.Append(CPPPATH = [ + '#/src', + '#/src/mapi', + '#/src/mesa', + '#/include/HaikuGL', +]) + +sources = [ + 'hgl.c', + 'bitmap_wrapper.cpp', +] + +st_haiku = env.ConvenienceLibrary( + target = 'st_haiku', + source = sources +) +Export('st_haiku') diff --git a/src/gallium/frontends/hgl/bitmap_wrapper.cpp b/src/gallium/frontends/hgl/bitmap_wrapper.cpp new file mode 100644 index 00000000000..ef81edc8a57 --- /dev/null +++ b/src/gallium/frontends/hgl/bitmap_wrapper.cpp @@ -0,0 +1,146 @@ +/************************************************************************** + * + * Copyright 2009 Artur Wyszynski + * Copyright 2013 Alexander von Gluck IV + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ + + +#include +#include +#include +#include +#include +#include + +#include "bitmap_wrapper.h" + + +extern "C" { +static int frameNo = 0; + + +Bitmap* +create_bitmap(int32 width, int32 height, color_space colorSpace) +{ + BBitmap *bb = new BBitmap(BRect(0, 0, width, height), colorSpace); + if (bb) + return (Bitmap*)bb; + return NULL; +} + + +void +get_bitmap_size(const Bitmap* bitmap, int32* width, int32* height) +{ + BBitmap *bb = (BBitmap*)bitmap; + if (bb && width && height) { + uint32 w = bb->Bounds().IntegerWidth() + 1; + uint32 h = bb->Bounds().IntegerHeight() + 1; + *width = w; + *height = h; + } +} + + +color_space +get_bitmap_color_space(const Bitmap* bitmap) +{ + BBitmap *bb = (BBitmap*)bitmap; + if (bb) + return bb->ColorSpace(); + return B_NO_COLOR_SPACE; +} + + +void +copy_bitmap_bits(const Bitmap* bitmap, void* data, int32 length) +{ + BBitmap *bb = (BBitmap*)bitmap; + + // We assume the data is 1:1 the format of the bitmap + if (bb) + bb->ImportBits(data, length, bb->BytesPerRow(), 0, bb->ColorSpace()); +} + + +void +import_bitmap_bits(const Bitmap* bitmap, void* data, int32 length, + unsigned srcStride, color_space srcColorSpace) +{ + BBitmap *bb = (BBitmap*)bitmap; + + // Import image and adjust image format from source to dest + if (bb) + bb->ImportBits(data, length, srcStride, 0, srcColorSpace); +} + + +void +delete_bitmap(Bitmap* bitmap) +{ + BBitmap *bb = (BBitmap*)bitmap; + delete bb; +} + + +int32 +get_bitmap_bytes_per_row(const Bitmap* bitmap) +{ + BBitmap *bb = (BBitmap*)bitmap; + if (bb) + return bb->BytesPerRow(); + return 0; +} + + +int32 +get_bitmap_bits_length(const Bitmap* bitmap) +{ + BBitmap *bb = (BBitmap*)bitmap; + if (bb) + return bb->BitsLength(); + return 0; +} + + +void +dump_bitmap(const Bitmap* bitmap) +{ + BBitmap *bb = (BBitmap*)bitmap; + if (!bb) + return; + + BString filename("/boot/home/frame_"); + filename << (int32)frameNo << ".png"; + + BTranslatorRoster *roster = BTranslatorRoster::Default(); + BBitmapStream stream(bb); + BFile dump(filename, B_CREATE_FILE | B_WRITE_ONLY); + + roster->Translate(&stream, NULL, NULL, &dump, 0); + + frameNo++; +} + +} diff --git a/src/gallium/frontends/hgl/bitmap_wrapper.h b/src/gallium/frontends/hgl/bitmap_wrapper.h new file mode 100644 index 00000000000..65ba14044d8 --- /dev/null +++ b/src/gallium/frontends/hgl/bitmap_wrapper.h @@ -0,0 +1,62 @@ +/************************************************************************** + * + * Copyright 2009 Artur Wyszynski + * Copyright 2013 Alexander von Gluck IV + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ +#ifndef __BBITMAP_WRAPPER_H__ +#define __BBITMAP_WRAPPER_H__ + + +#include +#include + + +typedef void Bitmap; + +#ifdef __cplusplus +extern "C" { +#endif + + +Bitmap* create_bitmap(int32 width, int32 height, color_space colorSpace); +void delete_bitmap(Bitmap* bitmap); + +void copy_bitmap_bits(const Bitmap* bitmap, void* data, int32 length); +void import_bitmap_bits(const Bitmap* bitmap, void* data, int32 length, + unsigned srcStride, color_space srcColorSpace); + +void get_bitmap_size(const Bitmap* bitmap, int32* width, int32* height); +color_space get_bitmap_color_space(const Bitmap* bitmap); +int32 get_bitmap_bytes_per_row(const Bitmap* bitmap); +int32 get_bitmap_bits_length(const Bitmap* bitmap); + +void dump_bitmap(const Bitmap* bitmap); + + +#ifdef __cplusplus +} +#endif + + +#endif /* __BBITMAP_WRAPPER_H__ */ diff --git a/src/gallium/frontends/hgl/hgl.c b/src/gallium/frontends/hgl/hgl.c new file mode 100644 index 00000000000..74cd81fc7bb --- /dev/null +++ b/src/gallium/frontends/hgl/hgl.c @@ -0,0 +1,362 @@ +/* + * Copyright 2012-2014, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Artur Wyszynski, harakash@gmail.com + * Alexander von Gluck IV, kallisti5@unixzen.com + */ + +#include "hgl_context.h" + +#include + +#include "pipe/p_format.h" +#include "util/u_atomic.h" +#include "util/format/u_format.h" +#include "util/u_memory.h" +#include "util/u_inlines.h" +#include "state_tracker/st_gl_api.h" /* for st_gl_api_create */ + +#include "GLView.h" + + +#ifdef DEBUG +# define TRACE(x...) printf("hgl:frontend: " x) +# define CALLED() TRACE("CALLED: %s\n", __PRETTY_FUNCTION__) +#else +# define TRACE(x...) +# define CALLED() +#endif +#define ERROR(x...) printf("hgl:frontend: " x) + + +// Perform a safe void to hgl_context cast +static inline struct hgl_context* +hgl_st_context(struct st_context_iface *stctxi) +{ + struct hgl_context* context; + assert(stctxi); + context = (struct hgl_context*)stctxi->st_manager_private; + assert(context); + return context; +} + + +// Perform a safe void to hgl_buffer cast +//static inline struct hgl_buffer* +struct hgl_buffer* +hgl_st_framebuffer(struct st_framebuffer_iface *stfbi) +{ + struct hgl_buffer* buffer; + assert(stfbi); + buffer = (struct hgl_buffer*)stfbi->st_manager_private; + assert(buffer); + return buffer; +} + + +static bool +hgl_st_framebuffer_flush_front(struct st_context_iface *stctxi, + struct st_framebuffer_iface* stfbi, enum st_attachment_type statt) +{ + CALLED(); + + //struct hgl_context* context = hgl_st_context(stctxi); + // struct hgl_buffer* buffer = hgl_st_context(stfbi); + struct hgl_buffer* buffer = hgl_st_framebuffer(stfbi); + //buffer->surface + + #if 0 + struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb); + mtx_lock(&stwfb->fb->mutex); + + struct pipe_resource* resource = textures[statt]; + if (resource) + stw_framebuffer_present_locked(...); + #endif + + return true; +} + + +static bool +hgl_st_framebuffer_validate_textures(struct st_framebuffer_iface *stfbi, + unsigned width, unsigned height, unsigned mask) +{ + struct hgl_buffer* buffer; + enum st_attachment_type i; + struct pipe_resource templat; + + CALLED(); + + buffer = hgl_st_framebuffer(stfbi); + + if (buffer->width != width || buffer->height != height) { + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) + pipe_resource_reference(&buffer->textures[i], NULL); + } + + memset(&templat, 0, sizeof(templat)); + templat.target = buffer->target; + templat.width0 = width; + templat.height0 = height; + templat.depth0 = 1; + templat.array_size = 1; + templat.last_level = 0; + + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { + enum pipe_format format; + unsigned bind; + + switch (i) { + case ST_ATTACHMENT_FRONT_LEFT: + case ST_ATTACHMENT_BACK_LEFT: + case ST_ATTACHMENT_FRONT_RIGHT: + case ST_ATTACHMENT_BACK_RIGHT: + format = buffer->visual->color_format; + bind = PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_RENDER_TARGET; + break; + case ST_ATTACHMENT_DEPTH_STENCIL: + format = buffer->visual->depth_stencil_format; + bind = PIPE_BIND_DEPTH_STENCIL; + break; + default: + format = PIPE_FORMAT_NONE; + bind = 0; + break; + } + + if (format != PIPE_FORMAT_NONE) { + templat.format = format; + templat.bind = bind; + buffer->textures[i] = buffer->screen->resource_create(buffer->screen, + &templat); + if (!buffer->textures[i]) + return FALSE; + } + } + + buffer->width = width; + buffer->height = height; + buffer->mask = mask; + + return true; +} + + +/** + * Called by the st manager to validate the framebuffer (allocate + * its resources). + */ +static bool +hgl_st_framebuffer_validate(struct st_context_iface *stctxi, + struct st_framebuffer_iface *stfbi, const enum st_attachment_type *statts, + unsigned count, struct pipe_resource **out) +{ + struct hgl_context* context; + struct hgl_buffer* buffer; + unsigned stAttachmentMask, newMask; + unsigned i; + bool resized; + + CALLED(); + + context = hgl_st_context(stctxi); + buffer = hgl_st_framebuffer(stfbi); + + //int32 width = 0; + //int32 height = 0; + //get_bitmap_size(context->bitmap, &width, &height); + + // Build mask of current attachments + stAttachmentMask = 0; + for (i = 0; i < count; i++) + stAttachmentMask |= 1 << statts[i]; + + newMask = stAttachmentMask & ~buffer->mask; + + resized = (buffer->width != context->width) + || (buffer->height != context->height); + + if (resized || newMask) { + boolean ret; + TRACE("%s: resize event. old: %d x %d; new: %d x %d\n", __func__, + buffer->width, buffer->height, context->width, context->height); + + ret = hgl_st_framebuffer_validate_textures(stfbi, + context->width, context->height, stAttachmentMask); + + if (!ret) + return ret; + + // TODO: Simply update attachments + //if (!resized) { + + //} + } + + for (i = 0; i < count; i++) + pipe_resource_reference(&out[i], buffer->textures[statts[i]]); + + return true; +} + + +static int +hgl_st_manager_get_param(struct st_manager *smapi, enum st_manager_param param) +{ + CALLED(); + + switch (param) { + case ST_MANAGER_BROKEN_INVALIDATE: + return 1; + } + + return 0; +} + + +/** + * Create new framebuffer + */ +struct hgl_buffer * +hgl_create_st_framebuffer(struct hgl_context* context) +{ + struct hgl_buffer *buffer; + CALLED(); + + // Our requires before creating a framebuffer + assert(context); + assert(context->screen); + assert(context->stVisual); + + buffer = CALLOC_STRUCT(hgl_buffer); + assert(buffer); + + // calloc and configure our st_framebuffer interface + buffer->stfbi = CALLOC_STRUCT(st_framebuffer_iface); + assert(buffer->stfbi); + + // Prepare our buffer + buffer->visual = context->stVisual; + buffer->screen = context->screen; + + if (context->screen->get_param(buffer->screen, PIPE_CAP_NPOT_TEXTURES)) + buffer->target = PIPE_TEXTURE_2D; + else + buffer->target = PIPE_TEXTURE_RECT; + + // Prepare our frontend interface + buffer->stfbi->flush_front = hgl_st_framebuffer_flush_front; + buffer->stfbi->validate = hgl_st_framebuffer_validate; + buffer->stfbi->visual = context->stVisual; + + p_atomic_set(&buffer->stfbi->stamp, 1); + buffer->stfbi->st_manager_private = (void*)buffer; + + return buffer; +} + + +struct st_api* +hgl_create_st_api() +{ + CALLED(); + return st_gl_api_create(); +} + + +struct st_manager * +hgl_create_st_manager(struct hgl_context* context) +{ + struct st_manager* manager; + + CALLED(); + + // Required things + assert(context); + assert(context->screen); + + manager = CALLOC_STRUCT(st_manager); + assert(manager); + + //manager->display = dpy; + manager->screen = context->screen; + manager->get_param = hgl_st_manager_get_param; + manager->st_manager_private = (void *)context; + + return manager; +} + + +void +hgl_destroy_st_manager(struct st_manager *manager) +{ + CALLED(); + + FREE(manager); +} + + +struct st_visual* +hgl_create_st_visual(ulong options) +{ + struct st_visual* visual; + + CALLED(); + + visual = CALLOC_STRUCT(st_visual); + assert(visual); + + // Determine color format + if ((options & BGL_INDEX) != 0) { + // Index color + visual->color_format = PIPE_FORMAT_B5G6R5_UNORM; + // TODO: Indexed color depth buffer? + visual->depth_stencil_format = PIPE_FORMAT_NONE; + } else { + // RGB color + visual->color_format = (options & BGL_ALPHA) + ? PIPE_FORMAT_BGRA8888_UNORM : PIPE_FORMAT_BGRX8888_UNORM; + // TODO: Determine additional stencil formats + visual->depth_stencil_format = (options & BGL_DEPTH) + ? PIPE_FORMAT_Z24_UNORM_S8_UINT : PIPE_FORMAT_NONE; + } + + visual->accum_format = (options & BGL_ACCUM) + ? PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE; + + visual->buffer_mask |= ST_ATTACHMENT_FRONT_LEFT_MASK; + visual->render_buffer = ST_ATTACHMENT_FRONT_LEFT; + + if ((options & BGL_DOUBLE) != 0) { + visual->buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK; + visual->render_buffer = ST_ATTACHMENT_BACK_LEFT; + } + + #if 0 + if ((options & BGL_STEREO) != 0) { + visual->buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK; + if ((options & BGL_DOUBLE) != 0) + visual->buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK; + } + #endif + + if ((options & BGL_DEPTH) || (options & BGL_STENCIL)) + visual->buffer_mask |= ST_ATTACHMENT_DEPTH_STENCIL_MASK; + + TRACE("%s: Visual color format: %s\n", __func__, + util_format_name(visual->color_format)); + + return visual; +} + + +void +hgl_destroy_st_visual(struct st_visual* visual) +{ + CALLED(); + + FREE(visual); +} diff --git a/src/gallium/frontends/hgl/hgl_context.h b/src/gallium/frontends/hgl/hgl_context.h new file mode 100644 index 00000000000..26a61f069a4 --- /dev/null +++ b/src/gallium/frontends/hgl/hgl_context.h @@ -0,0 +1,109 @@ +/* + * Copyright 2009-2014, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Alexander von Gluck IV, kallisti5@unixzen.com + */ +#ifndef HGL_CONTEXT_H +#define HGL_CONTEXT_H + + +#include "pipe/p_format.h" +#include "pipe/p_compiler.h" +#include "pipe/p_screen.h" +#include "postprocess/filters.h" + +#include "frontend/api.h" +#include "frontend/st_manager.h" +#include "os/os_thread.h" + +#include "bitmap_wrapper.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +#define CONTEXT_MAX 32 + +typedef int64 context_id; + + +struct hgl_buffer +{ + struct st_framebuffer_iface *stfbi; + struct st_visual* visual; + + unsigned width; + unsigned height; + unsigned mask; + + struct pipe_screen* screen; + struct pipe_surface* surface; + + enum pipe_texture_target target; + struct pipe_resource* textures[ST_ATTACHMENT_COUNT]; + + void *map; + + //struct hgl_buffer *next; /**< next in linked list */ +}; + + +struct hgl_context +{ + struct st_api* api; + // State Tracker API + struct st_manager* manager; + // State Tracker Manager + struct st_context_iface* st; + // State Tracker Interface Object + struct st_visual* stVisual; + // State Tracker Visual + + struct pipe_screen* screen; + + //struct pipe_resource* textures[ST_ATTACHMENT_COUNT]; + + // Post processing + struct pp_queue_t* postProcess; + unsigned int postProcessEnable[PP_FILTERS]; + + // Desired viewport size + unsigned width; + unsigned height; + + Bitmap* bitmap; + color_space colorSpace; + + mtx_t fbMutex; + + struct hgl_buffer* draw; + struct hgl_buffer* read; +}; + +// hgl_buffer from statetracker interface +struct hgl_buffer* hgl_st_framebuffer(struct st_framebuffer_iface *stfbi); + +// hgl frontend +struct st_api* hgl_create_st_api(void); + +// hgl framebuffer +struct hgl_buffer* hgl_create_st_framebuffer(struct hgl_context* context); + +// hgl manager +struct st_manager* hgl_create_st_manager(struct hgl_context* screen); +void hgl_destroy_st_manager(struct st_manager *manager); + +// hgl visual +struct st_visual* hgl_create_st_visual(ulong options); +void hgl_destroy_st_visual(struct st_visual* visual); + + +#ifdef __cplusplus +} +#endif + +#endif /* HGL_CONTEXT_H */ diff --git a/src/gallium/frontends/hgl/meson.build b/src/gallium/frontends/hgl/meson.build new file mode 100644 index 00000000000..3c5870fe101 --- /dev/null +++ b/src/gallium/frontends/hgl/meson.build @@ -0,0 +1,41 @@ +# Copyright © 2017 Dylan Baker + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +files_libsthgl = files( + 'bitmap_wrapper.cpp', + 'bitmap_wrapper.h', + 'hgl_context.h', + 'hgl.c', +) + +libsthgl_c_args = [] +if with_gallium_softpipe + libsthgl_c_args += '-DGALLIUM_SOFTPIPE' +endif + +libsthgl = static_library( + 'sthgl', + files_libsthgl, + include_directories : [ + inc_include, inc_haikugl, inc_util, inc_mesa, inc_mapi, inc_src, + inc_gallium, inc_gallium_aux + ], + c_args : [c_vis_args, libsthgl_c_args], +) diff --git a/src/gallium/frontends/nine/.editorconfig b/src/gallium/frontends/nine/.editorconfig new file mode 100644 index 00000000000..7b12a40ca00 --- /dev/null +++ b/src/gallium/frontends/nine/.editorconfig @@ -0,0 +1,3 @@ +[*.{c,h}] +indent_style = space +indent_size = 4 diff --git a/src/gallium/frontends/nine/Makefile.sources b/src/gallium/frontends/nine/Makefile.sources new file mode 100644 index 00000000000..56698a19f10 --- /dev/null +++ b/src/gallium/frontends/nine/Makefile.sources @@ -0,0 +1,82 @@ +C_SOURCES := \ + adapter9.c \ + adapter9.h \ + authenticatedchannel9.c \ + authenticatedchannel9.h \ + basetexture9.c \ + basetexture9.h \ + buffer9.c \ + buffer9.h \ + cryptosession9.c \ + cryptosession9.h \ + cubetexture9.c \ + cubetexture9.h \ + device9.c \ + device9.h \ + device9ex.c \ + device9ex.h \ + device9video.c \ + device9video.h \ + guid.c \ + guid.h \ + indexbuffer9.c \ + indexbuffer9.h \ + iunknown.c \ + iunknown.h \ + nine_buffer_upload.c \ + nine_buffer_upload.h \ + nine_csmt_helper.h \ + nine_debug.c \ + nine_debug.h \ + nine_defines.h \ + nine_dump.c \ + nine_dump.h \ + nineexoverlayextension.c \ + nineexoverlayextension.h \ + nine_ff.c \ + nine_ff.h \ + nine_flags.h \ + nine_helpers.c \ + nine_helpers.h \ + nine_limits.h \ + nine_lock.c \ + nine_lock.h \ + nine_pdata.h \ + nine_pipe.c \ + nine_pipe.h \ + nine_quirk.c \ + nine_quirk.h \ + nine_queue.c \ + nine_queue.h \ + nine_shader.c \ + nine_shader.h \ + nine_state.c \ + nine_state.h \ + pixelshader9.c \ + pixelshader9.h \ + query9.c \ + query9.h \ + resource9.c \ + resource9.h \ + stateblock9.c \ + stateblock9.h \ + surface9.c \ + surface9.h \ + swapchain9.c \ + swapchain9ex.c \ + swapchain9ex.h \ + swapchain9.h \ + texture9.c \ + texture9.h \ + threadpool.c \ + threadpool.h \ + vertexbuffer9.c \ + vertexbuffer9.h \ + vertexdeclaration9.c \ + vertexdeclaration9.h \ + vertexshader9.c \ + vertexshader9.h \ + volume9.c \ + volume9.h \ + volumetexture9.c \ + volumetexture9.h diff --git a/src/gallium/frontends/nine/README b/src/gallium/frontends/nine/README new file mode 100644 index 00000000000..34e928d4da3 --- /dev/null +++ b/src/gallium/frontends/nine/README @@ -0,0 +1,77 @@ +Quickstart Guide + +*** Configure and build mesa +CFLAGS="-m32" CXXFLAGS="-m32" ./autogen.sh --prefix=/usr \ + --with-gallium-drivers=nouveau,r600,swrast --enable-nine \ + --enable-debug --enable-texture-float --with-dri-drivers= --disable-dri \ + --disable-opengl --disable-egl --disable-vdpau --disable-xvmc --disable-gbm \ + --disable-llvm +make + +*** Then we create some symlinks to mesa: +ln -s "`pwd`/lib/gallium/libd3dadapter9.so.0.0.0" /usr/lib/ +ln -s "`pwd`/lib/gallium/libd3dadapter9.so.0" /usr/lib/ +ln -s "`pwd`/lib/gallium/libd3dadapter9.so" /usr/lib/ +ln -s "`pwd`/include/d3dadapter" /usr/include/ + +*** Clone and build a patched wine +git clone git@github.com:iXit/wine.git +./configure +make + +*** And finally we create some symlinks to our patched wine files: +for f in d3d9.dll gdi32.dll user32.dll wineps.drv winex11.drv; +do + mv /usr/lib/wine/$f.so /usr/lib/wine/$f.so.old + ln -s "`pwd`/dlls/`basename -s .dll $f`/$f.so" /usr/lib/wine/ +done + +*** Activating it within wine +regedit +Navigate to HKCU\Software\Wine\Direct3D +If it's not there, create it +Create a new DWORD value called UseNative +Set its value to 1 + +Every Direct3D9 program will now try using nine before wined3d + +If you want to selectively enable it per-exe instead, use the key: +HKCU\Software\Wine\AppDefaults\app.exe\Direct3D\UseNative +where app.exe is the name of your .exe file + + +*** HOW IT WORKS *** + +Nine implements the full IDirect3DDevice9 COM interface and a custom COM +interface called ID3DAdapter9 which is used to implement a final IDirect3D9Ex +COM interface. +ID3DAdapter9 is completely devoid of window system code, meaning this can be +provided by wine, Xlib, Wayland, etc. It's inadvisible to write a non-Windows +backend though, as we don't want to encourage linux developers to use this API. + +The state tracker is compiled, along with pipe-loader, into a library called +libd3dadapter9.so. This library loads pipe_[driver].so drivers on demand and +exports a single symbol for getting a subsystem driver. Currently only DRM is +supported. +This library is then linked to the library implementing the IDirect3D9[Ex] +interface and the actual Direct3D9 entry points (Direct3DCreate9[Ex]) + +The implementation of IDirect3D9[Ex] lies within wine and coexists with +wined3d. It's loaded on demand and so if it's not there, it doesn't have any +drivers or something else is wrong, d3d9.dll will automatically revert to using +wined3d. +Whether or not it's even tried is determined by 2 DWORD registry keys. +> HKCU\Software\Wine\Direct3D\UseNative +> HKCU\Software\Wine\AppDefaults\app.exe\Direct3D\UseNative +The former is the global on-switch. The latter is per-exe. + +The driver search path can be set at configure time with +--with-gallium-driver-dir and overridden at runtime with D3D9_DRIVERS_PATH. +Debugging information can be gotten with the WINEDEBUG channels d3d9 and +d3dadapter, and state_tracker debug information can be gotten with NINE_DEBUG. +Help on NINE_DEBUG is shown through NINE_DEBUG=help + +Finally, the ID3DPresent[Group] and ID3DAdapter9 interfaces are not set in +stone, so feel free to hack on those as well as st/nine. + +Happy Hacking! diff --git a/src/gallium/frontends/nine/adapter9.c b/src/gallium/frontends/nine/adapter9.c new file mode 100644 index 00000000000..e8d4697986c --- /dev/null +++ b/src/gallium/frontends/nine/adapter9.c @@ -0,0 +1,1128 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "adapter9.h" +#include "device9ex.h" +#include "nine_helpers.h" +#include "nine_defines.h" +#include "nine_pipe.h" +#include "nine_dump.h" +#include "util/u_math.h" +#include "util/format/u_format.h" +#include "util/u_dump.h" + +#include "pipe/p_screen.h" + +#define DBG_CHANNEL DBG_ADAPTER + +static bool +has_sm3(struct pipe_screen *hal) +{ + return hal->get_param(hal, PIPE_CAP_FRAGMENT_SHADER_TEXTURE_LOD) && + hal->get_param(hal, PIPE_CAP_FRAGMENT_SHADER_DERIVATIVES) && + hal->get_param(hal, PIPE_CAP_VERTEX_SHADER_SATURATE); +} + +HRESULT +NineAdapter9_ctor( struct NineAdapter9 *This, + struct NineUnknownParams *pParams, + struct d3dadapter9_context *pCTX ) +{ + struct pipe_screen *hal = pCTX->hal; + HRESULT hr = NineUnknown_ctor(&This->base, pParams); + if (FAILED(hr)) { return hr; } + + DBG("This=%p pParams=%p pCTX=%p\n", This, pParams, pCTX); + nine_dump_D3DADAPTER_IDENTIFIER9(DBG_CHANNEL, &pCTX->identifier); + + This->ctx = pCTX; + if (!hal->get_param(hal, PIPE_CAP_CLIP_HALFZ)) { + ERR("Driver doesn't support d3d9 coordinates\n"); + return D3DERR_DRIVERINTERNALERROR; + } + if (This->ctx->ref && + !This->ctx->ref->get_param(This->ctx->ref, PIPE_CAP_CLIP_HALFZ)) { + ERR("Warning: Sotware rendering driver doesn't support d3d9 coordinates\n"); + } + /* Old cards had tricks to bypass some restrictions to implement + * everything and fit tight the requirements: number of constants, + * number of temp registers, special behaviours, etc. Since we don't + * have access to all this, we need a bit more than what dx9 required. + * For example we have to use more than 32 temp registers to emulate + * behaviours, while some dx9 hw don't have more. As for sm2 hardware, + * we could support vs2 / ps2 for them but it needs some more care, and + * as these are very old, we choose to drop support for them */ + + /* checks minimum requirements, most are vs3/ps3 strict requirements */ + if (!has_sm3(hal) || + hal->get_shader_param(hal, PIPE_SHADER_VERTEX, + PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE) < 256 * sizeof(float[4]) || + hal->get_shader_param(hal, PIPE_SHADER_FRAGMENT, + PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE) < 244 * sizeof(float[4]) || + hal->get_shader_param(hal, PIPE_SHADER_VERTEX, + PIPE_SHADER_CAP_MAX_TEMPS) < 32 || + hal->get_shader_param(hal, PIPE_SHADER_FRAGMENT, + PIPE_SHADER_CAP_MAX_TEMPS) < 32 || + hal->get_shader_param(hal, PIPE_SHADER_VERTEX, + PIPE_SHADER_CAP_MAX_INPUTS) < 16 || + hal->get_shader_param(hal, PIPE_SHADER_FRAGMENT, + PIPE_SHADER_CAP_MAX_INPUTS) < 10 || + hal->get_shader_param(hal, PIPE_SHADER_FRAGMENT, + PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS) < 16) { + ERR("Your card is not supported by Gallium Nine. Minimum requirement " + "is >= r500, >= nv50, >= i965\n"); + return D3DERR_DRIVERINTERNALERROR; + } + /* for r500 */ + if (hal->get_shader_param(hal, PIPE_SHADER_VERTEX, + PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE) < 276 * sizeof(float[4]) || /* we put bool and int constants with float constants */ + hal->get_shader_param(hal, PIPE_SHADER_VERTEX, + PIPE_SHADER_CAP_MAX_TEMPS) < 40 || /* we use some more temp registers */ + hal->get_shader_param(hal, PIPE_SHADER_FRAGMENT, + PIPE_SHADER_CAP_MAX_TEMPS) < 40 || + hal->get_shader_param(hal, PIPE_SHADER_FRAGMENT, + PIPE_SHADER_CAP_MAX_INPUTS) < 20) /* we don't pack inputs as much as we could */ + ERR("Your card is at the limit of Gallium Nine requirements. Some games " + "may run into issues because requirements are too tight\n"); + return D3D_OK; +} + +void +NineAdapter9_dtor( struct NineAdapter9 *This ) +{ + struct d3dadapter9_context *ctx = This->ctx; + + DBG("This=%p\n", This); + + NineUnknown_dtor(&This->base); + + /* special case, call backend-specific dtor AFTER destroying this object + * completely. */ + if (ctx) { + if (ctx->destroy) { ctx->destroy(ctx); } + } +} + +static HRESULT +NineAdapter9_GetScreen( struct NineAdapter9 *This, + D3DDEVTYPE DevType, + struct pipe_screen **ppScreen ) +{ + const char *force_sw = getenv("D3D_ALWAYS_SOFTWARE"); + switch (DevType) { + case D3DDEVTYPE_HAL: + if (force_sw && !strcmp(force_sw, "1") && This->ctx->ref) { + *ppScreen = This->ctx->ref; + break; + } + *ppScreen = This->ctx->hal; + break; + + case D3DDEVTYPE_REF: + case D3DDEVTYPE_NULLREF: + case D3DDEVTYPE_SW: + if (force_sw && !strcmp(force_sw, "0")) { + *ppScreen = This->ctx->hal; + break; + } + *ppScreen = This->ctx->ref; + break; + + default: + user_assert(!"Invalid device type", D3DERR_INVALIDCALL); + } + + if (!*ppScreen) { return D3DERR_NOTAVAILABLE; } + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineAdapter9_GetAdapterIdentifier( struct NineAdapter9 *This, + DWORD Flags, + D3DADAPTER_IDENTIFIER9 *pIdentifier ) +{ + DBG("This=%p Flags=%x pIdentifier=%p\n", This, Flags, pIdentifier); + + /* regarding flags, MSDN has this to say: + * Flags sets the WHQLLevel member of D3DADAPTER_IDENTIFIER9. Flags can be + * set to either 0 or D3DENUM_WHQL_LEVEL. If D3DENUM_WHQL_LEVEL is + * specified, this call can connect to the Internet to download new + * Microsoft Windows Hardware Quality Labs (WHQL) certificates. + * so let's just ignore it. */ + *pIdentifier = This->ctx->identifier; + return D3D_OK; +} + +static inline boolean +backbuffer_format( D3DFORMAT dfmt, + D3DFORMAT bfmt, + boolean win ) +{ + if (dfmt == D3DFMT_A2R10G10B10 && win) { return FALSE; } + + if ((dfmt == D3DFMT_A2R10G10B10 && bfmt == dfmt) || + (dfmt == D3DFMT_X8R8G8B8 && (bfmt == dfmt || + bfmt == D3DFMT_A8R8G8B8)) || + (dfmt == D3DFMT_X1R5G5B5 && (bfmt == dfmt || + bfmt == D3DFMT_A1R5G5B5)) || + (dfmt == D3DFMT_R5G6B5 && bfmt == dfmt)) { + return TRUE; + } + + return FALSE; +} + +HRESULT NINE_WINAPI +NineAdapter9_CheckDeviceType( struct NineAdapter9 *This, + D3DDEVTYPE DevType, + D3DFORMAT AdapterFormat, + D3DFORMAT BackBufferFormat, + BOOL bWindowed ) +{ + struct pipe_screen *screen; + enum pipe_format dfmt, bfmt; + HRESULT hr; + + DBG("This=%p DevType=%s AdapterFormat=%s BackBufferFormat=%s " + "bWindowed=%i\n", This, nine_D3DDEVTYPE_to_str(DevType), + d3dformat_to_string(AdapterFormat), + d3dformat_to_string(BackBufferFormat), bWindowed); + + user_assert(backbuffer_format(AdapterFormat, BackBufferFormat, bWindowed), + D3DERR_NOTAVAILABLE); + + hr = NineAdapter9_GetScreen(This, DevType, &screen); + if (FAILED(hr)) { return hr; } + + /* The display format is not handled in Nine. We always present an XRGB8888 + * buffer (and the display server will eventually do the conversion). We probably + * don't need to check for anything for the adapter format support, since if the + * display server advertise support, it will likely be able to do the conversion. + * We do the approximation that a format is available in the display server if + * the format passes with NINE_BIND_BACKBUFFER_FLAGS */ + dfmt = d3d9_to_pipe_format_checked(screen, AdapterFormat, PIPE_TEXTURE_2D, + 1, + NINE_BIND_BACKBUFFER_FLAGS, FALSE, FALSE); + bfmt = d3d9_to_pipe_format_checked(screen, BackBufferFormat, PIPE_TEXTURE_2D, + 1, + NINE_BIND_BACKBUFFER_FLAGS, FALSE, FALSE); + if (dfmt == PIPE_FORMAT_NONE || bfmt == PIPE_FORMAT_NONE) { + DBG("Unsupported Adapter/BackBufferFormat.\n"); + return D3DERR_NOTAVAILABLE; + } + + return D3D_OK; +} + +static inline boolean +display_format( D3DFORMAT fmt, + boolean win ) +{ + /* http://msdn.microsoft.com/en-us/library/bb172558(v=VS.85).aspx#BackBuffer_or_Display_Formats */ + static const D3DFORMAT allowed[] = { + D3DFMT_A2R10G10B10, + D3DFMT_X8R8G8B8, + D3DFMT_X1R5G5B5, + D3DFMT_R5G6B5, + }; + unsigned i; + + if (fmt == D3DFMT_A2R10G10B10 && win) { return FALSE; } + + for (i = 0; i < sizeof(allowed)/sizeof(D3DFORMAT); i++) { + if (fmt == allowed[i]) { return TRUE; } + } + return FALSE; +} + +HRESULT NINE_WINAPI +NineAdapter9_CheckDeviceFormat( struct NineAdapter9 *This, + D3DDEVTYPE DeviceType, + D3DFORMAT AdapterFormat, + DWORD Usage, + D3DRESOURCETYPE RType, + D3DFORMAT CheckFormat ) +{ + struct pipe_screen *screen; + HRESULT hr; + enum pipe_format pf; + enum pipe_texture_target target; + unsigned bind = 0; + boolean srgb; + + /* Check adapter format. */ + + DBG("This=%p DeviceType=%s AdapterFormat=%s\n", This, + nine_D3DDEVTYPE_to_str(DeviceType), d3dformat_to_string(AdapterFormat)); + DBG("Usage=%x RType=%u CheckFormat=%s\n", Usage, RType, + d3dformat_to_string(CheckFormat)); + + user_assert(display_format(AdapterFormat, FALSE), D3DERR_INVALIDCALL); + + hr = NineAdapter9_GetScreen(This, DeviceType, &screen); + if (FAILED(hr)) + return hr; + pf = d3d9_to_pipe_format_checked(screen, AdapterFormat, PIPE_TEXTURE_2D, 0, + PIPE_BIND_DISPLAY_TARGET | + PIPE_BIND_SHARED, FALSE, FALSE); + if (pf == PIPE_FORMAT_NONE) { + DBG("AdapterFormat %s not available.\n", + d3dformat_to_string(AdapterFormat)); + return D3DERR_NOTAVAILABLE; + } + + /* Check actual format. */ + + switch (RType) { + case D3DRTYPE_SURFACE: target = PIPE_TEXTURE_2D; break; + case D3DRTYPE_TEXTURE: target = PIPE_TEXTURE_2D; break; + case D3DRTYPE_CUBETEXTURE: target = PIPE_TEXTURE_CUBE; break; + case D3DRTYPE_VOLUME: target = PIPE_TEXTURE_3D; break; + case D3DRTYPE_VOLUMETEXTURE: target = PIPE_TEXTURE_3D; break; + case D3DRTYPE_VERTEXBUFFER: target = PIPE_BUFFER; break; + case D3DRTYPE_INDEXBUFFER: target = PIPE_BUFFER; break; + default: + user_assert(0, D3DERR_INVALIDCALL); + } + + bind = 0; + if (Usage & D3DUSAGE_RENDERTARGET) bind |= PIPE_BIND_RENDER_TARGET; + if (Usage & D3DUSAGE_DEPTHSTENCIL) { + if (!depth_stencil_format(CheckFormat)) + return D3DERR_NOTAVAILABLE; + bind |= d3d9_get_pipe_depth_format_bindings(CheckFormat); + } + + /* API hack because setting RT[0] to NULL is forbidden */ + if (CheckFormat == D3DFMT_NULL && bind == PIPE_BIND_RENDER_TARGET && + (RType == D3DRTYPE_SURFACE || + RType == D3DRTYPE_TEXTURE)) + return D3D_OK; + + /* RESZ hack */ + if (CheckFormat == D3DFMT_RESZ && bind == PIPE_BIND_RENDER_TARGET && + RType == D3DRTYPE_SURFACE) + return screen->get_param(screen, PIPE_CAP_MULTISAMPLE_Z_RESOLVE) ? + D3D_OK : D3DERR_NOTAVAILABLE; + + /* ATOC hack */ + if (CheckFormat == D3DFMT_ATOC && RType == D3DRTYPE_SURFACE) + return D3D_OK; + + if ((Usage & D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) && + (Usage & D3DUSAGE_RENDERTARGET)) + bind |= PIPE_BIND_BLENDABLE; + + if (Usage & D3DUSAGE_DMAP) { + DBG("D3DUSAGE_DMAP not available\n"); + return D3DERR_NOTAVAILABLE; /* TODO: displacement mapping */ + } + + switch (RType) { + case D3DRTYPE_TEXTURE: bind |= PIPE_BIND_SAMPLER_VIEW; break; + case D3DRTYPE_CUBETEXTURE: bind |= PIPE_BIND_SAMPLER_VIEW; break; + case D3DRTYPE_VOLUMETEXTURE: bind |= PIPE_BIND_SAMPLER_VIEW; break; + case D3DRTYPE_VERTEXBUFFER: bind |= PIPE_BIND_VERTEX_BUFFER; break; + case D3DRTYPE_INDEXBUFFER: bind |= PIPE_BIND_INDEX_BUFFER; break; + case D3DRTYPE_SURFACE: + if (!(Usage & D3DUSAGE_DEPTHSTENCIL)) + bind |= PIPE_BIND_SAMPLER_VIEW; /* StretchRect */ + /* Offscreen surface support: Usage = 0. + * In practice drivers are very restrictive on the formats supported. + * Basically a few common formats + YUV and compressed formats. The + * reason is that offscreen surface are useful only for directdraw + * compatibility (a WONTIMPL of nine) + format conversion (useful in + * particular for YUV because the format was not advertised for textures + * on NV chips). */ + if (Usage == 0) + bind |= PIPE_BIND_RENDER_TARGET; /* A current requirement of our impl, which we should get rid of. */ + default: + break; + } + + + srgb = (Usage & (D3DUSAGE_QUERY_SRGBREAD | D3DUSAGE_QUERY_SRGBWRITE)) != 0; + pf = d3d9_to_pipe_format_checked(screen, CheckFormat, target, + 0, bind, srgb, FALSE); + if (pf == PIPE_FORMAT_NONE) { + DBG("NOT AVAILABLE\n"); + return D3DERR_NOTAVAILABLE; + } + + /* we support ATI1 and ATI2 hack only for 2D and Cube textures */ + if (RType != D3DRTYPE_TEXTURE && RType != D3DRTYPE_CUBETEXTURE && + (CheckFormat == D3DFMT_ATI1 || CheckFormat == D3DFMT_ATI2)) + return D3DERR_NOTAVAILABLE; + /* if (Usage & D3DUSAGE_NONSECURE) { don't know the implications of this } */ + /* if (Usage & D3DUSAGE_SOFTWAREPROCESSING) { we can always support this } */ + + if ((Usage & D3DUSAGE_AUTOGENMIPMAP) && !(bind & PIPE_BIND_SAMPLER_VIEW)) + return D3DOK_NOAUTOGEN; + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineAdapter9_CheckDeviceMultiSampleType( struct NineAdapter9 *This, + D3DDEVTYPE DeviceType, + D3DFORMAT SurfaceFormat, + BOOL Windowed, + D3DMULTISAMPLE_TYPE MultiSampleType, + DWORD *pQualityLevels ) +{ + struct pipe_screen *screen; + HRESULT hr; + enum pipe_format pf; + unsigned bind; + + DBG("This=%p DeviceType=%s SurfaceFormat=%s Windowed=%i MultiSampleType=%u " + "pQualityLevels=%p\n", This, nine_D3DDEVTYPE_to_str(DeviceType), + d3dformat_to_string(SurfaceFormat), Windowed, MultiSampleType, + pQualityLevels); + + if (pQualityLevels) { + /* In error cases return only 1 quality level supported */ + *pQualityLevels = 1; + } + user_assert(MultiSampleType <= D3DMULTISAMPLE_16_SAMPLES, D3DERR_INVALIDCALL); + + hr = NineAdapter9_GetScreen(This, DeviceType, &screen); + if (FAILED(hr)) + return hr; + + if (depth_stencil_format(SurfaceFormat)) + bind = d3d9_get_pipe_depth_format_bindings(SurfaceFormat); + else /* render-target */ + bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; + + pf = d3d9_to_pipe_format_checked(screen, SurfaceFormat, PIPE_TEXTURE_2D, + 0, PIPE_BIND_SAMPLER_VIEW, FALSE, FALSE); + + if (pf == PIPE_FORMAT_NONE && SurfaceFormat != D3DFMT_NULL) { + DBG("%s not available.\n", d3dformat_to_string(SurfaceFormat)); + return D3DERR_INVALIDCALL; + } + + pf = d3d9_to_pipe_format_checked(screen, SurfaceFormat, PIPE_TEXTURE_2D, + MultiSampleType, bind, FALSE, FALSE); + + if (pf == PIPE_FORMAT_NONE && SurfaceFormat != D3DFMT_NULL) { + DBG("%s with %u samples not available.\n", + d3dformat_to_string(SurfaceFormat), MultiSampleType); + return D3DERR_NOTAVAILABLE; + } + + if (pQualityLevels) { + /* NONMASKABLE MultiSampleType might have more than one quality level, + * while MASKABLE MultiSampleTypes have only one level. + * Advertise quality levels and map each level to a sample count. */ + (void ) d3dmultisample_type_check(screen, SurfaceFormat, + &MultiSampleType, D3DMULTISAMPLE_16_SAMPLES, pQualityLevels); + DBG("advertising %u quality levels\n", *pQualityLevels); + } + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineAdapter9_CheckDepthStencilMatch( struct NineAdapter9 *This, + D3DDEVTYPE DeviceType, + D3DFORMAT AdapterFormat, + D3DFORMAT RenderTargetFormat, + D3DFORMAT DepthStencilFormat ) +{ + struct pipe_screen *screen; + enum pipe_format dfmt, bfmt, zsfmt; + HRESULT hr; + + DBG("This=%p DeviceType=%s AdapterFormat=%s " + "RenderTargetFormat=%s DepthStencilFormat=%s\n", This, + nine_D3DDEVTYPE_to_str(DeviceType), d3dformat_to_string(AdapterFormat), + d3dformat_to_string(RenderTargetFormat), + d3dformat_to_string(DepthStencilFormat)); + + user_assert(display_format(AdapterFormat, FALSE), D3DERR_NOTAVAILABLE); + user_assert(depth_stencil_format(DepthStencilFormat), D3DERR_NOTAVAILABLE); + + hr = NineAdapter9_GetScreen(This, DeviceType, &screen); + if (FAILED(hr)) { return hr; } + + dfmt = d3d9_to_pipe_format_checked(screen, AdapterFormat, PIPE_TEXTURE_2D, 0, + NINE_BIND_BACKBUFFER_FLAGS, FALSE, FALSE); + bfmt = d3d9_to_pipe_format_checked(screen, RenderTargetFormat, + PIPE_TEXTURE_2D, 0, + NINE_BIND_BACKBUFFER_FLAGS, FALSE, FALSE); + if (RenderTargetFormat == D3DFMT_NULL) + bfmt = dfmt; + zsfmt = d3d9_to_pipe_format_checked(screen, DepthStencilFormat, + PIPE_TEXTURE_2D, 0, + d3d9_get_pipe_depth_format_bindings(DepthStencilFormat), + FALSE, FALSE); + if (dfmt == PIPE_FORMAT_NONE || + bfmt == PIPE_FORMAT_NONE || + zsfmt == PIPE_FORMAT_NONE) { + return D3DERR_NOTAVAILABLE; + } + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineAdapter9_CheckDeviceFormatConversion( struct NineAdapter9 *This, + D3DDEVTYPE DeviceType, + D3DFORMAT SourceFormat, + D3DFORMAT TargetFormat ) +{ + /* MSDN says this tests whether a certain backbuffer format can be used in + * conjunction with a certain front buffer format. It's a little confusing + * but some one wiser might be able to figure this one out. XXX */ + struct pipe_screen *screen; + enum pipe_format dfmt, bfmt; + HRESULT hr; + + DBG("This=%p DeviceType=%s SourceFormat=%s TargetFormat=%s\n", This, + nine_D3DDEVTYPE_to_str(DeviceType), + d3dformat_to_string(SourceFormat), d3dformat_to_string(TargetFormat)); + + user_assert(backbuffer_format(TargetFormat, SourceFormat, FALSE), + D3DERR_NOTAVAILABLE); + + hr = NineAdapter9_GetScreen(This, DeviceType, &screen); + if (FAILED(hr)) { return hr; } + + dfmt = d3d9_to_pipe_format_checked(screen, TargetFormat, PIPE_TEXTURE_2D, 1, + NINE_BIND_BACKBUFFER_FLAGS, FALSE, FALSE); + bfmt = d3d9_to_pipe_format_checked(screen, SourceFormat, PIPE_TEXTURE_2D, 1, + NINE_BIND_BACKBUFFER_FLAGS, FALSE, FALSE); + + if (dfmt == PIPE_FORMAT_NONE || bfmt == PIPE_FORMAT_NONE) { + DBG("%s to %s not supported.\n", + d3dformat_to_string(SourceFormat), + d3dformat_to_string(TargetFormat)); + return D3DERR_NOTAVAILABLE; + } + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineAdapter9_GetDeviceCaps( struct NineAdapter9 *This, + D3DDEVTYPE DeviceType, + D3DCAPS9 *pCaps ) +{ + struct pipe_screen *screen; + HRESULT hr; + + DBG("This=%p DeviceType=%s pCaps=%p\n", This, + nine_D3DDEVTYPE_to_str(DeviceType), pCaps); + + user_assert(pCaps, D3DERR_INVALIDCALL); + + hr = NineAdapter9_GetScreen(This, DeviceType, &screen); + if (FAILED(hr)) { + DBG("Failed to get pipe_screen.\n"); + return hr; + } + +#define D3DPIPECAP(pcap, d3dcap) \ + (screen->get_param(screen, PIPE_CAP_##pcap) ? (d3dcap) : 0) + +#define D3DNPIPECAP(pcap, d3dcap) \ + (screen->get_param(screen, PIPE_CAP_##pcap) ? 0 : (d3dcap)) + + pCaps->DeviceType = DeviceType; + + pCaps->AdapterOrdinal = 0; + + pCaps->Caps = D3DCAPS_READ_SCANLINE; + + pCaps->Caps2 = /* D3DCAPS2_CANMANAGERESOURCE | */ + /* D3DCAPS2_CANSHARERESOURCE | */ + /* D3DCAPS2_CANCALIBRATEGAMMA | */ + D3DCAPS2_DYNAMICTEXTURES | + D3DCAPS2_FULLSCREENGAMMA | + D3DCAPS2_CANAUTOGENMIPMAP; + + /* Note: D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD just means the + * backbuffer can be ARGB (instead of only XRGB) when we are fullscreen + * and in discard mode. */ + pCaps->Caps3 = D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD | + D3DCAPS3_COPY_TO_VIDMEM | + D3DCAPS3_COPY_TO_SYSTEMMEM | + D3DCAPS3_LINEAR_TO_SRGB_PRESENTATION; + + pCaps->PresentationIntervals = D3DPRESENT_INTERVAL_DEFAULT | + D3DPRESENT_INTERVAL_ONE | + D3DPRESENT_INTERVAL_TWO | + D3DPRESENT_INTERVAL_THREE | + D3DPRESENT_INTERVAL_FOUR | + D3DPRESENT_INTERVAL_IMMEDIATE; + pCaps->CursorCaps = D3DCURSORCAPS_COLOR /* | D3DCURSORCAPS_LOWRES*/; + + pCaps->DevCaps = D3DDEVCAPS_CANBLTSYSTONONLOCAL | + D3DDEVCAPS_CANRENDERAFTERFLIP | + D3DDEVCAPS_DRAWPRIMITIVES2 | + D3DDEVCAPS_DRAWPRIMITIVES2EX | + D3DDEVCAPS_DRAWPRIMTLVERTEX | + D3DDEVCAPS_EXECUTESYSTEMMEMORY | + D3DDEVCAPS_EXECUTEVIDEOMEMORY | + D3DDEVCAPS_HWRASTERIZATION | + D3DDEVCAPS_HWTRANSFORMANDLIGHT | + /*D3DDEVCAPS_NPATCHES |*/ + D3DDEVCAPS_PUREDEVICE | + /*D3DDEVCAPS_QUINTICRTPATCHES |*/ + /*D3DDEVCAPS_RTPATCHES |*/ + /*D3DDEVCAPS_RTPATCHHANDLEZERO |*/ + /*D3DDEVCAPS_SEPARATETEXTUREMEMORIES |*/ + D3DDEVCAPS_TEXTURENONLOCALVIDMEM | + /* D3DDEVCAPS_TEXTURESYSTEMMEMORY |*/ + D3DDEVCAPS_TEXTUREVIDEOMEMORY | + D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | + D3DDEVCAPS_TLVERTEXVIDEOMEMORY; + + pCaps->PrimitiveMiscCaps = D3DPMISCCAPS_MASKZ | + D3DPMISCCAPS_CULLNONE | /* XXX */ + D3DPMISCCAPS_CULLCW | + D3DPMISCCAPS_CULLCCW | + D3DPMISCCAPS_COLORWRITEENABLE | + D3DPMISCCAPS_CLIPPLANESCALEDPOINTS | + /*D3DPMISCCAPS_CLIPTLVERTS |*/ + D3DPMISCCAPS_TSSARGTEMP | + D3DPMISCCAPS_BLENDOP | + D3DPIPECAP(INDEP_BLEND_ENABLE, D3DPMISCCAPS_INDEPENDENTWRITEMASKS) | + D3DPMISCCAPS_PERSTAGECONSTANT | + /*D3DPMISCCAPS_POSTBLENDSRGBCONVERT |*/ /* TODO: advertise if Ex and dx10 able card */ + D3DPMISCCAPS_FOGANDSPECULARALPHA | /* Note: documentation of the flag is wrong */ + D3DPIPECAP(BLEND_EQUATION_SEPARATE, D3DPMISCCAPS_SEPARATEALPHABLEND) | + D3DPIPECAP(MIXED_COLORBUFFER_FORMATS, D3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS) | + D3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING | + D3DPMISCCAPS_FOGVERTEXCLAMPED; + if (!screen->get_param(screen, PIPE_CAP_TGSI_VS_WINDOW_SPACE_POSITION)) + pCaps->PrimitiveMiscCaps |= D3DPMISCCAPS_CLIPTLVERTS; + + pCaps->RasterCaps = + D3DPIPECAP(ANISOTROPIC_FILTER, D3DPRASTERCAPS_ANISOTROPY) | + D3DPRASTERCAPS_COLORPERSPECTIVE | + D3DPRASTERCAPS_DITHER | + D3DPRASTERCAPS_DEPTHBIAS | + D3DPRASTERCAPS_FOGRANGE | + D3DPRASTERCAPS_FOGTABLE | + D3DPRASTERCAPS_FOGVERTEX | + D3DPRASTERCAPS_MIPMAPLODBIAS | + D3DPRASTERCAPS_MULTISAMPLE_TOGGLE | + D3DPRASTERCAPS_SCISSORTEST | + D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS | + /*D3DPRASTERCAPS_WBUFFER |*/ + D3DPRASTERCAPS_WFOG | + /*D3DPRASTERCAPS_ZBUFFERLESSHSR |*/ + D3DPRASTERCAPS_ZFOG | + D3DPRASTERCAPS_ZTEST; + + pCaps->ZCmpCaps = D3DPCMPCAPS_NEVER | + D3DPCMPCAPS_LESS | + D3DPCMPCAPS_EQUAL | + D3DPCMPCAPS_LESSEQUAL | + D3DPCMPCAPS_GREATER | + D3DPCMPCAPS_NOTEQUAL | + D3DPCMPCAPS_GREATEREQUAL | + D3DPCMPCAPS_ALWAYS; + + pCaps->SrcBlendCaps = D3DPBLENDCAPS_ZERO | + D3DPBLENDCAPS_ONE | + D3DPBLENDCAPS_SRCCOLOR | + D3DPBLENDCAPS_INVSRCCOLOR | + D3DPBLENDCAPS_SRCALPHA | + D3DPBLENDCAPS_INVSRCALPHA | + D3DPBLENDCAPS_DESTALPHA | + D3DPBLENDCAPS_INVDESTALPHA | + D3DPBLENDCAPS_DESTCOLOR | + D3DPBLENDCAPS_INVDESTCOLOR | + D3DPBLENDCAPS_SRCALPHASAT | + D3DPBLENDCAPS_BOTHSRCALPHA | + D3DPBLENDCAPS_BOTHINVSRCALPHA | + D3DPBLENDCAPS_BLENDFACTOR | + D3DPIPECAP(MAX_DUAL_SOURCE_RENDER_TARGETS, + D3DPBLENDCAPS_INVSRCCOLOR2 | + D3DPBLENDCAPS_SRCCOLOR2); + + pCaps->DestBlendCaps = pCaps->SrcBlendCaps; + + pCaps->AlphaCmpCaps = D3DPCMPCAPS_NEVER | + D3DPCMPCAPS_LESS | + D3DPCMPCAPS_EQUAL | + D3DPCMPCAPS_LESSEQUAL | + D3DPCMPCAPS_GREATER | + D3DPCMPCAPS_NOTEQUAL | + D3DPCMPCAPS_GREATEREQUAL | + D3DPCMPCAPS_ALWAYS; + + /* FLAT caps not legal for D3D9. */ + pCaps->ShadeCaps = D3DPSHADECAPS_COLORGOURAUDRGB | + D3DPSHADECAPS_SPECULARGOURAUDRGB | + D3DPSHADECAPS_ALPHAGOURAUDBLEND | + D3DPSHADECAPS_FOGGOURAUD; + + pCaps->TextureCaps = + D3DPTEXTURECAPS_ALPHA | + D3DPTEXTURECAPS_ALPHAPALETTE | + D3DPTEXTURECAPS_PERSPECTIVE | + D3DPTEXTURECAPS_PROJECTED | + D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE | + D3DPTEXTURECAPS_CUBEMAP | + D3DPTEXTURECAPS_VOLUMEMAP | + D3DNPIPECAP(NPOT_TEXTURES, D3DPTEXTURECAPS_POW2) | + D3DNPIPECAP(NPOT_TEXTURES, D3DPTEXTURECAPS_NONPOW2CONDITIONAL) | + D3DNPIPECAP(NPOT_TEXTURES, D3DPTEXTURECAPS_CUBEMAP_POW2) | + D3DNPIPECAP(NPOT_TEXTURES, D3DPTEXTURECAPS_VOLUMEMAP_POW2) | + D3DPIPECAP(MAX_TEXTURE_2D_SIZE, D3DPTEXTURECAPS_MIPMAP) | + D3DPIPECAP(MAX_TEXTURE_3D_LEVELS, D3DPTEXTURECAPS_MIPVOLUMEMAP) | + D3DPIPECAP(MAX_TEXTURE_CUBE_LEVELS, D3DPTEXTURECAPS_MIPCUBEMAP); + + pCaps->TextureFilterCaps = + D3DPTFILTERCAPS_MINFPOINT | + D3DPTFILTERCAPS_MINFLINEAR | + D3DPIPECAP(ANISOTROPIC_FILTER, D3DPTFILTERCAPS_MINFANISOTROPIC) | + /*D3DPTFILTERCAPS_MINFPYRAMIDALQUAD |*/ + /*D3DPTFILTERCAPS_MINFGAUSSIANQUAD |*/ + D3DPTFILTERCAPS_MIPFPOINT | + D3DPTFILTERCAPS_MIPFLINEAR | + D3DPTFILTERCAPS_MAGFPOINT | + D3DPTFILTERCAPS_MAGFLINEAR | + D3DPIPECAP(ANISOTROPIC_FILTER, D3DPTFILTERCAPS_MAGFANISOTROPIC) | + /*D3DPTFILTERCAPS_MAGFPYRAMIDALQUAD |*/ + /*D3DPTFILTERCAPS_MAGFGAUSSIANQUAD*/0; + + pCaps->CubeTextureFilterCaps = pCaps->TextureFilterCaps; + pCaps->VolumeTextureFilterCaps = pCaps->TextureFilterCaps; + + pCaps->TextureAddressCaps = + D3DPTADDRESSCAPS_BORDER | + D3DPTADDRESSCAPS_INDEPENDENTUV | + D3DPTADDRESSCAPS_WRAP | + D3DPTADDRESSCAPS_MIRROR | + D3DPTADDRESSCAPS_CLAMP | + D3DPIPECAP(TEXTURE_MIRROR_CLAMP, D3DPTADDRESSCAPS_MIRRORONCE); + + pCaps->VolumeTextureAddressCaps = pCaps->TextureAddressCaps; + + pCaps->LineCaps = + D3DLINECAPS_ALPHACMP | + D3DLINECAPS_BLEND | + D3DLINECAPS_TEXTURE | + D3DLINECAPS_ZTEST | + D3DLINECAPS_FOG; + if (screen->get_paramf(screen, PIPE_CAPF_MAX_LINE_WIDTH_AA) > 0.0) { + pCaps->LineCaps |= D3DLINECAPS_ANTIALIAS; + } + + pCaps->MaxTextureWidth =screen->get_param(screen, + PIPE_CAP_MAX_TEXTURE_2D_SIZE); + pCaps->MaxTextureHeight = pCaps->MaxTextureWidth; + pCaps->MaxVolumeExtent = + 1 << (screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_3D_LEVELS) - 1); + /* XXX values from wine */ + pCaps->MaxTextureRepeat = 32768; + pCaps->MaxTextureAspectRatio = pCaps->MaxTextureWidth; + + pCaps->MaxAnisotropy = + (DWORD)screen->get_paramf(screen, PIPE_CAPF_MAX_TEXTURE_ANISOTROPY); + + /* Values for GeForce 9600 GT */ + pCaps->MaxVertexW = 1e10f; + pCaps->GuardBandLeft = -1e9f; + pCaps->GuardBandTop = -1e9f; + pCaps->GuardBandRight = 1e9f; + pCaps->GuardBandBottom = 1e9f; + pCaps->ExtentsAdjust = 0.0f; + + pCaps->StencilCaps = + D3DSTENCILCAPS_KEEP | + D3DSTENCILCAPS_ZERO | + D3DSTENCILCAPS_REPLACE | + D3DSTENCILCAPS_INCRSAT | + D3DSTENCILCAPS_DECRSAT | + D3DSTENCILCAPS_INVERT | + D3DSTENCILCAPS_INCR | + D3DSTENCILCAPS_DECR | + D3DSTENCILCAPS_TWOSIDED; + + pCaps->FVFCaps = + 8 | /* 8 textures max */ + /*D3DFVFCAPS_DONOTSTRIPELEMENTS |*/ + D3DFVFCAPS_PSIZE; + + pCaps->TextureOpCaps = D3DTEXOPCAPS_DISABLE | + D3DTEXOPCAPS_SELECTARG1 | + D3DTEXOPCAPS_SELECTARG2 | + D3DTEXOPCAPS_MODULATE | + D3DTEXOPCAPS_MODULATE2X | + D3DTEXOPCAPS_MODULATE4X | + D3DTEXOPCAPS_ADD | + D3DTEXOPCAPS_ADDSIGNED | + D3DTEXOPCAPS_ADDSIGNED2X | + D3DTEXOPCAPS_SUBTRACT | + D3DTEXOPCAPS_ADDSMOOTH | + D3DTEXOPCAPS_BLENDDIFFUSEALPHA | + D3DTEXOPCAPS_BLENDTEXTUREALPHA | + D3DTEXOPCAPS_BLENDFACTORALPHA | + D3DTEXOPCAPS_BLENDTEXTUREALPHAPM | + D3DTEXOPCAPS_BLENDCURRENTALPHA | + D3DTEXOPCAPS_PREMODULATE | + D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR | + D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA | + D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR | + D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA | + D3DTEXOPCAPS_BUMPENVMAP | + D3DTEXOPCAPS_BUMPENVMAPLUMINANCE | + D3DTEXOPCAPS_DOTPRODUCT3 | + D3DTEXOPCAPS_MULTIPLYADD | + D3DTEXOPCAPS_LERP; + + pCaps->MaxTextureBlendStages = 8; /* XXX wine */ + (DWORD)screen->get_param(screen, PIPE_CAP_BLEND_EQUATION_SEPARATE); + pCaps->MaxSimultaneousTextures = 8; + + pCaps->VertexProcessingCaps = D3DVTXPCAPS_TEXGEN | + D3DVTXPCAPS_TEXGEN_SPHEREMAP | + D3DVTXPCAPS_MATERIALSOURCE7 | + D3DVTXPCAPS_DIRECTIONALLIGHTS | + D3DVTXPCAPS_POSITIONALLIGHTS | + D3DVTXPCAPS_LOCALVIEWER | + D3DVTXPCAPS_TWEENING | + /*D3DVTXPCAPS_NO_TEXGEN_NONLOCALVIEWER*/0; + + pCaps->MaxActiveLights = NINE_MAX_LIGHTS_ACTIVE; /* like GL_LIGHTi */ + pCaps->MaxUserClipPlanes = PIPE_MAX_CLIP_PLANES; + pCaps->MaxVertexBlendMatrices = 4; /* 1 vec4 BLENDWEIGHT/INDICES input */ + pCaps->MaxVertexBlendMatrixIndex = 8; /* D3DTS_WORLDMATRIX(0..8) */ + + pCaps->MaxPointSize = screen->get_paramf(screen, PIPE_CAPF_MAX_POINT_WIDTH); + + pCaps->MaxPrimitiveCount = 0x555555; /* <- wine, really 0xFFFFFFFF; */ + pCaps->MaxVertexIndex = 0xFFFFFF; /* <- wine, really 0xFFFFFFFF */ + pCaps->MaxStreams = + _min(screen->get_shader_param(screen, + PIPE_SHADER_VERTEX, PIPE_SHADER_CAP_MAX_INPUTS), + 16); + + pCaps->MaxStreamStride = screen->get_param(screen, + PIPE_CAP_MAX_VERTEX_ATTRIB_STRIDE); + + pCaps->VertexShaderVersion = D3DVS_VERSION(3,0); + + /* VS 2 as well as 3.0 supports a minimum of 256 consts. + * Wine and d3d9 drivers for dx1x hw advertise 256. Just as them, + * advertise 256. Problem is with hw that can only do 256, because + * we need take a few slots for boolean and integer constants. For these + * we'll have to fail later if they use complex shaders. */ + pCaps->MaxVertexShaderConst = NINE_MAX_CONST_F; + + pCaps->PixelShaderVersion = D3DPS_VERSION(3,0); + /* Value for GeForce 9600 GT */ + pCaps->PixelShader1xMaxValue = 65504.f; + + pCaps->DevCaps2 = D3DDEVCAPS2_STREAMOFFSET | + D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET | + D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES | + /*D3DDEVCAPS2_DMAPNPATCH |*/ + /*D3DDEVCAPS2_ADAPTIVETESSRTPATCH |*/ + /*D3DDEVCAPS2_ADAPTIVETESSNPATCH |*/ + /*D3DDEVCAPS2_PRESAMPLEDDMAPNPATCH*/0; + + pCaps->MasterAdapterOrdinal = 0; + pCaps->AdapterOrdinalInGroup = 0; + pCaps->NumberOfAdaptersInGroup = 1; + + /* Undocumented ? */ + pCaps->MaxNpatchTessellationLevel = 0.0f; + pCaps->Reserved5 = 0; + + /* XXX: use is_format_supported */ + pCaps->DeclTypes = D3DDTCAPS_UBYTE4 | + D3DDTCAPS_UBYTE4N | + D3DDTCAPS_SHORT2N | + D3DDTCAPS_SHORT4N | + D3DDTCAPS_USHORT2N | + D3DDTCAPS_USHORT4N | + D3DDTCAPS_UDEC3 | + D3DDTCAPS_DEC3N | + D3DDTCAPS_FLOAT16_2 | + D3DDTCAPS_FLOAT16_4; + + pCaps->NumSimultaneousRTs = + screen->get_param(screen, PIPE_CAP_MAX_RENDER_TARGETS); + if (pCaps->NumSimultaneousRTs > NINE_MAX_SIMULTANEOUS_RENDERTARGETS) + pCaps->NumSimultaneousRTs = NINE_MAX_SIMULTANEOUS_RENDERTARGETS; + + pCaps->StretchRectFilterCaps = D3DPTFILTERCAPS_MINFPOINT | + D3DPTFILTERCAPS_MINFLINEAR | + D3DPTFILTERCAPS_MAGFPOINT | + D3DPTFILTERCAPS_MAGFLINEAR; + + + pCaps->VS20Caps.Caps = D3DVS20CAPS_PREDICATION; + pCaps->VS20Caps.DynamicFlowControlDepth = /* XXX is this dynamic ? */ + screen->get_shader_param(screen, PIPE_SHADER_VERTEX, + PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH); + pCaps->VS20Caps.NumTemps = + screen->get_shader_param(screen, PIPE_SHADER_VERTEX, + PIPE_SHADER_CAP_MAX_TEMPS); + pCaps->VS20Caps.StaticFlowControlDepth = /* XXX is this static ? */ + screen->get_shader_param(screen, PIPE_SHADER_VERTEX, + PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH); + + /* also check for values < 0, because get_shader_param may return unsigned */ + if (pCaps->VS20Caps.DynamicFlowControlDepth > D3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH + || pCaps->VS20Caps.DynamicFlowControlDepth < 0) + pCaps->VS20Caps.DynamicFlowControlDepth = D3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; + if (pCaps->VS20Caps.StaticFlowControlDepth > D3DVS20_MAX_STATICFLOWCONTROLDEPTH + || pCaps->VS20Caps.StaticFlowControlDepth < 0) + pCaps->VS20Caps.StaticFlowControlDepth = D3DVS20_MAX_STATICFLOWCONTROLDEPTH; + if (pCaps->VS20Caps.NumTemps > D3DVS20_MAX_NUMTEMPS) + pCaps->VS20Caps.NumTemps = D3DVS20_MAX_NUMTEMPS; + assert(pCaps->VS20Caps.DynamicFlowControlDepth >= D3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH); + assert(pCaps->VS20Caps.StaticFlowControlDepth >= D3DVS20_MIN_STATICFLOWCONTROLDEPTH); + assert(pCaps->VS20Caps.NumTemps >= D3DVS20_MIN_NUMTEMPS); + + + pCaps->PS20Caps.Caps = D3DPS20CAPS_ARBITRARYSWIZZLE | + D3DPS20CAPS_GRADIENTINSTRUCTIONS | + D3DPS20CAPS_PREDICATION; + if (screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT, + PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS) == + screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT, + PIPE_SHADER_CAP_MAX_INSTRUCTIONS)) + pCaps->PS20Caps.Caps |= D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT; + if (screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT, + PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS) == + screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT, + PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS)) + pCaps->PS20Caps.Caps |= D3DPS20CAPS_NODEPENDENTREADLIMIT; + pCaps->PS20Caps.DynamicFlowControlDepth = /* XXX is this dynamic ? */ + screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT, + PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH); + pCaps->PS20Caps.NumTemps = + screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT, + PIPE_SHADER_CAP_MAX_TEMPS); + pCaps->PS20Caps.StaticFlowControlDepth = /* XXX is this static ? */ + screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT, + PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH); + pCaps->PS20Caps.NumInstructionSlots = + screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT, + PIPE_SHADER_CAP_MAX_INSTRUCTIONS); + + if (pCaps->PS20Caps.DynamicFlowControlDepth > D3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH + || pCaps->PS20Caps.DynamicFlowControlDepth < 0) + pCaps->PS20Caps.DynamicFlowControlDepth = D3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; + if (pCaps->PS20Caps.StaticFlowControlDepth > D3DPS20_MAX_STATICFLOWCONTROLDEPTH + || pCaps->PS20Caps.StaticFlowControlDepth < 0) + pCaps->PS20Caps.StaticFlowControlDepth = D3DPS20_MAX_STATICFLOWCONTROLDEPTH; + if (pCaps->PS20Caps.NumTemps > D3DPS20_MAX_NUMTEMPS) + pCaps->PS20Caps.NumTemps = D3DPS20_MAX_NUMTEMPS; + if (pCaps->PS20Caps.NumInstructionSlots > D3DPS20_MAX_NUMINSTRUCTIONSLOTS) + pCaps->PS20Caps.NumInstructionSlots = D3DPS20_MAX_NUMINSTRUCTIONSLOTS; + assert(pCaps->PS20Caps.DynamicFlowControlDepth >= D3DPS20_MIN_DYNAMICFLOWCONTROLDEPTH); + assert(pCaps->PS20Caps.StaticFlowControlDepth >= D3DPS20_MIN_STATICFLOWCONTROLDEPTH); + assert(pCaps->PS20Caps.NumTemps >= D3DPS20_MIN_NUMTEMPS); + assert(pCaps->PS20Caps.NumInstructionSlots >= D3DPS20_MIN_NUMINSTRUCTIONSLOTS); + + + if (screen->get_shader_param(screen, PIPE_SHADER_VERTEX, + PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS)) + pCaps->VertexTextureFilterCaps = pCaps->TextureFilterCaps & + ~(D3DPTFILTERCAPS_MIPFPOINT | + D3DPTFILTERCAPS_MIPFPOINT); /* XXX */ + else + pCaps->VertexTextureFilterCaps = 0; + + pCaps->MaxVertexShader30InstructionSlots = + screen->get_shader_param(screen, PIPE_SHADER_VERTEX, + PIPE_SHADER_CAP_MAX_INSTRUCTIONS); + pCaps->MaxPixelShader30InstructionSlots = + screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT, + PIPE_SHADER_CAP_MAX_INSTRUCTIONS); + if (pCaps->MaxVertexShader30InstructionSlots > D3DMAX30SHADERINSTRUCTIONS) + pCaps->MaxVertexShader30InstructionSlots = D3DMAX30SHADERINSTRUCTIONS; + if (pCaps->MaxPixelShader30InstructionSlots > D3DMAX30SHADERINSTRUCTIONS) + pCaps->MaxPixelShader30InstructionSlots = D3DMAX30SHADERINSTRUCTIONS; + assert(pCaps->MaxVertexShader30InstructionSlots >= D3DMIN30SHADERINSTRUCTIONS); + assert(pCaps->MaxPixelShader30InstructionSlots >= D3DMIN30SHADERINSTRUCTIONS); + + /* 65535 is required, advertise more for GPUs with >= 2048 instruction slots */ + pCaps->MaxVShaderInstructionsExecuted = MAX2(65535, pCaps->MaxVertexShader30InstructionSlots * 32); + pCaps->MaxPShaderInstructionsExecuted = MAX2(65535, pCaps->MaxPixelShader30InstructionSlots * 32); + + if (debug_get_bool_option("NINE_DUMP_CAPS", FALSE)) + nine_dump_D3DCAPS9(DBG_CHANNEL, pCaps); + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineAdapter9_CreateDevice( struct NineAdapter9 *This, + UINT RealAdapter, + D3DDEVTYPE DeviceType, + HWND hFocusWindow, + DWORD BehaviorFlags, + D3DPRESENT_PARAMETERS *pPresentationParameters, + IDirect3D9 *pD3D9, + ID3DPresentGroup *pPresentationGroup, + IDirect3DDevice9 **ppReturnedDeviceInterface ) +{ + struct pipe_screen *screen; + D3DDEVICE_CREATION_PARAMETERS params; + D3DCAPS9 caps; + int major, minor; + HRESULT hr; + + DBG("This=%p RealAdapter=%u DeviceType=%s hFocusWindow=%p " + "BehaviourFlags=%x " "pD3D9=%p pPresentationGroup=%p " + "ppReturnedDeviceInterface=%p\n", This, + RealAdapter, nine_D3DDEVTYPE_to_str(DeviceType), hFocusWindow, + BehaviorFlags, pD3D9, pPresentationGroup, ppReturnedDeviceInterface); + + ID3DPresentGroup_GetVersion(pPresentationGroup, &major, &minor); + if (major != 1) { + ERR("Doesn't support the ID3DPresentGroup version %d %d. Expected 1\n", + major, minor); + return D3DERR_NOTAVAILABLE; + } + + hr = NineAdapter9_GetScreen(This, DeviceType, &screen); + if (FAILED(hr)) { + DBG("Failed to get pipe_screen.\n"); + return hr; + } + + hr = NineAdapter9_GetDeviceCaps(This, DeviceType, &caps); + if (FAILED(hr)) { + DBG("Failed to get device caps.\n"); + return hr; + } + + params.AdapterOrdinal = RealAdapter; + params.DeviceType = DeviceType; + params.hFocusWindow = hFocusWindow; + params.BehaviorFlags = BehaviorFlags; + + hr = NineDevice9_new(screen, ¶ms, &caps, pPresentationParameters, + pD3D9, pPresentationGroup, This->ctx, FALSE, NULL, + (struct NineDevice9 **)ppReturnedDeviceInterface, + minor); + if (FAILED(hr)) { + DBG("Failed to create device.\n"); + return hr; + } + DBG("NineDevice9 created successfully.\n"); + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineAdapter9_CreateDeviceEx( struct NineAdapter9 *This, + UINT RealAdapter, + D3DDEVTYPE DeviceType, + HWND hFocusWindow, + DWORD BehaviorFlags, + D3DPRESENT_PARAMETERS *pPresentationParameters, + D3DDISPLAYMODEEX *pFullscreenDisplayMode, + IDirect3D9Ex *pD3D9Ex, + ID3DPresentGroup *pPresentationGroup, + IDirect3DDevice9Ex **ppReturnedDeviceInterface ) +{ + struct pipe_screen *screen; + D3DDEVICE_CREATION_PARAMETERS params; + D3DCAPS9 caps; + int major, minor; + HRESULT hr; + + DBG("This=%p RealAdapter=%u DeviceType=%s hFocusWindow=%p " + "BehaviourFlags=%x " "pD3D9Ex=%p pPresentationGroup=%p " + "ppReturnedDeviceInterface=%p\n", This, + RealAdapter, nine_D3DDEVTYPE_to_str(DeviceType), hFocusWindow, + BehaviorFlags, pD3D9Ex, pPresentationGroup, ppReturnedDeviceInterface); + + ID3DPresentGroup_GetVersion(pPresentationGroup, &major, &minor); + if (major != 1) { + ERR("Doesn't support the ID3DPresentGroup version %d %d. Expected 1\n", + major, minor); + return D3DERR_NOTAVAILABLE; + } + + hr = NineAdapter9_GetScreen(This, DeviceType, &screen); + if (FAILED(hr)) { + DBG("Failed to get pipe_screen.\n"); + return hr; + } + + hr = NineAdapter9_GetDeviceCaps(This, DeviceType, &caps); + if (FAILED(hr)) { + DBG("Failed to get device caps.\n"); + return hr; + } + + params.AdapterOrdinal = RealAdapter; + params.DeviceType = DeviceType; + params.hFocusWindow = hFocusWindow; + params.BehaviorFlags = BehaviorFlags; + + hr = NineDevice9Ex_new(screen, ¶ms, &caps, pPresentationParameters, + pFullscreenDisplayMode, + pD3D9Ex, pPresentationGroup, This->ctx, + (struct NineDevice9Ex **)ppReturnedDeviceInterface, + minor); + if (FAILED(hr)) { + DBG("Failed to create device.\n"); + return hr; + } + DBG("NineDevice9Ex created successfully.\n"); + + return D3D_OK; +} + +ID3DAdapter9Vtbl NineAdapter9_vtable = { + (void *)NineUnknown_QueryInterface, + (void *)NineUnknown_AddRef, + (void *)NineUnknown_Release, + (void *)NineAdapter9_GetAdapterIdentifier, + (void *)NineAdapter9_CheckDeviceType, + (void *)NineAdapter9_CheckDeviceFormat, + (void *)NineAdapter9_CheckDeviceMultiSampleType, + (void *)NineAdapter9_CheckDepthStencilMatch, + (void *)NineAdapter9_CheckDeviceFormatConversion, + (void *)NineAdapter9_GetDeviceCaps, + (void *)NineAdapter9_CreateDevice, + (void *)NineAdapter9_CreateDeviceEx +}; + +static const GUID *NineAdapter9_IIDs[] = { + &IID_ID3D9Adapter, + &IID_IUnknown, + NULL +}; + +HRESULT +NineAdapter9_new( struct d3dadapter9_context *pCTX, + struct NineAdapter9 **ppOut ) +{ + NINE_NEW(Adapter9, ppOut, FALSE, /* args */ pCTX); +} diff --git a/src/gallium/frontends/nine/adapter9.h b/src/gallium/frontends/nine/adapter9.h new file mode 100644 index 00000000000..605444cbc8d --- /dev/null +++ b/src/gallium/frontends/nine/adapter9.h @@ -0,0 +1,144 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _NINE_ADAPTER9_H_ +#define _NINE_ADAPTER9_H_ + +#include "iunknown.h" + +#include "d3dadapter/d3dadapter9.h" + +struct pipe_screen; +struct pipe_resource; + +struct d3dadapter9_context +{ + struct pipe_screen *hal, *ref; + D3DADAPTER_IDENTIFIER9 identifier; + BOOL linear_framebuffer; + BOOL throttling; + int throttling_value; + int vblank_mode; + BOOL thread_submit; + BOOL discard_delayed_release; + BOOL tearfree_discard; + int csmt_force; + BOOL dynamic_texture_workaround; + BOOL shader_inline_constants; + + void (*destroy)( struct d3dadapter9_context *ctx ); +}; + +struct NineAdapter9 +{ + struct NineUnknown base; + + struct d3dadapter9_context *ctx; +}; +static inline struct NineAdapter9 * +NineAdapter9( void *data ) +{ + return (struct NineAdapter9 *)data; +} + +HRESULT +NineAdapter9_new( struct d3dadapter9_context *pCTX, + struct NineAdapter9 **ppOut ); + +HRESULT +NineAdapter9_ctor( struct NineAdapter9 *This, + struct NineUnknownParams *pParams, + struct d3dadapter9_context *pCTX ); + +void +NineAdapter9_dtor( struct NineAdapter9 *This ); + +HRESULT NINE_WINAPI +NineAdapter9_GetAdapterIdentifier( struct NineAdapter9 *This, + DWORD Flags, + D3DADAPTER_IDENTIFIER9 *pIdentifier ); + +HRESULT NINE_WINAPI +NineAdapter9_CheckDeviceType( struct NineAdapter9 *This, + D3DDEVTYPE DevType, + D3DFORMAT AdapterFormat, + D3DFORMAT BackBufferFormat, + BOOL bWindowed ); + +HRESULT NINE_WINAPI +NineAdapter9_CheckDeviceFormat( struct NineAdapter9 *This, + D3DDEVTYPE DeviceType, + D3DFORMAT AdapterFormat, + DWORD Usage, + D3DRESOURCETYPE RType, + D3DFORMAT CheckFormat ); + +HRESULT NINE_WINAPI +NineAdapter9_CheckDeviceMultiSampleType( struct NineAdapter9 *This, + D3DDEVTYPE DeviceType, + D3DFORMAT SurfaceFormat, + BOOL Windowed, + D3DMULTISAMPLE_TYPE MultiSampleType, + DWORD *pQualityLevels ); + +HRESULT NINE_WINAPI +NineAdapter9_CheckDepthStencilMatch( struct NineAdapter9 *This, + D3DDEVTYPE DeviceType, + D3DFORMAT AdapterFormat, + D3DFORMAT RenderTargetFormat, + D3DFORMAT DepthStencilFormat ); + +HRESULT NINE_WINAPI +NineAdapter9_CheckDeviceFormatConversion( struct NineAdapter9 *This, + D3DDEVTYPE DeviceType, + D3DFORMAT SourceFormat, + D3DFORMAT TargetFormat ); + +HRESULT NINE_WINAPI +NineAdapter9_GetDeviceCaps( struct NineAdapter9 *This, + D3DDEVTYPE DeviceType, + D3DCAPS9 *pCaps ); + +HRESULT NINE_WINAPI +NineAdapter9_CreateDevice( struct NineAdapter9 *This, + UINT RealAdapter, + D3DDEVTYPE DeviceType, + HWND hFocusWindow, + DWORD BehaviorFlags, + D3DPRESENT_PARAMETERS *pPresentationParameters, + IDirect3D9 *pD3D9, + ID3DPresentGroup *pPresentationGroup, + IDirect3DDevice9 **ppReturnedDeviceInterface ); + +HRESULT NINE_WINAPI +NineAdapter9_CreateDeviceEx( struct NineAdapter9 *This, + UINT RealAdapter, + D3DDEVTYPE DeviceType, + HWND hFocusWindow, + DWORD BehaviorFlags, + D3DPRESENT_PARAMETERS *pPresentationParameters, + D3DDISPLAYMODEEX *pFullscreenDisplayMode, + IDirect3D9Ex *pD3D9Ex, + ID3DPresentGroup *pPresentationGroup, + IDirect3DDevice9Ex **ppReturnedDeviceInterface ); + +#endif /* _NINE_ADAPTER9_H_ */ diff --git a/src/gallium/frontends/nine/authenticatedchannel9.c b/src/gallium/frontends/nine/authenticatedchannel9.c new file mode 100644 index 00000000000..45fca3a2975 --- /dev/null +++ b/src/gallium/frontends/nine/authenticatedchannel9.c @@ -0,0 +1,78 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "authenticatedchannel9.h" + +#define DBG_CHANNEL DBG_AUTHENTICATEDCHANNEL + +HRESULT NINE_WINAPI +NineAuthenticatedChannel9_GetCertificateSize( struct NineAuthenticatedChannel9 *This, + UINT *pCertificateSize ) +{ + STUB(D3DERR_INVALIDCALL); +} + +HRESULT NINE_WINAPI +NineAuthenticatedChannel9_GetCertificate( struct NineAuthenticatedChannel9 *This, + UINT CertifacteSize, + BYTE *ppCertificate ) +{ + STUB(D3DERR_INVALIDCALL); +} + +HRESULT NINE_WINAPI +NineAuthenticatedChannel9_NegotiateKeyExchange( struct NineAuthenticatedChannel9 *This, + UINT DataSize, + void *pData ) +{ + STUB(D3DERR_INVALIDCALL); +} + +HRESULT NINE_WINAPI +NineAuthenticatedChannel9_Query( struct NineAuthenticatedChannel9 *This, + UINT InputSize, + const void *pInput, + UINT OutputSize, + void *pOutput ) +{ + STUB(D3DERR_INVALIDCALL); +} + +HRESULT NINE_WINAPI +NineAuthenticatedChannel9_Configure( struct NineAuthenticatedChannel9 *This, + UINT InputSize, + const void *pInput, + D3DAUTHENTICATEDCHANNEL_CONFIGURE_OUTPUT *pOutput ) +{ + STUB(D3DERR_INVALIDCALL); +} + +IDirect3DAuthenticatedChannel9Vtbl NineAuthenticatedChannel9_vtable = { + (void *)NineUnknown_QueryInterface, + (void *)NineUnknown_AddRef, + (void *)NineUnknown_Release, + (void *)NineAuthenticatedChannel9_GetCertificateSize, + (void *)NineAuthenticatedChannel9_GetCertificate, + (void *)NineAuthenticatedChannel9_NegotiateKeyExchange, + (void *)NineAuthenticatedChannel9_Query, + (void *)NineAuthenticatedChannel9_Configure +}; diff --git a/src/gallium/frontends/nine/authenticatedchannel9.h b/src/gallium/frontends/nine/authenticatedchannel9.h new file mode 100644 index 00000000000..b18848235c8 --- /dev/null +++ b/src/gallium/frontends/nine/authenticatedchannel9.h @@ -0,0 +1,65 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _NINE_AUTHENTICATEDCHANNEL9_H_ +#define _NINE_AUTHENTICATEDCHANNEL9_H_ + +#include "iunknown.h" + +struct NineAuthenticatedChannel9 +{ + struct NineUnknown base; +}; +static inline struct NineAuthenticatedChannel9 * +NineAuthenticatedChannel9( void *data ) +{ + return (struct NineAuthenticatedChannel9 *)data; +} + +HRESULT NINE_WINAPI +NineAuthenticatedChannel9_GetCertificateSize( struct NineAuthenticatedChannel9 *This, + UINT *pCertificateSize ); + +HRESULT NINE_WINAPI +NineAuthenticatedChannel9_GetCertificate( struct NineAuthenticatedChannel9 *This, + UINT CertifacteSize, + BYTE *ppCertificate ); + +HRESULT NINE_WINAPI +NineAuthenticatedChannel9_NegotiateKeyExchange( struct NineAuthenticatedChannel9 *This, + UINT DataSize, + void *pData ); + +HRESULT NINE_WINAPI +NineAuthenticatedChannel9_Query( struct NineAuthenticatedChannel9 *This, + UINT InputSize, + const void *pInput, + UINT OutputSize, + void *pOutput ); + +HRESULT NINE_WINAPI +NineAuthenticatedChannel9_Configure( struct NineAuthenticatedChannel9 *This, + UINT InputSize, + const void *pInput, + D3DAUTHENTICATEDCHANNEL_CONFIGURE_OUTPUT *pOutput ); + +#endif /* _NINE_AUTHENTICATEDCHANNEL9_H_ */ diff --git a/src/gallium/frontends/nine/basetexture9.c b/src/gallium/frontends/nine/basetexture9.c new file mode 100644 index 00000000000..c59bda5d295 --- /dev/null +++ b/src/gallium/frontends/nine/basetexture9.c @@ -0,0 +1,623 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "basetexture9.h" +#include "device9.h" + +/* For UploadSelf: */ +#include "texture9.h" +#include "cubetexture9.h" +#include "volumetexture9.h" + +#if defined(DEBUG) || !defined(NDEBUG) +#include "nine_pipe.h" +#include "nine_dump.h" +#endif + +#include "util/format/u_format.h" + +#define DBG_CHANNEL DBG_BASETEXTURE + +HRESULT +NineBaseTexture9_ctor( struct NineBaseTexture9 *This, + struct NineUnknownParams *pParams, + struct pipe_resource *initResource, + D3DRESOURCETYPE Type, + D3DFORMAT format, + D3DPOOL Pool, + DWORD Usage) +{ + BOOL alloc = (Pool == D3DPOOL_DEFAULT) && !initResource && + (format != D3DFMT_NULL); + HRESULT hr; + + DBG("This=%p, pParams=%p initResource=%p Type=%d format=%d Pool=%d Usage=%d\n", + This, pParams, initResource, Type, format, Pool, Usage); + + user_assert(!(Usage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL)) || + Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); + user_assert(!(Usage & D3DUSAGE_DYNAMIC) || + !(Pool == D3DPOOL_MANAGED || + Pool == D3DPOOL_SCRATCH), D3DERR_INVALIDCALL); + + hr = NineResource9_ctor(&This->base, pParams, initResource, alloc, Type, Pool, Usage); + if (FAILED(hr)) + return hr; + + This->format = format; + This->mipfilter = (Usage & D3DUSAGE_AUTOGENMIPMAP) ? + D3DTEXF_LINEAR : D3DTEXF_NONE; + This->managed.lod = 0; + This->managed.lod_resident = -1; + /* Mark the texture as dirty to trigger first upload when we need the texture, + * even if it wasn't set by the application */ + if (Pool == D3DPOOL_MANAGED) + This->managed.dirty = TRUE; + /* When a depth buffer is sampled, it is for shadow mapping, except for + * D3DFMT_INTZ, D3DFMT_DF16 and D3DFMT_DF24. + * In addition D3DFMT_INTZ can be used for both texturing and depth buffering + * if z write is disabled. This particular feature may not work for us in + * practice because OGL doesn't have that. However apparently it is known + * some cards have performance issues with this feature, so real apps + * shouldn't use it. */ + This->shadow = (This->format != D3DFMT_INTZ && This->format != D3DFMT_DF16 && + This->format != D3DFMT_DF24) && + util_format_has_depth(util_format_description(This->base.info.format)); + + list_inithead(&This->list); + list_inithead(&This->list2); + if (Pool == D3DPOOL_MANAGED) + list_add(&This->list2, &This->base.base.device->managed_textures); + + return D3D_OK; +} + +void +NineBaseTexture9_dtor( struct NineBaseTexture9 *This ) +{ + DBG("This=%p\n", This); + + pipe_sampler_view_reference(&This->view[0], NULL); + pipe_sampler_view_reference(&This->view[1], NULL); + + if (This->list.prev != NULL && This->list.next != NULL) + list_del(&This->list); + if (This->list2.prev != NULL && This->list2.next != NULL) + list_del(&This->list2); + + NineResource9_dtor(&This->base); +} + +DWORD NINE_WINAPI +NineBaseTexture9_SetLOD( struct NineBaseTexture9 *This, + DWORD LODNew ) +{ + DWORD old = This->managed.lod; + DWORD max_level; + + DBG("This=%p LODNew=%d\n", This, LODNew); + + user_assert(This->base.pool == D3DPOOL_MANAGED, 0); + + max_level = (This->base.usage & D3DUSAGE_AUTOGENMIPMAP) ? + 0 : This->base.info.last_level; + This->managed.lod = MIN2(LODNew, max_level); + + if (This->managed.lod != old && This->bind_count && list_is_empty(&This->list)) + list_add(&This->list, &This->base.base.device->update_textures); + + return old; +} + +DWORD NINE_WINAPI +NineBaseTexture9_GetLOD( struct NineBaseTexture9 *This ) +{ + DBG("This=%p\n", This); + + return This->managed.lod; +} + +DWORD NINE_WINAPI +NineBaseTexture9_GetLevelCount( struct NineBaseTexture9 *This ) +{ + DBG("This=%p\n", This); + + if (This->base.usage & D3DUSAGE_AUTOGENMIPMAP) + return 1; + return This->base.info.last_level + 1; +} + +HRESULT NINE_WINAPI +NineBaseTexture9_SetAutoGenFilterType( struct NineBaseTexture9 *This, + D3DTEXTUREFILTERTYPE FilterType ) +{ + DBG("This=%p FilterType=%d\n", This, FilterType); + + if (!(This->base.usage & D3DUSAGE_AUTOGENMIPMAP)) + return D3D_OK; + user_assert(FilterType != D3DTEXF_NONE, D3DERR_INVALIDCALL); + + This->mipfilter = FilterType; + This->dirty_mip = TRUE; + NineBaseTexture9_GenerateMipSubLevels(This); + + return D3D_OK; +} + +D3DTEXTUREFILTERTYPE NINE_WINAPI +NineBaseTexture9_GetAutoGenFilterType( struct NineBaseTexture9 *This ) +{ + DBG("This=%p\n", This); + + return This->mipfilter; +} + +HRESULT +NineBaseTexture9_UploadSelf( struct NineBaseTexture9 *This ) +{ + HRESULT hr; + unsigned last_level = This->base.info.last_level; + unsigned l, min_level_dirty = This->managed.lod; + BOOL update_lod; + + DBG("This=%p dirty=%i type=%s\n", This, This->managed.dirty, + nine_D3DRTYPE_to_str(This->base.type)); + + assert(This->base.pool == D3DPOOL_MANAGED); + + if (This->base.usage & D3DUSAGE_AUTOGENMIPMAP) + last_level = 0; + + update_lod = This->managed.lod_resident != This->managed.lod; + if (!update_lod && !This->managed.dirty) + return D3D_OK; + + /* Allocate a new resource with the correct number of levels, + * Mark states for update, and tell the nine surfaces/volumes + * their new resource. */ + if (update_lod) { + struct pipe_resource *res; + + DBG("updating LOD from %u to %u ...\n", This->managed.lod_resident, This->managed.lod); + + pipe_sampler_view_reference(&This->view[0], NULL); + pipe_sampler_view_reference(&This->view[1], NULL); + + /* Allocate a new resource */ + hr = NineBaseTexture9_CreatePipeResource(This, This->managed.lod_resident != -1); + if (FAILED(hr)) + return hr; + res = This->base.resource; + + if (This->managed.lod_resident == -1) {/* no levels were resident */ + This->managed.dirty = FALSE; /* We are going to upload everything. */ + This->managed.lod_resident = This->base.info.last_level + 1; + } + + if (This->base.type == D3DRTYPE_TEXTURE) { + struct NineTexture9 *tex = NineTexture9(This); + + /* last content (if apply) has been copied to the new resource. + * Note: We cannot render to surfaces of managed textures. + * Note2: the level argument passed is to get the level offset + * right when the texture is uploaded (the texture first level + * corresponds to This->managed.lod). + * Note3: We don't care about the value passed for the surfaces + * before This->managed.lod, negative with this implementation. */ + for (l = 0; l <= This->base.info.last_level; ++l) + NineSurface9_SetResource(tex->surfaces[l], res, l - This->managed.lod); + } else + if (This->base.type == D3DRTYPE_CUBETEXTURE) { + struct NineCubeTexture9 *tex = NineCubeTexture9(This); + unsigned z; + + for (l = 0; l <= This->base.info.last_level; ++l) { + for (z = 0; z < 6; ++z) + NineSurface9_SetResource(tex->surfaces[l * 6 + z], + res, l - This->managed.lod); + } + } else + if (This->base.type == D3DRTYPE_VOLUMETEXTURE) { + struct NineVolumeTexture9 *tex = NineVolumeTexture9(This); + + for (l = 0; l <= This->base.info.last_level; ++l) + NineVolume9_SetResource(tex->volumes[l], res, l - This->managed.lod); + } else { + assert(!"invalid texture type"); + } + + /* We are going to fully upload the new levels, + * no need to update dirty parts of the texture for these */ + min_level_dirty = MAX2(This->managed.lod, This->managed.lod_resident); + } + + /* Update dirty parts of the texture */ + if (This->managed.dirty) { + if (This->base.type == D3DRTYPE_TEXTURE) { + struct NineTexture9 *tex = NineTexture9(This); + struct pipe_box box; + box.z = 0; + box.depth = 1; + + DBG("TEXTURE: dirty rect=(%u,%u) (%ux%u)\n", + tex->dirty_rect.x, tex->dirty_rect.y, + tex->dirty_rect.width, tex->dirty_rect.height); + + /* Note: for l < min_level_dirty, the resource is + * either non-existing (and thus will be entirely re-uploaded + * if the lod changes) or going to have a full upload */ + if (tex->dirty_rect.width) { + for (l = min_level_dirty; l <= last_level; ++l) { + u_box_minify_2d(&box, &tex->dirty_rect, l); + NineSurface9_UploadSelf(tex->surfaces[l], &box); + } + memset(&tex->dirty_rect, 0, sizeof(tex->dirty_rect)); + tex->dirty_rect.depth = 1; + } + } else + if (This->base.type == D3DRTYPE_CUBETEXTURE) { + struct NineCubeTexture9 *tex = NineCubeTexture9(This); + unsigned z; + struct pipe_box box; + box.z = 0; + box.depth = 1; + + for (z = 0; z < 6; ++z) { + DBG("FACE[%u]: dirty rect=(%u,%u) (%ux%u)\n", z, + tex->dirty_rect[z].x, tex->dirty_rect[z].y, + tex->dirty_rect[z].width, tex->dirty_rect[z].height); + + if (tex->dirty_rect[z].width) { + for (l = min_level_dirty; l <= last_level; ++l) { + u_box_minify_2d(&box, &tex->dirty_rect[z], l); + NineSurface9_UploadSelf(tex->surfaces[l * 6 + z], &box); + } + memset(&tex->dirty_rect[z], 0, sizeof(tex->dirty_rect[z])); + tex->dirty_rect[z].depth = 1; + } + } + } else + if (This->base.type == D3DRTYPE_VOLUMETEXTURE) { + struct NineVolumeTexture9 *tex = NineVolumeTexture9(This); + struct pipe_box box; + + DBG("VOLUME: dirty_box=(%u,%u,%u) (%ux%ux%u)\n", + tex->dirty_box.x, tex->dirty_box.y, tex->dirty_box.y, + tex->dirty_box.width, tex->dirty_box.height, tex->dirty_box.depth); + + if (tex->dirty_box.width) { + for (l = min_level_dirty; l <= last_level; ++l) { + u_box_minify_3d(&box, &tex->dirty_box, l); + NineVolume9_UploadSelf(tex->volumes[l], &box); + } + memset(&tex->dirty_box, 0, sizeof(tex->dirty_box)); + } + } else { + assert(!"invalid texture type"); + } + This->managed.dirty = FALSE; + } + + /* Upload the new levels */ + if (update_lod) { + if (This->base.type == D3DRTYPE_TEXTURE) { + struct NineTexture9 *tex = NineTexture9(This); + struct pipe_box box; + + box.x = box.y = box.z = 0; + box.depth = 1; + for (l = This->managed.lod; l < This->managed.lod_resident; ++l) { + box.width = u_minify(This->base.info.width0, l); + box.height = u_minify(This->base.info.height0, l); + NineSurface9_UploadSelf(tex->surfaces[l], &box); + } + } else + if (This->base.type == D3DRTYPE_CUBETEXTURE) { + struct NineCubeTexture9 *tex = NineCubeTexture9(This); + struct pipe_box box; + unsigned z; + + box.x = box.y = box.z = 0; + box.depth = 1; + for (l = This->managed.lod; l < This->managed.lod_resident; ++l) { + box.width = u_minify(This->base.info.width0, l); + box.height = u_minify(This->base.info.height0, l); + for (z = 0; z < 6; ++z) + NineSurface9_UploadSelf(tex->surfaces[l * 6 + z], &box); + } + } else + if (This->base.type == D3DRTYPE_VOLUMETEXTURE) { + struct NineVolumeTexture9 *tex = NineVolumeTexture9(This); + struct pipe_box box; + + box.x = box.y = box.z = 0; + for (l = This->managed.lod; l < This->managed.lod_resident; ++l) { + box.width = u_minify(This->base.info.width0, l); + box.height = u_minify(This->base.info.height0, l); + box.depth = u_minify(This->base.info.depth0, l); + NineVolume9_UploadSelf(tex->volumes[l], &box); + } + } else { + assert(!"invalid texture type"); + } + + This->managed.lod_resident = This->managed.lod; + } + + if (This->base.usage & D3DUSAGE_AUTOGENMIPMAP) + This->dirty_mip = TRUE; + + /* Set again the textures currently bound to update the texture data */ + if (This->bind_count) { + struct nine_state *state = &This->base.base.device->state; + unsigned s; + for (s = 0; s < NINE_MAX_SAMPLERS; ++s) + /* Dirty tracking is done in device9 state, not nine_context. */ + if (state->texture[s] == This) + nine_context_set_texture(This->base.base.device, s, This); + } + + DBG("DONE, generate mip maps = %i\n", This->dirty_mip); + return D3D_OK; +} + +void NINE_WINAPI +NineBaseTexture9_GenerateMipSubLevels( struct NineBaseTexture9 *This ) +{ + unsigned base_level = 0; + unsigned last_level = This->base.info.last_level - This->managed.lod; + unsigned first_layer = 0; + unsigned last_layer; + unsigned filter = This->mipfilter == D3DTEXF_POINT ? PIPE_TEX_FILTER_NEAREST + : PIPE_TEX_FILTER_LINEAR; + DBG("This=%p\n", This); + + if (This->base.pool == D3DPOOL_MANAGED) + NineBaseTexture9_UploadSelf(This); + if (!This->dirty_mip) + return; + if (This->managed.lod) { + ERR("AUTOGENMIPMAP if level 0 is not resident not supported yet !\n"); + return; + } + + if (!This->view[0]) + NineBaseTexture9_UpdateSamplerView(This, 0); + + last_layer = util_max_layer(This->view[0]->texture, base_level); + + nine_context_gen_mipmap(This->base.base.device, (struct NineUnknown *)This, + This->base.resource, + base_level, last_level, + first_layer, last_layer, filter); + + This->dirty_mip = FALSE; +} + +HRESULT +NineBaseTexture9_CreatePipeResource( struct NineBaseTexture9 *This, + BOOL CopyData ) +{ + struct pipe_context *pipe; + struct pipe_screen *screen = This->base.info.screen; + struct pipe_resource templ; + unsigned l, m; + struct pipe_resource *res; + struct pipe_resource *old = This->base.resource; + + DBG("This=%p lod=%u last_level=%u\n", This, + This->managed.lod, This->base.info.last_level); + + assert(This->base.pool == D3DPOOL_MANAGED); + + templ = This->base.info; + + if (This->managed.lod) { + templ.width0 = u_minify(templ.width0, This->managed.lod); + templ.height0 = u_minify(templ.height0, This->managed.lod); + templ.depth0 = u_minify(templ.depth0, This->managed.lod); + } + templ.last_level = This->base.info.last_level - This->managed.lod; + + if (old) { + /* LOD might have changed. */ + if (old->width0 == templ.width0 && + old->height0 == templ.height0 && + old->depth0 == templ.depth0) + return D3D_OK; + } + + res = screen->resource_create(screen, &templ); + if (!res) + return D3DERR_OUTOFVIDEOMEMORY; + This->base.resource = res; + + if (old && CopyData) { /* Don't return without releasing old ! */ + struct pipe_box box; + box.x = 0; + box.y = 0; + box.z = 0; + + l = (This->managed.lod < This->managed.lod_resident) ? This->managed.lod_resident - This->managed.lod : 0; + m = (This->managed.lod < This->managed.lod_resident) ? 0 : This->managed.lod - This->managed.lod_resident; + + box.width = u_minify(templ.width0, l); + box.height = u_minify(templ.height0, l); + box.depth = u_minify(templ.depth0, l); + + pipe = nine_context_get_pipe_acquire(This->base.base.device); + + for (; l <= templ.last_level; ++l, ++m) { + pipe->resource_copy_region(pipe, + res, l, 0, 0, 0, + old, m, &box); + box.width = u_minify(box.width, 1); + box.height = u_minify(box.height, 1); + box.depth = u_minify(box.depth, 1); + } + + nine_context_get_pipe_release(This->base.base.device); + } + pipe_resource_reference(&old, NULL); + + return D3D_OK; +} + +#define SWIZZLE_TO_REPLACE(s) (s == PIPE_SWIZZLE_0 || \ + s == PIPE_SWIZZLE_1 || \ + s == PIPE_SWIZZLE_NONE) + +HRESULT +NineBaseTexture9_UpdateSamplerView( struct NineBaseTexture9 *This, + const int sRGB ) +{ + const struct util_format_description *desc; + struct pipe_context *pipe; + struct pipe_screen *screen = NineDevice9_GetScreen(This->base.base.device); + struct pipe_resource *resource = This->base.resource; + struct pipe_sampler_view templ; + enum pipe_format srgb_format; + unsigned i; + uint8_t swizzle[4]; + + DBG("This=%p sRGB=%d\n", This, sRGB); + + if (unlikely(!resource)) { + if (unlikely(This->format == D3DFMT_NULL)) + return D3D_OK; + NineBaseTexture9_Dump(This); + } + assert(resource); + + pipe_sampler_view_reference(&This->view[sRGB], NULL); + + swizzle[0] = PIPE_SWIZZLE_X; + swizzle[1] = PIPE_SWIZZLE_Y; + swizzle[2] = PIPE_SWIZZLE_Z; + swizzle[3] = PIPE_SWIZZLE_W; + desc = util_format_description(resource->format); + if (desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) { + /* msdn doc is incomplete here and wrong. + * The only formats that can be read directly here + * are DF16, DF24 and INTZ. + * Tested on win the swizzle is + * R = depth, G = B = 0, A = 1 for DF16 and DF24 + * R = G = B = A = depth for INTZ + * For the other ZS formats that can't be read directly + * but can be used as shadow map, the result is duplicated on + * all channel */ + if (This->format == D3DFMT_DF16 || + This->format == D3DFMT_DF24) { + swizzle[1] = PIPE_SWIZZLE_0; + swizzle[2] = PIPE_SWIZZLE_0; + swizzle[3] = PIPE_SWIZZLE_1; + } else { + swizzle[1] = PIPE_SWIZZLE_X; + swizzle[2] = PIPE_SWIZZLE_X; + swizzle[3] = PIPE_SWIZZLE_X; + } + } else if (resource->format == PIPE_FORMAT_RGTC2_UNORM) { + swizzle[0] = PIPE_SWIZZLE_Y; + swizzle[1] = PIPE_SWIZZLE_X; + swizzle[2] = PIPE_SWIZZLE_1; + swizzle[3] = PIPE_SWIZZLE_1; + } else if (resource->format != PIPE_FORMAT_A8_UNORM && + resource->format != PIPE_FORMAT_RGTC1_UNORM) { + /* exceptions: + * A8 should have 0.0 as default values for RGB. + * ATI1/RGTC1 should be r 0 0 1 (tested on windows). + * It is already what gallium does. All the other ones + * should have 1.0 for non-defined values */ + for (i = 0; i < 4; i++) { + if (SWIZZLE_TO_REPLACE(desc->swizzle[i])) + swizzle[i] = PIPE_SWIZZLE_1; + } + } + + /* if requested and supported, convert to the sRGB format */ + srgb_format = util_format_srgb(resource->format); + if (sRGB && srgb_format != PIPE_FORMAT_NONE && + screen->is_format_supported(screen, srgb_format, + resource->target, 0, 0, resource->bind)) + templ.format = srgb_format; + else + templ.format = resource->format; + templ.u.tex.first_layer = 0; + templ.u.tex.last_layer = resource->target == PIPE_TEXTURE_3D ? + resource->depth0 - 1 : resource->array_size - 1; + templ.u.tex.first_level = 0; + templ.u.tex.last_level = resource->last_level; + templ.swizzle_r = swizzle[0]; + templ.swizzle_g = swizzle[1]; + templ.swizzle_b = swizzle[2]; + templ.swizzle_a = swizzle[3]; + templ.target = resource->target; + + pipe = nine_context_get_pipe_acquire(This->base.base.device); + This->view[sRGB] = pipe->create_sampler_view(pipe, resource, &templ); + nine_context_get_pipe_release(This->base.base.device); + + DBG("sampler view = %p(resource = %p)\n", This->view[sRGB], resource); + + return This->view ? D3D_OK : D3DERR_DRIVERINTERNALERROR; +} + +void NINE_WINAPI +NineBaseTexture9_PreLoad( struct NineBaseTexture9 *This ) +{ + DBG("This=%p\n", This); + + if (This->base.pool == D3DPOOL_MANAGED) + NineBaseTexture9_UploadSelf(This); +} + +void +NineBaseTexture9_UnLoad( struct NineBaseTexture9 *This ) +{ + if (This->base.pool != D3DPOOL_MANAGED || + This->managed.lod_resident == -1) + return; + + pipe_resource_reference(&This->base.resource, NULL); + This->managed.lod_resident = -1; + This->managed.dirty = TRUE; + + /* If the texture is bound, we have to re-upload it */ + BASETEX_REGISTER_UPDATE(This); +} + +#if defined(DEBUG) || !defined(NDEBUG) +void +NineBaseTexture9_Dump( struct NineBaseTexture9 *This ) +{ + DBG("\nNineBaseTexture9(%p->NULL/%p): Pool=%s Type=%s Usage=%s\n" + "Format=%s Dims=%ux%ux%u/%u LastLevel=%u Lod=%u(%u)\n", This, + This->base.resource, + nine_D3DPOOL_to_str(This->base.pool), + nine_D3DRTYPE_to_str(This->base.type), + nine_D3DUSAGE_to_str(This->base.usage), + d3dformat_to_string(This->format), + This->base.info.width0, This->base.info.height0, This->base.info.depth0, + This->base.info.array_size, This->base.info.last_level, + This->managed.lod, This->managed.lod_resident); +} +#endif /* DEBUG || !NDEBUG */ diff --git a/src/gallium/frontends/nine/basetexture9.h b/src/gallium/frontends/nine/basetexture9.h new file mode 100644 index 00000000000..70e8b934f56 --- /dev/null +++ b/src/gallium/frontends/nine/basetexture9.h @@ -0,0 +1,170 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _NINE_BASETEXTURE9_H_ +#define _NINE_BASETEXTURE9_H_ + +#include "device9.h" +#include "resource9.h" +#include "util/u_inlines.h" +#include "util/list.h" + +struct NineBaseTexture9 +{ + struct NineResource9 base; + struct list_head list; /* for update_textures */ + struct list_head list2; /* for managed_textures */ + + /* g3d */ + struct pipe_sampler_view *view[2]; /* linear and sRGB */ + + D3DFORMAT format; + + int16_t bind_count; /* to Device9->state.texture */ + + boolean shadow; + uint8_t pstype; /* 0: 2D, 1: 1D, 2: CUBE, 3: 3D */ + + boolean dirty_mip; + D3DTEXTUREFILTERTYPE mipfilter; + + /* Specific to managed textures */ + struct { + boolean dirty; + DWORD lod; + DWORD lod_resident; + } managed; +}; +static inline struct NineBaseTexture9 * +NineBaseTexture9( void *data ) +{ + return (struct NineBaseTexture9 *)data; +} + +HRESULT +NineBaseTexture9_ctor( struct NineBaseTexture9 *This, + struct NineUnknownParams *pParams, + struct pipe_resource *initResource, + D3DRESOURCETYPE Type, + D3DFORMAT format, + D3DPOOL Pool, + DWORD Usage); + +void +NineBaseTexture9_dtor( struct NineBaseTexture9 *This ); + +DWORD NINE_WINAPI +NineBaseTexture9_SetLOD( struct NineBaseTexture9 *This, + DWORD LODNew ); + +DWORD NINE_WINAPI +NineBaseTexture9_GetLOD( struct NineBaseTexture9 *This ); + +DWORD NINE_WINAPI +NineBaseTexture9_GetLevelCount( struct NineBaseTexture9 *This ); + +HRESULT NINE_WINAPI +NineBaseTexture9_SetAutoGenFilterType( struct NineBaseTexture9 *This, + D3DTEXTUREFILTERTYPE FilterType ); + +D3DTEXTUREFILTERTYPE NINE_WINAPI +NineBaseTexture9_GetAutoGenFilterType( struct NineBaseTexture9 *This ); + +void NINE_WINAPI +NineBaseTexture9_GenerateMipSubLevels( struct NineBaseTexture9 *This ); + +void NINE_WINAPI +NineBaseTexture9_PreLoad( struct NineBaseTexture9 *This ); + +void +NineBaseTexture9_UnLoad( struct NineBaseTexture9 *This ); + +/* For D3DPOOL_MANAGED only (after SetLOD change): */ +HRESULT +NineBaseTexture9_CreatePipeResource( struct NineBaseTexture9 *This, + BOOL CopyData ); + +/* For D3DPOOL_MANAGED only: */ +HRESULT +NineBaseTexture9_UploadSelf( struct NineBaseTexture9 *This ); + +HRESULT +NineBaseTexture9_UpdateSamplerView( struct NineBaseTexture9 *This, + const int sRGB ); + +static inline void +NineBaseTexture9_Validate( struct NineBaseTexture9 *This ) +{ + DBG_FLAG(DBG_BASETEXTURE, "This=%p dirty=%i dirty_mip=%i lod=%u/%u\n", + This, This->managed.dirty, This->dirty_mip, This->managed.lod, This->managed.lod_resident); + if ((This->base.pool == D3DPOOL_MANAGED) && + (This->managed.dirty || This->managed.lod != This->managed.lod_resident)) + NineBaseTexture9_UploadSelf(This); + if (This->dirty_mip) + NineBaseTexture9_GenerateMipSubLevels(This); +} + +static inline struct pipe_sampler_view * +NineBaseTexture9_GetSamplerView( struct NineBaseTexture9 *This, const int sRGB ) +{ + if (!This->view[sRGB]) + NineBaseTexture9_UpdateSamplerView(This, sRGB); + return This->view[sRGB]; +} + +static void inline +NineBindTextureToDevice( struct NineDevice9 *device, + struct NineBaseTexture9 **slot, + struct NineBaseTexture9 *tex ) +{ + struct NineBaseTexture9 *old = *slot; + + if (tex) { + if ((tex->managed.dirty | tex->dirty_mip) && list_is_empty(&tex->list)) + list_add(&tex->list, &device->update_textures); + + tex->bind_count++; + } + if (old) { + old->bind_count--; + if (!old->bind_count) + list_delinit(&old->list); + } + + nine_bind(slot, tex); +} + +#if defined(DEBUG) || !defined(NDEBUG) +void +NineBaseTexture9_Dump( struct NineBaseTexture9 *This ); +#else +static inline void +NineBaseTexture9_Dump( struct NineBaseTexture9 *This ) { } +#endif + +#define BASETEX_REGISTER_UPDATE(t) do { \ + if (((t)->managed.dirty | ((t)->dirty_mip)) && (t)->bind_count) \ + if (list_is_empty(&(t)->list)) \ + list_add(&(t)->list, &(t)->base.base.device->update_textures); \ + } while(0) + +#endif /* _NINE_BASETEXTURE9_H_ */ diff --git a/src/gallium/frontends/nine/buffer9.c b/src/gallium/frontends/nine/buffer9.c new file mode 100644 index 00000000000..629f33731ce --- /dev/null +++ b/src/gallium/frontends/nine/buffer9.c @@ -0,0 +1,461 @@ +/* + * Copyright 2011 Joakim Sindholt + * Copyright 2015 Patrick Rudolph + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "buffer9.h" +#include "device9.h" +#include "nine_buffer_upload.h" +#include "nine_helpers.h" +#include "nine_pipe.h" + +#include "pipe/p_screen.h" +#include "pipe/p_context.h" +#include "pipe/p_state.h" +#include "pipe/p_defines.h" +#include "pipe/p_format.h" +#include "util/u_box.h" +#include "util/u_inlines.h" + +#define DBG_CHANNEL (DBG_INDEXBUFFER|DBG_VERTEXBUFFER) + +HRESULT +NineBuffer9_ctor( struct NineBuffer9 *This, + struct NineUnknownParams *pParams, + D3DRESOURCETYPE Type, + DWORD Usage, + UINT Size, + D3DPOOL Pool ) +{ + struct pipe_resource *info = &This->base.info; + HRESULT hr; + + DBG("This=%p Size=0x%x Usage=%x Pool=%u\n", This, Size, Usage, Pool); + + user_assert(Pool != D3DPOOL_SCRATCH, D3DERR_INVALIDCALL); + + This->maps = MALLOC(sizeof(struct NineTransfer)); + if (!This->maps) + return E_OUTOFMEMORY; + This->nmaps = 0; + This->maxmaps = 1; + This->size = Size; + + info->screen = pParams->device->screen; + info->target = PIPE_BUFFER; + info->format = PIPE_FORMAT_R8_UNORM; + info->width0 = Size; + info->flags = 0; + + /* Note: WRITEONLY is just tip for resource placement, the resource + * can still be read (but slower). */ + info->bind = PIPE_BIND_VERTEX_BUFFER; + + /* It is hard to find clear information on where to place the buffer in + * memory depending on the flag. + * MSDN: resources are static, except for those with DYNAMIC, thus why you + * can only use DISCARD on them. + * ATI doc: The driver has the liberty it wants for having things static + * or not. + * MANAGED: Ram + uploads to Vram copy at unlock (msdn and nvidia doc say + * at first draw call using the buffer) + * DEFAULT + Usage = 0 => System memory backing for easy read access + * (That doc is very unclear on the details, like whether some copies to + * vram copy are involved or not). + * DEFAULT + WRITEONLY => Vram + * DEFAULT + WRITEONLY + DYNAMIC => Either Vram buffer or GTT_WC, depending on what the driver wants. + */ + if (Pool == D3DPOOL_SYSTEMMEM) + info->usage = PIPE_USAGE_STAGING; + else if (Pool == D3DPOOL_MANAGED) + info->usage = PIPE_USAGE_DEFAULT; + else if (Usage & D3DUSAGE_DYNAMIC && Usage & D3DUSAGE_WRITEONLY) + info->usage = PIPE_USAGE_STREAM; + else if (Usage & D3DUSAGE_WRITEONLY) + info->usage = PIPE_USAGE_DEFAULT; + /* For the remaining two, PIPE_USAGE_STAGING would probably be + * a good fit according to the doc. However it seems rather a mistake + * from apps to use these (mistakes that do really happen). Try + * to put the flags that are the best compromise between the real + * behaviour and what buggy apps should get for better performance. */ + else if (Usage & D3DUSAGE_DYNAMIC) + info->usage = PIPE_USAGE_STREAM; + else + info->usage = PIPE_USAGE_DYNAMIC; + + /* When Writeonly is not set, we don't want to enable the + * optimizations */ + This->discard_nooverwrite_only = !!(Usage & D3DUSAGE_WRITEONLY) && + pParams->device->buffer_upload; + /* if (pDesc->Usage & D3DUSAGE_DONOTCLIP) { } */ + /* if (pDesc->Usage & D3DUSAGE_NONSECURE) { } */ + /* if (pDesc->Usage & D3DUSAGE_NPATCHES) { } */ + /* if (pDesc->Usage & D3DUSAGE_POINTS) { } */ + /* if (pDesc->Usage & D3DUSAGE_RTPATCHES) { } */ + /* The buffer must be usable with both sw and hw + * vertex processing. It is expected to be slower with hw. */ + if (Usage & D3DUSAGE_SOFTWAREPROCESSING) + info->usage = PIPE_USAGE_STAGING; + /* if (pDesc->Usage & D3DUSAGE_TEXTAPI) { } */ + + info->height0 = 1; + info->depth0 = 1; + info->array_size = 1; + info->last_level = 0; + info->nr_samples = 0; + info->nr_storage_samples = 0; + + hr = NineResource9_ctor(&This->base, pParams, NULL, TRUE, + Type, Pool, Usage); + + if (FAILED(hr)) + return hr; + + if (Pool == D3DPOOL_MANAGED) { + This->managed.data = align_calloc( + nine_format_get_level_alloc_size(This->base.info.format, + Size, 1, 0), 32); + if (!This->managed.data) + return E_OUTOFMEMORY; + memset(This->managed.data, 0, Size); + This->managed.dirty = TRUE; + u_box_1d(0, Size, &This->managed.dirty_box); + list_inithead(&This->managed.list); + list_inithead(&This->managed.list2); + list_add(&This->managed.list2, &pParams->device->managed_buffers); + } + + return D3D_OK; +} + +void +NineBuffer9_dtor( struct NineBuffer9 *This ) +{ + DBG("This=%p\n", This); + + if (This->maps) { + while (This->nmaps) { + NineBuffer9_Unlock(This); + } + FREE(This->maps); + } + + if (This->base.pool == D3DPOOL_MANAGED) { + if (This->managed.data) + align_free(This->managed.data); + if (This->managed.list.prev != NULL && This->managed.list.next != NULL) + list_del(&This->managed.list); + if (This->managed.list2.prev != NULL && This->managed.list2.next != NULL) + list_del(&This->managed.list2); + } + + if (This->buf) + nine_upload_release_buffer(This->base.base.device->buffer_upload, This->buf); + + NineResource9_dtor(&This->base); +} + +struct pipe_resource * +NineBuffer9_GetResource( struct NineBuffer9 *This, unsigned *offset ) +{ + if (This->buf) + return nine_upload_buffer_resource_and_offset(This->buf, offset); + *offset = 0; + return NineResource9_GetResource(&This->base); +} + +static void +NineBuffer9_RebindIfRequired( struct NineBuffer9 *This, + struct NineDevice9 *device ) +{ + int i; + + if (!This->bind_count) + return; + for (i = 0; i < device->caps.MaxStreams; i++) { + if (device->state.stream[i] == (struct NineVertexBuffer9 *)This) + nine_context_set_stream_source(device, i, + (struct NineVertexBuffer9 *)This, + device->state.vtxbuf[i].buffer_offset, + device->state.vtxbuf[i].stride); + } + if (device->state.idxbuf == (struct NineIndexBuffer9 *)This) + nine_context_set_indices(device, (struct NineIndexBuffer9 *)This); +} + +HRESULT NINE_WINAPI +NineBuffer9_Lock( struct NineBuffer9 *This, + UINT OffsetToLock, + UINT SizeToLock, + void **ppbData, + DWORD Flags ) +{ + struct NineDevice9 *device = This->base.base.device; + struct pipe_box box; + struct pipe_context *pipe; + void *data; + unsigned usage; + + DBG("This=%p(pipe=%p) OffsetToLock=0x%x, SizeToLock=0x%x, Flags=0x%x\n", + This, This->base.resource, + OffsetToLock, SizeToLock, Flags); + + user_assert(ppbData, E_POINTER); + user_assert(!(Flags & ~(D3DLOCK_DISCARD | + D3DLOCK_DONOTWAIT | + D3DLOCK_NO_DIRTY_UPDATE | + D3DLOCK_NOSYSLOCK | + D3DLOCK_READONLY | + D3DLOCK_NOOVERWRITE)), D3DERR_INVALIDCALL); + + if (SizeToLock == 0) { + SizeToLock = This->size - OffsetToLock; + user_warn(OffsetToLock != 0); + } + + /* Write out of bound seems to have to be taken into account for these. + * TODO: Do more tests (is it only at buffer first lock ? etc). + * Since these buffers are supposed to be locked once and never + * writen again (MANAGED or DYNAMIC is used for the other uses cases), + * performance should be unaffected. */ + if (!(This->base.usage & D3DUSAGE_DYNAMIC) && This->base.pool != D3DPOOL_MANAGED) + SizeToLock = This->size - OffsetToLock; + + u_box_1d(OffsetToLock, SizeToLock, &box); + + if (This->base.pool == D3DPOOL_MANAGED) { + /* READONLY doesn't dirty the buffer */ + /* Tests on Win: READONLY doesn't wait for the upload */ + if (!(Flags & D3DLOCK_READONLY)) { + if (!This->managed.dirty) { + assert(list_is_empty(&This->managed.list)); + This->managed.dirty = TRUE; + This->managed.dirty_box = box; + if (p_atomic_read(&This->managed.pending_upload)) + nine_csmt_process(This->base.base.device); + } else + u_box_union_2d(&This->managed.dirty_box, &This->managed.dirty_box, &box); + /* Tests trying to draw while the buffer is locked show that + * MANAGED buffers are made dirty at Lock time */ + BASEBUF_REGISTER_UPDATE(This); + } + *ppbData = (char *)This->managed.data + OffsetToLock; + DBG("returning pointer %p\n", *ppbData); + This->nmaps++; + return D3D_OK; + } + + /* Driver ddi doc: READONLY is never passed to the device. So it can only + * have effect on things handled by the driver (MANAGED pool for example). + * Msdn doc: DISCARD and NOOVERWRITE are only for DYNAMIC. + * ATI doc: You can use DISCARD and NOOVERWRITE without DYNAMIC. + * Msdn doc: D3DLOCK_DONOTWAIT is not among the valid flags for buffers. + * Our tests: On win 7 nvidia, D3DLOCK_DONOTWAIT does return + * D3DERR_WASSTILLDRAWING if the resource is in use, except for DYNAMIC. + * Our tests: some apps do use both DISCARD and NOOVERWRITE at the same + * time. On windows it seems to return different pointer, thus indicating + * DISCARD is taken into account. + * Our tests: SYSTEMMEM doesn't DISCARD */ + + if (This->base.pool == D3DPOOL_SYSTEMMEM) + Flags &= ~(D3DLOCK_DISCARD | D3DLOCK_NOOVERWRITE); + + if (Flags & D3DLOCK_DISCARD) + usage = PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE; + else if (Flags & D3DLOCK_NOOVERWRITE) + usage = PIPE_TRANSFER_WRITE | PIPE_TRANSFER_UNSYNCHRONIZED; + else + /* Do not ask for READ if writeonly and default pool (should be safe enough, + * as the doc says app shouldn't expect reading to work with writeonly). + * Ignore for Systemmem as it has special behaviours. */ + usage = ((This->base.usage & D3DUSAGE_WRITEONLY) && This->base.pool == D3DPOOL_DEFAULT) ? + PIPE_TRANSFER_WRITE : + PIPE_TRANSFER_READ_WRITE; + if (Flags & D3DLOCK_DONOTWAIT && !(This->base.usage & D3DUSAGE_DYNAMIC)) + usage |= PIPE_TRANSFER_DONTBLOCK; + + This->discard_nooverwrite_only &= !!(Flags & (D3DLOCK_DISCARD | D3DLOCK_NOOVERWRITE)); + + if (This->nmaps == This->maxmaps) { + struct NineTransfer *newmaps = + REALLOC(This->maps, sizeof(struct NineTransfer)*This->maxmaps, + sizeof(struct NineTransfer)*(This->maxmaps << 1)); + if (newmaps == NULL) + return E_OUTOFMEMORY; + + This->maxmaps <<= 1; + This->maps = newmaps; + } + + if (This->buf && !This->discard_nooverwrite_only) { + struct pipe_box src_box; + unsigned offset; + struct pipe_resource *src_res; + DBG("Disabling nine_subbuffer for a buffer having" + "used a nine_subbuffer buffer\n"); + /* Copy buffer content to the buffer resource, which + * we will now use. + * Note: The behaviour may be different from what is expected + * with double lock. However applications can't really make expectations + * about double locks, and don't really use them, so that's ok. */ + src_res = nine_upload_buffer_resource_and_offset(This->buf, &offset); + u_box_1d(offset, This->size, &src_box); + + pipe = NineDevice9_GetPipe(device); + pipe->resource_copy_region(pipe, This->base.resource, 0, 0, 0, 0, + src_res, 0, &src_box); + /* Release previous resource */ + if (This->nmaps >= 1) + This->maps[This->nmaps-1].should_destroy_buf = true; + else + nine_upload_release_buffer(device->buffer_upload, This->buf); + This->buf = NULL; + /* Rebind buffer */ + NineBuffer9_RebindIfRequired(This, device); + } + + This->maps[This->nmaps].transfer = NULL; + This->maps[This->nmaps].is_pipe_secondary = false; + This->maps[This->nmaps].buf = NULL; + This->maps[This->nmaps].should_destroy_buf = false; + + if (This->discard_nooverwrite_only) { + if (This->buf && (Flags & D3DLOCK_DISCARD)) { + /* Release previous buffer */ + if (This->nmaps >= 1) + This->maps[This->nmaps-1].should_destroy_buf = true; + else + nine_upload_release_buffer(device->buffer_upload, This->buf); + This->buf = NULL; + } + + if (!This->buf) { + This->buf = nine_upload_create_buffer(device->buffer_upload, This->base.info.width0); + NineBuffer9_RebindIfRequired(This, device); + } + + if (This->buf) { + This->maps[This->nmaps].buf = This->buf; + This->nmaps++; + *ppbData = nine_upload_buffer_get_map(This->buf) + OffsetToLock; + return D3D_OK; + } else { + /* Fallback to normal path, and don't try again */ + This->discard_nooverwrite_only = false; + } + } + + /* Previous mappings may need pending commands to write to the + * buffer (staging buffer for example). Before a NOOVERWRITE, + * we thus need a finish, to guarantee any upload is finished. + * Note for discard_nooverwrite_only we don't need to do this + * check as neither discard nor nooverwrite have issues there */ + if (This->need_sync_if_nooverwrite && !(Flags & D3DLOCK_DISCARD) && + (Flags & D3DLOCK_NOOVERWRITE)) { + struct pipe_screen *screen = NineDevice9_GetScreen(device); + struct pipe_fence_handle *fence = NULL; + + pipe = NineDevice9_GetPipe(device); + pipe->flush(pipe, &fence, 0); + (void) screen->fence_finish(screen, NULL, fence, PIPE_TIMEOUT_INFINITE); + screen->fence_reference(screen, &fence, NULL); + } + This->need_sync_if_nooverwrite = !(Flags & (D3DLOCK_DISCARD | D3DLOCK_NOOVERWRITE)); + + /* When csmt is active, we want to avoid stalls as much as possible, + * and thus we want to create a new resource on discard and map it + * with the secondary pipe, instead of waiting on the main pipe. */ + if (Flags & D3DLOCK_DISCARD && device->csmt_active) { + struct pipe_screen *screen = NineDevice9_GetScreen(device); + struct pipe_resource *new_res = screen->resource_create(screen, &This->base.info); + if (new_res) { + /* Use the new resource */ + pipe_resource_reference(&This->base.resource, new_res); + pipe_resource_reference(&new_res, NULL); + usage = PIPE_TRANSFER_WRITE | PIPE_TRANSFER_UNSYNCHRONIZED; + NineBuffer9_RebindIfRequired(This, device); + This->maps[This->nmaps].is_pipe_secondary = TRUE; + } + } else if (Flags & D3DLOCK_NOOVERWRITE && device->csmt_active) + This->maps[This->nmaps].is_pipe_secondary = TRUE; + + if (This->maps[This->nmaps].is_pipe_secondary) + pipe = device->pipe_secondary; + else + pipe = NineDevice9_GetPipe(device); + + data = pipe->transfer_map(pipe, This->base.resource, 0, + usage, &box, &This->maps[This->nmaps].transfer); + + if (!data) { + DBG("pipe::transfer_map failed\n" + " usage = %x\n" + " box.x = %u\n" + " box.width = %u\n", + usage, box.x, box.width); + + if (Flags & D3DLOCK_DONOTWAIT) + return D3DERR_WASSTILLDRAWING; + return D3DERR_INVALIDCALL; + } + + DBG("returning pointer %p\n", data); + This->nmaps++; + *ppbData = data; + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineBuffer9_Unlock( struct NineBuffer9 *This ) +{ + struct NineDevice9 *device = This->base.base.device; + struct pipe_context *pipe; + DBG("This=%p\n", This); + + user_assert(This->nmaps > 0, D3DERR_INVALIDCALL); + This->nmaps--; + if (This->base.pool != D3DPOOL_MANAGED) { + if (!This->maps[This->nmaps].buf) { + pipe = This->maps[This->nmaps].is_pipe_secondary ? + device->pipe_secondary : + nine_context_get_pipe_acquire(device); + pipe->transfer_unmap(pipe, This->maps[This->nmaps].transfer); + /* We need to flush in case the driver does implicit copies */ + if (This->maps[This->nmaps].is_pipe_secondary) + pipe->flush(pipe, NULL, 0); + else + nine_context_get_pipe_release(device); + } else if (This->maps[This->nmaps].should_destroy_buf) + nine_upload_release_buffer(device->buffer_upload, This->maps[This->nmaps].buf); + } + return D3D_OK; +} + +void +NineBuffer9_SetDirty( struct NineBuffer9 *This ) +{ + assert(This->base.pool == D3DPOOL_MANAGED); + + This->managed.dirty = TRUE; + u_box_1d(0, This->size, &This->managed.dirty_box); + BASEBUF_REGISTER_UPDATE(This); +} diff --git a/src/gallium/frontends/nine/buffer9.h b/src/gallium/frontends/nine/buffer9.h new file mode 100644 index 00000000000..1c142fcf64a --- /dev/null +++ b/src/gallium/frontends/nine/buffer9.h @@ -0,0 +1,147 @@ +/* + * Copyright 2011 Joakim Sindholt + * Copyright 2015 Patrick Rudolph + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _NINE_BUFFER9_H_ +#define _NINE_BUFFER9_H_ + +#include "device9.h" +#include "nine_buffer_upload.h" +#include "nine_state.h" +#include "resource9.h" +#include "pipe/p_context.h" +#include "pipe/p_state.h" +#include "util/list.h" + +struct pipe_screen; +struct pipe_context; +struct pipe_transfer; + +struct NineTransfer { + struct pipe_transfer *transfer; + bool is_pipe_secondary; + struct nine_subbuffer *buf; /* NULL unless subbuffer are used */ + bool should_destroy_buf; /* If the subbuffer should be destroyed */ +}; + +struct NineBuffer9 +{ + struct NineResource9 base; + + /* G3D */ + struct NineTransfer *maps; + int nmaps, maxmaps; + UINT size; + + int16_t bind_count; /* to Device9->state.stream */ + /* Whether only discard and nooverwrite were used so far + * for this buffer. Allows some optimization. */ + boolean discard_nooverwrite_only; + boolean need_sync_if_nooverwrite; + struct nine_subbuffer *buf; + + /* Specific to managed buffers */ + struct { + void *data; + boolean dirty; + struct pipe_box dirty_box; + struct list_head list; /* for update_buffers */ + struct list_head list2; /* for managed_buffers */ + unsigned pending_upload; /* for uploads */ + } managed; +}; +static inline struct NineBuffer9 * +NineBuffer9( void *data ) +{ + return (struct NineBuffer9 *)data; +} + +HRESULT +NineBuffer9_ctor( struct NineBuffer9 *This, + struct NineUnknownParams *pParams, + D3DRESOURCETYPE Type, + DWORD Usage, + UINT Size, + D3DPOOL Pool ); + +void +NineBuffer9_dtor( struct NineBuffer9 *This ); + +struct pipe_resource * +NineBuffer9_GetResource( struct NineBuffer9 *This, unsigned *offset ); + +HRESULT NINE_WINAPI +NineBuffer9_Lock( struct NineBuffer9 *This, + UINT OffsetToLock, + UINT SizeToLock, + void **ppbData, + DWORD Flags ); + +HRESULT NINE_WINAPI +NineBuffer9_Unlock( struct NineBuffer9 *This ); + +static inline void +NineBuffer9_Upload( struct NineBuffer9 *This ) +{ + struct NineDevice9 *device = This->base.base.device; + + assert(This->base.pool == D3DPOOL_MANAGED && This->managed.dirty); + nine_context_range_upload(device, &This->managed.pending_upload, + (struct NineUnknown *)This, + This->base.resource, + This->managed.dirty_box.x, + This->managed.dirty_box.width, + (char *)This->managed.data + This->managed.dirty_box.x); + This->managed.dirty = FALSE; +} + +static void inline +NineBindBufferToDevice( struct NineDevice9 *device, + struct NineBuffer9 **slot, + struct NineBuffer9 *buf ) +{ + struct NineBuffer9 *old = *slot; + + if (buf) { + if ((buf->managed.dirty) && list_is_empty(&buf->managed.list)) + list_add(&buf->managed.list, &device->update_buffers); + buf->bind_count++; + } + if (old) { + old->bind_count--; + if (!old->bind_count && old->managed.dirty) + list_delinit(&old->managed.list); + } + + nine_bind(slot, buf); +} + +void +NineBuffer9_SetDirty( struct NineBuffer9 *This ); + +#define BASEBUF_REGISTER_UPDATE(b) { \ + if ((b)->managed.dirty && (b)->bind_count) \ + if (list_is_empty(&(b)->managed.list)) \ + list_add(&(b)->managed.list, &(b)->base.base.device->update_buffers); \ + } + +#endif /* _NINE_BUFFER9_H_ */ diff --git a/src/gallium/frontends/nine/cryptosession9.c b/src/gallium/frontends/nine/cryptosession9.c new file mode 100644 index 00000000000..c656f72a215 --- /dev/null +++ b/src/gallium/frontends/nine/cryptosession9.c @@ -0,0 +1,115 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "cryptosession9.h" + +#define DBG_CHANNEL DBG_CRYPTOSESSION + +HRESULT NINE_WINAPI +NineCryptoSession9_GetCertificateSize( struct NineCryptoSession9 *This, + UINT *pCertificateSize ) +{ + STUB(D3DERR_INVALIDCALL); +} + +HRESULT NINE_WINAPI +NineCryptoSession9_GetCertificate( struct NineCryptoSession9 *This, + UINT CertifacteSize, + BYTE *ppCertificate ) +{ + STUB(D3DERR_INVALIDCALL); +} + +HRESULT NINE_WINAPI +NineCryptoSession9_NegotiateKeyExchange( struct NineCryptoSession9 *This, + UINT DataSize, + void *pData ) +{ + STUB(D3DERR_INVALIDCALL); +} + +HRESULT NINE_WINAPI +NineCryptoSession9_EncryptionBlt( struct NineCryptoSession9 *This, + IDirect3DSurface9 *pSrcSurface, + IDirect3DSurface9 *pDstSurface, + UINT DstSurfaceSize, + void *pIV ) +{ + STUB(D3DERR_INVALIDCALL); +} + +HRESULT NINE_WINAPI +NineCryptoSession9_DecryptionBlt( struct NineCryptoSession9 *This, + IDirect3DSurface9 *pSrcSurface, + IDirect3DSurface9 *pDstSurface, + UINT SrcSurfaceSize, + D3DENCRYPTED_BLOCK_INFO *pEncryptedBlockInfo, + void *pContentKey, + void *pIV ) +{ + STUB(D3DERR_INVALIDCALL); +} + +HRESULT NINE_WINAPI +NineCryptoSession9_GetSurfacePitch( struct NineCryptoSession9 *This, + IDirect3DSurface9 *pSrcSurface, + UINT *pSurfacePitch ) +{ + STUB(D3DERR_INVALIDCALL); +} + +HRESULT NINE_WINAPI +NineCryptoSession9_StartSessionKeyRefresh( struct NineCryptoSession9 *This, + void *pRandomNumber, + UINT RandomNumberSize ) +{ + STUB(D3DERR_INVALIDCALL); +} + +HRESULT NINE_WINAPI +NineCryptoSession9_FinishSessionKeyRefresh( struct NineCryptoSession9 *This ) +{ + STUB(D3DERR_INVALIDCALL); +} + +HRESULT NINE_WINAPI +NineCryptoSession9_GetEncryptionBltKey( struct NineCryptoSession9 *This, + void *pReadbackKey, + UINT KeySize ) +{ + STUB(D3DERR_INVALIDCALL); +} + +IDirect3DCryptoSession9Vtbl NineCryptoSession9_vtable = { + (void *)NineUnknown_QueryInterface, + (void *)NineUnknown_AddRef, + (void *)NineUnknown_Release, + (void *)NineCryptoSession9_GetCertificateSize, + (void *)NineCryptoSession9_GetCertificate, + (void *)NineCryptoSession9_NegotiateKeyExchange, + (void *)NineCryptoSession9_EncryptionBlt, + (void *)NineCryptoSession9_DecryptionBlt, + (void *)NineCryptoSession9_GetSurfacePitch, + (void *)NineCryptoSession9_StartSessionKeyRefresh, + (void *)NineCryptoSession9_FinishSessionKeyRefresh, + (void *)NineCryptoSession9_GetEncryptionBltKey +}; diff --git a/src/gallium/frontends/nine/cryptosession9.h b/src/gallium/frontends/nine/cryptosession9.h new file mode 100644 index 00000000000..9904455a000 --- /dev/null +++ b/src/gallium/frontends/nine/cryptosession9.h @@ -0,0 +1,86 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _NINE_CRYPTOSESSION9_H_ +#define _NINE_CRYPTOSESSION9_H_ + +#include "iunknown.h" + +struct NineCryptoSession9 +{ + struct NineUnknown base; +}; +static inline struct NineCryptoSession9 * +NineCryptoSession9( void *data ) +{ + return (struct NineCryptoSession9 *)data; +} + +HRESULT NINE_WINAPI +NineCryptoSession9_GetCertificateSize( struct NineCryptoSession9 *This, + UINT *pCertificateSize ); + +HRESULT NINE_WINAPI +NineCryptoSession9_GetCertificate( struct NineCryptoSession9 *This, + UINT CertifacteSize, + BYTE *ppCertificate ); + +HRESULT NINE_WINAPI +NineCryptoSession9_NegotiateKeyExchange( struct NineCryptoSession9 *This, + UINT DataSize, + void *pData ); + +HRESULT NINE_WINAPI +NineCryptoSession9_EncryptionBlt( struct NineCryptoSession9 *This, + IDirect3DSurface9 *pSrcSurface, + IDirect3DSurface9 *pDstSurface, + UINT DstSurfaceSize, + void *pIV ); + +HRESULT NINE_WINAPI +NineCryptoSession9_DecryptionBlt( struct NineCryptoSession9 *This, + IDirect3DSurface9 *pSrcSurface, + IDirect3DSurface9 *pDstSurface, + UINT SrcSurfaceSize, + D3DENCRYPTED_BLOCK_INFO *pEncryptedBlockInfo, + void *pContentKey, + void *pIV ); + +HRESULT NINE_WINAPI +NineCryptoSession9_GetSurfacePitch( struct NineCryptoSession9 *This, + IDirect3DSurface9 *pSrcSurface, + UINT *pSurfacePitch ); + +HRESULT NINE_WINAPI +NineCryptoSession9_StartSessionKeyRefresh( struct NineCryptoSession9 *This, + void *pRandomNumber, + UINT RandomNumberSize ); + +HRESULT NINE_WINAPI +NineCryptoSession9_FinishSessionKeyRefresh( struct NineCryptoSession9 *This ); + +HRESULT NINE_WINAPI +NineCryptoSession9_GetEncryptionBltKey( struct NineCryptoSession9 *This, + void *pReadbackKey, + UINT KeySize ); + +#endif /* _NINE_CRYPTOSESSION9_H_ */ diff --git a/src/gallium/frontends/nine/cubetexture9.c b/src/gallium/frontends/nine/cubetexture9.c new file mode 100644 index 00000000000..89821682f8f --- /dev/null +++ b/src/gallium/frontends/nine/cubetexture9.c @@ -0,0 +1,350 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "c99_alloca.h" + +#include "device9.h" +#include "cubetexture9.h" +#include "nine_helpers.h" +#include "nine_pipe.h" + +#define DBG_CHANNEL DBG_CUBETEXTURE + + +static HRESULT +NineCubeTexture9_ctor( struct NineCubeTexture9 *This, + struct NineUnknownParams *pParams, + UINT EdgeLength, UINT Levels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + HANDLE *pSharedHandle ) +{ + struct pipe_resource *info = &This->base.base.info; + struct pipe_screen *screen = pParams->device->screen; + enum pipe_format pf; + unsigned i, l, f, offset, face_size = 0; + unsigned *level_offsets = NULL; + D3DSURFACE_DESC sfdesc; + void *p; + HRESULT hr; + + DBG("This=%p pParams=%p EdgeLength=%u Levels=%u Usage=%d " + "Format=%d Pool=%d pSharedHandle=%p\n", + This, pParams, EdgeLength, Levels, Usage, + Format, Pool, pSharedHandle); + + user_assert(EdgeLength, D3DERR_INVALIDCALL); + + /* user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); */ + user_assert(!pSharedHandle, D3DERR_INVALIDCALL); /* TODO */ + + user_assert(!(Usage & D3DUSAGE_AUTOGENMIPMAP) || + (Pool != D3DPOOL_SYSTEMMEM && Levels <= 1), D3DERR_INVALIDCALL); + + if (Usage & D3DUSAGE_AUTOGENMIPMAP) + Levels = 0; + + pf = d3d9_to_pipe_format_checked(screen, Format, PIPE_TEXTURE_CUBE, 0, + PIPE_BIND_SAMPLER_VIEW, FALSE, + Pool == D3DPOOL_SCRATCH); + + if (pf == PIPE_FORMAT_NONE) + return D3DERR_INVALIDCALL; + + if (compressed_format(Format)) { + const unsigned w = util_format_get_blockwidth(pf); + const unsigned h = util_format_get_blockheight(pf); + + user_assert(!(EdgeLength % w) && !(EdgeLength % h), D3DERR_INVALIDCALL); + } + + info->screen = pParams->device->screen; + info->target = PIPE_TEXTURE_CUBE; + info->format = pf; + info->width0 = EdgeLength; + info->height0 = EdgeLength; + info->depth0 = 1; + if (Levels) + info->last_level = Levels - 1; + else + info->last_level = util_logbase2(EdgeLength); + info->array_size = 6; + info->nr_samples = 0; + info->nr_storage_samples = 0; + info->bind = PIPE_BIND_SAMPLER_VIEW; + info->usage = PIPE_USAGE_DEFAULT; + info->flags = 0; + + if (Usage & D3DUSAGE_RENDERTARGET) + info->bind |= PIPE_BIND_RENDER_TARGET; + if (Usage & D3DUSAGE_DEPTHSTENCIL) + info->bind |= PIPE_BIND_DEPTH_STENCIL; + + if (Usage & D3DUSAGE_DYNAMIC) { + info->usage = PIPE_USAGE_DYNAMIC; + } + if (Usage & D3DUSAGE_SOFTWAREPROCESSING) + DBG("Application asked for Software Vertex Processing, " + "but this is unimplemented\n"); + + if (Pool != D3DPOOL_DEFAULT) { + level_offsets = alloca(sizeof(unsigned) * (info->last_level + 1)); + face_size = nine_format_get_size_and_offsets(pf, level_offsets, + EdgeLength, EdgeLength, + info->last_level); + This->managed_buffer = align_calloc(6 * face_size, 32); + if (!This->managed_buffer) + return E_OUTOFMEMORY; + } + + This->surfaces = CALLOC(6 * (info->last_level + 1), sizeof(*This->surfaces)); + if (!This->surfaces) + return E_OUTOFMEMORY; + + hr = NineBaseTexture9_ctor(&This->base, pParams, NULL, D3DRTYPE_CUBETEXTURE, + Format, Pool, Usage); + if (FAILED(hr)) + return hr; + This->base.pstype = 2; + + /* Create all the surfaces right away. + * They manage backing storage, and transfers (LockRect) are deferred + * to them. + */ + sfdesc.Format = Format; + sfdesc.Type = D3DRTYPE_SURFACE; + sfdesc.Usage = Usage; + sfdesc.Pool = Pool; + sfdesc.MultiSampleType = D3DMULTISAMPLE_NONE; + sfdesc.MultiSampleQuality = 0; + /* We allocate the memory for the surfaces as continous blocks. + * This is the expected behaviour, however we haven't tested for + * cube textures in which order the faces/levels should be in memory + */ + for (f = 0; f < 6; f++) { + offset = f * face_size; + for (l = 0; l <= info->last_level; l++) { + sfdesc.Width = sfdesc.Height = u_minify(EdgeLength, l); + p = This->managed_buffer ? This->managed_buffer + offset + + level_offsets[l] : NULL; + + hr = NineSurface9_new(This->base.base.base.device, NineUnknown(This), + This->base.base.resource, p, D3DRTYPE_CUBETEXTURE, + l, f, &sfdesc, &This->surfaces[f + 6 * l]); + if (FAILED(hr)) + return hr; + } + } + + for (i = 0; i < 6; ++i) { + /* Textures start initially dirty */ + This->dirty_rect[i].width = EdgeLength; + This->dirty_rect[i].height = EdgeLength; + This->dirty_rect[i].depth = 1; + } + + return D3D_OK; +} + +static void +NineCubeTexture9_dtor( struct NineCubeTexture9 *This ) +{ + unsigned i; + + DBG("This=%p\n", This); + + if (This->surfaces) { + for (i = 0; i < (This->base.base.info.last_level + 1) * 6; ++i) + NineUnknown_Destroy(&This->surfaces[i]->base.base); + FREE(This->surfaces); + } + + if (This->managed_buffer) + align_free(This->managed_buffer); + + NineBaseTexture9_dtor(&This->base); +} + +HRESULT NINE_WINAPI +NineCubeTexture9_GetLevelDesc( struct NineCubeTexture9 *This, + UINT Level, + D3DSURFACE_DESC *pDesc ) +{ + DBG("This=%p Level=%u pDesc=%p\n", This, Level, pDesc); + + user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); + user_assert(Level == 0 || !(This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP), + D3DERR_INVALIDCALL); + + *pDesc = This->surfaces[Level * 6]->desc; + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineCubeTexture9_GetCubeMapSurface( struct NineCubeTexture9 *This, + D3DCUBEMAP_FACES FaceType, + UINT Level, + IDirect3DSurface9 **ppCubeMapSurface ) +{ + const unsigned s = Level * 6 + FaceType; + + DBG("This=%p FaceType=%d Level=%u ppCubeMapSurface=%p\n", + This, FaceType, Level, ppCubeMapSurface); + + user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); + user_assert(Level == 0 || !(This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP), + D3DERR_INVALIDCALL); + user_assert(FaceType < 6, D3DERR_INVALIDCALL); + + NineUnknown_AddRef(NineUnknown(This->surfaces[s])); + *ppCubeMapSurface = (IDirect3DSurface9 *)This->surfaces[s]; + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineCubeTexture9_LockRect( struct NineCubeTexture9 *This, + D3DCUBEMAP_FACES FaceType, + UINT Level, + D3DLOCKED_RECT *pLockedRect, + const RECT *pRect, + DWORD Flags ) +{ + const unsigned s = Level * 6 + FaceType; + + DBG("This=%p FaceType=%d Level=%u pLockedRect=%p pRect=%p Flags=%d\n", + This, FaceType, Level, pLockedRect, pRect, Flags); + + user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); + user_assert(Level == 0 || !(This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP), + D3DERR_INVALIDCALL); + user_assert(FaceType < 6, D3DERR_INVALIDCALL); + + return NineSurface9_LockRect(This->surfaces[s], pLockedRect, pRect, Flags); +} + +HRESULT NINE_WINAPI +NineCubeTexture9_UnlockRect( struct NineCubeTexture9 *This, + D3DCUBEMAP_FACES FaceType, + UINT Level ) +{ + const unsigned s = Level * 6 + FaceType; + + DBG("This=%p FaceType=%d Level=%u\n", This, FaceType, Level); + + user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); + user_assert(FaceType < 6, D3DERR_INVALIDCALL); + + return NineSurface9_UnlockRect(This->surfaces[s]); +} + +HRESULT NINE_WINAPI +NineCubeTexture9_AddDirtyRect( struct NineCubeTexture9 *This, + D3DCUBEMAP_FACES FaceType, + const RECT *pDirtyRect ) +{ + DBG("This=%p FaceType=%d pDirtyRect=%p\n", This, FaceType, pDirtyRect); + + user_assert(FaceType < 6, D3DERR_INVALIDCALL); + + if (This->base.base.pool != D3DPOOL_MANAGED) { + if (This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP) { + This->base.dirty_mip = TRUE; + BASETEX_REGISTER_UPDATE(&This->base); + } + return D3D_OK; + } + + if (This->base.base.pool == D3DPOOL_MANAGED) { + This->base.managed.dirty = TRUE; + BASETEX_REGISTER_UPDATE(&This->base); + } + + if (!pDirtyRect) { + u_box_origin_2d(This->base.base.info.width0, + This->base.base.info.height0, + &This->dirty_rect[FaceType]); + } else { + if (This->dirty_rect[FaceType].width == 0) { + rect_to_pipe_box_clamp(&This->dirty_rect[FaceType], pDirtyRect); + } else { + struct pipe_box box; + rect_to_pipe_box_clamp(&box, pDirtyRect); + u_box_union_2d(&This->dirty_rect[FaceType], &This->dirty_rect[FaceType], + &box); + } + (void) u_box_clip_2d(&This->dirty_rect[FaceType], + &This->dirty_rect[FaceType], + This->base.base.info.width0, + This->base.base.info.height0); + } + return D3D_OK; +} + +IDirect3DCubeTexture9Vtbl NineCubeTexture9_vtable = { + (void *)NineUnknown_QueryInterface, + (void *)NineUnknown_AddRef, + (void *)NineUnknown_Release, + (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */ + (void *)NineUnknown_SetPrivateData, + (void *)NineUnknown_GetPrivateData, + (void *)NineUnknown_FreePrivateData, + (void *)NineResource9_SetPriority, + (void *)NineResource9_GetPriority, + (void *)NineBaseTexture9_PreLoad, + (void *)NineResource9_GetType, + (void *)NineBaseTexture9_SetLOD, + (void *)NineBaseTexture9_GetLOD, + (void *)NineBaseTexture9_GetLevelCount, + (void *)NineBaseTexture9_SetAutoGenFilterType, + (void *)NineBaseTexture9_GetAutoGenFilterType, + (void *)NineBaseTexture9_GenerateMipSubLevels, + (void *)NineCubeTexture9_GetLevelDesc, + (void *)NineCubeTexture9_GetCubeMapSurface, + (void *)NineCubeTexture9_LockRect, + (void *)NineCubeTexture9_UnlockRect, + (void *)NineCubeTexture9_AddDirtyRect +}; + +static const GUID *NineCubeTexture9_IIDs[] = { + &IID_IDirect3DCubeTexture9, + &IID_IDirect3DBaseTexture9, + &IID_IDirect3DResource9, + &IID_IUnknown, + NULL +}; + +HRESULT +NineCubeTexture9_new( struct NineDevice9 *pDevice, + UINT EdgeLength, UINT Levels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + struct NineCubeTexture9 **ppOut, + HANDLE *pSharedHandle ) +{ + NINE_DEVICE_CHILD_NEW(CubeTexture9, ppOut, pDevice, + EdgeLength, Levels, + Usage, Format, Pool, pSharedHandle); +} diff --git a/src/gallium/frontends/nine/cubetexture9.h b/src/gallium/frontends/nine/cubetexture9.h new file mode 100644 index 00000000000..129789d0d69 --- /dev/null +++ b/src/gallium/frontends/nine/cubetexture9.h @@ -0,0 +1,80 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _NINE_CUBETEXTURE9_H_ +#define _NINE_CUBETEXTURE9_H_ + +#include "basetexture9.h" +#include "surface9.h" + +struct NineCubeTexture9 +{ + struct NineBaseTexture9 base; + struct NineSurface9 **surfaces; + struct pipe_box dirty_rect[6]; /* covers all mip levels */ + uint8_t *managed_buffer; +}; +static inline struct NineCubeTexture9 * +NineCubeTexture9( void *data ) +{ + return (struct NineCubeTexture9 *)data; +} + +HRESULT +NineCubeTexture9_new( struct NineDevice9 *pDevice, + UINT EdgeLength, UINT Levels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + struct NineCubeTexture9 **ppOut, + HANDLE *pSharedHandle ); + +HRESULT NINE_WINAPI +NineCubeTexture9_GetLevelDesc( struct NineCubeTexture9 *This, + UINT Level, + D3DSURFACE_DESC *pDesc ); + +HRESULT NINE_WINAPI +NineCubeTexture9_GetCubeMapSurface( struct NineCubeTexture9 *This, + D3DCUBEMAP_FACES FaceType, + UINT Level, + IDirect3DSurface9 **ppCubeMapSurface ); + +HRESULT NINE_WINAPI +NineCubeTexture9_LockRect( struct NineCubeTexture9 *This, + D3DCUBEMAP_FACES FaceType, + UINT Level, + D3DLOCKED_RECT *pLockedRect, + const RECT *pRect, + DWORD Flags ); + +HRESULT NINE_WINAPI +NineCubeTexture9_UnlockRect( struct NineCubeTexture9 *This, + D3DCUBEMAP_FACES FaceType, + UINT Level ); + +HRESULT NINE_WINAPI +NineCubeTexture9_AddDirtyRect( struct NineCubeTexture9 *This, + D3DCUBEMAP_FACES FaceType, + const RECT *pDirtyRect ); + +#endif /* _NINE_CUBETEXTURE9_H_ */ diff --git a/src/gallium/frontends/nine/device9.c b/src/gallium/frontends/nine/device9.c new file mode 100644 index 00000000000..c5b5eff128e --- /dev/null +++ b/src/gallium/frontends/nine/device9.c @@ -0,0 +1,4053 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "device9.h" +#include "stateblock9.h" +#include "surface9.h" +#include "swapchain9.h" +#include "swapchain9ex.h" +#include "indexbuffer9.h" +#include "vertexbuffer9.h" +#include "vertexdeclaration9.h" +#include "vertexshader9.h" +#include "pixelshader9.h" +#include "query9.h" +#include "texture9.h" +#include "cubetexture9.h" +#include "volumetexture9.h" +#include "nine_buffer_upload.h" +#include "nine_helpers.h" +#include "nine_pipe.h" +#include "nine_ff.h" +#include "nine_dump.h" +#include "nine_limits.h" + +#include "pipe/p_screen.h" +#include "pipe/p_context.h" +#include "pipe/p_config.h" +#include "util/u_math.h" +#include "util/u_inlines.h" +#include "util/u_hash_table.h" +#include "util/format/u_format.h" +#include "util/u_surface.h" +#include "util/u_upload_mgr.h" +#include "hud/hud_context.h" +#include "compiler/glsl_types.h" + +#include "cso_cache/cso_context.h" + +#define DBG_CHANNEL DBG_DEVICE + +#if defined(PIPE_CC_GCC) && (defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)) + +static void nine_setup_fpu() +{ + uint16_t c; + + __asm__ __volatile__ ("fnstcw %0" : "=m" (*&c)); + + /* clear the control word */ + c &= 0xF0C0; + /* d3d9 doc/wine tests: mask all exceptions, use single-precision + * and round to nearest */ + c |= 0x003F; + + __asm__ __volatile__ ("fldcw %0" : : "m" (*&c)); +} + +#else + +static void nine_setup_fpu(void) +{ + WARN_ONCE("FPU setup not supported on non-x86 platforms\n"); +} + +#endif + +void +NineDevice9_SetDefaultState( struct NineDevice9 *This, boolean is_reset ) +{ + struct NineSurface9 *refSurf = NULL; + + DBG("This=%p is_reset=%d\n", This, (int) is_reset); + + assert(!This->is_recording); + + nine_state_set_defaults(This, &This->caps, is_reset); + + refSurf = This->swapchains[0]->buffers[0]; + assert(refSurf); + + This->state.viewport.X = 0; + This->state.viewport.Y = 0; + This->state.viewport.Width = refSurf->desc.Width; + This->state.viewport.Height = refSurf->desc.Height; + + nine_context_set_viewport(This, &This->state.viewport); + + This->state.scissor.minx = 0; + This->state.scissor.miny = 0; + This->state.scissor.maxx = refSurf->desc.Width; + This->state.scissor.maxy = refSurf->desc.Height; + + nine_context_set_scissor(This, &This->state.scissor); + + if (This->nswapchains && This->swapchains[0]->params.EnableAutoDepthStencil) { + nine_context_set_render_state(This, D3DRS_ZENABLE, TRUE); + This->state.rs_advertised[D3DRS_ZENABLE] = TRUE; + } + if (This->state.rs_advertised[D3DRS_ZENABLE]) + NineDevice9_SetDepthStencilSurface( + This, (IDirect3DSurface9 *)This->swapchains[0]->zsbuf); +} + +#define GET_PCAP(n) pScreen->get_param(pScreen, PIPE_CAP_##n) +HRESULT +NineDevice9_ctor( struct NineDevice9 *This, + struct NineUnknownParams *pParams, + struct pipe_screen *pScreen, + D3DDEVICE_CREATION_PARAMETERS *pCreationParameters, + D3DCAPS9 *pCaps, + D3DPRESENT_PARAMETERS *pPresentationParameters, + IDirect3D9 *pD3D9, + ID3DPresentGroup *pPresentationGroup, + struct d3dadapter9_context *pCTX, + boolean ex, + D3DDISPLAYMODEEX *pFullscreenDisplayMode, + int minorVersionNum ) +{ + unsigned i; + HRESULT hr = NineUnknown_ctor(&This->base, pParams); + + DBG("This=%p pParams=%p pScreen=%p pCreationParameters=%p pCaps=%p pPresentationParameters=%p " + "pD3D9=%p pPresentationGroup=%p pCTX=%p ex=%d pFullscreenDisplayMode=%p\n", + This, pParams, pScreen, pCreationParameters, pCaps, pPresentationParameters, pD3D9, + pPresentationGroup, pCTX, (int) ex, pFullscreenDisplayMode); + + if (FAILED(hr)) { return hr; } + + /* NIR shaders need to use GLSL types so let's initialize them here */ + glsl_type_singleton_init_or_ref(); + + list_inithead(&This->update_buffers); + list_inithead(&This->update_textures); + list_inithead(&This->managed_buffers); + list_inithead(&This->managed_textures); + + This->screen = pScreen; + This->screen_sw = pCTX->ref; + This->caps = *pCaps; + This->d3d9 = pD3D9; + This->params = *pCreationParameters; + This->ex = ex; + This->present = pPresentationGroup; + This->minor_version_num = minorVersionNum; + + IDirect3D9_AddRef(This->d3d9); + ID3DPresentGroup_AddRef(This->present); + + if (!(This->params.BehaviorFlags & D3DCREATE_FPU_PRESERVE)) + nine_setup_fpu(); + + if (This->params.BehaviorFlags & D3DCREATE_SOFTWARE_VERTEXPROCESSING) { + DBG("Application asked full Software Vertex Processing.\n"); + This->swvp = true; + This->may_swvp = true; + } else + This->swvp = false; + if (This->params.BehaviorFlags & D3DCREATE_MIXED_VERTEXPROCESSING) { + DBG("Application asked mixed Software Vertex Processing.\n"); + This->may_swvp = true; + } + This->context.swvp = This->swvp; + /* TODO: check if swvp is resetted by device Resets */ + + if (This->may_swvp && + (This->screen->get_shader_param(This->screen, PIPE_SHADER_VERTEX, + PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE) + < (NINE_MAX_CONST_F_SWVP/2) * sizeof(float[4]) || + This->screen->get_shader_param(This->screen, PIPE_SHADER_VERTEX, + PIPE_SHADER_CAP_MAX_CONST_BUFFERS) < 5)) { + /* Note: We just go on, some apps never use the abilities of + * swvp, and just set more constants than allowed at init. + * Only cards we support that are affected are the r500 */ + WARN("Card unable to handle Software Vertex Processing. Game may fail\n"); + } + + /* When may_swvp, SetConstant* limits are different */ + if (This->may_swvp) + This->caps.MaxVertexShaderConst = NINE_MAX_CONST_F_SWVP; + + This->context.pipe = This->screen->context_create(This->screen, NULL, 0); + This->pipe_secondary = This->screen->context_create(This->screen, NULL, 0); + if (!This->context.pipe || !This->pipe_secondary) { return E_OUTOFMEMORY; } /* guess */ + This->pipe_sw = This->screen_sw->context_create(This->screen_sw, NULL, 0); + if (!This->pipe_sw) { return E_OUTOFMEMORY; } + + This->context.cso = cso_create_context(This->context.pipe, 0); + if (!This->context.cso) { return E_OUTOFMEMORY; } /* also a guess */ + This->cso_sw = cso_create_context(This->pipe_sw, 0); + if (!This->cso_sw) { return E_OUTOFMEMORY; } + + /* Create first, it messes up our state. */ + This->hud = hud_create(This->context.cso, NULL); /* NULL result is fine */ + + /* Available memory counter. Updated only for allocations with this device + * instance. This is the Win 7 behavior. + * Win XP shares this counter across multiple devices. */ + This->available_texture_mem = This->screen->get_param(This->screen, PIPE_CAP_VIDEO_MEMORY); + if (This->available_texture_mem < 4096) + This->available_texture_mem <<= 20; + else + This->available_texture_mem = UINT_MAX; + /* We cap texture memory usage to 80% of what is reported free initially + * This helps get closer Win behaviour. For example VertexBuffer allocation + * still succeeds when texture allocation fails. */ + This->available_texture_limit = This->available_texture_mem * 20LL / 100LL; + + /* create implicit swapchains */ + This->nswapchains = ID3DPresentGroup_GetMultiheadCount(This->present); + This->swapchains = CALLOC(This->nswapchains, + sizeof(struct NineSwapChain9 *)); + if (!This->swapchains) { return E_OUTOFMEMORY; } + + for (i = 0; i < This->nswapchains; ++i) { + ID3DPresent *present; + + hr = ID3DPresentGroup_GetPresent(This->present, i, &present); + if (FAILED(hr)) + return hr; + + if (ex) { + D3DDISPLAYMODEEX *mode = NULL; + struct NineSwapChain9Ex **ret = + (struct NineSwapChain9Ex **)&This->swapchains[i]; + + if (pFullscreenDisplayMode) mode = &(pFullscreenDisplayMode[i]); + /* when this is a Device9Ex, it should create SwapChain9Exs */ + hr = NineSwapChain9Ex_new(This, TRUE, present, + &pPresentationParameters[i], pCTX, + This->params.hFocusWindow, mode, ret); + } else { + hr = NineSwapChain9_new(This, TRUE, present, + &pPresentationParameters[i], pCTX, + This->params.hFocusWindow, + &This->swapchains[i]); + } + + ID3DPresent_Release(present); + if (FAILED(hr)) + return hr; + NineUnknown_ConvertRefToBind(NineUnknown(This->swapchains[i])); + + hr = NineSwapChain9_GetBackBuffer(This->swapchains[i], 0, + D3DBACKBUFFER_TYPE_MONO, + (IDirect3DSurface9 **) + &This->state.rt[i]); + if (FAILED(hr)) + return hr; + NineUnknown_ConvertRefToBind(NineUnknown(This->state.rt[i])); + nine_bind(&This->context.rt[i], This->state.rt[i]); + } + + /* Initialize CSMT */ + /* r600, radeonsi and iris are thread safe. */ + if (pCTX->csmt_force == 1) + This->csmt_active = true; + else if (pCTX->csmt_force == 0) + This->csmt_active = false; + else if (strstr(pScreen->get_name(pScreen), "AMD") != NULL) + This->csmt_active = true; + else if (strstr(pScreen->get_name(pScreen), "Intel") != NULL) + This->csmt_active = true; + + /* We rely on u_upload_mgr using persistent coherent buffers (which don't + * require flush to work in multi-pipe_context scenario) for vertex and + * index buffers */ + if (!GET_PCAP(BUFFER_MAP_PERSISTENT_COHERENT)) + This->csmt_active = false; + + if (This->csmt_active) { + This->csmt_ctx = nine_csmt_create(This); + if (!This->csmt_ctx) + return E_OUTOFMEMORY; + } + + if (This->csmt_active) + DBG("\033[1;32mCSMT is active\033[0m\n"); + + This->workarounds.dynamic_texture_workaround = pCTX->dynamic_texture_workaround; + + This->buffer_upload = nine_upload_create(This->pipe_secondary, 4 * 1024 * 1024, 4); + + /* Initialize a dummy VBO to be used when a vertex declaration does not + * specify all the inputs needed by vertex shader, on win default behavior + * is to pass 0,0,0,0 to the shader */ + { + struct pipe_transfer *transfer; + struct pipe_resource tmpl; + struct pipe_box box; + unsigned char *data; + + memset(&tmpl, 0, sizeof(tmpl)); + tmpl.target = PIPE_BUFFER; + tmpl.format = PIPE_FORMAT_R8_UNORM; + tmpl.width0 = 16; /* 4 floats */ + tmpl.height0 = 1; + tmpl.depth0 = 1; + tmpl.array_size = 1; + tmpl.last_level = 0; + tmpl.nr_samples = 0; + tmpl.usage = PIPE_USAGE_DEFAULT; + tmpl.bind = PIPE_BIND_VERTEX_BUFFER; + tmpl.flags = 0; + This->dummy_vbo = pScreen->resource_create(pScreen, &tmpl); + + if (!This->dummy_vbo) + return D3DERR_OUTOFVIDEOMEMORY; + + u_box_1d(0, 16, &box); + data = This->context.pipe->transfer_map(This->context.pipe, This->dummy_vbo, 0, + PIPE_TRANSFER_WRITE | + PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE, + &box, &transfer); + assert(data); + assert(transfer); + memset(data, 0, 16); + This->context.pipe->transfer_unmap(This->context.pipe, transfer); + } + + This->cursor.software = FALSE; + This->cursor.hotspot.x = -1; + This->cursor.hotspot.y = -1; + This->cursor.w = This->cursor.h = 0; + This->cursor.visible = FALSE; + if (ID3DPresent_GetCursorPos(This->swapchains[0]->present, &This->cursor.pos) != S_OK) { + This->cursor.pos.x = 0; + This->cursor.pos.y = 0; + } + + { + struct pipe_resource tmpl; + memset(&tmpl, 0, sizeof(tmpl)); + tmpl.target = PIPE_TEXTURE_2D; + tmpl.format = PIPE_FORMAT_R8G8B8A8_UNORM; + tmpl.width0 = 64; + tmpl.height0 = 64; + tmpl.depth0 = 1; + tmpl.array_size = 1; + tmpl.last_level = 0; + tmpl.nr_samples = 0; + tmpl.usage = PIPE_USAGE_DEFAULT; + tmpl.bind = PIPE_BIND_CURSOR | PIPE_BIND_SAMPLER_VIEW; + tmpl.flags = 0; + + This->cursor.image = pScreen->resource_create(pScreen, &tmpl); + if (!This->cursor.image) + return D3DERR_OUTOFVIDEOMEMORY; + + /* For uploading 32x32 (argb) cursor */ + This->cursor.hw_upload_temp = MALLOC(32 * 4 * 32); + if (!This->cursor.hw_upload_temp) + return D3DERR_OUTOFVIDEOMEMORY; + } + + /* Create constant buffers. */ + { + unsigned max_const_vs, max_const_ps; + + /* vs 3.0: >= 256 float constants, but for cards with exactly 256 slots, + * we have to take in some more slots for int and bool*/ + max_const_vs = _min(pScreen->get_shader_param(pScreen, PIPE_SHADER_VERTEX, + PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE) / + sizeof(float[4]), + NINE_MAX_CONST_ALL); + /* ps 3.0: 224 float constants. All cards supported support at least + * 256 constants for ps */ + max_const_ps = NINE_MAX_CONST_F_PS3 + (NINE_MAX_CONST_I + NINE_MAX_CONST_B / 4); + + This->max_vs_const_f = max_const_vs - + (NINE_MAX_CONST_I + NINE_MAX_CONST_B / 4); + This->max_ps_const_f = max_const_ps - + (NINE_MAX_CONST_I + NINE_MAX_CONST_B / 4); + + This->vs_const_size = max_const_vs * sizeof(float[4]); + This->ps_const_size = max_const_ps * sizeof(float[4]); + /* Include space for I,B constants for user constbuf. */ + if (This->may_swvp) { + This->state.vs_const_f = CALLOC(NINE_MAX_CONST_F_SWVP * sizeof(float[4]),1); + This->context.vs_const_f_swvp = CALLOC(NINE_MAX_CONST_F_SWVP * sizeof(float[4]),1); + if (!This->context.vs_const_f_swvp) + return E_OUTOFMEMORY; + This->state.vs_lconstf_temp = CALLOC(NINE_MAX_CONST_F_SWVP * sizeof(float[4]),1); + This->context.vs_lconstf_temp = CALLOC(NINE_MAX_CONST_F_SWVP * sizeof(float[4]),1); + This->state.vs_const_i = CALLOC(NINE_MAX_CONST_I_SWVP * sizeof(int[4]), 1); + This->context.vs_const_i = CALLOC(NINE_MAX_CONST_I_SWVP * sizeof(int[4]), 1); + This->state.vs_const_b = CALLOC(NINE_MAX_CONST_B_SWVP * sizeof(BOOL), 1); + This->context.vs_const_b = CALLOC(NINE_MAX_CONST_B_SWVP * sizeof(BOOL), 1); + } else { + This->state.vs_const_f = CALLOC(NINE_MAX_CONST_F * sizeof(float[4]), 1); + This->context.vs_const_f_swvp = NULL; + This->state.vs_lconstf_temp = CALLOC(This->vs_const_size,1); + This->context.vs_lconstf_temp = CALLOC(This->vs_const_size,1); + This->state.vs_const_i = CALLOC(NINE_MAX_CONST_I * sizeof(int[4]), 1); + This->context.vs_const_i = CALLOC(NINE_MAX_CONST_I * sizeof(int[4]), 1); + This->state.vs_const_b = CALLOC(NINE_MAX_CONST_B * sizeof(BOOL), 1); + This->context.vs_const_b = CALLOC(NINE_MAX_CONST_B * sizeof(BOOL), 1); + } + This->context.vs_const_f = CALLOC(This->vs_const_size, 1); + This->state.ps_const_f = CALLOC(This->ps_const_size, 1); + This->context.ps_const_f = CALLOC(This->ps_const_size, 1); + This->context.ps_lconstf_temp = CALLOC(This->ps_const_size,1); + if (!This->state.vs_const_f || !This->context.vs_const_f || + !This->state.ps_const_f || !This->context.ps_const_f || + !This->state.vs_lconstf_temp || !This->context.vs_lconstf_temp || + !This->context.ps_lconstf_temp || + !This->state.vs_const_i || !This->context.vs_const_i || + !This->state.vs_const_b || !This->context.vs_const_b) + return E_OUTOFMEMORY; + + if (strstr(pScreen->get_name(pScreen), "AMD") || + strstr(pScreen->get_name(pScreen), "ATI")) { + This->driver_bugs.buggy_barycentrics = TRUE; + } + } + + /* allocate dummy texture/sampler for when there are missing ones bound */ + { + struct pipe_resource tmplt; + struct pipe_sampler_view templ; + struct pipe_sampler_state samp; + memset(&tmplt, 0, sizeof(tmplt)); + memset(&samp, 0, sizeof(samp)); + + tmplt.target = PIPE_TEXTURE_2D; + tmplt.width0 = 1; + tmplt.height0 = 1; + tmplt.depth0 = 1; + tmplt.last_level = 0; + tmplt.array_size = 1; + tmplt.usage = PIPE_USAGE_DEFAULT; + tmplt.flags = 0; + tmplt.format = PIPE_FORMAT_B8G8R8A8_UNORM; + tmplt.bind = PIPE_BIND_SAMPLER_VIEW; + tmplt.nr_samples = 0; + + This->dummy_texture = This->screen->resource_create(This->screen, &tmplt); + if (!This->dummy_texture) + return D3DERR_DRIVERINTERNALERROR; + + templ.format = PIPE_FORMAT_B8G8R8A8_UNORM; + templ.u.tex.first_layer = 0; + templ.u.tex.last_layer = 0; + templ.u.tex.first_level = 0; + templ.u.tex.last_level = 0; + templ.swizzle_r = PIPE_SWIZZLE_0; + templ.swizzle_g = PIPE_SWIZZLE_0; + templ.swizzle_b = PIPE_SWIZZLE_0; + templ.swizzle_a = PIPE_SWIZZLE_1; + templ.target = This->dummy_texture->target; + + This->dummy_sampler_view = This->context.pipe->create_sampler_view(This->context.pipe, This->dummy_texture, &templ); + if (!This->dummy_sampler_view) + return D3DERR_DRIVERINTERNALERROR; + + samp.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; + samp.max_lod = 15.0f; + samp.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + samp.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + samp.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + samp.min_img_filter = PIPE_TEX_FILTER_NEAREST; + samp.mag_img_filter = PIPE_TEX_FILTER_NEAREST; + samp.compare_mode = PIPE_TEX_COMPARE_NONE; + samp.compare_func = PIPE_FUNC_LEQUAL; + samp.normalized_coords = 1; + samp.seamless_cube_map = 0; + This->dummy_sampler_state = samp; + } + + /* Allocate upload helper for drivers that suck (from st pov ;). */ + + This->driver_caps.user_vbufs = GET_PCAP(USER_VERTEX_BUFFERS) && !This->csmt_active; + This->driver_caps.user_sw_vbufs = This->screen_sw->get_param(This->screen_sw, PIPE_CAP_USER_VERTEX_BUFFERS); + This->vertex_uploader = This->csmt_active ? This->pipe_secondary->stream_uploader : This->context.pipe->stream_uploader; + This->driver_caps.window_space_position_support = GET_PCAP(TGSI_VS_WINDOW_SPACE_POSITION); + This->driver_caps.vs_integer = pScreen->get_shader_param(pScreen, PIPE_SHADER_VERTEX, PIPE_SHADER_CAP_INTEGERS); + This->driver_caps.ps_integer = pScreen->get_shader_param(pScreen, PIPE_SHADER_FRAGMENT, PIPE_SHADER_CAP_INTEGERS); + This->driver_caps.offset_units_unscaled = GET_PCAP(POLYGON_OFFSET_UNITS_UNSCALED); + + This->context.inline_constants = pCTX->shader_inline_constants; + /* Code would be needed when integers are not available to correctly + * handle the conversion of integer constants */ + This->context.inline_constants &= This->driver_caps.vs_integer && This->driver_caps.ps_integer; + + nine_ff_init(This); /* initialize fixed function code */ + + NineDevice9_SetDefaultState(This, FALSE); + + { + struct pipe_poly_stipple stipple; + memset(&stipple, ~0, sizeof(stipple)); + This->context.pipe->set_polygon_stipple(This->context.pipe, &stipple); + } + + This->update = &This->state; + + nine_state_init_sw(This); + + ID3DPresentGroup_Release(This->present); + nine_csmt_process(This); + + return D3D_OK; +} +#undef GET_PCAP + +void +NineDevice9_dtor( struct NineDevice9 *This ) +{ + unsigned i; + + DBG("This=%p\n", This); + + /* Flush all pending commands to get refcount right, + * and properly release bound objects. It is ok to still + * execute commands while we are in device dtor, because + * we haven't released anything yet. Note that no pending + * command can increase the device refcount. */ + if (This->csmt_active && This->csmt_ctx) { + nine_csmt_process(This); + nine_csmt_destroy(This, This->csmt_ctx); + This->csmt_active = FALSE; + This->csmt_ctx = NULL; + } + + nine_ff_fini(This); + nine_state_destroy_sw(This); + nine_device_state_clear(This); + nine_context_clear(This); + + nine_bind(&This->record, NULL); + + pipe_sampler_view_reference(&This->dummy_sampler_view, NULL); + pipe_resource_reference(&This->dummy_texture, NULL); + pipe_resource_reference(&This->dummy_vbo, NULL); + FREE(This->state.vs_const_f); + FREE(This->context.vs_const_f); + FREE(This->state.ps_const_f); + FREE(This->context.ps_const_f); + FREE(This->state.vs_lconstf_temp); + FREE(This->context.vs_lconstf_temp); + FREE(This->context.ps_lconstf_temp); + FREE(This->state.vs_const_i); + FREE(This->context.vs_const_i); + FREE(This->state.vs_const_b); + FREE(This->context.vs_const_b); + FREE(This->context.vs_const_f_swvp); + + pipe_resource_reference(&This->cursor.image, NULL); + FREE(This->cursor.hw_upload_temp); + + if (This->swapchains) { + for (i = 0; i < This->nswapchains; ++i) + if (This->swapchains[i]) + NineUnknown_Unbind(NineUnknown(This->swapchains[i])); + FREE(This->swapchains); + } + + if (This->buffer_upload) + nine_upload_destroy(This->buffer_upload); + + /* Destroy cso first */ + if (This->context.cso) { cso_destroy_context(This->context.cso); } + if (This->cso_sw) { cso_destroy_context(This->cso_sw); } + if (This->context.pipe && This->context.pipe->destroy) { This->context.pipe->destroy(This->context.pipe); } + if (This->pipe_secondary && This->pipe_secondary->destroy) { This->pipe_secondary->destroy(This->pipe_secondary); } + if (This->pipe_sw && This->pipe_sw->destroy) { This->pipe_sw->destroy(This->pipe_sw); } + + if (This->present) { ID3DPresentGroup_Release(This->present); } + if (This->d3d9) { IDirect3D9_Release(This->d3d9); } + + NineUnknown_dtor(&This->base); + glsl_type_singleton_decref(); +} + +struct pipe_screen * +NineDevice9_GetScreen( struct NineDevice9 *This ) +{ + return This->screen; +} + +struct pipe_context * +NineDevice9_GetPipe( struct NineDevice9 *This ) +{ + return nine_context_get_pipe(This); +} + +const D3DCAPS9 * +NineDevice9_GetCaps( struct NineDevice9 *This ) +{ + return &This->caps; +} + +static inline void +NineDevice9_PauseRecording( struct NineDevice9 *This ) +{ + if (This->record) { + This->update = &This->state; + This->is_recording = FALSE; + } +} + +static inline void +NineDevice9_ResumeRecording( struct NineDevice9 *This ) +{ + if (This->record) { + This->update = &This->record->state; + This->is_recording = TRUE; + } +} + +HRESULT NINE_WINAPI +NineDevice9_TestCooperativeLevel( struct NineDevice9 *This ) +{ + if (NineSwapChain9_GetOccluded(This->swapchains[0])) { + This->device_needs_reset = TRUE; + return D3DERR_DEVICELOST; + } else if (NineSwapChain9_ResolutionMismatch(This->swapchains[0])) { + This->device_needs_reset = TRUE; + return D3DERR_DEVICENOTRESET; + } else if (This->device_needs_reset) { + return D3DERR_DEVICENOTRESET; + } + + return D3D_OK; +} + +UINT NINE_WINAPI +NineDevice9_GetAvailableTextureMem( struct NineDevice9 *This ) +{ + return This->available_texture_mem; +} + +HRESULT NINE_WINAPI +NineDevice9_EvictManagedResources( struct NineDevice9 *This ) +{ + struct NineBaseTexture9 *tex; + struct NineBuffer9 *buf; + + DBG("This=%p\n", This); + LIST_FOR_EACH_ENTRY(tex, &This->managed_textures, list2) { + NineBaseTexture9_UnLoad(tex); + } + /* Vertex/index buffers don't take a lot of space and aren't accounted + * for d3d memory usage. Instead of actually freeing from memory, + * just mark the buffer dirty to trigger a re-upload later. We + * could just ignore, but some bad behaving apps could rely on it (if + * they write outside the locked regions typically). */ + LIST_FOR_EACH_ENTRY(buf, &This->managed_buffers, managed.list2) { + NineBuffer9_SetDirty(buf); + } + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_GetDirect3D( struct NineDevice9 *This, + IDirect3D9 **ppD3D9 ) +{ + user_assert(ppD3D9 != NULL, E_POINTER); + IDirect3D9_AddRef(This->d3d9); + *ppD3D9 = This->d3d9; + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_GetDeviceCaps( struct NineDevice9 *This, + D3DCAPS9 *pCaps ) +{ + user_assert(pCaps != NULL, D3DERR_INVALIDCALL); + *pCaps = This->caps; + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_GetDisplayMode( struct NineDevice9 *This, + UINT iSwapChain, + D3DDISPLAYMODE *pMode ) +{ + DBG("This=%p iSwapChain=%u pMode=%p\n", This, iSwapChain, pMode); + + user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL); + + return NineSwapChain9_GetDisplayMode(This->swapchains[iSwapChain], pMode); +} + +HRESULT NINE_WINAPI +NineDevice9_GetCreationParameters( struct NineDevice9 *This, + D3DDEVICE_CREATION_PARAMETERS *pParameters ) +{ + user_assert(pParameters != NULL, D3DERR_INVALIDCALL); + *pParameters = This->params; + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_SetCursorProperties( struct NineDevice9 *This, + UINT XHotSpot, + UINT YHotSpot, + IDirect3DSurface9 *pCursorBitmap ) +{ + struct NineSurface9 *surf = NineSurface9(pCursorBitmap); + struct pipe_context *pipe = NineDevice9_GetPipe(This); + struct pipe_box box; + struct pipe_transfer *transfer; + BOOL hw_cursor; + void *ptr; + + DBG_FLAG(DBG_SWAPCHAIN, "This=%p XHotSpot=%u YHotSpot=%u " + "pCursorBitmap=%p\n", This, XHotSpot, YHotSpot, pCursorBitmap); + + user_assert(pCursorBitmap, D3DERR_INVALIDCALL); + user_assert(surf->desc.Format == D3DFMT_A8R8G8B8, D3DERR_INVALIDCALL); + + if (This->swapchains[0]->params.Windowed) { + This->cursor.w = MIN2(surf->desc.Width, 32); + This->cursor.h = MIN2(surf->desc.Height, 32); + hw_cursor = 1; /* always use hw cursor for windowed mode */ + } else { + This->cursor.w = MIN2(surf->desc.Width, This->cursor.image->width0); + This->cursor.h = MIN2(surf->desc.Height, This->cursor.image->height0); + hw_cursor = This->cursor.w == 32 && This->cursor.h == 32; + } + + u_box_origin_2d(This->cursor.w, This->cursor.h, &box); + + ptr = pipe->transfer_map(pipe, This->cursor.image, 0, + PIPE_TRANSFER_WRITE | + PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE, + &box, &transfer); + if (!ptr) + ret_err("Failed to update cursor image.\n", D3DERR_DRIVERINTERNALERROR); + + This->cursor.hotspot.x = XHotSpot; + This->cursor.hotspot.y = YHotSpot; + + /* Copy cursor image to internal storage. */ + { + D3DLOCKED_RECT lock; + HRESULT hr; + const struct util_format_description *sfmt = + util_format_description(surf->base.info.format); + assert(sfmt); + + hr = NineSurface9_LockRect(surf, &lock, NULL, D3DLOCK_READONLY); + if (FAILED(hr)) + ret_err("Failed to map cursor source image.\n", + D3DERR_DRIVERINTERNALERROR); + + sfmt->unpack_rgba_8unorm(ptr, transfer->stride, + lock.pBits, lock.Pitch, + This->cursor.w, This->cursor.h); + + if (hw_cursor) { + void *data = lock.pBits; + /* SetCursor assumes 32x32 argb with pitch 128 */ + if (lock.Pitch != 128) { + sfmt->unpack_rgba_8unorm(This->cursor.hw_upload_temp, 128, + lock.pBits, lock.Pitch, + 32, 32); + data = This->cursor.hw_upload_temp; + } + hw_cursor = ID3DPresent_SetCursor(This->swapchains[0]->present, + data, + &This->cursor.hotspot, + This->cursor.visible) == D3D_OK; + } + + NineSurface9_UnlockRect(surf); + } + pipe->transfer_unmap(pipe, transfer); + + /* hide cursor if we emulate it */ + if (!hw_cursor) + ID3DPresent_SetCursor(This->swapchains[0]->present, NULL, NULL, FALSE); + This->cursor.software = !hw_cursor; + + return D3D_OK; +} + +void NINE_WINAPI +NineDevice9_SetCursorPosition( struct NineDevice9 *This, + int X, + int Y, + DWORD Flags ) +{ + struct NineSwapChain9 *swap = This->swapchains[0]; + + DBG("This=%p X=%d Y=%d Flags=%d\n", This, X, Y, Flags); + + /* present >= v1.4 handles this itself */ + if (This->minor_version_num < 4) { + if (This->cursor.pos.x == X && This->cursor.pos.y == Y) + return; + } + + This->cursor.pos.x = X; + This->cursor.pos.y = Y; + + if (!This->cursor.software) + This->cursor.software = ID3DPresent_SetCursorPos(swap->present, &This->cursor.pos) != D3D_OK; +} + +BOOL NINE_WINAPI +NineDevice9_ShowCursor( struct NineDevice9 *This, + BOOL bShow ) +{ + BOOL old = This->cursor.visible; + + DBG("This=%p bShow=%d\n", This, (int) bShow); + + /* No-op until a cursor is set in d3d */ + if (This->cursor.hotspot.x == -1) + return old; + + This->cursor.visible = bShow; + /* Note: Don't optimize by avoiding the call if This->cursor.visible + * hasn't changed. One has to keep in mind the app may do SetCursor + * calls outside d3d, thus such an optimization affects behaviour. */ + if (!This->cursor.software) + This->cursor.software = ID3DPresent_SetCursor(This->swapchains[0]->present, NULL, NULL, bShow) != D3D_OK; + + return old; +} + +HRESULT NINE_WINAPI +NineDevice9_CreateAdditionalSwapChain( struct NineDevice9 *This, + D3DPRESENT_PARAMETERS *pPresentationParameters, + IDirect3DSwapChain9 **pSwapChain ) +{ + struct NineSwapChain9 *swapchain, *tmplt = This->swapchains[0]; + ID3DPresent *present; + HRESULT hr; + + DBG("This=%p pPresentationParameters=%p pSwapChain=%p\n", + This, pPresentationParameters, pSwapChain); + + user_assert(pPresentationParameters, D3DERR_INVALIDCALL); + user_assert(tmplt->params.Windowed && pPresentationParameters->Windowed, D3DERR_INVALIDCALL); + + /* TODO: this deserves more tests */ + if (!pPresentationParameters->hDeviceWindow) + pPresentationParameters->hDeviceWindow = This->params.hFocusWindow; + + hr = ID3DPresentGroup_CreateAdditionalPresent(This->present, pPresentationParameters, &present); + + if (FAILED(hr)) + return hr; + + hr = NineSwapChain9_new(This, FALSE, present, pPresentationParameters, + tmplt->actx, + tmplt->params.hDeviceWindow, + &swapchain); + if (FAILED(hr)) + return hr; + + *pSwapChain = (IDirect3DSwapChain9 *)swapchain; + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_GetSwapChain( struct NineDevice9 *This, + UINT iSwapChain, + IDirect3DSwapChain9 **pSwapChain ) +{ + user_assert(pSwapChain != NULL, D3DERR_INVALIDCALL); + + *pSwapChain = NULL; + user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL); + + NineUnknown_AddRef(NineUnknown(This->swapchains[iSwapChain])); + *pSwapChain = (IDirect3DSwapChain9 *)This->swapchains[iSwapChain]; + + return D3D_OK; +} + +UINT NINE_WINAPI +NineDevice9_GetNumberOfSwapChains( struct NineDevice9 *This ) +{ + return This->nswapchains; +} + +HRESULT NINE_WINAPI +NineDevice9_Reset( struct NineDevice9 *This, + D3DPRESENT_PARAMETERS *pPresentationParameters ) +{ + HRESULT hr = D3D_OK; + unsigned i; + + DBG("This=%p pPresentationParameters=%p\n", This, pPresentationParameters); + + if (NineSwapChain9_GetOccluded(This->swapchains[0])) { + This->device_needs_reset = TRUE; + return D3DERR_DEVICELOST; + } + + for (i = 0; i < This->nswapchains; ++i) { + D3DPRESENT_PARAMETERS *params = &pPresentationParameters[i]; + hr = NineSwapChain9_Resize(This->swapchains[i], params, NULL); + if (hr != D3D_OK) + break; + } + + nine_csmt_process(This); + nine_device_state_clear(This); + nine_context_clear(This); + + NineDevice9_SetDefaultState(This, TRUE); + NineDevice9_SetRenderTarget( + This, 0, (IDirect3DSurface9 *)This->swapchains[0]->buffers[0]); + /* XXX: better use GetBackBuffer here ? */ + + This->device_needs_reset = (hr != D3D_OK); + return hr; +} + +HRESULT NINE_WINAPI +NineDevice9_Present( struct NineDevice9 *This, + const RECT *pSourceRect, + const RECT *pDestRect, + HWND hDestWindowOverride, + const RGNDATA *pDirtyRegion ) +{ + unsigned i; + HRESULT hr; + + DBG("This=%p pSourceRect=%p pDestRect=%p hDestWindowOverride=%p pDirtyRegion=%p\n", + This, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion); + + /* XXX is this right? */ + for (i = 0; i < This->nswapchains; ++i) { + hr = NineSwapChain9_Present(This->swapchains[i], pSourceRect, pDestRect, + hDestWindowOverride, pDirtyRegion, 0); + if (FAILED(hr)) { return hr; } + } + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_GetBackBuffer( struct NineDevice9 *This, + UINT iSwapChain, + UINT iBackBuffer, + D3DBACKBUFFER_TYPE Type, + IDirect3DSurface9 **ppBackBuffer ) +{ + user_assert(ppBackBuffer != NULL, D3DERR_INVALIDCALL); + /* return NULL on error */ + *ppBackBuffer = NULL; + user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL); + + return NineSwapChain9_GetBackBuffer(This->swapchains[iSwapChain], + iBackBuffer, Type, ppBackBuffer); +} + +HRESULT NINE_WINAPI +NineDevice9_GetRasterStatus( struct NineDevice9 *This, + UINT iSwapChain, + D3DRASTER_STATUS *pRasterStatus ) +{ + user_assert(pRasterStatus != NULL, D3DERR_INVALIDCALL); + user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL); + + return NineSwapChain9_GetRasterStatus(This->swapchains[iSwapChain], + pRasterStatus); +} + +HRESULT NINE_WINAPI +NineDevice9_SetDialogBoxMode( struct NineDevice9 *This, + BOOL bEnableDialogs ) +{ + STUB(D3DERR_INVALIDCALL); +} + +void NINE_WINAPI +NineDevice9_SetGammaRamp( struct NineDevice9 *This, + UINT iSwapChain, + DWORD Flags, + const D3DGAMMARAMP *pRamp ) +{ + DBG("This=%p iSwapChain=%u Flags=%x pRamp=%p\n", This, + iSwapChain, Flags, pRamp); + + user_warn(iSwapChain >= This->nswapchains); + user_warn(!pRamp); + + if (pRamp && (iSwapChain < This->nswapchains)) { + struct NineSwapChain9 *swap = This->swapchains[iSwapChain]; + swap->gamma = *pRamp; + ID3DPresent_SetGammaRamp(swap->present, pRamp, swap->params.hDeviceWindow); + } +} + +void NINE_WINAPI +NineDevice9_GetGammaRamp( struct NineDevice9 *This, + UINT iSwapChain, + D3DGAMMARAMP *pRamp ) +{ + DBG("This=%p iSwapChain=%u pRamp=%p\n", This, iSwapChain, pRamp); + + user_warn(iSwapChain >= This->nswapchains); + user_warn(!pRamp); + + if (pRamp && (iSwapChain < This->nswapchains)) + *pRamp = This->swapchains[iSwapChain]->gamma; +} + +HRESULT NINE_WINAPI +NineDevice9_CreateTexture( struct NineDevice9 *This, + UINT Width, + UINT Height, + UINT Levels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + IDirect3DTexture9 **ppTexture, + HANDLE *pSharedHandle ) +{ + struct NineTexture9 *tex; + HRESULT hr; + + DBG("This=%p Width=%u Height=%u Levels=%u Usage=%s Format=%s Pool=%s " + "ppOut=%p pSharedHandle=%p\n", This, Width, Height, Levels, + nine_D3DUSAGE_to_str(Usage), d3dformat_to_string(Format), + nine_D3DPOOL_to_str(Pool), ppTexture, pSharedHandle); + + Usage &= D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_DMAP | + D3DUSAGE_DYNAMIC | D3DUSAGE_NONSECURE | D3DUSAGE_RENDERTARGET | + D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_TEXTAPI; + + *ppTexture = NULL; + + hr = NineTexture9_new(This, Width, Height, Levels, Usage, Format, Pool, + &tex, pSharedHandle); + if (SUCCEEDED(hr)) + *ppTexture = (IDirect3DTexture9 *)tex; + + return hr; +} + +HRESULT NINE_WINAPI +NineDevice9_CreateVolumeTexture( struct NineDevice9 *This, + UINT Width, + UINT Height, + UINT Depth, + UINT Levels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + IDirect3DVolumeTexture9 **ppVolumeTexture, + HANDLE *pSharedHandle ) +{ + struct NineVolumeTexture9 *tex; + HRESULT hr; + + DBG("This=%p Width=%u Height=%u Depth=%u Levels=%u Usage=%s Format=%s Pool=%s " + "ppOut=%p pSharedHandle=%p\n", This, Width, Height, Depth, Levels, + nine_D3DUSAGE_to_str(Usage), d3dformat_to_string(Format), + nine_D3DPOOL_to_str(Pool), ppVolumeTexture, pSharedHandle); + + Usage &= D3DUSAGE_DYNAMIC | D3DUSAGE_NONSECURE | + D3DUSAGE_SOFTWAREPROCESSING; + + *ppVolumeTexture = NULL; + + hr = NineVolumeTexture9_new(This, Width, Height, Depth, Levels, + Usage, Format, Pool, &tex, pSharedHandle); + if (SUCCEEDED(hr)) + *ppVolumeTexture = (IDirect3DVolumeTexture9 *)tex; + + return hr; +} + +HRESULT NINE_WINAPI +NineDevice9_CreateCubeTexture( struct NineDevice9 *This, + UINT EdgeLength, + UINT Levels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + IDirect3DCubeTexture9 **ppCubeTexture, + HANDLE *pSharedHandle ) +{ + struct NineCubeTexture9 *tex; + HRESULT hr; + + DBG("This=%p EdgeLength=%u Levels=%u Usage=%s Format=%s Pool=%s ppOut=%p " + "pSharedHandle=%p\n", This, EdgeLength, Levels, + nine_D3DUSAGE_to_str(Usage), d3dformat_to_string(Format), + nine_D3DPOOL_to_str(Pool), ppCubeTexture, pSharedHandle); + + Usage &= D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_DYNAMIC | + D3DUSAGE_NONSECURE | D3DUSAGE_RENDERTARGET | + D3DUSAGE_SOFTWAREPROCESSING; + + *ppCubeTexture = NULL; + + hr = NineCubeTexture9_new(This, EdgeLength, Levels, Usage, Format, Pool, + &tex, pSharedHandle); + if (SUCCEEDED(hr)) + *ppCubeTexture = (IDirect3DCubeTexture9 *)tex; + + return hr; +} + +HRESULT NINE_WINAPI +NineDevice9_CreateVertexBuffer( struct NineDevice9 *This, + UINT Length, + DWORD Usage, + DWORD FVF, + D3DPOOL Pool, + IDirect3DVertexBuffer9 **ppVertexBuffer, + HANDLE *pSharedHandle ) +{ + struct NineVertexBuffer9 *buf; + HRESULT hr; + D3DVERTEXBUFFER_DESC desc; + + DBG("This=%p Length=%u Usage=%x FVF=%x Pool=%u ppOut=%p pSharedHandle=%p\n", + This, Length, Usage, FVF, Pool, ppVertexBuffer, pSharedHandle); + + user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_NOTAVAILABLE); + + desc.Format = D3DFMT_VERTEXDATA; + desc.Type = D3DRTYPE_VERTEXBUFFER; + desc.Usage = Usage & + (D3DUSAGE_DONOTCLIP | D3DUSAGE_DYNAMIC | D3DUSAGE_NONSECURE | + D3DUSAGE_NPATCHES | D3DUSAGE_POINTS | D3DUSAGE_RTPATCHES | + D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_TEXTAPI | + D3DUSAGE_WRITEONLY); + desc.Pool = Pool; + desc.Size = Length; + desc.FVF = FVF; + + user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); + user_assert(desc.Usage == Usage, D3DERR_INVALIDCALL); + + hr = NineVertexBuffer9_new(This, &desc, &buf); + if (SUCCEEDED(hr)) + *ppVertexBuffer = (IDirect3DVertexBuffer9 *)buf; + return hr; +} + +HRESULT NINE_WINAPI +NineDevice9_CreateIndexBuffer( struct NineDevice9 *This, + UINT Length, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + IDirect3DIndexBuffer9 **ppIndexBuffer, + HANDLE *pSharedHandle ) +{ + struct NineIndexBuffer9 *buf; + HRESULT hr; + D3DINDEXBUFFER_DESC desc; + + DBG("This=%p Length=%u Usage=%x Format=%s Pool=%u ppOut=%p " + "pSharedHandle=%p\n", This, Length, Usage, + d3dformat_to_string(Format), Pool, ppIndexBuffer, pSharedHandle); + + user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_NOTAVAILABLE); + + desc.Format = Format; + desc.Type = D3DRTYPE_INDEXBUFFER; + desc.Usage = Usage & + (D3DUSAGE_DONOTCLIP | D3DUSAGE_DYNAMIC | D3DUSAGE_NONSECURE | + D3DUSAGE_NPATCHES | D3DUSAGE_POINTS | D3DUSAGE_RTPATCHES | + D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_WRITEONLY); + desc.Pool = Pool; + desc.Size = Length; + + user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); + user_assert(desc.Usage == Usage, D3DERR_INVALIDCALL); + + hr = NineIndexBuffer9_new(This, &desc, &buf); + if (SUCCEEDED(hr)) + *ppIndexBuffer = (IDirect3DIndexBuffer9 *)buf; + return hr; +} + +static HRESULT +create_zs_or_rt_surface(struct NineDevice9 *This, + unsigned type, /* 0 = RT, 1 = ZS, 2 = plain */ + D3DPOOL Pool, + UINT Width, UINT Height, + D3DFORMAT Format, + D3DMULTISAMPLE_TYPE MultiSample, + DWORD MultisampleQuality, + BOOL Discard_or_Lockable, + IDirect3DSurface9 **ppSurface, + HANDLE *pSharedHandle) +{ + struct NineSurface9 *surface; + HRESULT hr; + D3DSURFACE_DESC desc; + + DBG("This=%p type=%u Pool=%s Width=%u Height=%u Format=%s MS=%u Quality=%u " + "Discard_or_Lockable=%i ppSurface=%p pSharedHandle=%p\n", + This, type, nine_D3DPOOL_to_str(Pool), Width, Height, + d3dformat_to_string(Format), MultiSample, MultisampleQuality, + Discard_or_Lockable, ppSurface, pSharedHandle); + + if (pSharedHandle) + DBG("FIXME Used shared handle! This option isn't probably handled correctly!\n"); + + user_assert(Width && Height, D3DERR_INVALIDCALL); + user_assert(Pool != D3DPOOL_MANAGED, D3DERR_INVALIDCALL); + + desc.Format = Format; + desc.Type = D3DRTYPE_SURFACE; + desc.Usage = 0; + desc.Pool = Pool; + desc.MultiSampleType = MultiSample; + desc.MultiSampleQuality = MultisampleQuality; + desc.Width = Width; + desc.Height = Height; + switch (type) { + case 0: desc.Usage = D3DUSAGE_RENDERTARGET; break; + case 1: desc.Usage = D3DUSAGE_DEPTHSTENCIL; break; + default: assert(type == 2); break; + } + + hr = NineSurface9_new(This, NULL, NULL, NULL, 0, 0, 0, &desc, &surface); + if (SUCCEEDED(hr)) { + *ppSurface = (IDirect3DSurface9 *)surface; + + if (surface->base.resource && Discard_or_Lockable && (type != 1)) + surface->base.resource->flags |= NINE_RESOURCE_FLAG_LOCKABLE; + } + + return hr; +} + +HRESULT NINE_WINAPI +NineDevice9_CreateRenderTarget( struct NineDevice9 *This, + UINT Width, + UINT Height, + D3DFORMAT Format, + D3DMULTISAMPLE_TYPE MultiSample, + DWORD MultisampleQuality, + BOOL Lockable, + IDirect3DSurface9 **ppSurface, + HANDLE *pSharedHandle ) +{ + *ppSurface = NULL; + return create_zs_or_rt_surface(This, 0, D3DPOOL_DEFAULT, + Width, Height, Format, + MultiSample, MultisampleQuality, + Lockable, ppSurface, pSharedHandle); +} + +HRESULT NINE_WINAPI +NineDevice9_CreateDepthStencilSurface( struct NineDevice9 *This, + UINT Width, + UINT Height, + D3DFORMAT Format, + D3DMULTISAMPLE_TYPE MultiSample, + DWORD MultisampleQuality, + BOOL Discard, + IDirect3DSurface9 **ppSurface, + HANDLE *pSharedHandle ) +{ + *ppSurface = NULL; + if (!depth_stencil_format(Format)) + return D3DERR_NOTAVAILABLE; + return create_zs_or_rt_surface(This, 1, D3DPOOL_DEFAULT, + Width, Height, Format, + MultiSample, MultisampleQuality, + Discard, ppSurface, pSharedHandle); +} + +HRESULT NINE_WINAPI +NineDevice9_UpdateSurface( struct NineDevice9 *This, + IDirect3DSurface9 *pSourceSurface, + const RECT *pSourceRect, + IDirect3DSurface9 *pDestinationSurface, + const POINT *pDestPoint ) +{ + struct NineSurface9 *dst = NineSurface9(pDestinationSurface); + struct NineSurface9 *src = NineSurface9(pSourceSurface); + int copy_width, copy_height; + RECT destRect; + + DBG("This=%p pSourceSurface=%p pDestinationSurface=%p " + "pSourceRect=%p pDestPoint=%p\n", This, + pSourceSurface, pDestinationSurface, pSourceRect, pDestPoint); + if (pSourceRect) + DBG("pSourceRect = (%u,%u)-(%u,%u)\n", + pSourceRect->left, pSourceRect->top, + pSourceRect->right, pSourceRect->bottom); + if (pDestPoint) + DBG("pDestPoint = (%u,%u)\n", pDestPoint->x, pDestPoint->y); + + user_assert(dst && src, D3DERR_INVALIDCALL); + + user_assert(dst->base.pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); + user_assert(src->base.pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL); + + user_assert(dst->desc.MultiSampleType == D3DMULTISAMPLE_NONE, D3DERR_INVALIDCALL); + user_assert(src->desc.MultiSampleType == D3DMULTISAMPLE_NONE, D3DERR_INVALIDCALL); + + user_assert(!src->lock_count, D3DERR_INVALIDCALL); + user_assert(!dst->lock_count, D3DERR_INVALIDCALL); + + user_assert(dst->desc.Format == src->desc.Format, D3DERR_INVALIDCALL); + user_assert(!depth_stencil_format(dst->desc.Format), D3DERR_INVALIDCALL); + + if (pSourceRect) { + copy_width = pSourceRect->right - pSourceRect->left; + copy_height = pSourceRect->bottom - pSourceRect->top; + + user_assert(pSourceRect->left >= 0 && + copy_width > 0 && + pSourceRect->right <= src->desc.Width && + pSourceRect->top >= 0 && + copy_height > 0 && + pSourceRect->bottom <= src->desc.Height, + D3DERR_INVALIDCALL); + } else { + copy_width = src->desc.Width; + copy_height = src->desc.Height; + } + + destRect.right = copy_width; + destRect.bottom = copy_height; + + if (pDestPoint) { + user_assert(pDestPoint->x >= 0 && pDestPoint->y >= 0, + D3DERR_INVALIDCALL); + destRect.right += pDestPoint->x; + destRect.bottom += pDestPoint->y; + } + + user_assert(destRect.right <= dst->desc.Width && + destRect.bottom <= dst->desc.Height, + D3DERR_INVALIDCALL); + + if (compressed_format(dst->desc.Format)) { + const unsigned w = util_format_get_blockwidth(dst->base.info.format); + const unsigned h = util_format_get_blockheight(dst->base.info.format); + + if (pDestPoint) { + user_assert(!(pDestPoint->x % w) && !(pDestPoint->y % h), + D3DERR_INVALIDCALL); + } + + if (pSourceRect) { + user_assert(!(pSourceRect->left % w) && !(pSourceRect->top % h), + D3DERR_INVALIDCALL); + } + if (!(copy_width == src->desc.Width && + copy_width == dst->desc.Width && + copy_height == src->desc.Height && + copy_height == dst->desc.Height)) { + user_assert(!(copy_width % w) && !(copy_height % h), + D3DERR_INVALIDCALL); + } + } + + NineSurface9_CopyMemToDefault(dst, src, pDestPoint, pSourceRect); + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_UpdateTexture( struct NineDevice9 *This, + IDirect3DBaseTexture9 *pSourceTexture, + IDirect3DBaseTexture9 *pDestinationTexture ) +{ + struct NineBaseTexture9 *dstb = NineBaseTexture9(pDestinationTexture); + struct NineBaseTexture9 *srcb = NineBaseTexture9(pSourceTexture); + unsigned l, m; + unsigned last_src_level, last_dst_level; + RECT rect; + + DBG("This=%p pSourceTexture=%p pDestinationTexture=%p\n", This, + pSourceTexture, pDestinationTexture); + + user_assert(pSourceTexture && pDestinationTexture, D3DERR_INVALIDCALL); + user_assert(pSourceTexture != pDestinationTexture, D3DERR_INVALIDCALL); + + user_assert(dstb->base.pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); + user_assert(srcb->base.pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL); + user_assert(dstb->base.type == srcb->base.type, D3DERR_INVALIDCALL); + user_assert(!(srcb->base.usage & D3DUSAGE_AUTOGENMIPMAP) || + dstb->base.usage & D3DUSAGE_AUTOGENMIPMAP, D3DERR_INVALIDCALL); + + /* Spec: Failure if + * . Different formats + * . Fewer src levels than dst levels (if the opposite, only matching levels + * are supposed to be copied) + * . Levels do not match + * DDI: Actually the above should pass because of legacy applications + * Do what you want about these, but you shouldn't crash. + * However driver can expect that the top dimension is greater for src than dst. + * Wine tests: Every combination that passes the initial checks should pass. + * . Different formats => conversion driver and format dependent. + * . 1 level, but size not matching => copy is done (and even crash if src bigger + * than dst. For the case where dst bigger, wine doesn't test if a stretch is applied + * or if a subrect is copied). + * . 8x8 4 sublevels -> 7x7 2 sublevels => driver dependent, On NV seems to be 4x4 subrect + * copied to 7x7. + * + * From these, the proposal is: + * . Different formats -> use util_format_translate to translate if possible for surfaces. + * Accept ARGB/XRGB for Volumes. Do nothing for the other combinations + * . First level copied -> the first level such that src is smaller or equal to dst first level + * . number of levels copied -> as long as it fits and textures have levels + * That should satisfy the constraints (and instead of crashing for some cases we return D3D_OK) + */ + + last_src_level = (srcb->base.usage & D3DUSAGE_AUTOGENMIPMAP) ? 0 : srcb->base.info.last_level; + last_dst_level = (dstb->base.usage & D3DUSAGE_AUTOGENMIPMAP) ? 0 : dstb->base.info.last_level; + + for (m = 0; m <= last_src_level; ++m) { + unsigned w = u_minify(srcb->base.info.width0, m); + unsigned h = u_minify(srcb->base.info.height0, m); + unsigned d = u_minify(srcb->base.info.depth0, m); + + if (w <= dstb->base.info.width0 && + h <= dstb->base.info.height0 && + d <= dstb->base.info.depth0) + break; + } + user_assert(m <= last_src_level, D3D_OK); + + last_dst_level = MIN2(srcb->base.info.last_level - m, last_dst_level); + + if (dstb->base.type == D3DRTYPE_TEXTURE) { + struct NineTexture9 *dst = NineTexture9(dstb); + struct NineTexture9 *src = NineTexture9(srcb); + + if (src->dirty_rect.width == 0) + return D3D_OK; + + pipe_box_to_rect(&rect, &src->dirty_rect); + for (l = 0; l < m; ++l) + rect_minify_inclusive(&rect); + + for (l = 0; l <= last_dst_level; ++l, ++m) { + fit_rect_format_inclusive(dst->base.base.info.format, + &rect, + dst->surfaces[l]->desc.Width, + dst->surfaces[l]->desc.Height); + NineSurface9_CopyMemToDefault(dst->surfaces[l], + src->surfaces[m], + (POINT *)&rect, + &rect); + rect_minify_inclusive(&rect); + } + u_box_origin_2d(0, 0, &src->dirty_rect); + } else + if (dstb->base.type == D3DRTYPE_CUBETEXTURE) { + struct NineCubeTexture9 *dst = NineCubeTexture9(dstb); + struct NineCubeTexture9 *src = NineCubeTexture9(srcb); + unsigned z; + + /* GPUs usually have them stored as arrays of mip-mapped 2D textures. */ + for (z = 0; z < 6; ++z) { + if (src->dirty_rect[z].width == 0) + continue; + + pipe_box_to_rect(&rect, &src->dirty_rect[z]); + for (l = 0; l < m; ++l) + rect_minify_inclusive(&rect); + + for (l = 0; l <= last_dst_level; ++l, ++m) { + fit_rect_format_inclusive(dst->base.base.info.format, + &rect, + dst->surfaces[l * 6 + z]->desc.Width, + dst->surfaces[l * 6 + z]->desc.Height); + NineSurface9_CopyMemToDefault(dst->surfaces[l * 6 + z], + src->surfaces[m * 6 + z], + (POINT *)&rect, + &rect); + rect_minify_inclusive(&rect); + } + u_box_origin_2d(0, 0, &src->dirty_rect[z]); + m -= l; + } + } else + if (dstb->base.type == D3DRTYPE_VOLUMETEXTURE) { + struct NineVolumeTexture9 *dst = NineVolumeTexture9(dstb); + struct NineVolumeTexture9 *src = NineVolumeTexture9(srcb); + + if (src->dirty_box.width == 0) + return D3D_OK; + for (l = 0; l <= last_dst_level; ++l, ++m) + NineVolume9_CopyMemToDefault(dst->volumes[l], + src->volumes[m], 0, 0, 0, NULL); + u_box_3d(0, 0, 0, 0, 0, 0, &src->dirty_box); + } else{ + assert(!"invalid texture type"); + } + + if (dstb->base.usage & D3DUSAGE_AUTOGENMIPMAP) { + dstb->dirty_mip = TRUE; + NineBaseTexture9_GenerateMipSubLevels(dstb); + } + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_GetRenderTargetData( struct NineDevice9 *This, + IDirect3DSurface9 *pRenderTarget, + IDirect3DSurface9 *pDestSurface ) +{ + struct NineSurface9 *dst = NineSurface9(pDestSurface); + struct NineSurface9 *src = NineSurface9(pRenderTarget); + + DBG("This=%p pRenderTarget=%p pDestSurface=%p\n", + This, pRenderTarget, pDestSurface); + + user_assert(pRenderTarget && pDestSurface, D3DERR_INVALIDCALL); + + user_assert(dst->desc.Pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL); + user_assert(src->desc.Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); + + user_assert(dst->desc.MultiSampleType < 2, D3DERR_INVALIDCALL); + user_assert(src->desc.MultiSampleType < 2, D3DERR_INVALIDCALL); + + user_assert(src->desc.Width == dst->desc.Width, D3DERR_INVALIDCALL); + user_assert(src->desc.Height == dst->desc.Height, D3DERR_INVALIDCALL); + + user_assert(src->desc.Format != D3DFMT_NULL, D3DERR_INVALIDCALL); + + NineSurface9_CopyDefaultToMem(dst, src); + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_GetFrontBufferData( struct NineDevice9 *This, + UINT iSwapChain, + IDirect3DSurface9 *pDestSurface ) +{ + DBG("This=%p iSwapChain=%u pDestSurface=%p\n", This, + iSwapChain, pDestSurface); + + user_assert(pDestSurface != NULL, D3DERR_INVALIDCALL); + user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL); + + return NineSwapChain9_GetFrontBufferData(This->swapchains[iSwapChain], + pDestSurface); +} + +HRESULT NINE_WINAPI +NineDevice9_StretchRect( struct NineDevice9 *This, + IDirect3DSurface9 *pSourceSurface, + const RECT *pSourceRect, + IDirect3DSurface9 *pDestSurface, + const RECT *pDestRect, + D3DTEXTUREFILTERTYPE Filter ) +{ + struct pipe_screen *screen = This->screen; + struct NineSurface9 *dst = NineSurface9(pDestSurface); + struct NineSurface9 *src = NineSurface9(pSourceSurface); + struct pipe_resource *dst_res = NineSurface9_GetResource(dst); + struct pipe_resource *src_res = NineSurface9_GetResource(src); + boolean zs; + struct pipe_blit_info blit; + boolean scaled, clamped, ms, flip_x = FALSE, flip_y = FALSE; + + DBG("This=%p pSourceSurface=%p pSourceRect=%p pDestSurface=%p " + "pDestRect=%p Filter=%u\n", + This, pSourceSurface, pSourceRect, pDestSurface, pDestRect, Filter); + if (pSourceRect) + DBG("pSourceRect=(%u,%u)-(%u,%u)\n", + pSourceRect->left, pSourceRect->top, + pSourceRect->right, pSourceRect->bottom); + if (pDestRect) + DBG("pDestRect=(%u,%u)-(%u,%u)\n", pDestRect->left, pDestRect->top, + pDestRect->right, pDestRect->bottom); + + user_assert(dst->base.pool == D3DPOOL_DEFAULT && + src->base.pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); + zs = util_format_is_depth_or_stencil(dst_res->format); + user_assert(!zs || !This->in_scene, D3DERR_INVALIDCALL); + user_assert(!zs || !pSourceRect || + (pSourceRect->left == 0 && + pSourceRect->top == 0 && + pSourceRect->right == src->desc.Width && + pSourceRect->bottom == src->desc.Height), D3DERR_INVALIDCALL); + user_assert(!zs || !pDestRect || + (pDestRect->left == 0 && + pDestRect->top == 0 && + pDestRect->right == dst->desc.Width && + pDestRect->bottom == dst->desc.Height), D3DERR_INVALIDCALL); + user_assert(!zs || + (dst->desc.Width == src->desc.Width && + dst->desc.Height == src->desc.Height), D3DERR_INVALIDCALL); + user_assert(zs || !util_format_is_depth_or_stencil(src_res->format), + D3DERR_INVALIDCALL); + user_assert(!zs || dst->desc.Format == src->desc.Format, + D3DERR_INVALIDCALL); + user_assert(screen->is_format_supported(screen, src_res->format, + src_res->target, + src_res->nr_samples, + src_res->nr_storage_samples, + PIPE_BIND_SAMPLER_VIEW), + D3DERR_INVALIDCALL); + + /* We might want to permit these, but wine thinks we shouldn't. */ + user_assert(!pDestRect || + (pDestRect->left <= pDestRect->right && + pDestRect->top <= pDestRect->bottom), D3DERR_INVALIDCALL); + user_assert(!pSourceRect || + (pSourceRect->left <= pSourceRect->right && + pSourceRect->top <= pSourceRect->bottom), D3DERR_INVALIDCALL); + + memset(&blit, 0, sizeof(blit)); + blit.dst.resource = dst_res; + blit.dst.level = dst->level; + blit.dst.box.z = dst->layer; + blit.dst.box.depth = 1; + blit.dst.format = dst_res->format; + if (pDestRect) { + flip_x = pDestRect->left > pDestRect->right; + if (flip_x) { + blit.dst.box.x = pDestRect->right; + blit.dst.box.width = pDestRect->left - pDestRect->right; + } else { + blit.dst.box.x = pDestRect->left; + blit.dst.box.width = pDestRect->right - pDestRect->left; + } + flip_y = pDestRect->top > pDestRect->bottom; + if (flip_y) { + blit.dst.box.y = pDestRect->bottom; + blit.dst.box.height = pDestRect->top - pDestRect->bottom; + } else { + blit.dst.box.y = pDestRect->top; + blit.dst.box.height = pDestRect->bottom - pDestRect->top; + } + } else { + blit.dst.box.x = 0; + blit.dst.box.y = 0; + blit.dst.box.width = dst->desc.Width; + blit.dst.box.height = dst->desc.Height; + } + blit.src.resource = src_res; + blit.src.level = src->level; + blit.src.box.z = src->layer; + blit.src.box.depth = 1; + blit.src.format = src_res->format; + if (pSourceRect) { + if (flip_x ^ (pSourceRect->left > pSourceRect->right)) { + blit.src.box.x = pSourceRect->right; + blit.src.box.width = pSourceRect->left - pSourceRect->right; + } else { + blit.src.box.x = pSourceRect->left; + blit.src.box.width = pSourceRect->right - pSourceRect->left; + } + if (flip_y ^ (pSourceRect->top > pSourceRect->bottom)) { + blit.src.box.y = pSourceRect->bottom; + blit.src.box.height = pSourceRect->top - pSourceRect->bottom; + } else { + blit.src.box.y = pSourceRect->top; + blit.src.box.height = pSourceRect->bottom - pSourceRect->top; + } + } else { + blit.src.box.x = flip_x ? src->desc.Width : 0; + blit.src.box.y = flip_y ? src->desc.Height : 0; + blit.src.box.width = flip_x ? -src->desc.Width : src->desc.Width; + blit.src.box.height = flip_y ? -src->desc.Height : src->desc.Height; + } + blit.mask = zs ? PIPE_MASK_ZS : PIPE_MASK_RGBA; + blit.filter = Filter == D3DTEXF_LINEAR ? + PIPE_TEX_FILTER_LINEAR : PIPE_TEX_FILTER_NEAREST; + blit.scissor_enable = FALSE; + blit.alpha_blend = FALSE; + + /* If both of a src and dst dimension are negative, flip them. */ + if (blit.dst.box.width < 0 && blit.src.box.width < 0) { + blit.dst.box.width = -blit.dst.box.width; + blit.src.box.width = -blit.src.box.width; + } + if (blit.dst.box.height < 0 && blit.src.box.height < 0) { + blit.dst.box.height = -blit.dst.box.height; + blit.src.box.height = -blit.src.box.height; + } + scaled = + blit.dst.box.width != blit.src.box.width || + blit.dst.box.height != blit.src.box.height; + + user_assert(!scaled || dst != src, D3DERR_INVALIDCALL); + user_assert(!scaled || + !NineSurface9_IsOffscreenPlain(dst), D3DERR_INVALIDCALL); + user_assert(!NineSurface9_IsOffscreenPlain(dst) || + NineSurface9_IsOffscreenPlain(src), D3DERR_INVALIDCALL); + user_assert(NineSurface9_IsOffscreenPlain(dst) || + dst->desc.Usage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL), + D3DERR_INVALIDCALL); + user_assert(!scaled || + (!util_format_is_compressed(dst->base.info.format) && + !util_format_is_compressed(src->base.info.format)), + D3DERR_INVALIDCALL); + + user_warn(src == dst && + u_box_test_intersection_2d(&blit.src.box, &blit.dst.box)); + + /* Check for clipping/clamping: */ + { + struct pipe_box box; + int xy; + + xy = u_box_clip_2d(&box, &blit.dst.box, + dst->desc.Width, dst->desc.Height); + if (xy < 0) + return D3D_OK; + if (xy == 0) + xy = u_box_clip_2d(&box, &blit.src.box, + src->desc.Width, src->desc.Height); + clamped = !!xy; + } + + ms = (dst->desc.MultiSampleType != src->desc.MultiSampleType) || + (dst->desc.MultiSampleQuality != src->desc.MultiSampleQuality); + + if (clamped || scaled || (blit.dst.format != blit.src.format) || ms) { + DBG("using pipe->blit()\n"); + /* TODO: software scaling */ + user_assert(screen->is_format_supported(screen, dst_res->format, + dst_res->target, + dst_res->nr_samples, + dst_res->nr_storage_samples, + zs ? PIPE_BIND_DEPTH_STENCIL : + PIPE_BIND_RENDER_TARGET), + D3DERR_INVALIDCALL); + + nine_context_blit(This, (struct NineUnknown *)dst, + (struct NineUnknown *)src, &blit); + } else { + assert(blit.dst.box.x >= 0 && blit.dst.box.y >= 0 && + blit.src.box.x >= 0 && blit.src.box.y >= 0 && + blit.dst.box.x + blit.dst.box.width <= dst->desc.Width && + blit.src.box.x + blit.src.box.width <= src->desc.Width && + blit.dst.box.y + blit.dst.box.height <= dst->desc.Height && + blit.src.box.y + blit.src.box.height <= src->desc.Height); + /* Or drivers might crash ... */ + DBG("Using resource_copy_region.\n"); + nine_context_resource_copy_region(This, (struct NineUnknown *)dst, + (struct NineUnknown *)src, + blit.dst.resource, blit.dst.level, + &blit.dst.box, + blit.src.resource, blit.src.level, + &blit.src.box); + } + + /* Communicate the container it needs to update sublevels - if apply */ + NineSurface9_MarkContainerDirty(dst); + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_ColorFill( struct NineDevice9 *This, + IDirect3DSurface9 *pSurface, + const RECT *pRect, + D3DCOLOR color ) +{ + struct NineSurface9 *surf = NineSurface9(pSurface); + unsigned x, y, w, h; + + DBG("This=%p pSurface=%p pRect=%p color=%08x\n", This, + pSurface, pRect, color); + if (pRect) + DBG("pRect=(%u,%u)-(%u,%u)\n", pRect->left, pRect->top, + pRect->right, pRect->bottom); + + user_assert(surf->base.pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); + + user_assert((surf->base.usage & D3DUSAGE_RENDERTARGET) || + NineSurface9_IsOffscreenPlain(surf), D3DERR_INVALIDCALL); + + user_assert(surf->desc.Format != D3DFMT_NULL, D3D_OK); + + if (pRect) { + x = pRect->left; + y = pRect->top; + w = pRect->right - pRect->left; + h = pRect->bottom - pRect->top; + /* Wine tests: */ + if (compressed_format(surf->desc.Format)) { + const unsigned bw = util_format_get_blockwidth(surf->base.info.format); + const unsigned bh = util_format_get_blockheight(surf->base.info.format); + + user_assert(!(x % bw) && !(y % bh) && !(w % bw) && !(h % bh), + D3DERR_INVALIDCALL); + } + } else{ + x = 0; + y = 0; + w = surf->desc.Width; + h = surf->desc.Height; + } + + if (surf->base.info.bind & PIPE_BIND_RENDER_TARGET) { + nine_context_clear_render_target(This, surf, color, x, y, w, h); + } else { + D3DLOCKED_RECT lock; + union util_color uc; + HRESULT hr; + /* XXX: lock pRect and fix util_fill_rect */ + hr = NineSurface9_LockRect(surf, &lock, NULL, pRect ? 0 : D3DLOCK_DISCARD); + if (FAILED(hr)) + return hr; + util_pack_color_ub(color >> 16, color >> 8, color >> 0, color >> 24, + surf->base.info.format, &uc); + util_fill_rect(lock.pBits, surf->base.info.format,lock.Pitch, + x, y, w, h, &uc); + NineSurface9_UnlockRect(surf); + } + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_CreateOffscreenPlainSurface( struct NineDevice9 *This, + UINT Width, + UINT Height, + D3DFORMAT Format, + D3DPOOL Pool, + IDirect3DSurface9 **ppSurface, + HANDLE *pSharedHandle ) +{ + HRESULT hr; + + DBG("This=%p Width=%u Height=%u Format=%s(0x%x) Pool=%u " + "ppSurface=%p pSharedHandle=%p\n", This, + Width, Height, d3dformat_to_string(Format), Format, Pool, + ppSurface, pSharedHandle); + + *ppSurface = NULL; + user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT + || Pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL); + user_assert(Pool != D3DPOOL_MANAGED, D3DERR_INVALIDCALL); + + /* Can be used with StretchRect and ColorFill. It's also always lockable. + */ + hr = create_zs_or_rt_surface(This, 2, Pool, Width, Height, + Format, + D3DMULTISAMPLE_NONE, 0, + TRUE, + ppSurface, pSharedHandle); + if (FAILED(hr)) + DBG("Failed to create surface.\n"); + return hr; +} + +HRESULT NINE_WINAPI +NineDevice9_SetRenderTarget( struct NineDevice9 *This, + DWORD RenderTargetIndex, + IDirect3DSurface9 *pRenderTarget ) +{ + struct NineSurface9 *rt = NineSurface9(pRenderTarget); + const unsigned i = RenderTargetIndex; + + DBG("This=%p RenderTargetIndex=%u pRenderTarget=%p\n", This, + RenderTargetIndex, pRenderTarget); + + user_assert(i < This->caps.NumSimultaneousRTs, D3DERR_INVALIDCALL); + user_assert(i != 0 || pRenderTarget, D3DERR_INVALIDCALL); + user_assert(!pRenderTarget || + rt->desc.Usage & D3DUSAGE_RENDERTARGET, D3DERR_INVALIDCALL); + + if (i == 0) { + This->state.viewport.X = 0; + This->state.viewport.Y = 0; + This->state.viewport.Width = rt->desc.Width; + This->state.viewport.Height = rt->desc.Height; + This->state.viewport.MinZ = 0.0f; + This->state.viewport.MaxZ = 1.0f; + + This->state.scissor.minx = 0; + This->state.scissor.miny = 0; + This->state.scissor.maxx = rt->desc.Width; + This->state.scissor.maxy = rt->desc.Height; + } + + if (This->state.rt[i] != NineSurface9(pRenderTarget)) + nine_bind(&This->state.rt[i], pRenderTarget); + + nine_context_set_render_target(This, i, rt); + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_GetRenderTarget( struct NineDevice9 *This, + DWORD RenderTargetIndex, + IDirect3DSurface9 **ppRenderTarget ) +{ + const unsigned i = RenderTargetIndex; + + user_assert(i < This->caps.NumSimultaneousRTs, D3DERR_INVALIDCALL); + user_assert(ppRenderTarget, D3DERR_INVALIDCALL); + + *ppRenderTarget = (IDirect3DSurface9 *)This->state.rt[i]; + if (!This->state.rt[i]) + return D3DERR_NOTFOUND; + + NineUnknown_AddRef(NineUnknown(This->state.rt[i])); + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_SetDepthStencilSurface( struct NineDevice9 *This, + IDirect3DSurface9 *pNewZStencil ) +{ + struct NineSurface9 *ds = NineSurface9(pNewZStencil); + DBG("This=%p pNewZStencil=%p\n", This, pNewZStencil); + + if (This->state.ds != ds) { + nine_bind(&This->state.ds, ds); + nine_context_set_depth_stencil(This, ds); + } + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_GetDepthStencilSurface( struct NineDevice9 *This, + IDirect3DSurface9 **ppZStencilSurface ) +{ + user_assert(ppZStencilSurface, D3DERR_INVALIDCALL); + + *ppZStencilSurface = (IDirect3DSurface9 *)This->state.ds; + if (!This->state.ds) + return D3DERR_NOTFOUND; + + NineUnknown_AddRef(NineUnknown(This->state.ds)); + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_BeginScene( struct NineDevice9 *This ) +{ + DBG("This=%p\n", This); + user_assert(!This->in_scene, D3DERR_INVALIDCALL); + This->in_scene = TRUE; + /* Do we want to do anything else here ? */ + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_EndScene( struct NineDevice9 *This ) +{ + DBG("This=%p\n", This); + user_assert(This->in_scene, D3DERR_INVALIDCALL); + This->in_scene = FALSE; + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_Clear( struct NineDevice9 *This, + DWORD Count, + const D3DRECT *pRects, + DWORD Flags, + D3DCOLOR Color, + float Z, + DWORD Stencil ) +{ + struct NineSurface9 *zsbuf_surf = This->state.ds; + + DBG("This=%p Count=%u pRects=%p Flags=%x Color=%08x Z=%f Stencil=%x\n", + This, Count, pRects, Flags, Color, Z, Stencil); + + user_assert(This->state.ds || !(Flags & NINED3DCLEAR_DEPTHSTENCIL), + D3DERR_INVALIDCALL); + user_assert(!(Flags & D3DCLEAR_STENCIL) || + (zsbuf_surf && + util_format_is_depth_and_stencil(zsbuf_surf->base.info.format)), + D3DERR_INVALIDCALL); +#ifdef NINE_STRICT + user_assert((Count && pRects) || (!Count && !pRects), D3DERR_INVALIDCALL); +#else + user_warn((pRects && !Count) || (!pRects && Count)); + if (pRects && !Count) + return D3D_OK; + if (!pRects) + Count = 0; +#endif + + nine_context_clear_fb(This, Count, pRects, Flags, Color, Z, Stencil); + return D3D_OK; +} + +static void +nine_D3DMATRIX_print(const D3DMATRIX *M) +{ + DBG("\n(%f %f %f %f)\n" + "(%f %f %f %f)\n" + "(%f %f %f %f)\n" + "(%f %f %f %f)\n", + M->m[0][0], M->m[0][1], M->m[0][2], M->m[0][3], + M->m[1][0], M->m[1][1], M->m[1][2], M->m[1][3], + M->m[2][0], M->m[2][1], M->m[2][2], M->m[2][3], + M->m[3][0], M->m[3][1], M->m[3][2], M->m[3][3]); +} + +HRESULT NINE_WINAPI +NineDevice9_SetTransform( struct NineDevice9 *This, + D3DTRANSFORMSTATETYPE State, + const D3DMATRIX *pMatrix ) +{ + struct nine_state *state = This->update; + D3DMATRIX *M = nine_state_access_transform(&state->ff, State, TRUE); + + DBG("This=%p State=%d pMatrix=%p\n", This, State, pMatrix); + + user_assert(M, D3DERR_INVALIDCALL); + nine_D3DMATRIX_print(pMatrix); + + *M = *pMatrix; + if (unlikely(This->is_recording)) { + state->ff.changed.transform[State / 32] |= 1 << (State % 32); + state->changed.group |= NINE_STATE_FF_VSTRANSF; + } else + nine_context_set_transform(This, State, pMatrix); + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_GetTransform( struct NineDevice9 *This, + D3DTRANSFORMSTATETYPE State, + D3DMATRIX *pMatrix ) +{ + D3DMATRIX *M = nine_state_access_transform(&This->state.ff, State, FALSE); + user_assert(M, D3DERR_INVALIDCALL); + *pMatrix = *M; + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_MultiplyTransform( struct NineDevice9 *This, + D3DTRANSFORMSTATETYPE State, + const D3DMATRIX *pMatrix ) +{ + struct nine_state *state = This->update; + D3DMATRIX T; + D3DMATRIX *M = nine_state_access_transform(&state->ff, State, TRUE); + + DBG("This=%p State=%d pMatrix=%p\n", This, State, pMatrix); + + user_assert(M, D3DERR_INVALIDCALL); + + nine_d3d_matrix_matrix_mul(&T, pMatrix, M); + return NineDevice9_SetTransform(This, State, &T); +} + +HRESULT NINE_WINAPI +NineDevice9_SetViewport( struct NineDevice9 *This, + const D3DVIEWPORT9 *pViewport ) +{ + struct nine_state *state = This->update; + + DBG("X=%u Y=%u W=%u H=%u MinZ=%f MaxZ=%f\n", + pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, + pViewport->MinZ, pViewport->MaxZ); + + state->viewport = *pViewport; + nine_context_set_viewport(This, pViewport); + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_GetViewport( struct NineDevice9 *This, + D3DVIEWPORT9 *pViewport ) +{ + *pViewport = This->state.viewport; + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_SetMaterial( struct NineDevice9 *This, + const D3DMATERIAL9 *pMaterial ) +{ + struct nine_state *state = This->update; + + DBG("This=%p pMaterial=%p\n", This, pMaterial); + if (pMaterial) + nine_dump_D3DMATERIAL9(DBG_FF, pMaterial); + + user_assert(pMaterial, E_POINTER); + + state->ff.material = *pMaterial; + if (unlikely(This->is_recording)) + state->changed.group |= NINE_STATE_FF_MATERIAL; + else + nine_context_set_material(This, pMaterial); + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_GetMaterial( struct NineDevice9 *This, + D3DMATERIAL9 *pMaterial ) +{ + user_assert(pMaterial, E_POINTER); + *pMaterial = This->state.ff.material; + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_SetLight( struct NineDevice9 *This, + DWORD Index, + const D3DLIGHT9 *pLight ) +{ + struct nine_state *state = This->update; + HRESULT hr; + + DBG("This=%p Index=%u pLight=%p\n", This, Index, pLight); + if (pLight) + nine_dump_D3DLIGHT9(DBG_FF, pLight); + + user_assert(pLight, D3DERR_INVALIDCALL); + user_assert(pLight->Type < NINED3DLIGHT_INVALID, D3DERR_INVALIDCALL); + + user_assert(Index < NINE_MAX_LIGHTS, D3DERR_INVALIDCALL); /* sanity */ + + hr = nine_state_set_light(&state->ff, Index, pLight); + if (hr != D3D_OK) + return hr; + + if (pLight->Type != D3DLIGHT_DIRECTIONAL && + pLight->Attenuation0 == 0.0f && + pLight->Attenuation1 == 0.0f && + pLight->Attenuation2 == 0.0f) { + DBG("Warning: all D3DLIGHT9.Attenuation[i] are 0\n"); + } + + if (unlikely(This->is_recording)) + state->changed.group |= NINE_STATE_FF_LIGHTING; + else + nine_context_set_light(This, Index, pLight); + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_GetLight( struct NineDevice9 *This, + DWORD Index, + D3DLIGHT9 *pLight ) +{ + const struct nine_state *state = &This->state; + + user_assert(pLight, D3DERR_INVALIDCALL); + user_assert(Index < state->ff.num_lights, D3DERR_INVALIDCALL); + user_assert(state->ff.light[Index].Type < NINED3DLIGHT_INVALID, + D3DERR_INVALIDCALL); + + *pLight = state->ff.light[Index]; + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_LightEnable( struct NineDevice9 *This, + DWORD Index, + BOOL Enable ) +{ + struct nine_state *state = This->update; + + DBG("This=%p Index=%u Enable=%i\n", This, Index, Enable); + + if (Index >= state->ff.num_lights || + state->ff.light[Index].Type == NINED3DLIGHT_INVALID) { + /* This should create a default light. */ + D3DLIGHT9 light; + memset(&light, 0, sizeof(light)); + light.Type = D3DLIGHT_DIRECTIONAL; + light.Diffuse.r = 1.0f; + light.Diffuse.g = 1.0f; + light.Diffuse.b = 1.0f; + light.Direction.z = 1.0f; + NineDevice9_SetLight(This, Index, &light); + } + + nine_state_light_enable(&state->ff, Index, Enable); + if (likely(!This->is_recording)) + nine_context_light_enable(This, Index, Enable); + else + state->changed.group |= NINE_STATE_FF_LIGHTING; + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_GetLightEnable( struct NineDevice9 *This, + DWORD Index, + BOOL *pEnable ) +{ + const struct nine_state *state = &This->state; + unsigned i; + + user_assert(Index < state->ff.num_lights, D3DERR_INVALIDCALL); + user_assert(state->ff.light[Index].Type < NINED3DLIGHT_INVALID, + D3DERR_INVALIDCALL); + + for (i = 0; i < state->ff.num_lights_active; ++i) + if (state->ff.active_light[i] == Index) + break; + + *pEnable = i != state->ff.num_lights_active ? 128 : 0; // Taken from wine + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_SetClipPlane( struct NineDevice9 *This, + DWORD Index, + const float *pPlane ) +{ + struct nine_state *state = This->update; + + user_assert(pPlane, D3DERR_INVALIDCALL); + + DBG("This=%p Index=%u pPlane=%f %f %f %f\n", This, Index, + pPlane[0], pPlane[1], + pPlane[2], pPlane[3]); + + user_assert(Index < PIPE_MAX_CLIP_PLANES, D3DERR_INVALIDCALL); + + memcpy(&state->clip.ucp[Index][0], pPlane, sizeof(state->clip.ucp[0])); + if (unlikely(This->is_recording)) + state->changed.ucp |= 1 << Index; + else + nine_context_set_clip_plane(This, Index, (struct nine_clipplane *)pPlane); + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_GetClipPlane( struct NineDevice9 *This, + DWORD Index, + float *pPlane ) +{ + const struct nine_state *state = &This->state; + + user_assert(Index < PIPE_MAX_CLIP_PLANES, D3DERR_INVALIDCALL); + + memcpy(pPlane, &state->clip.ucp[Index][0], sizeof(state->clip.ucp[0])); + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_SetRenderState( struct NineDevice9 *This, + D3DRENDERSTATETYPE State, + DWORD Value ) +{ + struct nine_state *state = This->update; + + DBG("This=%p State=%u(%s) Value=%08x\n", This, + State, nine_d3drs_to_string(State), Value); + + user_assert(State < D3DRS_COUNT, D3DERR_INVALIDCALL); + + if (unlikely(This->is_recording)) { + state->rs_advertised[State] = Value; + /* only need to record changed render states for stateblocks */ + state->changed.rs[State / 32] |= 1 << (State % 32); + return D3D_OK; + } + + if (state->rs_advertised[State] == Value) + return D3D_OK; + + state->rs_advertised[State] = Value; + nine_context_set_render_state(This, State, Value); + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_GetRenderState( struct NineDevice9 *This, + D3DRENDERSTATETYPE State, + DWORD *pValue ) +{ + user_assert(State < D3DRS_COUNT, D3DERR_INVALIDCALL); + + *pValue = This->state.rs_advertised[State]; + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_CreateStateBlock( struct NineDevice9 *This, + D3DSTATEBLOCKTYPE Type, + IDirect3DStateBlock9 **ppSB ) +{ + struct NineStateBlock9 *nsb; + struct nine_state *dst; + HRESULT hr; + enum nine_stateblock_type type; + unsigned s; + + DBG("This=%p Type=%u ppSB=%p\n", This, Type, ppSB); + + user_assert(Type == D3DSBT_ALL || + Type == D3DSBT_VERTEXSTATE || + Type == D3DSBT_PIXELSTATE, D3DERR_INVALIDCALL); + + switch (Type) { + case D3DSBT_VERTEXSTATE: type = NINESBT_VERTEXSTATE; break; + case D3DSBT_PIXELSTATE: type = NINESBT_PIXELSTATE; break; + default: + type = NINESBT_ALL; + break; + } + + hr = NineStateBlock9_new(This, &nsb, type); + if (FAILED(hr)) + return hr; + *ppSB = (IDirect3DStateBlock9 *)nsb; + dst = &nsb->state; + + dst->changed.group = NINE_STATE_SAMPLER; + + if (Type == D3DSBT_ALL || Type == D3DSBT_VERTEXSTATE) { + dst->changed.group |= + NINE_STATE_FF_LIGHTING | + NINE_STATE_VS | NINE_STATE_VS_CONST | + NINE_STATE_VDECL; + /* TODO: texture/sampler state */ + memcpy(dst->changed.rs, + nine_render_states_vertex, sizeof(dst->changed.rs)); + nine_ranges_insert(&dst->changed.vs_const_f, 0, This->may_swvp ? NINE_MAX_CONST_F_SWVP : This->max_vs_const_f, + &This->range_pool); + nine_ranges_insert(&dst->changed.vs_const_i, 0, This->may_swvp ? NINE_MAX_CONST_I_SWVP : NINE_MAX_CONST_I, + &This->range_pool); + nine_ranges_insert(&dst->changed.vs_const_b, 0, This->may_swvp ? NINE_MAX_CONST_B_SWVP : NINE_MAX_CONST_B, + &This->range_pool); + for (s = 0; s < NINE_MAX_SAMPLERS; ++s) + dst->changed.sampler[s] |= 1 << D3DSAMP_DMAPOFFSET; + if (This->state.ff.num_lights) { + dst->ff.num_lights = This->state.ff.num_lights; + /* zero'd -> light type won't be NINED3DLIGHT_INVALID, so + * all currently existing lights will be captured + */ + dst->ff.light = CALLOC(This->state.ff.num_lights, + sizeof(D3DLIGHT9)); + if (!dst->ff.light) { + nine_bind(ppSB, NULL); + return E_OUTOFMEMORY; + } + } + } + if (Type == D3DSBT_ALL || Type == D3DSBT_PIXELSTATE) { + dst->changed.group |= + NINE_STATE_PS | NINE_STATE_PS_CONST | NINE_STATE_FF_PS_CONSTS; + memcpy(dst->changed.rs, + nine_render_states_pixel, sizeof(dst->changed.rs)); + nine_ranges_insert(&dst->changed.ps_const_f, 0, This->max_ps_const_f, + &This->range_pool); + dst->changed.ps_const_i = 0xffff; + dst->changed.ps_const_b = 0xffff; + for (s = 0; s < NINE_MAX_SAMPLERS; ++s) + dst->changed.sampler[s] |= 0x1ffe; + for (s = 0; s < NINE_MAX_TEXTURE_STAGES; ++s) { + dst->ff.changed.tex_stage[s][0] |= 0xffffffff; + dst->ff.changed.tex_stage[s][1] |= 0xffffffff; + } + } + if (Type == D3DSBT_ALL) { + dst->changed.group |= + NINE_STATE_VIEWPORT | + NINE_STATE_SCISSOR | + NINE_STATE_IDXBUF | + NINE_STATE_FF_MATERIAL | + NINE_STATE_FF_VSTRANSF; + memset(dst->changed.rs, ~0, (D3DRS_COUNT / 32) * sizeof(uint32_t)); + dst->changed.rs[D3DRS_LAST / 32] |= (1 << (D3DRS_COUNT % 32)) - 1; + dst->changed.vtxbuf = (1ULL << This->caps.MaxStreams) - 1; + dst->changed.stream_freq = dst->changed.vtxbuf; + dst->changed.ucp = (1 << PIPE_MAX_CLIP_PLANES) - 1; + dst->changed.texture = (1 << NINE_MAX_SAMPLERS) - 1; + /* The doc says the projection, world, view and texture matrices + * are saved, which would translate to: + * dst->ff.changed.transform[0] = 0x00FF000C; + * dst->ff.changed.transform[D3DTS_WORLD / 32] |= 1 << (D3DTS_WORLD % 32); + * However we assume they meant save everything (which is basically just the + * above plus the other world matrices). + */ + dst->ff.changed.transform[0] = 0x00FF000C; + for (s = 0; s < 8; s++) + dst->ff.changed.transform[8+s] = ~0; + } + NineStateBlock9_Capture(NineStateBlock9(*ppSB)); + + /* TODO: fixed function state */ + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_BeginStateBlock( struct NineDevice9 *This ) +{ + HRESULT hr; + + DBG("This=%p\n", This); + + user_assert(!This->record, D3DERR_INVALIDCALL); + + hr = NineStateBlock9_new(This, &This->record, NINESBT_CUSTOM); + if (FAILED(hr)) + return hr; + NineUnknown_ConvertRefToBind(NineUnknown(This->record)); + + This->update = &This->record->state; + This->is_recording = TRUE; + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_EndStateBlock( struct NineDevice9 *This, + IDirect3DStateBlock9 **ppSB ) +{ + DBG("This=%p ppSB=%p\n", This, ppSB); + + user_assert(This->record, D3DERR_INVALIDCALL); + + This->update = &This->state; + This->is_recording = FALSE; + + NineUnknown_AddRef(NineUnknown(This->record)); + *ppSB = (IDirect3DStateBlock9 *)This->record; + NineUnknown_Unbind(NineUnknown(This->record)); + This->record = NULL; + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_SetClipStatus( struct NineDevice9 *This, + const D3DCLIPSTATUS9 *pClipStatus ) +{ + STUB(D3DERR_INVALIDCALL); +} + +HRESULT NINE_WINAPI +NineDevice9_GetClipStatus( struct NineDevice9 *This, + D3DCLIPSTATUS9 *pClipStatus ) +{ + STUB(D3DERR_INVALIDCALL); +} + +HRESULT NINE_WINAPI +NineDevice9_GetTexture( struct NineDevice9 *This, + DWORD Stage, + IDirect3DBaseTexture9 **ppTexture ) +{ + user_assert(Stage < NINE_MAX_SAMPLERS_PS || + Stage == D3DDMAPSAMPLER || + (Stage >= D3DVERTEXTEXTURESAMPLER0 && + Stage <= D3DVERTEXTEXTURESAMPLER3), D3DERR_INVALIDCALL); + user_assert(ppTexture, D3DERR_INVALIDCALL); + + if (Stage >= D3DDMAPSAMPLER) + Stage = Stage - D3DDMAPSAMPLER + NINE_MAX_SAMPLERS_PS; + + *ppTexture = (IDirect3DBaseTexture9 *)This->state.texture[Stage]; + + if (This->state.texture[Stage]) + NineUnknown_AddRef(NineUnknown(This->state.texture[Stage])); + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_SetTexture( struct NineDevice9 *This, + DWORD Stage, + IDirect3DBaseTexture9 *pTexture ) +{ + struct nine_state *state = This->update; + struct NineBaseTexture9 *tex = NineBaseTexture9(pTexture); + struct NineBaseTexture9 *old; + + DBG("This=%p Stage=%u pTexture=%p\n", This, Stage, pTexture); + + user_assert(Stage < NINE_MAX_SAMPLERS_PS || + Stage == D3DDMAPSAMPLER || + (Stage >= D3DVERTEXTEXTURESAMPLER0 && + Stage <= D3DVERTEXTEXTURESAMPLER3), D3DERR_INVALIDCALL); + user_assert(!tex || (tex->base.pool != D3DPOOL_SCRATCH && + tex->base.pool != D3DPOOL_SYSTEMMEM), D3DERR_INVALIDCALL); + + if (Stage >= D3DDMAPSAMPLER) + Stage = Stage - D3DDMAPSAMPLER + NINE_MAX_SAMPLERS_PS; + + if (This->is_recording) { + state->changed.texture |= 1 << Stage; + nine_bind(&state->texture[Stage], pTexture); + return D3D_OK; + } + + old = state->texture[Stage]; + if (old == tex) + return D3D_OK; + + NineBindTextureToDevice(This, &state->texture[Stage], tex); + + nine_context_set_texture(This, Stage, tex); + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_GetTextureStageState( struct NineDevice9 *This, + DWORD Stage, + D3DTEXTURESTAGESTATETYPE Type, + DWORD *pValue ) +{ + const struct nine_state *state = &This->state; + + user_assert(Stage < ARRAY_SIZE(state->ff.tex_stage), D3DERR_INVALIDCALL); + user_assert(Type < ARRAY_SIZE(state->ff.tex_stage[0]), D3DERR_INVALIDCALL); + + *pValue = state->ff.tex_stage[Stage][Type]; + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_SetTextureStageState( struct NineDevice9 *This, + DWORD Stage, + D3DTEXTURESTAGESTATETYPE Type, + DWORD Value ) +{ + struct nine_state *state = This->update; + + DBG("Stage=%u Type=%u Value=%08x\n", Stage, Type, Value); + nine_dump_D3DTSS_value(DBG_FF, Type, Value); + + user_assert(Stage < ARRAY_SIZE(state->ff.tex_stage), D3DERR_INVALIDCALL); + user_assert(Type < ARRAY_SIZE(state->ff.tex_stage[0]), D3DERR_INVALIDCALL); + + state->ff.tex_stage[Stage][Type] = Value; + + if (unlikely(This->is_recording)) { + state->changed.group |= NINE_STATE_FF_PS_CONSTS; + state->ff.changed.tex_stage[Stage][Type / 32] |= 1 << (Type % 32); + } else + nine_context_set_texture_stage_state(This, Stage, Type, Value); + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_GetSamplerState( struct NineDevice9 *This, + DWORD Sampler, + D3DSAMPLERSTATETYPE Type, + DWORD *pValue ) +{ + user_assert(Sampler < NINE_MAX_SAMPLERS_PS || + Sampler == D3DDMAPSAMPLER || + (Sampler >= D3DVERTEXTEXTURESAMPLER0 && + Sampler <= D3DVERTEXTEXTURESAMPLER3), D3DERR_INVALIDCALL); + + if (Sampler >= D3DDMAPSAMPLER) + Sampler = Sampler - D3DDMAPSAMPLER + NINE_MAX_SAMPLERS_PS; + + *pValue = This->state.samp_advertised[Sampler][Type]; + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_SetSamplerState( struct NineDevice9 *This, + DWORD Sampler, + D3DSAMPLERSTATETYPE Type, + DWORD Value ) +{ + struct nine_state *state = This->update; + + DBG("This=%p Sampler=%u Type=%s Value=%08x\n", This, + Sampler, nine_D3DSAMP_to_str(Type), Value); + + user_assert(Sampler < NINE_MAX_SAMPLERS_PS || + Sampler == D3DDMAPSAMPLER || + (Sampler >= D3DVERTEXTEXTURESAMPLER0 && + Sampler <= D3DVERTEXTEXTURESAMPLER3), D3DERR_INVALIDCALL); + + if (Sampler >= D3DDMAPSAMPLER) + Sampler = Sampler - D3DDMAPSAMPLER + NINE_MAX_SAMPLERS_PS; + + if (unlikely(This->is_recording)) { + state->samp_advertised[Sampler][Type] = Value; + state->changed.group |= NINE_STATE_SAMPLER; + state->changed.sampler[Sampler] |= 1 << Type; + return D3D_OK; + } + + if (state->samp_advertised[Sampler][Type] == Value) + return D3D_OK; + + state->samp_advertised[Sampler][Type] = Value; + nine_context_set_sampler_state(This, Sampler, Type, Value); + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_ValidateDevice( struct NineDevice9 *This, + DWORD *pNumPasses ) +{ + const struct nine_state *state = &This->state; + unsigned i; + unsigned w = 0, h = 0; + + DBG("This=%p pNumPasses=%p\n", This, pNumPasses); + + for (i = 0; i < ARRAY_SIZE(state->samp_advertised); ++i) { + if (state->samp_advertised[i][D3DSAMP_MINFILTER] == D3DTEXF_NONE || + state->samp_advertised[i][D3DSAMP_MAGFILTER] == D3DTEXF_NONE) + return D3DERR_UNSUPPORTEDTEXTUREFILTER; + } + + for (i = 0; i < This->caps.NumSimultaneousRTs; ++i) { + if (!state->rt[i]) + continue; + if (w == 0) { + w = state->rt[i]->desc.Width; + h = state->rt[i]->desc.Height; + } else + if (state->rt[i]->desc.Width != w || state->rt[i]->desc.Height != h) { + return D3DERR_CONFLICTINGRENDERSTATE; + } + } + if (state->ds && + (state->rs_advertised[D3DRS_ZENABLE] || state->rs_advertised[D3DRS_STENCILENABLE])) { + if (w != 0 && + (state->ds->desc.Width != w || state->ds->desc.Height != h)) + return D3DERR_CONFLICTINGRENDERSTATE; + } + + if (pNumPasses) + *pNumPasses = 1; + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_SetPaletteEntries( struct NineDevice9 *This, + UINT PaletteNumber, + const PALETTEENTRY *pEntries ) +{ + STUB(D3D_OK); /* like wine */ +} + +HRESULT NINE_WINAPI +NineDevice9_GetPaletteEntries( struct NineDevice9 *This, + UINT PaletteNumber, + PALETTEENTRY *pEntries ) +{ + STUB(D3DERR_INVALIDCALL); +} + +HRESULT NINE_WINAPI +NineDevice9_SetCurrentTexturePalette( struct NineDevice9 *This, + UINT PaletteNumber ) +{ + STUB(D3D_OK); /* like wine */ +} + +HRESULT NINE_WINAPI +NineDevice9_GetCurrentTexturePalette( struct NineDevice9 *This, + UINT *PaletteNumber ) +{ + STUB(D3DERR_INVALIDCALL); +} + +HRESULT NINE_WINAPI +NineDevice9_SetScissorRect( struct NineDevice9 *This, + const RECT *pRect ) +{ + struct nine_state *state = This->update; + + DBG("x=(%u..%u) y=(%u..%u)\n", + pRect->left, pRect->top, pRect->right, pRect->bottom); + + state->scissor.minx = pRect->left; + state->scissor.miny = pRect->top; + state->scissor.maxx = pRect->right; + state->scissor.maxy = pRect->bottom; + + if (unlikely(This->is_recording)) + state->changed.group |= NINE_STATE_SCISSOR; + else + nine_context_set_scissor(This, &state->scissor); + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_GetScissorRect( struct NineDevice9 *This, + RECT *pRect ) +{ + pRect->left = This->state.scissor.minx; + pRect->top = This->state.scissor.miny; + pRect->right = This->state.scissor.maxx; + pRect->bottom = This->state.scissor.maxy; + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_SetSoftwareVertexProcessing( struct NineDevice9 *This, + BOOL bSoftware ) +{ + if (This->params.BehaviorFlags & D3DCREATE_MIXED_VERTEXPROCESSING) { + This->swvp = bSoftware; + nine_context_set_swvp(This, bSoftware); + return D3D_OK; + } else + return D3D_OK; /* msdn seems to indicate INVALIDCALL, but at least Halo expects OK */ +} + +BOOL NINE_WINAPI +NineDevice9_GetSoftwareVertexProcessing( struct NineDevice9 *This ) +{ + return This->swvp; +} + +HRESULT NINE_WINAPI +NineDevice9_SetNPatchMode( struct NineDevice9 *This, + float nSegments ) +{ + return D3D_OK; /* Nothing to do because we don't advertise NPatch support */ +} + +float NINE_WINAPI +NineDevice9_GetNPatchMode( struct NineDevice9 *This ) +{ + STUB(0); +} + +/* TODO: only go through dirty textures */ +static void +validate_textures(struct NineDevice9 *device) +{ + struct NineBaseTexture9 *tex, *ptr; + LIST_FOR_EACH_ENTRY_SAFE(tex, ptr, &device->update_textures, list) { + list_delinit(&tex->list); + NineBaseTexture9_Validate(tex); + } +} + +static void +update_managed_buffers(struct NineDevice9 *device) +{ + struct NineBuffer9 *buf, *ptr; + LIST_FOR_EACH_ENTRY_SAFE(buf, ptr, &device->update_buffers, managed.list) { + list_delinit(&buf->managed.list); + NineBuffer9_Upload(buf); + } +} + +static void +NineBeforeDraw( struct NineDevice9 *This ) +{ + /* Upload Managed dirty content */ + validate_textures(This); /* may clobber state */ + update_managed_buffers(This); +} + +static void +NineAfterDraw( struct NineDevice9 *This ) +{ + unsigned i; + struct nine_state *state = &This->state; + unsigned ps_mask = state->ps ? state->ps->rt_mask : 1; + + /* Flag render-targets with autogenmipmap for mipmap regeneration */ + for (i = 0; i < This->caps.NumSimultaneousRTs; ++i) { + struct NineSurface9 *rt = state->rt[i]; + + if (rt && rt->desc.Format != D3DFMT_NULL && (ps_mask & (1 << i)) && + rt->desc.Usage & D3DUSAGE_AUTOGENMIPMAP) { + assert(rt->texture == D3DRTYPE_TEXTURE || + rt->texture == D3DRTYPE_CUBETEXTURE); + NineBaseTexture9(rt->base.base.container)->dirty_mip = TRUE; + } + } +} + +HRESULT NINE_WINAPI +NineDevice9_DrawPrimitive( struct NineDevice9 *This, + D3DPRIMITIVETYPE PrimitiveType, + UINT StartVertex, + UINT PrimitiveCount ) +{ + DBG("iface %p, PrimitiveType %u, StartVertex %u, PrimitiveCount %u\n", + This, PrimitiveType, StartVertex, PrimitiveCount); + + NineBeforeDraw(This); + nine_context_draw_primitive(This, PrimitiveType, StartVertex, PrimitiveCount); + NineAfterDraw(This); + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_DrawIndexedPrimitive( struct NineDevice9 *This, + D3DPRIMITIVETYPE PrimitiveType, + INT BaseVertexIndex, + UINT MinVertexIndex, + UINT NumVertices, + UINT StartIndex, + UINT PrimitiveCount ) +{ + DBG("iface %p, PrimitiveType %u, BaseVertexIndex %u, MinVertexIndex %u " + "NumVertices %u, StartIndex %u, PrimitiveCount %u\n", + This, PrimitiveType, BaseVertexIndex, MinVertexIndex, NumVertices, + StartIndex, PrimitiveCount); + + user_assert(This->state.idxbuf, D3DERR_INVALIDCALL); + user_assert(This->state.vdecl, D3DERR_INVALIDCALL); + + NineBeforeDraw(This); + nine_context_draw_indexed_primitive(This, PrimitiveType, BaseVertexIndex, + MinVertexIndex, NumVertices, StartIndex, + PrimitiveCount); + NineAfterDraw(This); + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_DrawPrimitiveUP( struct NineDevice9 *This, + D3DPRIMITIVETYPE PrimitiveType, + UINT PrimitiveCount, + const void *pVertexStreamZeroData, + UINT VertexStreamZeroStride ) +{ + struct pipe_vertex_buffer vtxbuf; + + DBG("iface %p, PrimitiveType %u, PrimitiveCount %u, data %p, stride %u\n", + This, PrimitiveType, PrimitiveCount, + pVertexStreamZeroData, VertexStreamZeroStride); + + user_assert(pVertexStreamZeroData && VertexStreamZeroStride, + D3DERR_INVALIDCALL); + user_assert(PrimitiveCount, D3D_OK); + + vtxbuf.stride = VertexStreamZeroStride; + vtxbuf.buffer_offset = 0; + vtxbuf.is_user_buffer = true; + vtxbuf.buffer.user = pVertexStreamZeroData; + + if (!This->driver_caps.user_vbufs) { + vtxbuf.is_user_buffer = false; + vtxbuf.buffer.resource = NULL; + u_upload_data(This->vertex_uploader, + 0, + (prim_count_to_vertex_count(PrimitiveType, PrimitiveCount)) * VertexStreamZeroStride, /* XXX */ + 4, + pVertexStreamZeroData, + &vtxbuf.buffer_offset, + &vtxbuf.buffer.resource); + u_upload_unmap(This->vertex_uploader); + } + + NineBeforeDraw(This); + nine_context_draw_primitive_from_vtxbuf(This, PrimitiveType, PrimitiveCount, &vtxbuf); + NineAfterDraw(This); + + pipe_vertex_buffer_unreference(&vtxbuf); + + NineDevice9_PauseRecording(This); + NineDevice9_SetStreamSource(This, 0, NULL, 0, 0); + NineDevice9_ResumeRecording(This); + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_DrawIndexedPrimitiveUP( struct NineDevice9 *This, + D3DPRIMITIVETYPE PrimitiveType, + UINT MinVertexIndex, + UINT NumVertices, + UINT PrimitiveCount, + const void *pIndexData, + D3DFORMAT IndexDataFormat, + const void *pVertexStreamZeroData, + UINT VertexStreamZeroStride ) +{ + struct pipe_vertex_buffer vbuf; + + DBG("iface %p, PrimitiveType %u, MinVertexIndex %u, NumVertices %u " + "PrimitiveCount %u, pIndexData %p, IndexDataFormat %u " + "pVertexStreamZeroData %p, VertexStreamZeroStride %u\n", + This, PrimitiveType, MinVertexIndex, NumVertices, PrimitiveCount, + pIndexData, IndexDataFormat, + pVertexStreamZeroData, VertexStreamZeroStride); + + user_assert(pIndexData && pVertexStreamZeroData, D3DERR_INVALIDCALL); + user_assert(VertexStreamZeroStride, D3DERR_INVALIDCALL); + user_assert(IndexDataFormat == D3DFMT_INDEX16 || + IndexDataFormat == D3DFMT_INDEX32, D3DERR_INVALIDCALL); + user_assert(PrimitiveCount, D3D_OK); + + vbuf.stride = VertexStreamZeroStride; + vbuf.buffer_offset = 0; + vbuf.is_user_buffer = true; + vbuf.buffer.user = pVertexStreamZeroData; + + unsigned index_size = (IndexDataFormat == D3DFMT_INDEX16) ? 2 : 4; + struct pipe_resource *ibuf = NULL; + + if (!This->driver_caps.user_vbufs) { + const unsigned base = MinVertexIndex * VertexStreamZeroStride; + vbuf.is_user_buffer = false; + vbuf.buffer.resource = NULL; + u_upload_data(This->vertex_uploader, + base, + NumVertices * VertexStreamZeroStride, /* XXX */ + 4, + (const uint8_t *)pVertexStreamZeroData + base, + &vbuf.buffer_offset, + &vbuf.buffer.resource); + u_upload_unmap(This->vertex_uploader); + /* Won't be used: */ + vbuf.buffer_offset -= base; + } + + unsigned index_offset = 0; + if (This->csmt_active) { + u_upload_data(This->pipe_secondary->stream_uploader, + 0, + (prim_count_to_vertex_count(PrimitiveType, PrimitiveCount)) * index_size, + 4, + pIndexData, + &index_offset, + &ibuf); + u_upload_unmap(This->pipe_secondary->stream_uploader); + } + + NineBeforeDraw(This); + nine_context_draw_indexed_primitive_from_vtxbuf_idxbuf(This, PrimitiveType, + MinVertexIndex, + NumVertices, + PrimitiveCount, + &vbuf, + ibuf, + ibuf ? NULL : (void*)pIndexData, + index_offset, + index_size); + NineAfterDraw(This); + + pipe_vertex_buffer_unreference(&vbuf); + pipe_resource_reference(&ibuf, NULL); + + NineDevice9_PauseRecording(This); + NineDevice9_SetIndices(This, NULL); + NineDevice9_SetStreamSource(This, 0, NULL, 0, 0); + NineDevice9_ResumeRecording(This); + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_ProcessVertices( struct NineDevice9 *This, + UINT SrcStartIndex, + UINT DestIndex, + UINT VertexCount, + IDirect3DVertexBuffer9 *pDestBuffer, + IDirect3DVertexDeclaration9 *pVertexDecl, + DWORD Flags ) +{ + struct pipe_screen *screen_sw = This->screen_sw; + struct pipe_context *pipe_sw = This->pipe_sw; + struct NineVertexDeclaration9 *vdecl = NineVertexDeclaration9(pVertexDecl); + struct NineVertexBuffer9 *dst = NineVertexBuffer9(pDestBuffer); + struct NineVertexShader9 *vs; + struct pipe_resource *resource; + struct pipe_transfer *transfer = NULL; + struct pipe_stream_output_info so; + struct pipe_stream_output_target *target; + struct pipe_draw_info draw; + struct pipe_box box; + bool programmable_vs = This->state.vs && !(This->state.vdecl && This->state.vdecl->position_t); + unsigned offsets[1] = {0}; + HRESULT hr; + unsigned buffer_size; + void *map; + + DBG("This=%p SrcStartIndex=%u DestIndex=%u VertexCount=%u " + "pDestBuffer=%p pVertexDecl=%p Flags=%d\n", + This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, + pVertexDecl, Flags); + + if (!screen_sw->get_param(screen_sw, PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS)) { + DBG("ProcessVertices not supported\n"); + return D3DERR_INVALIDCALL; + } + + + vs = programmable_vs ? This->state.vs : This->ff.vs; + /* Note: version is 0 for ff */ + user_assert(vdecl || (vs->byte_code.version < 0x30 && dst->desc.FVF), + D3DERR_INVALIDCALL); + if (!vdecl) { + DWORD FVF = dst->desc.FVF; + vdecl = util_hash_table_get(This->ff.ht_fvf, &FVF); + if (!vdecl) { + hr = NineVertexDeclaration9_new_from_fvf(This, FVF, &vdecl); + if (FAILED(hr)) + return hr; + vdecl->fvf = FVF; + _mesa_hash_table_insert(This->ff.ht_fvf, &vdecl->fvf, vdecl); + NineUnknown_ConvertRefToBind(NineUnknown(vdecl)); + } + } + + /* Flags: Can be 0 or D3DPV_DONOTCOPYDATA, and/or lock flags + * D3DPV_DONOTCOPYDATA -> Has effect only for ff. In particular + * if not set, everything from src will be used, and dst + * must match exactly the ff vs outputs. + * TODO: Handle all the checks, etc for ff */ + user_assert(vdecl->position_t || programmable_vs, + D3DERR_INVALIDCALL); + + /* TODO: Support vs < 3 and ff */ + user_assert(vs->byte_code.version == 0x30, + D3DERR_INVALIDCALL); + /* TODO: Not hardcode the constant buffers for swvp */ + user_assert(This->may_swvp, + D3DERR_INVALIDCALL); + + nine_state_prepare_draw_sw(This, vdecl, SrcStartIndex, VertexCount, &so); + + buffer_size = VertexCount * so.stride[0] * 4; + { + struct pipe_resource templ; + + memset(&templ, 0, sizeof(templ)); + templ.target = PIPE_BUFFER; + templ.format = PIPE_FORMAT_R8_UNORM; + templ.width0 = buffer_size; + templ.flags = 0; + templ.bind = PIPE_BIND_STREAM_OUTPUT; + templ.usage = PIPE_USAGE_STREAM; + templ.height0 = templ.depth0 = templ.array_size = 1; + templ.last_level = templ.nr_samples = templ.nr_storage_samples = 0; + + resource = screen_sw->resource_create(screen_sw, &templ); + if (!resource) + return E_OUTOFMEMORY; + } + target = pipe_sw->create_stream_output_target(pipe_sw, resource, + 0, buffer_size); + if (!target) { + pipe_resource_reference(&resource, NULL); + return D3DERR_DRIVERINTERNALERROR; + } + + draw.mode = PIPE_PRIM_POINTS; + draw.count = VertexCount; + draw.start_instance = 0; + draw.primitive_restart = FALSE; + draw.restart_index = 0; + draw.count_from_stream_output = NULL; + draw.indirect = NULL; + draw.instance_count = 1; + draw.index_size = 0; + draw.start = 0; + draw.index_bias = 0; + draw.min_index = 0; + draw.max_index = VertexCount - 1; + + + pipe_sw->set_stream_output_targets(pipe_sw, 1, &target, offsets); + + pipe_sw->draw_vbo(pipe_sw, &draw); + + pipe_sw->set_stream_output_targets(pipe_sw, 0, NULL, 0); + pipe_sw->stream_output_target_destroy(pipe_sw, target); + + u_box_1d(0, VertexCount * so.stride[0] * 4, &box); + map = pipe_sw->transfer_map(pipe_sw, resource, 0, PIPE_TRANSFER_READ, &box, + &transfer); + if (!map) { + hr = D3DERR_DRIVERINTERNALERROR; + goto out; + } + + hr = NineVertexDeclaration9_ConvertStreamOutput(vdecl, + dst, DestIndex, VertexCount, + map, &so); + if (transfer) + pipe_sw->transfer_unmap(pipe_sw, transfer); + +out: + nine_state_after_draw_sw(This); + pipe_resource_reference(&resource, NULL); + return hr; +} + +HRESULT NINE_WINAPI +NineDevice9_CreateVertexDeclaration( struct NineDevice9 *This, + const D3DVERTEXELEMENT9 *pVertexElements, + IDirect3DVertexDeclaration9 **ppDecl ) +{ + struct NineVertexDeclaration9 *vdecl; + + DBG("This=%p pVertexElements=%p ppDecl=%p\n", + This, pVertexElements, ppDecl); + + HRESULT hr = NineVertexDeclaration9_new(This, pVertexElements, &vdecl); + if (SUCCEEDED(hr)) + *ppDecl = (IDirect3DVertexDeclaration9 *)vdecl; + + return hr; +} + +HRESULT NINE_WINAPI +NineDevice9_SetVertexDeclaration( struct NineDevice9 *This, + IDirect3DVertexDeclaration9 *pDecl ) +{ + struct nine_state *state = This->update; + struct NineVertexDeclaration9 *vdecl = NineVertexDeclaration9(pDecl); + + DBG("This=%p pDecl=%p\n", This, pDecl); + + if (unlikely(This->is_recording)) { + nine_bind(&state->vdecl, vdecl); + state->changed.group |= NINE_STATE_VDECL; + return D3D_OK; + } + + if (state->vdecl == vdecl) + return D3D_OK; + + nine_bind(&state->vdecl, vdecl); + + nine_context_set_vertex_declaration(This, vdecl); + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_GetVertexDeclaration( struct NineDevice9 *This, + IDirect3DVertexDeclaration9 **ppDecl ) +{ + user_assert(ppDecl, D3DERR_INVALIDCALL); + + *ppDecl = (IDirect3DVertexDeclaration9 *)This->state.vdecl; + if (*ppDecl) + NineUnknown_AddRef(NineUnknown(*ppDecl)); + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_SetFVF( struct NineDevice9 *This, + DWORD FVF ) +{ + struct NineVertexDeclaration9 *vdecl; + HRESULT hr; + + DBG("FVF = %08x\n", FVF); + if (!FVF) + return D3D_OK; /* like wine */ + + vdecl = util_hash_table_get(This->ff.ht_fvf, &FVF); + if (!vdecl) { + hr = NineVertexDeclaration9_new_from_fvf(This, FVF, &vdecl); + if (FAILED(hr)) + return hr; + vdecl->fvf = FVF; + _mesa_hash_table_insert(This->ff.ht_fvf, &vdecl->fvf, vdecl); + NineUnknown_ConvertRefToBind(NineUnknown(vdecl)); + } + return NineDevice9_SetVertexDeclaration( + This, (IDirect3DVertexDeclaration9 *)vdecl); +} + +HRESULT NINE_WINAPI +NineDevice9_GetFVF( struct NineDevice9 *This, + DWORD *pFVF ) +{ + *pFVF = This->state.vdecl ? This->state.vdecl->fvf : 0; + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_CreateVertexShader( struct NineDevice9 *This, + const DWORD *pFunction, + IDirect3DVertexShader9 **ppShader ) +{ + struct NineVertexShader9 *vs; + HRESULT hr; + + DBG("This=%p pFunction=%p ppShader=%p\n", This, pFunction, ppShader); + + hr = NineVertexShader9_new(This, &vs, pFunction, NULL); + if (FAILED(hr)) + return hr; + *ppShader = (IDirect3DVertexShader9 *)vs; + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_SetVertexShader( struct NineDevice9 *This, + IDirect3DVertexShader9 *pShader ) +{ + struct nine_state *state = This->update; + struct NineVertexShader9 *vs_shader = (struct NineVertexShader9*)pShader; + + DBG("This=%p pShader=%p\n", This, pShader); + + if (unlikely(This->is_recording)) { + nine_bind(&state->vs, vs_shader); + state->changed.group |= NINE_STATE_VS; + return D3D_OK; + } + + if (state->vs == vs_shader) + return D3D_OK; + + nine_bind(&state->vs, vs_shader); + + nine_context_set_vertex_shader(This, vs_shader); + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_GetVertexShader( struct NineDevice9 *This, + IDirect3DVertexShader9 **ppShader ) +{ + user_assert(ppShader, D3DERR_INVALIDCALL); + nine_reference_set(ppShader, This->state.vs); + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_SetVertexShaderConstantF( struct NineDevice9 *This, + UINT StartRegister, + const float *pConstantData, + UINT Vector4fCount ) +{ + struct nine_state *state = This->update; + float *vs_const_f = state->vs_const_f; + + DBG("This=%p StartRegister=%u pConstantData=%p Vector4fCount=%u\n", + This, StartRegister, pConstantData, Vector4fCount); + + user_assert(StartRegister < This->caps.MaxVertexShaderConst, D3DERR_INVALIDCALL); + user_assert(StartRegister + Vector4fCount <= This->caps.MaxVertexShaderConst, D3DERR_INVALIDCALL); + + if (!Vector4fCount) + return D3D_OK; + user_assert(pConstantData, D3DERR_INVALIDCALL); + + if (unlikely(This->is_recording)) { + memcpy(&vs_const_f[StartRegister * 4], + pConstantData, + Vector4fCount * 4 * sizeof(state->vs_const_f[0])); + + nine_ranges_insert(&state->changed.vs_const_f, + StartRegister, StartRegister + Vector4fCount, + &This->range_pool); + + state->changed.group |= NINE_STATE_VS_CONST; + + return D3D_OK; + } + + if (!memcmp(&vs_const_f[StartRegister * 4], pConstantData, + Vector4fCount * 4 * sizeof(state->vs_const_f[0]))) + return D3D_OK; + + memcpy(&vs_const_f[StartRegister * 4], + pConstantData, + Vector4fCount * 4 * sizeof(state->vs_const_f[0])); + + nine_context_set_vertex_shader_constant_f(This, StartRegister, pConstantData, + Vector4fCount * 4 * sizeof(state->vs_const_f[0]), + Vector4fCount); + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_GetVertexShaderConstantF( struct NineDevice9 *This, + UINT StartRegister, + float *pConstantData, + UINT Vector4fCount ) +{ + const struct nine_state *state = &This->state; + + user_assert(StartRegister < This->caps.MaxVertexShaderConst, D3DERR_INVALIDCALL); + user_assert(StartRegister + Vector4fCount <= This->caps.MaxVertexShaderConst, D3DERR_INVALIDCALL); + user_assert(pConstantData, D3DERR_INVALIDCALL); + + memcpy(pConstantData, + &state->vs_const_f[StartRegister * 4], + Vector4fCount * 4 * sizeof(state->vs_const_f[0])); + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_SetVertexShaderConstantI( struct NineDevice9 *This, + UINT StartRegister, + const int *pConstantData, + UINT Vector4iCount ) +{ + struct nine_state *state = This->update; + int i; + + DBG("This=%p StartRegister=%u pConstantData=%p Vector4iCount=%u\n", + This, StartRegister, pConstantData, Vector4iCount); + + user_assert(StartRegister < (This->may_swvp ? NINE_MAX_CONST_I_SWVP : NINE_MAX_CONST_I), + D3DERR_INVALIDCALL); + user_assert(StartRegister + Vector4iCount <= (This->may_swvp ? NINE_MAX_CONST_I_SWVP : NINE_MAX_CONST_I), + D3DERR_INVALIDCALL); + user_assert(pConstantData, D3DERR_INVALIDCALL); + + if (This->driver_caps.vs_integer) { + if (!This->is_recording) { + if (!memcmp(&state->vs_const_i[4 * StartRegister], pConstantData, + Vector4iCount * sizeof(int[4]))) + return D3D_OK; + } + memcpy(&state->vs_const_i[4 * StartRegister], + pConstantData, + Vector4iCount * sizeof(int[4])); + } else { + for (i = 0; i < Vector4iCount; i++) { + state->vs_const_i[4 * (StartRegister + i)] = fui((float)(pConstantData[4 * i])); + state->vs_const_i[4 * (StartRegister + i) + 1] = fui((float)(pConstantData[4 * i + 1])); + state->vs_const_i[4 * (StartRegister + i) + 2] = fui((float)(pConstantData[4 * i + 2])); + state->vs_const_i[4 * (StartRegister + i) + 3] = fui((float)(pConstantData[4 * i + 3])); + } + } + + if (unlikely(This->is_recording)) { + nine_ranges_insert(&state->changed.vs_const_i, + StartRegister, StartRegister + Vector4iCount, + &This->range_pool); + state->changed.group |= NINE_STATE_VS_CONST; + } else + nine_context_set_vertex_shader_constant_i(This, StartRegister, pConstantData, + Vector4iCount * sizeof(int[4]), Vector4iCount); + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_GetVertexShaderConstantI( struct NineDevice9 *This, + UINT StartRegister, + int *pConstantData, + UINT Vector4iCount ) +{ + const struct nine_state *state = &This->state; + int i; + + user_assert(StartRegister < (This->may_swvp ? NINE_MAX_CONST_I_SWVP : NINE_MAX_CONST_I), + D3DERR_INVALIDCALL); + user_assert(StartRegister + Vector4iCount <= (This->may_swvp ? NINE_MAX_CONST_I_SWVP : NINE_MAX_CONST_I), + D3DERR_INVALIDCALL); + user_assert(pConstantData, D3DERR_INVALIDCALL); + + if (This->driver_caps.vs_integer) { + memcpy(pConstantData, + &state->vs_const_i[4 * StartRegister], + Vector4iCount * sizeof(int[4])); + } else { + for (i = 0; i < Vector4iCount; i++) { + pConstantData[4 * i] = (int32_t) uif(state->vs_const_i[4 * (StartRegister + i)]); + pConstantData[4 * i + 1] = (int32_t) uif(state->vs_const_i[4 * (StartRegister + i) + 1]); + pConstantData[4 * i + 2] = (int32_t) uif(state->vs_const_i[4 * (StartRegister + i) + 2]); + pConstantData[4 * i + 3] = (int32_t) uif(state->vs_const_i[4 * (StartRegister + i) + 3]); + } + } + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_SetVertexShaderConstantB( struct NineDevice9 *This, + UINT StartRegister, + const BOOL *pConstantData, + UINT BoolCount ) +{ + struct nine_state *state = This->update; + int i; + uint32_t bool_true = This->driver_caps.vs_integer ? 0xFFFFFFFF : fui(1.0f); + + DBG("This=%p StartRegister=%u pConstantData=%p BoolCount=%u\n", + This, StartRegister, pConstantData, BoolCount); + + user_assert(StartRegister < (This->may_swvp ? NINE_MAX_CONST_B_SWVP : NINE_MAX_CONST_B), + D3DERR_INVALIDCALL); + user_assert(StartRegister + BoolCount <= (This->may_swvp ? NINE_MAX_CONST_B_SWVP : NINE_MAX_CONST_B), + D3DERR_INVALIDCALL); + user_assert(pConstantData, D3DERR_INVALIDCALL); + + if (!This->is_recording) { + bool noChange = true; + for (i = 0; i < BoolCount; i++) { + if (!!state->vs_const_b[StartRegister + i] != !!pConstantData[i]) + noChange = false; + } + if (noChange) + return D3D_OK; + } + + for (i = 0; i < BoolCount; i++) + state->vs_const_b[StartRegister + i] = pConstantData[i] ? bool_true : 0; + + if (unlikely(This->is_recording)) { + nine_ranges_insert(&state->changed.vs_const_b, + StartRegister, StartRegister + BoolCount, + &This->range_pool); + state->changed.group |= NINE_STATE_VS_CONST; + } else + nine_context_set_vertex_shader_constant_b(This, StartRegister, pConstantData, + sizeof(BOOL) * BoolCount, BoolCount); + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_GetVertexShaderConstantB( struct NineDevice9 *This, + UINT StartRegister, + BOOL *pConstantData, + UINT BoolCount ) +{ + const struct nine_state *state = &This->state; + int i; + + user_assert(StartRegister < (This->may_swvp ? NINE_MAX_CONST_B_SWVP : NINE_MAX_CONST_B), + D3DERR_INVALIDCALL); + user_assert(StartRegister + BoolCount <= (This->may_swvp ? NINE_MAX_CONST_B_SWVP : NINE_MAX_CONST_B), + D3DERR_INVALIDCALL); + user_assert(pConstantData, D3DERR_INVALIDCALL); + + for (i = 0; i < BoolCount; i++) + pConstantData[i] = state->vs_const_b[StartRegister + i] != 0 ? TRUE : FALSE; + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_SetStreamSource( struct NineDevice9 *This, + UINT StreamNumber, + IDirect3DVertexBuffer9 *pStreamData, + UINT OffsetInBytes, + UINT Stride ) +{ + struct nine_state *state = This->update; + struct NineVertexBuffer9 *pVBuf9 = NineVertexBuffer9(pStreamData); + const unsigned i = StreamNumber; + + DBG("This=%p StreamNumber=%u pStreamData=%p OffsetInBytes=%u Stride=%u\n", + This, StreamNumber, pStreamData, OffsetInBytes, Stride); + + user_assert(StreamNumber < This->caps.MaxStreams, D3DERR_INVALIDCALL); + user_assert(Stride <= This->caps.MaxStreamStride, D3DERR_INVALIDCALL); + + if (unlikely(This->is_recording)) { + nine_bind(&state->stream[i], pStreamData); + state->changed.vtxbuf |= 1 << StreamNumber; + state->vtxbuf[i].stride = Stride; + state->vtxbuf[i].buffer_offset = OffsetInBytes; + return D3D_OK; + } + + if (state->stream[i] == NineVertexBuffer9(pStreamData) && + state->vtxbuf[i].stride == Stride && + state->vtxbuf[i].buffer_offset == OffsetInBytes) + return D3D_OK; + + state->vtxbuf[i].stride = Stride; + state->vtxbuf[i].buffer_offset = OffsetInBytes; + + NineBindBufferToDevice(This, + (struct NineBuffer9 **)&state->stream[i], + (struct NineBuffer9 *)pVBuf9); + + nine_context_set_stream_source(This, + StreamNumber, + pVBuf9, + OffsetInBytes, + Stride); + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_GetStreamSource( struct NineDevice9 *This, + UINT StreamNumber, + IDirect3DVertexBuffer9 **ppStreamData, + UINT *pOffsetInBytes, + UINT *pStride ) +{ + const struct nine_state *state = &This->state; + const unsigned i = StreamNumber; + + user_assert(StreamNumber < This->caps.MaxStreams, D3DERR_INVALIDCALL); + user_assert(ppStreamData, D3DERR_INVALIDCALL); + + nine_reference_set(ppStreamData, state->stream[i]); + *pStride = state->vtxbuf[i].stride; + *pOffsetInBytes = state->vtxbuf[i].buffer_offset; + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_SetStreamSourceFreq( struct NineDevice9 *This, + UINT StreamNumber, + UINT Setting ) +{ + struct nine_state *state = This->update; + /* const UINT freq = Setting & 0x7FFFFF; */ + + DBG("This=%p StreamNumber=%u FrequencyParameter=0x%x\n", This, + StreamNumber, Setting); + + user_assert(StreamNumber < This->caps.MaxStreams, D3DERR_INVALIDCALL); + user_assert(StreamNumber != 0 || !(Setting & D3DSTREAMSOURCE_INSTANCEDATA), + D3DERR_INVALIDCALL); + user_assert(!((Setting & D3DSTREAMSOURCE_INSTANCEDATA) && + (Setting & D3DSTREAMSOURCE_INDEXEDDATA)), D3DERR_INVALIDCALL); + user_assert(Setting, D3DERR_INVALIDCALL); + + if (unlikely(This->is_recording)) { + state->stream_freq[StreamNumber] = Setting; + state->changed.stream_freq |= 1 << StreamNumber; + return D3D_OK; + } + + if (state->stream_freq[StreamNumber] == Setting) + return D3D_OK; + + state->stream_freq[StreamNumber] = Setting; + + nine_context_set_stream_source_freq(This, StreamNumber, Setting); + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_GetStreamSourceFreq( struct NineDevice9 *This, + UINT StreamNumber, + UINT *pSetting ) +{ + user_assert(StreamNumber < This->caps.MaxStreams, D3DERR_INVALIDCALL); + *pSetting = This->state.stream_freq[StreamNumber]; + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_SetIndices( struct NineDevice9 *This, + IDirect3DIndexBuffer9 *pIndexData ) +{ + struct nine_state *state = This->update; + struct NineIndexBuffer9 *idxbuf = NineIndexBuffer9(pIndexData); + + DBG("This=%p pIndexData=%p\n", This, pIndexData); + + if (unlikely(This->is_recording)) { + nine_bind(&state->idxbuf, idxbuf); + state->changed.group |= NINE_STATE_IDXBUF; + return D3D_OK; + } + + if (state->idxbuf == idxbuf) + return D3D_OK; + + NineBindBufferToDevice(This, + (struct NineBuffer9 **)&state->idxbuf, + (struct NineBuffer9 *)idxbuf); + + nine_context_set_indices(This, idxbuf); + + return D3D_OK; +} + +/* XXX: wine/d3d9 doesn't have pBaseVertexIndex, and it doesn't make sense + * here because it's an argument passed to the Draw calls. + */ +HRESULT NINE_WINAPI +NineDevice9_GetIndices( struct NineDevice9 *This, + IDirect3DIndexBuffer9 **ppIndexData) +{ + user_assert(ppIndexData, D3DERR_INVALIDCALL); + nine_reference_set(ppIndexData, This->state.idxbuf); + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_CreatePixelShader( struct NineDevice9 *This, + const DWORD *pFunction, + IDirect3DPixelShader9 **ppShader ) +{ + struct NinePixelShader9 *ps; + HRESULT hr; + + DBG("This=%p pFunction=%p ppShader=%p\n", This, pFunction, ppShader); + + hr = NinePixelShader9_new(This, &ps, pFunction, NULL); + if (FAILED(hr)) + return hr; + *ppShader = (IDirect3DPixelShader9 *)ps; + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_SetPixelShader( struct NineDevice9 *This, + IDirect3DPixelShader9 *pShader ) +{ + struct nine_state *state = This->update; + struct NinePixelShader9 *ps = (struct NinePixelShader9*)pShader; + + DBG("This=%p pShader=%p\n", This, pShader); + + if (unlikely(This->is_recording)) { + nine_bind(&state->ps, pShader); + state->changed.group |= NINE_STATE_PS; + return D3D_OK; + } + + if (state->ps == ps) + return D3D_OK; + + nine_bind(&state->ps, ps); + + nine_context_set_pixel_shader(This, ps); + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_GetPixelShader( struct NineDevice9 *This, + IDirect3DPixelShader9 **ppShader ) +{ + user_assert(ppShader, D3DERR_INVALIDCALL); + nine_reference_set(ppShader, This->state.ps); + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_SetPixelShaderConstantF( struct NineDevice9 *This, + UINT StartRegister, + const float *pConstantData, + UINT Vector4fCount ) +{ + struct nine_state *state = This->update; + + DBG("This=%p StartRegister=%u pConstantData=%p Vector4fCount=%u\n", + This, StartRegister, pConstantData, Vector4fCount); + + user_assert(StartRegister < NINE_MAX_CONST_F_PS3, D3DERR_INVALIDCALL); + user_assert(StartRegister + Vector4fCount <= NINE_MAX_CONST_F_PS3, D3DERR_INVALIDCALL); + + if (!Vector4fCount) + return D3D_OK; + user_assert(pConstantData, D3DERR_INVALIDCALL); + + if (unlikely(This->is_recording)) { + memcpy(&state->ps_const_f[StartRegister * 4], + pConstantData, + Vector4fCount * 4 * sizeof(state->ps_const_f[0])); + + nine_ranges_insert(&state->changed.ps_const_f, + StartRegister, StartRegister + Vector4fCount, + &This->range_pool); + + state->changed.group |= NINE_STATE_PS_CONST; + return D3D_OK; + } + + if (!memcmp(&state->ps_const_f[StartRegister * 4], pConstantData, + Vector4fCount * 4 * sizeof(state->ps_const_f[0]))) + return D3D_OK; + + memcpy(&state->ps_const_f[StartRegister * 4], + pConstantData, + Vector4fCount * 4 * sizeof(state->ps_const_f[0])); + + nine_context_set_pixel_shader_constant_f(This, StartRegister, pConstantData, + Vector4fCount * 4 * sizeof(state->ps_const_f[0]), + Vector4fCount); + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_GetPixelShaderConstantF( struct NineDevice9 *This, + UINT StartRegister, + float *pConstantData, + UINT Vector4fCount ) +{ + const struct nine_state *state = &This->state; + + user_assert(StartRegister < NINE_MAX_CONST_F_PS3, D3DERR_INVALIDCALL); + user_assert(StartRegister + Vector4fCount <= NINE_MAX_CONST_F_PS3, D3DERR_INVALIDCALL); + user_assert(pConstantData, D3DERR_INVALIDCALL); + + memcpy(pConstantData, + &state->ps_const_f[StartRegister * 4], + Vector4fCount * 4 * sizeof(state->ps_const_f[0])); + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_SetPixelShaderConstantI( struct NineDevice9 *This, + UINT StartRegister, + const int *pConstantData, + UINT Vector4iCount ) +{ + struct nine_state *state = This->update; + int i; + + DBG("This=%p StartRegister=%u pConstantData=%p Vector4iCount=%u\n", + This, StartRegister, pConstantData, Vector4iCount); + + user_assert(StartRegister < NINE_MAX_CONST_I, D3DERR_INVALIDCALL); + user_assert(StartRegister + Vector4iCount <= NINE_MAX_CONST_I, D3DERR_INVALIDCALL); + user_assert(pConstantData, D3DERR_INVALIDCALL); + + if (This->driver_caps.ps_integer) { + if (!This->is_recording) { + if (!memcmp(&state->ps_const_i[StartRegister][0], pConstantData, + Vector4iCount * sizeof(state->ps_const_i[0]))) + return D3D_OK; + } + memcpy(&state->ps_const_i[StartRegister][0], + pConstantData, + Vector4iCount * sizeof(state->ps_const_i[0])); + } else { + for (i = 0; i < Vector4iCount; i++) { + state->ps_const_i[StartRegister+i][0] = fui((float)(pConstantData[4*i])); + state->ps_const_i[StartRegister+i][1] = fui((float)(pConstantData[4*i+1])); + state->ps_const_i[StartRegister+i][2] = fui((float)(pConstantData[4*i+2])); + state->ps_const_i[StartRegister+i][3] = fui((float)(pConstantData[4*i+3])); + } + } + + if (unlikely(This->is_recording)) { + state->changed.ps_const_i |= ((1 << Vector4iCount) - 1) << StartRegister; + state->changed.group |= NINE_STATE_PS_CONST; + } else + nine_context_set_pixel_shader_constant_i(This, StartRegister, pConstantData, + sizeof(state->ps_const_i[0]) * Vector4iCount, Vector4iCount); + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_GetPixelShaderConstantI( struct NineDevice9 *This, + UINT StartRegister, + int *pConstantData, + UINT Vector4iCount ) +{ + const struct nine_state *state = &This->state; + int i; + + user_assert(StartRegister < NINE_MAX_CONST_I, D3DERR_INVALIDCALL); + user_assert(StartRegister + Vector4iCount <= NINE_MAX_CONST_I, D3DERR_INVALIDCALL); + user_assert(pConstantData, D3DERR_INVALIDCALL); + + if (This->driver_caps.ps_integer) { + memcpy(pConstantData, + &state->ps_const_i[StartRegister][0], + Vector4iCount * sizeof(state->ps_const_i[0])); + } else { + for (i = 0; i < Vector4iCount; i++) { + pConstantData[4*i] = (int32_t) uif(state->ps_const_i[StartRegister+i][0]); + pConstantData[4*i+1] = (int32_t) uif(state->ps_const_i[StartRegister+i][1]); + pConstantData[4*i+2] = (int32_t) uif(state->ps_const_i[StartRegister+i][2]); + pConstantData[4*i+3] = (int32_t) uif(state->ps_const_i[StartRegister+i][3]); + } + } + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_SetPixelShaderConstantB( struct NineDevice9 *This, + UINT StartRegister, + const BOOL *pConstantData, + UINT BoolCount ) +{ + struct nine_state *state = This->update; + int i; + uint32_t bool_true = This->driver_caps.ps_integer ? 0xFFFFFFFF : fui(1.0f); + + DBG("This=%p StartRegister=%u pConstantData=%p BoolCount=%u\n", + This, StartRegister, pConstantData, BoolCount); + + user_assert(StartRegister < NINE_MAX_CONST_B, D3DERR_INVALIDCALL); + user_assert(StartRegister + BoolCount <= NINE_MAX_CONST_B, D3DERR_INVALIDCALL); + user_assert(pConstantData, D3DERR_INVALIDCALL); + + if (!This->is_recording) { + bool noChange = true; + for (i = 0; i < BoolCount; i++) { + if (!!state->ps_const_b[StartRegister + i] != !!pConstantData[i]) + noChange = false; + } + if (noChange) + return D3D_OK; + } + + for (i = 0; i < BoolCount; i++) + state->ps_const_b[StartRegister + i] = pConstantData[i] ? bool_true : 0; + + if (unlikely(This->is_recording)) { + state->changed.ps_const_b |= ((1 << BoolCount) - 1) << StartRegister; + state->changed.group |= NINE_STATE_PS_CONST; + } else + nine_context_set_pixel_shader_constant_b(This, StartRegister, pConstantData, + sizeof(BOOL) * BoolCount, BoolCount); + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_GetPixelShaderConstantB( struct NineDevice9 *This, + UINT StartRegister, + BOOL *pConstantData, + UINT BoolCount ) +{ + const struct nine_state *state = &This->state; + int i; + + user_assert(StartRegister < NINE_MAX_CONST_B, D3DERR_INVALIDCALL); + user_assert(StartRegister + BoolCount <= NINE_MAX_CONST_B, D3DERR_INVALIDCALL); + user_assert(pConstantData, D3DERR_INVALIDCALL); + + for (i = 0; i < BoolCount; i++) + pConstantData[i] = state->ps_const_b[StartRegister + i] ? TRUE : FALSE; + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9_DrawRectPatch( struct NineDevice9 *This, + UINT Handle, + const float *pNumSegs, + const D3DRECTPATCH_INFO *pRectPatchInfo ) +{ + STUB(D3DERR_INVALIDCALL); +} + +HRESULT NINE_WINAPI +NineDevice9_DrawTriPatch( struct NineDevice9 *This, + UINT Handle, + const float *pNumSegs, + const D3DTRIPATCH_INFO *pTriPatchInfo ) +{ + STUB(D3DERR_INVALIDCALL); +} + +HRESULT NINE_WINAPI +NineDevice9_DeletePatch( struct NineDevice9 *This, + UINT Handle ) +{ + STUB(D3DERR_INVALIDCALL); +} + +HRESULT NINE_WINAPI +NineDevice9_CreateQuery( struct NineDevice9 *This, + D3DQUERYTYPE Type, + IDirect3DQuery9 **ppQuery ) +{ + struct NineQuery9 *query; + HRESULT hr; + + DBG("This=%p Type=%d ppQuery=%p\n", This, Type, ppQuery); + + hr = nine_is_query_supported(This->screen, Type); + if (!ppQuery || hr != D3D_OK) + return hr; + + hr = NineQuery9_new(This, &query, Type); + if (FAILED(hr)) + return hr; + *ppQuery = (IDirect3DQuery9 *)query; + return D3D_OK; +} + +IDirect3DDevice9Vtbl NineDevice9_vtable = { + (void *)NineUnknown_QueryInterface, + (void *)NineUnknown_AddRef, + (void *)NineUnknown_Release, + (void *)NineDevice9_TestCooperativeLevel, + (void *)NineDevice9_GetAvailableTextureMem, + (void *)NineDevice9_EvictManagedResources, + (void *)NineDevice9_GetDirect3D, + (void *)NineDevice9_GetDeviceCaps, + (void *)NineDevice9_GetDisplayMode, + (void *)NineDevice9_GetCreationParameters, + (void *)NineDevice9_SetCursorProperties, + (void *)NineDevice9_SetCursorPosition, + (void *)NineDevice9_ShowCursor, + (void *)NineDevice9_CreateAdditionalSwapChain, + (void *)NineDevice9_GetSwapChain, + (void *)NineDevice9_GetNumberOfSwapChains, + (void *)NineDevice9_Reset, + (void *)NineDevice9_Present, + (void *)NineDevice9_GetBackBuffer, + (void *)NineDevice9_GetRasterStatus, + (void *)NineDevice9_SetDialogBoxMode, + (void *)NineDevice9_SetGammaRamp, + (void *)NineDevice9_GetGammaRamp, + (void *)NineDevice9_CreateTexture, + (void *)NineDevice9_CreateVolumeTexture, + (void *)NineDevice9_CreateCubeTexture, + (void *)NineDevice9_CreateVertexBuffer, + (void *)NineDevice9_CreateIndexBuffer, + (void *)NineDevice9_CreateRenderTarget, + (void *)NineDevice9_CreateDepthStencilSurface, + (void *)NineDevice9_UpdateSurface, + (void *)NineDevice9_UpdateTexture, + (void *)NineDevice9_GetRenderTargetData, + (void *)NineDevice9_GetFrontBufferData, + (void *)NineDevice9_StretchRect, + (void *)NineDevice9_ColorFill, + (void *)NineDevice9_CreateOffscreenPlainSurface, + (void *)NineDevice9_SetRenderTarget, + (void *)NineDevice9_GetRenderTarget, + (void *)NineDevice9_SetDepthStencilSurface, + (void *)NineDevice9_GetDepthStencilSurface, + (void *)NineDevice9_BeginScene, + (void *)NineDevice9_EndScene, + (void *)NineDevice9_Clear, + (void *)NineDevice9_SetTransform, + (void *)NineDevice9_GetTransform, + (void *)NineDevice9_MultiplyTransform, + (void *)NineDevice9_SetViewport, + (void *)NineDevice9_GetViewport, + (void *)NineDevice9_SetMaterial, + (void *)NineDevice9_GetMaterial, + (void *)NineDevice9_SetLight, + (void *)NineDevice9_GetLight, + (void *)NineDevice9_LightEnable, + (void *)NineDevice9_GetLightEnable, + (void *)NineDevice9_SetClipPlane, + (void *)NineDevice9_GetClipPlane, + (void *)NineDevice9_SetRenderState, + (void *)NineDevice9_GetRenderState, + (void *)NineDevice9_CreateStateBlock, + (void *)NineDevice9_BeginStateBlock, + (void *)NineDevice9_EndStateBlock, + (void *)NineDevice9_SetClipStatus, + (void *)NineDevice9_GetClipStatus, + (void *)NineDevice9_GetTexture, + (void *)NineDevice9_SetTexture, + (void *)NineDevice9_GetTextureStageState, + (void *)NineDevice9_SetTextureStageState, + (void *)NineDevice9_GetSamplerState, + (void *)NineDevice9_SetSamplerState, + (void *)NineDevice9_ValidateDevice, + (void *)NineDevice9_SetPaletteEntries, + (void *)NineDevice9_GetPaletteEntries, + (void *)NineDevice9_SetCurrentTexturePalette, + (void *)NineDevice9_GetCurrentTexturePalette, + (void *)NineDevice9_SetScissorRect, + (void *)NineDevice9_GetScissorRect, + (void *)NineDevice9_SetSoftwareVertexProcessing, + (void *)NineDevice9_GetSoftwareVertexProcessing, + (void *)NineDevice9_SetNPatchMode, + (void *)NineDevice9_GetNPatchMode, + (void *)NineDevice9_DrawPrimitive, + (void *)NineDevice9_DrawIndexedPrimitive, + (void *)NineDevice9_DrawPrimitiveUP, + (void *)NineDevice9_DrawIndexedPrimitiveUP, + (void *)NineDevice9_ProcessVertices, + (void *)NineDevice9_CreateVertexDeclaration, + (void *)NineDevice9_SetVertexDeclaration, + (void *)NineDevice9_GetVertexDeclaration, + (void *)NineDevice9_SetFVF, + (void *)NineDevice9_GetFVF, + (void *)NineDevice9_CreateVertexShader, + (void *)NineDevice9_SetVertexShader, + (void *)NineDevice9_GetVertexShader, + (void *)NineDevice9_SetVertexShaderConstantF, + (void *)NineDevice9_GetVertexShaderConstantF, + (void *)NineDevice9_SetVertexShaderConstantI, + (void *)NineDevice9_GetVertexShaderConstantI, + (void *)NineDevice9_SetVertexShaderConstantB, + (void *)NineDevice9_GetVertexShaderConstantB, + (void *)NineDevice9_SetStreamSource, + (void *)NineDevice9_GetStreamSource, + (void *)NineDevice9_SetStreamSourceFreq, + (void *)NineDevice9_GetStreamSourceFreq, + (void *)NineDevice9_SetIndices, + (void *)NineDevice9_GetIndices, + (void *)NineDevice9_CreatePixelShader, + (void *)NineDevice9_SetPixelShader, + (void *)NineDevice9_GetPixelShader, + (void *)NineDevice9_SetPixelShaderConstantF, + (void *)NineDevice9_GetPixelShaderConstantF, + (void *)NineDevice9_SetPixelShaderConstantI, + (void *)NineDevice9_GetPixelShaderConstantI, + (void *)NineDevice9_SetPixelShaderConstantB, + (void *)NineDevice9_GetPixelShaderConstantB, + (void *)NineDevice9_DrawRectPatch, + (void *)NineDevice9_DrawTriPatch, + (void *)NineDevice9_DeletePatch, + (void *)NineDevice9_CreateQuery +}; + +static const GUID *NineDevice9_IIDs[] = { + &IID_IDirect3DDevice9, + &IID_IUnknown, + NULL +}; + +HRESULT +NineDevice9_new( struct pipe_screen *pScreen, + D3DDEVICE_CREATION_PARAMETERS *pCreationParameters, + D3DCAPS9 *pCaps, + D3DPRESENT_PARAMETERS *pPresentationParameters, + IDirect3D9 *pD3D9, + ID3DPresentGroup *pPresentationGroup, + struct d3dadapter9_context *pCTX, + boolean ex, + D3DDISPLAYMODEEX *pFullscreenDisplayMode, + struct NineDevice9 **ppOut, + int minorVersionNum ) +{ + BOOL lock; + lock = !!(pCreationParameters->BehaviorFlags & D3DCREATE_MULTITHREADED); + + NINE_NEW(Device9, ppOut, lock, /* args */ + pScreen, pCreationParameters, pCaps, + pPresentationParameters, pD3D9, pPresentationGroup, pCTX, + ex, pFullscreenDisplayMode, minorVersionNum ); +} diff --git a/src/gallium/frontends/nine/device9.h b/src/gallium/frontends/nine/device9.h new file mode 100644 index 00000000000..f24d79295ad --- /dev/null +++ b/src/gallium/frontends/nine/device9.h @@ -0,0 +1,841 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _NINE_DEVICE9_H_ +#define _NINE_DEVICE9_H_ + +#include "d3dadapter/d3dadapter9.h" + +#include "iunknown.h" +#include "adapter9.h" + +#include "nine_helpers.h" +#include "nine_state.h" + +struct gen_mipmap_state; +struct hash_table; +struct pipe_screen; +struct pipe_context; +struct cso_context; +struct hud_context; +struct u_upload_mgr; +struct csmt_context; + +struct NineSwapChain9; +struct NineStateBlock9; + +#include "util/list.h" + +struct NineDevice9 +{ + struct NineUnknown base; + boolean ex; + boolean may_swvp; + + /* G3D context */ + struct pipe_screen *screen; + /* For first time upload. No Sync with rendering thread */ + struct pipe_context *pipe_secondary; + struct pipe_screen *screen_sw; + struct pipe_context *pipe_sw; + struct cso_context *cso_sw; + + /* CSMT context */ + struct csmt_context *csmt_ctx; + BOOL csmt_active; + + /* For DISCARD/NOOVERWRITE */ + struct nine_buffer_upload *buffer_upload; + + /* creation parameters */ + D3DCAPS9 caps; + D3DDEVICE_CREATION_PARAMETERS params; + IDirect3D9 *d3d9; + + /* swapchain stuff */ + ID3DPresentGroup *present; + struct NineSwapChain9 **swapchains; + unsigned nswapchains; + + struct NineStateBlock9 *record; + struct nine_state *update; /* state to update (&state / &record->state) */ + struct nine_state state; /* device state */ + struct nine_context context; + struct nine_state_sw_internal state_sw_internal; + + struct list_head update_buffers; + struct list_head update_textures; + struct list_head managed_buffers; + struct list_head managed_textures; + + boolean is_recording; + boolean in_scene; + + uint16_t vs_const_size; + uint16_t ps_const_size; + uint16_t max_vs_const_f; + uint16_t max_ps_const_f; + + struct pipe_resource *dummy_texture; + struct pipe_sampler_view *dummy_sampler_view; + struct pipe_sampler_state dummy_sampler_state; + + struct gen_mipmap_state *gen_mipmap; + + struct { + struct hash_table *ht_vs; + struct hash_table *ht_ps; + struct NineVertexShader9 *vs; + struct NinePixelShader9 *ps; + unsigned num_vs; + unsigned num_ps; + float *vs_const; + float *ps_const; + + struct hash_table *ht_fvf; + } ff; + + struct { + struct pipe_resource *image; + unsigned w; + unsigned h; + POINT hotspot; /* -1, -1 if no cursor image set */ + POINT pos; + BOOL visible; + boolean software; + void *hw_upload_temp; + } cursor; + + struct { + boolean user_vbufs; + boolean user_sw_vbufs; + boolean window_space_position_support; + boolean vs_integer; + boolean ps_integer; + boolean offset_units_unscaled; + } driver_caps; + + struct { + boolean buggy_barycentrics; + } driver_bugs; + + struct { + boolean dynamic_texture_workaround; + } workarounds; + + struct u_upload_mgr *vertex_uploader; + + struct nine_range_pool range_pool; + + struct hud_context *hud; /* NULL if hud is disabled */ + + /* dummy vbo (containing 0 0 0 0) to bind if vertex shader input + * is not bound to anything by the vertex declaration */ + struct pipe_resource *dummy_vbo; + BOOL device_needs_reset; + int minor_version_num; + long long available_texture_mem; + long long available_texture_limit; + + /* software vertex processing */ + boolean swvp; +}; +static inline struct NineDevice9 * +NineDevice9( void *data ) +{ + return (struct NineDevice9 *)data; +} + +HRESULT +NineDevice9_new( struct pipe_screen *pScreen, + D3DDEVICE_CREATION_PARAMETERS *pCreationParameters, + D3DCAPS9 *pCaps, + D3DPRESENT_PARAMETERS *pPresentationParameters, + IDirect3D9 *pD3D9, + ID3DPresentGroup *pPresentationGroup, + struct d3dadapter9_context *pCTX, + boolean ex, + D3DDISPLAYMODEEX *pFullscreenDisplayMode, + struct NineDevice9 **ppOut, + int minorVersionNum ); + +HRESULT +NineDevice9_ctor( struct NineDevice9 *This, + struct NineUnknownParams *pParams, + struct pipe_screen *pScreen, + D3DDEVICE_CREATION_PARAMETERS *pCreationParameters, + D3DCAPS9 *pCaps, + D3DPRESENT_PARAMETERS *pPresentationParameters, + IDirect3D9 *pD3D9, + ID3DPresentGroup *pPresentationGroup, + struct d3dadapter9_context *pCTX, + boolean ex, + D3DDISPLAYMODEEX *pFullscreenDisplayMode, + int minorVersionNum ); + +void +NineDevice9_dtor( struct NineDevice9 *This ); + +/*** Nine private ***/ +void +NineDevice9_SetDefaultState( struct NineDevice9 *This, boolean is_reset ); + +struct pipe_screen * +NineDevice9_GetScreen( struct NineDevice9 *This ); + +struct pipe_context * +NineDevice9_GetPipe( struct NineDevice9 *This ); + +const D3DCAPS9 * +NineDevice9_GetCaps( struct NineDevice9 *This ); + +/*** Direct3D public ***/ + +HRESULT NINE_WINAPI +NineDevice9_TestCooperativeLevel( struct NineDevice9 *This ); + +UINT NINE_WINAPI +NineDevice9_GetAvailableTextureMem( struct NineDevice9 *This ); + +HRESULT NINE_WINAPI +NineDevice9_EvictManagedResources( struct NineDevice9 *This ); + +HRESULT NINE_WINAPI +NineDevice9_GetDirect3D( struct NineDevice9 *This, + IDirect3D9 **ppD3D9 ); + +HRESULT NINE_WINAPI +NineDevice9_GetDeviceCaps( struct NineDevice9 *This, + D3DCAPS9 *pCaps ); + +HRESULT NINE_WINAPI +NineDevice9_GetDisplayMode( struct NineDevice9 *This, + UINT iSwapChain, + D3DDISPLAYMODE *pMode ); + +HRESULT NINE_WINAPI +NineDevice9_GetCreationParameters( struct NineDevice9 *This, + D3DDEVICE_CREATION_PARAMETERS *pParameters ); + +HRESULT NINE_WINAPI +NineDevice9_SetCursorProperties( struct NineDevice9 *This, + UINT XHotSpot, + UINT YHotSpot, + IDirect3DSurface9 *pCursorBitmap ); + +void NINE_WINAPI +NineDevice9_SetCursorPosition( struct NineDevice9 *This, + int X, + int Y, + DWORD Flags ); + +BOOL NINE_WINAPI +NineDevice9_ShowCursor( struct NineDevice9 *This, + BOOL bShow ); + +HRESULT NINE_WINAPI +NineDevice9_CreateAdditionalSwapChain( struct NineDevice9 *This, + D3DPRESENT_PARAMETERS *pPresentationParameters, + IDirect3DSwapChain9 **pSwapChain ); + +HRESULT NINE_WINAPI +NineDevice9_GetSwapChain( struct NineDevice9 *This, + UINT iSwapChain, + IDirect3DSwapChain9 **pSwapChain ); + +UINT NINE_WINAPI +NineDevice9_GetNumberOfSwapChains( struct NineDevice9 *This ); + +HRESULT NINE_WINAPI +NineDevice9_Reset( struct NineDevice9 *This, + D3DPRESENT_PARAMETERS *pPresentationParameters ); + +HRESULT NINE_WINAPI +NineDevice9_Present( struct NineDevice9 *This, + const RECT *pSourceRect, + const RECT *pDestRect, + HWND hDestWindowOverride, + const RGNDATA *pDirtyRegion ); + +HRESULT NINE_WINAPI +NineDevice9_GetBackBuffer( struct NineDevice9 *This, + UINT iSwapChain, + UINT iBackBuffer, + D3DBACKBUFFER_TYPE Type, + IDirect3DSurface9 **ppBackBuffer ); + +HRESULT NINE_WINAPI +NineDevice9_GetRasterStatus( struct NineDevice9 *This, + UINT iSwapChain, + D3DRASTER_STATUS *pRasterStatus ); + +HRESULT NINE_WINAPI +NineDevice9_SetDialogBoxMode( struct NineDevice9 *This, + BOOL bEnableDialogs ); + +void NINE_WINAPI +NineDevice9_SetGammaRamp( struct NineDevice9 *This, + UINT iSwapChain, + DWORD Flags, + const D3DGAMMARAMP *pRamp ); + +void NINE_WINAPI +NineDevice9_GetGammaRamp( struct NineDevice9 *This, + UINT iSwapChain, + D3DGAMMARAMP *pRamp ); + +HRESULT NINE_WINAPI +NineDevice9_CreateTexture( struct NineDevice9 *This, + UINT Width, + UINT Height, + UINT Levels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + IDirect3DTexture9 **ppTexture, + HANDLE *pSharedHandle ); + +HRESULT NINE_WINAPI +NineDevice9_CreateVolumeTexture( struct NineDevice9 *This, + UINT Width, + UINT Height, + UINT Depth, + UINT Levels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + IDirect3DVolumeTexture9 **ppVolumeTexture, + HANDLE *pSharedHandle ); + +HRESULT NINE_WINAPI +NineDevice9_CreateCubeTexture( struct NineDevice9 *This, + UINT EdgeLength, + UINT Levels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + IDirect3DCubeTexture9 **ppCubeTexture, + HANDLE *pSharedHandle ); + +HRESULT NINE_WINAPI +NineDevice9_CreateVertexBuffer( struct NineDevice9 *This, + UINT Length, + DWORD Usage, + DWORD FVF, + D3DPOOL Pool, + IDirect3DVertexBuffer9 **ppVertexBuffer, + HANDLE *pSharedHandle ); + +HRESULT NINE_WINAPI +NineDevice9_CreateIndexBuffer( struct NineDevice9 *This, + UINT Length, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + IDirect3DIndexBuffer9 **ppIndexBuffer, + HANDLE *pSharedHandle ); + +HRESULT NINE_WINAPI +NineDevice9_CreateRenderTarget( struct NineDevice9 *This, + UINT Width, + UINT Height, + D3DFORMAT Format, + D3DMULTISAMPLE_TYPE MultiSample, + DWORD MultisampleQuality, + BOOL Lockable, + IDirect3DSurface9 **ppSurface, + HANDLE *pSharedHandle ); + +HRESULT NINE_WINAPI +NineDevice9_CreateDepthStencilSurface( struct NineDevice9 *This, + UINT Width, + UINT Height, + D3DFORMAT Format, + D3DMULTISAMPLE_TYPE MultiSample, + DWORD MultisampleQuality, + BOOL Discard, + IDirect3DSurface9 **ppSurface, + HANDLE *pSharedHandle ); + +HRESULT NINE_WINAPI +NineDevice9_UpdateSurface( struct NineDevice9 *This, + IDirect3DSurface9 *pSourceSurface, + const RECT *pSourceRect, + IDirect3DSurface9 *pDestinationSurface, + const POINT *pDestPoint ); + +HRESULT NINE_WINAPI +NineDevice9_UpdateTexture( struct NineDevice9 *This, + IDirect3DBaseTexture9 *pSourceTexture, + IDirect3DBaseTexture9 *pDestinationTexture ); + +HRESULT NINE_WINAPI +NineDevice9_GetRenderTargetData( struct NineDevice9 *This, + IDirect3DSurface9 *pRenderTarget, + IDirect3DSurface9 *pDestSurface ); + +HRESULT NINE_WINAPI +NineDevice9_GetFrontBufferData( struct NineDevice9 *This, + UINT iSwapChain, + IDirect3DSurface9 *pDestSurface ); + +HRESULT NINE_WINAPI +NineDevice9_StretchRect( struct NineDevice9 *This, + IDirect3DSurface9 *pSourceSurface, + const RECT *pSourceRect, + IDirect3DSurface9 *pDestSurface, + const RECT *pDestRect, + D3DTEXTUREFILTERTYPE Filter ); + +HRESULT NINE_WINAPI +NineDevice9_ColorFill( struct NineDevice9 *This, + IDirect3DSurface9 *pSurface, + const RECT *pRect, + D3DCOLOR color ); + +HRESULT NINE_WINAPI +NineDevice9_CreateOffscreenPlainSurface( struct NineDevice9 *This, + UINT Width, + UINT Height, + D3DFORMAT Format, + D3DPOOL Pool, + IDirect3DSurface9 **ppSurface, + HANDLE *pSharedHandle ); + +HRESULT NINE_WINAPI +NineDevice9_SetRenderTarget( struct NineDevice9 *This, + DWORD RenderTargetIndex, + IDirect3DSurface9 *pRenderTarget ); + +HRESULT NINE_WINAPI +NineDevice9_GetRenderTarget( struct NineDevice9 *This, + DWORD RenderTargetIndex, + IDirect3DSurface9 **ppRenderTarget ); + +HRESULT NINE_WINAPI +NineDevice9_SetDepthStencilSurface( struct NineDevice9 *This, + IDirect3DSurface9 *pNewZStencil ); + +HRESULT NINE_WINAPI +NineDevice9_GetDepthStencilSurface( struct NineDevice9 *This, + IDirect3DSurface9 **ppZStencilSurface ); + +HRESULT NINE_WINAPI +NineDevice9_BeginScene( struct NineDevice9 *This ); + +HRESULT NINE_WINAPI +NineDevice9_EndScene( struct NineDevice9 *This ); + +HRESULT NINE_WINAPI +NineDevice9_Clear( struct NineDevice9 *This, + DWORD Count, + const D3DRECT *pRects, + DWORD Flags, + D3DCOLOR Color, + float Z, + DWORD Stencil ); + +HRESULT NINE_WINAPI +NineDevice9_SetTransform( struct NineDevice9 *This, + D3DTRANSFORMSTATETYPE State, + const D3DMATRIX *pMatrix ); + +HRESULT NINE_WINAPI +NineDevice9_GetTransform( struct NineDevice9 *This, + D3DTRANSFORMSTATETYPE State, + D3DMATRIX *pMatrix ); + +HRESULT NINE_WINAPI +NineDevice9_MultiplyTransform( struct NineDevice9 *This, + D3DTRANSFORMSTATETYPE State, + const D3DMATRIX *pMatrix ); + +HRESULT NINE_WINAPI +NineDevice9_SetViewport( struct NineDevice9 *This, + const D3DVIEWPORT9 *pViewport ); + +HRESULT NINE_WINAPI +NineDevice9_GetViewport( struct NineDevice9 *This, + D3DVIEWPORT9 *pViewport ); + +HRESULT NINE_WINAPI +NineDevice9_SetMaterial( struct NineDevice9 *This, + const D3DMATERIAL9 *pMaterial ); + +HRESULT NINE_WINAPI +NineDevice9_GetMaterial( struct NineDevice9 *This, + D3DMATERIAL9 *pMaterial ); + +HRESULT NINE_WINAPI +NineDevice9_SetLight( struct NineDevice9 *This, + DWORD Index, + const D3DLIGHT9 *pLight ); + +HRESULT NINE_WINAPI +NineDevice9_GetLight( struct NineDevice9 *This, + DWORD Index, + D3DLIGHT9 *pLight ); + +HRESULT NINE_WINAPI +NineDevice9_LightEnable( struct NineDevice9 *This, + DWORD Index, + BOOL Enable ); + +HRESULT NINE_WINAPI +NineDevice9_GetLightEnable( struct NineDevice9 *This, + DWORD Index, + BOOL *pEnable ); + +HRESULT NINE_WINAPI +NineDevice9_SetClipPlane( struct NineDevice9 *This, + DWORD Index, + const float *pPlane ); + +HRESULT NINE_WINAPI +NineDevice9_GetClipPlane( struct NineDevice9 *This, + DWORD Index, + float *pPlane ); + +HRESULT NINE_WINAPI +NineDevice9_SetRenderState( struct NineDevice9 *This, + D3DRENDERSTATETYPE State, + DWORD Value ); + +HRESULT NINE_WINAPI +NineDevice9_GetRenderState( struct NineDevice9 *This, + D3DRENDERSTATETYPE State, + DWORD *pValue ); + +HRESULT NINE_WINAPI +NineDevice9_CreateStateBlock( struct NineDevice9 *This, + D3DSTATEBLOCKTYPE Type, + IDirect3DStateBlock9 **ppSB ); + +HRESULT NINE_WINAPI +NineDevice9_BeginStateBlock( struct NineDevice9 *This ); + +HRESULT NINE_WINAPI +NineDevice9_EndStateBlock( struct NineDevice9 *This, + IDirect3DStateBlock9 **ppSB ); + +HRESULT NINE_WINAPI +NineDevice9_SetClipStatus( struct NineDevice9 *This, + const D3DCLIPSTATUS9 *pClipStatus ); + +HRESULT NINE_WINAPI +NineDevice9_GetClipStatus( struct NineDevice9 *This, + D3DCLIPSTATUS9 *pClipStatus ); + +HRESULT NINE_WINAPI +NineDevice9_GetTexture( struct NineDevice9 *This, + DWORD Stage, + IDirect3DBaseTexture9 **ppTexture ); + +HRESULT NINE_WINAPI +NineDevice9_SetTexture( struct NineDevice9 *This, + DWORD Stage, + IDirect3DBaseTexture9 *pTexture ); + +HRESULT NINE_WINAPI +NineDevice9_GetTextureStageState( struct NineDevice9 *This, + DWORD Stage, + D3DTEXTURESTAGESTATETYPE Type, + DWORD *pValue ); + +HRESULT NINE_WINAPI +NineDevice9_SetTextureStageState( struct NineDevice9 *This, + DWORD Stage, + D3DTEXTURESTAGESTATETYPE Type, + DWORD Value ); + +HRESULT NINE_WINAPI +NineDevice9_GetSamplerState( struct NineDevice9 *This, + DWORD Sampler, + D3DSAMPLERSTATETYPE Type, + DWORD *pValue ); + +HRESULT NINE_WINAPI +NineDevice9_SetSamplerState( struct NineDevice9 *This, + DWORD Sampler, + D3DSAMPLERSTATETYPE Type, + DWORD Value ); + +HRESULT NINE_WINAPI +NineDevice9_ValidateDevice( struct NineDevice9 *This, + DWORD *pNumPasses ); + +HRESULT NINE_WINAPI +NineDevice9_SetPaletteEntries( struct NineDevice9 *This, + UINT PaletteNumber, + const PALETTEENTRY *pEntries ); + +HRESULT NINE_WINAPI +NineDevice9_GetPaletteEntries( struct NineDevice9 *This, + UINT PaletteNumber, + PALETTEENTRY *pEntries ); + +HRESULT NINE_WINAPI +NineDevice9_SetCurrentTexturePalette( struct NineDevice9 *This, + UINT PaletteNumber ); + +HRESULT NINE_WINAPI +NineDevice9_GetCurrentTexturePalette( struct NineDevice9 *This, + UINT *PaletteNumber ); + +HRESULT NINE_WINAPI +NineDevice9_SetScissorRect( struct NineDevice9 *This, + const RECT *pRect ); + +HRESULT NINE_WINAPI +NineDevice9_GetScissorRect( struct NineDevice9 *This, + RECT *pRect ); + +HRESULT NINE_WINAPI +NineDevice9_SetSoftwareVertexProcessing( struct NineDevice9 *This, + BOOL bSoftware ); + +BOOL NINE_WINAPI +NineDevice9_GetSoftwareVertexProcessing( struct NineDevice9 *This ); + +HRESULT NINE_WINAPI +NineDevice9_SetNPatchMode( struct NineDevice9 *This, + float nSegments ); + +float NINE_WINAPI +NineDevice9_GetNPatchMode( struct NineDevice9 *This ); + +HRESULT NINE_WINAPI +NineDevice9_DrawPrimitive( struct NineDevice9 *This, + D3DPRIMITIVETYPE PrimitiveType, + UINT StartVertex, + UINT PrimitiveCount ); + +HRESULT NINE_WINAPI +NineDevice9_DrawIndexedPrimitive( struct NineDevice9 *This, + D3DPRIMITIVETYPE PrimitiveType, + INT BaseVertexIndex, + UINT MinVertexIndex, + UINT NumVertices, + UINT startIndex, + UINT primCount ); + +HRESULT NINE_WINAPI +NineDevice9_DrawPrimitiveUP( struct NineDevice9 *This, + D3DPRIMITIVETYPE PrimitiveType, + UINT PrimitiveCount, + const void *pVertexStreamZeroData, + UINT VertexStreamZeroStride ); + +HRESULT NINE_WINAPI +NineDevice9_DrawIndexedPrimitiveUP( struct NineDevice9 *This, + D3DPRIMITIVETYPE PrimitiveType, + UINT MinVertexIndex, + UINT NumVertices, + UINT PrimitiveCount, + const void *pIndexData, + D3DFORMAT IndexDataFormat, + const void *pVertexStreamZeroData, + UINT VertexStreamZeroStride ); + +HRESULT NINE_WINAPI +NineDevice9_ProcessVertices( struct NineDevice9 *This, + UINT SrcStartIndex, + UINT DestIndex, + UINT VertexCount, + IDirect3DVertexBuffer9 *pDestBuffer, + IDirect3DVertexDeclaration9 *pVertexDecl, + DWORD Flags ); + +HRESULT NINE_WINAPI +NineDevice9_CreateVertexDeclaration( struct NineDevice9 *This, + const D3DVERTEXELEMENT9 *pVertexElements, + IDirect3DVertexDeclaration9 **ppDecl ); + +HRESULT NINE_WINAPI +NineDevice9_SetVertexDeclaration( struct NineDevice9 *This, + IDirect3DVertexDeclaration9 *pDecl ); + +HRESULT NINE_WINAPI +NineDevice9_GetVertexDeclaration( struct NineDevice9 *This, + IDirect3DVertexDeclaration9 **ppDecl ); + +HRESULT NINE_WINAPI +NineDevice9_SetFVF( struct NineDevice9 *This, + DWORD FVF ); + +HRESULT NINE_WINAPI +NineDevice9_GetFVF( struct NineDevice9 *This, + DWORD *pFVF ); + +HRESULT NINE_WINAPI +NineDevice9_CreateVertexShader( struct NineDevice9 *This, + const DWORD *pFunction, + IDirect3DVertexShader9 **ppShader ); + +HRESULT NINE_WINAPI +NineDevice9_SetVertexShader( struct NineDevice9 *This, + IDirect3DVertexShader9 *pShader ); + +HRESULT NINE_WINAPI +NineDevice9_GetVertexShader( struct NineDevice9 *This, + IDirect3DVertexShader9 **ppShader ); + +HRESULT NINE_WINAPI +NineDevice9_SetVertexShaderConstantF( struct NineDevice9 *This, + UINT StartRegister, + const float *pConstantData, + UINT Vector4fCount ); + +HRESULT NINE_WINAPI +NineDevice9_GetVertexShaderConstantF( struct NineDevice9 *This, + UINT StartRegister, + float *pConstantData, + UINT Vector4fCount ); + +HRESULT NINE_WINAPI +NineDevice9_SetVertexShaderConstantI( struct NineDevice9 *This, + UINT StartRegister, + const int *pConstantData, + UINT Vector4iCount ); + +HRESULT NINE_WINAPI +NineDevice9_GetVertexShaderConstantI( struct NineDevice9 *This, + UINT StartRegister, + int *pConstantData, + UINT Vector4iCount ); + +HRESULT NINE_WINAPI +NineDevice9_SetVertexShaderConstantB( struct NineDevice9 *This, + UINT StartRegister, + const BOOL *pConstantData, + UINT BoolCount ); + +HRESULT NINE_WINAPI +NineDevice9_GetVertexShaderConstantB( struct NineDevice9 *This, + UINT StartRegister, + BOOL *pConstantData, + UINT BoolCount ); + +HRESULT NINE_WINAPI +NineDevice9_SetStreamSource( struct NineDevice9 *This, + UINT StreamNumber, + IDirect3DVertexBuffer9 *pStreamData, + UINT OffsetInBytes, + UINT Stride ); + +HRESULT NINE_WINAPI +NineDevice9_GetStreamSource( struct NineDevice9 *This, + UINT StreamNumber, + IDirect3DVertexBuffer9 **ppStreamData, + UINT *pOffsetInBytes, + UINT *pStride ); + +HRESULT NINE_WINAPI +NineDevice9_SetStreamSourceFreq( struct NineDevice9 *This, + UINT StreamNumber, + UINT Setting ); + +HRESULT NINE_WINAPI +NineDevice9_GetStreamSourceFreq( struct NineDevice9 *This, + UINT StreamNumber, + UINT *pSetting ); + +HRESULT NINE_WINAPI +NineDevice9_SetIndices( struct NineDevice9 *This, + IDirect3DIndexBuffer9 *pIndexData ); + +HRESULT NINE_WINAPI +NineDevice9_GetIndices( struct NineDevice9 *This, + IDirect3DIndexBuffer9 **ppIndexData /*, + UINT *pBaseVertexIndex */ ); + +HRESULT NINE_WINAPI +NineDevice9_CreatePixelShader( struct NineDevice9 *This, + const DWORD *pFunction, + IDirect3DPixelShader9 **ppShader ); + +HRESULT NINE_WINAPI +NineDevice9_SetPixelShader( struct NineDevice9 *This, + IDirect3DPixelShader9 *pShader ); + +HRESULT NINE_WINAPI +NineDevice9_GetPixelShader( struct NineDevice9 *This, + IDirect3DPixelShader9 **ppShader ); + +HRESULT NINE_WINAPI +NineDevice9_SetPixelShaderConstantF( struct NineDevice9 *This, + UINT StartRegister, + const float *pConstantData, + UINT Vector4fCount ); + +HRESULT NINE_WINAPI +NineDevice9_GetPixelShaderConstantF( struct NineDevice9 *This, + UINT StartRegister, + float *pConstantData, + UINT Vector4fCount ); + +HRESULT NINE_WINAPI +NineDevice9_SetPixelShaderConstantI( struct NineDevice9 *This, + UINT StartRegister, + const int *pConstantData, + UINT Vector4iCount ); + +HRESULT NINE_WINAPI +NineDevice9_GetPixelShaderConstantI( struct NineDevice9 *This, + UINT StartRegister, + int *pConstantData, + UINT Vector4iCount ); + +HRESULT NINE_WINAPI +NineDevice9_SetPixelShaderConstantB( struct NineDevice9 *This, + UINT StartRegister, + const BOOL *pConstantData, + UINT BoolCount ); + +HRESULT NINE_WINAPI +NineDevice9_GetPixelShaderConstantB( struct NineDevice9 *This, + UINT StartRegister, + BOOL *pConstantData, + UINT BoolCount ); + +HRESULT NINE_WINAPI +NineDevice9_DrawRectPatch( struct NineDevice9 *This, + UINT Handle, + const float *pNumSegs, + const D3DRECTPATCH_INFO *pRectPatchInfo ); + +HRESULT NINE_WINAPI +NineDevice9_DrawTriPatch( struct NineDevice9 *This, + UINT Handle, + const float *pNumSegs, + const D3DTRIPATCH_INFO *pTriPatchInfo ); + +HRESULT NINE_WINAPI +NineDevice9_DeletePatch( struct NineDevice9 *This, + UINT Handle ); + +HRESULT NINE_WINAPI +NineDevice9_CreateQuery( struct NineDevice9 *This, + D3DQUERYTYPE Type, + IDirect3DQuery9 **ppQuery ); + +#endif /* _NINE_DEVICE9_H_ */ diff --git a/src/gallium/frontends/nine/device9ex.c b/src/gallium/frontends/nine/device9ex.c new file mode 100644 index 00000000000..3047657e95f --- /dev/null +++ b/src/gallium/frontends/nine/device9ex.c @@ -0,0 +1,458 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "device9.h" +#include "device9ex.h" +#include "nine_pipe.h" +#include "swapchain9ex.h" + +#include "nine_helpers.h" + +#define DBG_CHANNEL DBG_DEVICE + +static HRESULT +NineDevice9Ex_ctor( struct NineDevice9Ex *This, + struct NineUnknownParams *pParams, + struct pipe_screen *pScreen, + D3DDEVICE_CREATION_PARAMETERS *pCreationParameters, + D3DCAPS9 *pCaps, + D3DPRESENT_PARAMETERS *pPresentationParameters, + D3DDISPLAYMODEEX *pFullscreenDisplayMode, + IDirect3D9Ex *pD3D9Ex, + ID3DPresentGroup *pPresentationGroup, + struct d3dadapter9_context *pCTX, + int minorVersionNum ) +{ + DBG("This=%p pParams=%p pScreen=%p pCreationParameters=%p pCaps=%p " + "pPresentationParameters=%p pFullscreenDisplayMode=%p " + "pD3D9Ex=%p pPresentationGroup=%p pCTX=%p\n", + This, pParams, pScreen, pCreationParameters, pCaps, + pPresentationParameters, pFullscreenDisplayMode, + pD3D9Ex, pPresentationGroup, pCTX); + + return NineDevice9_ctor(&This->base, pParams, + pScreen, pCreationParameters, pCaps, + pPresentationParameters, + (IDirect3D9 *)pD3D9Ex, pPresentationGroup, pCTX, + TRUE, pFullscreenDisplayMode, minorVersionNum); +} + +static void +NineDevice9Ex_dtor( struct NineDevice9Ex *This ) +{ + NineDevice9_dtor(&This->base); +} + +HRESULT NINE_WINAPI +NineDevice9Ex_SetConvolutionMonoKernel( struct NineDevice9Ex *This, + UINT width, + UINT height, + float *rows, + float *columns ) +{ + STUB(D3DERR_INVALIDCALL); +} + +HRESULT NINE_WINAPI +NineDevice9Ex_ComposeRects( struct NineDevice9Ex *This, + IDirect3DSurface9 *pSrc, + IDirect3DSurface9 *pDst, + IDirect3DVertexBuffer9 *pSrcRectDescs, + UINT NumRects, + IDirect3DVertexBuffer9 *pDstRectDescs, + D3DCOMPOSERECTSOP Operation, + int Xoffset, + int Yoffset ) +{ + STUB(D3DERR_INVALIDCALL); +} + +HRESULT NINE_WINAPI +NineDevice9Ex_PresentEx( struct NineDevice9Ex *This, + const RECT *pSourceRect, + const RECT *pDestRect, + HWND hDestWindowOverride, + const RGNDATA *pDirtyRegion, + DWORD dwFlags ) +{ + unsigned i; + HRESULT hr; + + DBG("This=%p pSourceRect=%p pDestRect=%p hDestWindowOverride=%p " + "pDirtyRegion=%p dwFlags=%d\n", + This, pSourceRect, pDestRect, hDestWindowOverride, + pDirtyRegion, dwFlags); + + for (i = 0; i < This->base.nswapchains; i++) { + hr = NineSwapChain9_Present(This->base.swapchains[i], pSourceRect, pDestRect, + hDestWindowOverride, pDirtyRegion, dwFlags); + if (FAILED(hr)) { return hr; } + } + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9Ex_GetGPUThreadPriority( struct NineDevice9Ex *This, + INT *pPriority ) +{ + STUB(D3DERR_INVALIDCALL); +} + +HRESULT NINE_WINAPI +NineDevice9Ex_SetGPUThreadPriority( struct NineDevice9Ex *This, + INT Priority ) +{ + STUB(D3DERR_INVALIDCALL); +} + +HRESULT NINE_WINAPI +NineDevice9Ex_WaitForVBlank( struct NineDevice9Ex *This, + UINT iSwapChain ) +{ + STUB(D3DERR_INVALIDCALL); +} + +HRESULT NINE_WINAPI +NineDevice9Ex_CheckResourceResidency( struct NineDevice9Ex *This, + IDirect3DResource9 **pResourceArray, + UINT32 NumResources ) +{ + STUB(D3DERR_INVALIDCALL); +} + +HRESULT NINE_WINAPI +NineDevice9Ex_SetMaximumFrameLatency( struct NineDevice9Ex *This, + UINT MaxLatency ) +{ + STUB(D3DERR_INVALIDCALL); +} + +HRESULT NINE_WINAPI +NineDevice9Ex_GetMaximumFrameLatency( struct NineDevice9Ex *This, + UINT *pMaxLatency ) +{ + STUB(D3DERR_INVALIDCALL); +} + +HRESULT NINE_WINAPI +NineDevice9Ex_CheckDeviceState( struct NineDevice9Ex *This, + HWND hDestinationWindow ) +{ + DBG("This=%p hDestinationWindow=%p\n", + This, hDestinationWindow); + + user_assert(!This->base.swapchains[0]->params.Windowed, D3D_OK); + + if (This->base.params.hFocusWindow == hDestinationWindow) { + if (NineSwapChain9_GetOccluded(This->base.swapchains[0])) + return S_PRESENT_OCCLUDED; + } else if(!NineSwapChain9_GetOccluded(This->base.swapchains[0])) { + return S_PRESENT_OCCLUDED; + } + /* TODO: handle the other return values */ + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineDevice9Ex_CreateRenderTargetEx( struct NineDevice9Ex *This, + UINT Width, + UINT Height, + D3DFORMAT Format, + D3DMULTISAMPLE_TYPE MultiSample, + DWORD MultisampleQuality, + BOOL Lockable, + IDirect3DSurface9 **ppSurface, + HANDLE *pSharedHandle, + DWORD Usage ) +{ + STUB(D3DERR_INVALIDCALL); +} + +HRESULT NINE_WINAPI +NineDevice9Ex_CreateOffscreenPlainSurfaceEx( struct NineDevice9Ex *This, + UINT Width, + UINT Height, + D3DFORMAT Format, + D3DPOOL Pool, + IDirect3DSurface9 **ppSurface, + HANDLE *pSharedHandle, + DWORD Usage ) +{ + STUB(D3DERR_INVALIDCALL); +} + +HRESULT NINE_WINAPI +NineDevice9Ex_CreateDepthStencilSurfaceEx( struct NineDevice9Ex *This, + UINT Width, + UINT Height, + D3DFORMAT Format, + D3DMULTISAMPLE_TYPE MultiSample, + DWORD MultisampleQuality, + BOOL Discard, + IDirect3DSurface9 **ppSurface, + HANDLE *pSharedHandle, + DWORD Usage ) +{ + STUB(D3DERR_INVALIDCALL); +} + +HRESULT NINE_WINAPI +NineDevice9Ex_ResetEx( struct NineDevice9Ex *This, + D3DPRESENT_PARAMETERS *pPresentationParameters, + D3DDISPLAYMODEEX *pFullscreenDisplayMode ) +{ + HRESULT hr = D3D_OK; + unsigned i; + + DBG("This=%p pPresentationParameters=%p pFullscreenDisplayMode=%p\n", This, pPresentationParameters, pFullscreenDisplayMode); + + for (i = 0; i < This->base.nswapchains; ++i) { + D3DDISPLAYMODEEX *mode = NULL; + D3DPRESENT_PARAMETERS *params = &pPresentationParameters[i]; + if (pFullscreenDisplayMode) mode = &(pFullscreenDisplayMode[i]); + hr = NineSwapChain9_Resize(This->base.swapchains[i], params, mode); + if (FAILED(hr)) + break; + } + + NineDevice9_SetRenderTarget( + (struct NineDevice9 *)This, 0, (IDirect3DSurface9 *)This->base.swapchains[0]->buffers[0]); + + return hr; +} + +HRESULT NINE_WINAPI +NineDevice9Ex_Reset( struct NineDevice9Ex *This, + D3DPRESENT_PARAMETERS *pPresentationParameters ) +{ + HRESULT hr = D3D_OK; + unsigned i; + + DBG("This=%p pPresentationParameters=%p\n", This, pPresentationParameters); + + for (i = 0; i < This->base.nswapchains; ++i) { + D3DPRESENT_PARAMETERS *params = &pPresentationParameters[i]; + hr = NineSwapChain9_Resize(This->base.swapchains[i], params, NULL); + if (FAILED(hr)) + break; + } + + nine_csmt_process(&This->base); + nine_device_state_clear((struct NineDevice9 *)This); + nine_context_clear(&This->base); + + NineDevice9_SetDefaultState((struct NineDevice9 *)This, TRUE); + NineDevice9_SetRenderTarget( + (struct NineDevice9 *)This, 0, (IDirect3DSurface9 *)This->base.swapchains[0]->buffers[0]); + + return hr; +} + +HRESULT NINE_WINAPI +NineDevice9Ex_GetDisplayModeEx( struct NineDevice9Ex *This, + UINT iSwapChain, + D3DDISPLAYMODEEX *pMode, + D3DDISPLAYROTATION *pRotation ) +{ + struct NineSwapChain9Ex *swapchain; + + DBG("This=%p iSwapChain=%u pMode=%p pRotation=%p\n", + This, iSwapChain, pMode, pRotation); + + user_assert(iSwapChain < This->base.nswapchains, D3DERR_INVALIDCALL); + + swapchain = NineSwapChain9Ex(This->base.swapchains[iSwapChain]); + return NineSwapChain9Ex_GetDisplayModeEx(swapchain, pMode, pRotation); +} + +HRESULT NINE_WINAPI +NineDevice9Ex_TestCooperativeLevel( struct NineDevice9Ex *This ) +{ + return D3D_OK; +} + + +IDirect3DDevice9ExVtbl NineDevice9Ex_vtable = { + (void *)NineUnknown_QueryInterface, + (void *)NineUnknown_AddRef, + (void *)NineUnknown_Release, + (void *)NineDevice9Ex_TestCooperativeLevel, + (void *)NineDevice9_GetAvailableTextureMem, + (void *)NineDevice9_EvictManagedResources, + (void *)NineDevice9_GetDirect3D, + (void *)NineDevice9_GetDeviceCaps, + (void *)NineDevice9_GetDisplayMode, + (void *)NineDevice9_GetCreationParameters, + (void *)NineDevice9_SetCursorProperties, + (void *)NineDevice9_SetCursorPosition, + (void *)NineDevice9_ShowCursor, + (void *)NineDevice9_CreateAdditionalSwapChain, + (void *)NineDevice9_GetSwapChain, + (void *)NineDevice9_GetNumberOfSwapChains, + (void *)NineDevice9Ex_Reset, + (void *)NineDevice9_Present, + (void *)NineDevice9_GetBackBuffer, + (void *)NineDevice9_GetRasterStatus, + (void *)NineDevice9_SetDialogBoxMode, + (void *)NineDevice9_SetGammaRamp, + (void *)NineDevice9_GetGammaRamp, + (void *)NineDevice9_CreateTexture, + (void *)NineDevice9_CreateVolumeTexture, + (void *)NineDevice9_CreateCubeTexture, + (void *)NineDevice9_CreateVertexBuffer, + (void *)NineDevice9_CreateIndexBuffer, + (void *)NineDevice9_CreateRenderTarget, + (void *)NineDevice9_CreateDepthStencilSurface, + (void *)NineDevice9_UpdateSurface, + (void *)NineDevice9_UpdateTexture, + (void *)NineDevice9_GetRenderTargetData, + (void *)NineDevice9_GetFrontBufferData, + (void *)NineDevice9_StretchRect, + (void *)NineDevice9_ColorFill, + (void *)NineDevice9_CreateOffscreenPlainSurface, + (void *)NineDevice9_SetRenderTarget, + (void *)NineDevice9_GetRenderTarget, + (void *)NineDevice9_SetDepthStencilSurface, + (void *)NineDevice9_GetDepthStencilSurface, + (void *)NineDevice9_BeginScene, + (void *)NineDevice9_EndScene, + (void *)NineDevice9_Clear, + (void *)NineDevice9_SetTransform, + (void *)NineDevice9_GetTransform, + (void *)NineDevice9_MultiplyTransform, + (void *)NineDevice9_SetViewport, + (void *)NineDevice9_GetViewport, + (void *)NineDevice9_SetMaterial, + (void *)NineDevice9_GetMaterial, + (void *)NineDevice9_SetLight, + (void *)NineDevice9_GetLight, + (void *)NineDevice9_LightEnable, + (void *)NineDevice9_GetLightEnable, + (void *)NineDevice9_SetClipPlane, + (void *)NineDevice9_GetClipPlane, + (void *)NineDevice9_SetRenderState, + (void *)NineDevice9_GetRenderState, + (void *)NineDevice9_CreateStateBlock, + (void *)NineDevice9_BeginStateBlock, + (void *)NineDevice9_EndStateBlock, + (void *)NineDevice9_SetClipStatus, + (void *)NineDevice9_GetClipStatus, + (void *)NineDevice9_GetTexture, + (void *)NineDevice9_SetTexture, + (void *)NineDevice9_GetTextureStageState, + (void *)NineDevice9_SetTextureStageState, + (void *)NineDevice9_GetSamplerState, + (void *)NineDevice9_SetSamplerState, + (void *)NineDevice9_ValidateDevice, + (void *)NineDevice9_SetPaletteEntries, + (void *)NineDevice9_GetPaletteEntries, + (void *)NineDevice9_SetCurrentTexturePalette, + (void *)NineDevice9_GetCurrentTexturePalette, + (void *)NineDevice9_SetScissorRect, + (void *)NineDevice9_GetScissorRect, + (void *)NineDevice9_SetSoftwareVertexProcessing, + (void *)NineDevice9_GetSoftwareVertexProcessing, + (void *)NineDevice9_SetNPatchMode, + (void *)NineDevice9_GetNPatchMode, + (void *)NineDevice9_DrawPrimitive, + (void *)NineDevice9_DrawIndexedPrimitive, + (void *)NineDevice9_DrawPrimitiveUP, + (void *)NineDevice9_DrawIndexedPrimitiveUP, + (void *)NineDevice9_ProcessVertices, + (void *)NineDevice9_CreateVertexDeclaration, + (void *)NineDevice9_SetVertexDeclaration, + (void *)NineDevice9_GetVertexDeclaration, + (void *)NineDevice9_SetFVF, + (void *)NineDevice9_GetFVF, + (void *)NineDevice9_CreateVertexShader, + (void *)NineDevice9_SetVertexShader, + (void *)NineDevice9_GetVertexShader, + (void *)NineDevice9_SetVertexShaderConstantF, + (void *)NineDevice9_GetVertexShaderConstantF, + (void *)NineDevice9_SetVertexShaderConstantI, + (void *)NineDevice9_GetVertexShaderConstantI, + (void *)NineDevice9_SetVertexShaderConstantB, + (void *)NineDevice9_GetVertexShaderConstantB, + (void *)NineDevice9_SetStreamSource, + (void *)NineDevice9_GetStreamSource, + (void *)NineDevice9_SetStreamSourceFreq, + (void *)NineDevice9_GetStreamSourceFreq, + (void *)NineDevice9_SetIndices, + (void *)NineDevice9_GetIndices, + (void *)NineDevice9_CreatePixelShader, + (void *)NineDevice9_SetPixelShader, + (void *)NineDevice9_GetPixelShader, + (void *)NineDevice9_SetPixelShaderConstantF, + (void *)NineDevice9_GetPixelShaderConstantF, + (void *)NineDevice9_SetPixelShaderConstantI, + (void *)NineDevice9_GetPixelShaderConstantI, + (void *)NineDevice9_SetPixelShaderConstantB, + (void *)NineDevice9_GetPixelShaderConstantB, + (void *)NineDevice9_DrawRectPatch, + (void *)NineDevice9_DrawTriPatch, + (void *)NineDevice9_DeletePatch, + (void *)NineDevice9_CreateQuery, + (void *)NineDevice9Ex_SetConvolutionMonoKernel, + (void *)NineDevice9Ex_ComposeRects, + (void *)NineDevice9Ex_PresentEx, + (void *)NineDevice9Ex_GetGPUThreadPriority, + (void *)NineDevice9Ex_SetGPUThreadPriority, + (void *)NineDevice9Ex_WaitForVBlank, + (void *)NineDevice9Ex_CheckResourceResidency, + (void *)NineDevice9Ex_SetMaximumFrameLatency, + (void *)NineDevice9Ex_GetMaximumFrameLatency, + (void *)NineDevice9Ex_CheckDeviceState, + (void *)NineDevice9Ex_CreateRenderTargetEx, + (void *)NineDevice9Ex_CreateOffscreenPlainSurfaceEx, + (void *)NineDevice9Ex_CreateDepthStencilSurfaceEx, + (void *)NineDevice9Ex_ResetEx, + (void *)NineDevice9Ex_GetDisplayModeEx +}; + +static const GUID *NineDevice9Ex_IIDs[] = { + &IID_IDirect3DDevice9Ex, + &IID_IDirect3DDevice9, + &IID_IUnknown, + NULL +}; + +HRESULT +NineDevice9Ex_new( struct pipe_screen *pScreen, + D3DDEVICE_CREATION_PARAMETERS *pCreationParameters, + D3DCAPS9 *pCaps, + D3DPRESENT_PARAMETERS *pPresentationParameters, + D3DDISPLAYMODEEX *pFullscreenDisplayMode, + IDirect3D9Ex *pD3D9Ex, + ID3DPresentGroup *pPresentationGroup, + struct d3dadapter9_context *pCTX, + struct NineDevice9Ex **ppOut, + int minorVersionNum ) +{ + BOOL lock; + lock = !!(pCreationParameters->BehaviorFlags & D3DCREATE_MULTITHREADED); + + NINE_NEW(Device9Ex, ppOut, lock, + pScreen, pCreationParameters, pCaps, pPresentationParameters, + pFullscreenDisplayMode, pD3D9Ex, pPresentationGroup, pCTX, minorVersionNum ); +} + diff --git a/src/gallium/frontends/nine/device9ex.h b/src/gallium/frontends/nine/device9ex.h new file mode 100644 index 00000000000..3306f238b59 --- /dev/null +++ b/src/gallium/frontends/nine/device9ex.h @@ -0,0 +1,164 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _NINE_DEVICE9EX_H_ +#define _NINE_DEVICE9EX_H_ + +#include "device9.h" + +struct NineDevice9Ex +{ + struct NineDevice9 base; +}; +static inline struct NineDevice9Ex * +NineDevice9Ex( void *data ) +{ + return (struct NineDevice9Ex *)data; +} + +HRESULT +NineDevice9Ex_new( struct pipe_screen *pScreen, + D3DDEVICE_CREATION_PARAMETERS *pCreationParameters, + D3DCAPS9 *pCaps, + D3DPRESENT_PARAMETERS *pPresentationParameters, + D3DDISPLAYMODEEX *pFullscreenDisplayMode, + IDirect3D9Ex *pD3D9Ex, + ID3DPresentGroup *pPresentationGroup, + struct d3dadapter9_context *pCTX, + struct NineDevice9Ex **ppOut, + int minorVersionNum ); + +HRESULT NINE_WINAPI +NineDevice9Ex_SetConvolutionMonoKernel( struct NineDevice9Ex *This, + UINT width, + UINT height, + float *rows, + float *columns ); + +HRESULT NINE_WINAPI +NineDevice9Ex_ComposeRects( struct NineDevice9Ex *This, + IDirect3DSurface9 *pSrc, + IDirect3DSurface9 *pDst, + IDirect3DVertexBuffer9 *pSrcRectDescs, + UINT NumRects, + IDirect3DVertexBuffer9 *pDstRectDescs, + D3DCOMPOSERECTSOP Operation, + int Xoffset, + int Yoffset ); + +HRESULT NINE_WINAPI +NineDevice9Ex_PresentEx( struct NineDevice9Ex *This, + const RECT *pSourceRect, + const RECT *pDestRect, + HWND hDestWindowOverride, + const RGNDATA *pDirtyRegion, + DWORD dwFlags ); + +HRESULT NINE_WINAPI +NineDevice9Ex_Present( struct NineDevice9Ex *This, + const RECT *pSourceRect, + const RECT *pDestRect, + HWND hDestWindowOverride, + const RGNDATA *pDirtyRegion ); + +HRESULT NINE_WINAPI +NineDevice9Ex_GetGPUThreadPriority( struct NineDevice9Ex *This, + INT *pPriority ); + +HRESULT NINE_WINAPI +NineDevice9Ex_SetGPUThreadPriority( struct NineDevice9Ex *This, + INT Priority ); + +HRESULT NINE_WINAPI +NineDevice9Ex_WaitForVBlank( struct NineDevice9Ex *This, + UINT iSwapChain ); + +HRESULT NINE_WINAPI +NineDevice9Ex_CheckResourceResidency( struct NineDevice9Ex *This, + IDirect3DResource9 **pResourceArray, + UINT32 NumResources ); + +HRESULT NINE_WINAPI +NineDevice9Ex_SetMaximumFrameLatency( struct NineDevice9Ex *This, + UINT MaxLatency ); + +HRESULT NINE_WINAPI +NineDevice9Ex_GetMaximumFrameLatency( struct NineDevice9Ex *This, + UINT *pMaxLatency ); + +HRESULT NINE_WINAPI +NineDevice9Ex_CheckDeviceState( struct NineDevice9Ex *This, + HWND hDestinationWindow ); + +HRESULT NINE_WINAPI +NineDevice9Ex_CreateRenderTargetEx( struct NineDevice9Ex *This, + UINT Width, + UINT Height, + D3DFORMAT Format, + D3DMULTISAMPLE_TYPE MultiSample, + DWORD MultisampleQuality, + BOOL Lockable, + IDirect3DSurface9 **ppSurface, + HANDLE *pSharedHandle, + DWORD Usage ); + +HRESULT NINE_WINAPI +NineDevice9Ex_CreateOffscreenPlainSurfaceEx( struct NineDevice9Ex *This, + UINT Width, + UINT Height, + D3DFORMAT Format, + D3DPOOL Pool, + IDirect3DSurface9 **ppSurface, + HANDLE *pSharedHandle, + DWORD Usage ); + +HRESULT NINE_WINAPI +NineDevice9Ex_CreateDepthStencilSurfaceEx( struct NineDevice9Ex *This, + UINT Width, + UINT Height, + D3DFORMAT Format, + D3DMULTISAMPLE_TYPE MultiSample, + DWORD MultisampleQuality, + BOOL Discard, + IDirect3DSurface9 **ppSurface, + HANDLE *pSharedHandle, + DWORD Usage ); + +HRESULT NINE_WINAPI +NineDevice9Ex_ResetEx( struct NineDevice9Ex *This, + D3DPRESENT_PARAMETERS *pPresentationParameters, + D3DDISPLAYMODEEX *pFullscreenDisplayMode ); + +HRESULT NINE_WINAPI +NineDevice9Ex_Reset( struct NineDevice9Ex *This, + D3DPRESENT_PARAMETERS *pPresentationParameters ); + +HRESULT NINE_WINAPI +NineDevice9Ex_GetDisplayModeEx( struct NineDevice9Ex *This, + UINT iSwapChain, + D3DDISPLAYMODEEX *pMode, + D3DDISPLAYROTATION *pRotation ); + +HRESULT NINE_WINAPI +NineDevice9Ex_TestCooperativeLevel( struct NineDevice9Ex *This ); + +#endif /* _NINE_DEVICE9EX_H_ */ diff --git a/src/gallium/frontends/nine/device9video.c b/src/gallium/frontends/nine/device9video.c new file mode 100644 index 00000000000..2e8e94a26e7 --- /dev/null +++ b/src/gallium/frontends/nine/device9video.c @@ -0,0 +1,62 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "device9video.h" + +#define DBG_CHANNEL DBG_DEVICEVIDEO + +HRESULT NINE_WINAPI +NineDevice9Video_GetContentProtectionCaps( struct NineDevice9Video *This, + const GUID *pCryptoType, + const GUID *pDecodeProfile, + D3DCONTENTPROTECTIONCAPS *pCaps ) +{ + STUB(D3DERR_INVALIDCALL); +} + +HRESULT NINE_WINAPI +NineDevice9Video_CreateAuthenticatedChannel( struct NineDevice9Video *This, + D3DAUTHENTICATEDCHANNELTYPE ChannelType, + IDirect3DAuthenticatedChannel9 **ppAuthenticatedChannel, + HANDLE *pChannelHandle ) +{ + STUB(D3DERR_INVALIDCALL); +} + +HRESULT NINE_WINAPI +NineDevice9Video_CreateCryptoSession( struct NineDevice9Video *This, + const GUID *pCryptoType, + const GUID *pDecodeProfile, + IDirect3DCryptoSession9 **ppCryptoSession, + HANDLE *pCryptoHandle ) +{ + STUB(D3DERR_INVALIDCALL); +} + +IDirect3DDevice9VideoVtbl NineDevice9Video_vtable = { + (void *)NineUnknown_QueryInterface, + (void *)NineUnknown_AddRef, + (void *)NineUnknown_Release, + (void *)NineDevice9Video_GetContentProtectionCaps, + (void *)NineDevice9Video_CreateAuthenticatedChannel, + (void *)NineDevice9Video_CreateCryptoSession +}; diff --git a/src/gallium/frontends/nine/device9video.h b/src/gallium/frontends/nine/device9video.h new file mode 100644 index 00000000000..d77fd5ec57a --- /dev/null +++ b/src/gallium/frontends/nine/device9video.h @@ -0,0 +1,57 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _NINE_DEVICE9VIDEO_H_ +#define _NINE_DEVICE9VIDEO_H_ + +#include "iunknown.h" + +struct NineDevice9Video +{ + struct NineUnknown base; +}; +static inline struct NineDevice9Video * +NineDevice9Video( void *data ) +{ + return (struct NineDevice9Video *)data; +} + +HRESULT NINE_WINAPI +NineDevice9Video_GetContentProtectionCaps( struct NineDevice9Video *This, + const GUID *pCryptoType, + const GUID *pDecodeProfile, + D3DCONTENTPROTECTIONCAPS *pCaps ); + +HRESULT NINE_WINAPI +NineDevice9Video_CreateAuthenticatedChannel( struct NineDevice9Video *This, + D3DAUTHENTICATEDCHANNELTYPE ChannelType, + IDirect3DAuthenticatedChannel9 **ppAuthenticatedChannel, + HANDLE *pChannelHandle ); + +HRESULT NINE_WINAPI +NineDevice9Video_CreateCryptoSession( struct NineDevice9Video *This, + const GUID *pCryptoType, + const GUID *pDecodeProfile, + IDirect3DCryptoSession9 **ppCryptoSession, + HANDLE *pCryptoHandle ); + +#endif /* _NINE_DEVICE9VIDEO_H_ */ diff --git a/src/gallium/frontends/nine/guid.c b/src/gallium/frontends/nine/guid.c new file mode 100644 index 00000000000..5e63d2f6629 --- /dev/null +++ b/src/gallium/frontends/nine/guid.c @@ -0,0 +1,84 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include +#include "guid.h" + +const GUID IID_IUnknown = { 0x00000000, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } }; +const GUID IID_ID3D9Adapter = { 0xBF6C7B9A, 0xF0BE, 0x11DF, { 0x81, 0xE3, 0x7F, 0x57, 0xDF, 0xD7, 0x20, 0x85 } }; +const GUID IID_IDirect3D9ExOverlayExtension = { 0x187AEB13, 0xAAF5, 0x4C59, { 0x87, 0x6D, 0xE0, 0x59, 0x08, 0x8C, 0x0D, 0xF8 } }; +const GUID IID_IDirect3DAuthenticatedChannel9 = { 0xFF24BEEE, 0xDA21, 0x4BEB, { 0x98, 0xB5, 0xD2, 0xF8, 0x99, 0xF9, 0x8A, 0xF9 } }; +const GUID IID_IDirect3DBaseTexture9 = { 0x580CA87E, 0x1D3C, 0x4D54, { 0x99, 0x1D, 0xB7, 0xD3, 0xE3, 0xC2, 0x98, 0xCE } }; +const GUID IID_IDirect3DCryptoSession9 = { 0xFA0AB799, 0x7A9C, 0x48CA, { 0x8C, 0x5B, 0x23, 0x7E, 0x71, 0xA5, 0x44, 0x34 } }; +const GUID IID_IDirect3DCubeTexture9 = { 0xFFF32F81, 0xD953, 0x473A, { 0x92, 0x23, 0x93, 0xD6, 0x52, 0xAB, 0xA9, 0x3F } }; +const GUID IID_IDirect3DDevice9 = { 0xD0223B96, 0xBF7A, 0x43FD, { 0x92, 0xBD, 0xA4, 0x3B, 0x0D, 0x82, 0xB9, 0xEB } }; +const GUID IID_IDirect3DDevice9Ex = { 0xB18B10CE, 0x2649, 0x405A, { 0x87, 0x0F, 0x95, 0xF7, 0x77, 0xD4, 0x31, 0x3A } }; +const GUID IID_IDirect3DDevice9Video = { 0x26DC4561, 0xA1EE, 0x4AE7, { 0x96, 0xDA, 0x11, 0x8A, 0x36, 0xC0, 0xEC, 0x95 } }; +const GUID IID_IDirect3DIndexBuffer9 = { 0x7C9DD65E, 0xD3F7, 0x4529, { 0xAC, 0xEE, 0x78, 0x58, 0x30, 0xAC, 0xDE, 0x35 } }; +const GUID IID_IDirect3DPixelShader9 = { 0x6D3BDBDC, 0x5B02, 0x4415, { 0xB8, 0x52, 0xCE, 0x5E, 0x8B, 0xCC, 0xB2, 0x89 } }; +const GUID IID_IDirect3DQuery9 = { 0xD9771460, 0xA695, 0x4F26, { 0xBB, 0xD3, 0x27, 0xB8, 0x40, 0xB5, 0x41, 0xCC } }; +const GUID IID_IDirect3DResource9 = { 0x05EEC05D, 0x8F7D, 0x4362, { 0xB9, 0x99, 0xD1, 0xBA, 0xF3, 0x57, 0xC7, 0x4 } }; +const GUID IID_IDirect3DStateBlock9 = { 0xB07C4FE5, 0x310D, 0x4BA8, { 0xA2, 0x3C, 0x4F, 0x0F, 0x20, 0x6F, 0x21, 0x8B } }; +const GUID IID_IDirect3DSurface9 = { 0x0CFBAF3A, 0x9FF6, 0x429A, { 0x99, 0xB3, 0xA2, 0x79, 0x6A, 0xF8, 0xB8, 0x9B } }; +const GUID IID_IDirect3DSwapChain9 = { 0x794950F2, 0xADFC, 0x458A, { 0x90, 0x5E, 0x10, 0xA1, 0x0B, 0x0B, 0x50, 0x3B } }; +const GUID IID_IDirect3DSwapChain9Ex = { 0x91886CAF, 0x1C3D, 0x4D2E, { 0xA0, 0xAB, 0x3E, 0x4C, 0x7D, 0x8D, 0x33, 0x3 } }; +const GUID IID_IDirect3DTexture9 = { 0x85C31227, 0x3DE5, 0x4F00, { 0x9B, 0x3A, 0xF1, 0x1A, 0xC3, 0x8C, 0x18, 0xB5 } }; +const GUID IID_IDirect3DVertexBuffer9 = { 0xB64BB1B5, 0xFD70, 0x4DF6, { 0xBF, 0x91, 0x19, 0xD0, 0xA1, 0x24, 0x55, 0xE3 } }; +const GUID IID_IDirect3DVertexDeclaration9 = { 0xDD13C59C, 0x36FA, 0x4098, { 0xA8, 0xFB, 0xC7, 0xED, 0x39, 0xDC, 0x85, 0x46 } }; +const GUID IID_IDirect3DVertexShader9 = { 0xEFC5557E, 0x6265, 0x4613, { 0x8A, 0x94, 0x43, 0x85, 0x78, 0x89, 0xEB, 0x36 } }; +const GUID IID_IDirect3DVolume9 = { 0x24F416E6, 0x1F67, 0x4AA7, { 0xB8, 0x8E, 0xD3, 0x3F, 0x6F, 0x31, 0x28, 0xA1 } }; +const GUID IID_IDirect3DVolumeTexture9 = { 0x2518526C, 0xE789, 0x4111, { 0xA7, 0xB9, 0x47, 0xEF, 0x32, 0x8D, 0x13, 0xE6 } }; + +boolean +GUID_equal( const GUID *a, + const GUID *b ) +{ + unsigned i; + + if (!a || !b) + return FALSE; + + if (a->Data1 != b->Data1 || + a->Data2 != b->Data2 || + a->Data3 != b->Data3) { return FALSE; } + for (i = 0; i < 8; i++) { + if (a->Data4[i] != b->Data4[i]) { return FALSE; } + } + return TRUE; +} + +char* GUID_sprintf(char *guid_str, REFGUID id) { + sprintf( guid_str, + "{%08X,%04X,%04X,%02X%02X%02X%02X%02X%02X%02X%02X}", + id->Data1, + id->Data2, + id->Data3, + id->Data4[0], + id->Data4[1], + id->Data4[2], + id->Data4[3], + id->Data4[4], + id->Data4[5], + id->Data4[6], + id->Data4[7]); + return guid_str; +} diff --git a/src/gallium/frontends/nine/guid.h b/src/gallium/frontends/nine/guid.h new file mode 100644 index 00000000000..af8f081bfb5 --- /dev/null +++ b/src/gallium/frontends/nine/guid.h @@ -0,0 +1,40 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _NINE_GUID_H_ +#define _NINE_GUID_H_ + +#include "pipe/p_compiler.h" + +#include "d3d9types.h" + +extern const GUID IID_ID3D9Adapter; + +boolean +GUID_equal( const GUID *a, + const GUID *b ); + +char* +GUID_sprintf( char *guid_str, + REFGUID id ); + +#endif /* _NINE_GUID_H_ */ diff --git a/src/gallium/frontends/nine/indexbuffer9.c b/src/gallium/frontends/nine/indexbuffer9.c new file mode 100644 index 00000000000..e73d29b5bd3 --- /dev/null +++ b/src/gallium/frontends/nine/indexbuffer9.c @@ -0,0 +1,134 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "indexbuffer9.h" +#include "device9.h" +#include "nine_helpers.h" +#include "nine_pipe.h" +#include "nine_dump.h" + +#include "pipe/p_screen.h" +#include "pipe/p_context.h" +#include "pipe/p_state.h" +#include "pipe/p_defines.h" +#include "pipe/p_format.h" +#include "util/u_box.h" + +#define DBG_CHANNEL DBG_INDEXBUFFER + +HRESULT +NineIndexBuffer9_ctor( struct NineIndexBuffer9 *This, + struct NineUnknownParams *pParams, + D3DINDEXBUFFER_DESC *pDesc ) +{ + HRESULT hr; + DBG("This=%p pParams=%p pDesc=%p Usage=%s\n", + This, pParams, pDesc, nine_D3DUSAGE_to_str(pDesc->Usage)); + + hr = NineBuffer9_ctor(&This->base, pParams, D3DRTYPE_INDEXBUFFER, + pDesc->Usage, pDesc->Size, pDesc->Pool); + if (FAILED(hr)) + return hr; + + switch (pDesc->Format) { + case D3DFMT_INDEX16: This->index_size = 2; break; + case D3DFMT_INDEX32: This->index_size = 4; break; + default: + user_assert(!"Invalid index format.", D3DERR_INVALIDCALL); + break; + } + + pDesc->Type = D3DRTYPE_INDEXBUFFER; + This->desc = *pDesc; + + return D3D_OK; +} + +void +NineIndexBuffer9_dtor( struct NineIndexBuffer9 *This ) +{ + NineBuffer9_dtor(&This->base); +} + +struct pipe_resource * +NineIndexBuffer9_GetBuffer( struct NineIndexBuffer9 *This, unsigned *offset ) +{ + /* The resource may change */ + return NineBuffer9_GetResource(&This->base, offset); +} + +HRESULT NINE_WINAPI +NineIndexBuffer9_Lock( struct NineIndexBuffer9 *This, + UINT OffsetToLock, + UINT SizeToLock, + void **ppbData, + DWORD Flags ) +{ + return NineBuffer9_Lock(&This->base, OffsetToLock, SizeToLock, ppbData, Flags); +} + +HRESULT NINE_WINAPI +NineIndexBuffer9_Unlock( struct NineIndexBuffer9 *This ) +{ + return NineBuffer9_Unlock(&This->base); +} + +HRESULT NINE_WINAPI +NineIndexBuffer9_GetDesc( struct NineIndexBuffer9 *This, + D3DINDEXBUFFER_DESC *pDesc ) +{ + user_assert(pDesc, E_POINTER); + *pDesc = This->desc; + return D3D_OK; +} + +IDirect3DIndexBuffer9Vtbl NineIndexBuffer9_vtable = { + (void *)NineUnknown_QueryInterface, + (void *)NineUnknown_AddRef, + (void *)NineUnknown_Release, + (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */ + (void *)NineUnknown_SetPrivateData, + (void *)NineUnknown_GetPrivateData, + (void *)NineUnknown_FreePrivateData, + (void *)NineResource9_SetPriority, + (void *)NineResource9_GetPriority, + (void *)NineResource9_PreLoad, + (void *)NineResource9_GetType, + (void *)NineIndexBuffer9_Lock, + (void *)NineIndexBuffer9_Unlock, + (void *)NineIndexBuffer9_GetDesc +}; + +static const GUID *NineIndexBuffer9_IIDs[] = { + &IID_IDirect3DIndexBuffer9, + &IID_IDirect3DResource9, + &IID_IUnknown, + NULL +}; + +HRESULT +NineIndexBuffer9_new( struct NineDevice9 *pDevice, + D3DINDEXBUFFER_DESC *pDesc, + struct NineIndexBuffer9 **ppOut ) +{ + NINE_DEVICE_CHILD_NEW(IndexBuffer9, ppOut, /* args */ pDevice, pDesc); +} diff --git a/src/gallium/frontends/nine/indexbuffer9.h b/src/gallium/frontends/nine/indexbuffer9.h new file mode 100644 index 00000000000..e688488da84 --- /dev/null +++ b/src/gallium/frontends/nine/indexbuffer9.h @@ -0,0 +1,85 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _NINE_INDEXBUFFER9_H_ +#define _NINE_INDEXBUFFER9_H_ + +#include "resource9.h" +#include "buffer9.h" +#include "pipe/p_state.h" + +struct pipe_screen; +struct pipe_context; +struct pipe_transfer; +struct NineDevice9; + +struct NineIndexBuffer9 +{ + struct NineBuffer9 base; + + /* g3d stuff */ + unsigned index_size; + + D3DINDEXBUFFER_DESC desc; +}; +static inline struct NineIndexBuffer9 * +NineIndexBuffer9( void *data ) +{ + return (struct NineIndexBuffer9 *)data; +} + +HRESULT +NineIndexBuffer9_new( struct NineDevice9 *pDevice, + D3DINDEXBUFFER_DESC *pDesc, + struct NineIndexBuffer9 **ppOut ); + +HRESULT +NineIndexBuffer9_ctor( struct NineIndexBuffer9 *This, + struct NineUnknownParams *pParams, + D3DINDEXBUFFER_DESC *pDesc ); + +void +NineIndexBuffer9_dtor( struct NineIndexBuffer9 *This ); + +/*** Nine private ***/ + +struct pipe_resource * +NineIndexBuffer9_GetBuffer( struct NineIndexBuffer9 *This, + unsigned *offset ); + +/*** Direct3D public ***/ + +HRESULT NINE_WINAPI +NineIndexBuffer9_Lock( struct NineIndexBuffer9 *This, + UINT OffsetToLock, + UINT SizeToLock, + void **ppbData, + DWORD Flags ); + +HRESULT NINE_WINAPI +NineIndexBuffer9_Unlock( struct NineIndexBuffer9 *This ); + +HRESULT NINE_WINAPI +NineIndexBuffer9_GetDesc( struct NineIndexBuffer9 *This, + D3DINDEXBUFFER_DESC *pDesc ); + +#endif /* _NINE_INDEXBUFFER9_H_ */ diff --git a/src/gallium/frontends/nine/iunknown.c b/src/gallium/frontends/nine/iunknown.c new file mode 100644 index 00000000000..2d69afd5496 --- /dev/null +++ b/src/gallium/frontends/nine/iunknown.c @@ -0,0 +1,288 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "iunknown.h" +#include "util/u_atomic.h" +#include "util/u_hash_table.h" + +#include "nine_helpers.h" +#include "nine_pdata.h" +#include "nine_lock.h" + +#define DBG_CHANNEL DBG_UNKNOWN + +HRESULT +NineUnknown_ctor( struct NineUnknown *This, + struct NineUnknownParams *pParams ) +{ + if (pParams->container) { + This->refs = 0; + This->forward = true; + This->bind = 0; + assert(!pParams->start_with_bind_not_ref); + } else if (pParams->start_with_bind_not_ref) { + This->refs = 0; + This->forward = false; + This->bind = 1; + } else { + This->refs = 1; + This->forward = false; + This->bind = 0; + } + + This->container = pParams->container; + This->device = pParams->device; + if (This->refs && This->device) + NineUnknown_AddRef(NineUnknown(This->device)); + + This->vtable = pParams->vtable; + This->vtable_internal = pParams->vtable; + This->guids = pParams->guids; + This->dtor = pParams->dtor; + + This->pdata = _mesa_hash_table_create(NULL, ht_guid_hash, ht_guid_compare); + if (!This->pdata) + return E_OUTOFMEMORY; + + return D3D_OK; +} + +void +NineUnknown_dtor( struct NineUnknown *This ) +{ + if (This->refs && This->device) /* Possible only if early exit after a ctor failed */ + (void) NineUnknown_Release(NineUnknown(This->device)); + + if (This->pdata) { + util_hash_table_foreach(This->pdata, ht_guid_delete, NULL); + _mesa_hash_table_destroy(This->pdata, NULL); + } + + FREE(This); +} + +HRESULT NINE_WINAPI +NineUnknown_QueryInterface( struct NineUnknown *This, + REFIID riid, + void **ppvObject ) +{ + unsigned i = 0; + char guid_str[64]; + + DBG("This=%p riid=%p id=%s ppvObject=%p\n", + This, riid, riid ? GUID_sprintf(guid_str, riid) : "", ppvObject); + + (void)guid_str; + + if (!ppvObject) return E_POINTER; + + do { + if (GUID_equal(This->guids[i], riid)) { + *ppvObject = This; + /* Tests showed that this call succeeds even on objects with + * zero refcount. This can happen if the app released all references + * but the resource is still bound. + */ + NineUnknown_AddRef(This); + return S_OK; + } + } while (This->guids[++i]); + + *ppvObject = NULL; + return E_NOINTERFACE; +} + +ULONG NINE_WINAPI +NineUnknown_AddRef( struct NineUnknown *This ) +{ + ULONG r; + if (This->forward) + return NineUnknown_AddRef(This->container); + else + r = p_atomic_inc_return(&This->refs); + + if (r == 1) { + if (This->device) + NineUnknown_AddRef(NineUnknown(This->device)); + } + return r; +} + +ULONG NINE_WINAPI +NineUnknown_Release( struct NineUnknown *This ) +{ + if (This->forward) + return NineUnknown_Release(This->container); + + ULONG r = p_atomic_dec_return(&This->refs); + + if (r == 0) { + if (This->device) { + if (NineUnknown_Release(NineUnknown(This->device)) == 0) + return r; /* everything's gone */ + } + /* Containers (here with !forward) take care of item destruction */ + if (!This->container && This->bind == 0) { + This->dtor(This); + } + } + return r; +} + +/* No need to lock the mutex protecting nine (when D3DCREATE_MULTITHREADED) + * for AddRef and Release, except for dtor as some of the dtors require it. */ +ULONG NINE_WINAPI +NineUnknown_ReleaseWithDtorLock( struct NineUnknown *This ) +{ + if (This->forward) + return NineUnknown_ReleaseWithDtorLock(This->container); + + ULONG r = p_atomic_dec_return(&This->refs); + + if (r == 0) { + if (This->device) { + if (NineUnknown_ReleaseWithDtorLock(NineUnknown(This->device)) == 0) + return r; /* everything's gone */ + } + /* Containers (here with !forward) take care of item destruction */ + if (!This->container && This->bind == 0) { + NineLockGlobalMutex(); + This->dtor(This); + NineUnlockGlobalMutex(); + } + } + return r; +} + +HRESULT NINE_WINAPI +NineUnknown_GetDevice( struct NineUnknown *This, + IDirect3DDevice9 **ppDevice ) +{ + user_assert(ppDevice, E_POINTER); + NineUnknown_AddRef(NineUnknown(This->device)); + *ppDevice = (IDirect3DDevice9 *)This->device; + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineUnknown_SetPrivateData( struct NineUnknown *This, + REFGUID refguid, + const void *pData, + DWORD SizeOfData, + DWORD Flags ) +{ + enum pipe_error err; + struct pheader *header; + const void *user_data = pData; + char guid_str[64]; + void *header_data; + + DBG("This=%p GUID=%s pData=%p SizeOfData=%u Flags=%x\n", + This, GUID_sprintf(guid_str, refguid), pData, SizeOfData, Flags); + + (void)guid_str; + + if (Flags & D3DSPD_IUNKNOWN) + user_assert(SizeOfData == sizeof(IUnknown *), D3DERR_INVALIDCALL); + + /* data consists of a header and the actual data. avoiding 2 mallocs */ + header = CALLOC_VARIANT_LENGTH_STRUCT(pheader, SizeOfData); + if (!header) { return E_OUTOFMEMORY; } + header->unknown = (Flags & D3DSPD_IUNKNOWN) ? TRUE : FALSE; + + /* if the refguid already exists, delete it */ + NineUnknown_FreePrivateData(This, refguid); + + /* IUnknown special case */ + if (header->unknown) { + /* here the pointer doesn't point to the data we want, so point at the + * pointer making what we eventually copy is the pointer itself */ + user_data = &pData; + } + + header->size = SizeOfData; + header_data = (void *)header + sizeof(*header); + memcpy(header_data, user_data, header->size); + memcpy(&header->guid, refguid, sizeof(header->guid)); + + _mesa_hash_table_insert(This->pdata, &header->guid, header); + if (header->unknown) { IUnknown_AddRef(*(IUnknown **)header_data); } + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineUnknown_GetPrivateData( struct NineUnknown *This, + REFGUID refguid, + void *pData, + DWORD *pSizeOfData ) +{ + struct pheader *header; + DWORD sizeofdata; + char guid_str[64]; + void *header_data; + + DBG("This=%p GUID=%s pData=%p pSizeOfData=%p\n", + This, GUID_sprintf(guid_str, refguid), pData, pSizeOfData); + + (void)guid_str; + + header = util_hash_table_get(This->pdata, refguid); + if (!header) { return D3DERR_NOTFOUND; } + + user_assert(pSizeOfData, E_POINTER); + sizeofdata = *pSizeOfData; + *pSizeOfData = header->size; + + if (!pData) { + return D3D_OK; + } + if (sizeofdata < header->size) { + return D3DERR_MOREDATA; + } + + header_data = (void *)header + sizeof(*header); + if (header->unknown) { IUnknown_AddRef(*(IUnknown **)header_data); } + memcpy(pData, header_data, header->size); + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineUnknown_FreePrivateData( struct NineUnknown *This, + REFGUID refguid ) +{ + struct pheader *header; + char guid_str[64]; + + DBG("This=%p GUID=%s\n", This, GUID_sprintf(guid_str, refguid)); + + (void)guid_str; + + header = util_hash_table_get(This->pdata, refguid); + if (!header) + return D3DERR_NOTFOUND; + + ht_guid_delete(NULL, header, NULL); + _mesa_hash_table_remove_key(This->pdata, refguid); + + return D3D_OK; +} diff --git a/src/gallium/frontends/nine/iunknown.h b/src/gallium/frontends/nine/iunknown.h new file mode 100644 index 00000000000..20ad191cf44 --- /dev/null +++ b/src/gallium/frontends/nine/iunknown.h @@ -0,0 +1,180 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _NINE_IUNKNOWN_H_ +#define _NINE_IUNKNOWN_H_ + +#include "pipe/p_compiler.h" + +#include "util/u_atomic.h" +#include "util/u_memory.h" + +#include "guid.h" +#include "nine_flags.h" +#include "nine_debug.h" +#include "nine_quirk.h" + +#include "d3d9.h" + +struct Nine9; +struct NineDevice9; + +struct NineUnknown +{ + /* pointer to vtable (can be overriden outside gallium nine) */ + void *vtable; + /* pointer to internal vtable */ + void *vtable_internal; + + int32_t refs; /* external reference count */ + int32_t bind; /* internal bind count */ + boolean forward; /* whether to forward references to the container */ + + /* container: for surfaces and volumes only. + * Can be a texture, a volume texture or a swapchain. + * forward is set to false for the swapchain case. + * If forward is set, refs are passed to the container if forward is set + * and the container has bind increased if the object has non null bind. */ + struct NineUnknown *container; + struct NineDevice9 *device; /* referenced if (refs) */ + + const GUID **guids; /* for QueryInterface */ + + /* for [GS]etPrivateData/FreePrivateData */ + struct hash_table *pdata; + + void (*dtor)(void *data); /* top-level dtor */ +}; +static inline struct NineUnknown * +NineUnknown( void *data ) +{ + return (struct NineUnknown *)data; +} + +/* Use this instead of a shitload of arguments: */ +struct NineUnknownParams +{ + void *vtable; + const GUID **guids; + void (*dtor)(void *data); + struct NineUnknown *container; + struct NineDevice9 *device; + bool start_with_bind_not_ref; +}; + +HRESULT +NineUnknown_ctor( struct NineUnknown *This, + struct NineUnknownParams *pParams ); + +void +NineUnknown_dtor( struct NineUnknown *This ); + +/*** Direct3D public methods ***/ + +HRESULT NINE_WINAPI +NineUnknown_QueryInterface( struct NineUnknown *This, + REFIID riid, + void **ppvObject ); + +ULONG NINE_WINAPI +NineUnknown_AddRef( struct NineUnknown *This ); + +ULONG NINE_WINAPI +NineUnknown_Release( struct NineUnknown *This ); + +ULONG NINE_WINAPI +NineUnknown_ReleaseWithDtorLock( struct NineUnknown *This ); + +HRESULT NINE_WINAPI +NineUnknown_GetDevice( struct NineUnknown *This, + IDirect3DDevice9 **ppDevice ); + +HRESULT NINE_WINAPI +NineUnknown_SetPrivateData( struct NineUnknown *This, + REFGUID refguid, + const void *pData, + DWORD SizeOfData, + DWORD Flags ); + +HRESULT NINE_WINAPI +NineUnknown_GetPrivateData( struct NineUnknown *This, + REFGUID refguid, + void *pData, + DWORD *pSizeOfData ); + +HRESULT NINE_WINAPI +NineUnknown_FreePrivateData( struct NineUnknown *This, + REFGUID refguid ); + +/*** Nine private methods ***/ + +static inline void +NineUnknown_Destroy( struct NineUnknown *This ) +{ + assert(!(This->refs | This->bind)); + This->dtor(This); +} + +static inline UINT +NineUnknown_Bind( struct NineUnknown *This ) +{ + UINT b = p_atomic_inc_return(&This->bind); + assert(b); + + if (b == 1 && This->forward) + NineUnknown_Bind(This->container); + + return b; +} + +static inline UINT +NineUnknown_Unbind( struct NineUnknown *This ) +{ + UINT b = p_atomic_dec_return(&This->bind); + + if (b == 0 && This->forward) + NineUnknown_Unbind(This->container); + else if (b == 0 && This->refs == 0 && !This->container) + This->dtor(This); + + return b; +} + +static inline void +NineUnknown_ConvertRefToBind( struct NineUnknown *This ) +{ + NineUnknown_Bind(This); + NineUnknown_Release(This); +} + +/* Detach from container. */ +static inline void +NineUnknown_Detach( struct NineUnknown *This ) +{ + assert(This->container && !This->forward); + + This->container = NULL; + if (!(This->refs | This->bind)) + This->dtor(This); +} + +#endif /* _NINE_IUNKNOWN_H_ */ diff --git a/src/gallium/frontends/nine/meson.build b/src/gallium/frontends/nine/meson.build new file mode 100644 index 00000000000..7c9e035cafc --- /dev/null +++ b/src/gallium/frontends/nine/meson.build @@ -0,0 +1,75 @@ +# Copyright © 2017 Intel Corporation + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +nine_st_files = files( + 'adapter9.c', + 'authenticatedchannel9.c', + 'basetexture9.c', + 'buffer9.c', + 'cryptosession9.c', + 'cubetexture9.c', + 'device9.c', + 'device9ex.c', + 'device9video.c', + 'guid.c', + 'indexbuffer9.c', + 'iunknown.c', + 'nine_buffer_upload.c', + 'nine_debug.c', + 'nine_dump.c', + 'nineexoverlayextension.c', + 'nine_ff.c', + 'nine_helpers.c', + 'nine_lock.c', + 'nine_pipe.c', + 'nine_quirk.c', + 'nine_queue.c', + 'nine_shader.c', + 'nine_state.c', + 'pixelshader9.c', + 'query9.c', + 'resource9.c', + 'stateblock9.c', + 'surface9.c', + 'swapchain9.c', + 'swapchain9ex.c', + 'texture9.c', + 'threadpool.c', + 'vertexbuffer9.c', + 'vertexdeclaration9.c', + 'vertexshader9.c', + 'volume9.c', + 'volumetexture9.c', +) + +libnine_st = static_library( + 'nine_st', + nine_st_files, + c_args : c_vis_args, + include_directories : [ + inc_d3d9, inc_gallium, inc_include, inc_src, inc_gallium_aux, + ], + dependencies : [ + dep_thread, idep_nir, idep_nir_headers + ], + link_with : [ + libmesa_gallium + ] +) diff --git a/src/gallium/frontends/nine/nine_buffer_upload.c b/src/gallium/frontends/nine/nine_buffer_upload.c new file mode 100644 index 00000000000..a71f0195a2a --- /dev/null +++ b/src/gallium/frontends/nine/nine_buffer_upload.c @@ -0,0 +1,294 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * Copyright 2016 Axel Davy + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ +/* Adapted from u_upload_mgr. + * Makes suballocations from bigger allocations, + * while enabling fast mapping. */ + +#include "pipe/p_defines.h" +#include "util/u_inlines.h" +#include "pipe/p_context.h" +#include "util/u_memory.h" +#include "util/u_math.h" +#include "util/slab.h" + +#include "nine_buffer_upload.h" + +#include "nine_debug.h" + +#define DBG_CHANNEL (DBG_INDEXBUFFER|DBG_VERTEXBUFFER) + +struct nine_buffer_group { + unsigned refcount; /* How many sub-buffers live inside the buffer */ + struct pipe_resource *resource; + struct pipe_transfer *transfer; + uint8_t *map; + unsigned free_offset; /* Aligned offset to the upload buffer, pointing + * at the first unused byte. */ +}; + +struct nine_subbuffer { + struct nine_buffer_group *parent; /* Can be NULL */ + struct pipe_resource *resource; /* The parent resource if apply */ + unsigned offset; /* Offset inside the resource */ + /* If there is no parent, the resource map. Else NULL. */ + struct pipe_transfer *transfer; + uint8_t *map; +}; + +struct nine_buffer_upload { + struct pipe_context *pipe; + struct slab_mempool buffer_pool; + + unsigned buffers_size; /* Size of the big allocated buffers */ + unsigned num_buffers; + struct nine_buffer_group *buffers; +}; + +static void +nine_upload_create_buffer_group(struct nine_buffer_upload *upload, + struct nine_buffer_group *group) +{ + struct pipe_resource resource; + struct pipe_screen *screen = upload->pipe->screen; + DBG("%p %p\n", upload, group); + + memset(&resource, 0, sizeof(resource)); + resource.target = PIPE_BUFFER; + resource.format = PIPE_FORMAT_R8_UNORM; + resource.bind = PIPE_BIND_VERTEX_BUFFER; + resource.usage = PIPE_USAGE_STREAM; + resource.width0 = upload->buffers_size; + resource.height0 = 1; + resource.depth0 = 1; + resource.array_size = 1; + resource.flags = PIPE_RESOURCE_FLAG_MAP_PERSISTENT | + PIPE_RESOURCE_FLAG_MAP_COHERENT; + + group->refcount = 0; + group->resource = screen->resource_create(screen, &resource); + if (group->resource == NULL) + return; + + group->map = pipe_buffer_map_range(upload->pipe, group->resource, + 0, upload->buffers_size, + PIPE_TRANSFER_WRITE | + PIPE_TRANSFER_PERSISTENT | + PIPE_TRANSFER_COHERENT, + &group->transfer); + if (group->map == NULL) { + group->transfer = NULL; + pipe_resource_reference(&group->resource, NULL); + return; + } + + group->free_offset = 0; +} + +static void +nine_upload_destroy_buffer_group(struct nine_buffer_upload *upload, + struct nine_buffer_group *group) +{ + DBG("%p %p\n", upload, group); + assert(group->refcount == 0); + + if (group->transfer) + pipe_transfer_unmap(upload->pipe, group->transfer); + if (group->resource) + pipe_resource_reference(&group->resource, NULL); + group->transfer = NULL; + group->map = NULL; +} + +struct nine_buffer_upload * +nine_upload_create(struct pipe_context *pipe, unsigned buffers_size, + unsigned num_buffers) +{ + struct nine_buffer_upload *upload; + int i; + + DBG("\n"); + + if (!pipe->screen->get_param(pipe->screen, + PIPE_CAP_BUFFER_MAP_PERSISTENT_COHERENT)) + return NULL; + + upload = CALLOC_STRUCT(nine_buffer_upload); + + if (!upload) + return NULL; + + slab_create(&upload->buffer_pool, sizeof(struct nine_subbuffer), 4096); + + upload->pipe = pipe; + upload->buffers_size = align(buffers_size, 4096); + upload->num_buffers = num_buffers; + + upload->buffers = CALLOC(num_buffers, sizeof(struct nine_buffer_group)); + if (!upload->buffers) + goto buffers_fail; + + for (i = 0; i < num_buffers; i++) + nine_upload_create_buffer_group(upload, &upload->buffers[i]); + + return upload; + +buffers_fail: + slab_destroy(&upload->buffer_pool); + FREE(upload); + return NULL; +} + +void +nine_upload_destroy(struct nine_buffer_upload *upload) +{ + int i; + + DBG("%p\n", upload); + + for (i = 0; i < upload->num_buffers; i++) + nine_upload_destroy_buffer_group(upload, &upload->buffers[i]); + slab_destroy(&upload->buffer_pool); + FREE(upload); +} + +struct nine_subbuffer * +nine_upload_create_buffer(struct nine_buffer_upload *upload, + unsigned buffer_size) +{ + struct nine_subbuffer *buf = slab_alloc_st(&upload->buffer_pool); + struct nine_buffer_group *group = NULL; + unsigned size = align(buffer_size, 4096); + int i = 0; + + DBG("%p %d\n", upload, buffer_size); + + if (!buf) + return NULL; + + for (i = 0; i < upload->num_buffers; i++) { + group = &upload->buffers[i]; + if (group->resource && + group->free_offset + size <= upload->buffers_size) + break; + } + + if (i == upload->num_buffers) { + /* Allocate lonely buffer */ + struct pipe_resource resource; + struct pipe_screen *screen = upload->pipe->screen; + + DBG("Allocating buffer\n"); + buf->parent = NULL; + + memset(&resource, 0, sizeof(resource)); + resource.target = PIPE_BUFFER; + resource.format = PIPE_FORMAT_R8_UNORM; + resource.bind = PIPE_BIND_VERTEX_BUFFER; + resource.usage = PIPE_USAGE_STREAM; + resource.width0 = buffer_size; + resource.height0 = 1; + resource.depth0 = 1; + resource.array_size = 1; + resource.flags = PIPE_RESOURCE_FLAG_MAP_PERSISTENT | + PIPE_RESOURCE_FLAG_MAP_COHERENT; + + buf->resource = screen->resource_create(screen, &resource); + if (buf->resource == NULL) { + slab_free_st(&upload->buffer_pool, buf); + return NULL; + } + + buf->map = pipe_buffer_map_range(upload->pipe, buf->resource, + 0, buffer_size, + PIPE_TRANSFER_WRITE | + PIPE_TRANSFER_PERSISTENT | + PIPE_TRANSFER_COHERENT, + &buf->transfer); + if (buf->map == NULL) { + pipe_resource_reference(&buf->resource, NULL); + slab_free_st(&upload->buffer_pool, buf); + return NULL; + } + buf->offset = 0; + return buf; + } + + DBG("Using buffer group %d\n", i); + + buf->parent = group; + buf->resource = NULL; + pipe_resource_reference(&buf->resource, group->resource); + buf->offset = group->free_offset; + + group->free_offset += size; + group->refcount += 1; + + return buf; +} + +void +nine_upload_release_buffer(struct nine_buffer_upload *upload, + struct nine_subbuffer *buf) +{ + DBG("%p %p %p\n", upload, buf, buf->parent); + + if (buf->parent) { + pipe_resource_reference(&buf->resource, NULL); + buf->parent->refcount--; + if (buf->parent->refcount == 0) { + /* Allocate new buffer */ + nine_upload_destroy_buffer_group(upload, buf->parent); + nine_upload_create_buffer_group(upload, buf->parent); + } + } else { + /* lonely buffer */ + if (buf->transfer) + pipe_transfer_unmap(upload->pipe, buf->transfer); + pipe_resource_reference(&buf->resource, NULL); + } + + slab_free_st(&upload->buffer_pool, buf); +} + +uint8_t * +nine_upload_buffer_get_map(struct nine_subbuffer *buf) +{ + if (buf->parent) { + return buf->parent->map + buf->offset; + } + /* lonely buffer */ + return buf->map; +} + +struct pipe_resource * +nine_upload_buffer_resource_and_offset(struct nine_subbuffer *buf, + unsigned *offset) +{ + *offset = buf->offset; + return buf->resource; +} diff --git a/src/gallium/frontends/nine/nine_buffer_upload.h b/src/gallium/frontends/nine/nine_buffer_upload.h new file mode 100644 index 00000000000..b7088250a83 --- /dev/null +++ b/src/gallium/frontends/nine/nine_buffer_upload.h @@ -0,0 +1,59 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * Copyright 2016 Axel Davy + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef _NINE_BUFFER_UPLOAD_H_ +#define _NINE_BUFFER_UPLOAD_H_ + +#include "pipe/p_defines.h" + +struct nine_buffer_upload; +struct nine_subbuffer; + +struct nine_buffer_upload * +nine_upload_create(struct pipe_context *pipe, unsigned buffers_size, + unsigned num_buffers); + +void +nine_upload_destroy(struct nine_buffer_upload *upload); + +struct nine_subbuffer * +nine_upload_create_buffer(struct nine_buffer_upload *upload, + unsigned buffer_size); + +void +nine_upload_release_buffer(struct nine_buffer_upload *upload, + struct nine_subbuffer *buf); + +uint8_t * +nine_upload_buffer_get_map(struct nine_subbuffer *buf); + +struct pipe_resource * +nine_upload_buffer_resource_and_offset(struct nine_subbuffer *buf, + unsigned *offset); + +#endif /* _NINE_BUFFER_UPLOAD_H_ */ diff --git a/src/gallium/frontends/nine/nine_csmt_helper.h b/src/gallium/frontends/nine/nine_csmt_helper.h new file mode 100644 index 00000000000..7286cc31140 --- /dev/null +++ b/src/gallium/frontends/nine/nine_csmt_helper.h @@ -0,0 +1,438 @@ +/* + * Copyright 2016 Patrick Rudolph + * + * Permission is hereby granted, free of charge, f, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, f, copy, modify, merge, f, publish, distribute, f, sub + * license, f, and/or sell copies of the Software, f, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISe, f, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* get number of arguments with __NARG__ */ +#define __NARG__(...) __NARG_I_(__VA_ARGS__,__RSEQ_N()) +#define __NARG_I_(...) __ARG_N(__VA_ARGS__) +#define __ARG_N( \ + _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \ + _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \ + _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \ + _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \ + _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \ + _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \ + _61,_62,_63,N,...) N +#define __RSEQ_N() \ + 63,62,61,60, \ + 59,58,57,56,55,54,53,52,51,50, \ + 49,48,47,46,45,44,43,42,41,40, \ + 39,38,37,36,35,34,33,32,31,30, \ + 29,28,27,26,25,24,23,22,21,20, \ + 19,18,17,16,15,14,13,12,11,10, \ + 9,8,7,6,5,4,3,2,1,0 + + +#define _args_for_bypass_1(a) a +#define _args_for_bypass_7(a, b, c, d, e, f, g) ,g +#define _args_for_bypass_14(a, b, c, d, e, f, g, ...) ,g _args_for_bypass_7(__VA_ARGS__) +#define _args_for_bypass_21(a, b, c, d, e, f, g, ...) ,g _args_for_bypass_14(__VA_ARGS__) +#define _args_for_bypass_28(a, b, c, d, e, f, g, ...) ,g _args_for_bypass_21(__VA_ARGS__) +#define _args_for_bypass_35(a, b, c, d, e, f, g, ...) ,g _args_for_bypass_28(__VA_ARGS__) +#define _args_for_bypass_42(a, b, c, d, e, f, g, ...) ,g _args_for_bypass_35(__VA_ARGS__) +#define _args_for_bypass_49(a, b, c, d, e, f, g, ...) ,g _args_for_bypass_42(__VA_ARGS__) +#define _args_for_bypass_56(a, b, c, d, e, f, g, ...) ,g _args_for_bypass_49(__VA_ARGS__) +#define _args_for_bypass_63(a, b, c, d, e, f, g, ...) ,g _args_for_bypass_56(__VA_ARGS__) +#define _args_for_bypass_70(a, b, c, d, e, f, g, ...) ,g _args_for_bypass_63(__VA_ARGS__) + +#define _GFUNC_(n) _args_for_bypass_##n +#define _GFUNC(n) _GFUNC_(n) + +#define ARGS_FOR_BYPASS(...) _GFUNC(__NARG__(__VA_ARGS__)) (__VA_ARGS__) + +#define _args_for_mem_1(a) a; +#define _args_for_mem_7(a, b, c, d, e, f, g) f; +#define _args_for_mem_14(a, b, c, d, e, f, g, ...) f; _args_for_mem_7(__VA_ARGS__) +#define _args_for_mem_21(a, b, c, d, e, f, g, ...) f; _args_for_mem_14(__VA_ARGS__) +#define _args_for_mem_28(a, b, c, d, e, f, g, ...) f; _args_for_mem_21(__VA_ARGS__) +#define _args_for_mem_35(a, b, c, d, e, f, g, ...) f; _args_for_mem_28(__VA_ARGS__) +#define _args_for_mem_42(a, b, c, d, e, f, g, ...) f; _args_for_mem_35(__VA_ARGS__) +#define _args_for_mem_49(a, b, c, d, e, f, g, ...) f; _args_for_mem_42(__VA_ARGS__) +#define _args_for_mem_56(a, b, c, d, e, f, g, ...) f; _args_for_mem_49(__VA_ARGS__) +#define _args_for_mem_63(a, b, c, d, e, f, g, ...) f; _args_for_mem_56(__VA_ARGS__) +#define _args_for_mem_70(a, b, c, d, e, f, g, ...) f; _args_for_mem_63(__VA_ARGS__) + +#define _FFUNC_(n) _args_for_mem_##n +#define _FFUNC(n) _FFUNC_(n) + +#define ARGS_FOR_MEM(...) _FFUNC(__NARG__(__VA_ARGS__)) (__VA_ARGS__) + +#define _args_for_unbind_1(a) a; +#define _args_for_unbind_7(a, b, c, d, e, f, g) e; +#define _args_for_unbind_14(a, b, c, d, e, f, g, ...) e; _args_for_unbind_7(__VA_ARGS__) +#define _args_for_unbind_21(a, b, c, d, e, f, g, ...) e; _args_for_unbind_14(__VA_ARGS__) +#define _args_for_unbind_28(a, b, c, d, e, f, g, ...) e; _args_for_unbind_21(__VA_ARGS__) +#define _args_for_unbind_35(a, b, c, d, e, f, g, ...) e; _args_for_unbind_28(__VA_ARGS__) +#define _args_for_unbind_42(a, b, c, d, e, f, g, ...) e; _args_for_unbind_35(__VA_ARGS__) +#define _args_for_unbind_49(a, b, c, d, e, f, g, ...) e; _args_for_unbind_42(__VA_ARGS__) +#define _args_for_unbind_56(a, b, c, d, e, f, g, ...) e; _args_for_unbind_49(__VA_ARGS__) +#define _args_for_unbind_63(a, b, c, d, e, f, g, ...) e; _args_for_unbind_56(__VA_ARGS__) +#define _args_for_unbind_70(a, b, c, d, e, f, g, ...) e; _args_for_unbind_63(__VA_ARGS__) + +#define _EFUNC_(n) _args_for_unbind_##n +#define _EFUNC(n) _EFUNC_(n) + +#define ARGS_FOR_UNBIND(...) _EFUNC(__NARG__(__VA_ARGS__)) (__VA_ARGS__) + +#define _args_for_call_1(a) a +#define _args_for_call_7(a, b, c, d, e, f, g) ,d +#define _args_for_call_14(a, b, c, d, e, f, g, ...) ,d _args_for_call_7(__VA_ARGS__) +#define _args_for_call_21(a, b, c, d, e, f, g, ...) ,d _args_for_call_14(__VA_ARGS__) +#define _args_for_call_28(a, b, c, d, e, f, g, ...) ,d _args_for_call_21(__VA_ARGS__) +#define _args_for_call_35(a, b, c, d, e, f, g, ...) ,d _args_for_call_28(__VA_ARGS__) +#define _args_for_call_42(a, b, c, d, e, f, g, ...) ,d _args_for_call_35(__VA_ARGS__) +#define _args_for_call_49(a, b, c, d, e, f, g, ...) ,d _args_for_call_42(__VA_ARGS__) +#define _args_for_call_56(a, b, c, d, e, f, g, ...) ,d _args_for_call_49(__VA_ARGS__) +#define _args_for_call_63(a, b, c, d, e, f, g, ...) ,d _args_for_call_56(__VA_ARGS__) +#define _args_for_call_70(a, b, c, d, e, f, g, ...) ,d _args_for_call_63(__VA_ARGS__) + +#define _DFUNC_(n) _args_for_call_##n +#define _DFUNC(n) _DFUNC_(n) + +#define ARGS_FOR_CALL(...) _DFUNC(__NARG__(__VA_ARGS__)) (__VA_ARGS__) + +#define _args_for_decl_1(a) a +#define _args_for_decl_7(a, b, c, d, e, f, g) ,c +#define _args_for_decl_14(a, b, c, d, e, f, g, ...) ,c _args_for_decl_7(__VA_ARGS__) +#define _args_for_decl_21(a, b, c, d, e, f, g, ...) ,c _args_for_decl_14(__VA_ARGS__) +#define _args_for_decl_28(a, b, c, d, e, f, g, ...) ,c _args_for_decl_21(__VA_ARGS__) +#define _args_for_decl_35(a, b, c, d, e, f, g, ...) ,c _args_for_decl_28(__VA_ARGS__) +#define _args_for_decl_42(a, b, c, d, e, f, g, ...) ,c _args_for_decl_35(__VA_ARGS__) +#define _args_for_decl_49(a, b, c, d, e, f, g, ...) ,c _args_for_decl_42(__VA_ARGS__) +#define _args_for_decl_56(a, b, c, d, e, f, g, ...) ,c _args_for_decl_49(__VA_ARGS__) +#define _args_for_decl_63(a, b, c, d, e, f, g, ...) ,c _args_for_decl_56(__VA_ARGS__) +#define _args_for_decl_70(a, b, c, d, e, f, g, ...) ,c _args_for_decl_63(__VA_ARGS__) + +#define _CFUNC_(n) _args_for_decl_##n +#define _CFUNC(n) _CFUNC_(n) + +#define ARGS_FOR_DECLARATION(...) _CFUNC(__NARG__(__VA_ARGS__)) (__VA_ARGS__) + +#define _args_for_assign_1(a) a +#define _args_for_assign_7(a, b, c, d, e, f, g) b; +#define _args_for_assign_14(a, b, c, d, e, f, g, ...) b; _args_for_assign_7(__VA_ARGS__) +#define _args_for_assign_21(a, b, c, d, e, f, g, ...) b; _args_for_assign_14(__VA_ARGS__) +#define _args_for_assign_28(a, b, c, d, e, f, g, ...) b; _args_for_assign_21(__VA_ARGS__) +#define _args_for_assign_35(a, b, c, d, e, f, g, ...) b; _args_for_assign_28(__VA_ARGS__) +#define _args_for_assign_42(a, b, c, d, e, f, g, ...) b; _args_for_assign_35(__VA_ARGS__) +#define _args_for_assign_49(a, b, c, d, e, f, g, ...) b; _args_for_assign_42(__VA_ARGS__) +#define _args_for_assign_56(a, b, c, d, e, f, g, ...) b; _args_for_assign_49(__VA_ARGS__) +#define _args_for_assign_63(a, b, c, d, e, f, g, ...) b; _args_for_assign_56(__VA_ARGS__) +#define _args_for_assign_70(a, b, c, d, e, f, g, ...) b; _args_for_assign_63(__VA_ARGS__) + +#define _BFUNC_(n) _args_for_assign_##n +#define _BFUNC(n) _BFUNC_(n) + +#define ARGS_FOR_ASSIGN(...) _BFUNC(__NARG__(__VA_ARGS__)) (__VA_ARGS__) + +#define _args_for_struct_1(a) a; +#define _args_for_struct_7(a, b, c, d, e, f, g) a; +#define _args_for_struct_14(a, b, c, d, e, f, g, ...) a; _args_for_struct_7(__VA_ARGS__) +#define _args_for_struct_21(a, b, c, d, e, f, g, ...) a; _args_for_struct_14(__VA_ARGS__) +#define _args_for_struct_28(a, b, c, d, e, f, g, ...) a; _args_for_struct_21(__VA_ARGS__) +#define _args_for_struct_35(a, b, c, d, e, f, g, ...) a; _args_for_struct_28(__VA_ARGS__) +#define _args_for_struct_42(a, b, c, d, e, f, g, ...) a; _args_for_struct_35(__VA_ARGS__) +#define _args_for_struct_49(a, b, c, d, e, f, g, ...) a; _args_for_struct_42(__VA_ARGS__) +#define _args_for_struct_56(a, b, c, d, e, f, g, ...) a; _args_for_struct_49(__VA_ARGS__) +#define _args_for_struct_63(a, b, c, d, e, f, g, ...) a; _args_for_struct_56(__VA_ARGS__) +#define _args_for_struct_70(a, b, c, d, e, f, g, ...) a; _args_for_struct_63(__VA_ARGS__) + +#define _AFUNC_(n) _args_for_struct_##n +#define _AFUNC(n) _AFUNC_(n) + +#define ARGS_FOR_STRUCT(...) _AFUNC(__NARG__(__VA_ARGS__)) (__VA_ARGS__) + +/* Serialization and deserialization */ + +#define CSMT_ITEM_NO_WAIT(name, ...) \ +\ +struct s_##name##_private { \ + struct csmt_instruction instr; \ + ARGS_FOR_STRUCT( __VA_ARGS__ ) \ +}; \ +\ +static void \ +name##_priv( struct NineDevice9 *device ARGS_FOR_DECLARATION( __VA_ARGS__ ) ); \ +\ +static int \ +name##_rx( struct NineDevice9 *device, struct csmt_instruction *instr ) \ +{ \ + struct csmt_context *ctx = device->csmt_ctx; \ + struct s_##name##_private *args = (struct s_##name##_private *)instr; \ + \ + (void) args; \ + (void) ctx; \ + name##_priv( \ + device ARGS_FOR_CALL( __VA_ARGS__ ) \ + ); \ + ARGS_FOR_UNBIND( __VA_ARGS__ ) \ + return 0; \ +} \ +\ +void \ +name( struct NineDevice9 *device ARGS_FOR_DECLARATION( __VA_ARGS__ ) ) \ +{ \ + struct csmt_context *ctx = device->csmt_ctx; \ + struct s_##name##_private *args; \ + unsigned memsize = sizeof(struct s_##name##_private); \ + unsigned memsize2 = 0; \ + \ + if (!device->csmt_active) { \ + name##_priv( \ + device ARGS_FOR_BYPASS( __VA_ARGS__ ) \ + ); \ + return; \ + } \ + ARGS_FOR_MEM ( __VA_ARGS__ ) \ + args = nine_queue_alloc(ctx->pool, memsize + memsize2); \ + assert(args); \ + args->instr.func = &name##_rx; \ + ARGS_FOR_ASSIGN( __VA_ARGS__ ) \ +} \ +\ +static void \ +name##_priv( struct NineDevice9 *device ARGS_FOR_DECLARATION( __VA_ARGS__ ) ) + +#define CSMT_ITEM_NO_WAIT_WITH_COUNTER(name, ...) \ +\ +struct s_##name##_private { \ + struct csmt_instruction instr; \ + unsigned *counter; \ + ARGS_FOR_STRUCT( __VA_ARGS__ ) \ +}; \ +\ +static void \ +name##_priv( struct NineDevice9 *device ARGS_FOR_DECLARATION( __VA_ARGS__ ) ); \ +\ +static int \ +name##_rx( struct NineDevice9 *device, struct csmt_instruction *instr ) \ +{ \ + struct csmt_context *ctx = device->csmt_ctx; \ + struct s_##name##_private *args = (struct s_##name##_private *)instr; \ + \ + (void) args; \ + (void) ctx; \ + name##_priv( \ + device ARGS_FOR_CALL( __VA_ARGS__ ) \ + ); \ + p_atomic_dec(args->counter); \ + ARGS_FOR_UNBIND( __VA_ARGS__ ) \ + return 0; \ +} \ +\ +void \ +name( struct NineDevice9 *device, unsigned *counter ARGS_FOR_DECLARATION( __VA_ARGS__ ) ) \ +{ \ + struct csmt_context *ctx = device->csmt_ctx; \ + struct s_##name##_private *args; \ + unsigned memsize = sizeof(struct s_##name##_private); \ + unsigned memsize2 = 0; \ + \ + if (!device->csmt_active) { \ + name##_priv( \ + device ARGS_FOR_BYPASS( __VA_ARGS__ ) \ + ); \ + return; \ + } \ + assert(counter); \ + p_atomic_inc(counter); \ + ARGS_FOR_MEM ( __VA_ARGS__ ) \ + args = nine_queue_alloc(ctx->pool, memsize + memsize2); \ + assert(args); \ + args->instr.func = &name##_rx; \ + args->counter = counter; \ + ARGS_FOR_ASSIGN( __VA_ARGS__ ) \ +} \ +\ +static void \ +name##_priv( struct NineDevice9 *device ARGS_FOR_DECLARATION( __VA_ARGS__ ) ) + +#define CSMT_ITEM_DO_WAIT(name, ...) \ +\ +struct s_##name##_private { \ + struct csmt_instruction instr; \ + ARGS_FOR_STRUCT( __VA_ARGS__ ) \ +}; \ +static void \ +name##_priv( struct NineDevice9 *device ARGS_FOR_DECLARATION( __VA_ARGS__ ) ); \ +\ +static int \ +name##_rx( struct NineDevice9 *device, struct csmt_instruction *instr) \ +{ \ + struct csmt_context *ctx = device->csmt_ctx; \ + struct s_##name##_private *args = (struct s_##name##_private *)instr; \ + \ + (void) args; \ + (void) ctx; \ + name##_priv( \ + device ARGS_FOR_CALL( __VA_ARGS__ ) \ + ); \ + ARGS_FOR_UNBIND( __VA_ARGS__ ) \ + return 1; \ +} \ +\ +void \ +name( struct NineDevice9 *device ARGS_FOR_DECLARATION( __VA_ARGS__ ) ) \ +{ \ + struct csmt_context *ctx = device->csmt_ctx; \ + struct s_##name##_private *args; \ + unsigned memsize = sizeof(struct s_##name##_private); \ + unsigned memsize2 = 0; \ + \ + if (!device->csmt_active) { \ + name##_priv( \ + device ARGS_FOR_BYPASS( __VA_ARGS__ ) \ + ); \ + return; \ + } \ + ARGS_FOR_MEM ( __VA_ARGS__ ) \ + args = nine_queue_alloc(ctx->pool, memsize + memsize2); \ + assert(args); \ + args->instr.func = &name##_rx; \ + ARGS_FOR_ASSIGN( __VA_ARGS__ ) \ + ctx->processed = FALSE; \ + nine_queue_flush(ctx->pool); \ + nine_csmt_wait_processed(ctx); \ +} \ +\ +static void \ +name##_priv( struct NineDevice9 *device ARGS_FOR_DECLARATION( __VA_ARGS__ ) ) + +/* ARGS_FOR_STRUCT, ARGS_FOR_ASSIGN, ARGS_FOR_DECLARATION, ARGS_FOR_CALL, ARGS_FOR_UNBIND, ARGS_FOR_MEM, ARGS_FOR_BYPASS */ +#define ARG_VAL(x, y) \ + x _##y ; ,\ + args->_##y = y ; ,\ + x y ,\ + args->_##y ,\ + ,\ + ,\ + y + +#define ARG_REF(x, y) \ + x* _##y ; ,\ + args->_##y = y; ,\ + x *y ,\ + args->_##y ,\ + ,\ + ,\ + y + +#define ARG_COPY_REF(x, y) \ + x * _##y ; x __##y ; ,\ + if ( y ) { args->_##y = &args->__##y ; args->__##y = *y ; } else { args->_##y = NULL; } ,\ + const x *y ,\ + (const x *)args->_##y ,\ + ,\ + ,\ + (const x *)y + +#define ARG_BIND_REF(x, y) \ + x * _##y ,\ + if ( y ) \ + NineUnknown_Bind( (void *)y ); \ + args->_##y = y ; ,\ + x *y ,\ + args->_##y,\ + if (args->_##y) \ + NineUnknown_Unbind((void *)(args->_##y)); \ + args->_##y = NULL; ,\ + ,\ + y + +#define ARG_BIND_RES(x, y) \ + x * _##y ,\ + args->_##y = NULL; \ + if (y) \ + pipe_resource_reference(&args->_##y, y); ,\ + x *y ,\ + args->_##y ,\ + if (args->_##y) \ + pipe_resource_reference(&args->_##y, NULL); ,\ + ,\ + y + +#define ARG_MEM(x, y) \ + x * _##y ,\ + args->_##y = (void *)args + memsize;\ + memcpy(args->_##y, y, memsize2); ,\ + const x *y ,\ + (const x *)args->_##y ,\ + ,\ + ,\ + (const x *)y + +#define ARG_MEM_SIZE(x, y) \ + x _##y ,\ + args->_##y = y; ,\ + x y ,\ + args->_##y ,\ + ,\ + memsize2 = y, \ + y + +#define ARG_BIND_BLIT(x, y) \ + x _##y ,\ + memcpy(&args->_##y , y, sizeof(x)); \ + args->_##y.src.resource = NULL; \ + args->_##y.dst.resource = NULL; \ + pipe_resource_reference(&args->_##y.src.resource, y->src.resource); \ + pipe_resource_reference(&args->_##y.dst.resource, y->dst.resource);,\ + x *y ,\ + &args->_##y ,\ + pipe_resource_reference(&args->_##y.src.resource, NULL); \ + pipe_resource_reference(&args->_##y.dst.resource, NULL);,\ + ,\ + y + +#define ARG_BIND_VBUF(x, y) \ + x _##y ,\ + memcpy(&args->_##y , y, sizeof(x)); \ + args->_##y.buffer.resource = NULL; \ + pipe_resource_reference(&args->_##y.buffer.resource, y->buffer.resource); ,\ + x *y ,\ + &args->_##y ,\ + pipe_resource_reference(&args->_##y.buffer.resource, NULL); ,\ + ,\ + y + +#define ARG_BIND_IBUF(x, y) \ + x _##y ,\ + memcpy(&args->_##y , y, sizeof(x)); \ + args->_##y.buffer = NULL; \ + pipe_resource_reference(&args->_##y.buffer, y->buffer); ,\ + x *y ,\ + &args->_##y ,\ + pipe_resource_reference(&args->_##y.buffer, NULL); ,\ + ,\ + y + +#define ARG_BIND_VIEW(x, y) \ + x * _##y ,\ + args->_##y = NULL; \ + if (y) \ + pipe_sampler_view_reference(&args->_##y, y); ,\ + x *y ,\ + args->_##y ,\ + if (args->_##y) \ + pipe_sampler_view_reference(&args->_##y, NULL); ,\ + ,\ + y + diff --git a/src/gallium/frontends/nine/nine_debug.c b/src/gallium/frontends/nine/nine_debug.c new file mode 100644 index 00000000000..784d535d213 --- /dev/null +++ b/src/gallium/frontends/nine/nine_debug.c @@ -0,0 +1,117 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "nine_debug.h" + +#include +#include "c11/threads.h" + +static const struct debug_named_value nine_debug_flags[] = { + { "unknown", DBG_UNKNOWN, "IUnknown implementation." }, + { "adapter", DBG_ADAPTER, "ID3D9Adapter implementation." }, + { "overlay", DBG_OVERLAYEXTENSION, "IDirect3D9ExOverlayExtension implementation." }, + { "auth", DBG_AUTHENTICATEDCHANNEL, "IDirect3DAuthenticatedChannel9 implementation." }, + { "basetex", DBG_BASETEXTURE, "IDirect3DBaseTexture9 implementation." }, + { "crypto", DBG_CRYPTOSESSION, "IDirect3DCryptoSession9 implementation." }, + { "cubetex", DBG_CUBETEXTURE, "IDirect3DCubeTexture9 implementation." }, + { "device", DBG_DEVICE, "IDirect3DDevice9(Ex) implementation." }, + { "video", DBG_DEVICEVIDEO, "IDirect3DDeviceVideo9 implementation." }, + { "ibuf", DBG_INDEXBUFFER, "IDirect3DIndexBuffer9 implementation." }, + { "ps", DBG_PIXELSHADER, "IDirect3DPixelShader9 implementation." }, + { "query", DBG_QUERY, "IDirect3DQuery9 implementation." }, + { "res", DBG_RESOURCE, "IDirect3DResource9 implementation." }, + { "state", DBG_STATEBLOCK, "IDirect3DStateBlock9 implementation." }, + { "surf", DBG_SURFACE, "IDirect3DSurface9 implementation." }, + { "swap", DBG_SWAPCHAIN, "IDirect3DSwapChain9(Ex) implementation." }, + { "tex", DBG_TEXTURE, "IDirect3DTexture9 implementation." }, + { "vbuf", DBG_VERTEXBUFFER, "IDirect3DVertexBuffer9 implementation." }, + { "vdecl", DBG_VERTEXDECLARATION, "IDirect3DVertexDeclaration9 implementation." }, + { "vs", DBG_VERTEXSHADER, "IDirect3DVertexShader9 implementation." }, + { "3dsurf", DBG_VOLUME, "IDirect3DVolume9 implementation." }, + { "3dtex", DBG_VOLUMETEXTURE, "IDirect3DVolumeTexture9 implementation." }, + { "shader", DBG_SHADER, "Shader token stream translator." }, + { "ff", DBG_FF, "Fixed function emulation." }, + { "user", DBG_USER, "User errors, both fixable and unfixable." }, + { "error", DBG_ERROR, "Driver errors, always visible." }, + { "warn", DBG_WARN, "Driver warnings, always visible in debug builds." }, + { "tid", DBG_TID, "Display thread-ids." }, + DEBUG_NAMED_VALUE_END +}; + +void +_nine_debug_printf( unsigned long flag, + const char *func, + const char *fmt, + ... ) +{ + static boolean first = TRUE; + static unsigned long dbg_flags = DBG_ERROR | DBG_WARN; + unsigned long tid = 0; + + if (first) { + first = FALSE; + dbg_flags |= debug_get_flags_option("NINE_DEBUG", nine_debug_flags, 0); + } + +#if defined(HAVE_PTHREAD) + if (dbg_flags & DBG_TID) + tid = pthread_self(); +#endif + + if (dbg_flags & flag) { + const char *f = func ? strrchr(func, '_') : NULL; + va_list ap; + /* inside a class this will print nine:tid:classinlowercase:func: while + * outside a class (rarely used) it will just print nine:tid:func + * the reason for lower case is simply to match the filenames, as it + * will also strip off the "Nine" */ + if (f && strncmp(func, "Nine", 4) == 0) { + char klass[96]; /* no class name is this long */ + char *ptr = klass; + for (func += 4; func != f; ++func) { *ptr++ = tolower(*func); } + *ptr = '\0'; + if (tid) + _debug_printf("nine:0x%08lx:%s:%s: ", tid, klass, ++f); + else + _debug_printf("nine:%s:%s: ", klass, ++f); + } else if (func) { + if (tid) + _debug_printf("nine:0x%08lx:%s ", tid, func); + else + _debug_printf("nine:%s ", func); + } + + va_start(ap, fmt); + _debug_vprintf(fmt, ap); + va_end(ap); + } +} + +void +_nine_stub( const char *file, + const char *func, + unsigned line ) +{ + const char *r = strrchr(file, '/'); + if (r == NULL) { r = strrchr(file, '\\'); } + _debug_printf("nine:%s:%d: %s STUB!\n", r ? ++r : file, line, func); +} diff --git a/src/gallium/frontends/nine/nine_debug.h b/src/gallium/frontends/nine/nine_debug.h new file mode 100644 index 00000000000..75e412497b0 --- /dev/null +++ b/src/gallium/frontends/nine/nine_debug.h @@ -0,0 +1,137 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _NINE_DEBUG_H_ +#define _NINE_DEBUG_H_ + +#include "util/u_debug.h" +#include "pipe/p_compiler.h" + +void +_nine_debug_printf( unsigned long flag, + const char *func, + const char *fmt, + ... ) _util_printf_format(3,4); + +#define ERR(fmt, ...) _nine_debug_printf(DBG_ERROR, __FUNCTION__, fmt, ## __VA_ARGS__) + +#if defined(DEBUG) || !defined(NDEBUG) +#define WARN(fmt, ...) _nine_debug_printf(DBG_WARN, __FUNCTION__, fmt, ## __VA_ARGS__) +#define WARN_ONCE(fmt, ...) \ + do { \ + static boolean once = TRUE; \ + if (once) { \ + once = FALSE; \ + _nine_debug_printf(DBG_WARN, __FUNCTION__, fmt, ## __VA_ARGS__); \ + } \ + } while(0) +#else +#define WARN(fmt, ...) do {} while(0) +#define WARN_ONCE(fmt, ...) do {} while(0) +#endif + +#if defined(DEBUG) || !defined(NDEBUG) +#define DBG_FLAG(flag, fmt, ...) \ + _nine_debug_printf(flag, __FUNCTION__, fmt, ## __VA_ARGS__) +#else +#define DBG_FLAG(flag, fmt, ...) do {} while(0) +#endif +#define DBG(fmt, ...) DBG_FLAG(DBG_CHANNEL, fmt, ## __VA_ARGS__) + +#define DBG_UNKNOWN (1<< 0) +#define DBG_ADAPTER (1<< 1) +#define DBG_OVERLAYEXTENSION (1<< 2) +#define DBG_AUTHENTICATEDCHANNEL (1<< 3) +#define DBG_BASETEXTURE (1<< 4) +#define DBG_CRYPTOSESSION (1<< 5) +#define DBG_CUBETEXTURE (1<< 6) +#define DBG_DEVICE (1<< 7) +#define DBG_DEVICEVIDEO (1<< 8) +#define DBG_INDEXBUFFER (1<< 9) +#define DBG_PIXELSHADER (1<<10) +#define DBG_QUERY (1<<11) +#define DBG_RESOURCE (1<<12) +#define DBG_STATEBLOCK (1<<13) +#define DBG_SURFACE (1<<14) +#define DBG_SWAPCHAIN (1<<15) +#define DBG_TEXTURE (1<<16) +#define DBG_VERTEXBUFFER (1<<17) +#define DBG_VERTEXDECLARATION (1<<18) +#define DBG_VERTEXSHADER (1<<19) +#define DBG_VOLUME (1<<20) +#define DBG_VOLUMETEXTURE (1<<21) +#define DBG_SHADER (1<<22) +#define DBG_FF (1<<23) +#define DBG_USER (1<<24) +#define DBG_ERROR (1<<25) +#define DBG_WARN (1<<26) +#define DBG_TID (1<<27) + +void +_nine_stub( const char *file, + const char *func, + unsigned line ); + +#if defined(DEBUG) || !defined(NDEBUG) +#define STUB(ret) \ + do { \ + _nine_stub(__FILE__, __FUNCTION__, __LINE__); \ + return ret; \ + } while (0) +#else +#define STUB(ret) do { return ret; } while (0) +#endif + +/* the expression for this macro is equivalent of that to assert, however this + * macro is designed to be used in conditionals ala + * if (user_error(required condition)) { assertion failed } + * It also prints debug message if the assertion fails. */ +#if defined(DEBUG) || !defined(NDEBUG) +#define user_error(x) \ + (!(x) ? (DBG_FLAG(DBG_USER, "User assertion failed: `%s'\n", #x), TRUE) \ + : FALSE) +#else +#define user_error(x) (!(x) ? TRUE : FALSE) +#endif + +#if defined(DEBUG) || !defined(NDEBUG) +#define user_warn(x) \ + if ((x)) { DBG_FLAG(DBG_USER, "User warning: `%s'\n", #x); } +#else +#define user_warn(x) do {} while(0) +#endif + +/* nonfatal assert */ +#define user_assert(x, r) \ + do { \ + if (user_error(x)) { \ + return r; \ + } \ + } while (0) + +#define ret_err(x, r) \ + do { \ + ERR(x); \ + return r; \ + } while(0) + +#endif /* _NINE_DEBUG_H_ */ diff --git a/src/gallium/frontends/nine/nine_defines.h b/src/gallium/frontends/nine/nine_defines.h new file mode 100644 index 00000000000..26aa064b1ac --- /dev/null +++ b/src/gallium/frontends/nine/nine_defines.h @@ -0,0 +1,65 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _NINE_DEFINES_H_ +#define _NINE_DEFINES_H_ + +#include "pipe/p_defines.h" + + +#define NINE_RESOURCE_FLAG_LOCKABLE (PIPE_RESOURCE_FLAG_ST_PRIV << 1) +#define NINE_RESOURCE_FLAG_DUMMY (PIPE_RESOURCE_FLAG_ST_PRIV << 2) + +/* vertexdeclaration9.c */ +uint16_t nine_d3d9_to_nine_declusage(unsigned usage, unsigned index); + +#define NINE_DECLUSAGE_POSITION 0 +#define NINE_DECLUSAGE_BLENDWEIGHT 1 +#define NINE_DECLUSAGE_BLENDINDICES 2 +#define NINE_DECLUSAGE_NORMAL 3 +#define NINE_DECLUSAGE_TEXCOORD 4 +#define NINE_DECLUSAGE_TANGENT 5 +#define NINE_DECLUSAGE_BINORMAL 6 +#define NINE_DECLUSAGE_COLOR 7 +#define NINE_DECLUSAGE_POSITIONT 8 + +#define NINE_DECLUSAGE_PSIZE 9 +#define NINE_DECLUSAGE_TESSFACTOR 10 +#define NINE_DECLUSAGE_DEPTH 11 +#define NINE_DECLUSAGE_FOG 12 +#define NINE_DECLUSAGE_SAMPLE 13 +#define NINE_DECLUSAGE_NONE 14 +#define NINE_DECLUSAGE_COUNT (NINE_DECLUSAGE_NONE + 1) + +#define NINE_DECLUSAGE_i(declusage, n) NINE_DECLUSAGE_##declusage + n * NINE_DECLUSAGE_COUNT + +#define NINED3DCLEAR_DEPTHSTENCIL (D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL) + +#define NINE_BIND_BACKBUFFER_FLAGS (PIPE_BIND_RENDER_TARGET |\ + PIPE_BIND_SAMPLER_VIEW) + +#define NINE_BIND_PRESENTBUFFER_FLAGS (PIPE_BIND_RENDER_TARGET |\ + PIPE_BIND_DISPLAY_TARGET |\ + PIPE_BIND_SCANOUT |\ + PIPE_BIND_SHARED) + +#endif /* _NINE_DEFINES_H_ */ diff --git a/src/gallium/frontends/nine/nine_dump.c b/src/gallium/frontends/nine/nine_dump.c new file mode 100644 index 00000000000..85ee266defb --- /dev/null +++ b/src/gallium/frontends/nine/nine_dump.c @@ -0,0 +1,813 @@ + +#include "nine_debug.h" +#include "nine_pipe.h" + +#include +#include "util/u_memory.h" +#include "util/u_math.h" + +#include "nine_dump.h" + +#if defined(DEBUG) || !defined(NDEBUG) + +static char __thread tls[128]; + +const char *nine_D3DDEVTYPE_to_str(D3DDEVTYPE type) +{ + switch (type) { + case D3DDEVTYPE_HAL: return "HAL"; + case D3DDEVTYPE_NULLREF: return "NULLREF"; + case D3DDEVTYPE_REF: return "REF"; + case D3DDEVTYPE_SW: return "SW"; + default: + return "(D3DDEVTYPE_?)"; + } +} + +const char *nine_D3DPOOL_to_str(D3DPOOL pool) +{ + switch (pool) { + case D3DPOOL_DEFAULT: return "DEFAULT"; + case D3DPOOL_MANAGED: return "MANAGED"; + case D3DPOOL_SYSTEMMEM: return "SYSTEMMEM"; + case D3DPOOL_SCRATCH: return "SCRATCH"; + default: + return "(D3DPOOL_?)"; + } +} + +const char *nine_D3DSAMP_to_str(DWORD samp) +{ + switch (samp) { + case D3DSAMP_ADDRESSU: return "ADDRESSU"; + case D3DSAMP_ADDRESSV: return "ADDRESSV"; + case D3DSAMP_ADDRESSW: return "ADDRESSW"; + case D3DSAMP_BORDERCOLOR: return "BORDERCOLOR"; + case D3DSAMP_MAGFILTER: return "MAGFILTER"; + case D3DSAMP_MINFILTER: return "MINFILTER"; + case D3DSAMP_MIPFILTER: return "MIPFILTER"; + case D3DSAMP_MIPMAPLODBIAS: return "MIPMAPLODBIAS"; + case D3DSAMP_MAXMIPLEVEL: return "MAXMIPLEVEL"; + case D3DSAMP_MAXANISOTROPY: return "MAXANISOTROPY"; + case D3DSAMP_SRGBTEXTURE: return "SRGBTEXTURE"; + case D3DSAMP_ELEMENTINDEX: return "ELEMENTINDEX"; + case D3DSAMP_DMAPOFFSET: return "DMAPOFFSET"; + default: + return "(D3DSAMP_?)"; + } +} + +#define C2S(n,s) \ + do { \ + if (usage & D3DUSAGE_##n) p += snprintf(&tls[p], sizeof(tls) - p, s); \ + } while(0) +const char *nine_D3DUSAGE_to_str(DWORD usage) +{ + int p = 0; + tls[0] = 0; + C2S(AUTOGENMIPMAP, "MIPGEN"); + C2S(WRITEONLY, "WO"); + C2S(DYNAMIC, "DYNAMIC"); + C2S(DEPTHSTENCIL, "DS"); + C2S(RENDERTARGET, "RT"); + C2S(SOFTWAREPROCESSING, "SW"); + C2S(DONOTCLIP, "NOCLIP"); + C2S(POINTS, "POINTS"); + C2S(DMAP, "DMAP"); + C2S(NPATCHES, "NPATCHES"); + C2S(RTPATCHES, "RTPATCHES"); + C2S(TEXTAPI, "TEXTAPI"); + C2S(NONSECURE, "NONSECURE"); + C2S(RESTRICTED_CONTENT, "RESTRICTED_CONTENT"); + C2S(RESTRICT_SHARED_RESOURCE, "RESTRICT_SHARED_RESOURCE"); + C2S(RESTRICT_SHARED_RESOURCE_DRIVER, "RESTRICT_SHARED_RESOURCE_DRIVER"); + return tls; +} +#undef C2S + +#define C2S(n) \ + do { \ + if (flags & D3DPRESENTFLAG_##n) \ + p += snprintf(&tls[p], sizeof(tls) - p, #n); \ + } while(0) +const char *nine_D3DPRESENTFLAG_to_str(DWORD flags) +{ + int p = 0; + tls[0] = 0; + C2S(DEVICECLIP); + C2S(DISCARD_DEPTHSTENCIL); + C2S(LOCKABLE_BACKBUFFER); + C2S(NOAUTOROTATE); + C2S(UNPRUNEDMODE); + C2S(VIDEO); + C2S(OVERLAY_LIMITEDRGB); + C2S(OVERLAY_YCbCr_BT709); + C2S(OVERLAY_YCbCr_xvYCC); + C2S(RESTRICTED_CONTENT); + C2S(RESTRICT_SHARED_RESOURCE_DRIVER); + return tls; +} +#undef C2S + +#define C2S(n) \ + do { \ + if (lock & D3DLOCK_##n) p += snprintf(&tls[p], sizeof(tls) - p, #n"|"); \ + } while(0) +const char *nine_D3DLOCK_to_str(DWORD lock) +{ + int p = 0; + tls[0] = 0; + C2S(DISCARD); + C2S(DONOTWAIT); + C2S(NO_DIRTY_UPDATE); + C2S(NOOVERWRITE); + C2S(NOSYSLOCK); + C2S(READONLY); + return tls; +} +#undef C2S + +const char *nine_D3DRTYPE_to_str(D3DRESOURCETYPE type) +{ + switch (type) { + case D3DRTYPE_SURFACE: return "SURFACE"; + case D3DRTYPE_VOLUME: return "VOLUME"; + case D3DRTYPE_TEXTURE: return "TEXTURE"; + case D3DRTYPE_VOLUMETEXTURE: return "VOLUMETEXTURE"; + case D3DRTYPE_CUBETEXTURE: return "CUBETEXTURE"; + case D3DRTYPE_VERTEXBUFFER: return "VERTEXBUFFER"; + case D3DRTYPE_INDEXBUFFER: return "INDEXBUFFER"; + default: + return "(D3DRTYPE_?)"; + } +} + +const char *nine_D3DQUERYTYPE_to_str(D3DQUERYTYPE type) +{ + switch (type) { + case D3DQUERYTYPE_VCACHE: return "VCACHE"; + case D3DQUERYTYPE_RESOURCEMANAGER: return "RESOURCEMANAGER"; + case D3DQUERYTYPE_VERTEXSTATS: return "VERTEXSTATS"; + case D3DQUERYTYPE_EVENT: return "EVENT"; + case D3DQUERYTYPE_OCCLUSION: return "OCCLUSION"; + case D3DQUERYTYPE_TIMESTAMP: return "TIMESTAMP"; + case D3DQUERYTYPE_TIMESTAMPDISJOINT: return "TIMESTAMPDISJOINT"; + case D3DQUERYTYPE_TIMESTAMPFREQ: return "TIMESTAMPFREQ"; + case D3DQUERYTYPE_PIPELINETIMINGS: return "PIPELINETIMINGS"; + case D3DQUERYTYPE_INTERFACETIMINGS: return "INTERFACETIMINGS"; + case D3DQUERYTYPE_VERTEXTIMINGS: return "VERTEXTIMINGS"; + case D3DQUERYTYPE_PIXELTIMINGS: return "PIXELTIMINGS"; + case D3DQUERYTYPE_BANDWIDTHTIMINGS: return "BANDWIDTHTIMINGS"; + case D3DQUERYTYPE_CACHEUTILIZATION: return "CACHEUTILIZATION"; + default: + return "(D3DQUERYTYPE_?)"; + } +} + +const char *nine_D3DTSS_to_str(D3DTEXTURESTAGESTATETYPE type) +{ + switch (type) { + case D3DTSS_COLOROP: return "COLOROP"; + case D3DTSS_ALPHAOP: return "ALPHAOP"; + case D3DTSS_COLORARG0: return "COLORARG0"; + case D3DTSS_COLORARG1: return "COLORARG1"; + case D3DTSS_COLORARG2: return "COLORARG2"; + case D3DTSS_ALPHAARG0: return "ALPHAARG0"; + case D3DTSS_ALPHAARG1: return "ALPHAARG1"; + case D3DTSS_ALPHAARG2: return "ALPHAARG2"; + case D3DTSS_RESULTARG: return "RESULTARG"; + case D3DTSS_BUMPENVMAT00: return "BUMPENVMAT00"; + case D3DTSS_BUMPENVMAT01: return "BUMPENVMAT01"; + case D3DTSS_BUMPENVMAT10: return "BUMPENVMAT10"; + case D3DTSS_BUMPENVMAT11: return "BUMPENVMAT11"; + case D3DTSS_BUMPENVLSCALE: return "BUMPENVLSCALE"; + case D3DTSS_BUMPENVLOFFSET: return "BUMPENVLOFFSET"; + case D3DTSS_TEXCOORDINDEX: return "TEXCOORDINDEX"; + case D3DTSS_TEXTURETRANSFORMFLAGS: return "TEXTURETRANSFORMFLAGS"; + case D3DTSS_CONSTANT: return "CONSTANT"; + default: + return "(D3DTSS_?)"; + } +} + +#define D3DTOP_TO_STR_CASE(n) case D3DTOP_##n: return #n +const char *nine_D3DTOP_to_str(D3DTEXTUREOP top) +{ + switch (top) { + D3DTOP_TO_STR_CASE(DISABLE); + D3DTOP_TO_STR_CASE(SELECTARG1); + D3DTOP_TO_STR_CASE(SELECTARG2); + D3DTOP_TO_STR_CASE(MODULATE); + D3DTOP_TO_STR_CASE(MODULATE2X); + D3DTOP_TO_STR_CASE(MODULATE4X); + D3DTOP_TO_STR_CASE(ADD); + D3DTOP_TO_STR_CASE(ADDSIGNED); + D3DTOP_TO_STR_CASE(ADDSIGNED2X); + D3DTOP_TO_STR_CASE(SUBTRACT); + D3DTOP_TO_STR_CASE(ADDSMOOTH); + D3DTOP_TO_STR_CASE(BLENDDIFFUSEALPHA); + D3DTOP_TO_STR_CASE(BLENDTEXTUREALPHA); + D3DTOP_TO_STR_CASE(BLENDFACTORALPHA); + D3DTOP_TO_STR_CASE(BLENDTEXTUREALPHAPM); + D3DTOP_TO_STR_CASE(BLENDCURRENTALPHA); + D3DTOP_TO_STR_CASE(PREMODULATE); + D3DTOP_TO_STR_CASE(MODULATEALPHA_ADDCOLOR); + D3DTOP_TO_STR_CASE(MODULATECOLOR_ADDALPHA); + D3DTOP_TO_STR_CASE(MODULATEINVALPHA_ADDCOLOR); + D3DTOP_TO_STR_CASE(MODULATEINVCOLOR_ADDALPHA); + D3DTOP_TO_STR_CASE(BUMPENVMAP); + D3DTOP_TO_STR_CASE(BUMPENVMAPLUMINANCE); + D3DTOP_TO_STR_CASE(DOTPRODUCT3); + D3DTOP_TO_STR_CASE(MULTIPLYADD); + D3DTOP_TO_STR_CASE(LERP); + default: + return "(D3DTOP_?)"; + } +} + +static const char * +nine_D3DLIGHTTYPE_to_str(D3DLIGHTTYPE type) +{ + switch (type) { + case D3DLIGHT_POINT: return "POINT"; + case D3DLIGHT_SPOT: return "SPOT"; + case D3DLIGHT_DIRECTIONAL: return "DIRECTIONAL"; + default: + return "(D3DLIGHT_?)"; + } +} + +static const char * +nine_D3DTA_to_str(DWORD value) +{ + switch (value & D3DTA_SELECTMASK) { + case D3DTA_DIFFUSE: return "DIFFUSE"; + case D3DTA_CURRENT: return "CURRENT"; + case D3DTA_TEXTURE: return "TEXTURE"; + case D3DTA_TFACTOR: return "TFACTOR"; + case D3DTA_SPECULAR: return "SPECULAR"; + case D3DTA_TEMP: return "TEMP"; + case D3DTA_CONSTANT: return "CONSTANT"; + default: + return "(D3DTA_?)"; + } +} + +static const char * +nine_D3DTSS_TCI_to_str(DWORD value) +{ + switch (value & 0xf0000) { + case D3DTSS_TCI_PASSTHRU: return "PASSTHRU"; + case D3DTSS_TCI_CAMERASPACENORMAL: return "CAMERASPACENORMAL"; + case D3DTSS_TCI_CAMERASPACEPOSITION: return "CAMERASPACEPOSITION"; + case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR: + return "CAMERASPACEREFLECTIONVECTOR"; + case D3DTSS_TCI_SPHEREMAP: return "SPHEREMAP"; + default: + return "(D3DTSS_TCI_?)"; + } +} + +static const char * +nine_D3DTTFF_to_str(DWORD value) +{ + switch (value) { + case D3DTTFF_DISABLE: return "DISABLE"; + case D3DTTFF_COUNT1: return "COUNT1"; + case D3DTTFF_COUNT2: return "COUNT2"; + case D3DTTFF_COUNT3: return "COUNT3"; + case D3DTTFF_COUNT4: return "COUNT4"; + case D3DTTFF_PROJECTED: return "PROJECTED"; + default: + return "(D3DTTFF_?)"; + } +} + +void +nine_dump_D3DLIGHT9(unsigned ch, const D3DLIGHT9 *lit) +{ + DBG_FLAG(ch, "D3DLIGHT9(%p):\n" + "Type: %s\n" + "Diffuse: (%f %f %f %f)\n" + "Specular: (%f %f %f %f)\n" + "Ambient: (%f %f %f %f)\n" + "Position: (%f %f %f)\n" + "Direction: (%f %f %f)\n" + "Range: %f\n" + "Falloff: %f\n" + "Attenuation: %f + %f * d + %f * d^2\n" + "Theta: %f deg\n" + "Phi: %f deg\n", lit, + nine_D3DLIGHTTYPE_to_str(lit->Type), + lit->Diffuse.r,lit->Diffuse.r,lit->Diffuse.g,lit->Diffuse.a, + lit->Specular.r,lit->Specular.r,lit->Specular.g,lit->Specular.a, + lit->Ambient.r,lit->Ambient.r,lit->Ambient.g,lit->Ambient.a, + lit->Position.x,lit->Position.y,lit->Position.z, + lit->Direction.x,lit->Direction.y,lit->Direction.z, + lit->Range,lit->Falloff, + lit->Attenuation0,lit->Attenuation1,lit->Attenuation2, + lit->Theta * 360.0f / M_PI,lit->Phi * 360.0f / M_PI); +} + +void +nine_dump_D3DMATERIAL9(unsigned ch, const D3DMATERIAL9 *mat) +{ + DBG_FLAG(ch, "D3DMATERIAL9(%p):\n" + "Diffuse: (%f %f %f %f)\n" + "Specular: (%f %f %f %f)\n" + "Ambient: (%f %f %f %f)\n" + "Emissive: (%f %f %f %f)\n" + "Power: %f\n", mat, + mat->Diffuse.r,mat->Diffuse.r,mat->Diffuse.g,mat->Diffuse.a, + mat->Specular.r,mat->Specular.r,mat->Specular.g,mat->Specular.a, + mat->Ambient.r,mat->Ambient.r,mat->Ambient.g,mat->Ambient.a, + mat->Emissive.r,mat->Emissive.r,mat->Emissive.g,mat->Emissive.a, + mat->Power); +} + +void +nine_dump_D3DTSS_value(unsigned ch, D3DTEXTURESTAGESTATETYPE type, DWORD value) +{ + float rgba[4]; + + switch (type) { + case D3DTSS_COLOROP: + case D3DTSS_ALPHAOP: + DBG_FLAG(ch, "D3DTSS_%s = %s\n", + nine_D3DTSS_to_str(type), nine_D3DTOP_to_str(value)); + break; + case D3DTSS_COLORARG0: + case D3DTSS_COLORARG1: + case D3DTSS_COLORARG2: + case D3DTSS_ALPHAARG0: + case D3DTSS_ALPHAARG1: + case D3DTSS_ALPHAARG2: + case D3DTSS_RESULTARG: + DBG_FLAG(ch, "D3DTSS_%s = %s%s%s\n", + nine_D3DTSS_to_str(type), + (value & D3DTA_COMPLEMENT) ? "COMPLEMENT " : "", + (value & D3DTA_ALPHAREPLICATE) ? "ALPHAREPLICATE " : "", + nine_D3DTA_to_str(value)); + break; + case D3DTSS_BUMPENVMAT00: + case D3DTSS_BUMPENVMAT01: + case D3DTSS_BUMPENVMAT10: + case D3DTSS_BUMPENVMAT11: + case D3DTSS_BUMPENVLSCALE: + case D3DTSS_BUMPENVLOFFSET: + DBG_FLAG(ch, "D3DTSS_%s = %f\n", + nine_D3DTSS_to_str(type), asfloat(value)); + break; + case D3DTSS_TEXCOORDINDEX: + DBG_FLAG(ch, "D3DTSS_TEXCOORDINDEX = %s %u\n", + nine_D3DTSS_TCI_to_str(value), + value & 0xffff); + break; + case D3DTSS_TEXTURETRANSFORMFLAGS: + DBG_FLAG(ch, "D3DTSS_TEXTURETRANSFORMFLAGS = %s\n", + nine_D3DTTFF_to_str(value)); + break; + case D3DTSS_CONSTANT: + d3dcolor_to_rgba(rgba, value); + DBG_FLAG(ch, "D3DTSS_CONSTANT = %f %f %f %F\n", + rgba[0],rgba[1],rgba[2],rgba[3]); + break; + default: + DBG_FLAG(ch, "D3DTSS_? = 0x%08x\n", value); + break; + } +} + +void +nine_dump_D3DADAPTER_IDENTIFIER9(unsigned ch, const D3DADAPTER_IDENTIFIER9 *id) +{ + DBG_FLAG(ch, "D3DADAPTER_IDENTIFIER9(%p):\n" + "Driver: %s\n" + "Description: %s\n" + "DeviceName: %s\n" + "DriverVersion: %08x.%08x\n" + "VendorId: %x\n" + "DeviceId: %x\n" + "SubSysId: %x\n" + "Revision: %u\n" + "GUID: %08x.%04x.%04x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x\n" + "WHQLLevel: %u\n", id, id->Driver, id->Description, + id->DeviceName, + id->DriverVersionLowPart, id->DriverVersionHighPart, + id->VendorId, id->DeviceId, id->SubSysId, + id->Revision, + id->DeviceIdentifier.Data1, + id->DeviceIdentifier.Data2, + id->DeviceIdentifier.Data3, + id->DeviceIdentifier.Data4[0], + id->DeviceIdentifier.Data4[1], + id->DeviceIdentifier.Data4[2], + id->DeviceIdentifier.Data4[3], + id->DeviceIdentifier.Data4[4], + id->DeviceIdentifier.Data4[5], + id->DeviceIdentifier.Data4[6], + id->DeviceIdentifier.Data4[7], + id->WHQLLevel); +} + +#define C2S(args...) p += snprintf(&s[p],c-p,args) + +#define CAP_CASE(m,p,n) \ + do { \ + if (caps->m & p##_##n) \ + C2S(" "#n); \ + else \ + C2S(" ("#n")"); \ + } while(0) + +void +nine_dump_D3DCAPS9(unsigned ch, const D3DCAPS9 *caps) +{ + const int c = 1 << 17; + int p = 0; + char *s = (char *)MALLOC(c); + + if (!s) { + DBG_FLAG(ch, "D3DCAPS9(%p): (out of memory)\n", caps); + return; + } + + C2S("DeviceType: %s\n", nine_D3DDEVTYPE_to_str(caps->DeviceType)); + + C2S("AdapterOrdinal: %u\nCaps:", caps->AdapterOrdinal); + if (caps->Caps & 0x20000) + C2S(" READ_SCANLINE"); + if (caps->Caps & ~0x20000) + C2S(" %x", caps->Caps & ~0x20000); + + C2S("\nCaps2:"); + CAP_CASE(Caps2, D3DCAPS2, CANAUTOGENMIPMAP); + CAP_CASE(Caps2, D3DCAPS2, CANCALIBRATEGAMMA); + CAP_CASE(Caps2, D3DCAPS2, CANSHARERESOURCE); + CAP_CASE(Caps2, D3DCAPS2, CANMANAGERESOURCE); + CAP_CASE(Caps2, D3DCAPS2, DYNAMICTEXTURES); + CAP_CASE(Caps2, D3DCAPS2, FULLSCREENGAMMA); + + C2S("\nCaps3:"); + CAP_CASE(Caps3, D3DCAPS3, ALPHA_FULLSCREEN_FLIP_OR_DISCARD); + CAP_CASE(Caps3, D3DCAPS3, COPY_TO_VIDMEM); + CAP_CASE(Caps3, D3DCAPS3, COPY_TO_SYSTEMMEM); + CAP_CASE(Caps3, D3DCAPS3, DXVAHD); + CAP_CASE(Caps3, D3DCAPS3, LINEAR_TO_SRGB_PRESENTATION); + + C2S("\nPresentationIntervals:"); + CAP_CASE(PresentationIntervals, D3DPRESENT_INTERVAL, ONE); + CAP_CASE(PresentationIntervals, D3DPRESENT_INTERVAL, TWO); + CAP_CASE(PresentationIntervals, D3DPRESENT_INTERVAL, THREE); + CAP_CASE(PresentationIntervals, D3DPRESENT_INTERVAL, FOUR); + CAP_CASE(PresentationIntervals, D3DPRESENT_INTERVAL, IMMEDIATE); + + C2S("\nCursorCaps:"); + CAP_CASE(CursorCaps, D3DCURSORCAPS, COLOR); + CAP_CASE(CursorCaps, D3DCURSORCAPS, LOWRES); + + C2S("\nDevCaps:"); + CAP_CASE(DevCaps, D3DDEVCAPS, CANBLTSYSTONONLOCAL); + CAP_CASE(DevCaps, D3DDEVCAPS, CANRENDERAFTERFLIP); + CAP_CASE(DevCaps, D3DDEVCAPS, DRAWPRIMITIVES2); + CAP_CASE(DevCaps, D3DDEVCAPS, DRAWPRIMITIVES2EX); + CAP_CASE(DevCaps, D3DDEVCAPS, DRAWPRIMTLVERTEX); + CAP_CASE(DevCaps, D3DDEVCAPS, EXECUTESYSTEMMEMORY); + CAP_CASE(DevCaps, D3DDEVCAPS, EXECUTEVIDEOMEMORY); + CAP_CASE(DevCaps, D3DDEVCAPS, HWRASTERIZATION); + CAP_CASE(DevCaps, D3DDEVCAPS, HWTRANSFORMANDLIGHT); + CAP_CASE(DevCaps, D3DDEVCAPS, NPATCHES); + CAP_CASE(DevCaps, D3DDEVCAPS, PUREDEVICE); + CAP_CASE(DevCaps, D3DDEVCAPS, QUINTICRTPATCHES); + CAP_CASE(DevCaps, D3DDEVCAPS, RTPATCHES); + CAP_CASE(DevCaps, D3DDEVCAPS, RTPATCHHANDLEZERO); + CAP_CASE(DevCaps, D3DDEVCAPS, SEPARATETEXTUREMEMORIES); + CAP_CASE(DevCaps, D3DDEVCAPS, TEXTURENONLOCALVIDMEM); + CAP_CASE(DevCaps, D3DDEVCAPS, TEXTURESYSTEMMEMORY); + CAP_CASE(DevCaps, D3DDEVCAPS, TEXTUREVIDEOMEMORY); + CAP_CASE(DevCaps, D3DDEVCAPS, TLVERTEXSYSTEMMEMORY); + CAP_CASE(DevCaps, D3DDEVCAPS, TLVERTEXVIDEOMEMORY); + + C2S("\nPrimitiveMiscCaps:"); + CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, MASKZ); + CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, CULLNONE); + CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, CULLCW); + CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, CULLCCW); + CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, COLORWRITEENABLE); + CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, CLIPPLANESCALEDPOINTS); + CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, CLIPTLVERTS); + CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, TSSARGTEMP); + CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, BLENDOP); + CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, NULLREFERENCE); + CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, INDEPENDENTWRITEMASKS); + CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, PERSTAGECONSTANT); + CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, POSTBLENDSRGBCONVERT); + CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, FOGANDSPECULARALPHA); + CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, SEPARATEALPHABLEND); + CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, MRTINDEPENDENTBITDEPTHS); + CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, MRTPOSTPIXELSHADERBLENDING); + CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, FOGVERTEXCLAMPED); + + C2S("\nRasterCaps:"); + CAP_CASE(RasterCaps, D3DPRASTERCAPS, ANISOTROPY); + CAP_CASE(RasterCaps, D3DPRASTERCAPS, COLORPERSPECTIVE); + CAP_CASE(RasterCaps, D3DPRASTERCAPS, DITHER); + CAP_CASE(RasterCaps, D3DPRASTERCAPS, DEPTHBIAS); + CAP_CASE(RasterCaps, D3DPRASTERCAPS, FOGRANGE); + CAP_CASE(RasterCaps, D3DPRASTERCAPS, FOGTABLE); + CAP_CASE(RasterCaps, D3DPRASTERCAPS, FOGVERTEX); + CAP_CASE(RasterCaps, D3DPRASTERCAPS, MIPMAPLODBIAS); + CAP_CASE(RasterCaps, D3DPRASTERCAPS, MULTISAMPLE_TOGGLE); + CAP_CASE(RasterCaps, D3DPRASTERCAPS, SCISSORTEST); + CAP_CASE(RasterCaps, D3DPRASTERCAPS, SLOPESCALEDEPTHBIAS); + CAP_CASE(RasterCaps, D3DPRASTERCAPS, WBUFFER); + CAP_CASE(RasterCaps, D3DPRASTERCAPS, WFOG); + CAP_CASE(RasterCaps, D3DPRASTERCAPS, ZBUFFERLESSHSR); + CAP_CASE(RasterCaps, D3DPRASTERCAPS, ZFOG); + CAP_CASE(RasterCaps, D3DPRASTERCAPS, ZTEST); + + C2S("\nZCmpCaps:"); + CAP_CASE(ZCmpCaps, D3DPCMPCAPS, ALWAYS); + CAP_CASE(ZCmpCaps, D3DPCMPCAPS, EQUAL); + CAP_CASE(ZCmpCaps, D3DPCMPCAPS, GREATER); + CAP_CASE(ZCmpCaps, D3DPCMPCAPS, GREATEREQUAL); + CAP_CASE(ZCmpCaps, D3DPCMPCAPS, LESS); + CAP_CASE(ZCmpCaps, D3DPCMPCAPS, LESSEQUAL); + CAP_CASE(ZCmpCaps, D3DPCMPCAPS, NEVER); + CAP_CASE(ZCmpCaps, D3DPCMPCAPS, NOTEQUAL); + + C2S("\nSrcBlendCaps"); + CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, BLENDFACTOR); + CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, BOTHINVSRCALPHA); + CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, BOTHSRCALPHA); + CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, DESTALPHA); + CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, DESTCOLOR); + CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, INVDESTALPHA); + CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, INVDESTCOLOR); + CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, INVSRCALPHA); + CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, INVSRCCOLOR); + CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, INVSRCCOLOR2); + CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, ONE); + CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, SRCALPHA); + CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, SRCALPHASAT); + CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, SRCCOLOR); + CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, SRCCOLOR2); + CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, ZERO); + + C2S("\nDestBlendCaps"); + CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, BLENDFACTOR); + CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, BOTHINVSRCALPHA); + CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, BOTHSRCALPHA); + CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, DESTALPHA); + CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, DESTCOLOR); + CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, INVDESTALPHA); + CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, INVDESTCOLOR); + CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, INVSRCALPHA); + CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, INVSRCCOLOR); + CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, INVSRCCOLOR2); + CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, ONE); + CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, SRCALPHA); + CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, SRCALPHASAT); + CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, SRCCOLOR); + CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, SRCCOLOR2); + CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, ZERO); + + C2S("\nAlphaCmpCaps:"); + CAP_CASE(AlphaCmpCaps, D3DPCMPCAPS, ALWAYS); + CAP_CASE(AlphaCmpCaps, D3DPCMPCAPS, EQUAL); + CAP_CASE(AlphaCmpCaps, D3DPCMPCAPS, GREATER); + CAP_CASE(AlphaCmpCaps, D3DPCMPCAPS, GREATEREQUAL); + CAP_CASE(AlphaCmpCaps, D3DPCMPCAPS, LESS); + CAP_CASE(AlphaCmpCaps, D3DPCMPCAPS, LESSEQUAL); + CAP_CASE(AlphaCmpCaps, D3DPCMPCAPS, NEVER); + CAP_CASE(AlphaCmpCaps, D3DPCMPCAPS, NOTEQUAL); + + C2S("\nShadeCaps:"); + CAP_CASE(ShadeCaps, D3DPSHADECAPS, ALPHAGOURAUDBLEND); + CAP_CASE(ShadeCaps, D3DPSHADECAPS, COLORGOURAUDRGB); + CAP_CASE(ShadeCaps, D3DPSHADECAPS, FOGGOURAUD); + CAP_CASE(ShadeCaps, D3DPSHADECAPS, SPECULARGOURAUDRGB); + + C2S("\nTextureCaps:"); + CAP_CASE(TextureCaps, D3DPTEXTURECAPS, ALPHA); + CAP_CASE(TextureCaps, D3DPTEXTURECAPS, ALPHAPALETTE); + CAP_CASE(TextureCaps, D3DPTEXTURECAPS, CUBEMAP); + CAP_CASE(TextureCaps, D3DPTEXTURECAPS, CUBEMAP_POW2); + CAP_CASE(TextureCaps, D3DPTEXTURECAPS, MIPCUBEMAP); + CAP_CASE(TextureCaps, D3DPTEXTURECAPS, MIPMAP); + CAP_CASE(TextureCaps, D3DPTEXTURECAPS, MIPVOLUMEMAP); + CAP_CASE(TextureCaps, D3DPTEXTURECAPS, NONPOW2CONDITIONAL); + CAP_CASE(TextureCaps, D3DPTEXTURECAPS, NOPROJECTEDBUMPENV); + CAP_CASE(TextureCaps, D3DPTEXTURECAPS, PERSPECTIVE); + CAP_CASE(TextureCaps, D3DPTEXTURECAPS, POW2); + CAP_CASE(TextureCaps, D3DPTEXTURECAPS, PROJECTED); + CAP_CASE(TextureCaps, D3DPTEXTURECAPS, SQUAREONLY); + CAP_CASE(TextureCaps, D3DPTEXTURECAPS, TEXREPEATNOTSCALEDBYSIZE); + CAP_CASE(TextureCaps, D3DPTEXTURECAPS, VOLUMEMAP); + CAP_CASE(TextureCaps, D3DPTEXTURECAPS, VOLUMEMAP_POW2); + + C2S("\nTextureFilterCaps:"); + /* CAP_CASE(TextureFilterCaps, D3DPTFILTERCAPS, CONVOLUTIONMONO); */ + CAP_CASE(TextureFilterCaps, D3DPTFILTERCAPS, MAGFPOINT); + CAP_CASE(TextureFilterCaps, D3DPTFILTERCAPS, MAGFLINEAR); + CAP_CASE(TextureFilterCaps, D3DPTFILTERCAPS, MAGFANISOTROPIC); + CAP_CASE(TextureFilterCaps, D3DPTFILTERCAPS, MAGFPYRAMIDALQUAD); + CAP_CASE(TextureFilterCaps, D3DPTFILTERCAPS, MAGFGAUSSIANQUAD); + CAP_CASE(TextureFilterCaps, D3DPTFILTERCAPS, MINFPOINT); + CAP_CASE(TextureFilterCaps, D3DPTFILTERCAPS, MINFLINEAR); + CAP_CASE(TextureFilterCaps, D3DPTFILTERCAPS, MINFANISOTROPIC); + CAP_CASE(TextureFilterCaps, D3DPTFILTERCAPS, MINFPYRAMIDALQUAD); + CAP_CASE(TextureFilterCaps, D3DPTFILTERCAPS, MINFGAUSSIANQUAD); + CAP_CASE(TextureFilterCaps, D3DPTFILTERCAPS, MIPFPOINT); + CAP_CASE(TextureFilterCaps, D3DPTFILTERCAPS, MIPFLINEAR); + + C2S("\nCubeTextureFilterCaps:"); + /* CAP_CASE(CubeTextureFilterCaps, D3DPTFILTERCAPS, CONVOLUTIONMONO); */ + CAP_CASE(CubeTextureFilterCaps, D3DPTFILTERCAPS, MAGFPOINT); + CAP_CASE(CubeTextureFilterCaps, D3DPTFILTERCAPS, MAGFLINEAR); + CAP_CASE(CubeTextureFilterCaps, D3DPTFILTERCAPS, MAGFANISOTROPIC); + CAP_CASE(CubeTextureFilterCaps, D3DPTFILTERCAPS, MAGFPYRAMIDALQUAD); + CAP_CASE(CubeTextureFilterCaps, D3DPTFILTERCAPS, MAGFGAUSSIANQUAD); + CAP_CASE(CubeTextureFilterCaps, D3DPTFILTERCAPS, MINFPOINT); + CAP_CASE(CubeTextureFilterCaps, D3DPTFILTERCAPS, MINFLINEAR); + CAP_CASE(CubeTextureFilterCaps, D3DPTFILTERCAPS, MINFANISOTROPIC); + CAP_CASE(CubeTextureFilterCaps, D3DPTFILTERCAPS, MINFPYRAMIDALQUAD); + CAP_CASE(CubeTextureFilterCaps, D3DPTFILTERCAPS, MINFGAUSSIANQUAD); + CAP_CASE(CubeTextureFilterCaps, D3DPTFILTERCAPS, MIPFPOINT); + CAP_CASE(CubeTextureFilterCaps, D3DPTFILTERCAPS, MIPFLINEAR); + + C2S("\nVolumeTextureFilterCaps:"); + /* CAP_CASE(VolumeTextureFilterCaps, D3DPTFILTERCAPS, CONVOLUTIONMONO); */ + CAP_CASE(VolumeTextureFilterCaps, D3DPTFILTERCAPS, MAGFPOINT); + CAP_CASE(VolumeTextureFilterCaps, D3DPTFILTERCAPS, MAGFLINEAR); + CAP_CASE(VolumeTextureFilterCaps, D3DPTFILTERCAPS, MAGFANISOTROPIC); + CAP_CASE(VolumeTextureFilterCaps, D3DPTFILTERCAPS, MAGFPYRAMIDALQUAD); + CAP_CASE(VolumeTextureFilterCaps, D3DPTFILTERCAPS, MAGFGAUSSIANQUAD); + CAP_CASE(VolumeTextureFilterCaps, D3DPTFILTERCAPS, MINFPOINT); + CAP_CASE(VolumeTextureFilterCaps, D3DPTFILTERCAPS, MINFLINEAR); + CAP_CASE(VolumeTextureFilterCaps, D3DPTFILTERCAPS, MINFANISOTROPIC); + CAP_CASE(VolumeTextureFilterCaps, D3DPTFILTERCAPS, MINFPYRAMIDALQUAD); + CAP_CASE(VolumeTextureFilterCaps, D3DPTFILTERCAPS, MINFGAUSSIANQUAD); + CAP_CASE(VolumeTextureFilterCaps, D3DPTFILTERCAPS, MIPFPOINT); + CAP_CASE(VolumeTextureFilterCaps, D3DPTFILTERCAPS, MIPFLINEAR); + + C2S("\nTextureAddressCaps:"); + CAP_CASE(TextureAddressCaps, D3DPTADDRESSCAPS, BORDER); + CAP_CASE(TextureAddressCaps, D3DPTADDRESSCAPS, CLAMP); + CAP_CASE(TextureAddressCaps, D3DPTADDRESSCAPS, INDEPENDENTUV); + CAP_CASE(TextureAddressCaps, D3DPTADDRESSCAPS, MIRROR); + CAP_CASE(TextureAddressCaps, D3DPTADDRESSCAPS, MIRRORONCE); + CAP_CASE(TextureAddressCaps, D3DPTADDRESSCAPS, WRAP); + + C2S("\nVolumeTextureAddressCaps:"); + CAP_CASE(VolumeTextureAddressCaps, D3DPTADDRESSCAPS, BORDER); + CAP_CASE(VolumeTextureAddressCaps, D3DPTADDRESSCAPS, CLAMP); + CAP_CASE(VolumeTextureAddressCaps, D3DPTADDRESSCAPS, INDEPENDENTUV); + CAP_CASE(VolumeTextureAddressCaps, D3DPTADDRESSCAPS, MIRROR); + CAP_CASE(VolumeTextureAddressCaps, D3DPTADDRESSCAPS, MIRRORONCE); + CAP_CASE(VolumeTextureAddressCaps, D3DPTADDRESSCAPS, WRAP); + + C2S("\nLineCaps:"); + CAP_CASE(LineCaps, D3DLINECAPS, ALPHACMP); + CAP_CASE(LineCaps, D3DLINECAPS, ANTIALIAS); + CAP_CASE(LineCaps, D3DLINECAPS, BLEND); + CAP_CASE(LineCaps, D3DLINECAPS, FOG); + CAP_CASE(LineCaps, D3DLINECAPS, TEXTURE); + CAP_CASE(LineCaps, D3DLINECAPS, ZTEST); + + C2S("\nMaxTextureWidth: %u", caps->MaxTextureWidth); + C2S("\nMaxTextureHeight: %u", caps->MaxTextureHeight); + C2S("\nMaxVolumeExtent: %u", caps->MaxVolumeExtent); + C2S("\nMaxTextureRepeat: %u", caps->MaxTextureRepeat); + C2S("\nMaxTextureAspectRatio: %u", caps->MaxTextureAspectRatio); + C2S("\nMaxAnisotropy: %u", caps->MaxAnisotropy); + C2S("\nMaxVertexW: %f", caps->MaxVertexW); + + C2S("\nGuardBandLef,Top,Right,Bottom: %f %f %f %f", + caps->GuardBandLeft, caps->GuardBandTop, + caps->GuardBandRight, caps->GuardBandBottom); + + C2S("\nExtentsAdjust: %f", caps->ExtentsAdjust); + + C2S("\nStencilCaps:"); + CAP_CASE(StencilCaps, D3DSTENCILCAPS, KEEP); + CAP_CASE(StencilCaps, D3DSTENCILCAPS, ZERO); + CAP_CASE(StencilCaps, D3DSTENCILCAPS, REPLACE); + CAP_CASE(StencilCaps, D3DSTENCILCAPS, INCRSAT); + CAP_CASE(StencilCaps, D3DSTENCILCAPS, DECRSAT); + CAP_CASE(StencilCaps, D3DSTENCILCAPS, INVERT); + CAP_CASE(StencilCaps, D3DSTENCILCAPS, INCR); + CAP_CASE(StencilCaps, D3DSTENCILCAPS, DECR); + CAP_CASE(StencilCaps, D3DSTENCILCAPS, TWOSIDED); + + C2S("\nFVFCaps:"); + CAP_CASE(FVFCaps, D3DFVFCAPS, DONOTSTRIPELEMENTS); + CAP_CASE(FVFCaps, D3DFVFCAPS, PSIZE); + CAP_CASE(FVFCaps, D3DFVFCAPS, TEXCOORDCOUNTMASK); + + C2S("\nTextureOpCaps:"); + CAP_CASE(TextureOpCaps, D3DTEXOPCAPS, ADD); + CAP_CASE(TextureOpCaps, D3DTEXOPCAPS, ADDSIGNED); + C2S(" ..."); + + C2S("\nMaxTextureBlendStages: %u", caps->MaxTextureBlendStages); + C2S("\nMaxSimultaneousTextures: %u", caps->MaxTextureBlendStages); + + C2S("\nVertexProcessingCaps:"); + CAP_CASE(VertexProcessingCaps, D3DVTXPCAPS, DIRECTIONALLIGHTS); + CAP_CASE(VertexProcessingCaps, D3DVTXPCAPS, LOCALVIEWER); + CAP_CASE(VertexProcessingCaps, D3DVTXPCAPS, MATERIALSOURCE7); + CAP_CASE(VertexProcessingCaps, D3DVTXPCAPS, NO_TEXGEN_NONLOCALVIEWER); + CAP_CASE(VertexProcessingCaps, D3DVTXPCAPS, POSITIONALLIGHTS); + CAP_CASE(VertexProcessingCaps, D3DVTXPCAPS, TEXGEN); + CAP_CASE(VertexProcessingCaps, D3DVTXPCAPS, TEXGEN_SPHEREMAP); + CAP_CASE(VertexProcessingCaps, D3DVTXPCAPS, TWEENING); + + C2S("\nMaxActiveLights: %u", caps->MaxActiveLights); + C2S("\nMaxUserClipPlanes: %u", caps->MaxUserClipPlanes); + C2S("\nMaxVertexBlendMatrices: %u", caps->MaxVertexBlendMatrices); + C2S("\nMaxVertexBlendMatrixIndex: %u", caps->MaxVertexBlendMatrixIndex); + C2S("\nMaxPointSize: %f", caps->MaxPointSize); + C2S("\nMaxPrimitiveCount: 0x%x", caps->MaxPrimitiveCount); + C2S("\nMaxVertexIndex: 0x%x", caps->MaxVertexIndex); + C2S("\nMaxStreams: %u", caps->MaxStreams); + C2S("\nMaxStreamStride: 0x%x", caps->MaxStreamStride); + + C2S("\nVertexShaderVersion: %08x", caps->VertexShaderVersion); + C2S("\nMaxVertexShaderConst: %u", caps->MaxVertexShaderConst); + C2S("\nPixelShaderVersion: %08x", caps->PixelShaderVersion); + C2S("\nPixelShader1xMaxValue: %f", caps->PixelShader1xMaxValue); + + DBG_FLAG(ch, "D3DCAPS9(%p) part 1:\n%s\n", caps, s); + p = 0; + + C2S("DevCaps2:"); + CAP_CASE(DevCaps2, D3DDEVCAPS2, ADAPTIVETESSRTPATCH); + CAP_CASE(DevCaps2, D3DDEVCAPS2, ADAPTIVETESSNPATCH); + CAP_CASE(DevCaps2, D3DDEVCAPS2, CAN_STRETCHRECT_FROM_TEXTURES); + CAP_CASE(DevCaps2, D3DDEVCAPS2, DMAPNPATCH); + CAP_CASE(DevCaps2, D3DDEVCAPS2, PRESAMPLEDDMAPNPATCH); + CAP_CASE(DevCaps2, D3DDEVCAPS2, STREAMOFFSET); + CAP_CASE(DevCaps2, D3DDEVCAPS2, VERTEXELEMENTSCANSHARESTREAMOFFSET); + + C2S("\nMasterAdapterOrdinal: %u", caps->MasterAdapterOrdinal); + C2S("\nAdapterOrdinalInGroup: %u", caps->AdapterOrdinalInGroup); + C2S("\nNumberOfAdaptersInGroup: %u", caps->NumberOfAdaptersInGroup); + + C2S("\nDeclTypes:"); + CAP_CASE(DeclTypes, D3DDTCAPS, UBYTE4); + CAP_CASE(DeclTypes, D3DDTCAPS, UBYTE4N); + CAP_CASE(DeclTypes, D3DDTCAPS, SHORT2N); + CAP_CASE(DeclTypes, D3DDTCAPS, SHORT4N); + CAP_CASE(DeclTypes, D3DDTCAPS, USHORT2N); + CAP_CASE(DeclTypes, D3DDTCAPS, USHORT4N); + CAP_CASE(DeclTypes, D3DDTCAPS, UDEC3); + CAP_CASE(DeclTypes, D3DDTCAPS, DEC3N); + CAP_CASE(DeclTypes, D3DDTCAPS, FLOAT16_2); + CAP_CASE(DeclTypes, D3DDTCAPS, FLOAT16_4); + + C2S("\nNumSimultaneousRTs: %u", caps->NumSimultaneousRTs); + + C2S("\nStretchRectFilterCaps:"); + CAP_CASE(StretchRectFilterCaps, D3DPTFILTERCAPS, MINFPOINT); + CAP_CASE(StretchRectFilterCaps, D3DPTFILTERCAPS, MINFLINEAR); + CAP_CASE(StretchRectFilterCaps, D3DPTFILTERCAPS, MAGFPOINT); + CAP_CASE(StretchRectFilterCaps, D3DPTFILTERCAPS, MAGFLINEAR); + + C2S("\nVS20Caps.Caps: Predication=%s", caps->VS20Caps.Caps ? "yes" : "no"); + C2S("\nVS20Caps.DynamicFlowControlDepth: %u", caps->VS20Caps.DynamicFlowControlDepth); + C2S("\nVS20Caps.NumTemps: %u", caps->VS20Caps.NumTemps); + C2S("\nVS20Caps.StaticFlowControlDepth: %u", caps->VS20Caps.StaticFlowControlDepth); + + C2S("\nPS20Caps.Caps: Predication=%s", caps->VS20Caps.Caps ? "yes" : "no"); + C2S("\nPS20Caps.DynamicFlowControlDepth: %u", caps->PS20Caps.DynamicFlowControlDepth); + C2S("\nPS20Caps.NumTemps: %u", caps->PS20Caps.NumTemps); + C2S("\nPS20Caps.StaticFlowControlDepth: %u", caps->PS20Caps.StaticFlowControlDepth); + C2S("\nPS20Caps.NumInstructionSlots: %u", caps->PS20Caps.NumInstructionSlots); + + C2S("\nVertexTextureFilterCaps"); + /* CAP_CASE(VertexTextureFilterCaps, D3DPTFILTERCAPS, CONVOLUTIONMONO); */ + CAP_CASE(VertexTextureFilterCaps, D3DPTFILTERCAPS, MAGFPOINT); + CAP_CASE(VertexTextureFilterCaps, D3DPTFILTERCAPS, MAGFLINEAR); + CAP_CASE(VertexTextureFilterCaps, D3DPTFILTERCAPS, MAGFANISOTROPIC); + CAP_CASE(VertexTextureFilterCaps, D3DPTFILTERCAPS, MAGFPYRAMIDALQUAD); + CAP_CASE(VertexTextureFilterCaps, D3DPTFILTERCAPS, MAGFGAUSSIANQUAD); + CAP_CASE(VertexTextureFilterCaps, D3DPTFILTERCAPS, MINFPOINT); + CAP_CASE(VertexTextureFilterCaps, D3DPTFILTERCAPS, MINFLINEAR); + CAP_CASE(VertexTextureFilterCaps, D3DPTFILTERCAPS, MINFANISOTROPIC); + CAP_CASE(VertexTextureFilterCaps, D3DPTFILTERCAPS, MINFPYRAMIDALQUAD); + CAP_CASE(VertexTextureFilterCaps, D3DPTFILTERCAPS, MINFGAUSSIANQUAD); + CAP_CASE(VertexTextureFilterCaps, D3DPTFILTERCAPS, MIPFPOINT); + CAP_CASE(VertexTextureFilterCaps, D3DPTFILTERCAPS, MIPFLINEAR); + + C2S("\nMaxVShaderInstructionsExecuted: %u", caps->MaxVShaderInstructionsExecuted); + C2S("\nMaxPShaderInstructionsExecuted: %u", caps->MaxPShaderInstructionsExecuted); + C2S("\nMaxVertexShader30InstructionSlots: %u >= 512", caps->MaxVertexShader30InstructionSlots); + C2S("\nMaxPixelShader30InstructionSlots: %u >= 512", caps->MaxPixelShader30InstructionSlots); + + DBG_FLAG(ch, "D3DCAPS9(%p) part 2:\n%s\n", caps, s); + + FREE(s); +} + +#endif /* DEBUG || !NDEBUG */ diff --git a/src/gallium/frontends/nine/nine_dump.h b/src/gallium/frontends/nine/nine_dump.h new file mode 100644 index 00000000000..72342557d77 --- /dev/null +++ b/src/gallium/frontends/nine/nine_dump.h @@ -0,0 +1,52 @@ + +#ifndef _NINE_DUMP_H_ +#define _NINE_DUMP_H_ + +#include "d3d9types.h" +#include "d3d9caps.h" + +const char *nine_D3DDEVTYPE_to_str(D3DDEVTYPE); +const char *nine_D3DQUERYTYPE_to_str(D3DQUERYTYPE); +const char *nine_D3DTSS_to_str(D3DTEXTURESTAGESTATETYPE); +const char *nine_D3DTOP_to_str(D3DTEXTUREOP); +const char *nine_D3DPOOL_to_str(D3DPOOL); +const char *nine_D3DRTYPE_to_str(D3DRESOURCETYPE); +const char *nine_D3DUSAGE_to_str(DWORD); +const char *nine_D3DPRESENTFLAG_to_str(DWORD); +const char *nine_D3DLOCK_to_str(DWORD); +const char *nine_D3DSAMP_to_str(DWORD); + +#if defined(DEBUG) || !defined(NDEBUG) + +void +nine_dump_D3DADAPTER_IDENTIFIER9(unsigned, const D3DADAPTER_IDENTIFIER9 *); +void +nine_dump_D3DCAPS9(unsigned, const D3DCAPS9 *); +void +nine_dump_D3DLIGHT9(unsigned, const D3DLIGHT9 *); +void +nine_dump_D3DMATERIAL9(unsigned, const D3DMATERIAL9 *); +void +nine_dump_D3DTSS_value(unsigned, D3DTEXTURESTAGESTATETYPE, DWORD); + +#else /* !DEBUG && NDEBUG */ + +static inline void +nine_dump_D3DADAPTER_IDENTIFIER9(unsigned ch, const D3DADAPTER_IDENTIFIER9 *id) +{ } +static inline void +nine_dump_D3DCAPS9(unsigned ch, const D3DCAPS9 *caps) +{ } +static inline void +nine_dump_D3DLIGHT9(unsigned ch, const D3DLIGHT9 *light) +{ } +static inline void +nine_dump_D3DMATERIAL9(unsigned ch, const D3DMATERIAL9 *mat) +{ } +static inline void +nine_dump_D3DTSS_value(unsigned ch, D3DTEXTURESTAGESTATETYPE tss, DWORD value) +{ } + +#endif /* DEBUG || !NDEBUG */ + +#endif /* _NINE_DUMP_H_H_ */ diff --git a/src/gallium/frontends/nine/nine_ff.c b/src/gallium/frontends/nine/nine_ff.c new file mode 100644 index 00000000000..16d0ab2ab5c --- /dev/null +++ b/src/gallium/frontends/nine/nine_ff.c @@ -0,0 +1,2500 @@ + +/* FF is big and ugly so feel free to write lines as long as you like. + * Aieeeeeeeee ! + * + * Let me make that clearer: + * Aieeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee ! !! !!! + */ + +#include "device9.h" +#include "basetexture9.h" +#include "vertexdeclaration9.h" +#include "vertexshader9.h" +#include "pixelshader9.h" +#include "nine_ff.h" +#include "nine_defines.h" +#include "nine_helpers.h" +#include "nine_pipe.h" +#include "nine_dump.h" + +#include "pipe/p_context.h" +#include "tgsi/tgsi_ureg.h" +#include "tgsi/tgsi_dump.h" +#include "util/u_box.h" +#include "util/u_hash_table.h" +#include "util/u_upload_mgr.h" + +#define DBG_CHANNEL DBG_FF + +#define NINE_FF_NUM_VS_CONST 196 +#define NINE_FF_NUM_PS_CONST 24 + +struct fvec4 +{ + float x, y, z, w; +}; + +struct nine_ff_vs_key +{ + union { + struct { + uint32_t position_t : 1; + uint32_t lighting : 1; + uint32_t darkness : 1; /* lighting enabled but no active lights */ + uint32_t localviewer : 1; + uint32_t vertexpointsize : 1; + uint32_t pointscale : 1; + uint32_t vertexblend : 3; + uint32_t vertexblend_indexed : 1; + uint32_t vertextween : 1; + uint32_t mtl_diffuse : 2; /* 0 = material, 1 = color1, 2 = color2 */ + uint32_t mtl_ambient : 2; + uint32_t mtl_specular : 2; + uint32_t mtl_emissive : 2; + uint32_t fog_mode : 2; + uint32_t fog_range : 1; + uint32_t color0in_one : 1; + uint32_t color1in_zero : 1; + uint32_t has_normal : 1; + uint32_t fog : 1; + uint32_t normalizenormals : 1; + uint32_t ucp : 1; + uint32_t pad1 : 4; + uint32_t tc_dim_input: 16; /* 8 * 2 bits */ + uint32_t pad2 : 16; + uint32_t tc_dim_output: 24; /* 8 * 3 bits */ + uint32_t pad3 : 8; + uint32_t tc_gen : 24; /* 8 * 3 bits */ + uint32_t pad4 : 8; + uint32_t tc_idx : 24; + uint32_t pad5 : 8; + uint32_t passthrough; + }; + uint64_t value64[3]; /* don't forget to resize VertexShader9.ff_key */ + uint32_t value32[6]; + }; +}; + +/* Texture stage state: + * + * COLOROP D3DTOP 5 bit + * ALPHAOP D3DTOP 5 bit + * COLORARG0 D3DTA 3 bit + * COLORARG1 D3DTA 3 bit + * COLORARG2 D3DTA 3 bit + * ALPHAARG0 D3DTA 3 bit + * ALPHAARG1 D3DTA 3 bit + * ALPHAARG2 D3DTA 3 bit + * RESULTARG D3DTA 1 bit (CURRENT:0 or TEMP:1) + * TEXCOORDINDEX 0 - 7 3 bit + * =========================== + * 32 bit per stage + */ +struct nine_ff_ps_key +{ + union { + struct { + struct { + uint32_t colorop : 5; + uint32_t alphaop : 5; + uint32_t colorarg0 : 3; + uint32_t colorarg1 : 3; + uint32_t colorarg2 : 3; + uint32_t alphaarg0 : 3; + uint32_t alphaarg1 : 3; + uint32_t alphaarg2 : 3; + uint32_t resultarg : 1; /* CURRENT:0 or TEMP:1 */ + uint32_t textarget : 2; /* 1D/2D/3D/CUBE */ + uint32_t pad : 1; + /* that's 32 bit exactly */ + } ts[8]; + uint32_t projected : 16; + uint32_t fog : 1; /* for vFog coming from VS */ + uint32_t fog_mode : 2; + uint32_t fog_source : 1; /* 0: Z, 1: W */ + uint32_t specular : 1; + uint32_t pad1 : 11; /* 9 32-bit words with this */ + uint8_t colorarg_b4[3]; + uint8_t colorarg_b5[3]; + uint8_t alphaarg_b4[3]; /* 11 32-bit words plus a byte */ + uint8_t pad2[3]; + }; + uint64_t value64[6]; /* don't forget to resize PixelShader9.ff_key */ + uint32_t value32[12]; + }; +}; + +static uint32_t nine_ff_vs_key_hash(const void *key) +{ + const struct nine_ff_vs_key *vs = key; + unsigned i; + uint32_t hash = vs->value32[0]; + for (i = 1; i < ARRAY_SIZE(vs->value32); ++i) + hash ^= vs->value32[i]; + return hash; +} +static bool nine_ff_vs_key_comp(const void *key1, const void *key2) +{ + struct nine_ff_vs_key *a = (struct nine_ff_vs_key *)key1; + struct nine_ff_vs_key *b = (struct nine_ff_vs_key *)key2; + + return memcmp(a->value64, b->value64, sizeof(a->value64)) == 0; +} +static uint32_t nine_ff_ps_key_hash(const void *key) +{ + const struct nine_ff_ps_key *ps = key; + unsigned i; + uint32_t hash = ps->value32[0]; + for (i = 1; i < ARRAY_SIZE(ps->value32); ++i) + hash ^= ps->value32[i]; + return hash; +} +static bool nine_ff_ps_key_comp(const void *key1, const void *key2) +{ + struct nine_ff_ps_key *a = (struct nine_ff_ps_key *)key1; + struct nine_ff_ps_key *b = (struct nine_ff_ps_key *)key2; + + return memcmp(a->value64, b->value64, sizeof(a->value64)) == 0; +} +static uint32_t nine_ff_fvf_key_hash(const void *key) +{ + return *(DWORD *)key; +} +static bool nine_ff_fvf_key_comp(const void *key1, const void *key2) +{ + return *(DWORD *)key1 == *(DWORD *)key2; +} + +static void nine_ff_prune_vs(struct NineDevice9 *); +static void nine_ff_prune_ps(struct NineDevice9 *); + +static void nine_ureg_tgsi_dump(struct ureg_program *ureg, boolean override) +{ + if (debug_get_bool_option("NINE_FF_DUMP", FALSE) || override) { + const struct tgsi_token *toks = ureg_get_tokens(ureg, NULL); + tgsi_dump(toks, 0); + ureg_free_tokens(toks); + } +} + +#define _X(r) ureg_scalar(ureg_src(r), TGSI_SWIZZLE_X) +#define _Y(r) ureg_scalar(ureg_src(r), TGSI_SWIZZLE_Y) +#define _Z(r) ureg_scalar(ureg_src(r), TGSI_SWIZZLE_Z) +#define _W(r) ureg_scalar(ureg_src(r), TGSI_SWIZZLE_W) + +#define _XXXX(r) ureg_scalar(r, TGSI_SWIZZLE_X) +#define _YYYY(r) ureg_scalar(r, TGSI_SWIZZLE_Y) +#define _ZZZZ(r) ureg_scalar(r, TGSI_SWIZZLE_Z) +#define _WWWW(r) ureg_scalar(r, TGSI_SWIZZLE_W) + +#define _XYZW(r) (r) + +/* AL should contain base address of lights table. */ +#define LIGHT_CONST(i) \ + ureg_src_indirect(ureg_DECL_constant(ureg, i), _X(AL)) + +#define MATERIAL_CONST(i) \ + ureg_DECL_constant(ureg, 19 + (i)) + +#define _CONST(n) ureg_DECL_constant(ureg, n) + +/* VS FF constants layout: + * + * CONST[ 0.. 3] D3DTS_WORLD * D3DTS_VIEW * D3DTS_PROJECTION + * CONST[ 4.. 7] D3DTS_WORLD * D3DTS_VIEW + * CONST[ 8..11] D3DTS_PROJECTION + * CONST[12..15] D3DTS_VIEW^(-1) + * CONST[16..18] Normal matrix + * + * CONST[19].xyz MATERIAL.Emissive + Material.Ambient * RS.Ambient + * CONST[20] MATERIAL.Diffuse + * CONST[21] MATERIAL.Ambient + * CONST[22] MATERIAL.Specular + * CONST[23].x___ MATERIAL.Power + * CONST[24] MATERIAL.Emissive + * CONST[25] RS.Ambient + * + * CONST[26].x___ RS.PointSizeMin + * CONST[26]._y__ RS.PointSizeMax + * CONST[26].__z_ RS.PointSize + * CONST[26].___w RS.PointScaleA + * CONST[27].x___ RS.PointScaleB + * CONST[27]._y__ RS.PointScaleC + * + * CONST[28].x___ RS.FogEnd + * CONST[28]._y__ 1.0f / (RS.FogEnd - RS.FogStart) + * CONST[28].__z_ RS.FogDensity + + * CONST[30].x___ TWEENFACTOR + * + * CONST[32].x___ LIGHT[0].Type + * CONST[32]._yzw LIGHT[0].Attenuation0,1,2 + * CONST[33] LIGHT[0].Diffuse + * CONST[34] LIGHT[0].Specular + * CONST[35] LIGHT[0].Ambient + * CONST[36].xyz_ LIGHT[0].Position + * CONST[36].___w LIGHT[0].Range + * CONST[37].xyz_ LIGHT[0].Direction + * CONST[37].___w LIGHT[0].Falloff + * CONST[38].x___ cos(LIGHT[0].Theta / 2) + * CONST[38]._y__ cos(LIGHT[0].Phi / 2) + * CONST[38].__z_ 1.0f / (cos(LIGHT[0].Theta / 2) - cos(Light[0].Phi / 2)) + * CONST[39].xyz_ LIGHT[0].HalfVector (for directional lights) + * CONST[39].___w 1 if this is the last active light, 0 if not + * CONST[40] LIGHT[1] + * CONST[48] LIGHT[2] + * CONST[56] LIGHT[3] + * CONST[64] LIGHT[4] + * CONST[72] LIGHT[5] + * CONST[80] LIGHT[6] + * CONST[88] LIGHT[7] + * NOTE: no lighting code is generated if there are no active lights + * + * CONST[100].x___ Viewport 2/width + * CONST[100]._y__ Viewport 2/height + * CONST[100].__z_ Viewport 1/(zmax - zmin) + * CONST[100].___w Viewport width + * CONST[101].x___ Viewport x0 + * CONST[101]._y__ Viewport y0 + * CONST[101].__z_ Viewport z0 + * + * CONST[128..131] D3DTS_TEXTURE0 + * CONST[132..135] D3DTS_TEXTURE1 + * CONST[136..139] D3DTS_TEXTURE2 + * CONST[140..143] D3DTS_TEXTURE3 + * CONST[144..147] D3DTS_TEXTURE4 + * CONST[148..151] D3DTS_TEXTURE5 + * CONST[152..155] D3DTS_TEXTURE6 + * CONST[156..159] D3DTS_TEXTURE7 + * + * CONST[160] D3DTS_WORLDMATRIX[0] * D3DTS_VIEW + * CONST[164] D3DTS_WORLDMATRIX[1] * D3DTS_VIEW + * ... + * CONST[192] D3DTS_WORLDMATRIX[8] * D3DTS_VIEW + */ +struct vs_build_ctx +{ + struct ureg_program *ureg; + const struct nine_ff_vs_key *key; + + uint16_t input[PIPE_MAX_ATTRIBS]; + unsigned num_inputs; + + struct ureg_src aVtx; + struct ureg_src aNrm; + struct ureg_src aCol[2]; + struct ureg_src aTex[8]; + struct ureg_src aPsz; + struct ureg_src aInd; + struct ureg_src aWgt; + + struct ureg_src aVtx1; /* tweening */ + struct ureg_src aNrm1; + + struct ureg_src mtlA; + struct ureg_src mtlD; + struct ureg_src mtlS; + struct ureg_src mtlE; +}; + +static inline unsigned +get_texcoord_sn(struct pipe_screen *screen) +{ + if (screen->get_param(screen, PIPE_CAP_TGSI_TEXCOORD)) + return TGSI_SEMANTIC_TEXCOORD; + return TGSI_SEMANTIC_GENERIC; +} + +static inline struct ureg_src +build_vs_add_input(struct vs_build_ctx *vs, uint16_t ndecl) +{ + const unsigned i = vs->num_inputs++; + assert(i < PIPE_MAX_ATTRIBS); + vs->input[i] = ndecl; + return ureg_DECL_vs_input(vs->ureg, i); +} + +/* NOTE: dst may alias src */ +static inline void +ureg_normalize3(struct ureg_program *ureg, + struct ureg_dst dst, struct ureg_src src) +{ + struct ureg_dst tmp = ureg_DECL_temporary(ureg); + struct ureg_dst tmp_x = ureg_writemask(tmp, TGSI_WRITEMASK_X); + + ureg_DP3(ureg, tmp_x, src, src); + ureg_RSQ(ureg, tmp_x, _X(tmp)); + ureg_MUL(ureg, dst, src, _X(tmp)); + ureg_release_temporary(ureg, tmp); +} + +static void * +nine_ff_build_vs(struct NineDevice9 *device, struct vs_build_ctx *vs) +{ + const struct nine_ff_vs_key *key = vs->key; + struct ureg_program *ureg = ureg_create(PIPE_SHADER_VERTEX); + struct ureg_dst oPos, oCol[2], oPsz, oFog; + struct ureg_dst AR; + unsigned i, c; + unsigned label[32], l = 0; + boolean need_aNrm = key->lighting || key->passthrough & (1 << NINE_DECLUSAGE_NORMAL); + boolean has_aNrm = need_aNrm && key->has_normal; + boolean need_aVtx = key->lighting || key->fog_mode || key->pointscale || key->ucp; + const unsigned texcoord_sn = get_texcoord_sn(device->screen); + + vs->ureg = ureg; + + /* Check which inputs we should transform. */ + for (i = 0; i < 8 * 3; i += 3) { + switch ((key->tc_gen >> i) & 0x7) { + case NINED3DTSS_TCI_CAMERASPACENORMAL: + need_aNrm = TRUE; + break; + case NINED3DTSS_TCI_CAMERASPACEPOSITION: + need_aVtx = TRUE; + break; + case NINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR: + need_aVtx = need_aNrm = TRUE; + break; + case NINED3DTSS_TCI_SPHEREMAP: + need_aVtx = need_aNrm = TRUE; + break; + default: + break; + } + } + + /* Declare and record used inputs (needed for linkage with vertex format): + * (texture coordinates handled later) + */ + vs->aVtx = build_vs_add_input(vs, + key->position_t ? NINE_DECLUSAGE_POSITIONT : NINE_DECLUSAGE_POSITION); + + vs->aNrm = ureg_imm1f(ureg, 0.0f); + if (has_aNrm) + vs->aNrm = build_vs_add_input(vs, NINE_DECLUSAGE_NORMAL); + + vs->aCol[0] = ureg_imm1f(ureg, 1.0f); + vs->aCol[1] = ureg_imm1f(ureg, 0.0f); + + if (key->lighting || key->darkness) { + const unsigned mask = key->mtl_diffuse | key->mtl_specular | + key->mtl_ambient | key->mtl_emissive; + if ((mask & 0x1) && !key->color0in_one) + vs->aCol[0] = build_vs_add_input(vs, NINE_DECLUSAGE_i(COLOR, 0)); + if ((mask & 0x2) && !key->color1in_zero) + vs->aCol[1] = build_vs_add_input(vs, NINE_DECLUSAGE_i(COLOR, 1)); + + vs->mtlD = MATERIAL_CONST(1); + vs->mtlA = MATERIAL_CONST(2); + vs->mtlS = MATERIAL_CONST(3); + vs->mtlE = MATERIAL_CONST(5); + if (key->mtl_diffuse == 1) vs->mtlD = vs->aCol[0]; else + if (key->mtl_diffuse == 2) vs->mtlD = vs->aCol[1]; + if (key->mtl_ambient == 1) vs->mtlA = vs->aCol[0]; else + if (key->mtl_ambient == 2) vs->mtlA = vs->aCol[1]; + if (key->mtl_specular == 1) vs->mtlS = vs->aCol[0]; else + if (key->mtl_specular == 2) vs->mtlS = vs->aCol[1]; + if (key->mtl_emissive == 1) vs->mtlE = vs->aCol[0]; else + if (key->mtl_emissive == 2) vs->mtlE = vs->aCol[1]; + } else { + if (!key->color0in_one) vs->aCol[0] = build_vs_add_input(vs, NINE_DECLUSAGE_i(COLOR, 0)); + if (!key->color1in_zero) vs->aCol[1] = build_vs_add_input(vs, NINE_DECLUSAGE_i(COLOR, 1)); + } + + if (key->vertexpointsize) + vs->aPsz = build_vs_add_input(vs, NINE_DECLUSAGE_PSIZE); + + if (key->vertexblend_indexed || key->passthrough & (1 << NINE_DECLUSAGE_BLENDINDICES)) + vs->aInd = build_vs_add_input(vs, NINE_DECLUSAGE_BLENDINDICES); + if (key->vertexblend || key->passthrough & (1 << NINE_DECLUSAGE_BLENDWEIGHT)) + vs->aWgt = build_vs_add_input(vs, NINE_DECLUSAGE_BLENDWEIGHT); + if (key->vertextween) { + vs->aVtx1 = build_vs_add_input(vs, NINE_DECLUSAGE_i(POSITION,1)); + vs->aNrm1 = build_vs_add_input(vs, NINE_DECLUSAGE_i(NORMAL,1)); + } + + /* Declare outputs: + */ + oPos = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0); /* HPOS */ + oCol[0] = ureg_saturate(ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0)); + oCol[1] = ureg_saturate(ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 1)); + if (key->fog || key->passthrough & (1 << NINE_DECLUSAGE_FOG)) { + oFog = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 16); + oFog = ureg_writemask(oFog, TGSI_WRITEMASK_X); + } + + if (key->vertexpointsize || key->pointscale) { + oPsz = ureg_DECL_output_masked(ureg, TGSI_SEMANTIC_PSIZE, 0, + TGSI_WRITEMASK_X, 0, 1); + oPsz = ureg_writemask(oPsz, TGSI_WRITEMASK_X); + } + + if (key->lighting || key->vertexblend) + AR = ureg_DECL_address(ureg); + + /* === Vertex transformation / vertex blending: + */ + + if (key->position_t) { + if (device->driver_caps.window_space_position_support) { + ureg_MOV(ureg, oPos, vs->aVtx); + } else { + struct ureg_dst tmp = ureg_DECL_temporary(ureg); + /* vs->aVtx contains the coordinates buffer wise. + * later in the pipeline, clipping, viewport and division + * by w (rhw = 1/w) are going to be applied, so do the reverse + * of these transformations (except clipping) to have the good + * position at the end.*/ + ureg_MOV(ureg, tmp, vs->aVtx); + /* X from [X_min, X_min + width] to [-1, 1], same for Y. Z to [0, 1] */ + ureg_ADD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XYZ), ureg_src(tmp), ureg_negate(_CONST(101))); + ureg_MUL(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XYZ), ureg_src(tmp), _CONST(100)); + ureg_ADD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XY), ureg_src(tmp), ureg_imm1f(ureg, -1.0f)); + /* Y needs to be reversed */ + ureg_MOV(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Y), ureg_negate(ureg_src(tmp))); + /* inverse rhw */ + ureg_RCP(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_W), _W(tmp)); + /* multiply X, Y, Z by w */ + ureg_MUL(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XYZ), ureg_src(tmp), _W(tmp)); + ureg_MOV(ureg, oPos, ureg_src(tmp)); + ureg_release_temporary(ureg, tmp); + } + } else if (key->vertexblend) { + struct ureg_dst tmp = ureg_DECL_temporary(ureg); + struct ureg_dst tmp2 = ureg_DECL_temporary(ureg); + struct ureg_dst aVtx_dst = ureg_DECL_temporary(ureg); + struct ureg_dst aNrm_dst = ureg_DECL_temporary(ureg); + struct ureg_dst sum_blendweights = ureg_DECL_temporary(ureg); + struct ureg_src cWM[4]; + + for (i = 160; i <= 195; ++i) + ureg_DECL_constant(ureg, i); + + /* translate world matrix index to constant file index */ + if (key->vertexblend_indexed) { + ureg_MAD(ureg, tmp, vs->aInd, ureg_imm1f(ureg, 4.0f), ureg_imm1f(ureg, 160.0f)); + ureg_ARL(ureg, AR, ureg_src(tmp)); + } + + ureg_MOV(ureg, aVtx_dst, ureg_imm4f(ureg, 0.0f, 0.0f, 0.0f, 0.0f)); + ureg_MOV(ureg, aNrm_dst, ureg_imm4f(ureg, 0.0f, 0.0f, 0.0f, 0.0f)); + ureg_MOV(ureg, sum_blendweights, ureg_imm4f(ureg, 1.0f, 1.0f, 1.0f, 1.0f)); + + for (i = 0; i < key->vertexblend; ++i) { + for (c = 0; c < 4; ++c) { + cWM[c] = ureg_src_dimension(ureg_src_register(TGSI_FILE_CONSTANT, (160 + i * 4) * !key->vertexblend_indexed + c), 0); + if (key->vertexblend_indexed) + cWM[c] = ureg_src_indirect(cWM[c], ureg_scalar(ureg_src(AR), i)); + } + + /* multiply by WORLD(index) */ + ureg_MUL(ureg, tmp, _XXXX(vs->aVtx), cWM[0]); + ureg_MAD(ureg, tmp, _YYYY(vs->aVtx), cWM[1], ureg_src(tmp)); + ureg_MAD(ureg, tmp, _ZZZZ(vs->aVtx), cWM[2], ureg_src(tmp)); + ureg_MAD(ureg, tmp, _WWWW(vs->aVtx), cWM[3], ureg_src(tmp)); + + if (has_aNrm) { + /* Note: the spec says the transpose of the inverse of the + * WorldView matrices should be used, but all tests show + * otherwise. + * Only case unknown: D3DVBF_0WEIGHTS */ + ureg_MUL(ureg, tmp2, _XXXX(vs->aNrm), cWM[0]); + ureg_MAD(ureg, tmp2, _YYYY(vs->aNrm), cWM[1], ureg_src(tmp2)); + ureg_MAD(ureg, tmp2, _ZZZZ(vs->aNrm), cWM[2], ureg_src(tmp2)); + } + + if (i < (key->vertexblend - 1)) { + /* accumulate weighted position value */ + ureg_MAD(ureg, aVtx_dst, ureg_src(tmp), ureg_scalar(vs->aWgt, i), ureg_src(aVtx_dst)); + if (has_aNrm) + ureg_MAD(ureg, aNrm_dst, ureg_src(tmp2), ureg_scalar(vs->aWgt, i), ureg_src(aNrm_dst)); + /* subtract weighted position value for last value */ + ureg_ADD(ureg, sum_blendweights, ureg_src(sum_blendweights), ureg_negate(ureg_scalar(vs->aWgt, i))); + } + } + + /* the last weighted position is always 1 - sum_of_previous_weights */ + ureg_MAD(ureg, aVtx_dst, ureg_src(tmp), ureg_scalar(ureg_src(sum_blendweights), key->vertexblend - 1), ureg_src(aVtx_dst)); + if (has_aNrm) + ureg_MAD(ureg, aNrm_dst, ureg_src(tmp2), ureg_scalar(ureg_src(sum_blendweights), key->vertexblend - 1), ureg_src(aNrm_dst)); + + /* multiply by VIEW_PROJ */ + ureg_MUL(ureg, tmp, _X(aVtx_dst), _CONST(8)); + ureg_MAD(ureg, tmp, _Y(aVtx_dst), _CONST(9), ureg_src(tmp)); + ureg_MAD(ureg, tmp, _Z(aVtx_dst), _CONST(10), ureg_src(tmp)); + ureg_MAD(ureg, oPos, _W(aVtx_dst), _CONST(11), ureg_src(tmp)); + + if (need_aVtx) + vs->aVtx = ureg_src(aVtx_dst); + + ureg_release_temporary(ureg, tmp); + ureg_release_temporary(ureg, tmp2); + ureg_release_temporary(ureg, sum_blendweights); + if (!need_aVtx) + ureg_release_temporary(ureg, aVtx_dst); + + if (has_aNrm) { + if (key->normalizenormals) + ureg_normalize3(ureg, aNrm_dst, ureg_src(aNrm_dst)); + vs->aNrm = ureg_src(aNrm_dst); + } else + ureg_release_temporary(ureg, aNrm_dst); + } else { + struct ureg_dst tmp = ureg_DECL_temporary(ureg); + + if (key->vertextween) { + struct ureg_dst aVtx_dst = ureg_DECL_temporary(ureg); + ureg_LRP(ureg, aVtx_dst, _XXXX(_CONST(30)), vs->aVtx1, vs->aVtx); + vs->aVtx = ureg_src(aVtx_dst); + if (has_aNrm) { + struct ureg_dst aNrm_dst = ureg_DECL_temporary(ureg); + ureg_LRP(ureg, aNrm_dst, _XXXX(_CONST(30)), vs->aNrm1, vs->aNrm); + vs->aNrm = ureg_src(aNrm_dst); + } + } + + /* position = vertex * WORLD_VIEW_PROJ */ + ureg_MUL(ureg, tmp, _XXXX(vs->aVtx), _CONST(0)); + ureg_MAD(ureg, tmp, _YYYY(vs->aVtx), _CONST(1), ureg_src(tmp)); + ureg_MAD(ureg, tmp, _ZZZZ(vs->aVtx), _CONST(2), ureg_src(tmp)); + ureg_MAD(ureg, oPos, _WWWW(vs->aVtx), _CONST(3), ureg_src(tmp)); + ureg_release_temporary(ureg, tmp); + + if (need_aVtx) { + struct ureg_dst aVtx_dst = ureg_writemask(ureg_DECL_temporary(ureg), TGSI_WRITEMASK_XYZ); + ureg_MUL(ureg, aVtx_dst, _XXXX(vs->aVtx), _CONST(4)); + ureg_MAD(ureg, aVtx_dst, _YYYY(vs->aVtx), _CONST(5), ureg_src(aVtx_dst)); + ureg_MAD(ureg, aVtx_dst, _ZZZZ(vs->aVtx), _CONST(6), ureg_src(aVtx_dst)); + ureg_MAD(ureg, aVtx_dst, _WWWW(vs->aVtx), _CONST(7), ureg_src(aVtx_dst)); + vs->aVtx = ureg_src(aVtx_dst); + } + if (has_aNrm) { + struct ureg_dst aNrm_dst = ureg_writemask(ureg_DECL_temporary(ureg), TGSI_WRITEMASK_XYZ); + ureg_MUL(ureg, aNrm_dst, _XXXX(vs->aNrm), _CONST(16)); + ureg_MAD(ureg, aNrm_dst, _YYYY(vs->aNrm), _CONST(17), ureg_src(aNrm_dst)); + ureg_MAD(ureg, aNrm_dst, _ZZZZ(vs->aNrm), _CONST(18), ureg_src(aNrm_dst)); + if (key->normalizenormals) + ureg_normalize3(ureg, aNrm_dst, ureg_src(aNrm_dst)); + vs->aNrm = ureg_src(aNrm_dst); + } + } + + /* === Process point size: + */ + if (key->vertexpointsize || key->pointscale) { + struct ureg_dst tmp = ureg_DECL_temporary(ureg); + struct ureg_dst tmp_x = ureg_writemask(tmp, TGSI_WRITEMASK_X); + struct ureg_dst tmp_y = ureg_writemask(tmp, TGSI_WRITEMASK_Y); + struct ureg_dst tmp_z = ureg_writemask(tmp, TGSI_WRITEMASK_Z); + if (key->vertexpointsize) { + struct ureg_src cPsz1 = ureg_DECL_constant(ureg, 26); + ureg_MAX(ureg, tmp_z, _XXXX(vs->aPsz), _XXXX(cPsz1)); + ureg_MIN(ureg, tmp_z, _Z(tmp), _YYYY(cPsz1)); + } else { + struct ureg_src cPsz1 = ureg_DECL_constant(ureg, 26); + ureg_MOV(ureg, tmp_z, _ZZZZ(cPsz1)); + } + + if (key->pointscale) { + struct ureg_src cPsz1 = ureg_DECL_constant(ureg, 26); + struct ureg_src cPsz2 = ureg_DECL_constant(ureg, 27); + + ureg_DP3(ureg, tmp_x, vs->aVtx, vs->aVtx); + ureg_RSQ(ureg, tmp_y, _X(tmp)); + ureg_MUL(ureg, tmp_y, _Y(tmp), _X(tmp)); + ureg_CMP(ureg, tmp_y, ureg_negate(_Y(tmp)), _Y(tmp), ureg_imm1f(ureg, 0.0f)); + ureg_MAD(ureg, tmp_x, _Y(tmp), _YYYY(cPsz2), _XXXX(cPsz2)); + ureg_MAD(ureg, tmp_x, _Y(tmp), _X(tmp), _WWWW(cPsz1)); + ureg_RSQ(ureg, tmp_x, _X(tmp)); + ureg_MUL(ureg, tmp_x, _X(tmp), _Z(tmp)); + ureg_MUL(ureg, tmp_x, _X(tmp), _WWWW(_CONST(100))); + ureg_MAX(ureg, tmp_x, _X(tmp), _XXXX(cPsz1)); + ureg_MIN(ureg, tmp_z, _X(tmp), _YYYY(cPsz1)); + } + + ureg_MOV(ureg, oPsz, _Z(tmp)); + ureg_release_temporary(ureg, tmp); + } + + for (i = 0; i < 8; ++i) { + struct ureg_dst tmp, tmp_x, tmp2; + struct ureg_dst oTex, input_coord, transformed, t, aVtx_normed; + unsigned c, writemask; + const unsigned tci = (key->tc_gen >> (i * 3)) & 0x7; + const unsigned idx = (key->tc_idx >> (i * 3)) & 0x7; + unsigned dim_input = 1 + ((key->tc_dim_input >> (i * 2)) & 0x3); + const unsigned dim_output = (key->tc_dim_output >> (i * 3)) & 0x7; + + /* No texture output of index s */ + if (tci == NINED3DTSS_TCI_DISABLE) + continue; + oTex = ureg_DECL_output(ureg, texcoord_sn, i); + tmp = ureg_DECL_temporary(ureg); + tmp_x = ureg_writemask(tmp, TGSI_WRITEMASK_X); + input_coord = ureg_DECL_temporary(ureg); + transformed = ureg_DECL_temporary(ureg); + + /* Get the coordinate */ + switch (tci) { + case NINED3DTSS_TCI_PASSTHRU: + /* NINED3DTSS_TCI_PASSTHRU => Use texcoord coming from index idx * + * Else the idx is used only to determine wrapping mode. */ + vs->aTex[idx] = build_vs_add_input(vs, NINE_DECLUSAGE_i(TEXCOORD,idx)); + ureg_MOV(ureg, input_coord, vs->aTex[idx]); + break; + case NINED3DTSS_TCI_CAMERASPACENORMAL: + ureg_MOV(ureg, ureg_writemask(input_coord, TGSI_WRITEMASK_XYZ), vs->aNrm); + ureg_MOV(ureg, ureg_writemask(input_coord, TGSI_WRITEMASK_W), ureg_imm1f(ureg, 1.0f)); + dim_input = 4; + break; + case NINED3DTSS_TCI_CAMERASPACEPOSITION: + ureg_MOV(ureg, ureg_writemask(input_coord, TGSI_WRITEMASK_XYZ), vs->aVtx); + ureg_MOV(ureg, ureg_writemask(input_coord, TGSI_WRITEMASK_W), ureg_imm1f(ureg, 1.0f)); + dim_input = 4; + break; + case NINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR: + tmp.WriteMask = TGSI_WRITEMASK_XYZ; + aVtx_normed = ureg_DECL_temporary(ureg); + ureg_normalize3(ureg, aVtx_normed, vs->aVtx); + ureg_DP3(ureg, tmp_x, ureg_src(aVtx_normed), vs->aNrm); + ureg_MUL(ureg, tmp, vs->aNrm, _X(tmp)); + ureg_ADD(ureg, tmp, ureg_src(tmp), ureg_src(tmp)); + ureg_ADD(ureg, ureg_writemask(input_coord, TGSI_WRITEMASK_XYZ), ureg_src(aVtx_normed), ureg_negate(ureg_src(tmp))); + ureg_MOV(ureg, ureg_writemask(input_coord, TGSI_WRITEMASK_W), ureg_imm1f(ureg, 1.0f)); + ureg_release_temporary(ureg, aVtx_normed); + dim_input = 4; + tmp.WriteMask = TGSI_WRITEMASK_XYZW; + break; + case NINED3DTSS_TCI_SPHEREMAP: + /* Implement the formula of GL_SPHERE_MAP */ + tmp.WriteMask = TGSI_WRITEMASK_XYZ; + aVtx_normed = ureg_DECL_temporary(ureg); + tmp2 = ureg_DECL_temporary(ureg); + ureg_normalize3(ureg, aVtx_normed, vs->aVtx); + ureg_DP3(ureg, tmp_x, ureg_src(aVtx_normed), vs->aNrm); + ureg_MUL(ureg, tmp, vs->aNrm, _X(tmp)); + ureg_ADD(ureg, tmp, ureg_src(tmp), ureg_src(tmp)); + ureg_ADD(ureg, tmp, ureg_src(aVtx_normed), ureg_negate(ureg_src(tmp))); + /* now tmp = normed(Vtx) - 2 dot3(normed(Vtx), Nrm) Nrm */ + ureg_MOV(ureg, ureg_writemask(tmp2, TGSI_WRITEMASK_XYZ), ureg_src(tmp)); + ureg_MUL(ureg, tmp2, ureg_src(tmp2), ureg_src(tmp2)); + ureg_DP3(ureg, ureg_writemask(tmp2, TGSI_WRITEMASK_X), ureg_src(tmp2), ureg_src(tmp2)); + ureg_RSQ(ureg, ureg_writemask(tmp2, TGSI_WRITEMASK_X), ureg_src(tmp2)); + ureg_MUL(ureg, ureg_writemask(tmp2, TGSI_WRITEMASK_X), ureg_src(tmp2), ureg_imm1f(ureg, 0.5f)); + /* tmp2 = 0.5 / sqrt(tmp.x^2 + tmp.y^2 + (tmp.z+1)^2) + * TODO: z coordinates are a bit different gl vs d3d, should the formula be adapted ? */ + ureg_MUL(ureg, tmp, ureg_src(tmp), _X(tmp2)); + ureg_ADD(ureg, ureg_writemask(input_coord, TGSI_WRITEMASK_XY), ureg_src(tmp), ureg_imm1f(ureg, 0.5f)); + ureg_MOV(ureg, ureg_writemask(input_coord, TGSI_WRITEMASK_ZW), ureg_imm4f(ureg, 0.0f, 0.0f, 0.0f, 1.0f)); + ureg_release_temporary(ureg, aVtx_normed); + ureg_release_temporary(ureg, tmp2); + dim_input = 4; + tmp.WriteMask = TGSI_WRITEMASK_XYZW; + break; + default: + assert(0); + break; + } + + /* Apply the transformation */ + /* dim_output == 0 => do not transform the components. + * XYZRHW also disables transformation */ + if (!dim_output || key->position_t) { + ureg_release_temporary(ureg, transformed); + transformed = input_coord; + writemask = TGSI_WRITEMASK_XYZW; + } else { + for (c = 0; c < dim_output; c++) { + t = ureg_writemask(transformed, 1 << c); + switch (dim_input) { + /* dim_input = 1 2 3: -> we add trailing 1 to input*/ + case 1: ureg_MAD(ureg, t, _X(input_coord), _XXXX(_CONST(128 + i * 4 + c)), _YYYY(_CONST(128 + i * 4 + c))); + break; + case 2: ureg_DP2(ureg, t, ureg_src(input_coord), _CONST(128 + i * 4 + c)); + ureg_ADD(ureg, t, ureg_src(transformed), _ZZZZ(_CONST(128 + i * 4 + c))); + break; + case 3: ureg_DP3(ureg, t, ureg_src(input_coord), _CONST(128 + i * 4 + c)); + ureg_ADD(ureg, t, ureg_src(transformed), _WWWW(_CONST(128 + i * 4 + c))); + break; + case 4: ureg_DP4(ureg, t, ureg_src(input_coord), _CONST(128 + i * 4 + c)); break; + default: + assert(0); + } + } + writemask = (1 << dim_output) - 1; + ureg_release_temporary(ureg, input_coord); + } + + ureg_MOV(ureg, ureg_writemask(oTex, writemask), ureg_src(transformed)); + ureg_release_temporary(ureg, transformed); + ureg_release_temporary(ureg, tmp); + } + + /* === Lighting: + * + * DIRECTIONAL: Light at infinite distance, parallel rays, no attenuation. + * POINT: Finite distance to scene, divergent rays, isotropic, attenuation. + * SPOT: Finite distance, divergent rays, angular dependence, attenuation. + * + * vec3 normal = normalize(in.Normal * NormalMatrix); + * vec3 hitDir = light.direction; + * float atten = 1.0; + * + * if (light.type != DIRECTIONAL) + * { + * vec3 hitVec = light.position - eyeVertex; + * float d = length(hitVec); + * hitDir = hitVec / d; + * atten = 1 / ((light.atten2 * d + light.atten1) * d + light.atten0); + * } + * + * if (light.type == SPOTLIGHT) + * { + * float rho = dp3(-hitVec, light.direction); + * if (rho < cos(light.phi / 2)) + * atten = 0; + * if (rho < cos(light.theta / 2)) + * atten *= pow(some_func(rho), light.falloff); + * } + * + * float nDotHit = dp3_sat(normal, hitVec); + * float powFact = 0.0; + * + * if (nDotHit > 0.0) + * { + * vec3 midVec = normalize(hitDir + eye); + * float nDotMid = dp3_sat(normal, midVec); + * pFact = pow(nDotMid, material.power); + * } + * + * ambient += light.ambient * atten; + * diffuse += light.diffuse * atten * nDotHit; + * specular += light.specular * atten * powFact; + */ + if (key->lighting) { + struct ureg_dst tmp = ureg_DECL_temporary(ureg); + struct ureg_dst tmp_x = ureg_writemask(tmp, TGSI_WRITEMASK_X); + struct ureg_dst tmp_y = ureg_writemask(tmp, TGSI_WRITEMASK_Y); + struct ureg_dst tmp_z = ureg_writemask(tmp, TGSI_WRITEMASK_Z); + struct ureg_dst rAtt = ureg_writemask(ureg_DECL_temporary(ureg), TGSI_WRITEMASK_W); + struct ureg_dst rHit = ureg_writemask(ureg_DECL_temporary(ureg), TGSI_WRITEMASK_XYZ); + struct ureg_dst rMid = ureg_writemask(ureg_DECL_temporary(ureg), TGSI_WRITEMASK_XYZ); + + struct ureg_dst rCtr = ureg_writemask(ureg_DECL_temporary(ureg), TGSI_WRITEMASK_W); + + struct ureg_dst AL = ureg_writemask(AR, TGSI_WRITEMASK_X); + + /* Light.*.Alpha is not used. */ + struct ureg_dst rD = ureg_writemask(ureg_DECL_temporary(ureg), TGSI_WRITEMASK_XYZ); + struct ureg_dst rA = ureg_writemask(ureg_DECL_temporary(ureg), TGSI_WRITEMASK_XYZ); + struct ureg_dst rS = ureg_DECL_temporary(ureg); + + struct ureg_src mtlP = _XXXX(MATERIAL_CONST(4)); + + struct ureg_src cLKind = _XXXX(LIGHT_CONST(0)); + struct ureg_src cLAtt0 = _YYYY(LIGHT_CONST(0)); + struct ureg_src cLAtt1 = _ZZZZ(LIGHT_CONST(0)); + struct ureg_src cLAtt2 = _WWWW(LIGHT_CONST(0)); + struct ureg_src cLColD = _XYZW(LIGHT_CONST(1)); + struct ureg_src cLColS = _XYZW(LIGHT_CONST(2)); + struct ureg_src cLColA = _XYZW(LIGHT_CONST(3)); + struct ureg_src cLPos = _XYZW(LIGHT_CONST(4)); + struct ureg_src cLRng = _WWWW(LIGHT_CONST(4)); + struct ureg_src cLDir = _XYZW(LIGHT_CONST(5)); + struct ureg_src cLFOff = _WWWW(LIGHT_CONST(5)); + struct ureg_src cLTht = _XXXX(LIGHT_CONST(6)); + struct ureg_src cLPhi = _YYYY(LIGHT_CONST(6)); + struct ureg_src cLSDiv = _ZZZZ(LIGHT_CONST(6)); + struct ureg_src cLLast = _WWWW(LIGHT_CONST(7)); + + const unsigned loop_label = l++; + + /* Declare all light constants to allow indirect adressing */ + for (i = 32; i < 96; i++) + ureg_DECL_constant(ureg, i); + + ureg_MOV(ureg, rCtr, ureg_imm1f(ureg, 32.0f)); /* &lightconst(0) */ + ureg_MOV(ureg, rD, ureg_imm1f(ureg, 0.0f)); + ureg_MOV(ureg, rA, ureg_imm1f(ureg, 0.0f)); + ureg_MOV(ureg, rS, ureg_imm1f(ureg, 0.0f)); + + /* loop management */ + ureg_BGNLOOP(ureg, &label[loop_label]); + ureg_ARL(ureg, AL, _W(rCtr)); + + /* if (not DIRECTIONAL light): */ + ureg_SNE(ureg, tmp_x, cLKind, ureg_imm1f(ureg, D3DLIGHT_DIRECTIONAL)); + ureg_MOV(ureg, rHit, ureg_negate(cLDir)); + ureg_MOV(ureg, rAtt, ureg_imm1f(ureg, 1.0f)); + ureg_IF(ureg, _X(tmp), &label[l++]); + { + /* hitDir = light.position - eyeVtx + * d = length(hitDir) + */ + ureg_ADD(ureg, rHit, cLPos, ureg_negate(vs->aVtx)); + ureg_DP3(ureg, tmp_x, ureg_src(rHit), ureg_src(rHit)); + ureg_RSQ(ureg, tmp_y, _X(tmp)); + ureg_MUL(ureg, tmp_x, _X(tmp), _Y(tmp)); /* length */ + + /* att = 1.0 / (light.att0 + (light.att1 + light.att2 * d) * d) */ + ureg_MAD(ureg, rAtt, _X(tmp), cLAtt2, cLAtt1); + ureg_MAD(ureg, rAtt, _X(tmp), _W(rAtt), cLAtt0); + ureg_RCP(ureg, rAtt, _W(rAtt)); + /* cut-off if distance exceeds Light.Range */ + ureg_SLT(ureg, tmp_x, _X(tmp), cLRng); + ureg_MUL(ureg, rAtt, _W(rAtt), _X(tmp)); + } + ureg_fixup_label(ureg, label[l-1], ureg_get_instruction_number(ureg)); + ureg_ENDIF(ureg); + + /* normalize hitDir */ + ureg_normalize3(ureg, rHit, ureg_src(rHit)); + + /* if (SPOT light) */ + ureg_SEQ(ureg, tmp_x, cLKind, ureg_imm1f(ureg, D3DLIGHT_SPOT)); + ureg_IF(ureg, _X(tmp), &label[l++]); + { + /* rho = dp3(-hitDir, light.spotDir) + * + * if (rho > light.ctht2) NOTE: 0 <= phi <= pi, 0 <= theta <= phi + * spotAtt = 1 + * else + * if (rho <= light.cphi2) + * spotAtt = 0 + * else + * spotAtt = (rho - light.cphi2) / (light.ctht2 - light.cphi2) ^ light.falloff + */ + ureg_DP3(ureg, tmp_y, ureg_negate(ureg_src(rHit)), cLDir); /* rho */ + ureg_ADD(ureg, tmp_x, _Y(tmp), ureg_negate(cLPhi)); + ureg_MUL(ureg, tmp_x, _X(tmp), cLSDiv); + ureg_POW(ureg, tmp_x, _X(tmp), cLFOff); /* spotAtten */ + ureg_SGE(ureg, tmp_z, _Y(tmp), cLTht); /* if inside theta && phi */ + ureg_SGE(ureg, tmp_y, _Y(tmp), cLPhi); /* if inside phi */ + ureg_MAD(ureg, ureg_saturate(tmp_x), _X(tmp), _Y(tmp), _Z(tmp)); + ureg_MUL(ureg, rAtt, _W(rAtt), _X(tmp)); + } + ureg_fixup_label(ureg, label[l-1], ureg_get_instruction_number(ureg)); + ureg_ENDIF(ureg); + + /* directional factors, let's not use LIT because of clarity */ + + if (has_aNrm) { + if (key->localviewer) { + ureg_normalize3(ureg, rMid, vs->aVtx); + ureg_ADD(ureg, rMid, ureg_src(rHit), ureg_negate(ureg_src(rMid))); + } else { + ureg_ADD(ureg, rMid, ureg_src(rHit), ureg_imm3f(ureg, 0.0f, 0.0f, -1.0f)); + } + ureg_normalize3(ureg, rMid, ureg_src(rMid)); + ureg_DP3(ureg, ureg_saturate(tmp_x), vs->aNrm, ureg_src(rHit)); + ureg_DP3(ureg, ureg_saturate(tmp_y), vs->aNrm, ureg_src(rMid)); + ureg_MUL(ureg, tmp_z, _X(tmp), _Y(tmp)); + /* Tests show that specular is computed only if (dp3(normal,hitDir) > 0). + * For front facing, it is more restrictive than test (dp3(normal,mid) > 0). + * No tests were made for backfacing, so add the two conditions */ + ureg_IF(ureg, _Z(tmp), &label[l++]); + { + ureg_DP3(ureg, ureg_saturate(tmp_y), vs->aNrm, ureg_src(rMid)); + ureg_POW(ureg, tmp_y, _Y(tmp), mtlP); + ureg_MUL(ureg, tmp_y, _W(rAtt), _Y(tmp)); /* power factor * att */ + ureg_MAD(ureg, rS, cLColS, _Y(tmp), ureg_src(rS)); /* accumulate specular */ + } + ureg_fixup_label(ureg, label[l-1], ureg_get_instruction_number(ureg)); + ureg_ENDIF(ureg); + + ureg_MUL(ureg, tmp_x, _W(rAtt), _X(tmp)); /* dp3(normal,hitDir) * att */ + ureg_MAD(ureg, rD, cLColD, _X(tmp), ureg_src(rD)); /* accumulate diffuse */ + } + + ureg_MAD(ureg, rA, cLColA, _W(rAtt), ureg_src(rA)); /* accumulate ambient */ + + /* break if this was the last light */ + ureg_IF(ureg, cLLast, &label[l++]); + ureg_BRK(ureg); + ureg_ENDIF(ureg); + ureg_fixup_label(ureg, label[l-1], ureg_get_instruction_number(ureg)); + + ureg_ADD(ureg, rCtr, _W(rCtr), ureg_imm1f(ureg, 8.0f)); + ureg_fixup_label(ureg, label[loop_label], ureg_get_instruction_number(ureg)); + ureg_ENDLOOP(ureg, &label[loop_label]); + + /* Apply to material: + * + * oCol[0] = (material.emissive + material.ambient * rs.ambient) + + * material.ambient * ambient + + * material.diffuse * diffuse + + * oCol[1] = material.specular * specular; + */ + if (key->mtl_emissive == 0 && key->mtl_ambient == 0) + ureg_MAD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XYZ), ureg_src(rA), vs->mtlA, _CONST(19)); + else { + ureg_ADD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XYZ), ureg_src(rA), _CONST(25)); + ureg_MAD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XYZ), vs->mtlA, ureg_src(tmp), vs->mtlE); + } + + ureg_MAD(ureg, ureg_writemask(oCol[0], TGSI_WRITEMASK_XYZ), ureg_src(rD), vs->mtlD, ureg_src(tmp)); + ureg_MOV(ureg, ureg_writemask(oCol[0], TGSI_WRITEMASK_W), vs->mtlD); + ureg_MUL(ureg, oCol[1], ureg_src(rS), vs->mtlS); + ureg_release_temporary(ureg, rAtt); + ureg_release_temporary(ureg, rHit); + ureg_release_temporary(ureg, rMid); + ureg_release_temporary(ureg, rCtr); + ureg_release_temporary(ureg, rD); + ureg_release_temporary(ureg, rA); + ureg_release_temporary(ureg, rS); + ureg_release_temporary(ureg, rAtt); + ureg_release_temporary(ureg, tmp); + } else + /* COLOR */ + if (key->darkness) { + if (key->mtl_emissive == 0 && key->mtl_ambient == 0) + ureg_MOV(ureg, ureg_writemask(oCol[0], TGSI_WRITEMASK_XYZ), _CONST(19)); + else + ureg_MAD(ureg, ureg_writemask(oCol[0], TGSI_WRITEMASK_XYZ), vs->mtlA, _CONST(25), vs->mtlE); + ureg_MOV(ureg, ureg_writemask(oCol[0], TGSI_WRITEMASK_W), vs->mtlD); + ureg_MOV(ureg, oCol[1], ureg_imm1f(ureg, 0.0f)); + } else { + ureg_MOV(ureg, oCol[0], vs->aCol[0]); + ureg_MOV(ureg, oCol[1], vs->aCol[1]); + } + + /* === Process fog. + * + * exp(x) = ex2(log2(e) * x) + */ + if (key->fog_mode) { + struct ureg_dst tmp = ureg_DECL_temporary(ureg); + struct ureg_dst tmp_x = ureg_writemask(tmp, TGSI_WRITEMASK_X); + struct ureg_dst tmp_z = ureg_writemask(tmp, TGSI_WRITEMASK_Z); + if (key->fog_range) { + ureg_DP3(ureg, tmp_x, vs->aVtx, vs->aVtx); + ureg_RSQ(ureg, tmp_z, _X(tmp)); + ureg_MUL(ureg, tmp_z, _Z(tmp), _X(tmp)); + } else { + ureg_MOV(ureg, tmp_z, ureg_abs(_ZZZZ(vs->aVtx))); + } + + if (key->fog_mode == D3DFOG_EXP) { + ureg_MUL(ureg, tmp_x, _Z(tmp), _ZZZZ(_CONST(28))); + ureg_MUL(ureg, tmp_x, _X(tmp), ureg_imm1f(ureg, -1.442695f)); + ureg_EX2(ureg, tmp_x, _X(tmp)); + } else + if (key->fog_mode == D3DFOG_EXP2) { + ureg_MUL(ureg, tmp_x, _Z(tmp), _ZZZZ(_CONST(28))); + ureg_MUL(ureg, tmp_x, _X(tmp), _X(tmp)); + ureg_MUL(ureg, tmp_x, _X(tmp), ureg_imm1f(ureg, -1.442695f)); + ureg_EX2(ureg, tmp_x, _X(tmp)); + } else + if (key->fog_mode == D3DFOG_LINEAR) { + ureg_ADD(ureg, tmp_x, _XXXX(_CONST(28)), ureg_negate(_Z(tmp))); + ureg_MUL(ureg, ureg_saturate(tmp_x), _X(tmp), _YYYY(_CONST(28))); + } + ureg_MOV(ureg, oFog, _X(tmp)); + ureg_release_temporary(ureg, tmp); + } else if (key->fog && !(key->passthrough & (1 << NINE_DECLUSAGE_FOG))) { + ureg_MOV(ureg, oFog, ureg_scalar(vs->aCol[1], TGSI_SWIZZLE_W)); + } + + if (key->passthrough & (1 << NINE_DECLUSAGE_BLENDWEIGHT)) { + struct ureg_src input; + struct ureg_dst output; + input = vs->aWgt; + output = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 19); + ureg_MOV(ureg, output, input); + } + if (key->passthrough & (1 << NINE_DECLUSAGE_BLENDINDICES)) { + struct ureg_src input; + struct ureg_dst output; + input = vs->aInd; + output = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 20); + ureg_MOV(ureg, output, input); + } + if (key->passthrough & (1 << NINE_DECLUSAGE_NORMAL)) { + struct ureg_src input; + struct ureg_dst output; + input = vs->aNrm; + output = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 21); + ureg_MOV(ureg, output, input); + } + if (key->passthrough & (1 << NINE_DECLUSAGE_TANGENT)) { + struct ureg_src input; + struct ureg_dst output; + input = build_vs_add_input(vs, NINE_DECLUSAGE_TANGENT); + output = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 22); + ureg_MOV(ureg, output, input); + } + if (key->passthrough & (1 << NINE_DECLUSAGE_BINORMAL)) { + struct ureg_src input; + struct ureg_dst output; + input = build_vs_add_input(vs, NINE_DECLUSAGE_BINORMAL); + output = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 23); + ureg_MOV(ureg, output, input); + } + if (key->passthrough & (1 << NINE_DECLUSAGE_FOG)) { + struct ureg_src input; + struct ureg_dst output; + input = build_vs_add_input(vs, NINE_DECLUSAGE_FOG); + input = ureg_scalar(input, TGSI_SWIZZLE_X); + output = oFog; + ureg_MOV(ureg, output, input); + } + if (key->passthrough & (1 << NINE_DECLUSAGE_DEPTH)) { + (void) 0; /* TODO: replace z of position output ? */ + } + + /* ucp for ff applies on world coordinates. + * aVtx is in worldview coordinates. */ + if (key->ucp) { + struct ureg_dst clipVect = ureg_DECL_output(ureg, TGSI_SEMANTIC_CLIPVERTEX, 0); + struct ureg_dst tmp = ureg_DECL_temporary(ureg); + ureg_MUL(ureg, tmp, _XXXX(vs->aVtx), _CONST(12)); + ureg_MAD(ureg, tmp, _YYYY(vs->aVtx), _CONST(13), ureg_src(tmp)); + ureg_MAD(ureg, tmp, _ZZZZ(vs->aVtx), _CONST(14), ureg_src(tmp)); + ureg_ADD(ureg, clipVect, _CONST(15), ureg_src(tmp)); + ureg_release_temporary(ureg, tmp); + } + + if (key->position_t && device->driver_caps.window_space_position_support) + ureg_property(ureg, TGSI_PROPERTY_VS_WINDOW_SPACE_POSITION, TRUE); + + ureg_END(ureg); + nine_ureg_tgsi_dump(ureg, FALSE); + return nine_create_shader_with_so_and_destroy(ureg, device->context.pipe, NULL); +} + +/* PS FF constants layout: + * + * CONST[ 0.. 7] stage[i].D3DTSS_CONSTANT + * CONST[ 8..15].x___ stage[i].D3DTSS_BUMPENVMAT00 + * CONST[ 8..15]._y__ stage[i].D3DTSS_BUMPENVMAT01 + * CONST[ 8..15].__z_ stage[i].D3DTSS_BUMPENVMAT10 + * CONST[ 8..15].___w stage[i].D3DTSS_BUMPENVMAT11 + * CONST[16..19].x_z_ stage[i].D3DTSS_BUMPENVLSCALE + * CONST[17..19]._y_w stage[i].D3DTSS_BUMPENVLOFFSET + * + * CONST[20] D3DRS_TEXTUREFACTOR + * CONST[21] D3DRS_FOGCOLOR + * CONST[22].x___ RS.FogEnd + * CONST[22]._y__ 1.0f / (RS.FogEnd - RS.FogStart) + * CONST[22].__z_ RS.FogDensity + */ +struct ps_build_ctx +{ + struct ureg_program *ureg; + + struct ureg_src vC[2]; /* DIFFUSE, SPECULAR */ + struct ureg_src vT[8]; /* TEXCOORD[i] */ + struct ureg_dst rCur; /* D3DTA_CURRENT */ + struct ureg_dst rMod; + struct ureg_src rCurSrc; + struct ureg_dst rTmp; /* D3DTA_TEMP */ + struct ureg_src rTmpSrc; + struct ureg_dst rTex; + struct ureg_src rTexSrc; + struct ureg_src cBEM[8]; + struct ureg_src s[8]; + + struct { + unsigned index; + unsigned index_pre_mod; + } stage; +}; + +static struct ureg_src +ps_get_ts_arg(struct ps_build_ctx *ps, unsigned ta) +{ + struct ureg_src reg; + + switch (ta & D3DTA_SELECTMASK) { + case D3DTA_CONSTANT: + reg = ureg_DECL_constant(ps->ureg, ps->stage.index); + break; + case D3DTA_CURRENT: + reg = (ps->stage.index == ps->stage.index_pre_mod) ? ureg_src(ps->rMod) : ps->rCurSrc; + break; + case D3DTA_DIFFUSE: + reg = ureg_DECL_fs_input(ps->ureg, TGSI_SEMANTIC_COLOR, 0, TGSI_INTERPOLATE_COLOR); + break; + case D3DTA_SPECULAR: + reg = ureg_DECL_fs_input(ps->ureg, TGSI_SEMANTIC_COLOR, 1, TGSI_INTERPOLATE_COLOR); + break; + case D3DTA_TEMP: + reg = ps->rTmpSrc; + break; + case D3DTA_TEXTURE: + reg = ps->rTexSrc; + break; + case D3DTA_TFACTOR: + reg = ureg_DECL_constant(ps->ureg, 20); + break; + default: + assert(0); + reg = ureg_src_undef(); + break; + } + if (ta & D3DTA_COMPLEMENT) { + struct ureg_dst dst = ureg_DECL_temporary(ps->ureg); + ureg_ADD(ps->ureg, dst, ureg_imm1f(ps->ureg, 1.0f), ureg_negate(reg)); + reg = ureg_src(dst); + } + if (ta & D3DTA_ALPHAREPLICATE) + reg = _WWWW(reg); + return reg; +} + +static struct ureg_dst +ps_get_ts_dst(struct ps_build_ctx *ps, unsigned ta) +{ + assert(!(ta & (D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE))); + + switch (ta & D3DTA_SELECTMASK) { + case D3DTA_CURRENT: + return ps->rCur; + case D3DTA_TEMP: + return ps->rTmp; + default: + assert(0); + return ureg_dst_undef(); + } +} + +static uint8_t ps_d3dtop_args_mask(D3DTEXTUREOP top) +{ + switch (top) { + case D3DTOP_DISABLE: + return 0x0; + case D3DTOP_SELECTARG1: + case D3DTOP_PREMODULATE: + return 0x2; + case D3DTOP_SELECTARG2: + return 0x4; + case D3DTOP_MULTIPLYADD: + case D3DTOP_LERP: + return 0x7; + default: + return 0x6; + } +} + +static inline boolean +is_MOV_no_op(struct ureg_dst dst, struct ureg_src src) +{ + return !dst.WriteMask || + (dst.File == src.File && + dst.Index == src.Index && + !dst.Indirect && + !dst.Saturate && + !src.Indirect && + !src.Negate && + !src.Absolute && + (!(dst.WriteMask & TGSI_WRITEMASK_X) || (src.SwizzleX == TGSI_SWIZZLE_X)) && + (!(dst.WriteMask & TGSI_WRITEMASK_Y) || (src.SwizzleY == TGSI_SWIZZLE_Y)) && + (!(dst.WriteMask & TGSI_WRITEMASK_Z) || (src.SwizzleZ == TGSI_SWIZZLE_Z)) && + (!(dst.WriteMask & TGSI_WRITEMASK_W) || (src.SwizzleW == TGSI_SWIZZLE_W))); + +} + +static void +ps_do_ts_op(struct ps_build_ctx *ps, unsigned top, struct ureg_dst dst, struct ureg_src *arg) +{ + struct ureg_program *ureg = ps->ureg; + struct ureg_dst tmp = ureg_DECL_temporary(ureg); + struct ureg_dst tmp2 = ureg_DECL_temporary(ureg); + struct ureg_dst tmp_x = ureg_writemask(tmp, TGSI_WRITEMASK_X); + + tmp.WriteMask = dst.WriteMask; + + if (top != D3DTOP_SELECTARG1 && top != D3DTOP_SELECTARG2 && + top != D3DTOP_MODULATE && top != D3DTOP_PREMODULATE && + top != D3DTOP_BLENDDIFFUSEALPHA && top != D3DTOP_BLENDTEXTUREALPHA && + top != D3DTOP_BLENDFACTORALPHA && top != D3DTOP_BLENDCURRENTALPHA && + top != D3DTOP_BUMPENVMAP && top != D3DTOP_BUMPENVMAPLUMINANCE && + top != D3DTOP_LERP) + dst = ureg_saturate(dst); + + switch (top) { + case D3DTOP_SELECTARG1: + if (!is_MOV_no_op(dst, arg[1])) + ureg_MOV(ureg, dst, arg[1]); + break; + case D3DTOP_SELECTARG2: + if (!is_MOV_no_op(dst, arg[2])) + ureg_MOV(ureg, dst, arg[2]); + break; + case D3DTOP_MODULATE: + ureg_MUL(ureg, dst, arg[1], arg[2]); + break; + case D3DTOP_MODULATE2X: + ureg_MUL(ureg, tmp, arg[1], arg[2]); + ureg_ADD(ureg, dst, ureg_src(tmp), ureg_src(tmp)); + break; + case D3DTOP_MODULATE4X: + ureg_MUL(ureg, tmp, arg[1], arg[2]); + ureg_MUL(ureg, dst, ureg_src(tmp), ureg_imm1f(ureg, 4.0f)); + break; + case D3DTOP_ADD: + ureg_ADD(ureg, dst, arg[1], arg[2]); + break; + case D3DTOP_ADDSIGNED: + ureg_ADD(ureg, tmp, arg[1], arg[2]); + ureg_ADD(ureg, dst, ureg_src(tmp), ureg_imm1f(ureg, -0.5f)); + break; + case D3DTOP_ADDSIGNED2X: + ureg_ADD(ureg, tmp, arg[1], arg[2]); + ureg_MAD(ureg, dst, ureg_src(tmp), ureg_imm1f(ureg, 2.0f), ureg_imm1f(ureg, -1.0f)); + break; + case D3DTOP_SUBTRACT: + ureg_ADD(ureg, dst, arg[1], ureg_negate(arg[2])); + break; + case D3DTOP_ADDSMOOTH: + ureg_ADD(ureg, tmp, ureg_imm1f(ureg, 1.0f), ureg_negate(arg[1])); + ureg_MAD(ureg, dst, ureg_src(tmp), arg[2], arg[1]); + break; + case D3DTOP_BLENDDIFFUSEALPHA: + ureg_LRP(ureg, dst, _WWWW(ps->vC[0]), arg[1], arg[2]); + break; + case D3DTOP_BLENDTEXTUREALPHA: + /* XXX: alpha taken from previous stage, texture or result ? */ + ureg_LRP(ureg, dst, _W(ps->rTex), arg[1], arg[2]); + break; + case D3DTOP_BLENDFACTORALPHA: + ureg_LRP(ureg, dst, _WWWW(_CONST(20)), arg[1], arg[2]); + break; + case D3DTOP_BLENDTEXTUREALPHAPM: + ureg_ADD(ureg, tmp_x, ureg_imm1f(ureg, 1.0f), ureg_negate(_W(ps->rTex))); + ureg_MAD(ureg, dst, arg[2], _X(tmp), arg[1]); + break; + case D3DTOP_BLENDCURRENTALPHA: + ureg_LRP(ureg, dst, _WWWW(ps->rCurSrc), arg[1], arg[2]); + break; + case D3DTOP_PREMODULATE: + ureg_MOV(ureg, dst, arg[1]); + ps->stage.index_pre_mod = ps->stage.index + 1; + break; + case D3DTOP_MODULATEALPHA_ADDCOLOR: + ureg_MAD(ureg, dst, _WWWW(arg[1]), arg[2], arg[1]); + break; + case D3DTOP_MODULATECOLOR_ADDALPHA: + ureg_MAD(ureg, dst, arg[1], arg[2], _WWWW(arg[1])); + break; + case D3DTOP_MODULATEINVALPHA_ADDCOLOR: + ureg_ADD(ureg, tmp_x, ureg_imm1f(ureg, 1.0f), ureg_negate(_WWWW(arg[1]))); + ureg_MAD(ureg, dst, _X(tmp), arg[2], arg[1]); + break; + case D3DTOP_MODULATEINVCOLOR_ADDALPHA: + ureg_ADD(ureg, tmp, ureg_imm1f(ureg, 1.0f), ureg_negate(arg[1])); + ureg_MAD(ureg, dst, ureg_src(tmp), arg[2], _WWWW(arg[1])); + break; + case D3DTOP_BUMPENVMAP: + break; + case D3DTOP_BUMPENVMAPLUMINANCE: + break; + case D3DTOP_DOTPRODUCT3: + ureg_ADD(ureg, tmp, arg[1], ureg_imm4f(ureg,-0.5,-0.5,-0.5,-0.5)); + ureg_ADD(ureg, tmp2, arg[2] , ureg_imm4f(ureg,-0.5,-0.5,-0.5,-0.5)); + ureg_DP3(ureg, tmp, ureg_src(tmp), ureg_src(tmp2)); + ureg_MUL(ureg, ureg_saturate(dst), ureg_src(tmp), ureg_imm4f(ureg,4.0,4.0,4.0,4.0)); + break; + case D3DTOP_MULTIPLYADD: + ureg_MAD(ureg, dst, arg[1], arg[2], arg[0]); + break; + case D3DTOP_LERP: + ureg_LRP(ureg, dst, arg[0], arg[1], arg[2]); + break; + case D3DTOP_DISABLE: + /* no-op ? */ + break; + default: + assert(!"invalid D3DTOP"); + break; + } + ureg_release_temporary(ureg, tmp); + ureg_release_temporary(ureg, tmp2); +} + +static void * +nine_ff_build_ps(struct NineDevice9 *device, struct nine_ff_ps_key *key) +{ + struct ps_build_ctx ps; + struct ureg_program *ureg = ureg_create(PIPE_SHADER_FRAGMENT); + struct ureg_dst oCol; + unsigned s; + const unsigned texcoord_sn = get_texcoord_sn(device->screen); + + memset(&ps, 0, sizeof(ps)); + ps.ureg = ureg; + ps.stage.index_pre_mod = -1; + + ps.vC[0] = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_COLOR, 0, TGSI_INTERPOLATE_COLOR); + + ps.rCur = ureg_DECL_temporary(ureg); + ps.rTmp = ureg_DECL_temporary(ureg); + ps.rTex = ureg_DECL_temporary(ureg); + ps.rCurSrc = ureg_src(ps.rCur); + ps.rTmpSrc = ureg_src(ps.rTmp); + ps.rTexSrc = ureg_src(ps.rTex); + + /* Initial values */ + ureg_MOV(ureg, ps.rCur, ps.vC[0]); + ureg_MOV(ureg, ps.rTmp, ureg_imm1f(ureg, 0.0f)); + ureg_MOV(ureg, ps.rTex, ureg_imm1f(ureg, 0.0f)); + + for (s = 0; s < 8; ++s) { + ps.s[s] = ureg_src_undef(); + + if (key->ts[s].colorop != D3DTOP_DISABLE) { + if (key->ts[s].colorarg0 == D3DTA_SPECULAR || + key->ts[s].colorarg1 == D3DTA_SPECULAR || + key->ts[s].colorarg2 == D3DTA_SPECULAR) + ps.vC[1] = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_COLOR, 1, TGSI_INTERPOLATE_COLOR); + + if (key->ts[s].colorarg0 == D3DTA_TEXTURE || + key->ts[s].colorarg1 == D3DTA_TEXTURE || + key->ts[s].colorarg2 == D3DTA_TEXTURE) { + ps.s[s] = ureg_DECL_sampler(ureg, s); + ps.vT[s] = ureg_DECL_fs_input(ureg, texcoord_sn, s, TGSI_INTERPOLATE_PERSPECTIVE); + } + if (s && (key->ts[s - 1].colorop == D3DTOP_PREMODULATE || + key->ts[s - 1].alphaop == D3DTOP_PREMODULATE)) + ps.s[s] = ureg_DECL_sampler(ureg, s); + } + + if (key->ts[s].alphaop != D3DTOP_DISABLE) { + if (key->ts[s].alphaarg0 == D3DTA_SPECULAR || + key->ts[s].alphaarg1 == D3DTA_SPECULAR || + key->ts[s].alphaarg2 == D3DTA_SPECULAR) + ps.vC[1] = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_COLOR, 1, TGSI_INTERPOLATE_COLOR); + + if (key->ts[s].alphaarg0 == D3DTA_TEXTURE || + key->ts[s].alphaarg1 == D3DTA_TEXTURE || + key->ts[s].alphaarg2 == D3DTA_TEXTURE) { + ps.s[s] = ureg_DECL_sampler(ureg, s); + ps.vT[s] = ureg_DECL_fs_input(ureg, texcoord_sn, s, TGSI_INTERPOLATE_PERSPECTIVE); + } + } + } + if (key->specular) + ps.vC[1] = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_COLOR, 1, TGSI_INTERPOLATE_COLOR); + + oCol = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0); + + /* Run stages. + */ + for (s = 0; s < 8; ++s) { + unsigned colorarg[3]; + unsigned alphaarg[3]; + const uint8_t used_c = ps_d3dtop_args_mask(key->ts[s].colorop); + const uint8_t used_a = ps_d3dtop_args_mask(key->ts[s].alphaop); + struct ureg_dst dst; + struct ureg_src arg[3]; + + if (key->ts[s].colorop == D3DTOP_DISABLE) { + assert (key->ts[s].alphaop == D3DTOP_DISABLE); + continue; + } + ps.stage.index = s; + + DBG("STAGE[%u]: colorop=%s alphaop=%s\n", s, + nine_D3DTOP_to_str(key->ts[s].colorop), + nine_D3DTOP_to_str(key->ts[s].alphaop)); + + if (!ureg_src_is_undef(ps.s[s])) { + unsigned target; + struct ureg_src texture_coord = ps.vT[s]; + struct ureg_dst delta; + switch (key->ts[s].textarget) { + case 0: target = TGSI_TEXTURE_1D; break; + case 1: target = TGSI_TEXTURE_2D; break; + case 2: target = TGSI_TEXTURE_3D; break; + case 3: target = TGSI_TEXTURE_CUBE; break; + /* this is a 2 bit bitfield, do I really need a default case ? */ + } + + /* Modify coordinates */ + if (s >= 1 && + (key->ts[s-1].colorop == D3DTOP_BUMPENVMAP || + key->ts[s-1].colorop == D3DTOP_BUMPENVMAPLUMINANCE)) { + delta = ureg_DECL_temporary(ureg); + /* Du' = D3DTSS_BUMPENVMAT00(stage s-1)*t(s-1)R + D3DTSS_BUMPENVMAT10(stage s-1)*t(s-1)G */ + ureg_MUL(ureg, ureg_writemask(delta, TGSI_WRITEMASK_X), _X(ps.rTex), _XXXX(_CONST(8 + s - 1))); + ureg_MAD(ureg, ureg_writemask(delta, TGSI_WRITEMASK_X), _Y(ps.rTex), _ZZZZ(_CONST(8 + s - 1)), ureg_src(delta)); + /* Dv' = D3DTSS_BUMPENVMAT01(stage s-1)*t(s-1)R + D3DTSS_BUMPENVMAT11(stage s-1)*t(s-1)G */ + ureg_MUL(ureg, ureg_writemask(delta, TGSI_WRITEMASK_Y), _X(ps.rTex), _YYYY(_CONST(8 + s - 1))); + ureg_MAD(ureg, ureg_writemask(delta, TGSI_WRITEMASK_Y), _Y(ps.rTex), _WWWW(_CONST(8 + s - 1)), ureg_src(delta)); + texture_coord = ureg_src(ureg_DECL_temporary(ureg)); + ureg_MOV(ureg, ureg_writemask(ureg_dst(texture_coord), ureg_dst(ps.vT[s]).WriteMask), ps.vT[s]); + ureg_ADD(ureg, ureg_writemask(ureg_dst(texture_coord), TGSI_WRITEMASK_XY), texture_coord, ureg_src(delta)); + /* Prepare luminance multiplier + * t(s)RGBA = t(s)RGBA * clamp[(t(s-1)B * D3DTSS_BUMPENVLSCALE(stage s-1)) + D3DTSS_BUMPENVLOFFSET(stage s-1)] */ + if (key->ts[s-1].colorop == D3DTOP_BUMPENVMAPLUMINANCE) { + struct ureg_src bumpenvlscale = ((s-1) & 1) ? _ZZZZ(_CONST(16 + (s-1) / 2)) : _XXXX(_CONST(16 + (s-1) / 2)); + struct ureg_src bumpenvloffset = ((s-1) & 1) ? _WWWW(_CONST(16 + (s-1) / 2)) : _YYYY(_CONST(16 + (s-1) / 2)); + + ureg_MAD(ureg, ureg_saturate(ureg_writemask(delta, TGSI_WRITEMASK_X)), _Z(ps.rTex), bumpenvlscale, bumpenvloffset); + } + } + if (key->projected & (3 << (s *2))) { + unsigned dim = 1 + ((key->projected >> (2 * s)) & 3); + if (dim == 4) + ureg_TXP(ureg, ps.rTex, target, texture_coord, ps.s[s]); + else { + struct ureg_dst tmp = ureg_DECL_temporary(ureg); + ureg_RCP(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), ureg_scalar(texture_coord, dim-1)); + ureg_MUL(ureg, ps.rTmp, _X(tmp), texture_coord); + ureg_TEX(ureg, ps.rTex, target, ps.rTmpSrc, ps.s[s]); + ureg_release_temporary(ureg, tmp); + } + } else { + ureg_TEX(ureg, ps.rTex, target, texture_coord, ps.s[s]); + } + if (s >= 1 && key->ts[s-1].colorop == D3DTOP_BUMPENVMAPLUMINANCE) + ureg_MUL(ureg, ps.rTex, ureg_src(ps.rTex), _X(delta)); + } + + if (key->ts[s].colorop == D3DTOP_BUMPENVMAP || + key->ts[s].colorop == D3DTOP_BUMPENVMAPLUMINANCE) + continue; + + dst = ps_get_ts_dst(&ps, key->ts[s].resultarg ? D3DTA_TEMP : D3DTA_CURRENT); + + if (ps.stage.index_pre_mod == ps.stage.index) { + ps.rMod = ureg_DECL_temporary(ureg); + ureg_MUL(ureg, ps.rMod, ps.rCurSrc, ps.rTexSrc); + } + + colorarg[0] = (key->ts[s].colorarg0 | (((key->colorarg_b4[0] >> s) & 0x1) << 4) | ((key->colorarg_b5[0] >> s) << 5)) & 0x3f; + colorarg[1] = (key->ts[s].colorarg1 | (((key->colorarg_b4[1] >> s) & 0x1) << 4) | ((key->colorarg_b5[1] >> s) << 5)) & 0x3f; + colorarg[2] = (key->ts[s].colorarg2 | (((key->colorarg_b4[2] >> s) & 0x1) << 4) | ((key->colorarg_b5[2] >> s) << 5)) & 0x3f; + alphaarg[0] = (key->ts[s].alphaarg0 | ((key->alphaarg_b4[0] >> s) << 4)) & 0x1f; + alphaarg[1] = (key->ts[s].alphaarg1 | ((key->alphaarg_b4[1] >> s) << 4)) & 0x1f; + alphaarg[2] = (key->ts[s].alphaarg2 | ((key->alphaarg_b4[2] >> s) << 4)) & 0x1f; + + if (key->ts[s].colorop != key->ts[s].alphaop || + colorarg[0] != alphaarg[0] || + colorarg[1] != alphaarg[1] || + colorarg[2] != alphaarg[2]) + dst.WriteMask = TGSI_WRITEMASK_XYZ; + + /* Special DOTPRODUCT behaviour (see wine tests) */ + if (key->ts[s].colorop == D3DTOP_DOTPRODUCT3) + dst.WriteMask = TGSI_WRITEMASK_XYZW; + + if (used_c & 0x1) arg[0] = ps_get_ts_arg(&ps, colorarg[0]); + if (used_c & 0x2) arg[1] = ps_get_ts_arg(&ps, colorarg[1]); + if (used_c & 0x4) arg[2] = ps_get_ts_arg(&ps, colorarg[2]); + ps_do_ts_op(&ps, key->ts[s].colorop, dst, arg); + + if (dst.WriteMask != TGSI_WRITEMASK_XYZW) { + dst.WriteMask = TGSI_WRITEMASK_W; + + if (used_a & 0x1) arg[0] = ps_get_ts_arg(&ps, alphaarg[0]); + if (used_a & 0x2) arg[1] = ps_get_ts_arg(&ps, alphaarg[1]); + if (used_a & 0x4) arg[2] = ps_get_ts_arg(&ps, alphaarg[2]); + ps_do_ts_op(&ps, key->ts[s].alphaop, dst, arg); + } + } + + if (key->specular) + ureg_ADD(ureg, ureg_writemask(ps.rCur, TGSI_WRITEMASK_XYZ), ps.rCurSrc, ps.vC[1]); + + /* Fog. + */ + if (key->fog_mode) { + struct ureg_dst rFog = ureg_writemask(ps.rTmp, TGSI_WRITEMASK_X); + struct ureg_src vPos; + if (device->screen->get_param(device->screen, + PIPE_CAP_TGSI_FS_POSITION_IS_SYSVAL)) { + vPos = ureg_DECL_system_value(ureg, TGSI_SEMANTIC_POSITION, 0); + } else { + vPos = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_POSITION, 0, + TGSI_INTERPOLATE_LINEAR); + } + + /* Source is either W or Z. + * When we use vs ff, + * Z is when an orthogonal projection matrix is detected, + * W (WFOG) else. + * Z is used for programmable vs. + * Note: Tests indicate that the projection matrix coefficients do + * actually affect pixel fog (and not vertex fog) when vs ff is used, + * which justifies taking the position's w instead of taking the z coordinate + * before the projection in the vs shader. + */ + if (!key->fog_source) + ureg_MOV(ureg, rFog, _ZZZZ(vPos)); + else + /* Position's w is 1/w */ + ureg_RCP(ureg, rFog, _WWWW(vPos)); + + if (key->fog_mode == D3DFOG_EXP) { + ureg_MUL(ureg, rFog, _X(rFog), _ZZZZ(_CONST(22))); + ureg_MUL(ureg, rFog, _X(rFog), ureg_imm1f(ureg, -1.442695f)); + ureg_EX2(ureg, rFog, _X(rFog)); + } else + if (key->fog_mode == D3DFOG_EXP2) { + ureg_MUL(ureg, rFog, _X(rFog), _ZZZZ(_CONST(22))); + ureg_MUL(ureg, rFog, _X(rFog), _X(rFog)); + ureg_MUL(ureg, rFog, _X(rFog), ureg_imm1f(ureg, -1.442695f)); + ureg_EX2(ureg, rFog, _X(rFog)); + } else + if (key->fog_mode == D3DFOG_LINEAR) { + ureg_ADD(ureg, rFog, _XXXX(_CONST(22)), ureg_negate(_X(rFog))); + ureg_MUL(ureg, ureg_saturate(rFog), _X(rFog), _YYYY(_CONST(22))); + } + ureg_LRP(ureg, ureg_writemask(oCol, TGSI_WRITEMASK_XYZ), _X(rFog), ps.rCurSrc, _CONST(21)); + ureg_MOV(ureg, ureg_writemask(oCol, TGSI_WRITEMASK_W), ps.rCurSrc); + } else + if (key->fog) { + struct ureg_src vFog = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_GENERIC, 16, TGSI_INTERPOLATE_PERSPECTIVE); + ureg_LRP(ureg, ureg_writemask(oCol, TGSI_WRITEMASK_XYZ), _XXXX(vFog), ps.rCurSrc, _CONST(21)); + ureg_MOV(ureg, ureg_writemask(oCol, TGSI_WRITEMASK_W), ps.rCurSrc); + } else { + ureg_MOV(ureg, oCol, ps.rCurSrc); + } + + ureg_END(ureg); + nine_ureg_tgsi_dump(ureg, FALSE); + return nine_create_shader_with_so_and_destroy(ureg, device->context.pipe, NULL); +} + +static struct NineVertexShader9 * +nine_ff_get_vs(struct NineDevice9 *device) +{ + const struct nine_context *context = &device->context; + struct NineVertexShader9 *vs; + struct vs_build_ctx bld; + struct nine_ff_vs_key key; + unsigned s, i; + boolean has_indexes = false; + boolean has_weights = false; + char input_texture_coord[8]; + + assert(sizeof(key) <= sizeof(key.value32)); + + memset(&key, 0, sizeof(key)); + memset(&bld, 0, sizeof(bld)); + memset(&input_texture_coord, 0, sizeof(input_texture_coord)); + + bld.key = &key; + + /* FIXME: this shouldn't be NULL, but it is on init */ + if (context->vdecl) { + key.color0in_one = 1; + key.color1in_zero = 1; + for (i = 0; i < context->vdecl->nelems; i++) { + uint16_t usage = context->vdecl->usage_map[i]; + if (usage == NINE_DECLUSAGE_POSITIONT) + key.position_t = 1; + else if (usage == NINE_DECLUSAGE_i(COLOR, 0)) + key.color0in_one = 0; + else if (usage == NINE_DECLUSAGE_i(COLOR, 1)) + key.color1in_zero = 0; + else if (usage == NINE_DECLUSAGE_i(BLENDINDICES, 0)) { + has_indexes = true; + key.passthrough |= 1 << usage; + } else if (usage == NINE_DECLUSAGE_i(BLENDWEIGHT, 0)) { + has_weights = true; + key.passthrough |= 1 << usage; + } else if (usage == NINE_DECLUSAGE_i(NORMAL, 0)) { + key.has_normal = 1; + key.passthrough |= 1 << usage; + } else if (usage == NINE_DECLUSAGE_PSIZE) + key.vertexpointsize = 1; + else if (usage % NINE_DECLUSAGE_COUNT == NINE_DECLUSAGE_TEXCOORD) { + s = usage / NINE_DECLUSAGE_COUNT; + if (s < 8) + input_texture_coord[s] = nine_decltype_get_dim(context->vdecl->decls[i].Type); + else + DBG("FF given texture coordinate >= 8. Ignoring\n"); + } else if (usage < NINE_DECLUSAGE_NONE) + key.passthrough |= 1 << usage; + } + } + /* ff vs + ps 3.0: some elements are passed to the ps (wine test). + * We do restrict to indices 0 */ + key.passthrough &= ~((1 << NINE_DECLUSAGE_POSITION) | (1 << NINE_DECLUSAGE_PSIZE) | + (1 << NINE_DECLUSAGE_TEXCOORD) | (1 << NINE_DECLUSAGE_POSITIONT) | + (1 << NINE_DECLUSAGE_TESSFACTOR) | (1 << NINE_DECLUSAGE_SAMPLE)); + if (!key.position_t) + key.passthrough = 0; + key.pointscale = !!context->rs[D3DRS_POINTSCALEENABLE]; + + key.lighting = !!context->rs[D3DRS_LIGHTING] && context->ff.num_lights_active; + key.darkness = !!context->rs[D3DRS_LIGHTING] && !context->ff.num_lights_active; + if (key.position_t) { + key.darkness = 0; /* |= key.lighting; */ /* XXX ? */ + key.lighting = 0; + } + if ((key.lighting | key.darkness) && context->rs[D3DRS_COLORVERTEX]) { + uint32_t mask = (key.color0in_one ? 0 : 1) | (key.color1in_zero ? 0 : 2); + key.mtl_diffuse = context->rs[D3DRS_DIFFUSEMATERIALSOURCE] & mask; + key.mtl_ambient = context->rs[D3DRS_AMBIENTMATERIALSOURCE] & mask; + key.mtl_specular = context->rs[D3DRS_SPECULARMATERIALSOURCE] & mask; + key.mtl_emissive = context->rs[D3DRS_EMISSIVEMATERIALSOURCE] & mask; + } + key.fog = !!context->rs[D3DRS_FOGENABLE]; + key.fog_mode = (!key.position_t && context->rs[D3DRS_FOGENABLE]) ? context->rs[D3DRS_FOGVERTEXMODE] : 0; + if (key.fog_mode) + key.fog_range = context->rs[D3DRS_RANGEFOGENABLE]; + + key.localviewer = !!context->rs[D3DRS_LOCALVIEWER]; + key.normalizenormals = !!context->rs[D3DRS_NORMALIZENORMALS]; + key.ucp = !!context->rs[D3DRS_CLIPPLANEENABLE]; + + if (context->rs[D3DRS_VERTEXBLEND] != D3DVBF_DISABLE) { + key.vertexblend_indexed = !!context->rs[D3DRS_INDEXEDVERTEXBLENDENABLE] && has_indexes; + + switch (context->rs[D3DRS_VERTEXBLEND]) { + case D3DVBF_0WEIGHTS: key.vertexblend = key.vertexblend_indexed; break; + case D3DVBF_1WEIGHTS: key.vertexblend = 2; break; + case D3DVBF_2WEIGHTS: key.vertexblend = 3; break; + case D3DVBF_3WEIGHTS: key.vertexblend = 4; break; + case D3DVBF_TWEENING: key.vertextween = 1; break; + default: + assert(!"invalid D3DVBF"); + break; + } + if (!has_weights && context->rs[D3DRS_VERTEXBLEND] != D3DVBF_0WEIGHTS) + key.vertexblend = 0; /* TODO: if key.vertexblend_indexed, perhaps it should use 1.0 as weight, or revert to D3DVBF_0WEIGHTS */ + } + + for (s = 0; s < 8; ++s) { + unsigned gen = (context->ff.tex_stage[s][D3DTSS_TEXCOORDINDEX] >> 16) + 1; + unsigned idx = context->ff.tex_stage[s][D3DTSS_TEXCOORDINDEX] & 7; + unsigned dim; + + if (key.position_t && gen > NINED3DTSS_TCI_PASSTHRU) + gen = NINED3DTSS_TCI_PASSTHRU; + + if (!input_texture_coord[idx] && gen == NINED3DTSS_TCI_PASSTHRU) + gen = NINED3DTSS_TCI_DISABLE; + + key.tc_gen |= gen << (s * 3); + key.tc_idx |= idx << (s * 3); + key.tc_dim_input |= ((input_texture_coord[idx]-1) & 0x3) << (s * 2); + + dim = context->ff.tex_stage[s][D3DTSS_TEXTURETRANSFORMFLAGS] & 0x7; + if (dim > 4) + dim = input_texture_coord[idx]; + if (dim == 1) /* NV behaviour */ + dim = 0; + key.tc_dim_output |= dim << (s * 3); + } + + DBG("VS ff key hash: %x\n", nine_ff_vs_key_hash(&key)); + vs = util_hash_table_get(device->ff.ht_vs, &key); + if (vs) + return vs; + NineVertexShader9_new(device, &vs, NULL, nine_ff_build_vs(device, &bld)); + + nine_ff_prune_vs(device); + if (vs) { + unsigned n; + + memcpy(&vs->ff_key, &key, sizeof(vs->ff_key)); + + _mesa_hash_table_insert(device->ff.ht_vs, &vs->ff_key, vs); + device->ff.num_vs++; + + vs->num_inputs = bld.num_inputs; + for (n = 0; n < bld.num_inputs; ++n) + vs->input_map[n].ndecl = bld.input[n]; + + vs->position_t = key.position_t; + vs->point_size = key.vertexpointsize | key.pointscale; + } + return vs; +} + +#define GET_D3DTS(n) nine_state_access_transform(&context->ff, D3DTS_##n, FALSE) +#define IS_D3DTS_DIRTY(s,n) ((s)->ff.changed.transform[(D3DTS_##n) / 32] & (1 << ((D3DTS_##n) % 32))) + +static struct NinePixelShader9 * +nine_ff_get_ps(struct NineDevice9 *device) +{ + struct nine_context *context = &device->context; + D3DMATRIX *projection_matrix = GET_D3DTS(PROJECTION); + struct NinePixelShader9 *ps; + struct nine_ff_ps_key key; + unsigned s; + uint8_t sampler_mask = 0; + + assert(sizeof(key) <= sizeof(key.value32)); + + memset(&key, 0, sizeof(key)); + for (s = 0; s < 8; ++s) { + key.ts[s].colorop = context->ff.tex_stage[s][D3DTSS_COLOROP]; + key.ts[s].alphaop = context->ff.tex_stage[s][D3DTSS_ALPHAOP]; + const uint8_t used_c = ps_d3dtop_args_mask(key.ts[s].colorop); + const uint8_t used_a = ps_d3dtop_args_mask(key.ts[s].alphaop); + /* MSDN says D3DTOP_DISABLE disables this and all subsequent stages. + * ALPHAOP cannot be enabled if COLOROP is disabled. + * Verified on Windows. */ + if (key.ts[s].colorop == D3DTOP_DISABLE) { + key.ts[s].alphaop = D3DTOP_DISABLE; /* DISABLE == 1, avoid degenerate keys */ + break; + } + + if (!context->texture[s].enabled && + ((context->ff.tex_stage[s][D3DTSS_COLORARG0] == D3DTA_TEXTURE && + used_c & 0x1) || + (context->ff.tex_stage[s][D3DTSS_COLORARG1] == D3DTA_TEXTURE && + used_c & 0x2) || + (context->ff.tex_stage[s][D3DTSS_COLORARG2] == D3DTA_TEXTURE && + used_c & 0x4))) { + /* Tested on Windows: Invalid texture read disables the stage + * and the subsequent ones, but only for colorop. For alpha, + * it's as if the texture had alpha of 1.0, which is what + * has our dummy texture in that case. Invalid color also + * disabled the following alpha stages. */ + key.ts[s].colorop = key.ts[s].alphaop = D3DTOP_DISABLE; + break; + } + + if (context->ff.tex_stage[s][D3DTSS_COLORARG0] == D3DTA_TEXTURE || + context->ff.tex_stage[s][D3DTSS_COLORARG1] == D3DTA_TEXTURE || + context->ff.tex_stage[s][D3DTSS_COLORARG2] == D3DTA_TEXTURE || + context->ff.tex_stage[s][D3DTSS_ALPHAARG0] == D3DTA_TEXTURE || + context->ff.tex_stage[s][D3DTSS_ALPHAARG1] == D3DTA_TEXTURE || + context->ff.tex_stage[s][D3DTSS_ALPHAARG2] == D3DTA_TEXTURE) + sampler_mask |= (1 << s); + + if (key.ts[s].colorop != D3DTOP_DISABLE) { + if (used_c & 0x1) key.ts[s].colorarg0 = context->ff.tex_stage[s][D3DTSS_COLORARG0] & 0x7; + if (used_c & 0x2) key.ts[s].colorarg1 = context->ff.tex_stage[s][D3DTSS_COLORARG1] & 0x7; + if (used_c & 0x4) key.ts[s].colorarg2 = context->ff.tex_stage[s][D3DTSS_COLORARG2] & 0x7; + if (used_c & 0x1) key.colorarg_b4[0] |= ((context->ff.tex_stage[s][D3DTSS_COLORARG0] >> 4) & 0x1) << s; + if (used_c & 0x1) key.colorarg_b5[0] |= ((context->ff.tex_stage[s][D3DTSS_COLORARG0] >> 5) & 0x1) << s; + if (used_c & 0x2) key.colorarg_b4[1] |= ((context->ff.tex_stage[s][D3DTSS_COLORARG1] >> 4) & 0x1) << s; + if (used_c & 0x2) key.colorarg_b5[1] |= ((context->ff.tex_stage[s][D3DTSS_COLORARG1] >> 5) & 0x1) << s; + if (used_c & 0x4) key.colorarg_b4[2] |= ((context->ff.tex_stage[s][D3DTSS_COLORARG2] >> 4) & 0x1) << s; + if (used_c & 0x4) key.colorarg_b5[2] |= ((context->ff.tex_stage[s][D3DTSS_COLORARG2] >> 5) & 0x1) << s; + } + if (key.ts[s].alphaop != D3DTOP_DISABLE) { + if (used_a & 0x1) key.ts[s].alphaarg0 = context->ff.tex_stage[s][D3DTSS_ALPHAARG0] & 0x7; + if (used_a & 0x2) key.ts[s].alphaarg1 = context->ff.tex_stage[s][D3DTSS_ALPHAARG1] & 0x7; + if (used_a & 0x4) key.ts[s].alphaarg2 = context->ff.tex_stage[s][D3DTSS_ALPHAARG2] & 0x7; + if (used_a & 0x1) key.alphaarg_b4[0] |= ((context->ff.tex_stage[s][D3DTSS_ALPHAARG0] >> 4) & 0x1) << s; + if (used_a & 0x2) key.alphaarg_b4[1] |= ((context->ff.tex_stage[s][D3DTSS_ALPHAARG1] >> 4) & 0x1) << s; + if (used_a & 0x4) key.alphaarg_b4[2] |= ((context->ff.tex_stage[s][D3DTSS_ALPHAARG2] >> 4) & 0x1) << s; + } + key.ts[s].resultarg = context->ff.tex_stage[s][D3DTSS_RESULTARG] == D3DTA_TEMP; + + if (context->texture[s].enabled) { + switch (context->texture[s].type) { + case D3DRTYPE_TEXTURE: key.ts[s].textarget = 1; break; + case D3DRTYPE_VOLUMETEXTURE: key.ts[s].textarget = 2; break; + case D3DRTYPE_CUBETEXTURE: key.ts[s].textarget = 3; break; + default: + assert(!"unexpected texture type"); + break; + } + } else { + key.ts[s].textarget = 1; + } + } + + /* Note: If colorop is D3DTOP_DISABLE for the first stage + * (which implies alphaop is too), nothing particular happens, + * that is, current is equal to diffuse (which is the case anyway, + * because it is how it is initialized). + * Special case seems if alphaop is D3DTOP_DISABLE and not colorop, + * because then if the resultarg is TEMP, then diffuse alpha is written + * to it. */ + if (key.ts[0].colorop != D3DTOP_DISABLE && + key.ts[0].alphaop == D3DTOP_DISABLE && + key.ts[0].resultarg != 0) { + key.ts[0].alphaop = D3DTOP_SELECTARG1; + key.ts[0].alphaarg1 = D3DTA_DIFFUSE; + } + /* When no alpha stage writes to current, diffuse alpha is taken. + * Since we initialize current to diffuse, we have the behaviour. */ + + /* Last stage always writes to Current */ + if (s >= 1) + key.ts[s-1].resultarg = 0; + + key.projected = nine_ff_get_projected_key_ff(context); + key.specular = !!context->rs[D3DRS_SPECULARENABLE]; + + for (; s < 8; ++s) + key.ts[s].colorop = key.ts[s].alphaop = D3DTOP_DISABLE; + if (context->rs[D3DRS_FOGENABLE]) + key.fog_mode = context->rs[D3DRS_FOGTABLEMODE]; + key.fog = !!context->rs[D3DRS_FOGENABLE]; + /* Pixel fog (with WFOG advertised): source is either Z or W. + * W is the source if vs ff is used, and the + * projection matrix is not orthogonal. + * Tests on Win 10 seem to indicate _34 + * and _33 are checked against 0, 1. */ + if (key.fog_mode && key.fog) + key.fog_source = !context->programmable_vs && + !(projection_matrix->_34 == 0.0f && + projection_matrix->_44 == 1.0f); + + DBG("PS ff key hash: %x\n", nine_ff_ps_key_hash(&key)); + ps = util_hash_table_get(device->ff.ht_ps, &key); + if (ps) + return ps; + NinePixelShader9_new(device, &ps, NULL, nine_ff_build_ps(device, &key)); + + nine_ff_prune_ps(device); + if (ps) { + memcpy(&ps->ff_key, &key, sizeof(ps->ff_key)); + + _mesa_hash_table_insert(device->ff.ht_ps, &ps->ff_key, ps); + device->ff.num_ps++; + + ps->rt_mask = 0x1; + ps->sampler_mask = sampler_mask; + } + return ps; +} + +static void +nine_ff_load_vs_transforms(struct NineDevice9 *device) +{ + struct nine_context *context = &device->context; + D3DMATRIX T; + D3DMATRIX *M = (D3DMATRIX *)device->ff.vs_const; + unsigned i; + + /* TODO: make this nicer, and only upload the ones we need */ + /* TODO: use ff.vs_const as storage of W, V, P matrices */ + + if (IS_D3DTS_DIRTY(context, WORLD) || + IS_D3DTS_DIRTY(context, VIEW) || + IS_D3DTS_DIRTY(context, PROJECTION)) { + /* WVP, WV matrices */ + nine_d3d_matrix_matrix_mul(&M[1], GET_D3DTS(WORLD), GET_D3DTS(VIEW)); + nine_d3d_matrix_matrix_mul(&M[0], &M[1], GET_D3DTS(PROJECTION)); + + /* normal matrix == transpose(inverse(WV)) */ + nine_d3d_matrix_inverse(&T, &M[1]); + nine_d3d_matrix_transpose(&M[4], &T); + + /* P matrix */ + M[2] = *GET_D3DTS(PROJECTION); + + /* V and W matrix */ + nine_d3d_matrix_inverse(&M[3], GET_D3DTS(VIEW)); + M[40] = M[1]; + } + + if (context->rs[D3DRS_VERTEXBLEND] != D3DVBF_DISABLE) { + /* load other world matrices */ + for (i = 1; i <= 8; ++i) { + nine_d3d_matrix_matrix_mul(&M[40 + i], GET_D3DTS(WORLDMATRIX(i)), GET_D3DTS(VIEW)); + } + } + + device->ff.vs_const[30 * 4] = asfloat(context->rs[D3DRS_TWEENFACTOR]); +} + +static void +nine_ff_load_lights(struct NineDevice9 *device) +{ + struct nine_context *context = &device->context; + struct fvec4 *dst = (struct fvec4 *)device->ff.vs_const; + unsigned l; + + if (context->changed.group & NINE_STATE_FF_MATERIAL) { + const D3DMATERIAL9 *mtl = &context->ff.material; + + memcpy(&dst[20], &mtl->Diffuse, 4 * sizeof(float)); + memcpy(&dst[21], &mtl->Ambient, 4 * sizeof(float)); + memcpy(&dst[22], &mtl->Specular, 4 * sizeof(float)); + dst[23].x = mtl->Power; + memcpy(&dst[24], &mtl->Emissive, 4 * sizeof(float)); + d3dcolor_to_rgba(&dst[25].x, context->rs[D3DRS_AMBIENT]); + dst[19].x = dst[25].x * mtl->Ambient.r + mtl->Emissive.r; + dst[19].y = dst[25].y * mtl->Ambient.g + mtl->Emissive.g; + dst[19].z = dst[25].z * mtl->Ambient.b + mtl->Emissive.b; + } + + if (!(context->changed.group & NINE_STATE_FF_LIGHTING)) + return; + + for (l = 0; l < context->ff.num_lights_active; ++l) { + const D3DLIGHT9 *light = &context->ff.light[context->ff.active_light[l]]; + + dst[32 + l * 8].x = light->Type; + dst[32 + l * 8].y = light->Attenuation0; + dst[32 + l * 8].z = light->Attenuation1; + dst[32 + l * 8].w = light->Attenuation2; + memcpy(&dst[33 + l * 8].x, &light->Diffuse, sizeof(light->Diffuse)); + memcpy(&dst[34 + l * 8].x, &light->Specular, sizeof(light->Specular)); + memcpy(&dst[35 + l * 8].x, &light->Ambient, sizeof(light->Ambient)); + nine_d3d_vector4_matrix_mul((D3DVECTOR *)&dst[36 + l * 8].x, &light->Position, GET_D3DTS(VIEW)); + nine_d3d_vector3_matrix_mul((D3DVECTOR *)&dst[37 + l * 8].x, &light->Direction, GET_D3DTS(VIEW)); + dst[36 + l * 8].w = light->Type == D3DLIGHT_DIRECTIONAL ? 1e9f : light->Range; + dst[37 + l * 8].w = light->Falloff; + dst[38 + l * 8].x = cosf(light->Theta * 0.5f); + dst[38 + l * 8].y = cosf(light->Phi * 0.5f); + dst[38 + l * 8].z = 1.0f / (dst[38 + l * 8].x - dst[38 + l * 8].y); + dst[39 + l * 8].w = (float)((l + 1) == context->ff.num_lights_active); + } +} + +static void +nine_ff_load_point_and_fog_params(struct NineDevice9 *device) +{ + struct nine_context *context = &device->context; + struct fvec4 *dst = (struct fvec4 *)device->ff.vs_const; + + if (!(context->changed.group & NINE_STATE_FF_VS_OTHER)) + return; + dst[26].x = asfloat(context->rs[D3DRS_POINTSIZE_MIN]); + dst[26].y = asfloat(context->rs[D3DRS_POINTSIZE_MAX]); + dst[26].z = asfloat(context->rs[D3DRS_POINTSIZE]); + dst[26].w = asfloat(context->rs[D3DRS_POINTSCALE_A]); + dst[27].x = asfloat(context->rs[D3DRS_POINTSCALE_B]); + dst[27].y = asfloat(context->rs[D3DRS_POINTSCALE_C]); + dst[28].x = asfloat(context->rs[D3DRS_FOGEND]); + dst[28].y = 1.0f / (asfloat(context->rs[D3DRS_FOGEND]) - asfloat(context->rs[D3DRS_FOGSTART])); + if (isinf(dst[28].y)) + dst[28].y = 0.0f; + dst[28].z = asfloat(context->rs[D3DRS_FOGDENSITY]); +} + +static void +nine_ff_load_tex_matrices(struct NineDevice9 *device) +{ + struct nine_context *context = &device->context; + D3DMATRIX *M = (D3DMATRIX *)device->ff.vs_const; + unsigned s; + + if (!(context->ff.changed.transform[0] & 0xff0000)) + return; + for (s = 0; s < 8; ++s) { + if (IS_D3DTS_DIRTY(context, TEXTURE0 + s)) + nine_d3d_matrix_transpose(&M[32 + s], nine_state_access_transform(&context->ff, D3DTS_TEXTURE0 + s, FALSE)); + } +} + +static void +nine_ff_load_ps_params(struct NineDevice9 *device) +{ + struct nine_context *context = &device->context; + struct fvec4 *dst = (struct fvec4 *)device->ff.ps_const; + unsigned s; + + if (!(context->changed.group & NINE_STATE_FF_PS_CONSTS)) + return; + + for (s = 0; s < 8; ++s) + d3dcolor_to_rgba(&dst[s].x, context->ff.tex_stage[s][D3DTSS_CONSTANT]); + + for (s = 0; s < 8; ++s) { + dst[8 + s].x = asfloat(context->ff.tex_stage[s][D3DTSS_BUMPENVMAT00]); + dst[8 + s].y = asfloat(context->ff.tex_stage[s][D3DTSS_BUMPENVMAT01]); + dst[8 + s].z = asfloat(context->ff.tex_stage[s][D3DTSS_BUMPENVMAT10]); + dst[8 + s].w = asfloat(context->ff.tex_stage[s][D3DTSS_BUMPENVMAT11]); + if (s & 1) { + dst[16 + s / 2].z = asfloat(context->ff.tex_stage[s][D3DTSS_BUMPENVLSCALE]); + dst[16 + s / 2].w = asfloat(context->ff.tex_stage[s][D3DTSS_BUMPENVLOFFSET]); + } else { + dst[16 + s / 2].x = asfloat(context->ff.tex_stage[s][D3DTSS_BUMPENVLSCALE]); + dst[16 + s / 2].y = asfloat(context->ff.tex_stage[s][D3DTSS_BUMPENVLOFFSET]); + } + } + + d3dcolor_to_rgba(&dst[20].x, context->rs[D3DRS_TEXTUREFACTOR]); + d3dcolor_to_rgba(&dst[21].x, context->rs[D3DRS_FOGCOLOR]); + dst[22].x = asfloat(context->rs[D3DRS_FOGEND]); + dst[22].y = 1.0f / (asfloat(context->rs[D3DRS_FOGEND]) - asfloat(context->rs[D3DRS_FOGSTART])); + dst[22].z = asfloat(context->rs[D3DRS_FOGDENSITY]); +} + +static void +nine_ff_load_viewport_info(struct NineDevice9 *device) +{ + D3DVIEWPORT9 *viewport = &device->context.viewport; + struct fvec4 *dst = (struct fvec4 *)device->ff.vs_const; + float diffZ = viewport->MaxZ - viewport->MinZ; + + /* Note: the other functions avoids to fill the const again if nothing changed. + * But we don't have much to fill, and adding code to allow that may be complex + * so just fill it always */ + dst[100].x = 2.0f / (float)(viewport->Width); + dst[100].y = 2.0f / (float)(viewport->Height); + dst[100].z = (diffZ == 0.0f) ? 0.0f : (1.0f / diffZ); + dst[100].w = (float)(viewport->Width); + dst[101].x = (float)(viewport->X); + dst[101].y = (float)(viewport->Y); + dst[101].z = (float)(viewport->MinZ); +} + +void +nine_ff_update(struct NineDevice9 *device) +{ + struct nine_context *context = &device->context; + struct pipe_constant_buffer cb; + + DBG("vs=%p ps=%p\n", context->vs, context->ps); + + /* NOTE: the only reference belongs to the hash table */ + if (!context->programmable_vs) { + device->ff.vs = nine_ff_get_vs(device); + context->changed.group |= NINE_STATE_VS; + } + if (!context->ps) { + device->ff.ps = nine_ff_get_ps(device); + context->changed.group |= NINE_STATE_PS; + } + + if (!context->programmable_vs) { + nine_ff_load_vs_transforms(device); + nine_ff_load_tex_matrices(device); + nine_ff_load_lights(device); + nine_ff_load_point_and_fog_params(device); + nine_ff_load_viewport_info(device); + + memset(context->ff.changed.transform, 0, sizeof(context->ff.changed.transform)); + + cb.buffer_offset = 0; + cb.buffer = NULL; + cb.user_buffer = device->ff.vs_const; + cb.buffer_size = NINE_FF_NUM_VS_CONST * 4 * sizeof(float); + + context->pipe_data.cb_vs_ff = cb; + context->commit |= NINE_STATE_COMMIT_CONST_VS; + + context->changed.group &= ~NINE_STATE_FF_VS; + } + + if (!context->ps) { + nine_ff_load_ps_params(device); + + cb.buffer_offset = 0; + cb.buffer = NULL; + cb.user_buffer = device->ff.ps_const; + cb.buffer_size = NINE_FF_NUM_PS_CONST * 4 * sizeof(float); + + context->pipe_data.cb_ps_ff = cb; + context->commit |= NINE_STATE_COMMIT_CONST_PS; + + context->changed.group &= ~NINE_STATE_FF_PS; + } +} + + +boolean +nine_ff_init(struct NineDevice9 *device) +{ + device->ff.ht_vs = _mesa_hash_table_create(NULL, nine_ff_vs_key_hash, + nine_ff_vs_key_comp); + device->ff.ht_ps = _mesa_hash_table_create(NULL, nine_ff_ps_key_hash, + nine_ff_ps_key_comp); + + device->ff.ht_fvf = _mesa_hash_table_create(NULL, nine_ff_fvf_key_hash, + nine_ff_fvf_key_comp); + + device->ff.vs_const = CALLOC(NINE_FF_NUM_VS_CONST, 4 * sizeof(float)); + device->ff.ps_const = CALLOC(NINE_FF_NUM_PS_CONST, 4 * sizeof(float)); + + return device->ff.ht_vs && device->ff.ht_ps && + device->ff.ht_fvf && + device->ff.vs_const && device->ff.ps_const; +} + +static enum pipe_error nine_ff_ht_delete_cb(void *key, void *value, void *data) +{ + NineUnknown_Unbind(NineUnknown(value)); + return PIPE_OK; +} + +void +nine_ff_fini(struct NineDevice9 *device) +{ + if (device->ff.ht_vs) { + util_hash_table_foreach(device->ff.ht_vs, nine_ff_ht_delete_cb, NULL); + _mesa_hash_table_destroy(device->ff.ht_vs, NULL); + } + if (device->ff.ht_ps) { + util_hash_table_foreach(device->ff.ht_ps, nine_ff_ht_delete_cb, NULL); + _mesa_hash_table_destroy(device->ff.ht_ps, NULL); + } + if (device->ff.ht_fvf) { + util_hash_table_foreach(device->ff.ht_fvf, nine_ff_ht_delete_cb, NULL); + _mesa_hash_table_destroy(device->ff.ht_fvf, NULL); + } + device->ff.vs = NULL; /* destroyed by unbinding from hash table */ + device->ff.ps = NULL; + + FREE(device->ff.vs_const); + FREE(device->ff.ps_const); +} + +static void +nine_ff_prune_vs(struct NineDevice9 *device) +{ + struct nine_context *context = &device->context; + + if (device->ff.num_vs > 1024) { + /* could destroy the bound one here, so unbind */ + context->pipe->bind_vs_state(context->pipe, NULL); + util_hash_table_foreach(device->ff.ht_vs, nine_ff_ht_delete_cb, NULL); + _mesa_hash_table_clear(device->ff.ht_vs, NULL); + device->ff.num_vs = 0; + context->changed.group |= NINE_STATE_VS; + } +} +static void +nine_ff_prune_ps(struct NineDevice9 *device) +{ + struct nine_context *context = &device->context; + + if (device->ff.num_ps > 1024) { + /* could destroy the bound one here, so unbind */ + context->pipe->bind_fs_state(context->pipe, NULL); + util_hash_table_foreach(device->ff.ht_ps, nine_ff_ht_delete_cb, NULL); + _mesa_hash_table_clear(device->ff.ht_ps, NULL); + device->ff.num_ps = 0; + context->changed.group |= NINE_STATE_PS; + } +} + +/* ========================================================================== */ + +/* Matrix multiplication: + * + * in memory: 0 1 2 3 (row major) + * 4 5 6 7 + * 8 9 a b + * c d e f + * + * cA cB cC cD + * r0 = (r0 * cA) (r0 * cB) . . + * r1 = (r1 * cA) (r1 * cB) + * r2 = (r2 * cA) . + * r3 = (r3 * cA) . + * + * r: (11) (12) (13) (14) + * (21) (22) (23) (24) + * (31) (32) (33) (34) + * (41) (42) (43) (44) + * l: (11 12 13 14) + * (21 22 23 24) + * (31 32 33 34) + * (41 42 43 44) + * + * v: (x y z 1 ) + * + * t.xyzw = MUL(v.xxxx, r[0]); + * t.xyzw = MAD(v.yyyy, r[1], t.xyzw); + * t.xyzw = MAD(v.zzzz, r[2], t.xyzw); + * v.xyzw = MAD(v.wwww, r[3], t.xyzw); + * + * v.x = DP4(v, c[0]); + * v.y = DP4(v, c[1]); + * v.z = DP4(v, c[2]); + * v.w = DP4(v, c[3]) = 1 + */ + +/* +static void +nine_D3DMATRIX_print(const D3DMATRIX *M) +{ + DBG("\n(%f %f %f %f)\n" + "(%f %f %f %f)\n" + "(%f %f %f %f)\n" + "(%f %f %f %f)\n", + M->m[0][0], M->m[0][1], M->m[0][2], M->m[0][3], + M->m[1][0], M->m[1][1], M->m[1][2], M->m[1][3], + M->m[2][0], M->m[2][1], M->m[2][2], M->m[2][3], + M->m[3][0], M->m[3][1], M->m[3][2], M->m[3][3]); +} +*/ + +static inline float +nine_DP4_row_col(const D3DMATRIX *A, int r, const D3DMATRIX *B, int c) +{ + return A->m[r][0] * B->m[0][c] + + A->m[r][1] * B->m[1][c] + + A->m[r][2] * B->m[2][c] + + A->m[r][3] * B->m[3][c]; +} + +static inline float +nine_DP4_vec_col(const D3DVECTOR *v, const D3DMATRIX *M, int c) +{ + return v->x * M->m[0][c] + + v->y * M->m[1][c] + + v->z * M->m[2][c] + + 1.0f * M->m[3][c]; +} + +static inline float +nine_DP3_vec_col(const D3DVECTOR *v, const D3DMATRIX *M, int c) +{ + return v->x * M->m[0][c] + + v->y * M->m[1][c] + + v->z * M->m[2][c]; +} + +void +nine_d3d_matrix_matrix_mul(D3DMATRIX *D, const D3DMATRIX *L, const D3DMATRIX *R) +{ + D->_11 = nine_DP4_row_col(L, 0, R, 0); + D->_12 = nine_DP4_row_col(L, 0, R, 1); + D->_13 = nine_DP4_row_col(L, 0, R, 2); + D->_14 = nine_DP4_row_col(L, 0, R, 3); + + D->_21 = nine_DP4_row_col(L, 1, R, 0); + D->_22 = nine_DP4_row_col(L, 1, R, 1); + D->_23 = nine_DP4_row_col(L, 1, R, 2); + D->_24 = nine_DP4_row_col(L, 1, R, 3); + + D->_31 = nine_DP4_row_col(L, 2, R, 0); + D->_32 = nine_DP4_row_col(L, 2, R, 1); + D->_33 = nine_DP4_row_col(L, 2, R, 2); + D->_34 = nine_DP4_row_col(L, 2, R, 3); + + D->_41 = nine_DP4_row_col(L, 3, R, 0); + D->_42 = nine_DP4_row_col(L, 3, R, 1); + D->_43 = nine_DP4_row_col(L, 3, R, 2); + D->_44 = nine_DP4_row_col(L, 3, R, 3); +} + +void +nine_d3d_vector4_matrix_mul(D3DVECTOR *d, const D3DVECTOR *v, const D3DMATRIX *M) +{ + d->x = nine_DP4_vec_col(v, M, 0); + d->y = nine_DP4_vec_col(v, M, 1); + d->z = nine_DP4_vec_col(v, M, 2); +} + +void +nine_d3d_vector3_matrix_mul(D3DVECTOR *d, const D3DVECTOR *v, const D3DMATRIX *M) +{ + d->x = nine_DP3_vec_col(v, M, 0); + d->y = nine_DP3_vec_col(v, M, 1); + d->z = nine_DP3_vec_col(v, M, 2); +} + +void +nine_d3d_matrix_transpose(D3DMATRIX *D, const D3DMATRIX *M) +{ + unsigned i, j; + for (i = 0; i < 4; ++i) + for (j = 0; j < 4; ++j) + D->m[i][j] = M->m[j][i]; +} + +#define _M_ADD_PROD_1i_2j_3k_4l(i,j,k,l) do { \ + float t = M->_1##i * M->_2##j * M->_3##k * M->_4##l; \ + if (t > 0.0f) pos += t; else neg += t; } while(0) + +#define _M_SUB_PROD_1i_2j_3k_4l(i,j,k,l) do { \ + float t = M->_1##i * M->_2##j * M->_3##k * M->_4##l; \ + if (t > 0.0f) neg -= t; else pos -= t; } while(0) +float +nine_d3d_matrix_det(const D3DMATRIX *M) +{ + float pos = 0.0f; + float neg = 0.0f; + + _M_ADD_PROD_1i_2j_3k_4l(1, 2, 3, 4); + _M_ADD_PROD_1i_2j_3k_4l(1, 3, 4, 2); + _M_ADD_PROD_1i_2j_3k_4l(1, 4, 2, 3); + + _M_ADD_PROD_1i_2j_3k_4l(2, 1, 4, 3); + _M_ADD_PROD_1i_2j_3k_4l(2, 3, 1, 4); + _M_ADD_PROD_1i_2j_3k_4l(2, 4, 3, 1); + + _M_ADD_PROD_1i_2j_3k_4l(3, 1, 2, 4); + _M_ADD_PROD_1i_2j_3k_4l(3, 2, 4, 1); + _M_ADD_PROD_1i_2j_3k_4l(3, 4, 1, 2); + + _M_ADD_PROD_1i_2j_3k_4l(4, 1, 3, 2); + _M_ADD_PROD_1i_2j_3k_4l(4, 2, 1, 3); + _M_ADD_PROD_1i_2j_3k_4l(4, 3, 2, 1); + + _M_SUB_PROD_1i_2j_3k_4l(1, 2, 4, 3); + _M_SUB_PROD_1i_2j_3k_4l(1, 3, 2, 4); + _M_SUB_PROD_1i_2j_3k_4l(1, 4, 3, 2); + + _M_SUB_PROD_1i_2j_3k_4l(2, 1, 3, 4); + _M_SUB_PROD_1i_2j_3k_4l(2, 3, 4, 1); + _M_SUB_PROD_1i_2j_3k_4l(2, 4, 1, 3); + + _M_SUB_PROD_1i_2j_3k_4l(3, 1, 4, 2); + _M_SUB_PROD_1i_2j_3k_4l(3, 2, 1, 4); + _M_SUB_PROD_1i_2j_3k_4l(3, 4, 2, 1); + + _M_SUB_PROD_1i_2j_3k_4l(4, 1, 2, 3); + _M_SUB_PROD_1i_2j_3k_4l(4, 2, 3, 1); + _M_SUB_PROD_1i_2j_3k_4l(4, 3, 1, 2); + + return pos + neg; +} + +/* XXX: Probably better to just use src/mesa/math/m_matrix.c because + * I have no idea where this code came from. + */ +void +nine_d3d_matrix_inverse(D3DMATRIX *D, const D3DMATRIX *M) +{ + int i, k; + float det; + + D->m[0][0] = + M->m[1][1] * M->m[2][2] * M->m[3][3] - + M->m[1][1] * M->m[3][2] * M->m[2][3] - + M->m[1][2] * M->m[2][1] * M->m[3][3] + + M->m[1][2] * M->m[3][1] * M->m[2][3] + + M->m[1][3] * M->m[2][1] * M->m[3][2] - + M->m[1][3] * M->m[3][1] * M->m[2][2]; + + D->m[0][1] = + -M->m[0][1] * M->m[2][2] * M->m[3][3] + + M->m[0][1] * M->m[3][2] * M->m[2][3] + + M->m[0][2] * M->m[2][1] * M->m[3][3] - + M->m[0][2] * M->m[3][1] * M->m[2][3] - + M->m[0][3] * M->m[2][1] * M->m[3][2] + + M->m[0][3] * M->m[3][1] * M->m[2][2]; + + D->m[0][2] = + M->m[0][1] * M->m[1][2] * M->m[3][3] - + M->m[0][1] * M->m[3][2] * M->m[1][3] - + M->m[0][2] * M->m[1][1] * M->m[3][3] + + M->m[0][2] * M->m[3][1] * M->m[1][3] + + M->m[0][3] * M->m[1][1] * M->m[3][2] - + M->m[0][3] * M->m[3][1] * M->m[1][2]; + + D->m[0][3] = + -M->m[0][1] * M->m[1][2] * M->m[2][3] + + M->m[0][1] * M->m[2][2] * M->m[1][3] + + M->m[0][2] * M->m[1][1] * M->m[2][3] - + M->m[0][2] * M->m[2][1] * M->m[1][3] - + M->m[0][3] * M->m[1][1] * M->m[2][2] + + M->m[0][3] * M->m[2][1] * M->m[1][2]; + + D->m[1][0] = + -M->m[1][0] * M->m[2][2] * M->m[3][3] + + M->m[1][0] * M->m[3][2] * M->m[2][3] + + M->m[1][2] * M->m[2][0] * M->m[3][3] - + M->m[1][2] * M->m[3][0] * M->m[2][3] - + M->m[1][3] * M->m[2][0] * M->m[3][2] + + M->m[1][3] * M->m[3][0] * M->m[2][2]; + + D->m[1][1] = + M->m[0][0] * M->m[2][2] * M->m[3][3] - + M->m[0][0] * M->m[3][2] * M->m[2][3] - + M->m[0][2] * M->m[2][0] * M->m[3][3] + + M->m[0][2] * M->m[3][0] * M->m[2][3] + + M->m[0][3] * M->m[2][0] * M->m[3][2] - + M->m[0][3] * M->m[3][0] * M->m[2][2]; + + D->m[1][2] = + -M->m[0][0] * M->m[1][2] * M->m[3][3] + + M->m[0][0] * M->m[3][2] * M->m[1][3] + + M->m[0][2] * M->m[1][0] * M->m[3][3] - + M->m[0][2] * M->m[3][0] * M->m[1][3] - + M->m[0][3] * M->m[1][0] * M->m[3][2] + + M->m[0][3] * M->m[3][0] * M->m[1][2]; + + D->m[1][3] = + M->m[0][0] * M->m[1][2] * M->m[2][3] - + M->m[0][0] * M->m[2][2] * M->m[1][3] - + M->m[0][2] * M->m[1][0] * M->m[2][3] + + M->m[0][2] * M->m[2][0] * M->m[1][3] + + M->m[0][3] * M->m[1][0] * M->m[2][2] - + M->m[0][3] * M->m[2][0] * M->m[1][2]; + + D->m[2][0] = + M->m[1][0] * M->m[2][1] * M->m[3][3] - + M->m[1][0] * M->m[3][1] * M->m[2][3] - + M->m[1][1] * M->m[2][0] * M->m[3][3] + + M->m[1][1] * M->m[3][0] * M->m[2][3] + + M->m[1][3] * M->m[2][0] * M->m[3][1] - + M->m[1][3] * M->m[3][0] * M->m[2][1]; + + D->m[2][1] = + -M->m[0][0] * M->m[2][1] * M->m[3][3] + + M->m[0][0] * M->m[3][1] * M->m[2][3] + + M->m[0][1] * M->m[2][0] * M->m[3][3] - + M->m[0][1] * M->m[3][0] * M->m[2][3] - + M->m[0][3] * M->m[2][0] * M->m[3][1] + + M->m[0][3] * M->m[3][0] * M->m[2][1]; + + D->m[2][2] = + M->m[0][0] * M->m[1][1] * M->m[3][3] - + M->m[0][0] * M->m[3][1] * M->m[1][3] - + M->m[0][1] * M->m[1][0] * M->m[3][3] + + M->m[0][1] * M->m[3][0] * M->m[1][3] + + M->m[0][3] * M->m[1][0] * M->m[3][1] - + M->m[0][3] * M->m[3][0] * M->m[1][1]; + + D->m[2][3] = + -M->m[0][0] * M->m[1][1] * M->m[2][3] + + M->m[0][0] * M->m[2][1] * M->m[1][3] + + M->m[0][1] * M->m[1][0] * M->m[2][3] - + M->m[0][1] * M->m[2][0] * M->m[1][3] - + M->m[0][3] * M->m[1][0] * M->m[2][1] + + M->m[0][3] * M->m[2][0] * M->m[1][1]; + + D->m[3][0] = + -M->m[1][0] * M->m[2][1] * M->m[3][2] + + M->m[1][0] * M->m[3][1] * M->m[2][2] + + M->m[1][1] * M->m[2][0] * M->m[3][2] - + M->m[1][1] * M->m[3][0] * M->m[2][2] - + M->m[1][2] * M->m[2][0] * M->m[3][1] + + M->m[1][2] * M->m[3][0] * M->m[2][1]; + + D->m[3][1] = + M->m[0][0] * M->m[2][1] * M->m[3][2] - + M->m[0][0] * M->m[3][1] * M->m[2][2] - + M->m[0][1] * M->m[2][0] * M->m[3][2] + + M->m[0][1] * M->m[3][0] * M->m[2][2] + + M->m[0][2] * M->m[2][0] * M->m[3][1] - + M->m[0][2] * M->m[3][0] * M->m[2][1]; + + D->m[3][2] = + -M->m[0][0] * M->m[1][1] * M->m[3][2] + + M->m[0][0] * M->m[3][1] * M->m[1][2] + + M->m[0][1] * M->m[1][0] * M->m[3][2] - + M->m[0][1] * M->m[3][0] * M->m[1][2] - + M->m[0][2] * M->m[1][0] * M->m[3][1] + + M->m[0][2] * M->m[3][0] * M->m[1][1]; + + D->m[3][3] = + M->m[0][0] * M->m[1][1] * M->m[2][2] - + M->m[0][0] * M->m[2][1] * M->m[1][2] - + M->m[0][1] * M->m[1][0] * M->m[2][2] + + M->m[0][1] * M->m[2][0] * M->m[1][2] + + M->m[0][2] * M->m[1][0] * M->m[2][1] - + M->m[0][2] * M->m[2][0] * M->m[1][1]; + + det = + M->m[0][0] * D->m[0][0] + + M->m[1][0] * D->m[0][1] + + M->m[2][0] * D->m[0][2] + + M->m[3][0] * D->m[0][3]; + + if (fabsf(det) < 1e-30) {/* non inversible */ + *D = *M; /* wine tests */ + return; + } + + det = 1.0 / det; + + for (i = 0; i < 4; i++) + for (k = 0; k < 4; k++) + D->m[i][k] *= det; + +#if defined(DEBUG) || !defined(NDEBUG) + { + D3DMATRIX I; + + nine_d3d_matrix_matrix_mul(&I, D, M); + + for (i = 0; i < 4; ++i) + for (k = 0; k < 4; ++k) + if (fabsf(I.m[i][k] - (float)(i == k)) > 1e-3) + DBG("Matrix inversion check FAILED !\n"); + } +#endif +} diff --git a/src/gallium/frontends/nine/nine_ff.h b/src/gallium/frontends/nine/nine_ff.h new file mode 100644 index 00000000000..5345b99dbb5 --- /dev/null +++ b/src/gallium/frontends/nine/nine_ff.h @@ -0,0 +1,126 @@ + +#ifndef _NINE_FF_H_ +#define _NINE_FF_H_ + +#include "device9.h" +#include "vertexdeclaration9.h" + +boolean nine_ff_init(struct NineDevice9 *); +void nine_ff_fini(struct NineDevice9 *); + +void nine_ff_update(struct NineDevice9 *); + +void +nine_d3d_matrix_matrix_mul(D3DMATRIX *, const D3DMATRIX *, const D3DMATRIX *); + +void +nine_d3d_vector4_matrix_mul(D3DVECTOR *, const D3DVECTOR *, const D3DMATRIX *); +void +nine_d3d_vector3_matrix_mul(D3DVECTOR *, const D3DVECTOR *, const D3DMATRIX *); + +float +nine_d3d_matrix_det(const D3DMATRIX *); + +void +nine_d3d_matrix_inverse(D3DMATRIX *, const D3DMATRIX *); + +void +nine_d3d_matrix_transpose(D3DMATRIX *, const D3DMATRIX *); + +#define NINED3DTSS_TCI_DISABLE 0 +#define NINED3DTSS_TCI_PASSTHRU 1 +#define NINED3DTSS_TCI_CAMERASPACENORMAL 2 +#define NINED3DTSS_TCI_CAMERASPACEPOSITION 3 +#define NINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR 4 +#define NINED3DTSS_TCI_SPHEREMAP 5 + +static inline unsigned +nine_decltype_get_dim(BYTE type) +{ + switch (type) { + case D3DDECLTYPE_FLOAT1: return 1; + case D3DDECLTYPE_FLOAT2: return 2; + case D3DDECLTYPE_FLOAT3: return 3; + case D3DDECLTYPE_FLOAT4: return 4; + case D3DDECLTYPE_D3DCOLOR: return 1; + case D3DDECLTYPE_UBYTE4: return 4; + case D3DDECLTYPE_SHORT2: return 2; + case D3DDECLTYPE_SHORT4: return 4; + case D3DDECLTYPE_UBYTE4N: return 4; + case D3DDECLTYPE_SHORT2N: return 2; + case D3DDECLTYPE_SHORT4N: return 4; + case D3DDECLTYPE_USHORT2N: return 2; + case D3DDECLTYPE_USHORT4N: return 4; + case D3DDECLTYPE_UDEC3: return 3; + case D3DDECLTYPE_DEC3N: return 3; + case D3DDECLTYPE_FLOAT16_2: return 2; + case D3DDECLTYPE_FLOAT16_4: return 4; + default: + assert(!"Implementation error !"); + } + return 0; +} + +static inline uint16_t +nine_ff_get_projected_key(struct nine_context *context, unsigned num_stages) +{ + unsigned s, i; + uint16_t projected = 0; + char input_texture_coord[num_stages]; + memset(&input_texture_coord, 0, sizeof(input_texture_coord)); + + if (context->vdecl) { + for (i = 0; i < context->vdecl->nelems; i++) { + uint16_t usage = context->vdecl->usage_map[i]; + if (usage % NINE_DECLUSAGE_COUNT == NINE_DECLUSAGE_TEXCOORD) { + s = usage / NINE_DECLUSAGE_COUNT; + if (s < num_stages) + input_texture_coord[s] = nine_decltype_get_dim(context->vdecl->decls[i].Type); + } + } + } + + for (s = 0; s < num_stages; ++s) { + unsigned gen = (context->ff.tex_stage[s][D3DTSS_TEXCOORDINDEX] >> 16) + 1; + unsigned dim = context->ff.tex_stage[s][D3DTSS_TEXTURETRANSFORMFLAGS] & 0x7; + unsigned proj = !!(context->ff.tex_stage[s][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED); + + if (!context->vs) { + if (dim > 4) + dim = input_texture_coord[s]; + + if (!dim && gen == NINED3DTSS_TCI_PASSTHRU) + dim = input_texture_coord[s]; + else if (!dim) + dim = 4; + + if (dim == 1) /* NV behaviour */ + proj = 0; + if (dim > input_texture_coord[s] && gen == NINED3DTSS_TCI_PASSTHRU) + proj = 0; + } else { + dim = 4; + } + if (proj) + projected |= (dim-1) << (2 * s); + } + return projected; +} + +static inline uint16_t +nine_ff_get_projected_key_ff(struct nine_context *context) +{ + /* 8 stages */ + return nine_ff_get_projected_key(context, 8); +} + +static inline uint8_t +nine_ff_get_projected_key_programmable(struct nine_context *context) +{ + /* We only look at the 4 stages because this function + * is used only for ps 1.1-3, where only the first four + * slots are available */ + return (uint8_t)nine_ff_get_projected_key(context, 4); +} + +#endif /* _NINE_FF_H_ */ diff --git a/src/gallium/frontends/nine/nine_flags.h b/src/gallium/frontends/nine/nine_flags.h new file mode 100644 index 00000000000..61686a7f60f --- /dev/null +++ b/src/gallium/frontends/nine/nine_flags.h @@ -0,0 +1,14 @@ + + +#ifndef _NINE_FLAGS_H_ +#define _NINE_FLAGS_H_ + +#include "pipe/p_compiler.h" + +/* Incoming 32 bits calls are 4-byte aligned. + * We need to realign them to be able to use + * SSE and to work with other libraries (llvm, etc) + */ +#define NINE_WINAPI WINAPI PIPE_ALIGN_STACK + +#endif /* _NINE_FLAGS_H_ */ \ No newline at end of file diff --git a/src/gallium/frontends/nine/nine_helpers.c b/src/gallium/frontends/nine/nine_helpers.c new file mode 100644 index 00000000000..98c2ae30eba --- /dev/null +++ b/src/gallium/frontends/nine/nine_helpers.c @@ -0,0 +1,100 @@ +/* + * Copyright 2013 Christoph Bumiller + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "nine_helpers.h" + +static struct nine_range * +nine_range_pool_more(struct nine_range_pool *pool) +{ + struct nine_range *r = MALLOC(64 * sizeof(struct nine_range)); + int i; + assert(!pool->free); + + if (pool->num_slabs == pool->num_slabs_max) { + unsigned p = pool->num_slabs_max; + unsigned n = pool->num_slabs_max * 2; + if (!n) + n = 4; + pool->slabs = REALLOC(pool->slabs, + p * sizeof(struct nine_range *), + n * sizeof(struct nine_range *)); + pool->num_slabs_max = n; + } + pool->free = pool->slabs[pool->num_slabs++] = r; + + for (i = 0; i < 63; ++i, r = r->next) + r->next = (struct nine_range *) + ((uint8_t *)r + sizeof(struct nine_range)); + r->next = NULL; + + return pool->free; +} + +static inline struct nine_range * +nine_range_pool_get(struct nine_range_pool *pool, int16_t bgn, int16_t end) +{ + struct nine_range *r = pool->free; + if (!r) + r = nine_range_pool_more(pool); + assert(r); + pool->free = r->next; + r->bgn = bgn; + r->end = end; + return r; +} + +static inline void +nine_ranges_coalesce(struct nine_range *r, struct nine_range_pool *pool) +{ + struct nine_range *n; + + while (r->next && r->end >= r->next->bgn) { + n = r->next->next; + r->end = (r->end >= r->next->end) ? r->end : r->next->end; + nine_range_pool_put(pool, r->next); + r->next = n; + } +} + +void +nine_ranges_insert(struct nine_range **head, int16_t bgn, int16_t end, + struct nine_range_pool *pool) +{ + struct nine_range *r, **pn = head; + + for (r = *head; r && bgn > r->end; pn = &r->next, r = r->next); + + if (!r || end < r->bgn) { + *pn = nine_range_pool_get(pool, bgn, end); + (*pn)->next = r; + } else + if (bgn < r->bgn) { + r->bgn = bgn; + if (end > r->end) + r->end = end; + nine_ranges_coalesce(r, pool); + } else + if (end > r->end) { + r->end = end; + nine_ranges_coalesce(r, pool); + } +} diff --git a/src/gallium/frontends/nine/nine_helpers.h b/src/gallium/frontends/nine/nine_helpers.h new file mode 100644 index 00000000000..c14dd1c04fc --- /dev/null +++ b/src/gallium/frontends/nine/nine_helpers.h @@ -0,0 +1,200 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _NINE_HELPERS_H_ +#define _NINE_HELPERS_H_ + +#include "iunknown.h" +#include "nine_lock.h" + +/* + * Note: we use these function rather than the MIN2, MAX2, CLAMP macros to + * avoid evaluating arguments (which are often function calls) more than once. + */ + +static inline unsigned _min(unsigned a, unsigned b) +{ + return (a < b) ? a : b; +} + + +/* Sshhh ... */ +#define nine_reference(a, b) _nine_reference((void **)(a), (b)) + +static inline void _nine_reference(void **ref, void *ptr) +{ + if (*ref != ptr) { + if (*ref) + NineUnknown_Release(*ref); + if (ptr) + NineUnknown_AddRef(ptr); + *ref = ptr; + } +} + +#define nine_reference_set(a, b) _nine_reference_set((void **)(a), (b)) + +static inline void _nine_reference_set(void **ref, void *ptr) +{ + *ref = ptr; + if (ptr) + NineUnknown_AddRef(ptr); +} + +#define nine_bind(a, b) _nine_bind((void **)(a), (b)) + +static inline void _nine_bind(void **dst, void *obj) +{ + if (*dst != obj) { + if (*dst) + NineUnknown_Unbind(*dst); + if (obj) + NineUnknown_Bind(obj); + *dst = obj; + } +} + +#define NINE_DEVICE_CHILD_NEW(nine, out, dev, ...) \ + { \ + struct NineUnknownParams __params; \ + struct Nine##nine *__data; \ + \ + __data = CALLOC_STRUCT(Nine##nine); \ + if (!__data) { return E_OUTOFMEMORY; } \ + \ + __params.vtable = ((dev)->params.BehaviorFlags & D3DCREATE_MULTITHREADED) ? &Lock##nine##_vtable : &Nine##nine##_vtable; \ + __params.guids = Nine##nine##_IIDs; \ + __params.dtor = (void *)Nine##nine##_dtor; \ + __params.container = NULL; \ + __params.device = dev; \ + __params.start_with_bind_not_ref = false; \ + { \ + HRESULT __hr = Nine##nine##_ctor(__data, &__params, ## __VA_ARGS__); \ + if (FAILED(__hr)) { \ + Nine##nine##_dtor(__data); \ + return __hr; \ + } \ + } \ + \ + *(out) = __data; \ + } \ + return D3D_OK + +#define NINE_DEVICE_CHILD_BIND_NEW(nine, out, dev, ...) \ + { \ + struct NineUnknownParams __params; \ + struct Nine##nine *__data; \ + \ + __data = CALLOC_STRUCT(Nine##nine); \ + if (!__data) { return E_OUTOFMEMORY; } \ + \ + __params.vtable = ((dev)->params.BehaviorFlags & D3DCREATE_MULTITHREADED) ? &Lock##nine##_vtable : &Nine##nine##_vtable; \ + __params.guids = Nine##nine##_IIDs; \ + __params.dtor = (void *)Nine##nine##_dtor; \ + __params.container = NULL; \ + __params.device = dev; \ + __params.start_with_bind_not_ref = true; \ + { \ + HRESULT __hr = Nine##nine##_ctor(__data, &__params, ## __VA_ARGS__); \ + if (FAILED(__hr)) { \ + Nine##nine##_dtor(__data); \ + return __hr; \ + } \ + } \ + \ + *(out) = __data; \ + } \ + return D3D_OK + +#define NINE_NEW(nine, out, lock, ...) \ + { \ + struct NineUnknownParams __params; \ + struct Nine##nine *__data; \ + \ + __data = CALLOC_STRUCT(Nine##nine); \ + if (!__data) { return E_OUTOFMEMORY; } \ + \ + __params.vtable = (lock) ? &Lock##nine##_vtable : &Nine##nine##_vtable; \ + __params.guids = Nine##nine##_IIDs; \ + __params.dtor = (void *)Nine##nine##_dtor; \ + __params.container = NULL; \ + __params.device = NULL; \ + __params.start_with_bind_not_ref = false; \ + { \ + HRESULT __hr = Nine##nine##_ctor(__data, &__params, ## __VA_ARGS__); \ + if (FAILED(__hr)) { \ + Nine##nine##_dtor(__data); \ + return __hr; \ + } \ + } \ + \ + *(out) = __data; \ + } \ + return D3D_OK + +static inline float asfloat(DWORD value) +{ + union { + float f; + DWORD w; + } u; + u.w = value; + return u.f; +} + +struct nine_range +{ + struct nine_range *next; + int16_t bgn; /* inclusive */ + int16_t end; /* exclusive */ +}; + +/* We won't ever need more than 256 ranges, so just allocate once. */ +struct nine_range_pool +{ + struct nine_range *free; + struct nine_range **slabs; + unsigned num_slabs; + unsigned num_slabs_max; +}; + +static inline void +nine_range_pool_put(struct nine_range_pool *pool, struct nine_range *r) +{ + r->next = pool->free; + pool->free = r; +} + +static inline void +nine_range_pool_put_chain(struct nine_range_pool *pool, + struct nine_range *head, + struct nine_range *tail) +{ + tail->next = pool->free; + pool->free = head; +} + +void +nine_ranges_insert(struct nine_range **head, int16_t bgn, int16_t end, + struct nine_range_pool *pool); + +#endif /* _NINE_HELPERS_H_ */ diff --git a/src/gallium/frontends/nine/nine_limits.h b/src/gallium/frontends/nine/nine_limits.h new file mode 100644 index 00000000000..b5090daa11d --- /dev/null +++ b/src/gallium/frontends/nine/nine_limits.h @@ -0,0 +1,247 @@ +/* + * Copyright 2015 Axel Davy + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _NINE_LIMITS_H_ +#define _NINE_LIMITS_H_ + +#include "assert.h" +#include "d3d9types.h" + +// state can be any value +#define NINE_STATE_NO_LIMIT 0 +// value is clamped if below min or max +#define NINE_STATE_CLAMP 1 +// boolean: 0 -> false; any other value -> true +#define NINE_STATE_BOOL 2 +// a mask is applied on the value +#define NINE_STATE_MASK 3 +// if outside a range, state value is changed to a default value +#define NINE_STATE_RANGE_DEF_VAL 4 + +struct nine_state_behaviour { + unsigned state_value_behaviour; + union { + struct { + unsigned min; + unsigned max; + } clamp; + unsigned mask; + struct { + unsigned min; + unsigned max; + unsigned default_val; + } range_def_val; + } u; +}; + +#define __NO_LIMIT_RS(o) \ + [D3DRS_##o] = {NINE_STATE_NO_LIMIT} + +#define __CLAMP_RS(o, m, M) \ + [D3DRS_##o] = {NINE_STATE_CLAMP, {.clamp = {m, M}}} + +#define __BOOLEAN_RS(o) \ + [D3DRS_##o] = {NINE_STATE_BOOL} + +#define __MASK_RS(o, m) \ + [D3DRS_##o] = {NINE_STATE_MASK, {.mask = m}} + +#define __RANGE_DEF_VAL_RS(o, m, M, d) \ + [D3DRS_##o] = {NINE_STATE_RANGE_DEF_VAL, {.range_def_val = {m, M, d}}} + +#define __TO_DETERMINE_RS(o, m, M) \ + [D3DRS_##o] = {NINE_STATE_NO_LIMIT} + +static const struct nine_state_behaviour +render_state_limits_table[D3DRS_BLENDOPALPHA + 1] = { + __TO_DETERMINE_RS(ZENABLE, 0, 3), + __TO_DETERMINE_RS(FILLMODE, 1, 3), + __CLAMP_RS(SHADEMODE, 1, 3), + __BOOLEAN_RS(ZWRITEENABLE), + __BOOLEAN_RS(ALPHATESTENABLE), + __BOOLEAN_RS(LASTPIXEL), + __RANGE_DEF_VAL_RS(SRCBLEND, 1, 17, D3DBLEND_ZERO), + __RANGE_DEF_VAL_RS(DESTBLEND, 1, 17, D3DBLEND_ZERO), + __CLAMP_RS(CULLMODE, 1, 3), + __CLAMP_RS(ZFUNC, 1, 8), + __MASK_RS(ALPHAREF, 0x000000FF), + __CLAMP_RS(ALPHAFUNC, 1, 8), + __BOOLEAN_RS(DITHERENABLE), + __BOOLEAN_RS(ALPHABLENDENABLE), + __BOOLEAN_RS(FOGENABLE), + __BOOLEAN_RS(SPECULARENABLE), + __NO_LIMIT_RS(FOGCOLOR), + __MASK_RS(FOGTABLEMODE, 0x00000007), + __NO_LIMIT_RS(FOGSTART), /* a bit more complex than that, lets ignore */ + __NO_LIMIT_RS(FOGEND), + __NO_LIMIT_RS(FOGDENSITY), /* actually should be between 0.0 and 1.0 */ + __BOOLEAN_RS(RANGEFOGENABLE), + __BOOLEAN_RS(STENCILENABLE), + __CLAMP_RS(STENCILFAIL, 1, 8), + __CLAMP_RS(STENCILZFAIL, 1, 8), + __CLAMP_RS(STENCILPASS, 1, 8), + __CLAMP_RS(STENCILFUNC, 1, 8), + __NO_LIMIT_RS(STENCILREF), + __NO_LIMIT_RS(STENCILMASK), + __NO_LIMIT_RS(STENCILWRITEMASK), + __NO_LIMIT_RS(TEXTUREFACTOR), + __TO_DETERMINE_RS(WRAP0, 0, 15), + __TO_DETERMINE_RS(WRAP1, 0, 15), + __TO_DETERMINE_RS(WRAP2, 0, 15), + __TO_DETERMINE_RS(WRAP3, 0, 15), + __TO_DETERMINE_RS(WRAP4, 0, 15), + __TO_DETERMINE_RS(WRAP5, 0, 15), + __TO_DETERMINE_RS(WRAP6, 0, 15), + __TO_DETERMINE_RS(WRAP7, 0, 15), + __BOOLEAN_RS(CLIPPING), + __BOOLEAN_RS(LIGHTING), + __NO_LIMIT_RS(AMBIENT), + __MASK_RS(FOGVERTEXMODE, 0x00000007), + __BOOLEAN_RS(COLORVERTEX), + __BOOLEAN_RS(LOCALVIEWER), + __BOOLEAN_RS(NORMALIZENORMALS), + __TO_DETERMINE_RS(DIFFUSEMATERIALSOURCE, 0, 2), + __TO_DETERMINE_RS(SPECULARMATERIALSOURCE, 0, 2), + __TO_DETERMINE_RS(AMBIENTMATERIALSOURCE, 0, 2), + __TO_DETERMINE_RS(EMISSIVEMATERIALSOURCE, 0, 2), + __TO_DETERMINE_RS(VERTEXBLEND, 0, 256), /* values between 4 and 254 -both included- are forbidden too */ + __NO_LIMIT_RS(CLIPPLANEENABLE), /* expected check seems complex */ + __TO_DETERMINE_RS(POINTSIZE, 0, 0xFFFFFFFF), + __TO_DETERMINE_RS(POINTSIZE_MIN, 0, 0x7FFFFFFF), /* float >= 0.0 */ + __BOOLEAN_RS(POINTSPRITEENABLE), + __BOOLEAN_RS(POINTSCALEENABLE), + __TO_DETERMINE_RS(POINTSCALE_A, 0, 0x7FFFFFFF), /* float >= 0.0 */ + __TO_DETERMINE_RS(POINTSCALE_B, 0, 0x7FFFFFFF), /* float >= 0.0 */ + __TO_DETERMINE_RS(POINTSCALE_C, 0, 0x7FFFFFFF), /* float >= 0.0 */ + __BOOLEAN_RS(MULTISAMPLEANTIALIAS), + __NO_LIMIT_RS(MULTISAMPLEMASK), + __TO_DETERMINE_RS(PATCHEDGESTYLE, 0, 1), + __TO_DETERMINE_RS(DEBUGMONITORTOKEN, 0, 1), + __TO_DETERMINE_RS(POINTSIZE_MAX, 0, 0x7FFFFFFF), /* check more complex than that */ + __BOOLEAN_RS(INDEXEDVERTEXBLENDENABLE), + __TO_DETERMINE_RS(COLORWRITEENABLE, 0, 15), + __NO_LIMIT_RS(TWEENFACTOR), + __CLAMP_RS(BLENDOP, 1, 5), + __TO_DETERMINE_RS(POSITIONDEGREE, 1, 5), /* can actually be only 1 or 5 */ + __TO_DETERMINE_RS(NORMALDEGREE, 1, 2), + __BOOLEAN_RS(SCISSORTESTENABLE), + __NO_LIMIT_RS(SLOPESCALEDEPTHBIAS), + __BOOLEAN_RS(ANTIALIASEDLINEENABLE), + __NO_LIMIT_RS(MINTESSELLATIONLEVEL), + __NO_LIMIT_RS(MAXTESSELLATIONLEVEL), + __NO_LIMIT_RS(ADAPTIVETESS_X), + __NO_LIMIT_RS(ADAPTIVETESS_Y), + __NO_LIMIT_RS(ADAPTIVETESS_Z), + __NO_LIMIT_RS(ADAPTIVETESS_W), + __BOOLEAN_RS(ENABLEADAPTIVETESSELLATION), + __BOOLEAN_RS(TWOSIDEDSTENCILMODE), + __CLAMP_RS(CCW_STENCILFAIL, 1, 8), + __CLAMP_RS(CCW_STENCILZFAIL, 1, 8), + __CLAMP_RS(CCW_STENCILPASS, 1, 8), + __CLAMP_RS(CCW_STENCILFUNC, 1, 8), + __TO_DETERMINE_RS(COLORWRITEENABLE1, 0, 15), + __TO_DETERMINE_RS(COLORWRITEENABLE2, 0, 15), + __TO_DETERMINE_RS(COLORWRITEENABLE3, 0, 15), + __NO_LIMIT_RS(BLENDFACTOR), + __BOOLEAN_RS(SRGBWRITEENABLE), + __NO_LIMIT_RS(DEPTHBIAS), + __TO_DETERMINE_RS(WRAP8, 0, 15), + __TO_DETERMINE_RS(WRAP9, 0, 15), + __TO_DETERMINE_RS(WRAP10, 0, 15), + __TO_DETERMINE_RS(WRAP11, 0, 15), + __TO_DETERMINE_RS(WRAP12, 0, 15), + __TO_DETERMINE_RS(WRAP13, 0, 15), + __TO_DETERMINE_RS(WRAP14, 0, 15), + __TO_DETERMINE_RS(WRAP15, 0, 15), + __BOOLEAN_RS(SEPARATEALPHABLENDENABLE), + __RANGE_DEF_VAL_RS(SRCBLENDALPHA, 1, 17, D3DBLEND_ZERO), + __RANGE_DEF_VAL_RS(DESTBLENDALPHA, 1, 17, D3DBLEND_ZERO), + __CLAMP_RS(BLENDOPALPHA, 1, 5) +}; + +static DWORD inline +nine_fix_render_state_value(D3DRENDERSTATETYPE State, + DWORD Value) +{ + struct nine_state_behaviour behaviour = render_state_limits_table[State]; + + switch (behaviour.state_value_behaviour) { + case NINE_STATE_NO_LIMIT: + break; + case NINE_STATE_CLAMP: + if (Value < behaviour.u.clamp.min) + Value = behaviour.u.clamp.min; + else if (Value > behaviour.u.clamp.max) + Value = behaviour.u.clamp.max; + break; + case NINE_STATE_BOOL: + Value = Value ? 1 : 0; + break; + case NINE_STATE_MASK: + Value = Value & behaviour.u.mask; + break; + case NINE_STATE_RANGE_DEF_VAL: + if (Value < behaviour.u.range_def_val.min || Value > behaviour.u.range_def_val.max) + Value = behaviour.u.range_def_val.default_val; + break; + } + + return Value; +} + +struct nine_limits +{ + unsigned min; + unsigned max; +}; + +#define __VALUE_SAMP(o, m, M) \ + [D3DSAMP_##o] = {m, M} + +static const struct nine_limits +sampler_state_limits_table[D3DRS_BLENDOPALPHA + 1] = { + __VALUE_SAMP(ADDRESSU, 1, 5), + __VALUE_SAMP(ADDRESSV, 1, 5), + __VALUE_SAMP(ADDRESSW, 1, 5), + __VALUE_SAMP(BORDERCOLOR, 0, 0xFFFFFFFF), + __VALUE_SAMP(MAGFILTER, 0, 8), /* 4-5 should be forbidden */ + __VALUE_SAMP(MINFILTER, 0, 8), /* same */ + __VALUE_SAMP(MIPFILTER, 0, 8), /* same */ + __VALUE_SAMP(MIPMAPLODBIAS, 0, 0xFFFFFFFF), + __VALUE_SAMP(MAXMIPLEVEL, 0, 0xFFFFFFFF), + __VALUE_SAMP(MAXANISOTROPY, 1, 0xFFFFFFFF), /* Max value should be pCaps->MaxAnisotropy */ + __VALUE_SAMP(SRGBTEXTURE, 0, 1), + __VALUE_SAMP(ELEMENTINDEX, 0, 0xFFFFFFFF), + __VALUE_SAMP(DMAPOFFSET, 0, 0xFFFFFFFF) +}; + +static BOOL inline +nine_check_sampler_state_value(D3DSAMPLERSTATETYPE State, + DWORD Value) +{ + struct nine_limits limit; + + limit = sampler_state_limits_table[State]; + return (limit.min <= Value && Value <= limit.max); +} + +#endif /* _NINE_HELPERS_H_ */ diff --git a/src/gallium/frontends/nine/nine_lock.c b/src/gallium/frontends/nine/nine_lock.c new file mode 100644 index 00000000000..ca0f04a69b3 --- /dev/null +++ b/src/gallium/frontends/nine/nine_lock.c @@ -0,0 +1,3294 @@ +/* + * Copyright 2013 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "authenticatedchannel9.h" +#include "basetexture9.h" +#include "cryptosession9.h" +#include "cubetexture9.h" +#include "device9.h" +#include "device9ex.h" +#include "device9video.h" +#include "indexbuffer9.h" +#include "pixelshader9.h" +#include "query9.h" +#include "resource9.h" +#include "stateblock9.h" +#include "surface9.h" +#include "swapchain9.h" +#include "swapchain9ex.h" +#include "texture9.h" +#include "vertexbuffer9.h" +#include "vertexdeclaration9.h" +#include "vertexshader9.h" +#include "volume9.h" +#include "volumetexture9.h" + +#include "d3d9.h" +#include "nine_lock.h" + +#include "os/os_thread.h" + +/* Global mutex as described by MSDN */ +static mtx_t d3dlock_global = _MTX_INITIALIZER_NP; + +void +NineLockGlobalMutex() +{ + mtx_lock(&d3dlock_global); +} + +void +NineUnlockGlobalMutex() +{ + mtx_unlock(&d3dlock_global); +} + +static HRESULT NINE_WINAPI +LockAuthenticatedChannel9_GetCertificateSize( struct NineAuthenticatedChannel9 *This, + UINT *pCertificateSize ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineAuthenticatedChannel9_GetCertificateSize(This, pCertificateSize); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockAuthenticatedChannel9_GetCertificate( struct NineAuthenticatedChannel9 *This, + UINT CertifacteSize, + BYTE *ppCertificate ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineAuthenticatedChannel9_GetCertificate(This, CertifacteSize, ppCertificate); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockAuthenticatedChannel9_NegotiateKeyExchange( struct NineAuthenticatedChannel9 *This, + UINT DataSize, + void *pData ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineAuthenticatedChannel9_NegotiateKeyExchange(This, DataSize, pData); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockAuthenticatedChannel9_Query( struct NineAuthenticatedChannel9 *This, + UINT InputSize, + const void *pInput, + UINT OutputSize, + void *pOutput ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineAuthenticatedChannel9_Query(This, InputSize, pInput, OutputSize, pOutput); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockAuthenticatedChannel9_Configure( struct NineAuthenticatedChannel9 *This, + UINT InputSize, + const void *pInput, + D3DAUTHENTICATEDCHANNEL_CONFIGURE_OUTPUT *pOutput ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineAuthenticatedChannel9_Configure(This, InputSize, pInput, pOutput); + mtx_unlock(&d3dlock_global); + return r; +} + +IDirect3DAuthenticatedChannel9Vtbl LockAuthenticatedChannel9_vtable = { + (void *)NineUnknown_QueryInterface, + (void *)NineUnknown_AddRef, + (void *)NineUnknown_ReleaseWithDtorLock, + (void *)LockAuthenticatedChannel9_GetCertificateSize, + (void *)LockAuthenticatedChannel9_GetCertificate, + (void *)LockAuthenticatedChannel9_NegotiateKeyExchange, + (void *)LockAuthenticatedChannel9_Query, + (void *)LockAuthenticatedChannel9_Configure +}; + +static HRESULT NINE_WINAPI +LockUnknown_SetPrivateData( struct NineUnknown *This, + REFGUID refguid, + const void *pData, + DWORD SizeOfData, + DWORD Flags ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineUnknown_SetPrivateData(This, refguid, pData, SizeOfData, Flags); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockUnknown_GetPrivateData( struct NineUnknown *This, + REFGUID refguid, + void *pData, + DWORD *pSizeOfData ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineUnknown_GetPrivateData(This, refguid, pData, pSizeOfData); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockUnknown_FreePrivateData( struct NineUnknown *This, + REFGUID refguid ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineUnknown_FreePrivateData(This, refguid); + mtx_unlock(&d3dlock_global); + return r; +} + +#if 0 +static HRESULT NINE_WINAPI +LockResource9_GetDevice( struct NineResource9 *This, + IDirect3DDevice9 **ppDevice ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineUnknown_GetDevice(NineUnknown(This), ppDevice); + mtx_unlock(&d3dlock_global); + return r; +} +#endif + +static DWORD NINE_WINAPI +LockResource9_SetPriority( struct NineResource9 *This, + DWORD PriorityNew ) +{ + DWORD r; + mtx_lock(&d3dlock_global); + r = NineResource9_SetPriority(This, PriorityNew); + mtx_unlock(&d3dlock_global); + return r; +} + +static DWORD NINE_WINAPI +LockResource9_GetPriority( struct NineResource9 *This ) +{ + DWORD r; + mtx_lock(&d3dlock_global); + r = NineResource9_GetPriority(This); + mtx_unlock(&d3dlock_global); + return r; +} + +#if 0 +static void NINE_WINAPI +LockResource9_PreLoad( struct NineResource9 *This ) +{ + mtx_lock(&d3dlock_global); + NineResource9_PreLoad(This); + mtx_unlock(&d3dlock_global); +} +#endif + +#if 0 +static D3DRESOURCETYPE NINE_WINAPI +LockResource9_GetType( struct NineResource9 *This ) +{ + D3DRESOURCETYPE r; + mtx_lock(&d3dlock_global); + r = NineResource9_GetType(This); + mtx_unlock(&d3dlock_global); + return r; +} +#endif + +static DWORD NINE_WINAPI +LockBaseTexture9_SetLOD( struct NineBaseTexture9 *This, + DWORD LODNew ) +{ + DWORD r; + mtx_lock(&d3dlock_global); + r = NineBaseTexture9_SetLOD(This, LODNew); + mtx_unlock(&d3dlock_global); + return r; +} + +static DWORD NINE_WINAPI +LockBaseTexture9_GetLOD( struct NineBaseTexture9 *This ) +{ + DWORD r; + mtx_lock(&d3dlock_global); + r = NineBaseTexture9_GetLOD(This); + mtx_unlock(&d3dlock_global); + return r; +} + +static DWORD NINE_WINAPI +LockBaseTexture9_GetLevelCount( struct NineBaseTexture9 *This ) +{ + DWORD r; + mtx_lock(&d3dlock_global); + r = NineBaseTexture9_GetLevelCount(This); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockBaseTexture9_SetAutoGenFilterType( struct NineBaseTexture9 *This, + D3DTEXTUREFILTERTYPE FilterType ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineBaseTexture9_SetAutoGenFilterType(This, FilterType); + mtx_unlock(&d3dlock_global); + return r; +} + +static D3DTEXTUREFILTERTYPE NINE_WINAPI +LockBaseTexture9_GetAutoGenFilterType( struct NineBaseTexture9 *This ) +{ + D3DTEXTUREFILTERTYPE r; + mtx_lock(&d3dlock_global); + r = NineBaseTexture9_GetAutoGenFilterType(This); + mtx_unlock(&d3dlock_global); + return r; +} + +static void NINE_WINAPI +LockBaseTexture9_PreLoad( struct NineBaseTexture9 *This ) +{ + mtx_lock(&d3dlock_global); + NineBaseTexture9_PreLoad(This); + mtx_unlock(&d3dlock_global); +} + +static void NINE_WINAPI +LockBaseTexture9_GenerateMipSubLevels( struct NineBaseTexture9 *This ) +{ + mtx_lock(&d3dlock_global); + NineBaseTexture9_GenerateMipSubLevels(This); + mtx_unlock(&d3dlock_global); +} + +static HRESULT NINE_WINAPI +LockCryptoSession9_GetCertificateSize( struct NineCryptoSession9 *This, + UINT *pCertificateSize ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineCryptoSession9_GetCertificateSize(This, pCertificateSize); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockCryptoSession9_GetCertificate( struct NineCryptoSession9 *This, + UINT CertifacteSize, + BYTE *ppCertificate ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineCryptoSession9_GetCertificate(This, CertifacteSize, ppCertificate); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockCryptoSession9_NegotiateKeyExchange( struct NineCryptoSession9 *This, + UINT DataSize, + void *pData ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineCryptoSession9_NegotiateKeyExchange(This, DataSize, pData); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockCryptoSession9_EncryptionBlt( struct NineCryptoSession9 *This, + IDirect3DSurface9 *pSrcSurface, + IDirect3DSurface9 *pDstSurface, + UINT DstSurfaceSize, + void *pIV ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineCryptoSession9_EncryptionBlt(This, pSrcSurface, pDstSurface, DstSurfaceSize, pIV); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockCryptoSession9_DecryptionBlt( struct NineCryptoSession9 *This, + IDirect3DSurface9 *pSrcSurface, + IDirect3DSurface9 *pDstSurface, + UINT SrcSurfaceSize, + D3DENCRYPTED_BLOCK_INFO *pEncryptedBlockInfo, + void *pContentKey, + void *pIV ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineCryptoSession9_DecryptionBlt(This, pSrcSurface, pDstSurface, SrcSurfaceSize, pEncryptedBlockInfo, pContentKey, pIV); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockCryptoSession9_GetSurfacePitch( struct NineCryptoSession9 *This, + IDirect3DSurface9 *pSrcSurface, + UINT *pSurfacePitch ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineCryptoSession9_GetSurfacePitch(This, pSrcSurface, pSurfacePitch); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockCryptoSession9_StartSessionKeyRefresh( struct NineCryptoSession9 *This, + void *pRandomNumber, + UINT RandomNumberSize ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineCryptoSession9_StartSessionKeyRefresh(This, pRandomNumber, RandomNumberSize); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockCryptoSession9_FinishSessionKeyRefresh( struct NineCryptoSession9 *This ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineCryptoSession9_FinishSessionKeyRefresh(This); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockCryptoSession9_GetEncryptionBltKey( struct NineCryptoSession9 *This, + void *pReadbackKey, + UINT KeySize ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineCryptoSession9_GetEncryptionBltKey(This, pReadbackKey, KeySize); + mtx_unlock(&d3dlock_global); + return r; +} + +IDirect3DCryptoSession9Vtbl LockCryptoSession9_vtable = { + (void *)NineUnknown_QueryInterface, + (void *)NineUnknown_AddRef, + (void *)NineUnknown_ReleaseWithDtorLock, + (void *)LockCryptoSession9_GetCertificateSize, + (void *)LockCryptoSession9_GetCertificate, + (void *)LockCryptoSession9_NegotiateKeyExchange, + (void *)LockCryptoSession9_EncryptionBlt, + (void *)LockCryptoSession9_DecryptionBlt, + (void *)LockCryptoSession9_GetSurfacePitch, + (void *)LockCryptoSession9_StartSessionKeyRefresh, + (void *)LockCryptoSession9_FinishSessionKeyRefresh, + (void *)LockCryptoSession9_GetEncryptionBltKey +}; + +#if 0 +static HRESULT NINE_WINAPI +LockCubeTexture9_GetLevelDesc( struct NineCubeTexture9 *This, + UINT Level, + D3DSURFACE_DESC *pDesc ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineCubeTexture9_GetLevelDesc(This, Level, pDesc); + mtx_unlock(&d3dlock_global); + return r; +} +#endif + +#if 0 +static HRESULT NINE_WINAPI +LockCubeTexture9_GetCubeMapSurface( struct NineCubeTexture9 *This, + D3DCUBEMAP_FACES FaceType, + UINT Level, + IDirect3DSurface9 **ppCubeMapSurface ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineCubeTexture9_GetCubeMapSurface(This, FaceType, Level, ppCubeMapSurface); + mtx_unlock(&d3dlock_global); + return r; +} +#endif + +static HRESULT NINE_WINAPI +LockCubeTexture9_LockRect( struct NineCubeTexture9 *This, + D3DCUBEMAP_FACES FaceType, + UINT Level, + D3DLOCKED_RECT *pLockedRect, + const RECT *pRect, + DWORD Flags ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineCubeTexture9_LockRect(This, FaceType, Level, pLockedRect, pRect, Flags); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockCubeTexture9_UnlockRect( struct NineCubeTexture9 *This, + D3DCUBEMAP_FACES FaceType, + UINT Level ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineCubeTexture9_UnlockRect(This, FaceType, Level); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockCubeTexture9_AddDirtyRect( struct NineCubeTexture9 *This, + D3DCUBEMAP_FACES FaceType, + const RECT *pDirtyRect ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineCubeTexture9_AddDirtyRect(This, FaceType, pDirtyRect); + mtx_unlock(&d3dlock_global); + return r; +} + +IDirect3DCubeTexture9Vtbl LockCubeTexture9_vtable = { + (void *)NineUnknown_QueryInterface, + (void *)NineUnknown_AddRef, + (void *)NineUnknown_ReleaseWithDtorLock, + (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */ + (void *)LockUnknown_SetPrivateData, + (void *)LockUnknown_GetPrivateData, + (void *)LockUnknown_FreePrivateData, + (void *)LockResource9_SetPriority, + (void *)LockResource9_GetPriority, + (void *)LockBaseTexture9_PreLoad, + (void *)NineResource9_GetType, /* immutable */ + (void *)LockBaseTexture9_SetLOD, + (void *)LockBaseTexture9_GetLOD, + (void *)LockBaseTexture9_GetLevelCount, + (void *)LockBaseTexture9_SetAutoGenFilterType, + (void *)LockBaseTexture9_GetAutoGenFilterType, + (void *)LockBaseTexture9_GenerateMipSubLevels, + (void *)NineCubeTexture9_GetLevelDesc, /* immutable */ + (void *)NineCubeTexture9_GetCubeMapSurface, /* AddRef */ + (void *)LockCubeTexture9_LockRect, + (void *)LockCubeTexture9_UnlockRect, + (void *)LockCubeTexture9_AddDirtyRect +}; + +static HRESULT NINE_WINAPI +LockDevice9_TestCooperativeLevel( struct NineDevice9 *This ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_TestCooperativeLevel(This); + mtx_unlock(&d3dlock_global); + return r; +} + +static UINT NINE_WINAPI +LockDevice9_GetAvailableTextureMem( struct NineDevice9 *This ) +{ + UINT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_GetAvailableTextureMem(This); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_EvictManagedResources( struct NineDevice9 *This ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_EvictManagedResources(This); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_GetDirect3D( struct NineDevice9 *This, + IDirect3D9 **ppD3D9 ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_GetDirect3D(This, ppD3D9); + mtx_unlock(&d3dlock_global); + return r; +} + +#if 0 +static HRESULT NINE_WINAPI +LockDevice9_GetDeviceCaps( struct NineDevice9 *This, + D3DCAPS9 *pCaps ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_GetDeviceCaps(This, pCaps); + mtx_unlock(&d3dlock_global); + return r; +} +#endif + +static HRESULT NINE_WINAPI +LockDevice9_GetDisplayMode( struct NineDevice9 *This, + UINT iSwapChain, + D3DDISPLAYMODE *pMode ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_GetDisplayMode(This, iSwapChain, pMode); + mtx_unlock(&d3dlock_global); + return r; +} + +#if 0 +static HRESULT NINE_WINAPI +LockDevice9_GetCreationParameters( struct NineDevice9 *This, + D3DDEVICE_CREATION_PARAMETERS *pParameters ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_GetCreationParameters(This, pParameters); + mtx_unlock(&d3dlock_global); + return r; +} +#endif + +static HRESULT NINE_WINAPI +LockDevice9_SetCursorProperties( struct NineDevice9 *This, + UINT XHotSpot, + UINT YHotSpot, + IDirect3DSurface9 *pCursorBitmap ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_SetCursorProperties(This, XHotSpot, YHotSpot, pCursorBitmap); + mtx_unlock(&d3dlock_global); + return r; +} + +static void NINE_WINAPI +LockDevice9_SetCursorPosition( struct NineDevice9 *This, + int X, + int Y, + DWORD Flags ) +{ + mtx_lock(&d3dlock_global); + NineDevice9_SetCursorPosition(This, X, Y, Flags); + mtx_unlock(&d3dlock_global); +} + +static BOOL NINE_WINAPI +LockDevice9_ShowCursor( struct NineDevice9 *This, + BOOL bShow ) +{ + BOOL r; + mtx_lock(&d3dlock_global); + r = NineDevice9_ShowCursor(This, bShow); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_CreateAdditionalSwapChain( struct NineDevice9 *This, + D3DPRESENT_PARAMETERS *pPresentationParameters, + IDirect3DSwapChain9 **pSwapChain ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_CreateAdditionalSwapChain(This, pPresentationParameters, pSwapChain); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_GetSwapChain( struct NineDevice9 *This, + UINT iSwapChain, + IDirect3DSwapChain9 **pSwapChain ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_GetSwapChain(This, iSwapChain, pSwapChain); + mtx_unlock(&d3dlock_global); + return r; +} + +static UINT NINE_WINAPI +LockDevice9_GetNumberOfSwapChains( struct NineDevice9 *This ) +{ + UINT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_GetNumberOfSwapChains(This); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_Reset( struct NineDevice9 *This, + D3DPRESENT_PARAMETERS *pPresentationParameters ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_Reset(This, pPresentationParameters); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_Present( struct NineDevice9 *This, + const RECT *pSourceRect, + const RECT *pDestRect, + HWND hDestWindowOverride, + const RGNDATA *pDirtyRegion ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_Present(This, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_GetBackBuffer( struct NineDevice9 *This, + UINT iSwapChain, + UINT iBackBuffer, + D3DBACKBUFFER_TYPE Type, + IDirect3DSurface9 **ppBackBuffer ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_GetBackBuffer(This, iSwapChain, iBackBuffer, Type, ppBackBuffer); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_GetRasterStatus( struct NineDevice9 *This, + UINT iSwapChain, + D3DRASTER_STATUS *pRasterStatus ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_GetRasterStatus(This, iSwapChain, pRasterStatus); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_SetDialogBoxMode( struct NineDevice9 *This, + BOOL bEnableDialogs ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_SetDialogBoxMode(This, bEnableDialogs); + mtx_unlock(&d3dlock_global); + return r; +} + +static void NINE_WINAPI +LockDevice9_SetGammaRamp( struct NineDevice9 *This, + UINT iSwapChain, + DWORD Flags, + const D3DGAMMARAMP *pRamp ) +{ + mtx_lock(&d3dlock_global); + NineDevice9_SetGammaRamp(This, iSwapChain, Flags, pRamp); + mtx_unlock(&d3dlock_global); +} + +static void NINE_WINAPI +LockDevice9_GetGammaRamp( struct NineDevice9 *This, + UINT iSwapChain, + D3DGAMMARAMP *pRamp ) +{ + mtx_lock(&d3dlock_global); + NineDevice9_GetGammaRamp(This, iSwapChain, pRamp); + mtx_unlock(&d3dlock_global); +} + +static HRESULT NINE_WINAPI +LockDevice9_CreateTexture( struct NineDevice9 *This, + UINT Width, + UINT Height, + UINT Levels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + IDirect3DTexture9 **ppTexture, + HANDLE *pSharedHandle ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_CreateTexture(This, Width, Height, Levels, Usage, Format, Pool, ppTexture, pSharedHandle); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_CreateVolumeTexture( struct NineDevice9 *This, + UINT Width, + UINT Height, + UINT Depth, + UINT Levels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + IDirect3DVolumeTexture9 **ppVolumeTexture, + HANDLE *pSharedHandle ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_CreateVolumeTexture(This, Width, Height, Depth, Levels, Usage, Format, Pool, ppVolumeTexture, pSharedHandle); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_CreateCubeTexture( struct NineDevice9 *This, + UINT EdgeLength, + UINT Levels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + IDirect3DCubeTexture9 **ppCubeTexture, + HANDLE *pSharedHandle ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_CreateCubeTexture(This, EdgeLength, Levels, Usage, Format, Pool, ppCubeTexture, pSharedHandle); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_CreateVertexBuffer( struct NineDevice9 *This, + UINT Length, + DWORD Usage, + DWORD FVF, + D3DPOOL Pool, + IDirect3DVertexBuffer9 **ppVertexBuffer, + HANDLE *pSharedHandle ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_CreateVertexBuffer(This, Length, Usage, FVF, Pool, ppVertexBuffer, pSharedHandle); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_CreateIndexBuffer( struct NineDevice9 *This, + UINT Length, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + IDirect3DIndexBuffer9 **ppIndexBuffer, + HANDLE *pSharedHandle ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_CreateIndexBuffer(This, Length, Usage, Format, Pool, ppIndexBuffer, pSharedHandle); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_CreateRenderTarget( struct NineDevice9 *This, + UINT Width, + UINT Height, + D3DFORMAT Format, + D3DMULTISAMPLE_TYPE MultiSample, + DWORD MultisampleQuality, + BOOL Lockable, + IDirect3DSurface9 **ppSurface, + HANDLE *pSharedHandle ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_CreateRenderTarget(This, Width, Height, Format, MultiSample, MultisampleQuality, Lockable, ppSurface, pSharedHandle); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_CreateDepthStencilSurface( struct NineDevice9 *This, + UINT Width, + UINT Height, + D3DFORMAT Format, + D3DMULTISAMPLE_TYPE MultiSample, + DWORD MultisampleQuality, + BOOL Discard, + IDirect3DSurface9 **ppSurface, + HANDLE *pSharedHandle ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_CreateDepthStencilSurface(This, Width, Height, Format, MultiSample, MultisampleQuality, Discard, ppSurface, pSharedHandle); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_UpdateSurface( struct NineDevice9 *This, + IDirect3DSurface9 *pSourceSurface, + const RECT *pSourceRect, + IDirect3DSurface9 *pDestinationSurface, + const POINT *pDestPoint ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_UpdateSurface(This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_UpdateTexture( struct NineDevice9 *This, + IDirect3DBaseTexture9 *pSourceTexture, + IDirect3DBaseTexture9 *pDestinationTexture ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_UpdateTexture(This, pSourceTexture, pDestinationTexture); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_GetRenderTargetData( struct NineDevice9 *This, + IDirect3DSurface9 *pRenderTarget, + IDirect3DSurface9 *pDestSurface ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_GetRenderTargetData(This, pRenderTarget, pDestSurface); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_GetFrontBufferData( struct NineDevice9 *This, + UINT iSwapChain, + IDirect3DSurface9 *pDestSurface ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_GetFrontBufferData(This, iSwapChain, pDestSurface); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_StretchRect( struct NineDevice9 *This, + IDirect3DSurface9 *pSourceSurface, + const RECT *pSourceRect, + IDirect3DSurface9 *pDestSurface, + const RECT *pDestRect, + D3DTEXTUREFILTERTYPE Filter ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_StretchRect(This, pSourceSurface, pSourceRect, pDestSurface, pDestRect, Filter); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_ColorFill( struct NineDevice9 *This, + IDirect3DSurface9 *pSurface, + const RECT *pRect, + D3DCOLOR color ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_ColorFill(This, pSurface, pRect, color); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_CreateOffscreenPlainSurface( struct NineDevice9 *This, + UINT Width, + UINT Height, + D3DFORMAT Format, + D3DPOOL Pool, + IDirect3DSurface9 **ppSurface, + HANDLE *pSharedHandle ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_CreateOffscreenPlainSurface(This, Width, Height, Format, Pool, ppSurface, pSharedHandle); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_SetRenderTarget( struct NineDevice9 *This, + DWORD RenderTargetIndex, + IDirect3DSurface9 *pRenderTarget ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_SetRenderTarget(This, RenderTargetIndex, pRenderTarget); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_GetRenderTarget( struct NineDevice9 *This, + DWORD RenderTargetIndex, + IDirect3DSurface9 **ppRenderTarget ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_GetRenderTarget(This, RenderTargetIndex, ppRenderTarget); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_SetDepthStencilSurface( struct NineDevice9 *This, + IDirect3DSurface9 *pNewZStencil ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_SetDepthStencilSurface(This, pNewZStencil); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_GetDepthStencilSurface( struct NineDevice9 *This, + IDirect3DSurface9 **ppZStencilSurface ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_GetDepthStencilSurface(This, ppZStencilSurface); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_BeginScene( struct NineDevice9 *This ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_BeginScene(This); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_EndScene( struct NineDevice9 *This ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_EndScene(This); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_Clear( struct NineDevice9 *This, + DWORD Count, + const D3DRECT *pRects, + DWORD Flags, + D3DCOLOR Color, + float Z, + DWORD Stencil ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_Clear(This, Count, pRects, Flags, Color, Z, Stencil); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_SetTransform( struct NineDevice9 *This, + D3DTRANSFORMSTATETYPE State, + const D3DMATRIX *pMatrix ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_SetTransform(This, State, pMatrix); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_GetTransform( struct NineDevice9 *This, + D3DTRANSFORMSTATETYPE State, + D3DMATRIX *pMatrix ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_GetTransform(This, State, pMatrix); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_MultiplyTransform( struct NineDevice9 *This, + D3DTRANSFORMSTATETYPE State, + const D3DMATRIX *pMatrix ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_MultiplyTransform(This, State, pMatrix); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_SetViewport( struct NineDevice9 *This, + const D3DVIEWPORT9 *pViewport ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_SetViewport(This, pViewport); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_GetViewport( struct NineDevice9 *This, + D3DVIEWPORT9 *pViewport ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_GetViewport(This, pViewport); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_SetMaterial( struct NineDevice9 *This, + const D3DMATERIAL9 *pMaterial ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_SetMaterial(This, pMaterial); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_GetMaterial( struct NineDevice9 *This, + D3DMATERIAL9 *pMaterial ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_GetMaterial(This, pMaterial); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_SetLight( struct NineDevice9 *This, + DWORD Index, + const D3DLIGHT9 *pLight ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_SetLight(This, Index, pLight); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_GetLight( struct NineDevice9 *This, + DWORD Index, + D3DLIGHT9 *pLight ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_GetLight(This, Index, pLight); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_LightEnable( struct NineDevice9 *This, + DWORD Index, + BOOL Enable ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_LightEnable(This, Index, Enable); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_GetLightEnable( struct NineDevice9 *This, + DWORD Index, + BOOL *pEnable ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_GetLightEnable(This, Index, pEnable); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_SetClipPlane( struct NineDevice9 *This, + DWORD Index, + const float *pPlane ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_SetClipPlane(This, Index, pPlane); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_GetClipPlane( struct NineDevice9 *This, + DWORD Index, + float *pPlane ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_GetClipPlane(This, Index, pPlane); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_SetRenderState( struct NineDevice9 *This, + D3DRENDERSTATETYPE State, + DWORD Value ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_SetRenderState(This, State, Value); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_GetRenderState( struct NineDevice9 *This, + D3DRENDERSTATETYPE State, + DWORD *pValue ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_GetRenderState(This, State, pValue); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_CreateStateBlock( struct NineDevice9 *This, + D3DSTATEBLOCKTYPE Type, + IDirect3DStateBlock9 **ppSB ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_CreateStateBlock(This, Type, ppSB); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_BeginStateBlock( struct NineDevice9 *This ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_BeginStateBlock(This); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_EndStateBlock( struct NineDevice9 *This, + IDirect3DStateBlock9 **ppSB ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_EndStateBlock(This, ppSB); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_SetClipStatus( struct NineDevice9 *This, + const D3DCLIPSTATUS9 *pClipStatus ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_SetClipStatus(This, pClipStatus); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_GetClipStatus( struct NineDevice9 *This, + D3DCLIPSTATUS9 *pClipStatus ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_GetClipStatus(This, pClipStatus); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_GetTexture( struct NineDevice9 *This, + DWORD Stage, + IDirect3DBaseTexture9 **ppTexture ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_GetTexture(This, Stage, ppTexture); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_SetTexture( struct NineDevice9 *This, + DWORD Stage, + IDirect3DBaseTexture9 *pTexture ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_SetTexture(This, Stage, pTexture); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_GetTextureStageState( struct NineDevice9 *This, + DWORD Stage, + D3DTEXTURESTAGESTATETYPE Type, + DWORD *pValue ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_GetTextureStageState(This, Stage, Type, pValue); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_SetTextureStageState( struct NineDevice9 *This, + DWORD Stage, + D3DTEXTURESTAGESTATETYPE Type, + DWORD Value ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_SetTextureStageState(This, Stage, Type, Value); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_GetSamplerState( struct NineDevice9 *This, + DWORD Sampler, + D3DSAMPLERSTATETYPE Type, + DWORD *pValue ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_GetSamplerState(This, Sampler, Type, pValue); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_SetSamplerState( struct NineDevice9 *This, + DWORD Sampler, + D3DSAMPLERSTATETYPE Type, + DWORD Value ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_SetSamplerState(This, Sampler, Type, Value); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_ValidateDevice( struct NineDevice9 *This, + DWORD *pNumPasses ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_ValidateDevice(This, pNumPasses); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_SetPaletteEntries( struct NineDevice9 *This, + UINT PaletteNumber, + const PALETTEENTRY *pEntries ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_SetPaletteEntries(This, PaletteNumber, pEntries); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_GetPaletteEntries( struct NineDevice9 *This, + UINT PaletteNumber, + PALETTEENTRY *pEntries ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_GetPaletteEntries(This, PaletteNumber, pEntries); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_SetCurrentTexturePalette( struct NineDevice9 *This, + UINT PaletteNumber ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_SetCurrentTexturePalette(This, PaletteNumber); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_GetCurrentTexturePalette( struct NineDevice9 *This, + UINT *PaletteNumber ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_GetCurrentTexturePalette(This, PaletteNumber); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_SetScissorRect( struct NineDevice9 *This, + const RECT *pRect ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_SetScissorRect(This, pRect); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_GetScissorRect( struct NineDevice9 *This, + RECT *pRect ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_GetScissorRect(This, pRect); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_SetSoftwareVertexProcessing( struct NineDevice9 *This, + BOOL bSoftware ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_SetSoftwareVertexProcessing(This, bSoftware); + mtx_unlock(&d3dlock_global); + return r; +} + +static BOOL NINE_WINAPI +LockDevice9_GetSoftwareVertexProcessing( struct NineDevice9 *This ) +{ + BOOL r; + mtx_lock(&d3dlock_global); + r = NineDevice9_GetSoftwareVertexProcessing(This); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_SetNPatchMode( struct NineDevice9 *This, + float nSegments ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_SetNPatchMode(This, nSegments); + mtx_unlock(&d3dlock_global); + return r; +} + +static float NINE_WINAPI +LockDevice9_GetNPatchMode( struct NineDevice9 *This ) +{ + float r; + mtx_lock(&d3dlock_global); + r = NineDevice9_GetNPatchMode(This); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_DrawPrimitive( struct NineDevice9 *This, + D3DPRIMITIVETYPE PrimitiveType, + UINT StartVertex, + UINT PrimitiveCount ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_DrawPrimitive(This, PrimitiveType, StartVertex, PrimitiveCount); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_DrawIndexedPrimitive( struct NineDevice9 *This, + D3DPRIMITIVETYPE PrimitiveType, + INT BaseVertexIndex, + UINT MinVertexIndex, + UINT NumVertices, + UINT startIndex, + UINT primCount ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_DrawIndexedPrimitive(This, PrimitiveType, BaseVertexIndex, MinVertexIndex, NumVertices, startIndex, primCount); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_DrawPrimitiveUP( struct NineDevice9 *This, + D3DPRIMITIVETYPE PrimitiveType, + UINT PrimitiveCount, + const void *pVertexStreamZeroData, + UINT VertexStreamZeroStride ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_DrawPrimitiveUP(This, PrimitiveType, PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_DrawIndexedPrimitiveUP( struct NineDevice9 *This, + D3DPRIMITIVETYPE PrimitiveType, + UINT MinVertexIndex, + UINT NumVertices, + UINT PrimitiveCount, + const void *pIndexData, + D3DFORMAT IndexDataFormat, + const void *pVertexStreamZeroData, + UINT VertexStreamZeroStride ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_DrawIndexedPrimitiveUP(This, PrimitiveType, MinVertexIndex, NumVertices, PrimitiveCount, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_ProcessVertices( struct NineDevice9 *This, + UINT SrcStartIndex, + UINT DestIndex, + UINT VertexCount, + IDirect3DVertexBuffer9 *pDestBuffer, + IDirect3DVertexDeclaration9 *pVertexDecl, + DWORD Flags ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_ProcessVertices(This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_CreateVertexDeclaration( struct NineDevice9 *This, + const D3DVERTEXELEMENT9 *pVertexElements, + IDirect3DVertexDeclaration9 **ppDecl ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_CreateVertexDeclaration(This, pVertexElements, ppDecl); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_SetVertexDeclaration( struct NineDevice9 *This, + IDirect3DVertexDeclaration9 *pDecl ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_SetVertexDeclaration(This, pDecl); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_GetVertexDeclaration( struct NineDevice9 *This, + IDirect3DVertexDeclaration9 **ppDecl ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_GetVertexDeclaration(This, ppDecl); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_SetFVF( struct NineDevice9 *This, + DWORD FVF ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_SetFVF(This, FVF); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_GetFVF( struct NineDevice9 *This, + DWORD *pFVF ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_GetFVF(This, pFVF); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_CreateVertexShader( struct NineDevice9 *This, + const DWORD *pFunction, + IDirect3DVertexShader9 **ppShader ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_CreateVertexShader(This, pFunction, ppShader); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_SetVertexShader( struct NineDevice9 *This, + IDirect3DVertexShader9 *pShader ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_SetVertexShader(This, pShader); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_GetVertexShader( struct NineDevice9 *This, + IDirect3DVertexShader9 **ppShader ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_GetVertexShader(This, ppShader); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_SetVertexShaderConstantF( struct NineDevice9 *This, + UINT StartRegister, + const float *pConstantData, + UINT Vector4fCount ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_SetVertexShaderConstantF(This, StartRegister, pConstantData, Vector4fCount); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_GetVertexShaderConstantF( struct NineDevice9 *This, + UINT StartRegister, + float *pConstantData, + UINT Vector4fCount ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_GetVertexShaderConstantF(This, StartRegister, pConstantData, Vector4fCount); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_SetVertexShaderConstantI( struct NineDevice9 *This, + UINT StartRegister, + const int *pConstantData, + UINT Vector4iCount ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_SetVertexShaderConstantI(This, StartRegister, pConstantData, Vector4iCount); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_GetVertexShaderConstantI( struct NineDevice9 *This, + UINT StartRegister, + int *pConstantData, + UINT Vector4iCount ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_GetVertexShaderConstantI(This, StartRegister, pConstantData, Vector4iCount); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_SetVertexShaderConstantB( struct NineDevice9 *This, + UINT StartRegister, + const BOOL *pConstantData, + UINT BoolCount ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_SetVertexShaderConstantB(This, StartRegister, pConstantData, BoolCount); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_GetVertexShaderConstantB( struct NineDevice9 *This, + UINT StartRegister, + BOOL *pConstantData, + UINT BoolCount ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_GetVertexShaderConstantB(This, StartRegister, pConstantData, BoolCount); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_SetStreamSource( struct NineDevice9 *This, + UINT StreamNumber, + IDirect3DVertexBuffer9 *pStreamData, + UINT OffsetInBytes, + UINT Stride ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_SetStreamSource(This, StreamNumber, pStreamData, OffsetInBytes, Stride); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_GetStreamSource( struct NineDevice9 *This, + UINT StreamNumber, + IDirect3DVertexBuffer9 **ppStreamData, + UINT *pOffsetInBytes, + UINT *pStride ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_GetStreamSource(This, StreamNumber, ppStreamData, pOffsetInBytes, pStride); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_SetStreamSourceFreq( struct NineDevice9 *This, + UINT StreamNumber, + UINT Setting ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_SetStreamSourceFreq(This, StreamNumber, Setting); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_GetStreamSourceFreq( struct NineDevice9 *This, + UINT StreamNumber, + UINT *pSetting ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_GetStreamSourceFreq(This, StreamNumber, pSetting); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_SetIndices( struct NineDevice9 *This, + IDirect3DIndexBuffer9 *pIndexData ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_SetIndices(This, pIndexData); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_GetIndices( struct NineDevice9 *This, + IDirect3DIndexBuffer9 **ppIndexData ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_GetIndices(This, ppIndexData); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_CreatePixelShader( struct NineDevice9 *This, + const DWORD *pFunction, + IDirect3DPixelShader9 **ppShader ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_CreatePixelShader(This, pFunction, ppShader); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_SetPixelShader( struct NineDevice9 *This, + IDirect3DPixelShader9 *pShader ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_SetPixelShader(This, pShader); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_GetPixelShader( struct NineDevice9 *This, + IDirect3DPixelShader9 **ppShader ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_GetPixelShader(This, ppShader); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_SetPixelShaderConstantF( struct NineDevice9 *This, + UINT StartRegister, + const float *pConstantData, + UINT Vector4fCount ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_SetPixelShaderConstantF(This, StartRegister, pConstantData, Vector4fCount); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_GetPixelShaderConstantF( struct NineDevice9 *This, + UINT StartRegister, + float *pConstantData, + UINT Vector4fCount ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_GetPixelShaderConstantF(This, StartRegister, pConstantData, Vector4fCount); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_SetPixelShaderConstantI( struct NineDevice9 *This, + UINT StartRegister, + const int *pConstantData, + UINT Vector4iCount ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_SetPixelShaderConstantI(This, StartRegister, pConstantData, Vector4iCount); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_GetPixelShaderConstantI( struct NineDevice9 *This, + UINT StartRegister, + int *pConstantData, + UINT Vector4iCount ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_GetPixelShaderConstantI(This, StartRegister, pConstantData, Vector4iCount); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_SetPixelShaderConstantB( struct NineDevice9 *This, + UINT StartRegister, + const BOOL *pConstantData, + UINT BoolCount ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_SetPixelShaderConstantB(This, StartRegister, pConstantData, BoolCount); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_GetPixelShaderConstantB( struct NineDevice9 *This, + UINT StartRegister, + BOOL *pConstantData, + UINT BoolCount ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_GetPixelShaderConstantB(This, StartRegister, pConstantData, BoolCount); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_DrawRectPatch( struct NineDevice9 *This, + UINT Handle, + const float *pNumSegs, + const D3DRECTPATCH_INFO *pRectPatchInfo ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_DrawRectPatch(This, Handle, pNumSegs, pRectPatchInfo); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_DrawTriPatch( struct NineDevice9 *This, + UINT Handle, + const float *pNumSegs, + const D3DTRIPATCH_INFO *pTriPatchInfo ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_DrawTriPatch(This, Handle, pNumSegs, pTriPatchInfo); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_DeletePatch( struct NineDevice9 *This, + UINT Handle ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_DeletePatch(This, Handle); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9_CreateQuery( struct NineDevice9 *This, + D3DQUERYTYPE Type, + IDirect3DQuery9 **ppQuery ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9_CreateQuery(This, Type, ppQuery); + mtx_unlock(&d3dlock_global); + return r; +} + +IDirect3DDevice9Vtbl LockDevice9_vtable = { + (void *)NineUnknown_QueryInterface, + (void *)NineUnknown_AddRef, + (void *)NineUnknown_ReleaseWithDtorLock, + (void *)LockDevice9_TestCooperativeLevel, + (void *)LockDevice9_GetAvailableTextureMem, + (void *)LockDevice9_EvictManagedResources, + (void *)LockDevice9_GetDirect3D, + (void *)NineDevice9_GetDeviceCaps, /* immutable */ + (void *)LockDevice9_GetDisplayMode, + (void *)NineDevice9_GetCreationParameters, /* immutable */ + (void *)LockDevice9_SetCursorProperties, + (void *)LockDevice9_SetCursorPosition, + (void *)LockDevice9_ShowCursor, + (void *)LockDevice9_CreateAdditionalSwapChain, + (void *)LockDevice9_GetSwapChain, + (void *)LockDevice9_GetNumberOfSwapChains, + (void *)LockDevice9_Reset, + (void *)LockDevice9_Present, + (void *)LockDevice9_GetBackBuffer, + (void *)LockDevice9_GetRasterStatus, + (void *)LockDevice9_SetDialogBoxMode, + (void *)LockDevice9_SetGammaRamp, + (void *)LockDevice9_GetGammaRamp, + (void *)LockDevice9_CreateTexture, + (void *)LockDevice9_CreateVolumeTexture, + (void *)LockDevice9_CreateCubeTexture, + (void *)LockDevice9_CreateVertexBuffer, + (void *)LockDevice9_CreateIndexBuffer, + (void *)LockDevice9_CreateRenderTarget, + (void *)LockDevice9_CreateDepthStencilSurface, + (void *)LockDevice9_UpdateSurface, + (void *)LockDevice9_UpdateTexture, + (void *)LockDevice9_GetRenderTargetData, + (void *)LockDevice9_GetFrontBufferData, + (void *)LockDevice9_StretchRect, + (void *)LockDevice9_ColorFill, + (void *)LockDevice9_CreateOffscreenPlainSurface, + (void *)LockDevice9_SetRenderTarget, + (void *)LockDevice9_GetRenderTarget, + (void *)LockDevice9_SetDepthStencilSurface, + (void *)LockDevice9_GetDepthStencilSurface, + (void *)LockDevice9_BeginScene, + (void *)LockDevice9_EndScene, + (void *)LockDevice9_Clear, + (void *)LockDevice9_SetTransform, + (void *)LockDevice9_GetTransform, + (void *)LockDevice9_MultiplyTransform, + (void *)LockDevice9_SetViewport, + (void *)LockDevice9_GetViewport, + (void *)LockDevice9_SetMaterial, + (void *)LockDevice9_GetMaterial, + (void *)LockDevice9_SetLight, + (void *)LockDevice9_GetLight, + (void *)LockDevice9_LightEnable, + (void *)LockDevice9_GetLightEnable, + (void *)LockDevice9_SetClipPlane, + (void *)LockDevice9_GetClipPlane, + (void *)LockDevice9_SetRenderState, + (void *)LockDevice9_GetRenderState, + (void *)LockDevice9_CreateStateBlock, + (void *)LockDevice9_BeginStateBlock, + (void *)LockDevice9_EndStateBlock, + (void *)LockDevice9_SetClipStatus, + (void *)LockDevice9_GetClipStatus, + (void *)LockDevice9_GetTexture, + (void *)LockDevice9_SetTexture, + (void *)LockDevice9_GetTextureStageState, + (void *)LockDevice9_SetTextureStageState, + (void *)LockDevice9_GetSamplerState, + (void *)LockDevice9_SetSamplerState, + (void *)LockDevice9_ValidateDevice, + (void *)LockDevice9_SetPaletteEntries, + (void *)LockDevice9_GetPaletteEntries, + (void *)LockDevice9_SetCurrentTexturePalette, + (void *)LockDevice9_GetCurrentTexturePalette, + (void *)LockDevice9_SetScissorRect, + (void *)LockDevice9_GetScissorRect, + (void *)LockDevice9_SetSoftwareVertexProcessing, + (void *)LockDevice9_GetSoftwareVertexProcessing, + (void *)LockDevice9_SetNPatchMode, + (void *)LockDevice9_GetNPatchMode, + (void *)LockDevice9_DrawPrimitive, + (void *)LockDevice9_DrawIndexedPrimitive, + (void *)LockDevice9_DrawPrimitiveUP, + (void *)LockDevice9_DrawIndexedPrimitiveUP, + (void *)LockDevice9_ProcessVertices, + (void *)LockDevice9_CreateVertexDeclaration, + (void *)LockDevice9_SetVertexDeclaration, + (void *)LockDevice9_GetVertexDeclaration, + (void *)LockDevice9_SetFVF, + (void *)LockDevice9_GetFVF, + (void *)LockDevice9_CreateVertexShader, + (void *)LockDevice9_SetVertexShader, + (void *)LockDevice9_GetVertexShader, + (void *)LockDevice9_SetVertexShaderConstantF, + (void *)LockDevice9_GetVertexShaderConstantF, + (void *)LockDevice9_SetVertexShaderConstantI, + (void *)LockDevice9_GetVertexShaderConstantI, + (void *)LockDevice9_SetVertexShaderConstantB, + (void *)LockDevice9_GetVertexShaderConstantB, + (void *)LockDevice9_SetStreamSource, + (void *)LockDevice9_GetStreamSource, + (void *)LockDevice9_SetStreamSourceFreq, + (void *)LockDevice9_GetStreamSourceFreq, + (void *)LockDevice9_SetIndices, + (void *)LockDevice9_GetIndices, + (void *)LockDevice9_CreatePixelShader, + (void *)LockDevice9_SetPixelShader, + (void *)LockDevice9_GetPixelShader, + (void *)LockDevice9_SetPixelShaderConstantF, + (void *)LockDevice9_GetPixelShaderConstantF, + (void *)LockDevice9_SetPixelShaderConstantI, + (void *)LockDevice9_GetPixelShaderConstantI, + (void *)LockDevice9_SetPixelShaderConstantB, + (void *)LockDevice9_GetPixelShaderConstantB, + (void *)LockDevice9_DrawRectPatch, + (void *)LockDevice9_DrawTriPatch, + (void *)LockDevice9_DeletePatch, + (void *)LockDevice9_CreateQuery +}; + +static HRESULT NINE_WINAPI +LockDevice9Ex_SetConvolutionMonoKernel( struct NineDevice9Ex *This, + UINT width, + UINT height, + float *rows, + float *columns ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9Ex_SetConvolutionMonoKernel(This, width, height, rows, columns); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9Ex_ComposeRects( struct NineDevice9Ex *This, + IDirect3DSurface9 *pSrc, + IDirect3DSurface9 *pDst, + IDirect3DVertexBuffer9 *pSrcRectDescs, + UINT NumRects, + IDirect3DVertexBuffer9 *pDstRectDescs, + D3DCOMPOSERECTSOP Operation, + int Xoffset, + int Yoffset ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9Ex_ComposeRects(This, pSrc, pDst, pSrcRectDescs, NumRects, pDstRectDescs, Operation, Xoffset, Yoffset); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9Ex_PresentEx( struct NineDevice9Ex *This, + const RECT *pSourceRect, + const RECT *pDestRect, + HWND hDestWindowOverride, + const RGNDATA *pDirtyRegion, + DWORD dwFlags ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9Ex_PresentEx(This, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, dwFlags); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9Ex_GetGPUThreadPriority( struct NineDevice9Ex *This, + INT *pPriority ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9Ex_GetGPUThreadPriority(This, pPriority); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9Ex_SetGPUThreadPriority( struct NineDevice9Ex *This, + INT Priority ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9Ex_SetGPUThreadPriority(This, Priority); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9Ex_WaitForVBlank( struct NineDevice9Ex *This, + UINT iSwapChain ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9Ex_WaitForVBlank(This, iSwapChain); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9Ex_CheckResourceResidency( struct NineDevice9Ex *This, + IDirect3DResource9 **pResourceArray, + UINT32 NumResources ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9Ex_CheckResourceResidency(This, pResourceArray, NumResources); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9Ex_SetMaximumFrameLatency( struct NineDevice9Ex *This, + UINT MaxLatency ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9Ex_SetMaximumFrameLatency(This, MaxLatency); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9Ex_GetMaximumFrameLatency( struct NineDevice9Ex *This, + UINT *pMaxLatency ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9Ex_GetMaximumFrameLatency(This, pMaxLatency); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9Ex_CheckDeviceState( struct NineDevice9Ex *This, + HWND hDestinationWindow ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9Ex_CheckDeviceState(This, hDestinationWindow); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9Ex_CreateRenderTargetEx( struct NineDevice9Ex *This, + UINT Width, + UINT Height, + D3DFORMAT Format, + D3DMULTISAMPLE_TYPE MultiSample, + DWORD MultisampleQuality, + BOOL Lockable, + IDirect3DSurface9 **ppSurface, + HANDLE *pSharedHandle, + DWORD Usage ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9Ex_CreateRenderTargetEx(This, Width, Height, Format, MultiSample, MultisampleQuality, Lockable, ppSurface, pSharedHandle, Usage); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9Ex_CreateOffscreenPlainSurfaceEx( struct NineDevice9Ex *This, + UINT Width, + UINT Height, + D3DFORMAT Format, + D3DPOOL Pool, + IDirect3DSurface9 **ppSurface, + HANDLE *pSharedHandle, + DWORD Usage ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9Ex_CreateOffscreenPlainSurfaceEx(This, Width, Height, Format, Pool, ppSurface, pSharedHandle, Usage); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9Ex_CreateDepthStencilSurfaceEx( struct NineDevice9Ex *This, + UINT Width, + UINT Height, + D3DFORMAT Format, + D3DMULTISAMPLE_TYPE MultiSample, + DWORD MultisampleQuality, + BOOL Discard, + IDirect3DSurface9 **ppSurface, + HANDLE *pSharedHandle, + DWORD Usage ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9Ex_CreateDepthStencilSurfaceEx(This, Width, Height, Format, MultiSample, MultisampleQuality, Discard, ppSurface, pSharedHandle, Usage); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9Ex_ResetEx( struct NineDevice9Ex *This, + D3DPRESENT_PARAMETERS *pPresentationParameters, + D3DDISPLAYMODEEX *pFullscreenDisplayMode ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9Ex_ResetEx(This, pPresentationParameters, pFullscreenDisplayMode); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9Ex_GetDisplayModeEx( struct NineDevice9Ex *This, + UINT iSwapChain, + D3DDISPLAYMODEEX *pMode, + D3DDISPLAYROTATION *pRotation ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9Ex_GetDisplayModeEx(This, iSwapChain, pMode, pRotation); + mtx_unlock(&d3dlock_global); + return r; +} + +IDirect3DDevice9ExVtbl LockDevice9Ex_vtable = { + (void *)NineUnknown_QueryInterface, + (void *)NineUnknown_AddRef, + (void *)NineUnknown_ReleaseWithDtorLock, + (void *)LockDevice9_TestCooperativeLevel, + (void *)LockDevice9_GetAvailableTextureMem, + (void *)LockDevice9_EvictManagedResources, + (void *)LockDevice9_GetDirect3D, + (void *)NineDevice9_GetDeviceCaps, + (void *)LockDevice9_GetDisplayMode, + (void *)NineDevice9_GetCreationParameters, + (void *)LockDevice9_SetCursorProperties, + (void *)LockDevice9_SetCursorPosition, + (void *)LockDevice9_ShowCursor, + (void *)LockDevice9_CreateAdditionalSwapChain, + (void *)LockDevice9_GetSwapChain, + (void *)LockDevice9_GetNumberOfSwapChains, + (void *)LockDevice9_Reset, + (void *)LockDevice9_Present, + (void *)LockDevice9_GetBackBuffer, + (void *)LockDevice9_GetRasterStatus, + (void *)LockDevice9_SetDialogBoxMode, + (void *)LockDevice9_SetGammaRamp, + (void *)LockDevice9_GetGammaRamp, + (void *)LockDevice9_CreateTexture, + (void *)LockDevice9_CreateVolumeTexture, + (void *)LockDevice9_CreateCubeTexture, + (void *)LockDevice9_CreateVertexBuffer, + (void *)LockDevice9_CreateIndexBuffer, + (void *)LockDevice9_CreateRenderTarget, + (void *)LockDevice9_CreateDepthStencilSurface, + (void *)LockDevice9_UpdateSurface, + (void *)LockDevice9_UpdateTexture, + (void *)LockDevice9_GetRenderTargetData, + (void *)LockDevice9_GetFrontBufferData, + (void *)LockDevice9_StretchRect, + (void *)LockDevice9_ColorFill, + (void *)LockDevice9_CreateOffscreenPlainSurface, + (void *)LockDevice9_SetRenderTarget, + (void *)LockDevice9_GetRenderTarget, + (void *)LockDevice9_SetDepthStencilSurface, + (void *)LockDevice9_GetDepthStencilSurface, + (void *)LockDevice9_BeginScene, + (void *)LockDevice9_EndScene, + (void *)LockDevice9_Clear, + (void *)LockDevice9_SetTransform, + (void *)LockDevice9_GetTransform, + (void *)LockDevice9_MultiplyTransform, + (void *)LockDevice9_SetViewport, + (void *)LockDevice9_GetViewport, + (void *)LockDevice9_SetMaterial, + (void *)LockDevice9_GetMaterial, + (void *)LockDevice9_SetLight, + (void *)LockDevice9_GetLight, + (void *)LockDevice9_LightEnable, + (void *)LockDevice9_GetLightEnable, + (void *)LockDevice9_SetClipPlane, + (void *)LockDevice9_GetClipPlane, + (void *)LockDevice9_SetRenderState, + (void *)LockDevice9_GetRenderState, + (void *)LockDevice9_CreateStateBlock, + (void *)LockDevice9_BeginStateBlock, + (void *)LockDevice9_EndStateBlock, + (void *)LockDevice9_SetClipStatus, + (void *)LockDevice9_GetClipStatus, + (void *)LockDevice9_GetTexture, + (void *)LockDevice9_SetTexture, + (void *)LockDevice9_GetTextureStageState, + (void *)LockDevice9_SetTextureStageState, + (void *)LockDevice9_GetSamplerState, + (void *)LockDevice9_SetSamplerState, + (void *)LockDevice9_ValidateDevice, + (void *)LockDevice9_SetPaletteEntries, + (void *)LockDevice9_GetPaletteEntries, + (void *)LockDevice9_SetCurrentTexturePalette, + (void *)LockDevice9_GetCurrentTexturePalette, + (void *)LockDevice9_SetScissorRect, + (void *)LockDevice9_GetScissorRect, + (void *)LockDevice9_SetSoftwareVertexProcessing, + (void *)LockDevice9_GetSoftwareVertexProcessing, + (void *)LockDevice9_SetNPatchMode, + (void *)LockDevice9_GetNPatchMode, + (void *)LockDevice9_DrawPrimitive, + (void *)LockDevice9_DrawIndexedPrimitive, + (void *)LockDevice9_DrawPrimitiveUP, + (void *)LockDevice9_DrawIndexedPrimitiveUP, + (void *)LockDevice9_ProcessVertices, + (void *)LockDevice9_CreateVertexDeclaration, + (void *)LockDevice9_SetVertexDeclaration, + (void *)LockDevice9_GetVertexDeclaration, + (void *)LockDevice9_SetFVF, + (void *)LockDevice9_GetFVF, + (void *)LockDevice9_CreateVertexShader, + (void *)LockDevice9_SetVertexShader, + (void *)LockDevice9_GetVertexShader, + (void *)LockDevice9_SetVertexShaderConstantF, + (void *)LockDevice9_GetVertexShaderConstantF, + (void *)LockDevice9_SetVertexShaderConstantI, + (void *)LockDevice9_GetVertexShaderConstantI, + (void *)LockDevice9_SetVertexShaderConstantB, + (void *)LockDevice9_GetVertexShaderConstantB, + (void *)LockDevice9_SetStreamSource, + (void *)LockDevice9_GetStreamSource, + (void *)LockDevice9_SetStreamSourceFreq, + (void *)LockDevice9_GetStreamSourceFreq, + (void *)LockDevice9_SetIndices, + (void *)LockDevice9_GetIndices, + (void *)LockDevice9_CreatePixelShader, + (void *)LockDevice9_SetPixelShader, + (void *)LockDevice9_GetPixelShader, + (void *)LockDevice9_SetPixelShaderConstantF, + (void *)LockDevice9_GetPixelShaderConstantF, + (void *)LockDevice9_SetPixelShaderConstantI, + (void *)LockDevice9_GetPixelShaderConstantI, + (void *)LockDevice9_SetPixelShaderConstantB, + (void *)LockDevice9_GetPixelShaderConstantB, + (void *)LockDevice9_DrawRectPatch, + (void *)LockDevice9_DrawTriPatch, + (void *)LockDevice9_DeletePatch, + (void *)LockDevice9_CreateQuery, + (void *)LockDevice9Ex_SetConvolutionMonoKernel, + (void *)LockDevice9Ex_ComposeRects, + (void *)LockDevice9Ex_PresentEx, + (void *)LockDevice9Ex_GetGPUThreadPriority, + (void *)LockDevice9Ex_SetGPUThreadPriority, + (void *)LockDevice9Ex_WaitForVBlank, + (void *)LockDevice9Ex_CheckResourceResidency, + (void *)LockDevice9Ex_SetMaximumFrameLatency, + (void *)LockDevice9Ex_GetMaximumFrameLatency, + (void *)LockDevice9Ex_CheckDeviceState, + (void *)LockDevice9Ex_CreateRenderTargetEx, + (void *)LockDevice9Ex_CreateOffscreenPlainSurfaceEx, + (void *)LockDevice9Ex_CreateDepthStencilSurfaceEx, + (void *)LockDevice9Ex_ResetEx, + (void *)LockDevice9Ex_GetDisplayModeEx +}; + +static HRESULT NINE_WINAPI +LockDevice9Video_GetContentProtectionCaps( struct NineDevice9Video *This, + const GUID *pCryptoType, + const GUID *pDecodeProfile, + D3DCONTENTPROTECTIONCAPS *pCaps ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9Video_GetContentProtectionCaps(This, pCryptoType, pDecodeProfile, pCaps); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9Video_CreateAuthenticatedChannel( struct NineDevice9Video *This, + D3DAUTHENTICATEDCHANNELTYPE ChannelType, + IDirect3DAuthenticatedChannel9 **ppAuthenticatedChannel, + HANDLE *pChannelHandle ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9Video_CreateAuthenticatedChannel(This, ChannelType, ppAuthenticatedChannel, pChannelHandle); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockDevice9Video_CreateCryptoSession( struct NineDevice9Video *This, + const GUID *pCryptoType, + const GUID *pDecodeProfile, + IDirect3DCryptoSession9 **ppCryptoSession, + HANDLE *pCryptoHandle ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineDevice9Video_CreateCryptoSession(This, pCryptoType, pDecodeProfile, ppCryptoSession, pCryptoHandle); + mtx_unlock(&d3dlock_global); + return r; +} + +IDirect3DDevice9VideoVtbl LockDevice9Video_vtable = { + (void *)NineUnknown_QueryInterface, + (void *)NineUnknown_AddRef, + (void *)NineUnknown_ReleaseWithDtorLock, + (void *)LockDevice9Video_GetContentProtectionCaps, + (void *)LockDevice9Video_CreateAuthenticatedChannel, + (void *)LockDevice9Video_CreateCryptoSession +}; + +static HRESULT NINE_WINAPI +LockIndexBuffer9_Lock( struct NineIndexBuffer9 *This, + UINT OffsetToLock, + UINT SizeToLock, + void **ppbData, + DWORD Flags ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineIndexBuffer9_Lock(This, OffsetToLock, SizeToLock, ppbData, Flags); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockIndexBuffer9_Unlock( struct NineIndexBuffer9 *This ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineIndexBuffer9_Unlock(This); + mtx_unlock(&d3dlock_global); + return r; +} + +#if 0 +static HRESULT NINE_WINAPI +LockIndexBuffer9_GetDesc( struct NineIndexBuffer9 *This, + D3DINDEXBUFFER_DESC *pDesc ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineIndexBuffer9_GetDesc(This, pDesc); + mtx_unlock(&d3dlock_global); + return r; +} +#endif + +IDirect3DIndexBuffer9Vtbl LockIndexBuffer9_vtable = { + (void *)NineUnknown_QueryInterface, + (void *)NineUnknown_AddRef, + (void *)NineUnknown_ReleaseWithDtorLock, + (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */ + (void *)LockUnknown_SetPrivateData, + (void *)LockUnknown_GetPrivateData, + (void *)LockUnknown_FreePrivateData, + (void *)LockResource9_SetPriority, + (void *)LockResource9_GetPriority, + (void *)NineResource9_PreLoad, /* nop */ + (void *)NineResource9_GetType, /* immutable */ + (void *)LockIndexBuffer9_Lock, + (void *)LockIndexBuffer9_Unlock, + (void *)NineIndexBuffer9_GetDesc /* immutable */ +}; + +#if 0 +static HRESULT NINE_WINAPI +LockPixelShader9_GetDevice( struct NinePixelShader9 *This, + IDirect3DDevice9 **ppDevice ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineUnknown_GetDevice(NineUnknown(This), ppDevice); + mtx_unlock(&d3dlock_global); + return r; +} +#endif + +static HRESULT NINE_WINAPI +LockPixelShader9_GetFunction( struct NinePixelShader9 *This, + void *pData, + UINT *pSizeOfData ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NinePixelShader9_GetFunction(This, pData, pSizeOfData); + mtx_unlock(&d3dlock_global); + return r; +} + +IDirect3DPixelShader9Vtbl LockPixelShader9_vtable = { + (void *)NineUnknown_QueryInterface, + (void *)NineUnknown_AddRef, + (void *)NineUnknown_ReleaseWithDtorLock, + (void *)NineUnknown_GetDevice, + (void *)LockPixelShader9_GetFunction +}; + +#if 0 +static HRESULT NINE_WINAPI +LockQuery9_GetDevice( struct NineQuery9 *This, + IDirect3DDevice9 **ppDevice ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineUnknown_GetDevice(NineUnknown(This), ppDevice); + mtx_unlock(&d3dlock_global); + return r; +} +#endif + +#if 0 +static D3DQUERYTYPE NINE_WINAPI +LockQuery9_GetType( struct NineQuery9 *This ) +{ + D3DQUERYTYPE r; + mtx_lock(&d3dlock_global); + r = NineQuery9_GetType(This); + mtx_unlock(&d3dlock_global); + return r; +} +#endif + +#if 0 +static DWORD NINE_WINAPI +LockQuery9_GetDataSize( struct NineQuery9 *This ) +{ + DWORD r; + mtx_lock(&d3dlock_global); + r = NineQuery9_GetDataSize(This); + mtx_unlock(&d3dlock_global); + return r; +} +#endif + +static HRESULT NINE_WINAPI +LockQuery9_Issue( struct NineQuery9 *This, + DWORD dwIssueFlags ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineQuery9_Issue(This, dwIssueFlags); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockQuery9_GetData( struct NineQuery9 *This, + void *pData, + DWORD dwSize, + DWORD dwGetDataFlags ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineQuery9_GetData(This, pData, dwSize, dwGetDataFlags); + mtx_unlock(&d3dlock_global); + return r; +} + +IDirect3DQuery9Vtbl LockQuery9_vtable = { + (void *)NineUnknown_QueryInterface, + (void *)NineUnknown_AddRef, + (void *)NineUnknown_ReleaseWithDtorLock, + (void *)NineUnknown_GetDevice, /* actually part of Query9 iface */ + (void *)NineQuery9_GetType, /* immutable */ + (void *)NineQuery9_GetDataSize, /* immutable */ + (void *)LockQuery9_Issue, + (void *)LockQuery9_GetData +}; + +#if 0 +static HRESULT NINE_WINAPI +LockStateBlock9_GetDevice( struct NineStateBlock9 *This, + IDirect3DDevice9 **ppDevice ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineUnknown_GetDevice(NineUnknown(This), ppDevice); + mtx_unlock(&d3dlock_global); + return r; +} +#endif + +static HRESULT NINE_WINAPI +LockStateBlock9_Capture( struct NineStateBlock9 *This ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineStateBlock9_Capture(This); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockStateBlock9_Apply( struct NineStateBlock9 *This ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineStateBlock9_Apply(This); + mtx_unlock(&d3dlock_global); + return r; +} + +IDirect3DStateBlock9Vtbl LockStateBlock9_vtable = { + (void *)NineUnknown_QueryInterface, + (void *)NineUnknown_AddRef, + (void *)NineUnknown_ReleaseWithDtorLock, + (void *)NineUnknown_GetDevice, /* actually part of StateBlock9 iface */ + (void *)LockStateBlock9_Capture, + (void *)LockStateBlock9_Apply +}; + +static HRESULT NINE_WINAPI +LockSurface9_GetContainer( struct NineSurface9 *This, + REFIID riid, + void **ppContainer ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineSurface9_GetContainer(This, riid, ppContainer); + mtx_unlock(&d3dlock_global); + return r; +} + +#if 0 +static HRESULT NINE_WINAPI +LockSurface9_GetDesc( struct NineSurface9 *This, + D3DSURFACE_DESC *pDesc ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineSurface9_GetDesc(This, pDesc); + mtx_unlock(&d3dlock_global); + return r; +} +#endif + +static HRESULT NINE_WINAPI +LockSurface9_LockRect( struct NineSurface9 *This, + D3DLOCKED_RECT *pLockedRect, + const RECT *pRect, + DWORD Flags ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineSurface9_LockRect(This, pLockedRect, pRect, Flags); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockSurface9_UnlockRect( struct NineSurface9 *This ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineSurface9_UnlockRect(This); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockSurface9_GetDC( struct NineSurface9 *This, + HDC *phdc ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineSurface9_GetDC(This, phdc); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockSurface9_ReleaseDC( struct NineSurface9 *This, + HDC hdc ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineSurface9_ReleaseDC(This, hdc); + mtx_unlock(&d3dlock_global); + return r; +} + +IDirect3DSurface9Vtbl LockSurface9_vtable = { + (void *)NineUnknown_QueryInterface, + (void *)NineUnknown_AddRef, + (void *)NineUnknown_ReleaseWithDtorLock, + (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */ + (void *)LockUnknown_SetPrivateData, + (void *)LockUnknown_GetPrivateData, + (void *)LockUnknown_FreePrivateData, + (void *)LockResource9_SetPriority, + (void *)LockResource9_GetPriority, + (void *)NineResource9_PreLoad, /* nop */ + (void *)NineResource9_GetType, /* immutable */ + (void *)LockSurface9_GetContainer, + (void *)NineSurface9_GetDesc, /* immutable */ + (void *)LockSurface9_LockRect, + (void *)LockSurface9_UnlockRect, + (void *)LockSurface9_GetDC, + (void *)LockSurface9_ReleaseDC +}; + +static HRESULT NINE_WINAPI +LockSwapChain9_Present( struct NineSwapChain9 *This, + const RECT *pSourceRect, + const RECT *pDestRect, + HWND hDestWindowOverride, + const RGNDATA *pDirtyRegion, + DWORD dwFlags ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineSwapChain9_Present(This, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, dwFlags); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockSwapChain9_GetFrontBufferData( struct NineSwapChain9 *This, + IDirect3DSurface9 *pDestSurface ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineSwapChain9_GetFrontBufferData(This, pDestSurface); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockSwapChain9_GetBackBuffer( struct NineSwapChain9 *This, + UINT iBackBuffer, + D3DBACKBUFFER_TYPE Type, + IDirect3DSurface9 **ppBackBuffer ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineSwapChain9_GetBackBuffer(This, iBackBuffer, Type, ppBackBuffer); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockSwapChain9_GetRasterStatus( struct NineSwapChain9 *This, + D3DRASTER_STATUS *pRasterStatus ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineSwapChain9_GetRasterStatus(This, pRasterStatus); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockSwapChain9_GetDisplayMode( struct NineSwapChain9 *This, + D3DDISPLAYMODE *pMode ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineSwapChain9_GetDisplayMode(This, pMode); + mtx_unlock(&d3dlock_global); + return r; +} + +#if 0 +static HRESULT NINE_WINAPI +LockSwapChain9_GetDevice( struct NineSwapChain9 *This, + IDirect3DDevice9 **ppDevice ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineUnknown_GetDevice(NineUnknown(This), ppDevice); + mtx_unlock(&d3dlock_global); + return r; +} +#endif + +static HRESULT NINE_WINAPI +LockSwapChain9_GetPresentParameters( struct NineSwapChain9 *This, + D3DPRESENT_PARAMETERS *pPresentationParameters ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineSwapChain9_GetPresentParameters(This, pPresentationParameters); + mtx_unlock(&d3dlock_global); + return r; +} + +IDirect3DSwapChain9Vtbl LockSwapChain9_vtable = { + (void *)NineUnknown_QueryInterface, + (void *)NineUnknown_AddRef, + (void *)NineUnknown_ReleaseWithDtorLock, + (void *)LockSwapChain9_Present, + (void *)LockSwapChain9_GetFrontBufferData, + (void *)LockSwapChain9_GetBackBuffer, + (void *)LockSwapChain9_GetRasterStatus, + (void *)LockSwapChain9_GetDisplayMode, + (void *)NineUnknown_GetDevice, /* actually part of SwapChain9 iface */ + (void *)LockSwapChain9_GetPresentParameters +}; + +static HRESULT NINE_WINAPI +LockSwapChain9Ex_GetLastPresentCount( struct NineSwapChain9Ex *This, + UINT *pLastPresentCount ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineSwapChain9Ex_GetLastPresentCount(This, pLastPresentCount); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockSwapChain9Ex_GetPresentStats( struct NineSwapChain9Ex *This, + D3DPRESENTSTATS *pPresentationStatistics ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineSwapChain9Ex_GetPresentStats(This, pPresentationStatistics); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockSwapChain9Ex_GetDisplayModeEx( struct NineSwapChain9Ex *This, + D3DDISPLAYMODEEX *pMode, + D3DDISPLAYROTATION *pRotation ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineSwapChain9Ex_GetDisplayModeEx(This, pMode, pRotation); + mtx_unlock(&d3dlock_global); + return r; +} + +IDirect3DSwapChain9ExVtbl LockSwapChain9Ex_vtable = { + (void *)NineUnknown_QueryInterface, + (void *)NineUnknown_AddRef, + (void *)NineUnknown_ReleaseWithDtorLock, + (void *)LockSwapChain9_Present, + (void *)LockSwapChain9_GetFrontBufferData, + (void *)LockSwapChain9_GetBackBuffer, + (void *)LockSwapChain9_GetRasterStatus, + (void *)LockSwapChain9_GetDisplayMode, + (void *)NineUnknown_GetDevice, /* actually part of NineSwapChain9 iface */ + (void *)LockSwapChain9_GetPresentParameters, + (void *)LockSwapChain9Ex_GetLastPresentCount, + (void *)LockSwapChain9Ex_GetPresentStats, + (void *)LockSwapChain9Ex_GetDisplayModeEx +}; + +#if 0 +static HRESULT NINE_WINAPI +LockTexture9_GetLevelDesc( struct NineTexture9 *This, + UINT Level, + D3DSURFACE_DESC *pDesc ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineTexture9_GetLevelDesc(This, Level, pDesc); + mtx_unlock(&d3dlock_global); + return r; +} +#endif + +#if 0 +static HRESULT NINE_WINAPI +LockTexture9_GetSurfaceLevel( struct NineTexture9 *This, + UINT Level, + IDirect3DSurface9 **ppSurfaceLevel ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineTexture9_GetSurfaceLevel(This, Level, ppSurfaceLevel); + mtx_unlock(&d3dlock_global); + return r; +} +#endif + +static HRESULT NINE_WINAPI +LockTexture9_LockRect( struct NineTexture9 *This, + UINT Level, + D3DLOCKED_RECT *pLockedRect, + const RECT *pRect, + DWORD Flags ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineTexture9_LockRect(This, Level, pLockedRect, pRect, Flags); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockTexture9_UnlockRect( struct NineTexture9 *This, + UINT Level ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineTexture9_UnlockRect(This, Level); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockTexture9_AddDirtyRect( struct NineTexture9 *This, + const RECT *pDirtyRect ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineTexture9_AddDirtyRect(This, pDirtyRect); + mtx_unlock(&d3dlock_global); + return r; +} + +IDirect3DTexture9Vtbl LockTexture9_vtable = { + (void *)NineUnknown_QueryInterface, + (void *)NineUnknown_AddRef, + (void *)NineUnknown_ReleaseWithDtorLock, + (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */ + (void *)LockUnknown_SetPrivateData, + (void *)LockUnknown_GetPrivateData, + (void *)LockUnknown_FreePrivateData, + (void *)LockResource9_SetPriority, + (void *)LockResource9_GetPriority, + (void *)LockBaseTexture9_PreLoad, + (void *)NineResource9_GetType, /* immutable */ + (void *)LockBaseTexture9_SetLOD, + (void *)LockBaseTexture9_GetLOD, + (void *)LockBaseTexture9_GetLevelCount, + (void *)LockBaseTexture9_SetAutoGenFilterType, + (void *)LockBaseTexture9_GetAutoGenFilterType, + (void *)LockBaseTexture9_GenerateMipSubLevels, + (void *)NineTexture9_GetLevelDesc, /* immutable */ + (void *)NineTexture9_GetSurfaceLevel, /* AddRef */ + (void *)LockTexture9_LockRect, + (void *)LockTexture9_UnlockRect, + (void *)LockTexture9_AddDirtyRect +}; + +static HRESULT NINE_WINAPI +LockVertexBuffer9_Lock( struct NineVertexBuffer9 *This, + UINT OffsetToLock, + UINT SizeToLock, + void **ppbData, + DWORD Flags ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineVertexBuffer9_Lock(This, OffsetToLock, SizeToLock, ppbData, Flags); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockVertexBuffer9_Unlock( struct NineVertexBuffer9 *This ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineVertexBuffer9_Unlock(This); + mtx_unlock(&d3dlock_global); + return r; +} + +#if 0 +static HRESULT NINE_WINAPI +LockVertexBuffer9_GetDesc( struct NineVertexBuffer9 *This, + D3DVERTEXBUFFER_DESC *pDesc ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineVertexBuffer9_GetDesc(This, pDesc); + mtx_unlock(&d3dlock_global); + return r; +} +#endif + +IDirect3DVertexBuffer9Vtbl LockVertexBuffer9_vtable = { + (void *)NineUnknown_QueryInterface, + (void *)NineUnknown_AddRef, + (void *)NineUnknown_ReleaseWithDtorLock, + (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */ + (void *)LockUnknown_SetPrivateData, + (void *)LockUnknown_GetPrivateData, + (void *)LockUnknown_FreePrivateData, + (void *)LockResource9_SetPriority, + (void *)LockResource9_GetPriority, + (void *)NineResource9_PreLoad, /* nop */ + (void *)NineResource9_GetType, /* immutable */ + (void *)LockVertexBuffer9_Lock, + (void *)LockVertexBuffer9_Unlock, + (void *)NineVertexBuffer9_GetDesc /* immutable */ +}; + +#if 0 +static HRESULT NINE_WINAPI +LockVertexDeclaration9_GetDevice( struct NineVertexDeclaration9 *This, + IDirect3DDevice9 **ppDevice ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineUnknown_GetDevice(NineUnknown(This), ppDevice); + mtx_unlock(&d3dlock_global); + return r; +} +#endif + +static HRESULT NINE_WINAPI +LockVertexDeclaration9_GetDeclaration( struct NineVertexDeclaration9 *This, + D3DVERTEXELEMENT9 *pElement, + UINT *pNumElements ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineVertexDeclaration9_GetDeclaration(This, pElement, pNumElements); + mtx_unlock(&d3dlock_global); + return r; +} + +IDirect3DVertexDeclaration9Vtbl LockVertexDeclaration9_vtable = { + (void *)NineUnknown_QueryInterface, + (void *)NineUnknown_AddRef, + (void *)NineUnknown_ReleaseWithDtorLock, + (void *)NineUnknown_GetDevice, /* actually part of VertexDecl9 iface */ + (void *)LockVertexDeclaration9_GetDeclaration +}; + +#if 0 +static HRESULT NINE_WINAPI +LockVertexShader9_GetDevice( struct NineVertexShader9 *This, + IDirect3DDevice9 **ppDevice ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineUnknown_GetDevice(NineUnknown(This), ppDevice); + mtx_unlock(&d3dlock_global); + return r; +} +#endif + +static HRESULT NINE_WINAPI +LockVertexShader9_GetFunction( struct NineVertexShader9 *This, + void *pData, + UINT *pSizeOfData ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineVertexShader9_GetFunction(This, pData, pSizeOfData); + mtx_unlock(&d3dlock_global); + return r; +} + +IDirect3DVertexShader9Vtbl LockVertexShader9_vtable = { + (void *)NineUnknown_QueryInterface, + (void *)NineUnknown_AddRef, + (void *)NineUnknown_ReleaseWithDtorLock, + (void *)NineUnknown_GetDevice, + (void *)LockVertexShader9_GetFunction +}; + +#if 0 +static HRESULT NINE_WINAPI +LockVolume9_GetDevice( struct NineVolume9 *This, + IDirect3DDevice9 **ppDevice ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineUnknown_GetDevice(NineUnknown(This), ppDevice); + mtx_unlock(&d3dlock_global); + return r; +} +#endif + +static HRESULT NINE_WINAPI +LockVolume9_GetContainer( struct NineVolume9 *This, + REFIID riid, + void **ppContainer ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineVolume9_GetContainer(This, riid, ppContainer); + mtx_unlock(&d3dlock_global); + return r; +} + +#if 0 +static HRESULT NINE_WINAPI +LockVolume9_GetDesc( struct NineVolume9 *This, + D3DVOLUME_DESC *pDesc ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineVolume9_GetDesc(This, pDesc); + mtx_unlock(&d3dlock_global); + return r; +} +#endif + +static HRESULT NINE_WINAPI +LockVolume9_LockBox( struct NineVolume9 *This, + D3DLOCKED_BOX *pLockedVolume, + const D3DBOX *pBox, + DWORD Flags ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineVolume9_LockBox(This, pLockedVolume, pBox, Flags); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockVolume9_UnlockBox( struct NineVolume9 *This ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineVolume9_UnlockBox(This); + mtx_unlock(&d3dlock_global); + return r; +} + +IDirect3DVolume9Vtbl LockVolume9_vtable = { + (void *)NineUnknown_QueryInterface, + (void *)NineUnknown_AddRef, + (void *)NineUnknown_ReleaseWithDtorLock, + (void *)NineUnknown_GetDevice, /* actually part of Volume9 iface */ + (void *)NineUnknown_SetPrivateData, + (void *)NineUnknown_GetPrivateData, + (void *)NineUnknown_FreePrivateData, + (void *)LockVolume9_GetContainer, + (void *)NineVolume9_GetDesc, /* immutable */ + (void *)LockVolume9_LockBox, + (void *)LockVolume9_UnlockBox +}; + +#if 0 +static HRESULT NINE_WINAPI +LockVolumeTexture9_GetLevelDesc( struct NineVolumeTexture9 *This, + UINT Level, + D3DVOLUME_DESC *pDesc ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineVolumeTexture9_GetLevelDesc(This, Level, pDesc); + mtx_unlock(&d3dlock_global); + return r; +} +#endif + +#if 0 +static HRESULT NINE_WINAPI +LockVolumeTexture9_GetVolumeLevel( struct NineVolumeTexture9 *This, + UINT Level, + IDirect3DVolume9 **ppVolumeLevel ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineVolumeTexture9_GetVolumeLevel(This, Level, ppVolumeLevel); + mtx_unlock(&d3dlock_global); + return r; +} +#endif + +static HRESULT NINE_WINAPI +LockVolumeTexture9_LockBox( struct NineVolumeTexture9 *This, + UINT Level, + D3DLOCKED_BOX *pLockedVolume, + const D3DBOX *pBox, + DWORD Flags ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineVolumeTexture9_LockBox(This, Level, pLockedVolume, pBox, Flags); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockVolumeTexture9_UnlockBox( struct NineVolumeTexture9 *This, + UINT Level ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineVolumeTexture9_UnlockBox(This, Level); + mtx_unlock(&d3dlock_global); + return r; +} + +static HRESULT NINE_WINAPI +LockVolumeTexture9_AddDirtyBox( struct NineVolumeTexture9 *This, + const D3DBOX *pDirtyBox ) +{ + HRESULT r; + mtx_lock(&d3dlock_global); + r = NineVolumeTexture9_AddDirtyBox(This, pDirtyBox); + mtx_unlock(&d3dlock_global); + return r; +} + +IDirect3DVolumeTexture9Vtbl LockVolumeTexture9_vtable = { + (void *)NineUnknown_QueryInterface, + (void *)NineUnknown_AddRef, + (void *)NineUnknown_ReleaseWithDtorLock, + (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */ + (void *)LockUnknown_SetPrivateData, + (void *)LockUnknown_GetPrivateData, + (void *)LockUnknown_FreePrivateData, + (void *)LockResource9_SetPriority, + (void *)LockResource9_GetPriority, + (void *)LockBaseTexture9_PreLoad, + (void *)NineResource9_GetType, /* immutable */ + (void *)LockBaseTexture9_SetLOD, + (void *)LockBaseTexture9_GetLOD, + (void *)LockBaseTexture9_GetLevelCount, + (void *)LockBaseTexture9_SetAutoGenFilterType, + (void *)LockBaseTexture9_GetAutoGenFilterType, + (void *)LockBaseTexture9_GenerateMipSubLevels, + (void *)NineVolumeTexture9_GetLevelDesc, /* immutable */ + (void *)NineVolumeTexture9_GetVolumeLevel, /* AddRef */ + (void *)LockVolumeTexture9_LockBox, + (void *)LockVolumeTexture9_UnlockBox, + (void *)LockVolumeTexture9_AddDirtyBox +}; + +ID3DAdapter9Vtbl LockAdapter9_vtable = { /* not used */ + (void *)NULL, + (void *)NULL, + (void *)NULL, + (void *)NULL, + (void *)NULL, + (void *)NULL, + (void *)NULL, + (void *)NULL, + (void *)NULL, + (void *)NULL, + (void *)NULL, + (void *)NULL +}; diff --git a/src/gallium/frontends/nine/nine_lock.h b/src/gallium/frontends/nine/nine_lock.h new file mode 100644 index 00000000000..4f4a5f14e54 --- /dev/null +++ b/src/gallium/frontends/nine/nine_lock.h @@ -0,0 +1,54 @@ +/* + * Copyright 2013 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _NINE_LOCK_H_ +#define _NINE_LOCK_H_ + +#include "d3d9.h" +#include "d3dadapter/d3dadapter9.h" + +extern IDirect3DAuthenticatedChannel9Vtbl LockAuthenticatedChannel9_vtable; +extern IDirect3DCryptoSession9Vtbl LockCryptoSession9_vtable; +extern IDirect3DCubeTexture9Vtbl LockCubeTexture9_vtable; +extern IDirect3DDevice9Vtbl LockDevice9_vtable; +extern IDirect3DDevice9ExVtbl LockDevice9Ex_vtable; +extern IDirect3DDevice9VideoVtbl LockDevice9Video_vtable; +extern IDirect3DIndexBuffer9Vtbl LockIndexBuffer9_vtable; +extern IDirect3DPixelShader9Vtbl LockPixelShader9_vtable; +extern IDirect3DQuery9Vtbl LockQuery9_vtable; +extern IDirect3DStateBlock9Vtbl LockStateBlock9_vtable; +extern IDirect3DSurface9Vtbl LockSurface9_vtable; +extern IDirect3DSwapChain9Vtbl LockSwapChain9_vtable; +extern IDirect3DSwapChain9ExVtbl LockSwapChain9Ex_vtable; +extern IDirect3DTexture9Vtbl LockTexture9_vtable; +extern IDirect3DVertexBuffer9Vtbl LockVertexBuffer9_vtable; +extern IDirect3DVertexDeclaration9Vtbl LockVertexDeclaration9_vtable; +extern IDirect3DVertexShader9Vtbl LockVertexShader9_vtable; +extern IDirect3DVolume9Vtbl LockVolume9_vtable; +extern IDirect3DVolumeTexture9Vtbl LockVolumeTexture9_vtable; +extern IDirect3DVolumeTexture9Vtbl LockVolumeTexture9_vtable; +extern ID3DAdapter9Vtbl LockAdapter9_vtable; + +void NineLockGlobalMutex(void); +void NineUnlockGlobalMutex(void); + +#endif /* _NINE_LOCK_H_ */ diff --git a/src/gallium/frontends/nine/nine_pdata.h b/src/gallium/frontends/nine/nine_pdata.h new file mode 100644 index 00000000000..8c73cd619ba --- /dev/null +++ b/src/gallium/frontends/nine/nine_pdata.h @@ -0,0 +1,46 @@ + +#ifndef _NINE_PDATA_H_ +#define _NINE_PDATA_H_ + +struct pheader +{ + boolean unknown; + GUID guid; + DWORD size; +}; + +static bool +ht_guid_compare( const void *a, + const void *b ) +{ + return GUID_equal(a, b); +} + +static uint32_t +ht_guid_hash( const void *key ) +{ + unsigned i, hash = 0; + const unsigned char *str = key; + + for (i = 0; i < sizeof(GUID); i++) { + hash = (unsigned)(str[i]) + (hash << 6) + (hash << 16) - hash; + } + + return hash; +} + +static enum pipe_error +ht_guid_delete( void *key, + void *value, + void *data ) +{ + struct pheader *header = value; + void *header_data = (void *)header + sizeof(*header); + + if (header->unknown) { IUnknown_Release(*(IUnknown **)header_data); } + FREE(header); + + return PIPE_OK; +} + +#endif /* _NINE_PDATA_H_ */ diff --git a/src/gallium/frontends/nine/nine_pipe.c b/src/gallium/frontends/nine/nine_pipe.c new file mode 100644 index 00000000000..cc63a9fce8f --- /dev/null +++ b/src/gallium/frontends/nine/nine_pipe.c @@ -0,0 +1,383 @@ +/* + * Copyright 2011 Joakim Sindholt + * Copyright 2013 Christoph Bumiller + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "device9.h" +#include "nine_pipe.h" + +#include "cso_cache/cso_context.h" + +void +nine_convert_dsa_state(struct pipe_depth_stencil_alpha_state *dsa_state, + const DWORD *rs) +{ + struct pipe_depth_stencil_alpha_state dsa; + + memset(&dsa, 0, sizeof(dsa)); /* memcmp safety */ + + if (rs[D3DRS_ZENABLE]) { + dsa.depth.enabled = 1; + dsa.depth.func = d3dcmpfunc_to_pipe_func(rs[D3DRS_ZFUNC]); + /* Disable depth write if no change can occur */ + dsa.depth.writemask = !!rs[D3DRS_ZWRITEENABLE] && + dsa.depth.func != PIPE_FUNC_EQUAL && + dsa.depth.func != PIPE_FUNC_NEVER; + } + + if (rs[D3DRS_STENCILENABLE]) { + dsa.stencil[0].enabled = 1; + dsa.stencil[0].func = d3dcmpfunc_to_pipe_func(rs[D3DRS_STENCILFUNC]); + dsa.stencil[0].fail_op = d3dstencilop_to_pipe_stencil_op(rs[D3DRS_STENCILFAIL]); + dsa.stencil[0].zpass_op = d3dstencilop_to_pipe_stencil_op(rs[D3DRS_STENCILPASS]); + dsa.stencil[0].zfail_op = d3dstencilop_to_pipe_stencil_op(rs[D3DRS_STENCILZFAIL]); + dsa.stencil[0].valuemask = rs[D3DRS_STENCILMASK]; + dsa.stencil[0].writemask = rs[D3DRS_STENCILWRITEMASK]; + + if (rs[D3DRS_TWOSIDEDSTENCILMODE]) { + dsa.stencil[1].enabled = 1; + dsa.stencil[1].func = d3dcmpfunc_to_pipe_func(rs[D3DRS_CCW_STENCILFUNC]); + dsa.stencil[1].fail_op = d3dstencilop_to_pipe_stencil_op(rs[D3DRS_CCW_STENCILFAIL]); + dsa.stencil[1].zpass_op = d3dstencilop_to_pipe_stencil_op(rs[D3DRS_CCW_STENCILPASS]); + dsa.stencil[1].zfail_op = d3dstencilop_to_pipe_stencil_op(rs[D3DRS_CCW_STENCILZFAIL]); + dsa.stencil[1].valuemask = dsa.stencil[0].valuemask; + dsa.stencil[1].writemask = dsa.stencil[0].writemask; + } + } + + if (rs[D3DRS_ALPHATESTENABLE]) { + dsa.alpha.enabled = 1; + dsa.alpha.func = d3dcmpfunc_to_pipe_func(rs[D3DRS_ALPHAFUNC]); + dsa.alpha.ref_value = (float)rs[D3DRS_ALPHAREF] / 255.0f; + } + + *dsa_state = dsa; +} + +void +nine_convert_rasterizer_state(struct NineDevice9 *device, + struct pipe_rasterizer_state *rast_state, + const DWORD *rs) +{ + struct pipe_rasterizer_state rast; + + memset(&rast, 0, sizeof(rast)); + + rast.flatshade = rs[D3DRS_SHADEMODE] == D3DSHADE_FLAT; + /* rast.light_twoside = 0; */ + /* rast.clamp_fragment_color = 0; */ + /* rast.clamp_vertex_color = 0; */ + /* rast.front_ccw = 0; */ + rast.cull_face = d3dcull_to_pipe_face(rs[D3DRS_CULLMODE]); + rast.fill_front = d3dfillmode_to_pipe_polygon_mode(rs[D3DRS_FILLMODE]); + rast.fill_back = rast.fill_front; + rast.offset_tri = !!(rs[D3DRS_DEPTHBIAS] | rs[D3DRS_SLOPESCALEDEPTHBIAS]); + rast.offset_line = rast.offset_tri; /* triangles in wireframe mode */ + rast.offset_point = 0; /* XXX ? */ + rast.scissor = !!rs[D3DRS_SCISSORTESTENABLE]; + /* rast.poly_smooth = 0; */ + /* rast.poly_stipple_enable = 0; */ + /* rast.point_smooth = 0; */ + rast.sprite_coord_mode = PIPE_SPRITE_COORD_UPPER_LEFT; + rast.point_quad_rasterization = 1; + rast.point_size_per_vertex = rs[NINED3DRS_VSPOINTSIZE]; + rast.multisample = rs[NINED3DRS_MULTISAMPLE]; + rast.line_smooth = !!rs[D3DRS_ANTIALIASEDLINEENABLE]; + /* rast.line_stipple_enable = 0; */ + rast.line_last_pixel = !!rs[D3DRS_LASTPIXEL]; + rast.flatshade_first = 1; + /* rast.half_pixel_center = 0; */ + /* rast.lower_left_origin = 0; */ + /* rast.bottom_edge_rule = 0; */ + /* rast.rasterizer_discard = 0; */ + rast.depth_clip_near = 1; + rast.depth_clip_far = 1; + rast.clip_halfz = 1; + rast.clip_plane_enable = rs[D3DRS_CLIPPLANEENABLE]; + /* rast.line_stipple_factor = 0; */ + /* rast.line_stipple_pattern = 0; */ + rast.sprite_coord_enable = rs[D3DRS_POINTSPRITEENABLE] ? 0xff : 0x00; + rast.line_width = 1.0f; + if (rs[NINED3DRS_VSPOINTSIZE]) { + rast.point_size = 1.0f; + } else { + rast.point_size = CLAMP(asfloat(rs[D3DRS_POINTSIZE]), + asfloat(rs[D3DRS_POINTSIZE_MIN]), + asfloat(rs[D3DRS_POINTSIZE_MAX])); + } + /* offset_units has the ogl/d3d11 meaning. + * d3d9: offset = scale * dz + bias + * ogl/d3d11: offset = scale * dz + r * bias + * with r implementation dependent (+ different formula for float depth + * buffers). r=2^-23 is often the right value for gallium drivers. + * If possible, use offset_units_unscaled, which gives the d3d9 + * behaviour, else scale by 1 << 23 */ + rast.offset_units = asfloat(rs[D3DRS_DEPTHBIAS]) * (device->driver_caps.offset_units_unscaled ? 1.0f : (float)(1 << 23)); + rast.offset_units_unscaled = device->driver_caps.offset_units_unscaled; + rast.offset_scale = asfloat(rs[D3DRS_SLOPESCALEDEPTHBIAS]); + /* rast.offset_clamp = 0.0f; */ + + *rast_state = rast; +} + +static inline void +nine_convert_blend_state_fixup(struct pipe_blend_state *blend, const DWORD *rs) +{ + if (unlikely(rs[D3DRS_SRCBLEND] == D3DBLEND_BOTHSRCALPHA || + rs[D3DRS_SRCBLEND] == D3DBLEND_BOTHINVSRCALPHA)) { + blend->rt[0].rgb_dst_factor = (rs[D3DRS_SRCBLEND] == D3DBLEND_BOTHSRCALPHA) ? + PIPE_BLENDFACTOR_INV_SRC_ALPHA : PIPE_BLENDFACTOR_SRC_ALPHA; + if (!rs[D3DRS_SEPARATEALPHABLENDENABLE]) + blend->rt[0].alpha_dst_factor = blend->rt[0].rgb_dst_factor; + } else + if (unlikely(rs[D3DRS_SEPARATEALPHABLENDENABLE] && + (rs[D3DRS_SRCBLENDALPHA] == D3DBLEND_BOTHSRCALPHA || + rs[D3DRS_SRCBLENDALPHA] == D3DBLEND_BOTHINVSRCALPHA))) { + blend->rt[0].alpha_dst_factor = (rs[D3DRS_SRCBLENDALPHA] == D3DBLEND_BOTHSRCALPHA) ? + PIPE_BLENDFACTOR_INV_SRC_ALPHA : PIPE_BLENDFACTOR_SRC_ALPHA; + } +} + +void +nine_convert_blend_state(struct pipe_blend_state *blend_state, const DWORD *rs) +{ + struct pipe_blend_state blend; + + memset(&blend, 0, sizeof(blend)); /* memcmp safety */ + + blend.dither = !!rs[D3DRS_DITHERENABLE]; + + /* blend.alpha_to_one = 0; */ + blend.alpha_to_coverage = rs[NINED3DRS_ALPHACOVERAGE] & 1; + + blend.rt[0].blend_enable = !!rs[D3DRS_ALPHABLENDENABLE]; + if (blend.rt[0].blend_enable) { + blend.rt[0].rgb_func = d3dblendop_to_pipe_blend(rs[D3DRS_BLENDOP]); + blend.rt[0].rgb_src_factor = d3dblend_color_to_pipe_blendfactor(rs[D3DRS_SRCBLEND]); + blend.rt[0].rgb_dst_factor = d3dblend_color_to_pipe_blendfactor(rs[D3DRS_DESTBLEND]); + if (rs[D3DRS_SEPARATEALPHABLENDENABLE]) { + blend.rt[0].alpha_func = d3dblendop_to_pipe_blend(rs[D3DRS_BLENDOPALPHA]); + blend.rt[0].alpha_src_factor = d3dblend_alpha_to_pipe_blendfactor(rs[D3DRS_SRCBLENDALPHA]); + blend.rt[0].alpha_dst_factor = d3dblend_alpha_to_pipe_blendfactor(rs[D3DRS_DESTBLENDALPHA]); + } else { + /* TODO: Just copy the rgb values ? SRC1_x may differ ... */ + blend.rt[0].alpha_func = blend.rt[0].rgb_func; + blend.rt[0].alpha_src_factor = d3dblend_alpha_to_pipe_blendfactor(rs[D3DRS_SRCBLEND]); + blend.rt[0].alpha_dst_factor = d3dblend_alpha_to_pipe_blendfactor(rs[D3DRS_DESTBLEND]); + } + nine_convert_blend_state_fixup(&blend, rs); /* for BOTH[INV]SRCALPHA */ + } + + blend.max_rt = 3; /* Upper bound. Could be optimized to fb->nr_cbufs for example */ + blend.rt[0].colormask = rs[D3DRS_COLORWRITEENABLE]; + + if (rs[D3DRS_COLORWRITEENABLE1] != rs[D3DRS_COLORWRITEENABLE] || + rs[D3DRS_COLORWRITEENABLE2] != rs[D3DRS_COLORWRITEENABLE] || + rs[D3DRS_COLORWRITEENABLE3] != rs[D3DRS_COLORWRITEENABLE]) { + unsigned i; + blend.independent_blend_enable = TRUE; + for (i = 1; i < 4; ++i) + blend.rt[i] = blend.rt[0]; + blend.rt[1].colormask = rs[D3DRS_COLORWRITEENABLE1]; + blend.rt[2].colormask = rs[D3DRS_COLORWRITEENABLE2]; + blend.rt[3].colormask = rs[D3DRS_COLORWRITEENABLE3]; + } + + /* blend.force_srgb = !!rs[D3DRS_SRGBWRITEENABLE]; */ + + *blend_state = blend; +} + +void +nine_convert_sampler_state(struct cso_context *ctx, int idx, const DWORD *ss) +{ + struct pipe_sampler_state samp; + + assert(idx >= 0 && + (idx < NINE_MAX_SAMPLERS_PS || idx >= NINE_SAMPLER_VS(0)) && + (idx < NINE_MAX_SAMPLERS)); + + memset(&samp, 0, sizeof(samp)); /* memcmp safety */ + + if (ss[D3DSAMP_MIPFILTER] != D3DTEXF_NONE) { + samp.lod_bias = asfloat(ss[D3DSAMP_MIPMAPLODBIAS]); + samp.min_lod = ss[NINED3DSAMP_MINLOD]; + samp.min_mip_filter = (ss[D3DSAMP_MIPFILTER] == D3DTEXF_POINT) ? PIPE_TEX_FILTER_NEAREST : PIPE_TEX_FILTER_LINEAR; + } else { + samp.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; + } + samp.max_lod = 15.0f; + + if (ss[NINED3DSAMP_CUBETEX]) { + /* Cube textures are always clamped to edge on D3D */ + samp.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + samp.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + samp.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + } else { + samp.wrap_s = d3dtextureaddress_to_pipe_tex_wrap(ss[D3DSAMP_ADDRESSU]); + samp.wrap_t = d3dtextureaddress_to_pipe_tex_wrap(ss[D3DSAMP_ADDRESSV]); + samp.wrap_r = d3dtextureaddress_to_pipe_tex_wrap(ss[D3DSAMP_ADDRESSW]); + } + samp.min_img_filter = (ss[D3DSAMP_MINFILTER] == D3DTEXF_POINT && !ss[NINED3DSAMP_SHADOW]) ? PIPE_TEX_FILTER_NEAREST : PIPE_TEX_FILTER_LINEAR; + samp.mag_img_filter = (ss[D3DSAMP_MAGFILTER] == D3DTEXF_POINT && !ss[NINED3DSAMP_SHADOW]) ? PIPE_TEX_FILTER_NEAREST : PIPE_TEX_FILTER_LINEAR; + if (ss[D3DSAMP_MINFILTER] == D3DTEXF_ANISOTROPIC || + ss[D3DSAMP_MAGFILTER] == D3DTEXF_ANISOTROPIC) + samp.max_anisotropy = ss[D3DSAMP_MAXANISOTROPY]; + samp.compare_mode = ss[NINED3DSAMP_SHADOW] ? PIPE_TEX_COMPARE_R_TO_TEXTURE : PIPE_TEX_COMPARE_NONE; + samp.compare_func = PIPE_FUNC_LEQUAL; + samp.normalized_coords = 1; + samp.seamless_cube_map = 0; + d3dcolor_to_pipe_color_union(&samp.border_color, ss[D3DSAMP_BORDERCOLOR]); + + /* see nine_state.h */ + if (idx < NINE_MAX_SAMPLERS_PS) + cso_single_sampler(ctx, PIPE_SHADER_FRAGMENT, idx - NINE_SAMPLER_PS(0), &samp); + else + cso_single_sampler(ctx, PIPE_SHADER_VERTEX, idx - NINE_SAMPLER_VS(0), &samp); +} + +const enum pipe_format nine_d3d9_to_pipe_format_map[120] = +{ + [D3DFMT_UNKNOWN] = PIPE_FORMAT_NONE, + [D3DFMT_R8G8B8] = PIPE_FORMAT_R8G8B8_UNORM, + [D3DFMT_A8R8G8B8] = PIPE_FORMAT_B8G8R8A8_UNORM, + [D3DFMT_X8R8G8B8] = PIPE_FORMAT_B8G8R8X8_UNORM, + [D3DFMT_R5G6B5] = PIPE_FORMAT_B5G6R5_UNORM, + [D3DFMT_X1R5G5B5] = PIPE_FORMAT_B5G5R5X1_UNORM, + [D3DFMT_A1R5G5B5] = PIPE_FORMAT_B5G5R5A1_UNORM, + [D3DFMT_A4R4G4B4] = PIPE_FORMAT_B4G4R4A4_UNORM, + [D3DFMT_R3G3B2] = PIPE_FORMAT_B2G3R3_UNORM, + [D3DFMT_A8] = PIPE_FORMAT_A8_UNORM, + [D3DFMT_A8R3G3B2] = PIPE_FORMAT_NONE, + [D3DFMT_X4R4G4B4] = PIPE_FORMAT_B4G4R4X4_UNORM, + [D3DFMT_A2B10G10R10] = PIPE_FORMAT_R10G10B10A2_UNORM, + [D3DFMT_A8B8G8R8] = PIPE_FORMAT_R8G8B8A8_UNORM, + [D3DFMT_X8B8G8R8] = PIPE_FORMAT_R8G8B8X8_UNORM, + [D3DFMT_G16R16] = PIPE_FORMAT_R16G16_UNORM, + [D3DFMT_A2R10G10B10] = PIPE_FORMAT_B10G10R10A2_UNORM, + [D3DFMT_A16B16G16R16] = PIPE_FORMAT_R16G16B16A16_UNORM, + [D3DFMT_A8P8] = PIPE_FORMAT_NONE, + [D3DFMT_P8] = PIPE_FORMAT_NONE, + [D3DFMT_L8] = PIPE_FORMAT_L8_UNORM, + [D3DFMT_A8L8] = PIPE_FORMAT_L8A8_UNORM, + [D3DFMT_A4L4] = PIPE_FORMAT_L4A4_UNORM, + [D3DFMT_V8U8] = PIPE_FORMAT_R8G8_SNORM, + [D3DFMT_L6V5U5] = PIPE_FORMAT_NONE, /* Should be PIPE_FORMAT_R5SG5SB6U_NORM, but interpretation of the data differs a bit. */ + [D3DFMT_X8L8V8U8] = PIPE_FORMAT_R8SG8SB8UX8U_NORM, + [D3DFMT_Q8W8V8U8] = PIPE_FORMAT_R8G8B8A8_SNORM, + [D3DFMT_V16U16] = PIPE_FORMAT_R16G16_SNORM, + [D3DFMT_A2W10V10U10] = PIPE_FORMAT_R10SG10SB10SA2U_NORM, + [D3DFMT_D16_LOCKABLE] = PIPE_FORMAT_Z16_UNORM, + [D3DFMT_D32] = PIPE_FORMAT_Z32_UNORM, + [D3DFMT_D15S1] = PIPE_FORMAT_NONE, + [D3DFMT_D24S8] = PIPE_FORMAT_S8_UINT_Z24_UNORM, + [D3DFMT_D24X8] = PIPE_FORMAT_X8Z24_UNORM, + [D3DFMT_D24X4S4] = PIPE_FORMAT_NONE, + [D3DFMT_D16] = PIPE_FORMAT_Z16_UNORM, + [D3DFMT_D32F_LOCKABLE] = PIPE_FORMAT_Z32_FLOAT, + [D3DFMT_D24FS8] = PIPE_FORMAT_Z32_FLOAT_S8X24_UINT, + [D3DFMT_D32_LOCKABLE] = PIPE_FORMAT_NONE, + [D3DFMT_S8_LOCKABLE] = PIPE_FORMAT_NONE, + [D3DFMT_L16] = PIPE_FORMAT_L16_UNORM, + [D3DFMT_VERTEXDATA] = PIPE_FORMAT_NONE, + [D3DFMT_INDEX16] = PIPE_FORMAT_R16_UINT, + [D3DFMT_INDEX32] = PIPE_FORMAT_R32_UINT, + [D3DFMT_Q16W16V16U16] = PIPE_FORMAT_R16G16B16A16_SNORM, + [D3DFMT_R16F] = PIPE_FORMAT_R16_FLOAT, + [D3DFMT_G16R16F] = PIPE_FORMAT_R16G16_FLOAT, + [D3DFMT_A16B16G16R16F] = PIPE_FORMAT_R16G16B16A16_FLOAT, + [D3DFMT_R32F] = PIPE_FORMAT_R32_FLOAT, + [D3DFMT_G32R32F] = PIPE_FORMAT_R32G32_FLOAT, + [D3DFMT_A32B32G32R32F] = PIPE_FORMAT_R32G32B32A32_FLOAT, + [D3DFMT_CxV8U8] = PIPE_FORMAT_NONE, + [D3DFMT_A1] = PIPE_FORMAT_NONE, + [D3DFMT_A2B10G10R10_XR_BIAS] = PIPE_FORMAT_NONE, +}; + +const D3DFORMAT nine_pipe_to_d3d9_format_map[PIPE_FORMAT_COUNT] = +{ + [PIPE_FORMAT_NONE] = D3DFMT_UNKNOWN, + /* TODO: rename PIPE_FORMAT_R8G8B8_UNORM to PIPE_FORMAT_B8G8R8_UNORM */ + [PIPE_FORMAT_R8G8B8_UNORM] = D3DFMT_R8G8B8, + [PIPE_FORMAT_B8G8R8A8_UNORM] = D3DFMT_A8R8G8B8, + [PIPE_FORMAT_B8G8R8X8_UNORM] = D3DFMT_X8R8G8B8, + [PIPE_FORMAT_B5G6R5_UNORM] = D3DFMT_R5G6B5, + [PIPE_FORMAT_B5G5R5X1_UNORM] = D3DFMT_X1R5G5B5, + [PIPE_FORMAT_B5G5R5A1_UNORM] = D3DFMT_A1R5G5B5, + [PIPE_FORMAT_B4G4R4A4_UNORM] = D3DFMT_A4R4G4B4, + [PIPE_FORMAT_B2G3R3_UNORM] = D3DFMT_R3G3B2, + [PIPE_FORMAT_A8_UNORM] = D3DFMT_A8, +/* [PIPE_FORMAT_B2G3R3A8_UNORM] = D3DFMT_A8R3G3B2, */ + [PIPE_FORMAT_B4G4R4X4_UNORM] = D3DFMT_X4R4G4B4, + [PIPE_FORMAT_R10G10B10A2_UNORM] = D3DFMT_A2B10G10R10, + [PIPE_FORMAT_R8G8B8A8_UNORM] = D3DFMT_A8B8G8R8, + [PIPE_FORMAT_R8G8B8X8_UNORM] = D3DFMT_X8B8G8R8, + [PIPE_FORMAT_R16G16_UNORM] = D3DFMT_G16R16, + [PIPE_FORMAT_B10G10R10A2_UNORM] = D3DFMT_A2R10G10B10, + [PIPE_FORMAT_R16G16B16A16_UNORM] = D3DFMT_A16B16G16R16, + + [PIPE_FORMAT_R8_UINT] = D3DFMT_P8, + [PIPE_FORMAT_R8A8_UINT] = D3DFMT_A8P8, + + [PIPE_FORMAT_L8_UNORM] = D3DFMT_L8, + [PIPE_FORMAT_L8A8_UNORM] = D3DFMT_A8L8, + [PIPE_FORMAT_L4A4_UNORM] = D3DFMT_A4L4, + + [PIPE_FORMAT_R8G8_SNORM] = D3DFMT_V8U8, +/* [PIPE_FORMAT_?] = D3DFMT_L6V5U5, */ +/* [PIPE_FORMAT_?] = D3DFMT_X8L8V8U8, */ + [PIPE_FORMAT_R8G8B8A8_SNORM] = D3DFMT_Q8W8V8U8, + [PIPE_FORMAT_R16G16_SNORM] = D3DFMT_V16U16, + [PIPE_FORMAT_R10SG10SB10SA2U_NORM] = D3DFMT_A2W10V10U10, + + [PIPE_FORMAT_YUYV] = D3DFMT_UYVY, +/* [PIPE_FORMAT_YUY2] = D3DFMT_YUY2, */ + [PIPE_FORMAT_DXT1_RGBA] = D3DFMT_DXT1, +/* [PIPE_FORMAT_DXT2_RGBA] = D3DFMT_DXT2, */ + [PIPE_FORMAT_DXT3_RGBA] = D3DFMT_DXT3, +/* [PIPE_FORMAT_DXT4_RGBA] = D3DFMT_DXT4, */ + [PIPE_FORMAT_DXT5_RGBA] = D3DFMT_DXT5, +/* [PIPE_FORMAT_?] = D3DFMT_MULTI2_ARGB8, (MET) */ + [PIPE_FORMAT_R8G8_B8G8_UNORM] = D3DFMT_R8G8_B8G8, /* XXX: order */ + [PIPE_FORMAT_G8R8_G8B8_UNORM] = D3DFMT_G8R8_G8B8, + + [PIPE_FORMAT_Z16_UNORM] = D3DFMT_D16_LOCKABLE, + [PIPE_FORMAT_Z32_UNORM] = D3DFMT_D32, +/* [PIPE_FORMAT_Z15_UNORM_S1_UINT] = D3DFMT_D15S1, */ + [PIPE_FORMAT_S8_UINT_Z24_UNORM] = D3DFMT_D24S8, + [PIPE_FORMAT_X8Z24_UNORM] = D3DFMT_D24X8, + [PIPE_FORMAT_L16_UNORM] = D3DFMT_L16, + [PIPE_FORMAT_Z32_FLOAT] = D3DFMT_D32F_LOCKABLE, +/* [PIPE_FORMAT_Z24_FLOAT_S8_UINT] = D3DFMT_D24FS8, */ + + [PIPE_FORMAT_R16_UINT] = D3DFMT_INDEX16, + [PIPE_FORMAT_R32_UINT] = D3DFMT_INDEX32, + [PIPE_FORMAT_R16G16B16A16_SNORM] = D3DFMT_Q16W16V16U16, + + [PIPE_FORMAT_R16_FLOAT] = D3DFMT_R16F, + [PIPE_FORMAT_R32_FLOAT] = D3DFMT_R32F, + [PIPE_FORMAT_R16G16_FLOAT] = D3DFMT_G16R16F, + [PIPE_FORMAT_R32G32_FLOAT] = D3DFMT_G32R32F, + [PIPE_FORMAT_R16G16B16A16_FLOAT] = D3DFMT_A16B16G16R16F, + [PIPE_FORMAT_R32G32B32A32_FLOAT] = D3DFMT_A32B32G32R32F, + +/* [PIPE_FORMAT_?] = D3DFMT_CxV8U8, */ +}; diff --git a/src/gallium/frontends/nine/nine_pipe.h b/src/gallium/frontends/nine/nine_pipe.h new file mode 100644 index 00000000000..6a85c042db7 --- /dev/null +++ b/src/gallium/frontends/nine/nine_pipe.h @@ -0,0 +1,827 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _NINE_PIPE_H_ +#define _NINE_PIPE_H_ + +#include "d3d9.h" +#include "pipe/p_format.h" +#include "pipe/p_screen.h" +#include "pipe/p_state.h" /* pipe_box */ +#include "util/macros.h" +#include "util/u_rect.h" +#include "util/format/u_format.h" +#include "nine_helpers.h" + +struct cso_context; + +extern const enum pipe_format nine_d3d9_to_pipe_format_map[120]; +extern const D3DFORMAT nine_pipe_to_d3d9_format_map[PIPE_FORMAT_COUNT]; + +void nine_convert_dsa_state(struct pipe_depth_stencil_alpha_state *, const DWORD *); +void nine_convert_rasterizer_state(struct NineDevice9 *, struct pipe_rasterizer_state *, const DWORD *); +void nine_convert_blend_state(struct pipe_blend_state *, const DWORD *); +void nine_convert_sampler_state(struct cso_context *, int idx, const DWORD *); + +#define is_ATI1_ATI2(format) (format == PIPE_FORMAT_RGTC1_UNORM || format == PIPE_FORMAT_RGTC2_UNORM) + +static inline void +rect_to_pipe_box(struct pipe_box *dst, const RECT *src) +{ + dst->x = src->left; + dst->y = src->top; + dst->z = 0; + dst->width = src->right - src->left; + dst->height = src->bottom - src->top; + dst->depth = 1; +} + +static inline void +pipe_box_to_rect(RECT *dst, const struct pipe_box *src) +{ + dst->left = src->x; + dst->right = src->x + src->width; + dst->top = src->y; + dst->bottom = src->y + src->height; +} + +static inline void +rect_minify_inclusive(RECT *rect) +{ + rect->left = rect->left >> 2; + rect->top = rect->top >> 2; + rect->right = DIV_ROUND_UP(rect->right, 2); + rect->bottom = DIV_ROUND_UP(rect->bottom, 2); +} + +/* We suppose: + * 0 <= rect->left < rect->right + * 0 <= rect->top < rect->bottom + */ +static inline void +fit_rect_format_inclusive(enum pipe_format format, RECT *rect, int width, int height) +{ + const unsigned w = util_format_get_blockwidth(format); + const unsigned h = util_format_get_blockheight(format); + + if (util_format_is_compressed(format)) { + rect->left = rect->left - rect->left % w; + rect->top = rect->top - rect->top % h; + rect->right = (rect->right % w) == 0 ? + rect->right : + rect->right - (rect->right % w) + w; + rect->bottom = (rect->bottom % h) == 0 ? + rect->bottom : + rect->bottom - (rect->bottom % h) + h; + } + + rect->right = MIN2(rect->right, width); + rect->bottom = MIN2(rect->bottom, height); +} + +static inline boolean +rect_to_pipe_box_clamp(struct pipe_box *dst, const RECT *src) +{ + rect_to_pipe_box(dst, src); + + if (dst->width <= 0 || dst->height <= 0) { + DBG_FLAG(DBG_UNKNOWN, "Warning: NULL box"); + dst->width = MAX2(dst->width, 0); + dst->height = MAX2(dst->height, 0); + return TRUE; + } + return FALSE; +} + +static inline boolean +rect_to_pipe_box_flip(struct pipe_box *dst, const RECT *src) +{ + rect_to_pipe_box(dst, src); + + if (dst->width >= 0 && dst->height >= 0) + return FALSE; + if (dst->width < 0) dst->width = -dst->width; + if (dst->height < 0) dst->height = -dst->height; + return TRUE; +} + +static inline void +rect_to_pipe_box_xy_only(struct pipe_box *dst, const RECT *src) +{ + user_warn(src->left > src->right || src->top > src->bottom); + + dst->x = src->left; + dst->y = src->top; + dst->width = src->right - src->left; + dst->height = src->bottom - src->top; +} + +static inline boolean +rect_to_pipe_box_xy_only_clamp(struct pipe_box *dst, const RECT *src) +{ + rect_to_pipe_box_xy_only(dst, src); + + if (dst->width <= 0 || dst->height <= 0) { + DBG_FLAG(DBG_UNKNOWN, "Warning: NULL box"); + dst->width = MAX2(dst->width, 0); + dst->height = MAX2(dst->height, 0); + return TRUE; + } + return FALSE; +} + +static inline void +rect_to_g3d_u_rect(struct u_rect *dst, const RECT *src) +{ + user_warn(src->left > src->right || src->top > src->bottom); + + dst->x0 = src->left; + dst->x1 = src->right; + dst->y0 = src->top; + dst->y1 = src->bottom; +} + +static inline void +d3dbox_to_pipe_box(struct pipe_box *dst, const D3DBOX *src) +{ + user_warn(src->Left > src->Right); + user_warn(src->Top > src->Bottom); + user_warn(src->Front > src->Back); + + dst->x = src->Left; + dst->y = src->Top; + dst->z = src->Front; + dst->width = src->Right - src->Left; + dst->height = src->Bottom - src->Top; + dst->depth = src->Back - src->Front; +} + +static inline D3DFORMAT +pipe_to_d3d9_format(enum pipe_format format) +{ + return nine_pipe_to_d3d9_format_map[format]; +} + +/* ATI1 and ATI2 are not officially compressed in d3d9 */ +static inline boolean +compressed_format( D3DFORMAT fmt ) +{ + switch (fmt) { + case D3DFMT_DXT1: + case D3DFMT_DXT2: + case D3DFMT_DXT3: + case D3DFMT_DXT4: + case D3DFMT_DXT5: + return TRUE; + default: + break; + } + return FALSE; +} + +static inline boolean +depth_stencil_format( D3DFORMAT fmt ) +{ + static const D3DFORMAT allowed[] = { + D3DFMT_D16_LOCKABLE, + D3DFMT_D32, + D3DFMT_D15S1, + D3DFMT_D24S8, + D3DFMT_D24X8, + D3DFMT_D24X4S4, + D3DFMT_D16, + D3DFMT_D32F_LOCKABLE, + D3DFMT_D24FS8, + D3DFMT_D32_LOCKABLE, + D3DFMT_DF16, + D3DFMT_DF24, + D3DFMT_INTZ + }; + unsigned i; + + for (i = 0; i < sizeof(allowed)/sizeof(D3DFORMAT); i++) { + if (fmt == allowed[i]) { return TRUE; } + } + return FALSE; +} + +static inline unsigned +d3d9_get_pipe_depth_format_bindings(D3DFORMAT format) +{ + switch (format) { + case D3DFMT_D32: + case D3DFMT_D15S1: + case D3DFMT_D24S8: + case D3DFMT_D24X8: + case D3DFMT_D24X4S4: + case D3DFMT_D16: + case D3DFMT_D24FS8: + return PIPE_BIND_DEPTH_STENCIL; + case D3DFMT_D32F_LOCKABLE: + case D3DFMT_D16_LOCKABLE: + case D3DFMT_D32_LOCKABLE: + return PIPE_BIND_DEPTH_STENCIL; + case D3DFMT_DF16: + case D3DFMT_DF24: + case D3DFMT_INTZ: + return PIPE_BIND_DEPTH_STENCIL | PIPE_BIND_SAMPLER_VIEW; + default: unreachable("Unexpected format"); + } +} + +static inline enum pipe_format +d3d9_to_pipe_format_internal(D3DFORMAT format) +{ + if (format <= D3DFMT_A2B10G10R10_XR_BIAS) + return nine_d3d9_to_pipe_format_map[format]; + switch (format) { + case D3DFMT_INTZ: return PIPE_FORMAT_S8_UINT_Z24_UNORM; + case D3DFMT_DF16: return PIPE_FORMAT_Z16_UNORM; + case D3DFMT_DXT1: return PIPE_FORMAT_DXT1_RGBA; + case D3DFMT_DXT2: return PIPE_FORMAT_DXT3_RGBA; /* XXX */ + case D3DFMT_DXT3: return PIPE_FORMAT_DXT3_RGBA; + case D3DFMT_DXT4: return PIPE_FORMAT_DXT5_RGBA; /* XXX */ + case D3DFMT_DXT5: return PIPE_FORMAT_DXT5_RGBA; + case D3DFMT_ATI1: return PIPE_FORMAT_RGTC1_UNORM; + case D3DFMT_ATI2: return PIPE_FORMAT_RGTC2_UNORM; + case D3DFMT_UYVY: return PIPE_FORMAT_UYVY; + case D3DFMT_YUY2: return PIPE_FORMAT_YUYV; /* XXX check */ + case D3DFMT_NV12: return PIPE_FORMAT_NV12; + case D3DFMT_G8R8_G8B8: return PIPE_FORMAT_G8R8_G8B8_UNORM; /* XXX order ? */ + case D3DFMT_R8G8_B8G8: return PIPE_FORMAT_R8G8_B8G8_UNORM; /* XXX order ? */ + case D3DFMT_BINARYBUFFER: return PIPE_FORMAT_NONE; /* not a format */ + case D3DFMT_MULTI2_ARGB8: return PIPE_FORMAT_NONE; /* not supported */ + case D3DFMT_Y210: /* XXX */ + case D3DFMT_Y216: + case D3DFMT_NV11: + case D3DFMT_DF24: /* Similar to D3DFMT_DF16 but for 24-bits. + We don't advertise it because when it is supported, Fetch-4 is + supposed to be supported, which we don't support yet. */ + case D3DFMT_NULL: /* special cased, only for surfaces */ + return PIPE_FORMAT_NONE; + default: + DBG_FLAG(DBG_UNKNOWN, "unknown D3DFORMAT: 0x%x/%c%c%c%c\n", + format, (char)format, (char)(format >> 8), + (char)(format >> 16), (char)(format >> 24)); + return PIPE_FORMAT_NONE; + } +} + +#define format_check_internal(pipe_format) \ + screen->is_format_supported(screen, pipe_format, target, \ + sample_count, sample_count, bindings) + +static inline enum pipe_format +d3d9_to_pipe_format_checked(struct pipe_screen *screen, + D3DFORMAT format, + enum pipe_texture_target target, + unsigned sample_count, + unsigned bindings, + boolean srgb, + boolean bypass_check) +{ + enum pipe_format result; + + result = d3d9_to_pipe_format_internal(format); + if (result == PIPE_FORMAT_NONE) + return PIPE_FORMAT_NONE; + + if (srgb) + result = util_format_srgb(result); + + /* bypass_check: Used for D3DPOOL_SCRATCH, which + * isn't limited to the formats supported by the + * device, and to check we are not using a format + * fallback. */ + if (bypass_check || format_check_internal(result)) + return result; + + /* fallback to another format for formats + * that match several pipe_format */ + switch(format) { + /* depth buffer formats are not lockable (except those for which it + * is precised in the name), so it is ok to match to another similar + * format. In all cases, if the app reads the texture with a shader, + * it gets depth on r and doesn't get stencil.*/ + case D3DFMT_INTZ: + case D3DFMT_D24S8: + if (format_check_internal(PIPE_FORMAT_Z24_UNORM_S8_UINT)) + return PIPE_FORMAT_Z24_UNORM_S8_UINT; + break; + case D3DFMT_D24X8: + if (format_check_internal(PIPE_FORMAT_Z24X8_UNORM)) + return PIPE_FORMAT_Z24X8_UNORM; + break; + /* Support for X8L8V8U8 bumpenvmap format with lighting bits. + * X8L8V8U8 is commonly supported among dx9 cards. + * To avoid precision loss, we use PIPE_FORMAT_R32G32B32X32_FLOAT, + * however using PIPE_FORMAT_R8G8B8A8_SNORM should be ok */ + case D3DFMT_X8L8V8U8: + if (bindings & PIPE_BIND_RENDER_TARGET) + return PIPE_FORMAT_NONE; + if (format_check_internal(PIPE_FORMAT_R32G32B32X32_FLOAT)) + return PIPE_FORMAT_R32G32B32X32_FLOAT; + default: + break; + } + return PIPE_FORMAT_NONE; +} + +/* The quality levels are vendor dependent, so we set our own. + * Every quality level has its own sample count and sample + * position matrix. + * The exact mapping might differ from system to system but thats OK, + * as there's no way to gather more information about quality levels + * in D3D9. + * In case of NONMASKABLE multisample map every quality-level + * to a MASKABLE MultiSampleType: + * 0: no MSAA + * 1: 2x MSAA + * 2: 4x MSAA + * ... + * If the requested quality level is not available to nearest + * matching quality level is used. + * If no multisample is available the function sets + * multisample to D3DMULTISAMPLE_NONE and returns zero. + */ +static inline HRESULT +d3dmultisample_type_check(struct pipe_screen *screen, + D3DFORMAT format, + D3DMULTISAMPLE_TYPE *multisample, + DWORD multisamplequality, + DWORD *levels) +{ + unsigned bind, i; + + assert(multisample); + + if (levels) + *levels = 1; + + /* Ignores multisamplequality */ + if (*multisample == D3DMULTISAMPLE_NONE) + return D3D_OK; + + if (*multisample == D3DMULTISAMPLE_NONMASKABLE) { + if (depth_stencil_format(format)) + bind = d3d9_get_pipe_depth_format_bindings(format); + else /* render-target */ + bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; + + *multisample = 0; + for (i = D3DMULTISAMPLE_2_SAMPLES; i < D3DMULTISAMPLE_16_SAMPLES && + multisamplequality; ++i) { + if (d3d9_to_pipe_format_checked(screen, format, PIPE_TEXTURE_2D, + i, bind, FALSE, FALSE) != PIPE_FORMAT_NONE) { + multisamplequality--; + if (levels) + (*levels)++; + *multisample = i; + } + } + } + /* Make sure to get an exact match */ + if (multisamplequality) + return D3DERR_INVALIDCALL; + return D3D_OK; +} + +static inline const char * +d3dformat_to_string(D3DFORMAT fmt) +{ + switch (fmt) { + case D3DFMT_UNKNOWN: return "D3DFMT_UNKNOWN"; + case D3DFMT_R8G8B8: return "D3DFMT_R8G8B8"; + case D3DFMT_A8R8G8B8: return "D3DFMT_A8R8G8B8"; + case D3DFMT_X8R8G8B8: return "D3DFMT_X8R8G8B8"; + case D3DFMT_R5G6B5: return "D3DFMT_R5G6B5"; + case D3DFMT_X1R5G5B5: return "D3DFMT_X1R5G5B5"; + case D3DFMT_A1R5G5B5: return "D3DFMT_A1R5G5B5"; + case D3DFMT_A4R4G4B4: return "D3DFMT_A4R4G4B4"; + case D3DFMT_R3G3B2: return "D3DFMT_R3G3B2"; + case D3DFMT_A8: return "D3DFMT_A8"; + case D3DFMT_A8R3G3B2: return "D3DFMT_A8R3G3B2"; + case D3DFMT_X4R4G4B4: return "D3DFMT_X4R4G4B4"; + case D3DFMT_A2B10G10R10: return "D3DFMT_A2B10G10R10"; + case D3DFMT_A8B8G8R8: return "D3DFMT_A8B8G8R8"; + case D3DFMT_X8B8G8R8: return "D3DFMT_X8B8G8R8"; + case D3DFMT_G16R16: return "D3DFMT_G16R16"; + case D3DFMT_A2R10G10B10: return "D3DFMT_A2R10G10B10"; + case D3DFMT_A16B16G16R16: return "D3DFMT_A16B16G16R16"; + case D3DFMT_A8P8: return "D3DFMT_A8P8"; + case D3DFMT_P8: return "D3DFMT_P8"; + case D3DFMT_L8: return "D3DFMT_L8"; + case D3DFMT_A8L8: return "D3DFMT_A8L8"; + case D3DFMT_A4L4: return "D3DFMT_A4L4"; + case D3DFMT_V8U8: return "D3DFMT_V8U8"; + case D3DFMT_L6V5U5: return "D3DFMT_L6V5U5"; + case D3DFMT_X8L8V8U8: return "D3DFMT_X8L8V8U8"; + case D3DFMT_Q8W8V8U8: return "D3DFMT_Q8W8V8U8"; + case D3DFMT_V16U16: return "D3DFMT_V16U16"; + case D3DFMT_A2W10V10U10: return "D3DFMT_A2W10V10U10"; + case D3DFMT_UYVY: return "D3DFMT_UYVY"; + case D3DFMT_R8G8_B8G8: return "D3DFMT_R8G8_B8G8"; + case D3DFMT_YUY2: return "D3DFMT_YUY2"; + case D3DFMT_G8R8_G8B8: return "D3DFMT_G8R8_G8B8"; + case D3DFMT_DXT1: return "D3DFMT_DXT1"; + case D3DFMT_DXT2: return "D3DFMT_DXT2"; + case D3DFMT_DXT3: return "D3DFMT_DXT3"; + case D3DFMT_DXT4: return "D3DFMT_DXT4"; + case D3DFMT_DXT5: return "D3DFMT_DXT5"; + case D3DFMT_ATI1: return "D3DFMT_ATI1"; + case D3DFMT_ATI2: return "D3DFMT_ATI2"; + case D3DFMT_D16_LOCKABLE: return "D3DFMT_D16_LOCKABLE"; + case D3DFMT_D32: return "D3DFMT_D32"; + case D3DFMT_D15S1: return "D3DFMT_D15S1"; + case D3DFMT_D24S8: return "D3DFMT_D24S8"; + case D3DFMT_D24X8: return "D3DFMT_D24X8"; + case D3DFMT_D24X4S4: return "D3DFMT_D24X4S4"; + case D3DFMT_D16: return "D3DFMT_D16"; + case D3DFMT_D32F_LOCKABLE: return "D3DFMT_D32F_LOCKABLE"; + case D3DFMT_D24FS8: return "D3DFMT_D24FS8"; + case D3DFMT_D32_LOCKABLE: return "D3DFMT_D32_LOCKABLE"; + case D3DFMT_S8_LOCKABLE: return "D3DFMT_S8_LOCKABLE"; + case D3DFMT_L16: return "D3DFMT_L16"; + case D3DFMT_VERTEXDATA: return "D3DFMT_VERTEXDATA"; + case D3DFMT_INDEX16: return "D3DFMT_INDEX16"; + case D3DFMT_INDEX32: return "D3DFMT_INDEX32"; + case D3DFMT_Q16W16V16U16: return "D3DFMT_Q16W16V16U16"; + case D3DFMT_MULTI2_ARGB8: return "D3DFMT_MULTI2_ARGB8"; + case D3DFMT_R16F: return "D3DFMT_R16F"; + case D3DFMT_G16R16F: return "D3DFMT_G16R16F"; + case D3DFMT_A16B16G16R16F: return "D3DFMT_A16B16G16R16F"; + case D3DFMT_R32F: return "D3DFMT_R32F"; + case D3DFMT_G32R32F: return "D3DFMT_G32R32F"; + case D3DFMT_A32B32G32R32F: return "D3DFMT_A32B32G32R32F"; + case D3DFMT_CxV8U8: return "D3DFMT_CxV8U8"; + case D3DFMT_A1: return "D3DFMT_A1"; + case D3DFMT_A2B10G10R10_XR_BIAS: return "D3DFMT_A2B10G10R10_XR_BIAS"; + case D3DFMT_BINARYBUFFER: return "D3DFMT_BINARYBUFFER"; + case D3DFMT_DF16: return "D3DFMT_DF16"; + case D3DFMT_DF24: return "D3DFMT_DF24"; + case D3DFMT_INTZ: return "D3DFMT_INTZ"; + case D3DFMT_NVDB: return "D3DFMT_NVDB"; + case D3DFMT_RESZ: return "D3DFMT_RESZ"; + case D3DFMT_NULL: return "D3DFMT_NULL"; + case D3DFMT_ATOC: return "D3DFMT_ATOC"; + default: + break; + } + return "Unknown"; +} + +static inline unsigned +nine_fvf_stride( DWORD fvf ) +{ + unsigned texcount, i, size = 0; + + switch (fvf & D3DFVF_POSITION_MASK) { + case D3DFVF_XYZ: size += 3*4; break; + case D3DFVF_XYZRHW: size += 4*4; break; + case D3DFVF_XYZB1: size += 4*4; break; + case D3DFVF_XYZB2: size += 5*4; break; + case D3DFVF_XYZB3: size += 6*4; break; + case D3DFVF_XYZB4: size += 7*4; break; + case D3DFVF_XYZB5: size += 8*4; break; + case D3DFVF_XYZW: size += 4*4; break; + default: + user_warn("Position doesn't match any known combination."); + break; + } + + if (fvf & D3DFVF_NORMAL) { size += 3*4; } + if (fvf & D3DFVF_PSIZE) { size += 1*4; } + if (fvf & D3DFVF_DIFFUSE) { size += 1*4; } + if (fvf & D3DFVF_SPECULAR) { size += 1*4; } + + texcount = (fvf >> D3DFVF_TEXCOUNT_SHIFT) & D3DFVF_TEXCOUNT_MASK; + if (user_error(texcount <= 8)) + texcount = 8; + + for (i = 0; i < texcount; ++i) { + unsigned texformat = (fvf>>(16+i*2))&0x3; + /* texformats are defined having been shifted around so 1=3,2=0,3=1,4=2 + * meaning we can just do this instead of the switch below */ + size += (((texformat+1)&0x3)+1)*4; + + /* + switch (texformat) { + case D3DFVF_TEXTUREFORMAT1: size += 1*4; + case D3DFVF_TEXTUREFORMAT2: size += 2*4; + case D3DFVF_TEXTUREFORMAT3: size += 3*4; + case D3DFVF_TEXTUREFORMAT4: size += 4*4; + } + */ + } + + return size; +} + +static inline void +d3dcolor_to_rgba(float *rgba, D3DCOLOR color) +{ + rgba[0] = (float)((color >> 16) & 0xFF) / 0xFF; + rgba[1] = (float)((color >> 8) & 0xFF) / 0xFF; + rgba[2] = (float)((color >> 0) & 0xFF) / 0xFF; + rgba[3] = (float)((color >> 24) & 0xFF) / 0xFF; +} + +static inline void +d3dcolor_to_pipe_color_union(union pipe_color_union *rgba, D3DCOLOR color) +{ + d3dcolor_to_rgba(&rgba->f[0], color); +} + +static inline unsigned +d3dprimitivetype_to_pipe_prim(D3DPRIMITIVETYPE prim) +{ + switch (prim) { + case D3DPT_POINTLIST: return PIPE_PRIM_POINTS; + case D3DPT_LINELIST: return PIPE_PRIM_LINES; + case D3DPT_LINESTRIP: return PIPE_PRIM_LINE_STRIP; + case D3DPT_TRIANGLELIST: return PIPE_PRIM_TRIANGLES; + case D3DPT_TRIANGLESTRIP: return PIPE_PRIM_TRIANGLE_STRIP; + case D3DPT_TRIANGLEFAN: return PIPE_PRIM_TRIANGLE_FAN; + default: + assert(0); + return PIPE_PRIM_POINTS; + } +} + +static inline unsigned +prim_count_to_vertex_count(D3DPRIMITIVETYPE prim, UINT count) +{ + switch (prim) { + case D3DPT_POINTLIST: return count; + case D3DPT_LINELIST: return count * 2; + case D3DPT_LINESTRIP: return count + 1; + case D3DPT_TRIANGLELIST: return count * 3; + case D3DPT_TRIANGLESTRIP: return count + 2; + case D3DPT_TRIANGLEFAN: return count + 2; + default: + assert(0); + return 0; + } +} + +static inline unsigned +d3dcmpfunc_to_pipe_func(D3DCMPFUNC func) +{ + switch (func) { + case D3DCMP_NEVER: return PIPE_FUNC_NEVER; + case D3DCMP_LESS: return PIPE_FUNC_LESS; + case D3DCMP_EQUAL: return PIPE_FUNC_EQUAL; + case D3DCMP_LESSEQUAL: return PIPE_FUNC_LEQUAL; + case D3DCMP_GREATER: return PIPE_FUNC_GREATER; + case D3DCMP_NOTEQUAL: return PIPE_FUNC_NOTEQUAL; + case D3DCMP_GREATEREQUAL: return PIPE_FUNC_GEQUAL; + case D3DCMP_ALWAYS: return PIPE_FUNC_ALWAYS; + case D3DCMP_NEVER_ZERO: return PIPE_FUNC_NEVER; // Tested on windows + ATI HD5770 + default: + assert(0); + return PIPE_FUNC_NEVER; + } +} + +static inline unsigned +d3dstencilop_to_pipe_stencil_op(D3DSTENCILOP op) +{ + switch (op) { + case D3DSTENCILOP_KEEP: return PIPE_STENCIL_OP_KEEP; + case D3DSTENCILOP_ZERO: return PIPE_STENCIL_OP_ZERO; + case D3DSTENCILOP_REPLACE: return PIPE_STENCIL_OP_REPLACE; + case D3DSTENCILOP_INCRSAT: return PIPE_STENCIL_OP_INCR; + case D3DSTENCILOP_DECRSAT: return PIPE_STENCIL_OP_DECR; + case D3DSTENCILOP_INVERT: return PIPE_STENCIL_OP_INVERT; + case D3DSTENCILOP_INCR: return PIPE_STENCIL_OP_INCR_WRAP; + case D3DSTENCILOP_DECR: return PIPE_STENCIL_OP_DECR_WRAP; + default: + return PIPE_STENCIL_OP_ZERO; + } +} + +static inline unsigned +d3dcull_to_pipe_face(D3DCULL cull) +{ + switch (cull) { + case D3DCULL_NONE: return PIPE_FACE_NONE; + case D3DCULL_CW: return PIPE_FACE_FRONT; + case D3DCULL_CCW: return PIPE_FACE_BACK; + default: + assert(0); + return PIPE_FACE_NONE; + } +} + +static inline unsigned +d3dfillmode_to_pipe_polygon_mode(D3DFILLMODE mode) +{ + switch (mode) { + case D3DFILL_POINT: return PIPE_POLYGON_MODE_POINT; + case D3DFILL_WIREFRAME: return PIPE_POLYGON_MODE_LINE; + case D3DFILL_SOLID: return PIPE_POLYGON_MODE_FILL; + case D3DFILL_SOLID_ZERO:return PIPE_POLYGON_MODE_FILL; + default: + assert(0); + return PIPE_POLYGON_MODE_FILL; + } +} + +static inline unsigned +d3dblendop_to_pipe_blend(D3DBLENDOP op) +{ + switch (op) { + case D3DBLENDOP_ADD: return PIPE_BLEND_ADD; + case D3DBLENDOP_SUBTRACT: return PIPE_BLEND_SUBTRACT; + case D3DBLENDOP_REVSUBTRACT: return PIPE_BLEND_REVERSE_SUBTRACT; + case D3DBLENDOP_MIN: return PIPE_BLEND_MIN; + case D3DBLENDOP_MAX: return PIPE_BLEND_MAX; + default: + assert(0); + return PIPE_BLEND_ADD; + } +} + +/* NOTE: The COLOR factors for are equal to the ALPHA ones for alpha. + * Drivers may check RGB and ALPHA factors for equality so we should not + * simply substitute the ALPHA variants. + */ +static inline unsigned +d3dblend_alpha_to_pipe_blendfactor(D3DBLEND b) +{ + switch (b) { + case D3DBLEND_ZERO: return PIPE_BLENDFACTOR_ZERO; + case D3DBLEND_ONE: return PIPE_BLENDFACTOR_ONE; + case D3DBLEND_SRCCOLOR: return PIPE_BLENDFACTOR_SRC_COLOR/*ALPHA*/; + case D3DBLEND_INVSRCCOLOR: return PIPE_BLENDFACTOR_INV_SRC_COLOR/*ALPHA*/; + case D3DBLEND_SRCALPHA: return PIPE_BLENDFACTOR_SRC_ALPHA; + case D3DBLEND_INVSRCALPHA: return PIPE_BLENDFACTOR_INV_SRC_ALPHA; + case D3DBLEND_DESTALPHA: return PIPE_BLENDFACTOR_DST_ALPHA; + case D3DBLEND_INVDESTALPHA: return PIPE_BLENDFACTOR_INV_DST_ALPHA; + case D3DBLEND_DESTCOLOR: return PIPE_BLENDFACTOR_DST_COLOR/*ALPHA*/; + case D3DBLEND_INVDESTCOLOR: return PIPE_BLENDFACTOR_INV_DST_COLOR/*ALPHA*/; + case D3DBLEND_SRCALPHASAT: return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE; + case D3DBLEND_BOTHSRCALPHA: return PIPE_BLENDFACTOR_SRC_ALPHA; + case D3DBLEND_BOTHINVSRCALPHA: return PIPE_BLENDFACTOR_INV_SRC_ALPHA; + case D3DBLEND_BLENDFACTOR: return PIPE_BLENDFACTOR_CONST_COLOR/*ALPHA*/; + case D3DBLEND_INVBLENDFACTOR: return PIPE_BLENDFACTOR_INV_CONST_COLOR/*ALPHA*/; + case D3DBLEND_SRCCOLOR2: return PIPE_BLENDFACTOR_ONE; /* XXX */ + case D3DBLEND_INVSRCCOLOR2: return PIPE_BLENDFACTOR_ZERO; /* XXX */ + default: + DBG_FLAG(DBG_UNKNOWN, "Unhandled blend factor %d\n", b); + return PIPE_BLENDFACTOR_ZERO; + } +} + +static inline unsigned +d3dblend_color_to_pipe_blendfactor(D3DBLEND b) +{ + switch (b) { + case D3DBLEND_ZERO: return PIPE_BLENDFACTOR_ZERO; + case D3DBLEND_ONE: return PIPE_BLENDFACTOR_ONE; + case D3DBLEND_SRCCOLOR: return PIPE_BLENDFACTOR_SRC_COLOR; + case D3DBLEND_INVSRCCOLOR: return PIPE_BLENDFACTOR_INV_SRC_COLOR; + case D3DBLEND_SRCALPHA: return PIPE_BLENDFACTOR_SRC_ALPHA; + case D3DBLEND_INVSRCALPHA: return PIPE_BLENDFACTOR_INV_SRC_ALPHA; + case D3DBLEND_DESTALPHA: return PIPE_BLENDFACTOR_DST_ALPHA; + case D3DBLEND_INVDESTALPHA: return PIPE_BLENDFACTOR_INV_DST_ALPHA; + case D3DBLEND_DESTCOLOR: return PIPE_BLENDFACTOR_DST_COLOR; + case D3DBLEND_INVDESTCOLOR: return PIPE_BLENDFACTOR_INV_DST_COLOR; + case D3DBLEND_SRCALPHASAT: return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE; + case D3DBLEND_BOTHSRCALPHA: return PIPE_BLENDFACTOR_SRC_ALPHA; + case D3DBLEND_BOTHINVSRCALPHA: return PIPE_BLENDFACTOR_INV_SRC_ALPHA; + case D3DBLEND_BLENDFACTOR: return PIPE_BLENDFACTOR_CONST_COLOR; + case D3DBLEND_INVBLENDFACTOR: return PIPE_BLENDFACTOR_INV_CONST_COLOR; + case D3DBLEND_SRCCOLOR2: return PIPE_BLENDFACTOR_SRC1_COLOR; + case D3DBLEND_INVSRCCOLOR2: return PIPE_BLENDFACTOR_INV_SRC1_COLOR; + default: + DBG_FLAG(DBG_UNKNOWN, "Unhandled blend factor %d\n", b); + return PIPE_BLENDFACTOR_ZERO; + } +} + +static inline unsigned +d3dtextureaddress_to_pipe_tex_wrap(D3DTEXTUREADDRESS addr) +{ + switch (addr) { + case D3DTADDRESS_WRAP: return PIPE_TEX_WRAP_REPEAT; + case D3DTADDRESS_MIRROR: return PIPE_TEX_WRAP_MIRROR_REPEAT; + case D3DTADDRESS_CLAMP: return PIPE_TEX_WRAP_CLAMP_TO_EDGE; + case D3DTADDRESS_BORDER: return PIPE_TEX_WRAP_CLAMP_TO_BORDER; + case D3DTADDRESS_MIRRORONCE: return PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE; + default: + assert(0); + return PIPE_TEX_WRAP_CLAMP_TO_EDGE; + } +} + +static inline unsigned +d3dtexturefiltertype_to_pipe_tex_filter(D3DTEXTUREFILTERTYPE filter) +{ + switch (filter) { + case D3DTEXF_POINT: return PIPE_TEX_FILTER_NEAREST; + case D3DTEXF_LINEAR: return PIPE_TEX_FILTER_LINEAR; + case D3DTEXF_ANISOTROPIC: return PIPE_TEX_FILTER_LINEAR; + + case D3DTEXF_NONE: + case D3DTEXF_PYRAMIDALQUAD: + case D3DTEXF_GAUSSIANQUAD: + case D3DTEXF_CONVOLUTIONMONO: + default: + assert(0); + return PIPE_TEX_FILTER_NEAREST; + } +} + +static inline unsigned +d3dtexturefiltertype_to_pipe_tex_mipfilter(D3DTEXTUREFILTERTYPE filter) +{ + switch (filter) { + case D3DTEXF_NONE: return PIPE_TEX_MIPFILTER_NONE; + case D3DTEXF_POINT: return PIPE_TEX_FILTER_NEAREST; + case D3DTEXF_LINEAR: return PIPE_TEX_FILTER_LINEAR; + case D3DTEXF_ANISOTROPIC: return PIPE_TEX_FILTER_LINEAR; + + case D3DTEXF_PYRAMIDALQUAD: + case D3DTEXF_GAUSSIANQUAD: + case D3DTEXF_CONVOLUTIONMONO: + default: + assert(0); + return PIPE_TEX_MIPFILTER_NONE; + } +} + +static inline unsigned nine_format_get_stride(enum pipe_format format, + unsigned width) +{ + unsigned stride = util_format_get_stride(format, width); + + return align(stride, 4); +} + +static inline unsigned nine_format_get_level_alloc_size(enum pipe_format format, + unsigned width, + unsigned height, + unsigned level) +{ + unsigned w, h, size; + + w = u_minify(width, level); + h = u_minify(height, level); + if (is_ATI1_ATI2(format)) { + /* For "unknown" formats like ATIx use width * height bytes */ + size = w * h; + } else if (format == PIPE_FORMAT_NONE) { /* D3DFMT_NULL */ + size = w * h * 4; + } else { + size = nine_format_get_stride(format, w) * + util_format_get_nblocksy(format, h); + } + + return size; +} + +static inline unsigned nine_format_get_size_and_offsets(enum pipe_format format, + unsigned *offsets, + unsigned width, + unsigned height, + unsigned last_level) +{ + unsigned l, w, h, size = 0; + + for (l = 0; l <= last_level; ++l) { + w = u_minify(width, l); + h = u_minify(height, l); + offsets[l] = size; + if (is_ATI1_ATI2(format)) { + /* For "unknown" formats like ATIx use width * height bytes */ + size += w * h; + } else { + size += nine_format_get_stride(format, w) * + util_format_get_nblocksy(format, h); + } + } + + return size; +} + +#endif /* _NINE_PIPE_H_ */ diff --git a/src/gallium/frontends/nine/nine_queue.c b/src/gallium/frontends/nine/nine_queue.c new file mode 100644 index 00000000000..c09810b1a8a --- /dev/null +++ b/src/gallium/frontends/nine/nine_queue.c @@ -0,0 +1,279 @@ +/* + * Copyright 2016 Patrick Rudolph + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "nine_queue.h" +#include "os/os_thread.h" +#include "util/macros.h" +#include "nine_helpers.h" + +#define NINE_CMD_BUF_INSTR (256) + +#define NINE_CMD_BUFS (32) +#define NINE_CMD_BUFS_MASK (NINE_CMD_BUFS - 1) + +#define NINE_QUEUE_SIZE (8192 * 16 + 128) + +#define DBG_CHANNEL DBG_DEVICE + +/* + * Single producer - single consumer pool queue + * + * Producer: + * Calls nine_queue_alloc to get a slice of memory in current cmdbuf. + * Calls nine_queue_flush to flush the queue by request. + * The queue is flushed automatically on insufficient space or once the + * cmdbuf contains NINE_CMD_BUF_INSTR instructions. + * + * nine_queue_flush does block, while nine_queue_alloc doesn't block. + * + * nine_queue_alloc returns NULL on insufficent space. + * + * Consumer: + * Calls nine_queue_wait_flush to wait for a cmdbuf. + * After waiting for a cmdbuf it calls nine_queue_get until NULL is returned. + * + * nine_queue_wait_flush does block, while nine_queue_get doesn't block. + * + * Constrains: + * Only a single consumer and a single producer are supported. + * + */ + +struct nine_cmdbuf { + unsigned instr_size[NINE_CMD_BUF_INSTR]; + unsigned num_instr; + unsigned offset; + void *mem_pool; + BOOL full; +}; + +struct nine_queue_pool { + struct nine_cmdbuf pool[NINE_CMD_BUFS]; + unsigned head; + unsigned tail; + unsigned cur_instr; + BOOL worker_wait; + cnd_t event_pop; + cnd_t event_push; + mtx_t mutex_pop; + mtx_t mutex_push; +}; + +/* Consumer functions: */ +void +nine_queue_wait_flush(struct nine_queue_pool* ctx) +{ + struct nine_cmdbuf *cmdbuf = &ctx->pool[ctx->tail]; + + /* wait for cmdbuf full */ + mtx_lock(&ctx->mutex_push); + while (!cmdbuf->full) + { + DBG("waiting for full cmdbuf\n"); + cnd_wait(&ctx->event_push, &ctx->mutex_push); + } + DBG("got cmdbuf=%p\n", cmdbuf); + mtx_unlock(&ctx->mutex_push); + + cmdbuf->offset = 0; + ctx->cur_instr = 0; +} + +/* Gets a pointer to the next memory slice. + * Does not block. + * Returns NULL on empty cmdbuf. */ +void * +nine_queue_get(struct nine_queue_pool* ctx) +{ + struct nine_cmdbuf *cmdbuf = &ctx->pool[ctx->tail]; + unsigned offset; + + /* At this pointer there's always a cmdbuf. */ + + if (ctx->cur_instr == cmdbuf->num_instr) { + /* signal waiting producer */ + mtx_lock(&ctx->mutex_pop); + DBG("freeing cmdbuf=%p\n", cmdbuf); + cmdbuf->full = 0; + cnd_signal(&ctx->event_pop); + mtx_unlock(&ctx->mutex_pop); + + ctx->tail = (ctx->tail + 1) & NINE_CMD_BUFS_MASK; + + return NULL; + } + + /* At this pointer there's always a cmdbuf with instruction to process. */ + offset = cmdbuf->offset; + cmdbuf->offset += cmdbuf->instr_size[ctx->cur_instr]; + ctx->cur_instr ++; + + return cmdbuf->mem_pool + offset; +} + +/* Producer functions: */ + +/* Flushes the queue. + * Moves the current cmdbuf to worker thread. + * Blocks until next cmdbuf is free. */ +void +nine_queue_flush(struct nine_queue_pool* ctx) +{ + struct nine_cmdbuf *cmdbuf = &ctx->pool[ctx->head]; + + DBG("flushing cmdbuf=%p instr=%d size=%d\n", + cmdbuf, cmdbuf->num_instr, cmdbuf->offset); + + /* Nothing to flush */ + if (!cmdbuf->num_instr) + return; + + /* signal waiting worker */ + mtx_lock(&ctx->mutex_push); + cmdbuf->full = 1; + cnd_signal(&ctx->event_push); + mtx_unlock(&ctx->mutex_push); + + ctx->head = (ctx->head + 1) & NINE_CMD_BUFS_MASK; + + cmdbuf = &ctx->pool[ctx->head]; + + /* wait for queue empty */ + mtx_lock(&ctx->mutex_pop); + while (cmdbuf->full) + { + DBG("waiting for empty cmdbuf\n"); + cnd_wait(&ctx->event_pop, &ctx->mutex_pop); + } + DBG("got empty cmdbuf=%p\n", cmdbuf); + mtx_unlock(&ctx->mutex_pop); + cmdbuf->offset = 0; + cmdbuf->num_instr = 0; +} + +/* Gets a a pointer to slice of memory with size @space. + * Does block if queue is full. + * Returns NULL on @space > NINE_QUEUE_SIZE. */ +void * +nine_queue_alloc(struct nine_queue_pool* ctx, unsigned space) +{ + unsigned offset; + struct nine_cmdbuf *cmdbuf = &ctx->pool[ctx->head]; + + if (space > NINE_QUEUE_SIZE) + return NULL; + + /* at this pointer there's always a free queue available */ + + if ((cmdbuf->offset + space > NINE_QUEUE_SIZE) || + (cmdbuf->num_instr == NINE_CMD_BUF_INSTR)) { + + nine_queue_flush(ctx); + + cmdbuf = &ctx->pool[ctx->head]; + } + + DBG("cmdbuf=%p space=%d\n", cmdbuf, space); + + /* at this pointer there's always a free queue with sufficient space available */ + + offset = cmdbuf->offset; + cmdbuf->offset += space; + cmdbuf->instr_size[cmdbuf->num_instr] = space; + cmdbuf->num_instr ++; + + return cmdbuf->mem_pool + offset; +} + +/* Returns the current queue flush state. + * TRUE nothing flushed + * FALSE one ore more instructions queued flushed. */ +bool +nine_queue_no_flushed_work(struct nine_queue_pool* ctx) +{ + return (ctx->tail == ctx->head); +} + +/* Returns the current queue empty state. + * TRUE no instructions queued. + * FALSE one ore more instructions queued. */ +bool +nine_queue_isempty(struct nine_queue_pool* ctx) +{ + struct nine_cmdbuf *cmdbuf = &ctx->pool[ctx->head]; + + return (ctx->tail == ctx->head) && !cmdbuf->num_instr; +} + +struct nine_queue_pool* +nine_queue_create(void) +{ + unsigned i; + struct nine_queue_pool *ctx; + + ctx = CALLOC_STRUCT(nine_queue_pool); + if (!ctx) + goto failed; + + for (i = 0; i < NINE_CMD_BUFS; i++) { + ctx->pool[i].mem_pool = MALLOC(NINE_QUEUE_SIZE); + if (!ctx->pool[i].mem_pool) + goto failed; + } + + cnd_init(&ctx->event_pop); + (void) mtx_init(&ctx->mutex_pop, mtx_plain); + + cnd_init(&ctx->event_push); + (void) mtx_init(&ctx->mutex_push, mtx_plain); + + /* Block until first cmdbuf has been flushed. */ + ctx->worker_wait = TRUE; + + return ctx; +failed: + if (ctx) { + for (i = 0; i < NINE_CMD_BUFS; i++) { + if (ctx->pool[i].mem_pool) + FREE(ctx->pool[i].mem_pool); + } + FREE(ctx); + } + return NULL; +} + +void +nine_queue_delete(struct nine_queue_pool *ctx) +{ + unsigned i; + + mtx_destroy(&ctx->mutex_pop); + cnd_destroy(&ctx->event_pop); + + mtx_destroy(&ctx->mutex_push); + cnd_destroy(&ctx->event_push); + + for (i = 0; i < NINE_CMD_BUFS; i++) + FREE(ctx->pool[i].mem_pool); + + FREE(ctx); +} diff --git a/src/gallium/frontends/nine/nine_queue.h b/src/gallium/frontends/nine/nine_queue.h new file mode 100644 index 00000000000..52f6cbdfa87 --- /dev/null +++ b/src/gallium/frontends/nine/nine_queue.h @@ -0,0 +1,54 @@ +/* + * Copyright 2016 Patrick Rudolph + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _NINE_QUEUE_H_ +#define _NINE_QUEUE_H_ + +#include "pipe/p_compiler.h" + +struct nine_queue_pool; + +void +nine_queue_wait_flush(struct nine_queue_pool* ctx); + +void * +nine_queue_get(struct nine_queue_pool* ctx); + +void +nine_queue_flush(struct nine_queue_pool* ctx); + +void * +nine_queue_alloc(struct nine_queue_pool* ctx, unsigned space); + +bool +nine_queue_no_flushed_work(struct nine_queue_pool* ctx); + +bool +nine_queue_isempty(struct nine_queue_pool* ctx); + +struct nine_queue_pool* +nine_queue_create(void); + +void +nine_queue_delete(struct nine_queue_pool *ctx); + +#endif /* _NINE_QUEUE_H_ */ diff --git a/src/gallium/frontends/nine/nine_quirk.c b/src/gallium/frontends/nine/nine_quirk.c new file mode 100644 index 00000000000..267436b14de --- /dev/null +++ b/src/gallium/frontends/nine/nine_quirk.c @@ -0,0 +1,49 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "nine_quirk.h" + +#include "util/u_debug.h" + +static const struct debug_named_value nine_quirk_table[] = { + { "fakecaps", QUIRK_FAKE_CAPS, + "Fake caps to emulate D3D specs regardless of hardware caps." }, + { "lenientshader", QUIRK_LENIENT_SHADER, + "Be lenient when translating shaders." }, + { "all", ~0U, + "Enable all quirks." }, + DEBUG_NAMED_VALUE_END +}; + +boolean +_nine_get_quirk( unsigned quirk ) +{ + static boolean first = TRUE; + static unsigned long flags = 0; + + if (first) { + first = FALSE; + flags = debug_get_flags_option("NINE_QUIRKS", nine_quirk_table, 0); + } + + return !!(flags & quirk); +} diff --git a/src/gallium/frontends/nine/nine_quirk.h b/src/gallium/frontends/nine/nine_quirk.h new file mode 100644 index 00000000000..9c082dd9f93 --- /dev/null +++ b/src/gallium/frontends/nine/nine_quirk.h @@ -0,0 +1,36 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _NINE_QUIRK_H_ +#define _NINE_QUIRK_H_ + +#include "pipe/p_compiler.h" + +boolean +_nine_get_quirk( unsigned quirk ); + +#define QUIRK(q) (_nine_get_quirk(QUIRK_##q)) + +#define QUIRK_FAKE_CAPS 0x00000001 +#define QUIRK_LENIENT_SHADER 0x00000002 + +#endif /* _NINE_QUIRK_H_ */ diff --git a/src/gallium/frontends/nine/nine_shader.c b/src/gallium/frontends/nine/nine_shader.c new file mode 100644 index 00000000000..195a1fe5f59 --- /dev/null +++ b/src/gallium/frontends/nine/nine_shader.c @@ -0,0 +1,4140 @@ +/* + * Copyright 2011 Joakim Sindholt + * Copyright 2013 Christoph Bumiller + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "nine_shader.h" + +#include "device9.h" +#include "nine_debug.h" +#include "nine_state.h" +#include "vertexdeclaration9.h" + +#include "util/macros.h" +#include "util/u_memory.h" +#include "util/u_inlines.h" +#include "pipe/p_shader_tokens.h" +#include "tgsi/tgsi_ureg.h" +#include "tgsi/tgsi_dump.h" +#include "nir/tgsi_to_nir.h" + +#define DBG_CHANNEL DBG_SHADER + +#define DUMP(args...) _nine_debug_printf(DBG_CHANNEL, NULL, args) + + +struct shader_translator; + +typedef HRESULT (*translate_instruction_func)(struct shader_translator *); + +static inline const char *d3dsio_to_string(unsigned opcode); + + +#define NINED3D_SM1_VS 0xfffe +#define NINED3D_SM1_PS 0xffff + +#define NINE_MAX_COND_DEPTH 64 +#define NINE_MAX_LOOP_DEPTH 64 + +#define NINED3DSP_END 0x0000ffff + +#define NINED3DSPTYPE_FLOAT4 0 +#define NINED3DSPTYPE_INT4 1 +#define NINED3DSPTYPE_BOOL 2 + +#define NINED3DSPR_IMMEDIATE (D3DSPR_PREDICATE + 1) + +#define NINED3DSP_WRITEMASK_MASK D3DSP_WRITEMASK_ALL +#define NINED3DSP_WRITEMASK_SHIFT 16 + +#define NINED3DSHADER_INST_PREDICATED (1 << 28) + +#define NINED3DSHADER_REL_OP_GT 1 +#define NINED3DSHADER_REL_OP_EQ 2 +#define NINED3DSHADER_REL_OP_GE 3 +#define NINED3DSHADER_REL_OP_LT 4 +#define NINED3DSHADER_REL_OP_NE 5 +#define NINED3DSHADER_REL_OP_LE 6 + +#define NINED3DSIO_OPCODE_FLAGS_SHIFT 16 +#define NINED3DSIO_OPCODE_FLAGS_MASK (0xff << NINED3DSIO_OPCODE_FLAGS_SHIFT) + +#define NINED3DSI_TEXLD_PROJECT 0x1 +#define NINED3DSI_TEXLD_BIAS 0x2 + +#define NINED3DSP_WRITEMASK_0 0x1 +#define NINED3DSP_WRITEMASK_1 0x2 +#define NINED3DSP_WRITEMASK_2 0x4 +#define NINED3DSP_WRITEMASK_3 0x8 +#define NINED3DSP_WRITEMASK_ALL 0xf + +#define NINED3DSP_NOSWIZZLE ((0 << 0) | (1 << 2) | (2 << 4) | (3 << 6)) + +#define NINE_SWIZZLE4(x,y,z,w) \ + TGSI_SWIZZLE_##x, TGSI_SWIZZLE_##y, TGSI_SWIZZLE_##z, TGSI_SWIZZLE_##w + +#define NINE_APPLY_SWIZZLE(src, s) \ + ureg_swizzle(src, NINE_SWIZZLE4(s, s, s, s)) + +#define NINED3DSPDM_SATURATE (D3DSPDM_SATURATE >> D3DSP_DSTMOD_SHIFT) +#define NINED3DSPDM_PARTIALP (D3DSPDM_PARTIALPRECISION >> D3DSP_DSTMOD_SHIFT) +#define NINED3DSPDM_CENTROID (D3DSPDM_MSAMPCENTROID >> D3DSP_DSTMOD_SHIFT) + +/* + * NEG all, not ps: m3x2, m3x3, m3x4, m4x3, m4x4 + * BIAS <= PS 1.4 (x-0.5) + * BIASNEG <= PS 1.4 (-(x-0.5)) + * SIGN <= PS 1.4 (2(x-0.5)) + * SIGNNEG <= PS 1.4 (-2(x-0.5)) + * COMP <= PS 1.4 (1-x) + * X2 = PS 1.4 (2x) + * X2NEG = PS 1.4 (-2x) + * DZ <= PS 1.4, tex{ld,crd} (.xy/.z), z=0 => .11 + * DW <= PS 1.4, tex{ld,crd} (.xy/.w), w=0 => .11 + * ABS >= SM 3.0 (abs(x)) + * ABSNEG >= SM 3.0 (-abs(x)) + * NOT >= SM 2.0 pedication only + */ +#define NINED3DSPSM_NONE (D3DSPSM_NONE >> D3DSP_SRCMOD_SHIFT) +#define NINED3DSPSM_NEG (D3DSPSM_NEG >> D3DSP_SRCMOD_SHIFT) +#define NINED3DSPSM_BIAS (D3DSPSM_BIAS >> D3DSP_SRCMOD_SHIFT) +#define NINED3DSPSM_BIASNEG (D3DSPSM_BIASNEG >> D3DSP_SRCMOD_SHIFT) +#define NINED3DSPSM_SIGN (D3DSPSM_SIGN >> D3DSP_SRCMOD_SHIFT) +#define NINED3DSPSM_SIGNNEG (D3DSPSM_SIGNNEG >> D3DSP_SRCMOD_SHIFT) +#define NINED3DSPSM_COMP (D3DSPSM_COMP >> D3DSP_SRCMOD_SHIFT) +#define NINED3DSPSM_X2 (D3DSPSM_X2 >> D3DSP_SRCMOD_SHIFT) +#define NINED3DSPSM_X2NEG (D3DSPSM_X2NEG >> D3DSP_SRCMOD_SHIFT) +#define NINED3DSPSM_DZ (D3DSPSM_DZ >> D3DSP_SRCMOD_SHIFT) +#define NINED3DSPSM_DW (D3DSPSM_DW >> D3DSP_SRCMOD_SHIFT) +#define NINED3DSPSM_ABS (D3DSPSM_ABS >> D3DSP_SRCMOD_SHIFT) +#define NINED3DSPSM_ABSNEG (D3DSPSM_ABSNEG >> D3DSP_SRCMOD_SHIFT) +#define NINED3DSPSM_NOT (D3DSPSM_NOT >> D3DSP_SRCMOD_SHIFT) + +static const char *sm1_mod_str[] = +{ + [NINED3DSPSM_NONE] = "", + [NINED3DSPSM_NEG] = "-", + [NINED3DSPSM_BIAS] = "bias", + [NINED3DSPSM_BIASNEG] = "biasneg", + [NINED3DSPSM_SIGN] = "sign", + [NINED3DSPSM_SIGNNEG] = "signneg", + [NINED3DSPSM_COMP] = "comp", + [NINED3DSPSM_X2] = "x2", + [NINED3DSPSM_X2NEG] = "x2neg", + [NINED3DSPSM_DZ] = "dz", + [NINED3DSPSM_DW] = "dw", + [NINED3DSPSM_ABS] = "abs", + [NINED3DSPSM_ABSNEG] = "-abs", + [NINED3DSPSM_NOT] = "not" +}; + +static void +sm1_dump_writemask(BYTE mask) +{ + if (mask & 1) DUMP("x"); else DUMP("_"); + if (mask & 2) DUMP("y"); else DUMP("_"); + if (mask & 4) DUMP("z"); else DUMP("_"); + if (mask & 8) DUMP("w"); else DUMP("_"); +} + +static void +sm1_dump_swizzle(BYTE s) +{ + char c[4] = { 'x', 'y', 'z', 'w' }; + DUMP("%c%c%c%c", + c[(s >> 0) & 3], c[(s >> 2) & 3], c[(s >> 4) & 3], c[(s >> 6) & 3]); +} + +static const char sm1_file_char[] = +{ + [D3DSPR_TEMP] = 'r', + [D3DSPR_INPUT] = 'v', + [D3DSPR_CONST] = 'c', + [D3DSPR_ADDR] = 'A', + [D3DSPR_RASTOUT] = 'R', + [D3DSPR_ATTROUT] = 'D', + [D3DSPR_OUTPUT] = 'o', + [D3DSPR_CONSTINT] = 'I', + [D3DSPR_COLOROUT] = 'C', + [D3DSPR_DEPTHOUT] = 'D', + [D3DSPR_SAMPLER] = 's', + [D3DSPR_CONST2] = 'c', + [D3DSPR_CONST3] = 'c', + [D3DSPR_CONST4] = 'c', + [D3DSPR_CONSTBOOL] = 'B', + [D3DSPR_LOOP] = 'L', + [D3DSPR_TEMPFLOAT16] = 'h', + [D3DSPR_MISCTYPE] = 'M', + [D3DSPR_LABEL] = 'X', + [D3DSPR_PREDICATE] = 'p' +}; + +static void +sm1_dump_reg(BYTE file, INT index) +{ + switch (file) { + case D3DSPR_LOOP: + DUMP("aL"); + break; + case D3DSPR_COLOROUT: + DUMP("oC%i", index); + break; + case D3DSPR_DEPTHOUT: + DUMP("oDepth"); + break; + case D3DSPR_RASTOUT: + DUMP("oRast%i", index); + break; + case D3DSPR_CONSTINT: + DUMP("iconst[%i]", index); + break; + case D3DSPR_CONSTBOOL: + DUMP("bconst[%i]", index); + break; + default: + DUMP("%c%i", sm1_file_char[file], index); + break; + } +} + +struct sm1_src_param +{ + INT idx; + struct sm1_src_param *rel; + BYTE file; + BYTE swizzle; + BYTE mod; + BYTE type; + union { + DWORD d[4]; + float f[4]; + int i[4]; + BOOL b; + } imm; +}; +static void +sm1_parse_immediate(struct shader_translator *, struct sm1_src_param *); + +struct sm1_dst_param +{ + INT idx; + struct sm1_src_param *rel; + BYTE file; + BYTE mask; + BYTE mod; + int8_t shift; /* sint4 */ + BYTE type; +}; + +static inline void +assert_replicate_swizzle(const struct ureg_src *reg) +{ + assert(reg->SwizzleY == reg->SwizzleX && + reg->SwizzleZ == reg->SwizzleX && + reg->SwizzleW == reg->SwizzleX); +} + +static void +sm1_dump_immediate(const struct sm1_src_param *param) +{ + switch (param->type) { + case NINED3DSPTYPE_FLOAT4: + DUMP("{ %f %f %f %f }", + param->imm.f[0], param->imm.f[1], + param->imm.f[2], param->imm.f[3]); + break; + case NINED3DSPTYPE_INT4: + DUMP("{ %i %i %i %i }", + param->imm.i[0], param->imm.i[1], + param->imm.i[2], param->imm.i[3]); + break; + case NINED3DSPTYPE_BOOL: + DUMP("%s", param->imm.b ? "TRUE" : "FALSE"); + break; + default: + assert(0); + break; + } +} + +static void +sm1_dump_src_param(const struct sm1_src_param *param) +{ + if (param->file == NINED3DSPR_IMMEDIATE) { + assert(!param->mod && + !param->rel && + param->swizzle == NINED3DSP_NOSWIZZLE); + sm1_dump_immediate(param); + return; + } + + if (param->mod) + DUMP("%s(", sm1_mod_str[param->mod]); + if (param->rel) { + DUMP("%c[", sm1_file_char[param->file]); + sm1_dump_src_param(param->rel); + DUMP("+%i]", param->idx); + } else { + sm1_dump_reg(param->file, param->idx); + } + if (param->mod) + DUMP(")"); + if (param->swizzle != NINED3DSP_NOSWIZZLE) { + DUMP("."); + sm1_dump_swizzle(param->swizzle); + } +} + +static void +sm1_dump_dst_param(const struct sm1_dst_param *param) +{ + if (param->mod & NINED3DSPDM_SATURATE) + DUMP("sat "); + if (param->mod & NINED3DSPDM_PARTIALP) + DUMP("pp "); + if (param->mod & NINED3DSPDM_CENTROID) + DUMP("centroid "); + if (param->shift < 0) + DUMP("/%u ", 1 << -param->shift); + if (param->shift > 0) + DUMP("*%u ", 1 << param->shift); + + if (param->rel) { + DUMP("%c[", sm1_file_char[param->file]); + sm1_dump_src_param(param->rel); + DUMP("+%i]", param->idx); + } else { + sm1_dump_reg(param->file, param->idx); + } + if (param->mask != NINED3DSP_WRITEMASK_ALL) { + DUMP("."); + sm1_dump_writemask(param->mask); + } +} + +struct sm1_semantic +{ + struct sm1_dst_param reg; + BYTE sampler_type; + D3DDECLUSAGE usage; + BYTE usage_idx; +}; + +struct sm1_op_info +{ + /* NOTE: 0 is a valid TGSI opcode, but if handler is set, this parameter + * should be ignored completely */ + unsigned sio; + unsigned opcode; /* TGSI_OPCODE_x */ + + /* versions are still set even handler is set */ + struct { + unsigned min; + unsigned max; + } vert_version, frag_version; + + /* number of regs parsed outside of special handler */ + unsigned ndst; + unsigned nsrc; + + /* some instructions don't map perfectly, so use a special handler */ + translate_instruction_func handler; +}; + +struct sm1_instruction +{ + D3DSHADER_INSTRUCTION_OPCODE_TYPE opcode; + BYTE flags; + BOOL coissue; + BOOL predicated; + BYTE ndst; + BYTE nsrc; + struct sm1_src_param src[4]; + struct sm1_src_param src_rel[4]; + struct sm1_src_param pred; + struct sm1_src_param dst_rel[1]; + struct sm1_dst_param dst[1]; + + const struct sm1_op_info *info; +}; + +static void +sm1_dump_instruction(struct sm1_instruction *insn, unsigned indent) +{ + unsigned i; + + /* no info stored for these: */ + if (insn->opcode == D3DSIO_DCL) + return; + for (i = 0; i < indent; ++i) + DUMP(" "); + + if (insn->predicated) { + DUMP("@"); + sm1_dump_src_param(&insn->pred); + DUMP(" "); + } + DUMP("%s", d3dsio_to_string(insn->opcode)); + if (insn->flags) { + switch (insn->opcode) { + case D3DSIO_TEX: + DUMP(insn->flags == NINED3DSI_TEXLD_PROJECT ? "p" : "b"); + break; + default: + DUMP("_%x", insn->flags); + break; + } + } + if (insn->coissue) + DUMP("_co"); + DUMP(" "); + + for (i = 0; i < insn->ndst && i < ARRAY_SIZE(insn->dst); ++i) { + sm1_dump_dst_param(&insn->dst[i]); + DUMP(" "); + } + + for (i = 0; i < insn->nsrc && i < ARRAY_SIZE(insn->src); ++i) { + sm1_dump_src_param(&insn->src[i]); + DUMP(" "); + } + if (insn->opcode == D3DSIO_DEF || + insn->opcode == D3DSIO_DEFI || + insn->opcode == D3DSIO_DEFB) + sm1_dump_immediate(&insn->src[0]); + + DUMP("\n"); +} + +struct sm1_local_const +{ + INT idx; + struct ureg_src reg; + float f[4]; /* for indirect addressing of float constants */ +}; + +struct shader_translator +{ + const DWORD *byte_code; + const DWORD *parse; + const DWORD *parse_next; + + struct ureg_program *ureg; + + /* shader version */ + struct { + BYTE major; + BYTE minor; + } version; + unsigned processor; /* PIPE_SHADER_VERTEX/FRAMGENT */ + unsigned num_constf_allowed; + unsigned num_consti_allowed; + unsigned num_constb_allowed; + + boolean native_integers; + boolean inline_subroutines; + boolean want_texcoord; + boolean shift_wpos; + boolean wpos_is_sysval; + boolean face_is_sysval_integer; + boolean mul_zero_wins; + unsigned texcoord_sn; + + struct sm1_instruction insn; /* current instruction */ + + struct { + struct ureg_dst *r; + struct ureg_dst oPos; + struct ureg_dst oPos_out; /* the real output when doing streamout */ + struct ureg_dst oFog; + struct ureg_dst oPts; + struct ureg_dst oCol[4]; + struct ureg_dst o[PIPE_MAX_SHADER_OUTPUTS]; + struct ureg_dst oDepth; + struct ureg_src v[PIPE_MAX_SHADER_INPUTS]; + struct ureg_src v_consecutive; /* copy in temp array of ps inputs for rel addressing */ + struct ureg_src vPos; + struct ureg_src vFace; + struct ureg_src s; + struct ureg_dst p; + struct ureg_dst address; + struct ureg_dst a0; + struct ureg_dst predicate; + struct ureg_dst predicate_tmp; + struct ureg_dst predicate_dst; + struct ureg_dst tS[8]; /* texture stage registers */ + struct ureg_dst tdst; /* scratch dst if we need extra modifiers */ + struct ureg_dst t[8]; /* scratch TEMPs */ + struct ureg_src vC[2]; /* PS color in */ + struct ureg_src vT[8]; /* PS texcoord in */ + struct ureg_dst rL[NINE_MAX_LOOP_DEPTH]; /* loop ctr */ + } regs; + unsigned num_temp; /* ARRAY_SIZE(regs.r) */ + unsigned num_scratch; + unsigned loop_depth; + unsigned loop_depth_max; + unsigned cond_depth; + unsigned loop_labels[NINE_MAX_LOOP_DEPTH]; + unsigned cond_labels[NINE_MAX_COND_DEPTH]; + boolean loop_or_rep[NINE_MAX_LOOP_DEPTH]; /* true: loop, false: rep */ + boolean predicated_activated; + + unsigned *inst_labels; /* LABEL op */ + unsigned num_inst_labels; + + unsigned sampler_targets[NINE_MAX_SAMPLERS]; /* TGSI_TEXTURE_x */ + + struct sm1_local_const *lconstf; + unsigned num_lconstf; + struct sm1_local_const *lconsti; + unsigned num_lconsti; + struct sm1_local_const *lconstb; + unsigned num_lconstb; + + boolean slots_used[NINE_MAX_CONST_ALL]; + unsigned *slot_map; + unsigned num_slots; + + boolean indirect_const_access; + boolean failure; + + struct nine_vs_output_info output_info[16]; + int num_outputs; + + struct nine_shader_info *info; + + int16_t op_info_map[D3DSIO_BREAKP + 1]; +}; + +#define IS_VS (tx->processor == PIPE_SHADER_VERTEX) +#define IS_PS (tx->processor == PIPE_SHADER_FRAGMENT) + +#define FAILURE_VOID(cond) if ((cond)) {tx->failure=1;return;} + +static void +sm1_read_semantic(struct shader_translator *, struct sm1_semantic *); + +static void +sm1_instruction_check(const struct sm1_instruction *insn) +{ + if (insn->opcode == D3DSIO_CRS) + { + if (insn->dst[0].mask & NINED3DSP_WRITEMASK_3) + { + DBG("CRS.mask.w\n"); + } + } +} + +static void +nine_record_outputs(struct shader_translator *tx, BYTE Usage, BYTE UsageIndex, + int mask, int output_index) +{ + tx->output_info[tx->num_outputs].output_semantic = Usage; + tx->output_info[tx->num_outputs].output_semantic_index = UsageIndex; + tx->output_info[tx->num_outputs].mask = mask; + tx->output_info[tx->num_outputs].output_index = output_index; + tx->num_outputs++; +} + +static struct ureg_src nine_float_constant_src(struct shader_translator *tx, int idx) +{ + struct ureg_src src; + + if (tx->slot_map) + idx = tx->slot_map[idx]; + /* vswp constant handling: we use two buffers + * to fit all the float constants. The special handling + * doesn't need to be elsewhere, because all the instructions + * accessing the constants directly are VS1, and swvp + * is VS >= 2 */ + if (tx->info->swvp_on && idx >= 4096) { + /* TODO: swvp rel is broken if many constants are used */ + src = ureg_src_register(TGSI_FILE_CONSTANT, idx - 4096); + src = ureg_src_dimension(src, 1); + } else { + src = ureg_src_register(TGSI_FILE_CONSTANT, idx); + src = ureg_src_dimension(src, 0); + } + + if (!tx->info->swvp_on) + tx->slots_used[idx] = TRUE; + if (tx->info->const_float_slots < (idx + 1)) + tx->info->const_float_slots = idx + 1; + if (tx->num_slots < (idx + 1)) + tx->num_slots = idx + 1; + + return src; +} + +static struct ureg_src nine_integer_constant_src(struct shader_translator *tx, int idx) +{ + struct ureg_src src; + + if (tx->info->swvp_on) { + src = ureg_src_register(TGSI_FILE_CONSTANT, idx); + src = ureg_src_dimension(src, 2); + } else { + unsigned slot_idx = tx->info->const_i_base + idx; + if (tx->slot_map) + slot_idx = tx->slot_map[slot_idx]; + src = ureg_src_register(TGSI_FILE_CONSTANT, slot_idx); + src = ureg_src_dimension(src, 0); + tx->slots_used[slot_idx] = TRUE; + tx->info->int_slots_used[idx] = TRUE; + if (tx->num_slots < (slot_idx + 1)) + tx->num_slots = slot_idx + 1; + } + + if (tx->info->const_int_slots < (idx + 1)) + tx->info->const_int_slots = idx + 1; + + return src; +} + +static struct ureg_src nine_boolean_constant_src(struct shader_translator *tx, int idx) +{ + struct ureg_src src; + + char r = idx / 4; + char s = idx & 3; + + if (tx->info->swvp_on) { + src = ureg_src_register(TGSI_FILE_CONSTANT, r); + src = ureg_src_dimension(src, 3); + } else { + unsigned slot_idx = tx->info->const_b_base + r; + if (tx->slot_map) + slot_idx = tx->slot_map[slot_idx]; + src = ureg_src_register(TGSI_FILE_CONSTANT, slot_idx); + src = ureg_src_dimension(src, 0); + tx->slots_used[slot_idx] = TRUE; + tx->info->bool_slots_used[idx] = TRUE; + if (tx->num_slots < (slot_idx + 1)) + tx->num_slots = slot_idx + 1; + } + src = ureg_swizzle(src, s, s, s, s); + + if (tx->info->const_bool_slots < (idx + 1)) + tx->info->const_bool_slots = idx + 1; + + return src; +} + +static boolean +tx_lconstf(struct shader_translator *tx, struct ureg_src *src, INT index) +{ + INT i; + + if (index < 0 || index >= tx->num_constf_allowed) { + tx->failure = TRUE; + return FALSE; + } + for (i = 0; i < tx->num_lconstf; ++i) { + if (tx->lconstf[i].idx == index) { + *src = tx->lconstf[i].reg; + return TRUE; + } + } + return FALSE; +} +static boolean +tx_lconsti(struct shader_translator *tx, struct ureg_src *src, INT index) +{ + int i; + + if (index < 0 || index >= tx->num_consti_allowed) { + tx->failure = TRUE; + return FALSE; + } + for (i = 0; i < tx->num_lconsti; ++i) { + if (tx->lconsti[i].idx == index) { + *src = tx->lconsti[i].reg; + return TRUE; + } + } + return FALSE; +} +static boolean +tx_lconstb(struct shader_translator *tx, struct ureg_src *src, INT index) +{ + int i; + + if (index < 0 || index >= tx->num_constb_allowed) { + tx->failure = TRUE; + return FALSE; + } + for (i = 0; i < tx->num_lconstb; ++i) { + if (tx->lconstb[i].idx == index) { + *src = tx->lconstb[i].reg; + return TRUE; + } + } + return FALSE; +} + +static void +tx_set_lconstf(struct shader_translator *tx, INT index, float f[4]) +{ + unsigned n; + + FAILURE_VOID(index < 0 || index >= tx->num_constf_allowed) + + for (n = 0; n < tx->num_lconstf; ++n) + if (tx->lconstf[n].idx == index) + break; + if (n == tx->num_lconstf) { + if ((n % 8) == 0) { + tx->lconstf = REALLOC(tx->lconstf, + (n + 0) * sizeof(tx->lconstf[0]), + (n + 8) * sizeof(tx->lconstf[0])); + assert(tx->lconstf); + } + tx->num_lconstf++; + } + tx->lconstf[n].idx = index; + tx->lconstf[n].reg = ureg_imm4f(tx->ureg, f[0], f[1], f[2], f[3]); + + memcpy(tx->lconstf[n].f, f, sizeof(tx->lconstf[n].f)); +} +static void +tx_set_lconsti(struct shader_translator *tx, INT index, int i[4]) +{ + unsigned n; + + FAILURE_VOID(index < 0 || index >= tx->num_consti_allowed) + + for (n = 0; n < tx->num_lconsti; ++n) + if (tx->lconsti[n].idx == index) + break; + if (n == tx->num_lconsti) { + if ((n % 8) == 0) { + tx->lconsti = REALLOC(tx->lconsti, + (n + 0) * sizeof(tx->lconsti[0]), + (n + 8) * sizeof(tx->lconsti[0])); + assert(tx->lconsti); + } + tx->num_lconsti++; + } + + tx->lconsti[n].idx = index; + tx->lconsti[n].reg = tx->native_integers ? + ureg_imm4i(tx->ureg, i[0], i[1], i[2], i[3]) : + ureg_imm4f(tx->ureg, i[0], i[1], i[2], i[3]); +} +static void +tx_set_lconstb(struct shader_translator *tx, INT index, BOOL b) +{ + unsigned n; + + FAILURE_VOID(index < 0 || index >= tx->num_constb_allowed) + + for (n = 0; n < tx->num_lconstb; ++n) + if (tx->lconstb[n].idx == index) + break; + if (n == tx->num_lconstb) { + if ((n % 8) == 0) { + tx->lconstb = REALLOC(tx->lconstb, + (n + 0) * sizeof(tx->lconstb[0]), + (n + 8) * sizeof(tx->lconstb[0])); + assert(tx->lconstb); + } + tx->num_lconstb++; + } + + tx->lconstb[n].idx = index; + tx->lconstb[n].reg = tx->native_integers ? + ureg_imm1u(tx->ureg, b ? 0xffffffff : 0) : + ureg_imm1f(tx->ureg, b ? 1.0f : 0.0f); +} + +static inline struct ureg_dst +tx_scratch(struct shader_translator *tx) +{ + if (tx->num_scratch >= ARRAY_SIZE(tx->regs.t)) { + tx->failure = TRUE; + return tx->regs.t[0]; + } + if (ureg_dst_is_undef(tx->regs.t[tx->num_scratch])) + tx->regs.t[tx->num_scratch] = ureg_DECL_local_temporary(tx->ureg); + return tx->regs.t[tx->num_scratch++]; +} + +static inline struct ureg_dst +tx_scratch_scalar(struct shader_translator *tx) +{ + return ureg_writemask(tx_scratch(tx), TGSI_WRITEMASK_X); +} + +static inline struct ureg_src +tx_src_scalar(struct ureg_dst dst) +{ + struct ureg_src src = ureg_src(dst); + int c = ffs(dst.WriteMask) - 1; + if (dst.WriteMask == (1 << c)) + src = ureg_scalar(src, c); + return src; +} + +static inline void +tx_temp_alloc(struct shader_translator *tx, INT idx) +{ + assert(idx >= 0); + if (idx >= tx->num_temp) { + unsigned k = tx->num_temp; + unsigned n = idx + 1; + tx->regs.r = REALLOC(tx->regs.r, + k * sizeof(tx->regs.r[0]), + n * sizeof(tx->regs.r[0])); + for (; k < n; ++k) + tx->regs.r[k] = ureg_dst_undef(); + tx->num_temp = n; + } + if (ureg_dst_is_undef(tx->regs.r[idx])) + tx->regs.r[idx] = ureg_DECL_temporary(tx->ureg); +} + +static inline void +tx_addr_alloc(struct shader_translator *tx, INT idx) +{ + assert(idx == 0); + if (ureg_dst_is_undef(tx->regs.address)) + tx->regs.address = ureg_DECL_address(tx->ureg); + if (ureg_dst_is_undef(tx->regs.a0)) + tx->regs.a0 = ureg_DECL_temporary(tx->ureg); +} + +/* NOTE: It's not very clear on which ps1.1-ps1.3 instructions + * the projection should be applied on the texture. It doesn't + * apply on texkill. + * The doc is very imprecise here (it says the projection is done + * before rasterization, thus in vs, which seems wrong since ps instructions + * are affected differently) + * For now we only apply to the ps TEX instruction and TEXBEM. + * Perhaps some other instructions would need it */ +static inline void +apply_ps1x_projection(struct shader_translator *tx, struct ureg_dst dst, + struct ureg_src src, INT idx) +{ + struct ureg_dst tmp; + unsigned dim = 1 + ((tx->info->projected >> (2 * idx)) & 3); + + /* no projection */ + if (dim == 1) { + ureg_MOV(tx->ureg, dst, src); + } else { + tmp = tx_scratch_scalar(tx); + ureg_RCP(tx->ureg, tmp, ureg_scalar(src, dim-1)); + ureg_MUL(tx->ureg, dst, tx_src_scalar(tmp), src); + } +} + +static inline void +TEX_with_ps1x_projection(struct shader_translator *tx, struct ureg_dst dst, + unsigned target, struct ureg_src src0, + struct ureg_src src1, INT idx) +{ + unsigned dim = 1 + ((tx->info->projected >> (2 * idx)) & 3); + struct ureg_dst tmp; + boolean shadow = !!(tx->info->sampler_mask_shadow & (1 << idx)); + + /* dim == 1: no projection + * Looks like must be disabled when it makes no + * sense according the texture dimensions + */ + if (dim == 1 || (dim <= target && !shadow)) { + ureg_TEX(tx->ureg, dst, target, src0, src1); + } else if (dim == 4) { + ureg_TXP(tx->ureg, dst, target, src0, src1); + } else { + tmp = tx_scratch(tx); + apply_ps1x_projection(tx, tmp, src0, idx); + ureg_TEX(tx->ureg, dst, target, ureg_src(tmp), src1); + } +} + +static inline void +tx_texcoord_alloc(struct shader_translator *tx, INT idx) +{ + assert(IS_PS); + assert(idx >= 0 && idx < ARRAY_SIZE(tx->regs.vT)); + if (ureg_src_is_undef(tx->regs.vT[idx])) + tx->regs.vT[idx] = ureg_DECL_fs_input(tx->ureg, tx->texcoord_sn, idx, + TGSI_INTERPOLATE_PERSPECTIVE); +} + +static inline unsigned * +tx_bgnloop(struct shader_translator *tx) +{ + tx->loop_depth++; + if (tx->loop_depth_max < tx->loop_depth) + tx->loop_depth_max = tx->loop_depth; + assert(tx->loop_depth < NINE_MAX_LOOP_DEPTH); + return &tx->loop_labels[tx->loop_depth - 1]; +} + +static inline unsigned * +tx_endloop(struct shader_translator *tx) +{ + assert(tx->loop_depth); + tx->loop_depth--; + ureg_fixup_label(tx->ureg, tx->loop_labels[tx->loop_depth], + ureg_get_instruction_number(tx->ureg)); + return &tx->loop_labels[tx->loop_depth]; +} + +static struct ureg_dst +tx_get_loopctr(struct shader_translator *tx, boolean loop_or_rep) +{ + const unsigned l = tx->loop_depth - 1; + + if (!tx->loop_depth) + { + DBG("loop counter requested outside of loop\n"); + return ureg_dst_undef(); + } + + if (ureg_dst_is_undef(tx->regs.rL[l])) { + /* loop or rep ctr creation */ + tx->regs.rL[l] = ureg_DECL_local_temporary(tx->ureg); + tx->loop_or_rep[l] = loop_or_rep; + } + /* loop - rep - endloop - endrep not allowed */ + assert(tx->loop_or_rep[l] == loop_or_rep); + + return tx->regs.rL[l]; +} + +static struct ureg_src +tx_get_loopal(struct shader_translator *tx) +{ + int loop_level = tx->loop_depth - 1; + + while (loop_level >= 0) { + /* handle loop - rep - endrep - endloop case */ + if (tx->loop_or_rep[loop_level]) + /* the value is in the loop counter y component (nine implementation) */ + return ureg_scalar(ureg_src(tx->regs.rL[loop_level]), TGSI_SWIZZLE_Y); + loop_level--; + } + + DBG("aL counter requested outside of loop\n"); + return ureg_src_undef(); +} + +static inline unsigned * +tx_cond(struct shader_translator *tx) +{ + assert(tx->cond_depth <= NINE_MAX_COND_DEPTH); + tx->cond_depth++; + return &tx->cond_labels[tx->cond_depth - 1]; +} + +static inline unsigned * +tx_elsecond(struct shader_translator *tx) +{ + assert(tx->cond_depth); + return &tx->cond_labels[tx->cond_depth - 1]; +} + +static inline void +tx_endcond(struct shader_translator *tx) +{ + assert(tx->cond_depth); + tx->cond_depth--; + ureg_fixup_label(tx->ureg, tx->cond_labels[tx->cond_depth], + ureg_get_instruction_number(tx->ureg)); +} + +static inline struct ureg_dst +nine_ureg_dst_register(unsigned file, int index) +{ + return ureg_dst(ureg_src_register(file, index)); +} + +static inline struct ureg_src +nine_get_position_input(struct shader_translator *tx) +{ + struct ureg_program *ureg = tx->ureg; + + if (tx->wpos_is_sysval) + return ureg_DECL_system_value(ureg, TGSI_SEMANTIC_POSITION, 0); + else + return ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_POSITION, + 0, TGSI_INTERPOLATE_LINEAR); +} + +static struct ureg_src +tx_src_param(struct shader_translator *tx, const struct sm1_src_param *param) +{ + struct ureg_program *ureg = tx->ureg; + struct ureg_src src; + struct ureg_dst tmp; + + assert(!param->rel || (IS_VS && param->file == D3DSPR_CONST) || + (D3DSPR_ADDR && tx->version.major == 3)); + + switch (param->file) + { + case D3DSPR_TEMP: + tx_temp_alloc(tx, param->idx); + src = ureg_src(tx->regs.r[param->idx]); + break; + /* case D3DSPR_TEXTURE: == D3DSPR_ADDR */ + case D3DSPR_ADDR: + if (IS_VS) { + assert(param->idx == 0); + /* the address register (vs only) must be + * assigned before use */ + assert(!ureg_dst_is_undef(tx->regs.a0)); + /* Round to lowest for vs1.1 (contrary to the doc), else + * round to nearest */ + if (tx->version.major < 2 && tx->version.minor < 2) + ureg_ARL(ureg, tx->regs.address, ureg_src(tx->regs.a0)); + else + ureg_ARR(ureg, tx->regs.address, ureg_src(tx->regs.a0)); + src = ureg_src(tx->regs.address); + } else { + if (tx->version.major < 2 && tx->version.minor < 4) { + /* no subroutines, so should be defined */ + src = ureg_src(tx->regs.tS[param->idx]); + } else { + tx_texcoord_alloc(tx, param->idx); + src = tx->regs.vT[param->idx]; + } + } + break; + case D3DSPR_INPUT: + if (IS_VS) { + src = ureg_src_register(TGSI_FILE_INPUT, param->idx); + } else { + if (tx->version.major < 3) { + src = ureg_DECL_fs_input_cyl_centroid( + ureg, TGSI_SEMANTIC_COLOR, param->idx, + TGSI_INTERPOLATE_COLOR, 0, + tx->info->force_color_in_centroid ? + TGSI_INTERPOLATE_LOC_CENTROID : 0, + 0, 1); + } else { + if(param->rel) { + /* Copy all inputs (non consecutive) + * to temp array (consecutive). + * This is not good for performance. + * A better way would be to have inputs + * consecutive (would need implement alternative + * way to match vs outputs and ps inputs). + * However even with the better way, the temp array + * copy would need to be used if some inputs + * are not GENERIC or if they have different + * interpolation flag. */ + if (ureg_src_is_undef(tx->regs.v_consecutive)) { + int i; + tx->regs.v_consecutive = ureg_src(ureg_DECL_array_temporary(ureg, 10, 0)); + for (i = 0; i < 10; i++) { + if (!ureg_src_is_undef(tx->regs.v[i])) + ureg_MOV(ureg, ureg_dst_array_offset(ureg_dst(tx->regs.v_consecutive), i), tx->regs.v[i]); + else + ureg_MOV(ureg, ureg_dst_array_offset(ureg_dst(tx->regs.v_consecutive), i), ureg_imm4f(ureg, 0.0f, 0.0f, 0.0f, 1.0f)); + } + } + src = ureg_src_array_offset(tx->regs.v_consecutive, param->idx); + } else { + assert(param->idx < ARRAY_SIZE(tx->regs.v)); + src = tx->regs.v[param->idx]; + } + } + } + if (param->rel) + src = ureg_src_indirect(src, tx_src_param(tx, param->rel)); + break; + case D3DSPR_PREDICATE: + if (ureg_dst_is_undef(tx->regs.predicate)) { + /* Forbidden to use the predicate register before being set */ + tx->failure = TRUE; + tx->regs.predicate = ureg_DECL_temporary(tx->ureg); + } + src = ureg_src(tx->regs.predicate); + break; + case D3DSPR_SAMPLER: + assert(param->mod == NINED3DSPSM_NONE); + assert(param->swizzle == NINED3DSP_NOSWIZZLE); + src = ureg_DECL_sampler(ureg, param->idx); + break; + case D3DSPR_CONST: + if (param->rel || !tx_lconstf(tx, &src, param->idx)) { + src = nine_float_constant_src(tx, param->idx); + if (param->rel) { + tx->indirect_const_access = TRUE; + src = ureg_src_indirect(src, tx_src_param(tx, param->rel)); + } + } + if (!IS_VS && tx->version.major < 2) { + /* ps 1.X clamps constants */ + tmp = tx_scratch(tx); + ureg_MIN(ureg, tmp, src, ureg_imm1f(ureg, 1.0f)); + ureg_MAX(ureg, tmp, ureg_src(tmp), ureg_imm1f(ureg, -1.0f)); + src = ureg_src(tmp); + } + break; + case D3DSPR_CONST2: + case D3DSPR_CONST3: + case D3DSPR_CONST4: + DBG("CONST2/3/4 should have been collapsed into D3DSPR_CONST !\n"); + assert(!"CONST2/3/4"); + src = ureg_imm1f(ureg, 0.0f); + break; + case D3DSPR_CONSTINT: + /* relative adressing only possible for float constants in vs */ + if (!tx_lconsti(tx, &src, param->idx)) + src = nine_integer_constant_src(tx, param->idx); + break; + case D3DSPR_CONSTBOOL: + if (!tx_lconstb(tx, &src, param->idx)) + src = nine_boolean_constant_src(tx, param->idx); + break; + case D3DSPR_LOOP: + if (ureg_dst_is_undef(tx->regs.address)) + tx->regs.address = ureg_DECL_address(ureg); + if (!tx->native_integers) + ureg_ARR(ureg, tx->regs.address, tx_get_loopal(tx)); + else + ureg_UARL(ureg, tx->regs.address, tx_get_loopal(tx)); + src = ureg_src(tx->regs.address); + break; + case D3DSPR_MISCTYPE: + switch (param->idx) { + case D3DSMO_POSITION: + if (ureg_src_is_undef(tx->regs.vPos)) + tx->regs.vPos = nine_get_position_input(tx); + if (tx->shift_wpos) { + /* TODO: do this only once */ + struct ureg_dst wpos = tx_scratch(tx); + ureg_ADD(ureg, wpos, tx->regs.vPos, + ureg_imm4f(ureg, -0.5f, -0.5f, 0.0f, 0.0f)); + src = ureg_src(wpos); + } else { + src = tx->regs.vPos; + } + break; + case D3DSMO_FACE: + if (ureg_src_is_undef(tx->regs.vFace)) { + if (tx->face_is_sysval_integer) { + tmp = ureg_DECL_temporary(ureg); + tx->regs.vFace = + ureg_DECL_system_value(ureg, TGSI_SEMANTIC_FACE, 0); + + /* convert bool to float */ + ureg_UCMP(ureg, tmp, ureg_scalar(tx->regs.vFace, TGSI_SWIZZLE_X), + ureg_imm1f(ureg, 1), ureg_imm1f(ureg, -1)); + tx->regs.vFace = ureg_src(tmp); + } else { + tx->regs.vFace = ureg_DECL_fs_input(ureg, + TGSI_SEMANTIC_FACE, 0, + TGSI_INTERPOLATE_CONSTANT); + } + tx->regs.vFace = ureg_scalar(tx->regs.vFace, TGSI_SWIZZLE_X); + } + src = tx->regs.vFace; + break; + default: + assert(!"invalid src D3DSMO"); + break; + } + break; + case D3DSPR_TEMPFLOAT16: + break; + default: + assert(!"invalid src D3DSPR"); + } + + switch (param->mod) { + case NINED3DSPSM_DW: + tmp = tx_scratch(tx); + /* NOTE: app is not allowed to read w with this modifier */ + ureg_RCP(ureg, ureg_writemask(tmp, NINED3DSP_WRITEMASK_3), ureg_scalar(src, TGSI_SWIZZLE_W)); + ureg_MUL(ureg, tmp, src, ureg_swizzle(ureg_src(tmp), NINE_SWIZZLE4(W,W,W,W))); + src = ureg_src(tmp); + break; + case NINED3DSPSM_DZ: + tmp = tx_scratch(tx); + /* NOTE: app is not allowed to read z with this modifier */ + ureg_RCP(ureg, ureg_writemask(tmp, NINED3DSP_WRITEMASK_2), ureg_scalar(src, TGSI_SWIZZLE_Z)); + ureg_MUL(ureg, tmp, src, ureg_swizzle(ureg_src(tmp), NINE_SWIZZLE4(Z,Z,Z,Z))); + src = ureg_src(tmp); + break; + default: + break; + } + + if (param->swizzle != NINED3DSP_NOSWIZZLE) + src = ureg_swizzle(src, + (param->swizzle >> 0) & 0x3, + (param->swizzle >> 2) & 0x3, + (param->swizzle >> 4) & 0x3, + (param->swizzle >> 6) & 0x3); + + switch (param->mod) { + case NINED3DSPSM_ABS: + src = ureg_abs(src); + break; + case NINED3DSPSM_ABSNEG: + src = ureg_negate(ureg_abs(src)); + break; + case NINED3DSPSM_NEG: + src = ureg_negate(src); + break; + case NINED3DSPSM_BIAS: + tmp = tx_scratch(tx); + ureg_ADD(ureg, tmp, src, ureg_imm1f(ureg, -0.5f)); + src = ureg_src(tmp); + break; + case NINED3DSPSM_BIASNEG: + tmp = tx_scratch(tx); + ureg_ADD(ureg, tmp, ureg_imm1f(ureg, 0.5f), ureg_negate(src)); + src = ureg_src(tmp); + break; + case NINED3DSPSM_NOT: + if (tx->native_integers && param->file == D3DSPR_CONSTBOOL) { + tmp = tx_scratch(tx); + ureg_NOT(ureg, tmp, src); + src = ureg_src(tmp); + break; + } else { /* predicate */ + tmp = tx_scratch(tx); + ureg_ADD(ureg, tmp, ureg_imm1f(ureg, 1.0f), ureg_negate(src)); + src = ureg_src(tmp); + } + /* fall through */ + case NINED3DSPSM_COMP: + tmp = tx_scratch(tx); + ureg_ADD(ureg, tmp, ureg_imm1f(ureg, 1.0f), ureg_negate(src)); + src = ureg_src(tmp); + break; + case NINED3DSPSM_DZ: + case NINED3DSPSM_DW: + /* Already handled*/ + break; + case NINED3DSPSM_SIGN: + tmp = tx_scratch(tx); + ureg_MAD(ureg, tmp, src, ureg_imm1f(ureg, 2.0f), ureg_imm1f(ureg, -1.0f)); + src = ureg_src(tmp); + break; + case NINED3DSPSM_SIGNNEG: + tmp = tx_scratch(tx); + ureg_MAD(ureg, tmp, src, ureg_imm1f(ureg, -2.0f), ureg_imm1f(ureg, 1.0f)); + src = ureg_src(tmp); + break; + case NINED3DSPSM_X2: + tmp = tx_scratch(tx); + ureg_ADD(ureg, tmp, src, src); + src = ureg_src(tmp); + break; + case NINED3DSPSM_X2NEG: + tmp = tx_scratch(tx); + ureg_ADD(ureg, tmp, src, src); + src = ureg_negate(ureg_src(tmp)); + break; + default: + assert(param->mod == NINED3DSPSM_NONE); + break; + } + + return src; +} + +static struct ureg_dst +_tx_dst_param(struct shader_translator *tx, const struct sm1_dst_param *param) +{ + struct ureg_dst dst; + + switch (param->file) + { + case D3DSPR_TEMP: + assert(!param->rel); + tx_temp_alloc(tx, param->idx); + dst = tx->regs.r[param->idx]; + break; + /* case D3DSPR_TEXTURE: == D3DSPR_ADDR */ + case D3DSPR_ADDR: + assert(!param->rel); + if (tx->version.major < 2 && !IS_VS) { + if (ureg_dst_is_undef(tx->regs.tS[param->idx])) + tx->regs.tS[param->idx] = ureg_DECL_temporary(tx->ureg); + dst = tx->regs.tS[param->idx]; + } else + if (!IS_VS && tx->insn.opcode == D3DSIO_TEXKILL) { /* maybe others, too */ + tx_texcoord_alloc(tx, param->idx); + dst = ureg_dst(tx->regs.vT[param->idx]); + } else { + tx_addr_alloc(tx, param->idx); + dst = tx->regs.a0; + } + break; + case D3DSPR_RASTOUT: + assert(!param->rel); + switch (param->idx) { + case 0: + if (ureg_dst_is_undef(tx->regs.oPos)) + tx->regs.oPos = + ureg_DECL_output(tx->ureg, TGSI_SEMANTIC_POSITION, 0); + dst = tx->regs.oPos; + break; + case 1: + if (ureg_dst_is_undef(tx->regs.oFog)) + tx->regs.oFog = + ureg_saturate(ureg_DECL_output(tx->ureg, TGSI_SEMANTIC_GENERIC, 16)); + dst = tx->regs.oFog; + break; + case 2: + if (ureg_dst_is_undef(tx->regs.oPts)) + tx->regs.oPts = ureg_DECL_temporary(tx->ureg); + dst = tx->regs.oPts; + break; + default: + assert(0); + break; + } + break; + /* case D3DSPR_TEXCRDOUT: == D3DSPR_OUTPUT */ + case D3DSPR_OUTPUT: + if (tx->version.major < 3) { + assert(!param->rel); + dst = ureg_DECL_output(tx->ureg, tx->texcoord_sn, param->idx); + } else { + assert(!param->rel); /* TODO */ + assert(param->idx < ARRAY_SIZE(tx->regs.o)); + dst = tx->regs.o[param->idx]; + } + break; + case D3DSPR_ATTROUT: /* VS */ + case D3DSPR_COLOROUT: /* PS */ + assert(param->idx >= 0 && param->idx < 4); + assert(!param->rel); + tx->info->rt_mask |= 1 << param->idx; + if (ureg_dst_is_undef(tx->regs.oCol[param->idx])) { + /* ps < 3: oCol[0] will have fog blending afterward */ + if (!IS_VS && tx->version.major < 3 && param->idx == 0) { + tx->regs.oCol[0] = ureg_DECL_temporary(tx->ureg); + } else { + tx->regs.oCol[param->idx] = + ureg_DECL_output(tx->ureg, TGSI_SEMANTIC_COLOR, param->idx); + } + } + dst = tx->regs.oCol[param->idx]; + if (IS_VS && tx->version.major < 3) + dst = ureg_saturate(dst); + break; + case D3DSPR_DEPTHOUT: + assert(!param->rel); + if (ureg_dst_is_undef(tx->regs.oDepth)) + tx->regs.oDepth = + ureg_DECL_output_masked(tx->ureg, TGSI_SEMANTIC_POSITION, 0, + TGSI_WRITEMASK_Z, 0, 1); + dst = tx->regs.oDepth; /* XXX: must write .z component */ + break; + case D3DSPR_PREDICATE: + if (ureg_dst_is_undef(tx->regs.predicate)) + tx->regs.predicate = ureg_DECL_temporary(tx->ureg); + dst = tx->regs.predicate; + break; + case D3DSPR_TEMPFLOAT16: + DBG("unhandled D3DSPR: %u\n", param->file); + break; + default: + assert(!"invalid dst D3DSPR"); + break; + } + if (param->rel) + dst = ureg_dst_indirect(dst, tx_src_param(tx, param->rel)); + + if (param->mask != NINED3DSP_WRITEMASK_ALL) + dst = ureg_writemask(dst, param->mask); + if (param->mod & NINED3DSPDM_SATURATE) + dst = ureg_saturate(dst); + + if (tx->predicated_activated) { + tx->regs.predicate_dst = dst; + dst = tx->regs.predicate_tmp; + } + + return dst; +} + +static struct ureg_dst +tx_dst_param(struct shader_translator *tx, const struct sm1_dst_param *param) +{ + if (param->shift) { + tx->regs.tdst = ureg_writemask(tx_scratch(tx), param->mask); + return tx->regs.tdst; + } + return _tx_dst_param(tx, param); +} + +static void +tx_apply_dst0_modifiers(struct shader_translator *tx) +{ + struct ureg_dst rdst; + float f; + + if (!tx->insn.ndst || !tx->insn.dst[0].shift || tx->insn.opcode == D3DSIO_TEXKILL) + return; + rdst = _tx_dst_param(tx, &tx->insn.dst[0]); + + assert(rdst.File != TGSI_FILE_ADDRESS); /* this probably isn't possible */ + + if (tx->insn.dst[0].shift < 0) + f = 1.0f / (1 << -tx->insn.dst[0].shift); + else + f = 1 << tx->insn.dst[0].shift; + + ureg_MUL(tx->ureg, rdst, ureg_src(tx->regs.tdst), ureg_imm1f(tx->ureg, f)); +} + +static struct ureg_src +tx_dst_param_as_src(struct shader_translator *tx, const struct sm1_dst_param *param) +{ + struct ureg_src src; + + assert(!param->shift); + assert(!(param->mod & NINED3DSPDM_SATURATE)); + + switch (param->file) { + case D3DSPR_INPUT: + if (IS_VS) { + src = ureg_src_register(TGSI_FILE_INPUT, param->idx); + } else { + assert(!param->rel); + assert(param->idx < ARRAY_SIZE(tx->regs.v)); + src = tx->regs.v[param->idx]; + } + break; + default: + src = ureg_src(tx_dst_param(tx, param)); + break; + } + if (param->rel) + src = ureg_src_indirect(src, tx_src_param(tx, param->rel)); + + if (!param->mask) + WARN("mask is 0, using identity swizzle\n"); + + if (param->mask && param->mask != NINED3DSP_WRITEMASK_ALL) { + char s[4]; + int n; + int c; + for (n = 0, c = 0; c < 4; ++c) + if (param->mask & (1 << c)) + s[n++] = c; + assert(n); + for (c = n; c < 4; ++c) + s[c] = s[n - 1]; + src = ureg_swizzle(src, s[0], s[1], s[2], s[3]); + } + return src; +} + +static HRESULT +NineTranslateInstruction_Mkxn(struct shader_translator *tx, const unsigned k, const unsigned n) +{ + struct ureg_program *ureg = tx->ureg; + struct ureg_dst dst; + struct ureg_src src[2]; + struct sm1_src_param *src_mat = &tx->insn.src[1]; + unsigned i; + + dst = tx_dst_param(tx, &tx->insn.dst[0]); + src[0] = tx_src_param(tx, &tx->insn.src[0]); + + for (i = 0; i < n; i++) + { + const unsigned m = (1 << i); + + src[1] = tx_src_param(tx, src_mat); + src_mat->idx++; + + if (!(dst.WriteMask & m)) + continue; + + /* XXX: src == dst case ? */ + + switch (k) { + case 3: + ureg_DP3(ureg, ureg_writemask(dst, m), src[0], src[1]); + break; + case 4: + ureg_DP4(ureg, ureg_writemask(dst, m), src[0], src[1]); + break; + default: + DBG("invalid operation: M%ux%u\n", m, n); + break; + } + } + + return D3D_OK; +} + +#define VNOTSUPPORTED 0, 0 +#define V(maj, min) (((maj) << 8) | (min)) + +static inline const char * +d3dsio_to_string( unsigned opcode ) +{ + static const char *names[] = { + "NOP", + "MOV", + "ADD", + "SUB", + "MAD", + "MUL", + "RCP", + "RSQ", + "DP3", + "DP4", + "MIN", + "MAX", + "SLT", + "SGE", + "EXP", + "LOG", + "LIT", + "DST", + "LRP", + "FRC", + "M4x4", + "M4x3", + "M3x4", + "M3x3", + "M3x2", + "CALL", + "CALLNZ", + "LOOP", + "RET", + "ENDLOOP", + "LABEL", + "DCL", + "POW", + "CRS", + "SGN", + "ABS", + "NRM", + "SINCOS", + "REP", + "ENDREP", + "IF", + "IFC", + "ELSE", + "ENDIF", + "BREAK", + "BREAKC", + "MOVA", + "DEFB", + "DEFI", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "TEXCOORD", + "TEXKILL", + "TEX", + "TEXBEM", + "TEXBEML", + "TEXREG2AR", + "TEXREG2GB", + "TEXM3x2PAD", + "TEXM3x2TEX", + "TEXM3x3PAD", + "TEXM3x3TEX", + NULL, + "TEXM3x3SPEC", + "TEXM3x3VSPEC", + "EXPP", + "LOGP", + "CND", + "DEF", + "TEXREG2RGB", + "TEXDP3TEX", + "TEXM3x2DEPTH", + "TEXDP3", + "TEXM3x3", + "TEXDEPTH", + "CMP", + "BEM", + "DP2ADD", + "DSX", + "DSY", + "TEXLDD", + "SETP", + "TEXLDL", + "BREAKP" + }; + + if (opcode < ARRAY_SIZE(names)) return names[opcode]; + + switch (opcode) { + case D3DSIO_PHASE: return "PHASE"; + case D3DSIO_COMMENT: return "COMMENT"; + case D3DSIO_END: return "END"; + default: + return NULL; + } +} + +#define NULL_INSTRUCTION { 0, { 0, 0 }, { 0, 0 }, 0, 0, NULL } +#define IS_VALID_INSTRUCTION(inst) ((inst).vert_version.min | \ + (inst).vert_version.max | \ + (inst).frag_version.min | \ + (inst).frag_version.max) + +#define SPECIAL(name) \ + NineTranslateInstruction_##name + +#define DECL_SPECIAL(name) \ + static HRESULT \ + NineTranslateInstruction_##name( struct shader_translator *tx ) + +static HRESULT +NineTranslateInstruction_Generic(struct shader_translator *); + +DECL_SPECIAL(NOP) +{ + /* Nothing to do. NOP was used to avoid hangs + * with very old d3d drivers. */ + return D3D_OK; +} + +DECL_SPECIAL(SUB) +{ + struct ureg_program *ureg = tx->ureg; + struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); + struct ureg_src src0 = tx_src_param(tx, &tx->insn.src[0]); + struct ureg_src src1 = tx_src_param(tx, &tx->insn.src[1]); + + ureg_ADD(ureg, dst, src0, ureg_negate(src1)); + return D3D_OK; +} + +DECL_SPECIAL(ABS) +{ + struct ureg_program *ureg = tx->ureg; + struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); + struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]); + + ureg_MOV(ureg, dst, ureg_abs(src)); + return D3D_OK; +} + +DECL_SPECIAL(XPD) +{ + struct ureg_program *ureg = tx->ureg; + struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); + struct ureg_src src0 = tx_src_param(tx, &tx->insn.src[0]); + struct ureg_src src1 = tx_src_param(tx, &tx->insn.src[1]); + + ureg_MUL(ureg, ureg_writemask(dst, TGSI_WRITEMASK_XYZ), + ureg_swizzle(src0, TGSI_SWIZZLE_Y, TGSI_SWIZZLE_Z, + TGSI_SWIZZLE_X, 0), + ureg_swizzle(src1, TGSI_SWIZZLE_Z, TGSI_SWIZZLE_X, + TGSI_SWIZZLE_Y, 0)); + ureg_MAD(ureg, ureg_writemask(dst, TGSI_WRITEMASK_XYZ), + ureg_swizzle(src0, TGSI_SWIZZLE_Z, TGSI_SWIZZLE_X, + TGSI_SWIZZLE_Y, 0), + ureg_negate(ureg_swizzle(src1, TGSI_SWIZZLE_Y, + TGSI_SWIZZLE_Z, TGSI_SWIZZLE_X, 0)), + ureg_src(dst)); + ureg_MOV(ureg, ureg_writemask(dst, TGSI_WRITEMASK_W), + ureg_imm1f(ureg, 1)); + return D3D_OK; +} + +DECL_SPECIAL(M4x4) +{ + return NineTranslateInstruction_Mkxn(tx, 4, 4); +} + +DECL_SPECIAL(M4x3) +{ + return NineTranslateInstruction_Mkxn(tx, 4, 3); +} + +DECL_SPECIAL(M3x4) +{ + return NineTranslateInstruction_Mkxn(tx, 3, 4); +} + +DECL_SPECIAL(M3x3) +{ + return NineTranslateInstruction_Mkxn(tx, 3, 3); +} + +DECL_SPECIAL(M3x2) +{ + return NineTranslateInstruction_Mkxn(tx, 3, 2); +} + +DECL_SPECIAL(CMP) +{ + ureg_CMP(tx->ureg, tx_dst_param(tx, &tx->insn.dst[0]), + tx_src_param(tx, &tx->insn.src[0]), + tx_src_param(tx, &tx->insn.src[2]), + tx_src_param(tx, &tx->insn.src[1])); + return D3D_OK; +} + +DECL_SPECIAL(CND) +{ + struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); + struct ureg_dst cgt; + struct ureg_src cnd; + + /* the coissue flag was a tip for compilers to advise to + * execute two operations at the same time, in cases + * the two executions had same dst with different channels. + * It has no effect on current hw. However it seems CND + * is affected. The handling of this very specific case + * handled below mimick wine behaviour */ + if (tx->insn.coissue && tx->version.major == 1 && tx->version.minor < 4 && tx->insn.dst[0].mask != NINED3DSP_WRITEMASK_3) { + ureg_MOV(tx->ureg, + dst, tx_src_param(tx, &tx->insn.src[1])); + return D3D_OK; + } + + cnd = tx_src_param(tx, &tx->insn.src[0]); + cgt = tx_scratch(tx); + + if (tx->version.major == 1 && tx->version.minor < 4) + cnd = ureg_scalar(cnd, TGSI_SWIZZLE_W); + + ureg_SGT(tx->ureg, cgt, cnd, ureg_imm1f(tx->ureg, 0.5f)); + + ureg_CMP(tx->ureg, dst, ureg_negate(ureg_src(cgt)), + tx_src_param(tx, &tx->insn.src[1]), + tx_src_param(tx, &tx->insn.src[2])); + return D3D_OK; +} + +DECL_SPECIAL(CALL) +{ + assert(tx->insn.src[0].idx < tx->num_inst_labels); + ureg_CAL(tx->ureg, &tx->inst_labels[tx->insn.src[0].idx]); + return D3D_OK; +} + +DECL_SPECIAL(CALLNZ) +{ + struct ureg_program *ureg = tx->ureg; + struct ureg_src src = tx_src_param(tx, &tx->insn.src[1]); + + if (!tx->native_integers) + ureg_IF(ureg, src, tx_cond(tx)); + else + ureg_UIF(ureg, src, tx_cond(tx)); + ureg_CAL(ureg, &tx->inst_labels[tx->insn.src[0].idx]); + tx_endcond(tx); + ureg_ENDIF(ureg); + return D3D_OK; +} + +DECL_SPECIAL(LOOP) +{ + struct ureg_program *ureg = tx->ureg; + unsigned *label; + struct ureg_src src = tx_src_param(tx, &tx->insn.src[1]); + struct ureg_dst ctr; + struct ureg_dst tmp; + struct ureg_src ctrx; + + label = tx_bgnloop(tx); + ctr = tx_get_loopctr(tx, TRUE); + ctrx = ureg_scalar(ureg_src(ctr), TGSI_SWIZZLE_X); + + /* src: num_iterations - start_value of al - step for al - 0 */ + ureg_MOV(ureg, ctr, src); + ureg_BGNLOOP(tx->ureg, label); + tmp = tx_scratch_scalar(tx); + /* Initially ctr.x contains the number of iterations. + * ctr.y will contain the updated value of al. + * We decrease ctr.x at the end of every iteration, + * and stop when it reaches 0. */ + + if (!tx->native_integers) { + /* case src and ctr contain floats */ + /* to avoid precision issue, we stop when ctr <= 0.5 */ + ureg_SGE(ureg, tmp, ureg_imm1f(ureg, 0.5f), ctrx); + ureg_IF(ureg, tx_src_scalar(tmp), tx_cond(tx)); + } else { + /* case src and ctr contain integers */ + ureg_ISGE(ureg, tmp, ureg_imm1i(ureg, 0), ctrx); + ureg_UIF(ureg, tx_src_scalar(tmp), tx_cond(tx)); + } + ureg_BRK(ureg); + tx_endcond(tx); + ureg_ENDIF(ureg); + return D3D_OK; +} + +DECL_SPECIAL(RET) +{ + /* RET as a last instruction could be safely ignored. + * Remove it to prevent crashes/warnings in case underlying + * driver doesn't implement arbitrary returns. + */ + if (*(tx->parse_next) != NINED3DSP_END) { + ureg_RET(tx->ureg); + } + return D3D_OK; +} + +DECL_SPECIAL(ENDLOOP) +{ + struct ureg_program *ureg = tx->ureg; + struct ureg_dst ctr = tx_get_loopctr(tx, TRUE); + struct ureg_dst dst_ctrx, dst_al; + struct ureg_src src_ctr, al_counter; + + dst_ctrx = ureg_writemask(ctr, NINED3DSP_WRITEMASK_0); + dst_al = ureg_writemask(ctr, NINED3DSP_WRITEMASK_1); + src_ctr = ureg_src(ctr); + al_counter = ureg_scalar(src_ctr, TGSI_SWIZZLE_Z); + + /* ctr.x -= 1 + * ctr.y (aL) += step */ + if (!tx->native_integers) { + ureg_ADD(ureg, dst_ctrx, src_ctr, ureg_imm1f(ureg, -1.0f)); + ureg_ADD(ureg, dst_al, src_ctr, al_counter); + } else { + ureg_UADD(ureg, dst_ctrx, src_ctr, ureg_imm1i(ureg, -1)); + ureg_UADD(ureg, dst_al, src_ctr, al_counter); + } + ureg_ENDLOOP(tx->ureg, tx_endloop(tx)); + return D3D_OK; +} + +DECL_SPECIAL(LABEL) +{ + unsigned k = tx->num_inst_labels; + unsigned n = tx->insn.src[0].idx; + assert(n < 2048); + if (n >= k) + tx->inst_labels = REALLOC(tx->inst_labels, + k * sizeof(tx->inst_labels[0]), + n * sizeof(tx->inst_labels[0])); + + tx->inst_labels[n] = ureg_get_instruction_number(tx->ureg); + return D3D_OK; +} + +DECL_SPECIAL(SINCOS) +{ + struct ureg_program *ureg = tx->ureg; + struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); + struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]); + struct ureg_dst tmp = tx_scratch_scalar(tx); + + assert(!(dst.WriteMask & 0xc)); + + /* Copying to a temporary register avoids src/dst aliasing. + * src is supposed to have replicated swizzle. */ + ureg_MOV(ureg, tmp, src); + + /* z undefined, w untouched */ + ureg_COS(ureg, ureg_writemask(dst, TGSI_WRITEMASK_X), + tx_src_scalar(tmp)); + ureg_SIN(ureg, ureg_writemask(dst, TGSI_WRITEMASK_Y), + tx_src_scalar(tmp)); + return D3D_OK; +} + +DECL_SPECIAL(SGN) +{ + ureg_SSG(tx->ureg, + tx_dst_param(tx, &tx->insn.dst[0]), + tx_src_param(tx, &tx->insn.src[0])); + return D3D_OK; +} + +DECL_SPECIAL(REP) +{ + struct ureg_program *ureg = tx->ureg; + unsigned *label; + struct ureg_src rep = tx_src_param(tx, &tx->insn.src[0]); + struct ureg_dst ctr; + struct ureg_dst tmp; + struct ureg_src ctrx; + + label = tx_bgnloop(tx); + ctr = ureg_writemask(tx_get_loopctr(tx, FALSE), NINED3DSP_WRITEMASK_0); + ctrx = ureg_scalar(ureg_src(ctr), TGSI_SWIZZLE_X); + + /* NOTE: rep must be constant, so we don't have to save the count */ + assert(rep.File == TGSI_FILE_CONSTANT || rep.File == TGSI_FILE_IMMEDIATE); + + /* rep: num_iterations - 0 - 0 - 0 */ + ureg_MOV(ureg, ctr, rep); + ureg_BGNLOOP(ureg, label); + tmp = tx_scratch_scalar(tx); + /* Initially ctr.x contains the number of iterations. + * We decrease ctr.x at the end of every iteration, + * and stop when it reaches 0. */ + + if (!tx->native_integers) { + /* case src and ctr contain floats */ + /* to avoid precision issue, we stop when ctr <= 0.5 */ + ureg_SGE(ureg, tmp, ureg_imm1f(ureg, 0.5f), ctrx); + ureg_IF(ureg, tx_src_scalar(tmp), tx_cond(tx)); + } else { + /* case src and ctr contain integers */ + ureg_ISGE(ureg, tmp, ureg_imm1i(ureg, 0), ctrx); + ureg_UIF(ureg, tx_src_scalar(tmp), tx_cond(tx)); + } + ureg_BRK(ureg); + tx_endcond(tx); + ureg_ENDIF(ureg); + + return D3D_OK; +} + +DECL_SPECIAL(ENDREP) +{ + struct ureg_program *ureg = tx->ureg; + struct ureg_dst ctr = tx_get_loopctr(tx, FALSE); + struct ureg_dst dst_ctrx = ureg_writemask(ctr, NINED3DSP_WRITEMASK_0); + struct ureg_src src_ctr = ureg_src(ctr); + + /* ctr.x -= 1 */ + if (!tx->native_integers) + ureg_ADD(ureg, dst_ctrx, src_ctr, ureg_imm1f(ureg, -1.0f)); + else + ureg_UADD(ureg, dst_ctrx, src_ctr, ureg_imm1i(ureg, -1)); + + ureg_ENDLOOP(tx->ureg, tx_endloop(tx)); + return D3D_OK; +} + +DECL_SPECIAL(ENDIF) +{ + tx_endcond(tx); + ureg_ENDIF(tx->ureg); + return D3D_OK; +} + +DECL_SPECIAL(IF) +{ + struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]); + + if (tx->native_integers && tx->insn.src[0].file == D3DSPR_CONSTBOOL) + ureg_UIF(tx->ureg, src, tx_cond(tx)); + else + ureg_IF(tx->ureg, src, tx_cond(tx)); + + return D3D_OK; +} + +static inline unsigned +sm1_insn_flags_to_tgsi_setop(BYTE flags) +{ + switch (flags) { + case NINED3DSHADER_REL_OP_GT: return TGSI_OPCODE_SGT; + case NINED3DSHADER_REL_OP_EQ: return TGSI_OPCODE_SEQ; + case NINED3DSHADER_REL_OP_GE: return TGSI_OPCODE_SGE; + case NINED3DSHADER_REL_OP_LT: return TGSI_OPCODE_SLT; + case NINED3DSHADER_REL_OP_NE: return TGSI_OPCODE_SNE; + case NINED3DSHADER_REL_OP_LE: return TGSI_OPCODE_SLE; + default: + assert(!"invalid comparison flags"); + return TGSI_OPCODE_SGT; + } +} + +DECL_SPECIAL(IFC) +{ + const unsigned cmp_op = sm1_insn_flags_to_tgsi_setop(tx->insn.flags); + struct ureg_src src[2]; + struct ureg_dst tmp = ureg_writemask(tx_scratch(tx), TGSI_WRITEMASK_X); + src[0] = tx_src_param(tx, &tx->insn.src[0]); + src[1] = tx_src_param(tx, &tx->insn.src[1]); + ureg_insn(tx->ureg, cmp_op, &tmp, 1, src, 2, 0); + ureg_IF(tx->ureg, ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X), tx_cond(tx)); + return D3D_OK; +} + +DECL_SPECIAL(ELSE) +{ + ureg_ELSE(tx->ureg, tx_elsecond(tx)); + return D3D_OK; +} + +DECL_SPECIAL(BREAKC) +{ + const unsigned cmp_op = sm1_insn_flags_to_tgsi_setop(tx->insn.flags); + struct ureg_src src[2]; + struct ureg_dst tmp = ureg_writemask(tx_scratch(tx), TGSI_WRITEMASK_X); + src[0] = tx_src_param(tx, &tx->insn.src[0]); + src[1] = tx_src_param(tx, &tx->insn.src[1]); + ureg_insn(tx->ureg, cmp_op, &tmp, 1, src, 2, 0); + ureg_IF(tx->ureg, ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X), tx_cond(tx)); + ureg_BRK(tx->ureg); + tx_endcond(tx); + ureg_ENDIF(tx->ureg); + return D3D_OK; +} + +static const char *sm1_declusage_names[] = +{ + [D3DDECLUSAGE_POSITION] = "POSITION", + [D3DDECLUSAGE_BLENDWEIGHT] = "BLENDWEIGHT", + [D3DDECLUSAGE_BLENDINDICES] = "BLENDINDICES", + [D3DDECLUSAGE_NORMAL] = "NORMAL", + [D3DDECLUSAGE_PSIZE] = "PSIZE", + [D3DDECLUSAGE_TEXCOORD] = "TEXCOORD", + [D3DDECLUSAGE_TANGENT] = "TANGENT", + [D3DDECLUSAGE_BINORMAL] = "BINORMAL", + [D3DDECLUSAGE_TESSFACTOR] = "TESSFACTOR", + [D3DDECLUSAGE_POSITIONT] = "POSITIONT", + [D3DDECLUSAGE_COLOR] = "COLOR", + [D3DDECLUSAGE_FOG] = "FOG", + [D3DDECLUSAGE_DEPTH] = "DEPTH", + [D3DDECLUSAGE_SAMPLE] = "SAMPLE" +}; + +static inline unsigned +sm1_to_nine_declusage(struct sm1_semantic *dcl) +{ + return nine_d3d9_to_nine_declusage(dcl->usage, dcl->usage_idx); +} + +static void +sm1_declusage_to_tgsi(struct tgsi_declaration_semantic *sem, + boolean tc, + struct sm1_semantic *dcl) +{ + BYTE index = dcl->usage_idx; + + /* For everything that is not matching to a TGSI_SEMANTIC_****, + * we match to a TGSI_SEMANTIC_GENERIC with index. + * + * The index can be anything UINT16 and usage_idx is BYTE, + * so we can fit everything. It doesn't matter if indices + * are close together or low. + * + * + * POSITION >= 1: 10 * index + 7 + * COLOR >= 2: 10 * (index-1) + 8 + * FOG: 16 + * TEXCOORD[0..15]: index + * BLENDWEIGHT: 10 * index + 19 + * BLENDINDICES: 10 * index + 20 + * NORMAL: 10 * index + 21 + * TANGENT: 10 * index + 22 + * BINORMAL: 10 * index + 23 + * TESSFACTOR: 10 * index + 24 + */ + + switch (dcl->usage) { + case D3DDECLUSAGE_POSITION: + case D3DDECLUSAGE_POSITIONT: + case D3DDECLUSAGE_DEPTH: + if (index == 0) { + sem->Name = TGSI_SEMANTIC_POSITION; + sem->Index = 0; + } else { + sem->Name = TGSI_SEMANTIC_GENERIC; + sem->Index = 10 * index + 7; + } + break; + case D3DDECLUSAGE_COLOR: + if (index < 2) { + sem->Name = TGSI_SEMANTIC_COLOR; + sem->Index = index; + } else { + sem->Name = TGSI_SEMANTIC_GENERIC; + sem->Index = 10 * (index-1) + 8; + } + break; + case D3DDECLUSAGE_FOG: + assert(index == 0); + sem->Name = TGSI_SEMANTIC_GENERIC; + sem->Index = 16; + break; + case D3DDECLUSAGE_PSIZE: + assert(index == 0); + sem->Name = TGSI_SEMANTIC_PSIZE; + sem->Index = 0; + break; + case D3DDECLUSAGE_TEXCOORD: + assert(index < 16); + if (index < 8 && tc) + sem->Name = TGSI_SEMANTIC_TEXCOORD; + else + sem->Name = TGSI_SEMANTIC_GENERIC; + sem->Index = index; + break; + case D3DDECLUSAGE_BLENDWEIGHT: + sem->Name = TGSI_SEMANTIC_GENERIC; + sem->Index = 10 * index + 19; + break; + case D3DDECLUSAGE_BLENDINDICES: + sem->Name = TGSI_SEMANTIC_GENERIC; + sem->Index = 10 * index + 20; + break; + case D3DDECLUSAGE_NORMAL: + sem->Name = TGSI_SEMANTIC_GENERIC; + sem->Index = 10 * index + 21; + break; + case D3DDECLUSAGE_TANGENT: + sem->Name = TGSI_SEMANTIC_GENERIC; + sem->Index = 10 * index + 22; + break; + case D3DDECLUSAGE_BINORMAL: + sem->Name = TGSI_SEMANTIC_GENERIC; + sem->Index = 10 * index + 23; + break; + case D3DDECLUSAGE_TESSFACTOR: + sem->Name = TGSI_SEMANTIC_GENERIC; + sem->Index = 10 * index + 24; + break; + case D3DDECLUSAGE_SAMPLE: + sem->Name = TGSI_SEMANTIC_COUNT; + sem->Index = 0; + break; + default: + unreachable("Invalid DECLUSAGE."); + break; + } +} + +#define NINED3DSTT_1D (D3DSTT_1D >> D3DSP_TEXTURETYPE_SHIFT) +#define NINED3DSTT_2D (D3DSTT_2D >> D3DSP_TEXTURETYPE_SHIFT) +#define NINED3DSTT_VOLUME (D3DSTT_VOLUME >> D3DSP_TEXTURETYPE_SHIFT) +#define NINED3DSTT_CUBE (D3DSTT_CUBE >> D3DSP_TEXTURETYPE_SHIFT) +static inline unsigned +d3dstt_to_tgsi_tex(BYTE sampler_type) +{ + switch (sampler_type) { + case NINED3DSTT_1D: return TGSI_TEXTURE_1D; + case NINED3DSTT_2D: return TGSI_TEXTURE_2D; + case NINED3DSTT_VOLUME: return TGSI_TEXTURE_3D; + case NINED3DSTT_CUBE: return TGSI_TEXTURE_CUBE; + default: + assert(0); + return TGSI_TEXTURE_UNKNOWN; + } +} +static inline unsigned +d3dstt_to_tgsi_tex_shadow(BYTE sampler_type) +{ + switch (sampler_type) { + case NINED3DSTT_1D: return TGSI_TEXTURE_SHADOW1D; + case NINED3DSTT_2D: return TGSI_TEXTURE_SHADOW2D; + case NINED3DSTT_VOLUME: + case NINED3DSTT_CUBE: + default: + assert(0); + return TGSI_TEXTURE_UNKNOWN; + } +} +static inline unsigned +ps1x_sampler_type(const struct nine_shader_info *info, unsigned stage) +{ + boolean shadow = !!(info->sampler_mask_shadow & (1 << stage)); + switch ((info->sampler_ps1xtypes >> (stage * 2)) & 0x3) { + case 1: return shadow ? TGSI_TEXTURE_SHADOW1D : TGSI_TEXTURE_1D; + case 0: return shadow ? TGSI_TEXTURE_SHADOW2D : TGSI_TEXTURE_2D; + case 3: return TGSI_TEXTURE_3D; + default: + return TGSI_TEXTURE_CUBE; + } +} + +static const char * +sm1_sampler_type_name(BYTE sampler_type) +{ + switch (sampler_type) { + case NINED3DSTT_1D: return "1D"; + case NINED3DSTT_2D: return "2D"; + case NINED3DSTT_VOLUME: return "VOLUME"; + case NINED3DSTT_CUBE: return "CUBE"; + default: + return "(D3DSTT_?)"; + } +} + +static inline unsigned +nine_tgsi_to_interp_mode(struct tgsi_declaration_semantic *sem) +{ + switch (sem->Name) { + case TGSI_SEMANTIC_POSITION: + case TGSI_SEMANTIC_NORMAL: + return TGSI_INTERPOLATE_LINEAR; + case TGSI_SEMANTIC_BCOLOR: + case TGSI_SEMANTIC_COLOR: + return TGSI_INTERPOLATE_COLOR; + case TGSI_SEMANTIC_FOG: + case TGSI_SEMANTIC_GENERIC: + case TGSI_SEMANTIC_TEXCOORD: + case TGSI_SEMANTIC_CLIPDIST: + case TGSI_SEMANTIC_CLIPVERTEX: + return TGSI_INTERPOLATE_PERSPECTIVE; + case TGSI_SEMANTIC_EDGEFLAG: + case TGSI_SEMANTIC_FACE: + case TGSI_SEMANTIC_INSTANCEID: + case TGSI_SEMANTIC_PCOORD: + case TGSI_SEMANTIC_PRIMID: + case TGSI_SEMANTIC_PSIZE: + case TGSI_SEMANTIC_VERTEXID: + return TGSI_INTERPOLATE_CONSTANT; + default: + assert(0); + return TGSI_INTERPOLATE_CONSTANT; + } +} + +DECL_SPECIAL(DCL) +{ + struct ureg_program *ureg = tx->ureg; + boolean is_input; + boolean is_sampler; + struct tgsi_declaration_semantic tgsi; + struct sm1_semantic sem; + sm1_read_semantic(tx, &sem); + + is_input = sem.reg.file == D3DSPR_INPUT; + is_sampler = + sem.usage == D3DDECLUSAGE_SAMPLE || sem.reg.file == D3DSPR_SAMPLER; + + DUMP("DCL "); + sm1_dump_dst_param(&sem.reg); + if (is_sampler) + DUMP(" %s\n", sm1_sampler_type_name(sem.sampler_type)); + else + if (tx->version.major >= 3) + DUMP(" %s%i\n", sm1_declusage_names[sem.usage], sem.usage_idx); + else + if (sem.usage | sem.usage_idx) + DUMP(" %u[%u]\n", sem.usage, sem.usage_idx); + else + DUMP("\n"); + + if (is_sampler) { + const unsigned m = 1 << sem.reg.idx; + ureg_DECL_sampler(ureg, sem.reg.idx); + tx->info->sampler_mask |= m; + tx->sampler_targets[sem.reg.idx] = (tx->info->sampler_mask_shadow & m) ? + d3dstt_to_tgsi_tex_shadow(sem.sampler_type) : + d3dstt_to_tgsi_tex(sem.sampler_type); + return D3D_OK; + } + + sm1_declusage_to_tgsi(&tgsi, tx->want_texcoord, &sem); + if (IS_VS) { + if (is_input) { + /* linkage outside of shader with vertex declaration */ + ureg_DECL_vs_input(ureg, sem.reg.idx); + assert(sem.reg.idx < ARRAY_SIZE(tx->info->input_map)); + tx->info->input_map[sem.reg.idx] = sm1_to_nine_declusage(&sem); + tx->info->num_inputs = MAX2(tx->info->num_inputs, sem.reg.idx + 1); + /* NOTE: preserving order in case of indirect access */ + } else + if (tx->version.major >= 3) { + /* SM2 output semantic determined by file */ + assert(sem.reg.mask != 0); + if (sem.usage == D3DDECLUSAGE_POSITIONT) + tx->info->position_t = TRUE; + assert(sem.reg.idx < ARRAY_SIZE(tx->regs.o)); + assert(ureg_dst_is_undef(tx->regs.o[sem.reg.idx]) && "Nine doesn't support yet packing"); + tx->regs.o[sem.reg.idx] = ureg_DECL_output_masked( + ureg, tgsi.Name, tgsi.Index, sem.reg.mask, 0, 1); + nine_record_outputs(tx, sem.usage, sem.usage_idx, sem.reg.mask, sem.reg.idx); + if (tx->info->process_vertices && sem.usage == D3DDECLUSAGE_POSITION && sem.usage_idx == 0) { + tx->regs.oPos_out = tx->regs.o[sem.reg.idx]; + tx->regs.o[sem.reg.idx] = ureg_DECL_temporary(ureg); + tx->regs.oPos = tx->regs.o[sem.reg.idx]; + } + + if (tgsi.Name == TGSI_SEMANTIC_PSIZE) { + tx->regs.o[sem.reg.idx] = ureg_DECL_temporary(ureg); + tx->regs.oPts = tx->regs.o[sem.reg.idx]; + } + } + } else { + if (is_input && tx->version.major >= 3) { + unsigned interp_location = 0; + /* SM3 only, SM2 input semantic determined by file */ + assert(sem.reg.idx < ARRAY_SIZE(tx->regs.v)); + assert(ureg_src_is_undef(tx->regs.v[sem.reg.idx]) && "Nine doesn't support yet packing"); + /* PositionT and tessfactor forbidden */ + if (sem.usage == D3DDECLUSAGE_POSITIONT || sem.usage == D3DDECLUSAGE_TESSFACTOR) + return D3DERR_INVALIDCALL; + + if (tgsi.Name == TGSI_SEMANTIC_POSITION) { + /* Position0 is forbidden (likely because vPos already does that) */ + if (sem.usage == D3DDECLUSAGE_POSITION) + return D3DERR_INVALIDCALL; + /* Following code is for depth */ + tx->regs.v[sem.reg.idx] = nine_get_position_input(tx); + return D3D_OK; + } + + if (sem.reg.mod & NINED3DSPDM_CENTROID || + (tgsi.Name == TGSI_SEMANTIC_COLOR && tx->info->force_color_in_centroid)) + interp_location = TGSI_INTERPOLATE_LOC_CENTROID; + + tx->regs.v[sem.reg.idx] = ureg_DECL_fs_input_cyl_centroid( + ureg, tgsi.Name, tgsi.Index, + nine_tgsi_to_interp_mode(&tgsi), + 0, /* cylwrap */ + interp_location, 0, 1); + } else + if (!is_input && 0) { /* declare in COLOROUT/DEPTHOUT case */ + /* FragColor or FragDepth */ + assert(sem.reg.mask != 0); + ureg_DECL_output_masked(ureg, tgsi.Name, tgsi.Index, sem.reg.mask, + 0, 1); + } + } + return D3D_OK; +} + +DECL_SPECIAL(DEF) +{ + tx_set_lconstf(tx, tx->insn.dst[0].idx, tx->insn.src[0].imm.f); + return D3D_OK; +} + +DECL_SPECIAL(DEFB) +{ + tx_set_lconstb(tx, tx->insn.dst[0].idx, tx->insn.src[0].imm.b); + return D3D_OK; +} + +DECL_SPECIAL(DEFI) +{ + tx_set_lconsti(tx, tx->insn.dst[0].idx, tx->insn.src[0].imm.i); + return D3D_OK; +} + +DECL_SPECIAL(POW) +{ + struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); + struct ureg_src src[2] = { + tx_src_param(tx, &tx->insn.src[0]), + tx_src_param(tx, &tx->insn.src[1]) + }; + ureg_POW(tx->ureg, dst, ureg_abs(src[0]), src[1]); + return D3D_OK; +} + +/* Tests results on Win 10: + * NV (NVIDIA GeForce GT 635M) + * AMD (AMD Radeon HD 7730M) + * INTEL (Intel(R) HD Graphics 4000) + * PS2 and PS3: + * RCP and RSQ can generate inf on NV and AMD. + * RCP and RSQ are clamped on INTEL (+- FLT_MAX), + * NV: log not clamped + * AMD: log(0) is -FLT_MAX (but log(inf) is inf) + * INTEL: log(0) is -FLT_MAX and log(inf) is 127 + * All devices have 0*anything = 0 + * + * INTEL VS2 and VS3: same behaviour. + * Some differences VS2 and VS3 for constants defined with inf/NaN. + * While PS3, VS3 and PS2 keep NaN and Inf shader constants without change, + * VS2 seems to clamp to zero (may be test failure). + * AMD VS2: unknown, VS3: very likely behaviour of PS3 + * NV VS2 and VS3: very likely behaviour of PS3 + * For both, Inf in VS becomes NaN is PS + * "Very likely" because the test was less extensive. + * + * Thus all clamping can be removed for shaders 2 and 3, + * as long as 0*anything = 0. + * Else clamps to enforce 0*anything = 0 (anything being then + * neither inf or NaN, the user being unlikely to pass them + * as constant). + * The status for VS1 and PS1 is unknown. + */ + +DECL_SPECIAL(RCP) +{ + struct ureg_program *ureg = tx->ureg; + struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); + struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]); + struct ureg_dst tmp = tx->mul_zero_wins ? dst : tx_scratch(tx); + ureg_RCP(ureg, tmp, src); + if (!tx->mul_zero_wins) { + /* FLT_MAX has issues with Rayman */ + ureg_MIN(ureg, tmp, ureg_imm1f(ureg, FLT_MAX/2.f), ureg_src(tmp)); + ureg_MAX(ureg, dst, ureg_imm1f(ureg, -FLT_MAX/2.f), ureg_src(tmp)); + } + return D3D_OK; +} + +DECL_SPECIAL(RSQ) +{ + struct ureg_program *ureg = tx->ureg; + struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); + struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]); + struct ureg_dst tmp = tx->mul_zero_wins ? dst : tx_scratch(tx); + ureg_RSQ(ureg, tmp, ureg_abs(src)); + if (!tx->mul_zero_wins) + ureg_MIN(ureg, dst, ureg_imm1f(ureg, FLT_MAX), ureg_src(tmp)); + return D3D_OK; +} + +DECL_SPECIAL(LOG) +{ + struct ureg_program *ureg = tx->ureg; + struct ureg_dst tmp = tx_scratch_scalar(tx); + struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); + struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]); + ureg_LG2(ureg, tmp, ureg_abs(src)); + if (tx->mul_zero_wins) { + ureg_MOV(ureg, dst, tx_src_scalar(tmp)); + } else { + ureg_MAX(ureg, dst, ureg_imm1f(ureg, -FLT_MAX), tx_src_scalar(tmp)); + } + return D3D_OK; +} + +DECL_SPECIAL(LIT) +{ + struct ureg_program *ureg = tx->ureg; + struct ureg_dst tmp = tx_scratch(tx); + struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); + struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]); + ureg_LIT(ureg, tmp, src); + /* d3d9 LIT is the same than gallium LIT. One difference is that d3d9 + * states that dst.z is 0 when src.y <= 0. Gallium definition can assign + * it 0^0 if src.w=0, which value is driver dependent. */ + ureg_CMP(ureg, ureg_writemask(dst, TGSI_WRITEMASK_Z), + ureg_negate(ureg_scalar(src, TGSI_SWIZZLE_Y)), + ureg_src(tmp), ureg_imm1f(ureg, 0.0f)); + ureg_MOV(ureg, ureg_writemask(dst, TGSI_WRITEMASK_XYW), ureg_src(tmp)); + return D3D_OK; +} + +DECL_SPECIAL(NRM) +{ + struct ureg_program *ureg = tx->ureg; + struct ureg_dst tmp = tx_scratch_scalar(tx); + struct ureg_src nrm = tx_src_scalar(tmp); + struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); + struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]); + ureg_DP3(ureg, tmp, src, src); + ureg_RSQ(ureg, tmp, nrm); + if (!tx->mul_zero_wins) + ureg_MIN(ureg, tmp, ureg_imm1f(ureg, FLT_MAX), nrm); + ureg_MUL(ureg, dst, src, nrm); + return D3D_OK; +} + +DECL_SPECIAL(DP2ADD) +{ + struct ureg_dst tmp = tx_scratch_scalar(tx); + struct ureg_src dp2 = tx_src_scalar(tmp); + struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); + struct ureg_src src[3]; + int i; + for (i = 0; i < 3; ++i) + src[i] = tx_src_param(tx, &tx->insn.src[i]); + assert_replicate_swizzle(&src[2]); + + ureg_DP2(tx->ureg, tmp, src[0], src[1]); + ureg_ADD(tx->ureg, dst, src[2], dp2); + + return D3D_OK; +} + +DECL_SPECIAL(TEXCOORD) +{ + struct ureg_program *ureg = tx->ureg; + const unsigned s = tx->insn.dst[0].idx; + struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); + + tx_texcoord_alloc(tx, s); + ureg_MOV(ureg, ureg_writemask(ureg_saturate(dst), TGSI_WRITEMASK_XYZ), tx->regs.vT[s]); + ureg_MOV(ureg, ureg_writemask(dst, TGSI_WRITEMASK_W), ureg_imm1f(tx->ureg, 1.0f)); + + return D3D_OK; +} + +DECL_SPECIAL(TEXCOORD_ps14) +{ + struct ureg_program *ureg = tx->ureg; + struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]); + struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); + + assert(tx->insn.src[0].file == D3DSPR_TEXTURE); + + ureg_MOV(ureg, dst, src); + + return D3D_OK; +} + +DECL_SPECIAL(TEXKILL) +{ + struct ureg_src reg; + + if (tx->version.major > 1 || tx->version.minor > 3) { + reg = tx_dst_param_as_src(tx, &tx->insn.dst[0]); + } else { + tx_texcoord_alloc(tx, tx->insn.dst[0].idx); + reg = tx->regs.vT[tx->insn.dst[0].idx]; + } + if (tx->version.major < 2) + reg = ureg_swizzle(reg, NINE_SWIZZLE4(X,Y,Z,Z)); + ureg_KILL_IF(tx->ureg, reg); + + return D3D_OK; +} + +DECL_SPECIAL(TEXBEM) +{ + struct ureg_program *ureg = tx->ureg; + struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); + struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]); /* t[n] */ + struct ureg_dst tmp, tmp2, texcoord; + struct ureg_src sample, m00, m01, m10, m11, c8m, c16m2; + struct ureg_src bumpenvlscale, bumpenvloffset; + const int m = tx->insn.dst[0].idx; + + assert(tx->version.major == 1); + + sample = ureg_DECL_sampler(ureg, m); + tx->info->sampler_mask |= 1 << m; + + tx_texcoord_alloc(tx, m); + + tmp = tx_scratch(tx); + tmp2 = tx_scratch(tx); + texcoord = tx_scratch(tx); + /* + * Bump-env-matrix: + * 00 is X + * 01 is Y + * 10 is Z + * 11 is W + */ + c8m = nine_float_constant_src(tx, 8+m); + c16m2 = nine_float_constant_src(tx, 8+8+m/2); + + m00 = NINE_APPLY_SWIZZLE(c8m, X); + m01 = NINE_APPLY_SWIZZLE(c8m, Y); + m10 = NINE_APPLY_SWIZZLE(c8m, Z); + m11 = NINE_APPLY_SWIZZLE(c8m, W); + + /* These two attributes are packed as X=scale0 Y=offset0 Z=scale1 W=offset1 etc */ + if (m % 2 == 0) { + bumpenvlscale = NINE_APPLY_SWIZZLE(c16m2, X); + bumpenvloffset = NINE_APPLY_SWIZZLE(c16m2, Y); + } else { + bumpenvlscale = NINE_APPLY_SWIZZLE(c16m2, Z); + bumpenvloffset = NINE_APPLY_SWIZZLE(c16m2, W); + } + + apply_ps1x_projection(tx, texcoord, tx->regs.vT[m], m); + + /* u' = TextureCoordinates(stage m)u + D3DTSS_BUMPENVMAT00(stage m)*t(n)R */ + ureg_MAD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), m00, + NINE_APPLY_SWIZZLE(src, X), ureg_src(texcoord)); + /* u' = u' + D3DTSS_BUMPENVMAT10(stage m)*t(n)G */ + ureg_MAD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), m10, + NINE_APPLY_SWIZZLE(src, Y), + NINE_APPLY_SWIZZLE(ureg_src(tmp), X)); + + /* v' = TextureCoordinates(stage m)v + D3DTSS_BUMPENVMAT01(stage m)*t(n)R */ + ureg_MAD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Y), m01, + NINE_APPLY_SWIZZLE(src, X), ureg_src(texcoord)); + /* v' = v' + D3DTSS_BUMPENVMAT11(stage m)*t(n)G*/ + ureg_MAD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Y), m11, + NINE_APPLY_SWIZZLE(src, Y), + NINE_APPLY_SWIZZLE(ureg_src(tmp), Y)); + + /* Now the texture coordinates are in tmp.xy */ + + if (tx->insn.opcode == D3DSIO_TEXBEM) { + ureg_TEX(ureg, dst, ps1x_sampler_type(tx->info, m), ureg_src(tmp), sample); + } else if (tx->insn.opcode == D3DSIO_TEXBEML) { + /* t(m)RGBA = t(m)RGBA * [(t(n)B * D3DTSS_BUMPENVLSCALE(stage m)) + D3DTSS_BUMPENVLOFFSET(stage m)] */ + ureg_TEX(ureg, tmp, ps1x_sampler_type(tx->info, m), ureg_src(tmp), sample); + ureg_MAD(ureg, tmp2, NINE_APPLY_SWIZZLE(src, Z), + bumpenvlscale, bumpenvloffset); + ureg_MUL(ureg, dst, ureg_src(tmp), ureg_src(tmp2)); + } + + tx->info->bumpenvmat_needed = 1; + + return D3D_OK; +} + +DECL_SPECIAL(TEXREG2AR) +{ + struct ureg_program *ureg = tx->ureg; + struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); + struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]); /* t[n] */ + struct ureg_src sample; + const int m = tx->insn.dst[0].idx; + ASSERTED const int n = tx->insn.src[0].idx; + assert(m >= 0 && m > n); + + sample = ureg_DECL_sampler(ureg, m); + tx->info->sampler_mask |= 1 << m; + ureg_TEX(ureg, dst, ps1x_sampler_type(tx->info, m), ureg_swizzle(src, NINE_SWIZZLE4(W,X,X,X)), sample); + + return D3D_OK; +} + +DECL_SPECIAL(TEXREG2GB) +{ + struct ureg_program *ureg = tx->ureg; + struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); + struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]); /* t[n] */ + struct ureg_src sample; + const int m = tx->insn.dst[0].idx; + ASSERTED const int n = tx->insn.src[0].idx; + assert(m >= 0 && m > n); + + sample = ureg_DECL_sampler(ureg, m); + tx->info->sampler_mask |= 1 << m; + ureg_TEX(ureg, dst, ps1x_sampler_type(tx->info, m), ureg_swizzle(src, NINE_SWIZZLE4(Y,Z,Z,Z)), sample); + + return D3D_OK; +} + +DECL_SPECIAL(TEXM3x2PAD) +{ + return D3D_OK; /* this is just padding */ +} + +DECL_SPECIAL(TEXM3x2TEX) +{ + struct ureg_program *ureg = tx->ureg; + struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); + struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]); /* t[n] */ + struct ureg_src sample; + const int m = tx->insn.dst[0].idx - 1; + ASSERTED const int n = tx->insn.src[0].idx; + assert(m >= 0 && m > n); + + tx_texcoord_alloc(tx, m); + tx_texcoord_alloc(tx, m+1); + + /* performs the matrix multiplication */ + ureg_DP3(ureg, ureg_writemask(dst, TGSI_WRITEMASK_X), tx->regs.vT[m], src); + ureg_DP3(ureg, ureg_writemask(dst, TGSI_WRITEMASK_Y), tx->regs.vT[m+1], src); + + sample = ureg_DECL_sampler(ureg, m + 1); + tx->info->sampler_mask |= 1 << (m + 1); + ureg_TEX(ureg, dst, ps1x_sampler_type(tx->info, m + 1), ureg_src(dst), sample); + + return D3D_OK; +} + +DECL_SPECIAL(TEXM3x3PAD) +{ + return D3D_OK; /* this is just padding */ +} + +DECL_SPECIAL(TEXM3x3SPEC) +{ + struct ureg_program *ureg = tx->ureg; + struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); + struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]); /* t[n] */ + struct ureg_src E = tx_src_param(tx, &tx->insn.src[1]); + struct ureg_src sample; + struct ureg_dst tmp; + const int m = tx->insn.dst[0].idx - 2; + ASSERTED const int n = tx->insn.src[0].idx; + assert(m >= 0 && m > n); + + tx_texcoord_alloc(tx, m); + tx_texcoord_alloc(tx, m+1); + tx_texcoord_alloc(tx, m+2); + + ureg_DP3(ureg, ureg_writemask(dst, TGSI_WRITEMASK_X), tx->regs.vT[m], src); + ureg_DP3(ureg, ureg_writemask(dst, TGSI_WRITEMASK_Y), tx->regs.vT[m+1], src); + ureg_DP3(ureg, ureg_writemask(dst, TGSI_WRITEMASK_Z), tx->regs.vT[m+2], src); + + sample = ureg_DECL_sampler(ureg, m + 2); + tx->info->sampler_mask |= 1 << (m + 2); + tmp = ureg_writemask(tx_scratch(tx), TGSI_WRITEMASK_XYZ); + + /* At this step, dst = N = (u', w', z'). + * We want dst to be the texture sampled at (u'', w'', z''), with + * (u'', w'', z'') = 2 * (N.E / N.N) * N - E */ + ureg_DP3(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), ureg_src(dst), ureg_src(dst)); + ureg_RCP(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X)); + /* at this step tmp.x = 1/N.N */ + ureg_DP3(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Y), ureg_src(dst), E); + /* at this step tmp.y = N.E */ + ureg_MUL(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X), ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_Y)); + /* at this step tmp.x = N.E/N.N */ + ureg_MUL(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X), ureg_imm1f(ureg, 2.0f)); + ureg_MUL(ureg, tmp, ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X), ureg_src(dst)); + /* at this step tmp.xyz = 2 * (N.E / N.N) * N */ + ureg_ADD(ureg, tmp, ureg_src(tmp), ureg_negate(E)); + ureg_TEX(ureg, dst, ps1x_sampler_type(tx->info, m + 2), ureg_src(tmp), sample); + + return D3D_OK; +} + +DECL_SPECIAL(TEXREG2RGB) +{ + struct ureg_program *ureg = tx->ureg; + struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); + struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]); /* t[n] */ + struct ureg_src sample; + const int m = tx->insn.dst[0].idx; + ASSERTED const int n = tx->insn.src[0].idx; + assert(m >= 0 && m > n); + + sample = ureg_DECL_sampler(ureg, m); + tx->info->sampler_mask |= 1 << m; + ureg_TEX(ureg, dst, ps1x_sampler_type(tx->info, m), src, sample); + + return D3D_OK; +} + +DECL_SPECIAL(TEXDP3TEX) +{ + struct ureg_program *ureg = tx->ureg; + struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); + struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]); /* t[n] */ + struct ureg_dst tmp; + struct ureg_src sample; + const int m = tx->insn.dst[0].idx; + ASSERTED const int n = tx->insn.src[0].idx; + assert(m >= 0 && m > n); + + tx_texcoord_alloc(tx, m); + + tmp = tx_scratch(tx); + ureg_DP3(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), tx->regs.vT[m], src); + ureg_MOV(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_YZ), ureg_imm1f(ureg, 0.0f)); + + sample = ureg_DECL_sampler(ureg, m); + tx->info->sampler_mask |= 1 << m; + ureg_TEX(ureg, dst, ps1x_sampler_type(tx->info, m), ureg_src(tmp), sample); + + return D3D_OK; +} + +DECL_SPECIAL(TEXM3x2DEPTH) +{ + struct ureg_program *ureg = tx->ureg; + struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]); /* t[n] */ + struct ureg_dst tmp; + const int m = tx->insn.dst[0].idx - 1; + ASSERTED const int n = tx->insn.src[0].idx; + assert(m >= 0 && m > n); + + tx_texcoord_alloc(tx, m); + tx_texcoord_alloc(tx, m+1); + + tmp = tx_scratch(tx); + + /* performs the matrix multiplication */ + ureg_DP3(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), tx->regs.vT[m], src); + ureg_DP3(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Y), tx->regs.vT[m+1], src); + + ureg_RCP(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Z), ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_Y)); + /* tmp.x = 'z', tmp.y = 'w', tmp.z = 1/'w'. */ + ureg_MUL(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X), ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_Z)); + /* res = 'w' == 0 ? 1.0 : z/w */ + ureg_CMP(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), ureg_negate(ureg_abs(ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_Y))), + ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X), ureg_imm1f(ureg, 1.0f)); + /* replace the depth for depth testing with the result */ + tx->regs.oDepth = ureg_DECL_output_masked(ureg, TGSI_SEMANTIC_POSITION, 0, + TGSI_WRITEMASK_Z, 0, 1); + ureg_MOV(ureg, tx->regs.oDepth, ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X)); + /* note that we write nothing to the destination, since it's disallowed to use it afterward */ + return D3D_OK; +} + +DECL_SPECIAL(TEXDP3) +{ + struct ureg_program *ureg = tx->ureg; + struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); + struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]); /* t[n] */ + const int m = tx->insn.dst[0].idx; + ASSERTED const int n = tx->insn.src[0].idx; + assert(m >= 0 && m > n); + + tx_texcoord_alloc(tx, m); + + ureg_DP3(ureg, dst, tx->regs.vT[m], src); + + return D3D_OK; +} + +DECL_SPECIAL(TEXM3x3) +{ + struct ureg_program *ureg = tx->ureg; + struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); + struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]); /* t[n] */ + struct ureg_src sample; + struct ureg_dst E, tmp; + const int m = tx->insn.dst[0].idx - 2; + ASSERTED const int n = tx->insn.src[0].idx; + assert(m >= 0 && m > n); + + tx_texcoord_alloc(tx, m); + tx_texcoord_alloc(tx, m+1); + tx_texcoord_alloc(tx, m+2); + + ureg_DP3(ureg, ureg_writemask(dst, TGSI_WRITEMASK_X), tx->regs.vT[m], src); + ureg_DP3(ureg, ureg_writemask(dst, TGSI_WRITEMASK_Y), tx->regs.vT[m+1], src); + ureg_DP3(ureg, ureg_writemask(dst, TGSI_WRITEMASK_Z), tx->regs.vT[m+2], src); + + switch (tx->insn.opcode) { + case D3DSIO_TEXM3x3: + ureg_MOV(ureg, ureg_writemask(dst, TGSI_WRITEMASK_W), ureg_imm1f(ureg, 1.0f)); + break; + case D3DSIO_TEXM3x3TEX: + sample = ureg_DECL_sampler(ureg, m + 2); + tx->info->sampler_mask |= 1 << (m + 2); + ureg_TEX(ureg, dst, ps1x_sampler_type(tx->info, m + 2), ureg_src(dst), sample); + break; + case D3DSIO_TEXM3x3VSPEC: + sample = ureg_DECL_sampler(ureg, m + 2); + tx->info->sampler_mask |= 1 << (m + 2); + E = tx_scratch(tx); + tmp = ureg_writemask(tx_scratch(tx), TGSI_WRITEMASK_XYZ); + ureg_MOV(ureg, ureg_writemask(E, TGSI_WRITEMASK_X), ureg_scalar(tx->regs.vT[m], TGSI_SWIZZLE_W)); + ureg_MOV(ureg, ureg_writemask(E, TGSI_WRITEMASK_Y), ureg_scalar(tx->regs.vT[m+1], TGSI_SWIZZLE_W)); + ureg_MOV(ureg, ureg_writemask(E, TGSI_WRITEMASK_Z), ureg_scalar(tx->regs.vT[m+2], TGSI_SWIZZLE_W)); + /* At this step, dst = N = (u', w', z'). + * We want dst to be the texture sampled at (u'', w'', z''), with + * (u'', w'', z'') = 2 * (N.E / N.N) * N - E */ + ureg_DP3(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), ureg_src(dst), ureg_src(dst)); + ureg_RCP(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X)); + /* at this step tmp.x = 1/N.N */ + ureg_DP3(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Y), ureg_src(dst), ureg_src(E)); + /* at this step tmp.y = N.E */ + ureg_MUL(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X), ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_Y)); + /* at this step tmp.x = N.E/N.N */ + ureg_MUL(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X), ureg_imm1f(ureg, 2.0f)); + ureg_MUL(ureg, tmp, ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X), ureg_src(dst)); + /* at this step tmp.xyz = 2 * (N.E / N.N) * N */ + ureg_ADD(ureg, tmp, ureg_src(tmp), ureg_negate(ureg_src(E))); + ureg_TEX(ureg, dst, ps1x_sampler_type(tx->info, m + 2), ureg_src(tmp), sample); + break; + default: + return D3DERR_INVALIDCALL; + } + return D3D_OK; +} + +DECL_SPECIAL(TEXDEPTH) +{ + struct ureg_program *ureg = tx->ureg; + struct ureg_dst r5; + struct ureg_src r5r, r5g; + + assert(tx->insn.dst[0].idx == 5); /* instruction must get r5 here */ + + /* we must replace the depth by r5.g == 0 ? 1.0f : r5.r/r5.g. + * r5 won't be used afterward, thus we can use r5.ba */ + r5 = tx->regs.r[5]; + r5r = ureg_scalar(ureg_src(r5), TGSI_SWIZZLE_X); + r5g = ureg_scalar(ureg_src(r5), TGSI_SWIZZLE_Y); + + ureg_RCP(ureg, ureg_writemask(r5, TGSI_WRITEMASK_Z), r5g); + ureg_MUL(ureg, ureg_writemask(r5, TGSI_WRITEMASK_X), r5r, ureg_scalar(ureg_src(r5), TGSI_SWIZZLE_Z)); + /* r5.r = r/g */ + ureg_CMP(ureg, ureg_writemask(r5, TGSI_WRITEMASK_X), ureg_negate(ureg_abs(r5g)), + r5r, ureg_imm1f(ureg, 1.0f)); + /* replace the depth for depth testing with the result */ + tx->regs.oDepth = ureg_DECL_output_masked(ureg, TGSI_SEMANTIC_POSITION, 0, + TGSI_WRITEMASK_Z, 0, 1); + ureg_MOV(ureg, tx->regs.oDepth, r5r); + + return D3D_OK; +} + +DECL_SPECIAL(BEM) +{ + struct ureg_program *ureg = tx->ureg; + struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); + struct ureg_src src0 = tx_src_param(tx, &tx->insn.src[0]); + struct ureg_src src1 = tx_src_param(tx, &tx->insn.src[1]); + struct ureg_src m00, m01, m10, m11, c8m; + const int m = tx->insn.dst[0].idx; + struct ureg_dst tmp; + /* + * Bump-env-matrix: + * 00 is X + * 01 is Y + * 10 is Z + * 11 is W + */ + c8m = nine_float_constant_src(tx, 8+m); + m00 = NINE_APPLY_SWIZZLE(c8m, X); + m01 = NINE_APPLY_SWIZZLE(c8m, Y); + m10 = NINE_APPLY_SWIZZLE(c8m, Z); + m11 = NINE_APPLY_SWIZZLE(c8m, W); + /* dest.r = src0.r + D3DTSS_BUMPENVMAT00(stage n) * src1.r */ + ureg_MAD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), m00, + NINE_APPLY_SWIZZLE(src1, X), NINE_APPLY_SWIZZLE(src0, X)); + /* dest.r = dest.r + D3DTSS_BUMPENVMAT10(stage n) * src1.g; */ + ureg_MAD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), m10, + NINE_APPLY_SWIZZLE(src1, Y), NINE_APPLY_SWIZZLE(ureg_src(tmp), X)); + + /* dest.g = src0.g + D3DTSS_BUMPENVMAT01(stage n) * src1.r */ + ureg_MAD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Y), m01, + NINE_APPLY_SWIZZLE(src1, X), src0); + /* dest.g = dest.g + D3DTSS_BUMPENVMAT11(stage n) * src1.g */ + ureg_MAD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Y), m11, + NINE_APPLY_SWIZZLE(src1, Y), NINE_APPLY_SWIZZLE(ureg_src(tmp), Y)); + ureg_MOV(ureg, ureg_writemask(dst, TGSI_WRITEMASK_XY), ureg_src(tmp)); + + tx->info->bumpenvmat_needed = 1; + + return D3D_OK; +} + +DECL_SPECIAL(TEXLD) +{ + struct ureg_program *ureg = tx->ureg; + unsigned target; + struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); + struct ureg_src src[2] = { + tx_src_param(tx, &tx->insn.src[0]), + tx_src_param(tx, &tx->insn.src[1]) + }; + assert(tx->insn.src[1].idx >= 0 && + tx->insn.src[1].idx < ARRAY_SIZE(tx->sampler_targets)); + target = tx->sampler_targets[tx->insn.src[1].idx]; + + switch (tx->insn.flags) { + case 0: + ureg_TEX(ureg, dst, target, src[0], src[1]); + break; + case NINED3DSI_TEXLD_PROJECT: + ureg_TXP(ureg, dst, target, src[0], src[1]); + break; + case NINED3DSI_TEXLD_BIAS: + ureg_TXB(ureg, dst, target, src[0], src[1]); + break; + default: + assert(0); + return D3DERR_INVALIDCALL; + } + return D3D_OK; +} + +DECL_SPECIAL(TEXLD_14) +{ + struct ureg_program *ureg = tx->ureg; + struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); + struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]); + const unsigned s = tx->insn.dst[0].idx; + const unsigned t = ps1x_sampler_type(tx->info, s); + + tx->info->sampler_mask |= 1 << s; + ureg_TEX(ureg, dst, t, src, ureg_DECL_sampler(ureg, s)); + + return D3D_OK; +} + +DECL_SPECIAL(TEX) +{ + struct ureg_program *ureg = tx->ureg; + const unsigned s = tx->insn.dst[0].idx; + const unsigned t = ps1x_sampler_type(tx->info, s); + struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); + struct ureg_src src[2]; + + tx_texcoord_alloc(tx, s); + + src[0] = tx->regs.vT[s]; + src[1] = ureg_DECL_sampler(ureg, s); + tx->info->sampler_mask |= 1 << s; + + TEX_with_ps1x_projection(tx, dst, t, src[0], src[1], s); + + return D3D_OK; +} + +DECL_SPECIAL(TEXLDD) +{ + unsigned target; + struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); + struct ureg_src src[4] = { + tx_src_param(tx, &tx->insn.src[0]), + tx_src_param(tx, &tx->insn.src[1]), + tx_src_param(tx, &tx->insn.src[2]), + tx_src_param(tx, &tx->insn.src[3]) + }; + assert(tx->insn.src[1].idx >= 0 && + tx->insn.src[1].idx < ARRAY_SIZE(tx->sampler_targets)); + target = tx->sampler_targets[tx->insn.src[1].idx]; + + ureg_TXD(tx->ureg, dst, target, src[0], src[2], src[3], src[1]); + return D3D_OK; +} + +DECL_SPECIAL(TEXLDL) +{ + unsigned target; + struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); + struct ureg_src src[2] = { + tx_src_param(tx, &tx->insn.src[0]), + tx_src_param(tx, &tx->insn.src[1]) + }; + assert(tx->insn.src[1].idx >= 0 && + tx->insn.src[1].idx < ARRAY_SIZE(tx->sampler_targets)); + target = tx->sampler_targets[tx->insn.src[1].idx]; + + ureg_TXL(tx->ureg, dst, target, src[0], src[1]); + return D3D_OK; +} + +DECL_SPECIAL(SETP) +{ + const unsigned cmp_op = sm1_insn_flags_to_tgsi_setop(tx->insn.flags); + struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); + struct ureg_src src[2] = { + tx_src_param(tx, &tx->insn.src[0]), + tx_src_param(tx, &tx->insn.src[1]) + }; + ureg_insn(tx->ureg, cmp_op, &dst, 1, src, 2, 0); + return D3D_OK; +} + +DECL_SPECIAL(BREAKP) +{ + struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]); + ureg_IF(tx->ureg, src, tx_cond(tx)); + ureg_BRK(tx->ureg); + tx_endcond(tx); + ureg_ENDIF(tx->ureg); + return D3D_OK; +} + +DECL_SPECIAL(PHASE) +{ + return D3D_OK; /* we don't care about phase */ +} + +DECL_SPECIAL(COMMENT) +{ + return D3D_OK; /* nothing to do */ +} + + +#define _OPI(o,t,vv1,vv2,pv1,pv2,d,s,h) \ + { D3DSIO_##o, TGSI_OPCODE_##t, { vv1, vv2 }, { pv1, pv2, }, d, s, h } + +static const struct sm1_op_info inst_table[] = +{ + _OPI(NOP, NOP, V(0,0), V(3,0), V(0,0), V(3,0), 0, 0, SPECIAL(NOP)), /* 0 */ + _OPI(MOV, MOV, V(0,0), V(3,0), V(0,0), V(3,0), 1, 1, NULL), + _OPI(ADD, ADD, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, NULL), /* 2 */ + _OPI(SUB, NOP, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, SPECIAL(SUB)), /* 3 */ + _OPI(MAD, MAD, V(0,0), V(3,0), V(0,0), V(3,0), 1, 3, NULL), /* 4 */ + _OPI(MUL, MUL, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, NULL), /* 5 */ + _OPI(RCP, RCP, V(0,0), V(3,0), V(0,0), V(3,0), 1, 1, SPECIAL(RCP)), /* 6 */ + _OPI(RSQ, RSQ, V(0,0), V(3,0), V(0,0), V(3,0), 1, 1, SPECIAL(RSQ)), /* 7 */ + _OPI(DP3, DP3, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, NULL), /* 8 */ + _OPI(DP4, DP4, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, NULL), /* 9 */ + _OPI(MIN, MIN, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, NULL), /* 10 */ + _OPI(MAX, MAX, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, NULL), /* 11 */ + _OPI(SLT, SLT, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, NULL), /* 12 */ + _OPI(SGE, SGE, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, NULL), /* 13 */ + _OPI(EXP, EX2, V(0,0), V(3,0), V(0,0), V(3,0), 1, 1, NULL), /* 14 */ + _OPI(LOG, LG2, V(0,0), V(3,0), V(0,0), V(3,0), 1, 1, SPECIAL(LOG)), /* 15 */ + _OPI(LIT, LIT, V(0,0), V(3,0), V(0,0), V(0,0), 1, 1, SPECIAL(LIT)), /* 16 */ + _OPI(DST, DST, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, NULL), /* 17 */ + _OPI(LRP, LRP, V(0,0), V(3,0), V(0,0), V(3,0), 1, 3, NULL), /* 18 */ + _OPI(FRC, FRC, V(0,0), V(3,0), V(0,0), V(3,0), 1, 1, NULL), /* 19 */ + + _OPI(M4x4, NOP, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, SPECIAL(M4x4)), + _OPI(M4x3, NOP, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, SPECIAL(M4x3)), + _OPI(M3x4, NOP, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, SPECIAL(M3x4)), + _OPI(M3x3, NOP, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, SPECIAL(M3x3)), + _OPI(M3x2, NOP, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, SPECIAL(M3x2)), + + _OPI(CALL, CAL, V(2,0), V(3,0), V(2,1), V(3,0), 0, 1, SPECIAL(CALL)), + _OPI(CALLNZ, CAL, V(2,0), V(3,0), V(2,1), V(3,0), 0, 2, SPECIAL(CALLNZ)), + _OPI(LOOP, BGNLOOP, V(2,0), V(3,0), V(3,0), V(3,0), 0, 2, SPECIAL(LOOP)), + _OPI(RET, RET, V(2,0), V(3,0), V(2,1), V(3,0), 0, 0, SPECIAL(RET)), + _OPI(ENDLOOP, ENDLOOP, V(2,0), V(3,0), V(3,0), V(3,0), 0, 0, SPECIAL(ENDLOOP)), + _OPI(LABEL, NOP, V(2,0), V(3,0), V(2,1), V(3,0), 0, 1, SPECIAL(LABEL)), + + _OPI(DCL, NOP, V(0,0), V(3,0), V(0,0), V(3,0), 0, 0, SPECIAL(DCL)), + + _OPI(POW, POW, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, SPECIAL(POW)), + _OPI(CRS, NOP, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, SPECIAL(XPD)), /* XXX: .w */ + _OPI(SGN, SSG, V(2,0), V(3,0), V(0,0), V(0,0), 1, 3, SPECIAL(SGN)), /* ignore src1,2 */ + _OPI(ABS, NOP, V(0,0), V(3,0), V(0,0), V(3,0), 1, 1, SPECIAL(ABS)), + _OPI(NRM, NOP, V(0,0), V(3,0), V(0,0), V(3,0), 1, 1, SPECIAL(NRM)), /* NRM doesn't fit */ + + _OPI(SINCOS, NOP, V(2,0), V(2,1), V(2,0), V(2,1), 1, 3, SPECIAL(SINCOS)), + _OPI(SINCOS, NOP, V(3,0), V(3,0), V(3,0), V(3,0), 1, 1, SPECIAL(SINCOS)), + + /* More flow control */ + _OPI(REP, NOP, V(2,0), V(3,0), V(2,1), V(3,0), 0, 1, SPECIAL(REP)), + _OPI(ENDREP, NOP, V(2,0), V(3,0), V(2,1), V(3,0), 0, 0, SPECIAL(ENDREP)), + _OPI(IF, IF, V(2,0), V(3,0), V(2,1), V(3,0), 0, 1, SPECIAL(IF)), + _OPI(IFC, IF, V(2,1), V(3,0), V(2,1), V(3,0), 0, 2, SPECIAL(IFC)), + _OPI(ELSE, ELSE, V(2,0), V(3,0), V(2,1), V(3,0), 0, 0, SPECIAL(ELSE)), + _OPI(ENDIF, ENDIF, V(2,0), V(3,0), V(2,1), V(3,0), 0, 0, SPECIAL(ENDIF)), + _OPI(BREAK, BRK, V(2,1), V(3,0), V(2,1), V(3,0), 0, 0, NULL), + _OPI(BREAKC, NOP, V(2,1), V(3,0), V(2,1), V(3,0), 0, 2, SPECIAL(BREAKC)), + /* we don't write to the address register, but a normal register (copied + * when needed to the address register), thus we don't use ARR */ + _OPI(MOVA, MOV, V(2,0), V(3,0), V(0,0), V(0,0), 1, 1, NULL), + + _OPI(DEFB, NOP, V(0,0), V(3,0) , V(0,0), V(3,0) , 1, 0, SPECIAL(DEFB)), + _OPI(DEFI, NOP, V(0,0), V(3,0) , V(0,0), V(3,0) , 1, 0, SPECIAL(DEFI)), + + _OPI(TEXCOORD, NOP, V(0,0), V(0,0), V(0,0), V(1,3), 1, 0, SPECIAL(TEXCOORD)), + _OPI(TEXCOORD, MOV, V(0,0), V(0,0), V(1,4), V(1,4), 1, 1, SPECIAL(TEXCOORD_ps14)), + _OPI(TEXKILL, KILL_IF, V(0,0), V(0,0), V(0,0), V(3,0), 1, 0, SPECIAL(TEXKILL)), + _OPI(TEX, TEX, V(0,0), V(0,0), V(0,0), V(1,3), 1, 0, SPECIAL(TEX)), + _OPI(TEX, TEX, V(0,0), V(0,0), V(1,4), V(1,4), 1, 1, SPECIAL(TEXLD_14)), + _OPI(TEX, TEX, V(0,0), V(0,0), V(2,0), V(3,0), 1, 2, SPECIAL(TEXLD)), + _OPI(TEXBEM, TEX, V(0,0), V(0,0), V(0,0), V(1,3), 1, 1, SPECIAL(TEXBEM)), + _OPI(TEXBEML, TEX, V(0,0), V(0,0), V(0,0), V(1,3), 1, 1, SPECIAL(TEXBEM)), + _OPI(TEXREG2AR, TEX, V(0,0), V(0,0), V(0,0), V(1,3), 1, 1, SPECIAL(TEXREG2AR)), + _OPI(TEXREG2GB, TEX, V(0,0), V(0,0), V(0,0), V(1,3), 1, 1, SPECIAL(TEXREG2GB)), + _OPI(TEXM3x2PAD, TEX, V(0,0), V(0,0), V(0,0), V(1,3), 1, 1, SPECIAL(TEXM3x2PAD)), + _OPI(TEXM3x2TEX, TEX, V(0,0), V(0,0), V(0,0), V(1,3), 1, 1, SPECIAL(TEXM3x2TEX)), + _OPI(TEXM3x3PAD, TEX, V(0,0), V(0,0), V(0,0), V(1,3), 1, 1, SPECIAL(TEXM3x3PAD)), + _OPI(TEXM3x3TEX, TEX, V(0,0), V(0,0), V(0,0), V(1,3), 1, 1, SPECIAL(TEXM3x3)), + _OPI(TEXM3x3SPEC, TEX, V(0,0), V(0,0), V(0,0), V(1,3), 1, 2, SPECIAL(TEXM3x3SPEC)), + _OPI(TEXM3x3VSPEC, TEX, V(0,0), V(0,0), V(0,0), V(1,3), 1, 1, SPECIAL(TEXM3x3)), + + _OPI(EXPP, EXP, V(0,0), V(1,1), V(0,0), V(0,0), 1, 1, NULL), + _OPI(EXPP, EX2, V(2,0), V(3,0), V(0,0), V(0,0), 1, 1, NULL), + _OPI(LOGP, LG2, V(0,0), V(3,0), V(0,0), V(0,0), 1, 1, SPECIAL(LOG)), + _OPI(CND, NOP, V(0,0), V(0,0), V(0,0), V(1,4), 1, 3, SPECIAL(CND)), + + _OPI(DEF, NOP, V(0,0), V(3,0), V(0,0), V(3,0), 1, 0, SPECIAL(DEF)), + + /* More tex stuff */ + _OPI(TEXREG2RGB, TEX, V(0,0), V(0,0), V(1,2), V(1,3), 1, 1, SPECIAL(TEXREG2RGB)), + _OPI(TEXDP3TEX, TEX, V(0,0), V(0,0), V(1,2), V(1,3), 1, 1, SPECIAL(TEXDP3TEX)), + _OPI(TEXM3x2DEPTH, TEX, V(0,0), V(0,0), V(1,3), V(1,3), 1, 1, SPECIAL(TEXM3x2DEPTH)), + _OPI(TEXDP3, TEX, V(0,0), V(0,0), V(1,2), V(1,3), 1, 1, SPECIAL(TEXDP3)), + _OPI(TEXM3x3, TEX, V(0,0), V(0,0), V(1,2), V(1,3), 1, 1, SPECIAL(TEXM3x3)), + _OPI(TEXDEPTH, TEX, V(0,0), V(0,0), V(1,4), V(1,4), 1, 0, SPECIAL(TEXDEPTH)), + + /* Misc */ + _OPI(CMP, CMP, V(0,0), V(0,0), V(1,2), V(3,0), 1, 3, SPECIAL(CMP)), /* reversed */ + _OPI(BEM, NOP, V(0,0), V(0,0), V(1,4), V(1,4), 1, 2, SPECIAL(BEM)), + _OPI(DP2ADD, NOP, V(0,0), V(0,0), V(2,0), V(3,0), 1, 3, SPECIAL(DP2ADD)), + _OPI(DSX, DDX, V(0,0), V(0,0), V(2,1), V(3,0), 1, 1, NULL), + _OPI(DSY, DDY, V(0,0), V(0,0), V(2,1), V(3,0), 1, 1, NULL), + _OPI(TEXLDD, TXD, V(0,0), V(0,0), V(2,1), V(3,0), 1, 4, SPECIAL(TEXLDD)), + _OPI(SETP, NOP, V(0,0), V(3,0), V(2,1), V(3,0), 1, 2, SPECIAL(SETP)), + _OPI(TEXLDL, TXL, V(3,0), V(3,0), V(3,0), V(3,0), 1, 2, SPECIAL(TEXLDL)), + _OPI(BREAKP, BRK, V(0,0), V(3,0), V(2,1), V(3,0), 0, 1, SPECIAL(BREAKP)) +}; + +static const struct sm1_op_info inst_phase = + _OPI(PHASE, NOP, V(0,0), V(0,0), V(1,4), V(1,4), 0, 0, SPECIAL(PHASE)); + +static const struct sm1_op_info inst_comment = + _OPI(COMMENT, NOP, V(0,0), V(3,0), V(0,0), V(3,0), 0, 0, SPECIAL(COMMENT)); + +static void +create_op_info_map(struct shader_translator *tx) +{ + const unsigned version = (tx->version.major << 8) | tx->version.minor; + unsigned i; + + for (i = 0; i < ARRAY_SIZE(tx->op_info_map); ++i) + tx->op_info_map[i] = -1; + + if (tx->processor == PIPE_SHADER_VERTEX) { + for (i = 0; i < ARRAY_SIZE(inst_table); ++i) { + assert(inst_table[i].sio < ARRAY_SIZE(tx->op_info_map)); + if (inst_table[i].vert_version.min <= version && + inst_table[i].vert_version.max >= version) + tx->op_info_map[inst_table[i].sio] = i; + } + } else { + for (i = 0; i < ARRAY_SIZE(inst_table); ++i) { + assert(inst_table[i].sio < ARRAY_SIZE(tx->op_info_map)); + if (inst_table[i].frag_version.min <= version && + inst_table[i].frag_version.max >= version) + tx->op_info_map[inst_table[i].sio] = i; + } + } +} + +static inline HRESULT +NineTranslateInstruction_Generic(struct shader_translator *tx) +{ + struct ureg_dst dst[1]; + struct ureg_src src[4]; + unsigned i; + + for (i = 0; i < tx->insn.ndst && i < ARRAY_SIZE(dst); ++i) + dst[i] = tx_dst_param(tx, &tx->insn.dst[i]); + for (i = 0; i < tx->insn.nsrc && i < ARRAY_SIZE(src); ++i) + src[i] = tx_src_param(tx, &tx->insn.src[i]); + + ureg_insn(tx->ureg, tx->insn.info->opcode, + dst, tx->insn.ndst, + src, tx->insn.nsrc, 0); + return D3D_OK; +} + +static inline DWORD +TOKEN_PEEK(struct shader_translator *tx) +{ + return *(tx->parse); +} + +static inline DWORD +TOKEN_NEXT(struct shader_translator *tx) +{ + return *(tx->parse)++; +} + +static inline void +TOKEN_JUMP(struct shader_translator *tx) +{ + if (tx->parse_next && tx->parse != tx->parse_next) { + WARN("parse(%p) != parse_next(%p) !\n", tx->parse, tx->parse_next); + tx->parse = tx->parse_next; + } +} + +static inline boolean +sm1_parse_eof(struct shader_translator *tx) +{ + return TOKEN_PEEK(tx) == NINED3DSP_END; +} + +static void +sm1_read_version(struct shader_translator *tx) +{ + const DWORD tok = TOKEN_NEXT(tx); + + tx->version.major = D3DSHADER_VERSION_MAJOR(tok); + tx->version.minor = D3DSHADER_VERSION_MINOR(tok); + + switch (tok >> 16) { + case NINED3D_SM1_VS: tx->processor = PIPE_SHADER_VERTEX; break; + case NINED3D_SM1_PS: tx->processor = PIPE_SHADER_FRAGMENT; break; + default: + DBG("Invalid shader type: %x\n", tok); + tx->processor = ~0; + break; + } +} + +/* This is just to check if we parsed the instruction properly. */ +static void +sm1_parse_get_skip(struct shader_translator *tx) +{ + const DWORD tok = TOKEN_PEEK(tx); + + if (tx->version.major >= 2) { + tx->parse_next = tx->parse + 1 /* this */ + + ((tok & D3DSI_INSTLENGTH_MASK) >> D3DSI_INSTLENGTH_SHIFT); + } else { + tx->parse_next = NULL; /* TODO: determine from param count */ + } +} + +static void +sm1_print_comment(const char *comment, UINT size) +{ + if (!size) + return; + /* TODO */ +} + +static void +sm1_parse_comments(struct shader_translator *tx, BOOL print) +{ + DWORD tok = TOKEN_PEEK(tx); + + while ((tok & D3DSI_OPCODE_MASK) == D3DSIO_COMMENT) + { + const char *comment = ""; + UINT size = (tok & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT; + tx->parse += size + 1; + + if (print) + sm1_print_comment(comment, size); + + tok = TOKEN_PEEK(tx); + } +} + +static void +sm1_parse_get_param(struct shader_translator *tx, DWORD *reg, DWORD *rel) +{ + *reg = TOKEN_NEXT(tx); + + if (*reg & D3DSHADER_ADDRMODE_RELATIVE) + { + if (tx->version.major < 2) + *rel = (1 << 31) | + ((D3DSPR_ADDR << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2) | + ((D3DSPR_ADDR << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK) | + D3DSP_NOSWIZZLE; + else + *rel = TOKEN_NEXT(tx); + } +} + +static void +sm1_parse_dst_param(struct sm1_dst_param *dst, DWORD tok) +{ + int8_t shift; + dst->file = + (tok & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT | + (tok & D3DSP_REGTYPE_MASK2) >> D3DSP_REGTYPE_SHIFT2; + dst->type = TGSI_RETURN_TYPE_FLOAT; + dst->idx = tok & D3DSP_REGNUM_MASK; + dst->rel = NULL; + dst->mask = (tok & NINED3DSP_WRITEMASK_MASK) >> NINED3DSP_WRITEMASK_SHIFT; + dst->mod = (tok & D3DSP_DSTMOD_MASK) >> D3DSP_DSTMOD_SHIFT; + shift = (tok & D3DSP_DSTSHIFT_MASK) >> D3DSP_DSTSHIFT_SHIFT; + dst->shift = (shift & 0x7) - (shift & 0x8); +} + +static void +sm1_parse_src_param(struct sm1_src_param *src, DWORD tok) +{ + src->file = + ((tok & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT) | + ((tok & D3DSP_REGTYPE_MASK2) >> D3DSP_REGTYPE_SHIFT2); + src->type = TGSI_RETURN_TYPE_FLOAT; + src->idx = tok & D3DSP_REGNUM_MASK; + src->rel = NULL; + src->swizzle = (tok & D3DSP_SWIZZLE_MASK) >> D3DSP_SWIZZLE_SHIFT; + src->mod = (tok & D3DSP_SRCMOD_MASK) >> D3DSP_SRCMOD_SHIFT; + + switch (src->file) { + case D3DSPR_CONST2: src->file = D3DSPR_CONST; src->idx += 2048; break; + case D3DSPR_CONST3: src->file = D3DSPR_CONST; src->idx += 4096; break; + case D3DSPR_CONST4: src->file = D3DSPR_CONST; src->idx += 6144; break; + default: + break; + } +} + +static void +sm1_parse_immediate(struct shader_translator *tx, + struct sm1_src_param *imm) +{ + imm->file = NINED3DSPR_IMMEDIATE; + imm->idx = INT_MIN; + imm->rel = NULL; + imm->swizzle = NINED3DSP_NOSWIZZLE; + imm->mod = 0; + switch (tx->insn.opcode) { + case D3DSIO_DEF: + imm->type = NINED3DSPTYPE_FLOAT4; + memcpy(&imm->imm.d[0], tx->parse, 4 * sizeof(DWORD)); + tx->parse += 4; + break; + case D3DSIO_DEFI: + imm->type = NINED3DSPTYPE_INT4; + memcpy(&imm->imm.d[0], tx->parse, 4 * sizeof(DWORD)); + tx->parse += 4; + break; + case D3DSIO_DEFB: + imm->type = NINED3DSPTYPE_BOOL; + memcpy(&imm->imm.d[0], tx->parse, 1 * sizeof(DWORD)); + tx->parse += 1; + break; + default: + assert(0); + break; + } +} + +static void +sm1_read_dst_param(struct shader_translator *tx, + struct sm1_dst_param *dst, + struct sm1_src_param *rel) +{ + DWORD tok_dst, tok_rel = 0; + + sm1_parse_get_param(tx, &tok_dst, &tok_rel); + sm1_parse_dst_param(dst, tok_dst); + if (tok_dst & D3DSHADER_ADDRMODE_RELATIVE) { + sm1_parse_src_param(rel, tok_rel); + dst->rel = rel; + } +} + +static void +sm1_read_src_param(struct shader_translator *tx, + struct sm1_src_param *src, + struct sm1_src_param *rel) +{ + DWORD tok_src, tok_rel = 0; + + sm1_parse_get_param(tx, &tok_src, &tok_rel); + sm1_parse_src_param(src, tok_src); + if (tok_src & D3DSHADER_ADDRMODE_RELATIVE) { + assert(rel); + sm1_parse_src_param(rel, tok_rel); + src->rel = rel; + } +} + +static void +sm1_read_semantic(struct shader_translator *tx, + struct sm1_semantic *sem) +{ + const DWORD tok_usg = TOKEN_NEXT(tx); + const DWORD tok_dst = TOKEN_NEXT(tx); + + sem->sampler_type = (tok_usg & D3DSP_TEXTURETYPE_MASK) >> D3DSP_TEXTURETYPE_SHIFT; + sem->usage = (tok_usg & D3DSP_DCL_USAGE_MASK) >> D3DSP_DCL_USAGE_SHIFT; + sem->usage_idx = (tok_usg & D3DSP_DCL_USAGEINDEX_MASK) >> D3DSP_DCL_USAGEINDEX_SHIFT; + + sm1_parse_dst_param(&sem->reg, tok_dst); +} + +static void +sm1_parse_instruction(struct shader_translator *tx) +{ + struct sm1_instruction *insn = &tx->insn; + HRESULT hr; + DWORD tok; + const struct sm1_op_info *info = NULL; + unsigned i; + + sm1_parse_comments(tx, TRUE); + sm1_parse_get_skip(tx); + + tok = TOKEN_NEXT(tx); + + insn->opcode = tok & D3DSI_OPCODE_MASK; + insn->flags = (tok & NINED3DSIO_OPCODE_FLAGS_MASK) >> NINED3DSIO_OPCODE_FLAGS_SHIFT; + insn->coissue = !!(tok & D3DSI_COISSUE); + insn->predicated = !!(tok & NINED3DSHADER_INST_PREDICATED); + + if (insn->opcode < ARRAY_SIZE(tx->op_info_map)) { + int k = tx->op_info_map[insn->opcode]; + if (k >= 0) { + assert(k < ARRAY_SIZE(inst_table)); + info = &inst_table[k]; + } + } else { + if (insn->opcode == D3DSIO_PHASE) info = &inst_phase; + if (insn->opcode == D3DSIO_COMMENT) info = &inst_comment; + } + if (!info) { + DBG("illegal or unhandled opcode: %08x\n", insn->opcode); + TOKEN_JUMP(tx); + return; + } + insn->info = info; + insn->ndst = info->ndst; + insn->nsrc = info->nsrc; + + /* check version */ + { + unsigned min = IS_VS ? info->vert_version.min : info->frag_version.min; + unsigned max = IS_VS ? info->vert_version.max : info->frag_version.max; + unsigned ver = (tx->version.major << 8) | tx->version.minor; + if (ver < min || ver > max) { + DBG("opcode not supported in this shader version: %x <= %x <= %x\n", + min, ver, max); + return; + } + } + + for (i = 0; i < insn->ndst; ++i) + sm1_read_dst_param(tx, &insn->dst[i], &insn->dst_rel[i]); + if (insn->predicated) + sm1_read_src_param(tx, &insn->pred, NULL); + for (i = 0; i < insn->nsrc; ++i) + sm1_read_src_param(tx, &insn->src[i], &insn->src_rel[i]); + + /* parse here so we can dump them before processing */ + if (insn->opcode == D3DSIO_DEF || + insn->opcode == D3DSIO_DEFI || + insn->opcode == D3DSIO_DEFB) + sm1_parse_immediate(tx, &tx->insn.src[0]); + + sm1_dump_instruction(insn, tx->cond_depth + tx->loop_depth); + sm1_instruction_check(insn); + + if (insn->predicated) { + tx->predicated_activated = true; + if (ureg_dst_is_undef(tx->regs.predicate_tmp)) { + tx->regs.predicate_tmp = ureg_DECL_temporary(tx->ureg); + tx->regs.predicate_dst = ureg_DECL_temporary(tx->ureg); + } + } + + if (info->handler) + hr = info->handler(tx); + else + hr = NineTranslateInstruction_Generic(tx); + tx_apply_dst0_modifiers(tx); + + if (insn->predicated) { + tx->predicated_activated = false; + /* TODO: predicate might be allowed on outputs, + * which cannot be src. Workaround it. */ + ureg_CMP(tx->ureg, tx->regs.predicate_dst, + ureg_negate(tx_src_param(tx, &insn->pred)), + ureg_src(tx->regs.predicate_tmp), + ureg_src(tx->regs.predicate_dst)); + } + + if (hr != D3D_OK) + tx->failure = TRUE; + tx->num_scratch = 0; /* reset */ + + TOKEN_JUMP(tx); +} + +#define GET_CAP(n) screen->get_param( \ + screen, PIPE_CAP_##n) +#define GET_SHADER_CAP(n) screen->get_shader_param( \ + screen, info->type, PIPE_SHADER_CAP_##n) + +static HRESULT +tx_ctor(struct shader_translator *tx, struct pipe_screen *screen, struct nine_shader_info *info) +{ + unsigned i; + + memset(tx, 0, sizeof(*tx)); + + tx->info = info; + + tx->byte_code = info->byte_code; + tx->parse = info->byte_code; + + for (i = 0; i < ARRAY_SIZE(info->input_map); ++i) + info->input_map[i] = NINE_DECLUSAGE_NONE; + info->num_inputs = 0; + + info->position_t = FALSE; + info->point_size = FALSE; + + memset(tx->slots_used, 0, sizeof(tx->slots_used)); + memset(info->int_slots_used, 0, sizeof(info->int_slots_used)); + memset(info->bool_slots_used, 0, sizeof(info->bool_slots_used)); + + tx->info->const_float_slots = 0; + tx->info->const_int_slots = 0; + tx->info->const_bool_slots = 0; + + info->sampler_mask = 0x0; + info->rt_mask = 0x0; + + info->lconstf.data = NULL; + info->lconstf.ranges = NULL; + + info->bumpenvmat_needed = 0; + + for (i = 0; i < ARRAY_SIZE(tx->regs.rL); ++i) { + tx->regs.rL[i] = ureg_dst_undef(); + } + tx->regs.address = ureg_dst_undef(); + tx->regs.a0 = ureg_dst_undef(); + tx->regs.p = ureg_dst_undef(); + tx->regs.oDepth = ureg_dst_undef(); + tx->regs.vPos = ureg_src_undef(); + tx->regs.vFace = ureg_src_undef(); + for (i = 0; i < ARRAY_SIZE(tx->regs.o); ++i) + tx->regs.o[i] = ureg_dst_undef(); + for (i = 0; i < ARRAY_SIZE(tx->regs.oCol); ++i) + tx->regs.oCol[i] = ureg_dst_undef(); + for (i = 0; i < ARRAY_SIZE(tx->regs.vC); ++i) + tx->regs.vC[i] = ureg_src_undef(); + for (i = 0; i < ARRAY_SIZE(tx->regs.vT); ++i) + tx->regs.vT[i] = ureg_src_undef(); + + sm1_read_version(tx); + + info->version = (tx->version.major << 4) | tx->version.minor; + + tx->num_outputs = 0; + + create_op_info_map(tx); + + tx->ureg = ureg_create(info->type); + if (!tx->ureg) { + return E_OUTOFMEMORY; + } + + tx->native_integers = GET_SHADER_CAP(INTEGERS); + tx->inline_subroutines = !GET_SHADER_CAP(SUBROUTINES); + tx->want_texcoord = GET_CAP(TGSI_TEXCOORD); + tx->shift_wpos = !GET_CAP(TGSI_FS_COORD_PIXEL_CENTER_INTEGER); + tx->texcoord_sn = tx->want_texcoord ? + TGSI_SEMANTIC_TEXCOORD : TGSI_SEMANTIC_GENERIC; + tx->wpos_is_sysval = GET_CAP(TGSI_FS_POSITION_IS_SYSVAL); + tx->face_is_sysval_integer = GET_CAP(TGSI_FS_FACE_IS_INTEGER_SYSVAL); + + if (IS_VS) { + tx->num_constf_allowed = NINE_MAX_CONST_F; + } else if (tx->version.major < 2) {/* IS_PS v1 */ + tx->num_constf_allowed = 8; + } else if (tx->version.major == 2) {/* IS_PS v2 */ + tx->num_constf_allowed = 32; + } else {/* IS_PS v3 */ + tx->num_constf_allowed = NINE_MAX_CONST_F_PS3; + } + + if (tx->version.major < 2) { + tx->num_consti_allowed = 0; + tx->num_constb_allowed = 0; + } else { + tx->num_consti_allowed = NINE_MAX_CONST_I; + tx->num_constb_allowed = NINE_MAX_CONST_B; + } + + if (info->swvp_on && tx->version.major >= 2) { + tx->num_constf_allowed = 8192; + tx->num_consti_allowed = 2048; + tx->num_constb_allowed = 2048; + } + + /* VS must always write position. Declare it here to make it the 1st output. + * (Some drivers like nv50 are buggy and rely on that.) + */ + if (IS_VS) { + tx->regs.oPos = ureg_DECL_output(tx->ureg, TGSI_SEMANTIC_POSITION, 0); + } else { + ureg_property(tx->ureg, TGSI_PROPERTY_FS_COORD_ORIGIN, TGSI_FS_COORD_ORIGIN_UPPER_LEFT); + if (!tx->shift_wpos) + ureg_property(tx->ureg, TGSI_PROPERTY_FS_COORD_PIXEL_CENTER, TGSI_FS_COORD_PIXEL_CENTER_INTEGER); + } + + tx->mul_zero_wins = GET_CAP(TGSI_MUL_ZERO_WINS); + if (tx->mul_zero_wins) + ureg_property(tx->ureg, TGSI_PROPERTY_MUL_ZERO_WINS, 1); + + /* Add additional definition of constants */ + if (info->add_constants_defs.c_combination) { + unsigned i; + + assert(info->add_constants_defs.int_const_added); + assert(info->add_constants_defs.bool_const_added); + /* We only add constants that are used by the shader + * and that are not defined in the shader */ + for (i = 0; i < NINE_MAX_CONST_I; ++i) { + if ((*info->add_constants_defs.int_const_added)[i]) { + DBG("Defining const i%i : { %i %i %i %i }\n", i, + info->add_constants_defs.c_combination->const_i[i][0], + info->add_constants_defs.c_combination->const_i[i][1], + info->add_constants_defs.c_combination->const_i[i][2], + info->add_constants_defs.c_combination->const_i[i][3]); + tx_set_lconsti(tx, i, info->add_constants_defs.c_combination->const_i[i]); + } + } + for (i = 0; i < NINE_MAX_CONST_B; ++i) { + if ((*info->add_constants_defs.bool_const_added)[i]) { + DBG("Defining const b%i : %i\n", i, (int)(info->add_constants_defs.c_combination->const_b[i] != 0)); + tx_set_lconstb(tx, i, info->add_constants_defs.c_combination->const_b[i]); + } + } + } + return D3D_OK; +} + +static void +tx_dtor(struct shader_translator *tx) +{ + if (tx->slot_map) + FREE(tx->slot_map); + if (tx->num_inst_labels) + FREE(tx->inst_labels); + FREE(tx->lconstf); + FREE(tx->regs.r); + FREE(tx); +} + +/* CONST[0].xyz = width/2, -height/2, zmax-zmin + * CONST[1].xyz = x+width/2, y+height/2, zmin */ +static void +shader_add_vs_viewport_transform(struct shader_translator *tx) +{ + struct ureg_program *ureg = tx->ureg; + struct ureg_src c0 = ureg_src_register(TGSI_FILE_CONSTANT, 0); + struct ureg_src c1 = ureg_src_register(TGSI_FILE_CONSTANT, 1); + /* struct ureg_dst pos_tmp = ureg_DECL_temporary(ureg);*/ + + c0 = ureg_src_dimension(c0, 4); + c1 = ureg_src_dimension(c1, 4); + /* TODO: find out when we need to apply the viewport transformation or not. + * Likely will be XYZ vs XYZRHW in vdecl_out + * ureg_MUL(ureg, ureg_writemask(pos_tmp, TGSI_WRITEMASK_XYZ), ureg_src(tx->regs.oPos), c0); + * ureg_ADD(ureg, ureg_writemask(tx->regs.oPos_out, TGSI_WRITEMASK_XYZ), ureg_src(pos_tmp), c1); + */ + ureg_MOV(ureg, ureg_writemask(tx->regs.oPos_out, TGSI_WRITEMASK_XYZ), ureg_src(tx->regs.oPos)); +} + +static void +shader_add_ps_fog_stage(struct shader_translator *tx, struct ureg_src src_col) +{ + struct ureg_program *ureg = tx->ureg; + struct ureg_dst oCol0 = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0); + struct ureg_src fog_end, fog_coeff, fog_density, fog_params; + struct ureg_src fog_vs, fog_color; + struct ureg_dst fog_factor, depth; + + if (!tx->info->fog_enable) { + ureg_MOV(ureg, oCol0, src_col); + return; + } + + if (tx->info->fog_mode != D3DFOG_NONE) { + depth = tx_scratch_scalar(tx); + /* Depth used for fog is perspective interpolated */ + ureg_RCP(ureg, depth, ureg_scalar(nine_get_position_input(tx), TGSI_SWIZZLE_W)); + ureg_MUL(ureg, depth, ureg_src(depth), ureg_scalar(nine_get_position_input(tx), TGSI_SWIZZLE_Z)); + } + + fog_color = nine_float_constant_src(tx, 32); + fog_params = nine_float_constant_src(tx, 33); + fog_factor = tx_scratch_scalar(tx); + + if (tx->info->fog_mode == D3DFOG_LINEAR) { + fog_end = NINE_APPLY_SWIZZLE(fog_params, X); + fog_coeff = NINE_APPLY_SWIZZLE(fog_params, Y); + ureg_ADD(ureg, fog_factor, fog_end, ureg_negate(ureg_src(depth))); + ureg_MUL(ureg, ureg_saturate(fog_factor), tx_src_scalar(fog_factor), fog_coeff); + } else if (tx->info->fog_mode == D3DFOG_EXP) { + fog_density = NINE_APPLY_SWIZZLE(fog_params, X); + ureg_MUL(ureg, fog_factor, ureg_src(depth), fog_density); + ureg_MUL(ureg, fog_factor, tx_src_scalar(fog_factor), ureg_imm1f(ureg, -1.442695f)); + ureg_EX2(ureg, fog_factor, tx_src_scalar(fog_factor)); + } else if (tx->info->fog_mode == D3DFOG_EXP2) { + fog_density = NINE_APPLY_SWIZZLE(fog_params, X); + ureg_MUL(ureg, fog_factor, ureg_src(depth), fog_density); + ureg_MUL(ureg, fog_factor, tx_src_scalar(fog_factor), tx_src_scalar(fog_factor)); + ureg_MUL(ureg, fog_factor, tx_src_scalar(fog_factor), ureg_imm1f(ureg, -1.442695f)); + ureg_EX2(ureg, fog_factor, tx_src_scalar(fog_factor)); + } else { + fog_vs = ureg_scalar(ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_GENERIC, 16, + TGSI_INTERPOLATE_PERSPECTIVE), + TGSI_SWIZZLE_X); + ureg_MOV(ureg, fog_factor, fog_vs); + } + + ureg_LRP(ureg, ureg_writemask(oCol0, TGSI_WRITEMASK_XYZ), + tx_src_scalar(fog_factor), src_col, fog_color); + ureg_MOV(ureg, ureg_writemask(oCol0, TGSI_WRITEMASK_W), src_col); +} + +static void parse_shader(struct shader_translator *tx) +{ + struct nine_shader_info *info = tx->info; + + while (!sm1_parse_eof(tx) && !tx->failure) + sm1_parse_instruction(tx); + tx->parse++; /* for byte_size */ + + if (tx->failure) + return; + + if (IS_PS && tx->version.major < 3) { + if (tx->version.major < 2) { + assert(tx->num_temp); /* there must be color output */ + info->rt_mask |= 0x1; + shader_add_ps_fog_stage(tx, ureg_src(tx->regs.r[0])); + } else { + shader_add_ps_fog_stage(tx, ureg_src(tx->regs.oCol[0])); + } + } + + if (IS_VS && tx->version.major < 3 && ureg_dst_is_undef(tx->regs.oFog) && info->fog_enable) { + tx->regs.oFog = ureg_DECL_output(tx->ureg, TGSI_SEMANTIC_GENERIC, 16); + ureg_MOV(tx->ureg, ureg_writemask(tx->regs.oFog, TGSI_WRITEMASK_X), ureg_imm1f(tx->ureg, 0.0f)); + } + + if (info->position_t) + ureg_property(tx->ureg, TGSI_PROPERTY_VS_WINDOW_SPACE_POSITION, TRUE); + + if (IS_VS && !ureg_dst_is_undef(tx->regs.oPts)) { + struct ureg_dst oPts = ureg_DECL_output(tx->ureg, TGSI_SEMANTIC_PSIZE, 0); + ureg_MAX(tx->ureg, tx->regs.oPts, ureg_src(tx->regs.oPts), ureg_imm1f(tx->ureg, info->point_size_min)); + ureg_MIN(tx->ureg, oPts, ureg_src(tx->regs.oPts), ureg_imm1f(tx->ureg, info->point_size_max)); + info->point_size = TRUE; + } + + if (info->process_vertices) + shader_add_vs_viewport_transform(tx); + + ureg_END(tx->ureg); +} + +#define NINE_SHADER_DEBUG_OPTION_NIR_VS (1 << 0) +#define NINE_SHADER_DEBUG_OPTION_NIR_PS (1 << 1) +#define NINE_SHADER_DEBUG_OPTION_NO_NIR_VS (1 << 2) +#define NINE_SHADER_DEBUG_OPTION_NO_NIR_PS (1 << 3) +#define NINE_SHADER_DEBUG_OPTION_DUMP_NIR (1 << 4) +#define NINE_SHADER_DEBUG_OPTION_DUMP_TGSI (1 << 5) + +static const struct debug_named_value nine_shader_debug_options[] = { + { "nir_vs", NINE_SHADER_DEBUG_OPTION_NIR_VS, "Use NIR for vertex shaders even if the driver doesn't prefer it." }, + { "nir_ps", NINE_SHADER_DEBUG_OPTION_NIR_PS, "Use NIR for pixel shaders even if the driver doesn't prefer it." }, + { "no_nir_vs", NINE_SHADER_DEBUG_OPTION_NO_NIR_VS, "Never use NIR for vertex shaders even if the driver prefers it." }, + { "no_nir_ps", NINE_SHADER_DEBUG_OPTION_NO_NIR_PS, "Never use NIR for pixel shaders even if the driver prefers it." }, + { "dump_nir", NINE_SHADER_DEBUG_OPTION_DUMP_NIR, "Print translated NIR shaders." }, + { "dump_tgsi", NINE_SHADER_DEBUG_OPTION_DUMP_TGSI, "Print TGSI shaders." }, + DEBUG_NAMED_VALUE_END /* must be last */ +}; + +static inline boolean +nine_shader_get_debug_flag(uint64_t flag) +{ + static uint64_t flags = 0; + static boolean first_run = TRUE; + + if (unlikely(first_run)) { + first_run = FALSE; + flags = debug_get_flags_option("NINE_SHADER", nine_shader_debug_options, 0); + + // Check old TGSI dump envvar too + if (debug_get_bool_option("NINE_TGSI_DUMP", FALSE)) { + flags |= NINE_SHADER_DEBUG_OPTION_DUMP_TGSI; + } + } + + return !!(flags & flag); +} + +static void +nine_pipe_nir_shader_state_from_tgsi(struct pipe_shader_state *state, const struct tgsi_token *tgsi_tokens, + struct pipe_screen *screen) +{ + struct nir_shader *nir = tgsi_to_nir(tgsi_tokens, screen); + + if (unlikely(nine_shader_get_debug_flag(NINE_SHADER_DEBUG_OPTION_DUMP_NIR))) { + nir_print_shader(nir, stdout); + } + + state->type = PIPE_SHADER_IR_NIR; + state->tokens = NULL; + state->ir.nir = nir; + memset(&state->stream_output, 0, sizeof(state->stream_output)); +} + +static void * +nine_ureg_create_shader(struct ureg_program *ureg, + struct pipe_context *pipe, + const struct pipe_stream_output_info *so) +{ + struct pipe_shader_state state; + const struct tgsi_token *tgsi_tokens; + struct pipe_screen *screen = pipe->screen; + + tgsi_tokens = ureg_finalize(ureg); + if (!tgsi_tokens) + return NULL; + + assert(((struct tgsi_header *) &tgsi_tokens[0])->HeaderSize >= 2); + enum pipe_shader_type shader_type = ((struct tgsi_processor *) &tgsi_tokens[1])->Processor; + + int preferred_ir = screen->get_shader_param(screen, shader_type, PIPE_SHADER_CAP_PREFERRED_IR); + bool prefer_nir = (preferred_ir == PIPE_SHADER_IR_NIR); + bool use_nir = prefer_nir || + ((shader_type == PIPE_SHADER_VERTEX) && nine_shader_get_debug_flag(NINE_SHADER_DEBUG_OPTION_NIR_VS)) || + ((shader_type == PIPE_SHADER_FRAGMENT) && nine_shader_get_debug_flag(NINE_SHADER_DEBUG_OPTION_NIR_PS)); + + /* Allow user to override preferred IR, this is very useful for debugging */ + if (unlikely(shader_type == PIPE_SHADER_VERTEX && nine_shader_get_debug_flag(NINE_SHADER_DEBUG_OPTION_NO_NIR_VS))) + use_nir = false; + if (unlikely(shader_type == PIPE_SHADER_FRAGMENT && nine_shader_get_debug_flag(NINE_SHADER_DEBUG_OPTION_NO_NIR_PS))) + use_nir = false; + + DUMP("shader type: %s, preferred IR: %s, selected IR: %s\n", + shader_type == PIPE_SHADER_VERTEX ? "VS" : "PS", + prefer_nir ? "NIR" : "TGSI", + use_nir ? "NIR" : "TGSI"); + + if (use_nir) { + nine_pipe_nir_shader_state_from_tgsi(&state, tgsi_tokens, screen); + } else { + pipe_shader_state_from_tgsi(&state, tgsi_tokens); + } + + assert(state.tokens || state.ir.nir); + + if (so) + state.stream_output = *so; + + switch (shader_type) { + case PIPE_SHADER_VERTEX: + return pipe->create_vs_state(pipe, &state); + case PIPE_SHADER_FRAGMENT: + return pipe->create_fs_state(pipe, &state); + default: + unreachable("unsupported shader type"); + } +} + + +void * +nine_create_shader_with_so_and_destroy(struct ureg_program *p, + struct pipe_context *pipe, + const struct pipe_stream_output_info *so) +{ + void *result = nine_ureg_create_shader(p, pipe, so); + ureg_destroy(p); + return result; +} + +HRESULT +nine_translate_shader(struct NineDevice9 *device, struct nine_shader_info *info, struct pipe_context *pipe) +{ + struct shader_translator *tx; + HRESULT hr = D3D_OK; + const unsigned processor = info->type; + struct pipe_screen *screen = info->process_vertices ? device->screen_sw : device->screen; + unsigned *const_ranges = NULL; + + user_assert(processor != ~0, D3DERR_INVALIDCALL); + + tx = MALLOC_STRUCT(shader_translator); + if (!tx) + return E_OUTOFMEMORY; + + if (tx_ctor(tx, screen, info) == E_OUTOFMEMORY) { + hr = E_OUTOFMEMORY; + goto out; + } + + assert(IS_VS || !info->swvp_on); + + if (((tx->version.major << 16) | tx->version.minor) > 0x00030000) { + hr = D3DERR_INVALIDCALL; + DBG("Unsupported shader version: %u.%u !\n", + tx->version.major, tx->version.minor); + goto out; + } + if (tx->processor != processor) { + hr = D3DERR_INVALIDCALL; + DBG("Shader type mismatch: %u / %u !\n", tx->processor, processor); + goto out; + } + DUMP("%s%u.%u\n", processor == PIPE_SHADER_VERTEX ? "VS" : "PS", + tx->version.major, tx->version.minor); + + parse_shader(tx); + + if (tx->failure) { + /* For VS shaders, we print the warning later, + * we first try with swvp. */ + if (IS_PS) + ERR("Encountered buggy shader\n"); + ureg_destroy(tx->ureg); + hr = D3DERR_INVALIDCALL; + goto out; + } + + /* Recompile after compacting constant slots if possible */ + if (!tx->indirect_const_access && !info->swvp_on && tx->num_slots > 0) { + unsigned *slot_map; + unsigned c; + int i, j, num_ranges, prev; + + DBG("Recompiling shader for constant compaction\n"); + ureg_destroy(tx->ureg); + + if (tx->num_inst_labels) + FREE(tx->inst_labels); + FREE(tx->lconstf); + FREE(tx->regs.r); + + num_ranges = 0; + prev = -2; + for (i = 0; i < NINE_MAX_CONST_ALL; i++) { + if (tx->slots_used[i]) { + if (prev != i - 1) + num_ranges++; + prev = i; + } + } + slot_map = MALLOC(NINE_MAX_CONST_ALL * sizeof(unsigned)); + const_ranges = CALLOC(num_ranges + 1, 2 * sizeof(unsigned)); /* ranges stop when last is of size 0 */ + if (!slot_map || !const_ranges) { + hr = E_OUTOFMEMORY; + goto out; + } + c = 0; + j = -1; + prev = -2; + for (i = 0; i < NINE_MAX_CONST_ALL; i++) { + if (tx->slots_used[i]) { + if (prev != i - 1) + j++; + /* Initialize first slot of the range */ + if (!const_ranges[2*j+1]) + const_ranges[2*j] = i; + const_ranges[2*j+1]++; + prev = i; + slot_map[i] = c++; + } + } + + if (tx_ctor(tx, screen, info) == E_OUTOFMEMORY) { + hr = E_OUTOFMEMORY; + goto out; + } + tx->slot_map = slot_map; + parse_shader(tx); + assert(!tx->failure); +#if !defined(NDEBUG) + i = 0; + j = 0; + while (const_ranges[i*2+1] != 0) { + j += const_ranges[i*2+1]; + i++; + } + assert(j == tx->num_slots); +#endif + } + + /* record local constants */ + if (tx->num_lconstf && tx->indirect_const_access) { + struct nine_range *ranges; + float *data; + int *indices; + unsigned i, k, n; + + hr = E_OUTOFMEMORY; + + data = MALLOC(tx->num_lconstf * 4 * sizeof(float)); + if (!data) + goto out; + info->lconstf.data = data; + + indices = MALLOC(tx->num_lconstf * sizeof(indices[0])); + if (!indices) + goto out; + + /* lazy sort, num_lconstf should be small */ + for (n = 0; n < tx->num_lconstf; ++n) { + for (k = 0, i = 0; i < tx->num_lconstf; ++i) { + if (tx->lconstf[i].idx < tx->lconstf[k].idx) + k = i; + } + indices[n] = tx->lconstf[k].idx; + memcpy(&data[n * 4], &tx->lconstf[k].f[0], 4 * sizeof(float)); + tx->lconstf[k].idx = INT_MAX; + } + + /* count ranges */ + for (n = 1, i = 1; i < tx->num_lconstf; ++i) + if (indices[i] != indices[i - 1] + 1) + ++n; + ranges = MALLOC(n * sizeof(ranges[0])); + if (!ranges) { + FREE(indices); + goto out; + } + info->lconstf.ranges = ranges; + + k = 0; + ranges[k].bgn = indices[0]; + for (i = 1; i < tx->num_lconstf; ++i) { + if (indices[i] != indices[i - 1] + 1) { + ranges[k].next = &ranges[k + 1]; + ranges[k].end = indices[i - 1] + 1; + ++k; + ranges[k].bgn = indices[i]; + } + } + ranges[k].end = indices[i - 1] + 1; + ranges[k].next = NULL; + assert(n == (k + 1)); + + FREE(indices); + hr = D3D_OK; + } + + /* r500 */ + if (info->const_float_slots > device->max_vs_const_f && + (info->const_int_slots || info->const_bool_slots) && + !info->swvp_on) + ERR("Overlapping constant slots. The shader is likely to be buggy\n"); + + + if (tx->indirect_const_access) { /* vs only */ + info->const_float_slots = device->max_vs_const_f; + tx->num_slots = MAX2(tx->num_slots, device->max_vs_const_f); + } + + if (!info->swvp_on) { + info->const_used_size = sizeof(float[4]) * tx->num_slots; + if (tx->num_slots) + ureg_DECL_constant2D(tx->ureg, 0, tx->num_slots-1, 0); + } else { + ureg_DECL_constant2D(tx->ureg, 0, 4095, 0); + ureg_DECL_constant2D(tx->ureg, 0, 4095, 1); + ureg_DECL_constant2D(tx->ureg, 0, 2047, 2); + ureg_DECL_constant2D(tx->ureg, 0, 511, 3); + } + + if (info->process_vertices) + ureg_DECL_constant2D(tx->ureg, 0, 2, 4); /* Viewport data */ + + if (unlikely(nine_shader_get_debug_flag(NINE_SHADER_DEBUG_OPTION_DUMP_TGSI))) { + const struct tgsi_token *toks = ureg_get_tokens(tx->ureg, NULL); + tgsi_dump(toks, 0); + ureg_free_tokens(toks); + } + + if (info->process_vertices) { + NineVertexDeclaration9_FillStreamOutputInfo(info->vdecl_out, + tx->output_info, + tx->num_outputs, + &(info->so)); + info->cso = nine_create_shader_with_so_and_destroy(tx->ureg, pipe, &(info->so)); + } else + info->cso = nine_create_shader_with_so_and_destroy(tx->ureg, pipe, NULL); + if (!info->cso) { + hr = D3DERR_DRIVERINTERNALERROR; + FREE(info->lconstf.data); + FREE(info->lconstf.ranges); + goto out; + } + + info->const_ranges = const_ranges; + const_ranges = NULL; + info->byte_size = (tx->parse - tx->byte_code) * sizeof(DWORD); +out: + if (const_ranges) + FREE(const_ranges); + tx_dtor(tx); + return hr; +} diff --git a/src/gallium/frontends/nine/nine_shader.h b/src/gallium/frontends/nine/nine_shader.h new file mode 100644 index 00000000000..5abdbe24472 --- /dev/null +++ b/src/gallium/frontends/nine/nine_shader.h @@ -0,0 +1,327 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _NINE_SHADER_H_ +#define _NINE_SHADER_H_ + +#include "d3d9types.h" +#include "d3d9caps.h" +#include "nine_defines.h" +#include "nine_helpers.h" +#include "nine_state.h" +#include "pipe/p_state.h" /* PIPE_MAX_ATTRIBS */ +#include "util/u_memory.h" + +struct NineDevice9; +struct NineVertexDeclaration9; +struct ureg_program; + +struct nine_lconstf /* NOTE: both pointers should be FREE'd by the user */ +{ + struct nine_range *ranges; /* single MALLOC, but next-pointers valid */ + float *data; +}; + +struct nine_shader_constant_combination; + +struct nine_shader_info +{ + unsigned type; /* in, PIPE_SHADER_x */ + + uint8_t version; /* (major << 4) | minor */ + + const DWORD *byte_code; /* in, pointer to shader tokens */ + DWORD byte_size; /* out, size of data at byte_code */ + + void *cso; /* out, pipe cso for bind_vs,fs_state */ + + uint16_t input_map[PIPE_MAX_ATTRIBS]; /* VS input -> NINE_DECLUSAGE_x */ + uint8_t num_inputs; /* there may be unused inputs (NINE_DECLUSAGE_NONE) */ + + boolean position_t; /* out, true if VP writes pre-transformed position */ + boolean point_size; /* out, true if VP writes point size */ + float point_size_min; + float point_size_max; + + uint32_t sampler_ps1xtypes; /* 2 bits per sampler */ + uint16_t sampler_mask; /* out, which samplers are being used */ + uint16_t sampler_mask_shadow; /* in, which samplers use depth compare */ + uint8_t rt_mask; /* out, which render targets are being written */ + + uint8_t fog_enable; + uint8_t fog_mode; + uint8_t force_color_in_centroid; + uint8_t projected; /* ps 1.1 to 1.3 */ + + unsigned const_i_base; /* in vec4 (16 byte) units */ + unsigned const_b_base; /* in vec4 (16 byte) units */ + unsigned const_used_size; + + boolean int_slots_used[NINE_MAX_CONST_I]; + boolean bool_slots_used[NINE_MAX_CONST_B]; + + unsigned const_float_slots; + unsigned const_int_slots; + unsigned const_bool_slots; + + unsigned *const_ranges; + + struct nine_lconstf lconstf; /* out, NOTE: members to be free'd by user */ + uint8_t bumpenvmat_needed; + + struct { + struct nine_shader_constant_combination* c_combination; + boolean (*int_const_added)[NINE_MAX_CONST_I]; + boolean (*bool_const_added)[NINE_MAX_CONST_B]; + } add_constants_defs; + + boolean swvp_on; + + boolean process_vertices; + struct NineVertexDeclaration9 *vdecl_out; + struct pipe_stream_output_info so; +}; + +struct nine_vs_output_info +{ + BYTE output_semantic; + int output_semantic_index; + int mask; + int output_index; +}; + +void * +nine_create_shader_with_so_and_destroy(struct ureg_program *p, + struct pipe_context *pipe, + const struct pipe_stream_output_info *so); + +HRESULT +nine_translate_shader(struct NineDevice9 *device, + struct nine_shader_info *, + struct pipe_context *); + + +struct nine_shader_variant +{ + struct nine_shader_variant *next; + void *cso; + unsigned *const_ranges; + unsigned const_used_size; + uint64_t key; +}; + +static inline void * +nine_shader_variant_get(struct nine_shader_variant *list, + unsigned **const_ranges, + unsigned *const_used_size, + uint64_t key) +{ + while (list->key != key && list->next) + list = list->next; + if (list->key == key) { + *const_ranges = list->const_ranges; + *const_used_size = list->const_used_size; + return list->cso; + } + return NULL; +} + +static inline boolean +nine_shader_variant_add(struct nine_shader_variant *list, + uint64_t key, void *cso, + unsigned *const_ranges, + unsigned const_used_size) +{ + while (list->next) { + assert(list->key != key); + list = list->next; + } + list->next = MALLOC_STRUCT(nine_shader_variant); + if (!list->next) + return FALSE; + list->next->next = NULL; + list->next->key = key; + list->next->cso = cso; + list->next->const_ranges = const_ranges; + list->next->const_used_size = const_used_size; + return TRUE; +} + +static inline void +nine_shader_variants_free(struct nine_shader_variant *list) +{ + while (list->next) { + struct nine_shader_variant *ptr = list->next; + list->next = ptr->next; + FREE(ptr); + } +} + +struct nine_shader_variant_so +{ + struct nine_shader_variant_so *next; + struct NineVertexDeclaration9 *vdecl; + struct pipe_stream_output_info so; + void *cso; +}; + +static inline void * +nine_shader_variant_so_get(struct nine_shader_variant_so *list, + struct NineVertexDeclaration9 *vdecl, + struct pipe_stream_output_info *so) +{ + while (list->vdecl != vdecl && list->next) + list = list->next; + if (list->vdecl == vdecl) { + *so = list->so; + return list->cso; + } + return NULL; +} + +static inline boolean +nine_shader_variant_so_add(struct nine_shader_variant_so *list, + struct NineVertexDeclaration9 *vdecl, + struct pipe_stream_output_info *so, void *cso) +{ + if (list->vdecl == NULL) { /* first shader */ + list->next = NULL; + nine_bind(&list->vdecl, vdecl); + list->so = *so; + list->cso = cso; + return TRUE; + } + while (list->next) { + assert(list->vdecl != vdecl); + list = list->next; + } + list->next = MALLOC_STRUCT(nine_shader_variant_so); + if (!list->next) + return FALSE; + list->next->next = NULL; + nine_bind(&list->vdecl, vdecl); + list->next->so = *so; + list->next->cso = cso; + return TRUE; +} + +static inline void +nine_shader_variants_so_free(struct nine_shader_variant_so *list) +{ + while (list->next) { + struct nine_shader_variant_so *ptr = list->next; + list->next = ptr->next; + nine_bind(&ptr->vdecl, NULL); + FREE(ptr); + } + if (list->vdecl) + nine_bind(&list->vdecl, NULL); +} + +struct nine_shader_constant_combination +{ + struct nine_shader_constant_combination *next; + int const_i[NINE_MAX_CONST_I][4]; + BOOL const_b[NINE_MAX_CONST_B]; +}; + +#define NINE_MAX_CONSTANT_COMBINATION_VARIANTS 32 + +static inline uint8_t +nine_shader_constant_combination_key(struct nine_shader_constant_combination **list, + boolean *int_slots_used, + boolean *bool_slots_used, + int *const_i, + BOOL *const_b) +{ + int i; + uint8_t index = 0; + boolean match; + struct nine_shader_constant_combination **next_allocate = list, *current = *list; + + assert(int_slots_used); + assert(bool_slots_used); + assert(const_i); + assert(const_b); + + while (current) { + index++; /* start at 1. 0 is for the variant without constant replacement */ + match = TRUE; + for (i = 0; i < NINE_MAX_CONST_I; ++i) { + if (int_slots_used[i]) + match &= !memcmp(const_i + 4*i, current->const_i[i], sizeof(current->const_i[0])); + } + for (i = 0; i < NINE_MAX_CONST_B; ++i) { + if (bool_slots_used[i]) + match &= const_b[i] == current->const_b[i]; + } + if (match) + return index; + next_allocate = ¤t->next; + current = current->next; + } + + if (index < NINE_MAX_CONSTANT_COMBINATION_VARIANTS) { + *next_allocate = MALLOC_STRUCT(nine_shader_constant_combination); + current = *next_allocate; + index++; + current->next = NULL; + memcpy(current->const_i, const_i, sizeof(current->const_i)); + memcpy(current->const_b, const_b, sizeof(current->const_b)); + return index; + } + + return 0; /* Too many variants, revert to no replacement */ +} + +static inline struct nine_shader_constant_combination * +nine_shader_constant_combination_get(struct nine_shader_constant_combination *list, uint8_t index) +{ + if (index == 0) + return NULL; + while (index) { + assert(list != NULL); + index--; + if (index == 0) + return list; + list = list->next; + } + assert(FALSE); + return NULL; +} + +static inline void +nine_shader_constant_combination_free(struct nine_shader_constant_combination *list) +{ + if (!list) + return; + + while (list->next) { + struct nine_shader_constant_combination *ptr = list->next; + list->next = ptr->next; + FREE(ptr); + } + + FREE(list); +} + +#endif /* _NINE_SHADER_H_ */ diff --git a/src/gallium/frontends/nine/nine_state.c b/src/gallium/frontends/nine/nine_state.c new file mode 100644 index 00000000000..8724ec87c81 --- /dev/null +++ b/src/gallium/frontends/nine/nine_state.c @@ -0,0 +1,3710 @@ +/* + * Copyright 2011 Joakim Sindholt + * Copyright 2013 Christoph Bumiller + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#define NINE_STATE + +#include "device9.h" +#include "swapchain9.h" +#include "basetexture9.h" +#include "buffer9.h" +#include "indexbuffer9.h" +#include "surface9.h" +#include "vertexbuffer9.h" +#include "vertexdeclaration9.h" +#include "vertexshader9.h" +#include "pixelshader9.h" +#include "nine_pipe.h" +#include "nine_ff.h" +#include "nine_limits.h" +#include "pipe/p_context.h" +#include "pipe/p_state.h" +#include "cso_cache/cso_context.h" +#include "util/u_atomic.h" +#include "util/u_upload_mgr.h" +#include "util/u_math.h" +#include "util/u_box.h" +#include "util/u_simple_shaders.h" +#include "util/u_gen_mipmap.h" + +/* CSMT headers */ +#include "nine_queue.h" +#include "nine_csmt_helper.h" +#include "os/os_thread.h" + +#define DBG_CHANNEL DBG_DEVICE + +/* Nine CSMT */ + +struct csmt_instruction { + int (* func)(struct NineDevice9 *This, struct csmt_instruction *instr); +}; + +struct csmt_context { + thrd_t worker; + struct nine_queue_pool* pool; + BOOL terminate; + cnd_t event_processed; + mtx_t mutex_processed; + struct NineDevice9 *device; + BOOL processed; + BOOL toPause; + BOOL hasPaused; + mtx_t thread_running; + mtx_t thread_resume; +}; + +/* Wait for instruction to be processed. + * Caller has to ensure that only one thread waits at time. + */ +static void +nine_csmt_wait_processed(struct csmt_context *ctx) +{ + mtx_lock(&ctx->mutex_processed); + while (!p_atomic_read(&ctx->processed)) { + cnd_wait(&ctx->event_processed, &ctx->mutex_processed); + } + mtx_unlock(&ctx->mutex_processed); +} + +/* CSMT worker thread */ +static +int +nine_csmt_worker(void *arg) +{ + struct csmt_context *ctx = arg; + struct csmt_instruction *instr; + DBG("CSMT worker spawned\n"); + + u_thread_setname("CSMT-Worker"); + + while (1) { + nine_queue_wait_flush(ctx->pool); + mtx_lock(&ctx->thread_running); + + /* Get instruction. NULL on empty cmdbuf. */ + while (!p_atomic_read(&ctx->terminate) && + (instr = (struct csmt_instruction *)nine_queue_get(ctx->pool))) { + + /* decode */ + if (instr->func(ctx->device, instr)) { + mtx_lock(&ctx->mutex_processed); + p_atomic_set(&ctx->processed, TRUE); + cnd_signal(&ctx->event_processed); + mtx_unlock(&ctx->mutex_processed); + } + if (p_atomic_read(&ctx->toPause)) { + mtx_unlock(&ctx->thread_running); + /* will wait here the thread can be resumed */ + mtx_lock(&ctx->thread_resume); + mtx_lock(&ctx->thread_running); + mtx_unlock(&ctx->thread_resume); + } + } + + mtx_unlock(&ctx->thread_running); + if (p_atomic_read(&ctx->terminate)) { + mtx_lock(&ctx->mutex_processed); + p_atomic_set(&ctx->processed, TRUE); + cnd_signal(&ctx->event_processed); + mtx_unlock(&ctx->mutex_processed); + break; + } + } + + DBG("CSMT worker destroyed\n"); + return 0; +} + +/* Create a CSMT context. + * Spawns a worker thread. + */ +struct csmt_context * +nine_csmt_create( struct NineDevice9 *This ) +{ + struct csmt_context *ctx; + + ctx = CALLOC_STRUCT(csmt_context); + if (!ctx) + return NULL; + + ctx->pool = nine_queue_create(); + if (!ctx->pool) { + FREE(ctx); + return NULL; + } + cnd_init(&ctx->event_processed); + (void) mtx_init(&ctx->mutex_processed, mtx_plain); + (void) mtx_init(&ctx->thread_running, mtx_plain); + (void) mtx_init(&ctx->thread_resume, mtx_plain); + +#if defined(DEBUG) || !defined(NDEBUG) + u_thread_setname("Main thread"); +#endif + + ctx->device = This; + + ctx->worker = u_thread_create(nine_csmt_worker, ctx); + if (!ctx->worker) { + nine_queue_delete(ctx->pool); + FREE(ctx); + return NULL; + } + + DBG("Returning context %p\n", ctx); + + return ctx; +} + +static int +nop_func( struct NineDevice9 *This, struct csmt_instruction *instr ) +{ + (void) This; + (void) instr; + + return 1; +} + +/* Push nop instruction and flush the queue. + * Waits for the worker to complete. */ +void +nine_csmt_process( struct NineDevice9 *device ) +{ + struct csmt_instruction* instr; + struct csmt_context *ctx = device->csmt_ctx; + + if (!device->csmt_active) + return; + + if (nine_queue_isempty(ctx->pool)) + return; + + DBG("device=%p\n", device); + + /* NOP */ + instr = nine_queue_alloc(ctx->pool, sizeof(struct csmt_instruction)); + assert(instr); + instr->func = nop_func; + + p_atomic_set(&ctx->processed, FALSE); + nine_queue_flush(ctx->pool); + + nine_csmt_wait_processed(ctx); +} + +/* Destroys a CSMT context. + * Waits for the worker thread to terminate. + */ +void +nine_csmt_destroy( struct NineDevice9 *device, struct csmt_context *ctx ) +{ + struct csmt_instruction* instr; + thrd_t render_thread = ctx->worker; + + DBG("device=%p ctx=%p\n", device, ctx); + + /* Push nop and flush the queue. */ + instr = nine_queue_alloc(ctx->pool, sizeof(struct csmt_instruction)); + assert(instr); + instr->func = nop_func; + + p_atomic_set(&ctx->processed, FALSE); + /* Signal worker to terminate. */ + p_atomic_set(&ctx->terminate, TRUE); + nine_queue_flush(ctx->pool); + + nine_csmt_wait_processed(ctx); + nine_queue_delete(ctx->pool); + + mtx_destroy(&ctx->thread_resume); + mtx_destroy(&ctx->thread_running); + + mtx_destroy(&ctx->mutex_processed); + cnd_destroy(&ctx->event_processed); + + FREE(ctx); + + thrd_join(render_thread, NULL); +} + +static void +nine_csmt_pause( struct NineDevice9 *device ) +{ + struct csmt_context *ctx = device->csmt_ctx; + + if (!device->csmt_active) + return; + + /* No need to pause the thread */ + if (nine_queue_no_flushed_work(ctx->pool)) + return; + + mtx_lock(&ctx->thread_resume); + p_atomic_set(&ctx->toPause, TRUE); + + /* Wait the thread is paused */ + mtx_lock(&ctx->thread_running); + ctx->hasPaused = TRUE; + p_atomic_set(&ctx->toPause, FALSE); +} + +static void +nine_csmt_resume( struct NineDevice9 *device ) +{ + struct csmt_context *ctx = device->csmt_ctx; + + if (!device->csmt_active) + return; + + if (!ctx->hasPaused) + return; + + ctx->hasPaused = FALSE; + mtx_unlock(&ctx->thread_running); + mtx_unlock(&ctx->thread_resume); +} + +struct pipe_context * +nine_context_get_pipe( struct NineDevice9 *device ) +{ + nine_csmt_process(device); + return device->context.pipe; +} + +struct pipe_context * +nine_context_get_pipe_multithread( struct NineDevice9 *device ) +{ + struct csmt_context *ctx = device->csmt_ctx; + + if (!device->csmt_active) + return device->context.pipe; + + if (!u_thread_is_self(ctx->worker)) + nine_csmt_process(device); + + return device->context.pipe; +} + +struct pipe_context * +nine_context_get_pipe_acquire( struct NineDevice9 *device ) +{ + nine_csmt_pause(device); + return device->context.pipe; +} + +void +nine_context_get_pipe_release( struct NineDevice9 *device ) +{ + nine_csmt_resume(device); +} + +/* Nine state functions */ + +/* Check if some states need to be set dirty */ + +static inline DWORD +check_multisample(struct NineDevice9 *device) +{ + DWORD *rs = device->context.rs; + DWORD new_value = (rs[D3DRS_ZENABLE] || rs[D3DRS_STENCILENABLE]) && + device->context.rt[0]->desc.MultiSampleType >= 1 && + rs[D3DRS_MULTISAMPLEANTIALIAS]; + if (rs[NINED3DRS_MULTISAMPLE] != new_value) { + rs[NINED3DRS_MULTISAMPLE] = new_value; + return NINE_STATE_RASTERIZER; + } + return 0; +} + +/* State preparation only */ + +static inline void +prepare_blend(struct NineDevice9 *device) +{ + nine_convert_blend_state(&device->context.pipe_data.blend, device->context.rs); + device->context.commit |= NINE_STATE_COMMIT_BLEND; +} + +static inline void +prepare_dsa(struct NineDevice9 *device) +{ + nine_convert_dsa_state(&device->context.pipe_data.dsa, device->context.rs); + device->context.commit |= NINE_STATE_COMMIT_DSA; +} + +static inline void +prepare_rasterizer(struct NineDevice9 *device) +{ + nine_convert_rasterizer_state(device, &device->context.pipe_data.rast, device->context.rs); + device->context.commit |= NINE_STATE_COMMIT_RASTERIZER; +} + +static void +prepare_vs_constants_userbuf_swvp(struct NineDevice9 *device) +{ + struct nine_context *context = &device->context; + + if (context->changed.vs_const_f || context->changed.group & NINE_STATE_SWVP) { + struct pipe_constant_buffer cb; + + cb.buffer_offset = 0; + cb.buffer_size = 4096 * sizeof(float[4]); + cb.user_buffer = context->vs_const_f_swvp; + + if (context->vs->lconstf.ranges) { + const struct nine_lconstf *lconstf = &(context->vs->lconstf); + const struct nine_range *r = lconstf->ranges; + unsigned n = 0; + float *dst = context->vs_lconstf_temp; + float *src = (float *)cb.user_buffer; + memcpy(dst, src, cb.buffer_size); + while (r) { + unsigned p = r->bgn; + unsigned c = r->end - r->bgn; + memcpy(&dst[p * 4], &lconstf->data[n * 4], c * 4 * sizeof(float)); + n += c; + r = r->next; + } + cb.user_buffer = dst; + } + + context->pipe_data.cb0_swvp.buffer_offset = cb.buffer_offset; + context->pipe_data.cb0_swvp.buffer_size = cb.buffer_size; + context->pipe_data.cb0_swvp.user_buffer = cb.user_buffer; + + cb.user_buffer = (char *)cb.user_buffer + 4096 * sizeof(float[4]); + context->pipe_data.cb1_swvp.buffer_offset = cb.buffer_offset; + context->pipe_data.cb1_swvp.buffer_size = cb.buffer_size; + context->pipe_data.cb1_swvp.user_buffer = cb.user_buffer; + + context->changed.vs_const_f = 0; + } + + if (context->changed.vs_const_i || context->changed.group & NINE_STATE_SWVP) { + struct pipe_constant_buffer cb; + + cb.buffer_offset = 0; + cb.buffer_size = 2048 * sizeof(float[4]); + cb.user_buffer = context->vs_const_i; + + context->pipe_data.cb2_swvp.buffer_offset = cb.buffer_offset; + context->pipe_data.cb2_swvp.buffer_size = cb.buffer_size; + context->pipe_data.cb2_swvp.user_buffer = cb.user_buffer; + context->changed.vs_const_i = 0; + } + + if (context->changed.vs_const_b || context->changed.group & NINE_STATE_SWVP) { + struct pipe_constant_buffer cb; + + cb.buffer_offset = 0; + cb.buffer_size = 512 * sizeof(float[4]); + cb.user_buffer = context->vs_const_b; + + context->pipe_data.cb3_swvp.buffer_offset = cb.buffer_offset; + context->pipe_data.cb3_swvp.buffer_size = cb.buffer_size; + context->pipe_data.cb3_swvp.user_buffer = cb.user_buffer; + context->changed.vs_const_b = 0; + } + + context->changed.group &= ~NINE_STATE_VS_CONST; + context->commit |= NINE_STATE_COMMIT_CONST_VS; +} + +static void +prepare_vs_constants_userbuf(struct NineDevice9 *device) +{ + struct nine_context *context = &device->context; + uint8_t *upload_ptr = NULL; + struct pipe_constant_buffer cb; + cb.buffer = NULL; + cb.buffer_offset = 0; + cb.buffer_size = context->cso_shader.vs_const_used_size; + cb.user_buffer = context->vs_const_f; + + if (context->swvp) { + prepare_vs_constants_userbuf_swvp(device); + return; + } + + if (context->changed.vs_const_i || context->changed.group & NINE_STATE_SWVP) { + int *idst = (int *)&context->vs_const_f[4 * device->max_vs_const_f]; + memcpy(idst, context->vs_const_i, NINE_MAX_CONST_I * sizeof(int[4])); + context->changed.vs_const_i = 0; + } + + if (context->changed.vs_const_b || context->changed.group & NINE_STATE_SWVP) { + int *idst = (int *)&context->vs_const_f[4 * device->max_vs_const_f]; + uint32_t *bdst = (uint32_t *)&idst[4 * NINE_MAX_CONST_I]; + memcpy(bdst, context->vs_const_b, NINE_MAX_CONST_B * sizeof(BOOL)); + context->changed.vs_const_b = 0; + } + + if (!cb.buffer_size) + return; + + if (context->vs->lconstf.ranges) { + /* TODO: Can we make it so that we don't have to copy everything ? */ + const struct nine_lconstf *lconstf = &(context->vs->lconstf); + const struct nine_range *r = lconstf->ranges; + unsigned n = 0; + float *dst = context->vs_lconstf_temp; + float *src = (float *)cb.user_buffer; + memcpy(dst, src, cb.buffer_size); + while (r) { + unsigned p = r->bgn; + unsigned c = r->end - r->bgn; + memcpy(&dst[p * 4], &lconstf->data[n * 4], c * 4 * sizeof(float)); + n += c; + r = r->next; + } + cb.user_buffer = dst; + } + + /* Note: We probably don't want to do separate memcpy to + * upload_ptr directly, if we have to copy some constants + * at random locations (context->vs->lconstf.ranges), + * to have efficient WC. Thus for this case we really want + * that intermediate buffer. */ + + u_upload_alloc(context->pipe->const_uploader, + 0, + cb.buffer_size, + 256, /* Be conservative about alignment */ + &(cb.buffer_offset), + &(cb.buffer), + (void**)&upload_ptr); + + assert(cb.buffer && upload_ptr); + + if (!context->cso_shader.vs_const_ranges) { + memcpy(upload_ptr, cb.user_buffer, cb.buffer_size); + } else { + unsigned i = 0; + unsigned offset = 0; + while (context->cso_shader.vs_const_ranges[i*2+1] != 0) { + memcpy(upload_ptr+offset, + &((float*)cb.user_buffer)[4*context->cso_shader.vs_const_ranges[i*2]], + context->cso_shader.vs_const_ranges[i*2+1] * sizeof(float[4])); + offset += context->cso_shader.vs_const_ranges[i*2+1] * sizeof(float[4]); + i++; + } + } + + u_upload_unmap(context->pipe->const_uploader); + cb.user_buffer = NULL; + + /* Free previous resource */ + pipe_resource_reference(&context->pipe_data.cb_vs.buffer, NULL); + + context->pipe_data.cb_vs = cb; + context->changed.vs_const_f = 0; + + context->changed.group &= ~NINE_STATE_VS_CONST; + context->commit |= NINE_STATE_COMMIT_CONST_VS; +} + +static void +prepare_ps_constants_userbuf(struct NineDevice9 *device) +{ + struct nine_context *context = &device->context; + uint8_t *upload_ptr = NULL; + struct pipe_constant_buffer cb; + cb.buffer = NULL; + cb.buffer_offset = 0; + cb.buffer_size = context->cso_shader.ps_const_used_size; + cb.user_buffer = context->ps_const_f; + + if (context->changed.ps_const_i) { + int *idst = (int *)&context->ps_const_f[4 * device->max_ps_const_f]; + memcpy(idst, context->ps_const_i, sizeof(context->ps_const_i)); + context->changed.ps_const_i = 0; + } + if (context->changed.ps_const_b) { + int *idst = (int *)&context->ps_const_f[4 * device->max_ps_const_f]; + uint32_t *bdst = (uint32_t *)&idst[4 * NINE_MAX_CONST_I]; + memcpy(bdst, context->ps_const_b, sizeof(context->ps_const_b)); + context->changed.ps_const_b = 0; + } + + /* Upload special constants needed to implement PS1.x instructions like TEXBEM,TEXBEML and BEM */ + if (context->ps->bumpenvmat_needed) { + memcpy(context->ps_lconstf_temp, cb.user_buffer, 8 * sizeof(float[4])); + memcpy(&context->ps_lconstf_temp[4 * 8], &device->context.bumpmap_vars, sizeof(device->context.bumpmap_vars)); + + cb.user_buffer = context->ps_lconstf_temp; + } + + if (context->ps->byte_code.version < 0x30 && + context->rs[D3DRS_FOGENABLE]) { + float *dst = &context->ps_lconstf_temp[4 * 32]; + if (cb.user_buffer != context->ps_lconstf_temp) { + memcpy(context->ps_lconstf_temp, cb.user_buffer, 32 * sizeof(float[4])); + cb.user_buffer = context->ps_lconstf_temp; + } + + d3dcolor_to_rgba(dst, context->rs[D3DRS_FOGCOLOR]); + if (context->rs[D3DRS_FOGTABLEMODE] == D3DFOG_LINEAR) { + dst[4] = asfloat(context->rs[D3DRS_FOGEND]); + dst[5] = 1.0f / (asfloat(context->rs[D3DRS_FOGEND]) - asfloat(context->rs[D3DRS_FOGSTART])); + } else if (context->rs[D3DRS_FOGTABLEMODE] != D3DFOG_NONE) { + dst[4] = asfloat(context->rs[D3DRS_FOGDENSITY]); + } + } + + if (!cb.buffer_size) + return; + + u_upload_alloc(context->pipe->const_uploader, + 0, + cb.buffer_size, + 256, /* Be conservative about alignment */ + &(cb.buffer_offset), + &(cb.buffer), + (void**)&upload_ptr); + + assert(cb.buffer && upload_ptr); + + if (!context->cso_shader.ps_const_ranges) { + memcpy(upload_ptr, cb.user_buffer, cb.buffer_size); + } else { + unsigned i = 0; + unsigned offset = 0; + while (context->cso_shader.ps_const_ranges[i*2+1] != 0) { + memcpy(upload_ptr+offset, + &((float*)cb.user_buffer)[4*context->cso_shader.ps_const_ranges[i*2]], + context->cso_shader.ps_const_ranges[i*2+1] * sizeof(float[4])); + offset += context->cso_shader.ps_const_ranges[i*2+1] * sizeof(float[4]); + i++; + } + } + + u_upload_unmap(context->pipe->const_uploader); + cb.user_buffer = NULL; + + /* Free previous resource */ + pipe_resource_reference(&context->pipe_data.cb_ps.buffer, NULL); + + context->pipe_data.cb_ps = cb; + context->changed.ps_const_f = 0; + + context->changed.group &= ~NINE_STATE_PS_CONST; + context->commit |= NINE_STATE_COMMIT_CONST_PS; +} + +static inline uint32_t +prepare_vs(struct NineDevice9 *device, uint8_t shader_changed) +{ + struct nine_context *context = &device->context; + struct NineVertexShader9 *vs = context->vs; + uint32_t changed_group = 0; + int has_key_changed = 0; + + if (likely(context->programmable_vs)) + has_key_changed = NineVertexShader9_UpdateKey(vs, device); + + if (!shader_changed && !has_key_changed) + return 0; + + /* likely because we dislike FF */ + if (likely(context->programmable_vs)) { + context->cso_shader.vs = NineVertexShader9_GetVariant(vs, + &context->cso_shader.vs_const_ranges, + &context->cso_shader.vs_const_used_size); + } else { + vs = device->ff.vs; + context->cso_shader.vs = vs->ff_cso; + } + + if (context->rs[NINED3DRS_VSPOINTSIZE] != vs->point_size) { + context->rs[NINED3DRS_VSPOINTSIZE] = vs->point_size; + changed_group |= NINE_STATE_RASTERIZER; + } + + if ((context->bound_samplers_mask_vs & vs->sampler_mask) != vs->sampler_mask) + /* Bound dummy sampler. */ + changed_group |= NINE_STATE_SAMPLER; + + context->commit |= NINE_STATE_COMMIT_VS; + return changed_group; +} + +static inline uint32_t +prepare_ps(struct NineDevice9 *device, uint8_t shader_changed) +{ + struct nine_context *context = &device->context; + struct NinePixelShader9 *ps = context->ps; + uint32_t changed_group = 0; + int has_key_changed = 0; + + if (likely(ps)) + has_key_changed = NinePixelShader9_UpdateKey(ps, context); + + if (!shader_changed && !has_key_changed) + return 0; + + if (likely(ps)) { + context->cso_shader.ps = NinePixelShader9_GetVariant(ps, + &context->cso_shader.ps_const_ranges, + &context->cso_shader.ps_const_used_size); + } else { + ps = device->ff.ps; + context->cso_shader.ps = ps->ff_cso; + } + + if ((context->bound_samplers_mask_ps & ps->sampler_mask) != ps->sampler_mask) + /* Bound dummy sampler. */ + changed_group |= NINE_STATE_SAMPLER; + + context->commit |= NINE_STATE_COMMIT_PS; + return changed_group; +} + +/* State preparation incremental */ + +/* State preparation + State commit */ + +static void +update_framebuffer(struct NineDevice9 *device, bool is_clear) +{ + struct nine_context *context = &device->context; + struct pipe_context *pipe = context->pipe; + struct pipe_framebuffer_state *fb = &context->pipe_data.fb; + unsigned i; + struct NineSurface9 *rt0 = context->rt[0]; + unsigned w = rt0->desc.Width; + unsigned h = rt0->desc.Height; + unsigned nr_samples = rt0->base.info.nr_samples; + unsigned ps_mask = context->ps ? context->ps->rt_mask : 1; + unsigned mask = is_clear ? 0xf : ps_mask; + const int sRGB = context->rs[D3DRS_SRGBWRITEENABLE] ? 1 : 0; + + DBG("\n"); + + context->rt_mask = 0x0; + fb->nr_cbufs = 0; + + /* all render targets must have the same size and the depth buffer must be + * bigger. Multisample has to match, according to spec. But some apps do + * things wrong there, and no error is returned. The behaviour they get + * apparently is that depth buffer is disabled if it doesn't match. + * Surely the same for render targets. */ + + /* Special case: D3DFMT_NULL is used to bound no real render target, + * but render to depth buffer. We have to not take into account the render + * target info. TODO: know what should happen when there are several render targers + * and the first one is D3DFMT_NULL */ + if (rt0->desc.Format == D3DFMT_NULL && context->ds) { + w = context->ds->desc.Width; + h = context->ds->desc.Height; + nr_samples = context->ds->base.info.nr_samples; + } + + for (i = 0; i < device->caps.NumSimultaneousRTs; ++i) { + struct NineSurface9 *rt = context->rt[i]; + + if (rt && rt->desc.Format != D3DFMT_NULL && (mask & (1 << i)) && + rt->desc.Width == w && rt->desc.Height == h && + rt->base.info.nr_samples == nr_samples) { + fb->cbufs[i] = NineSurface9_GetSurface(rt, sRGB); + context->rt_mask |= 1 << i; + fb->nr_cbufs = i + 1; + } else { + /* Color outputs must match RT slot, + * drivers will have to handle NULL entries for GL, too. + */ + fb->cbufs[i] = NULL; + } + } + + if (context->ds && context->ds->desc.Width >= w && + context->ds->desc.Height >= h && + context->ds->base.info.nr_samples == nr_samples) { + fb->zsbuf = NineSurface9_GetSurface(context->ds, 0); + } else { + fb->zsbuf = NULL; + } + + fb->width = w; + fb->height = h; + + pipe->set_framebuffer_state(pipe, fb); /* XXX: cso ? */ + + if (is_clear && context->rt_mask == ps_mask) + context->changed.group &= ~NINE_STATE_FB; +} + +static void +update_viewport(struct NineDevice9 *device) +{ + struct nine_context *context = &device->context; + const D3DVIEWPORT9 *vport = &context->viewport; + struct pipe_viewport_state pvport; + + /* D3D coordinates are: + * -1 .. +1 for X,Y and + * 0 .. +1 for Z (we use pipe_rasterizer_state.clip_halfz) + */ + pvport.scale[0] = (float)vport->Width * 0.5f; + pvport.scale[1] = (float)vport->Height * -0.5f; + pvport.scale[2] = vport->MaxZ - vport->MinZ; + pvport.translate[0] = (float)vport->Width * 0.5f + (float)vport->X; + pvport.translate[1] = (float)vport->Height * 0.5f + (float)vport->Y; + pvport.translate[2] = vport->MinZ; + + /* We found R600 and SI cards have some imprecision + * on the barycentric coordinates used for interpolation. + * Some shaders rely on having something precise. + * We found that the proprietary driver has the imprecision issue, + * except when the render target width and height are powers of two. + * It is using some sort of workaround for these cases + * which covers likely all the cases the applications rely + * on something precise. + * We haven't found the workaround, but it seems like it's better + * for applications if the imprecision is biased towards infinity + * instead of -infinity (which is what measured). So shift slightly + * the viewport: not enough to change rasterization result (in particular + * for multisampling), but enough to make the imprecision biased + * towards infinity. We do this shift only if render target width and + * height are powers of two. + * Solves 'red shadows' bug on UE3 games. + */ + if (device->driver_bugs.buggy_barycentrics && + ((vport->Width & (vport->Width-1)) == 0) && + ((vport->Height & (vport->Height-1)) == 0)) { + pvport.translate[0] -= 1.0f / 128.0f; + pvport.translate[1] -= 1.0f / 128.0f; + } + + cso_set_viewport(context->cso, &pvport); +} + +/* Loop through VS inputs and pick the vertex elements with the declared + * usage from the vertex declaration, then insert the instance divisor from + * the stream source frequency setting. + */ +static void +update_vertex_elements(struct NineDevice9 *device) +{ + struct nine_context *context = &device->context; + const struct NineVertexDeclaration9 *vdecl = device->context.vdecl; + const struct NineVertexShader9 *vs; + unsigned n, b, i; + int index; + char vdecl_index_map[16]; /* vs->num_inputs <= 16 */ + char used_streams[device->caps.MaxStreams]; + int dummy_vbo_stream = -1; + BOOL need_dummy_vbo = FALSE; + struct cso_velems_state ve; + + context->stream_usage_mask = 0; + memset(vdecl_index_map, -1, 16); + memset(used_streams, 0, device->caps.MaxStreams); + vs = context->programmable_vs ? context->vs : device->ff.vs; + + if (vdecl) { + for (n = 0; n < vs->num_inputs; ++n) { + DBG("looking up input %u (usage %u) from vdecl(%p)\n", + n, vs->input_map[n].ndecl, vdecl); + + for (i = 0; i < vdecl->nelems; i++) { + if (vdecl->usage_map[i] == vs->input_map[n].ndecl) { + vdecl_index_map[n] = i; + used_streams[vdecl->elems[i].vertex_buffer_index] = 1; + break; + } + } + if (vdecl_index_map[n] < 0) + need_dummy_vbo = TRUE; + } + } else { + /* No vertex declaration. Likely will never happen in practice, + * but we need not crash on this */ + need_dummy_vbo = TRUE; + } + + if (need_dummy_vbo) { + for (i = 0; i < device->caps.MaxStreams; i++ ) { + if (!used_streams[i]) { + dummy_vbo_stream = i; + break; + } + } + } + /* there are less vertex shader inputs than stream slots, + * so if we need a slot for the dummy vbo, we should have found one */ + assert (!need_dummy_vbo || dummy_vbo_stream != -1); + + for (n = 0; n < vs->num_inputs; ++n) { + index = vdecl_index_map[n]; + if (index >= 0) { + ve.velems[n] = vdecl->elems[index]; + b = ve.velems[n].vertex_buffer_index; + context->stream_usage_mask |= 1 << b; + /* XXX wine just uses 1 here: */ + if (context->stream_freq[b] & D3DSTREAMSOURCE_INSTANCEDATA) + ve.velems[n].instance_divisor = context->stream_freq[b] & 0x7FFFFF; + } else { + /* if the vertex declaration is incomplete compared to what the + * vertex shader needs, we bind a dummy vbo with 0 0 0 0. + * This is not precised by the spec, but is the behaviour + * tested on win */ + ve.velems[n].vertex_buffer_index = dummy_vbo_stream; + ve.velems[n].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + ve.velems[n].src_offset = 0; + ve.velems[n].instance_divisor = 0; + } + } + + if (context->dummy_vbo_bound_at != dummy_vbo_stream) { + if (context->dummy_vbo_bound_at >= 0) + context->changed.vtxbuf |= 1 << context->dummy_vbo_bound_at; + if (dummy_vbo_stream >= 0) { + context->changed.vtxbuf |= 1 << dummy_vbo_stream; + context->vbo_bound_done = FALSE; + } + context->dummy_vbo_bound_at = dummy_vbo_stream; + } + + ve.count = vs->num_inputs; + cso_set_vertex_elements(context->cso, &ve); +} + +static void +update_vertex_buffers(struct NineDevice9 *device) +{ + struct nine_context *context = &device->context; + struct pipe_context *pipe = context->pipe; + struct pipe_vertex_buffer dummy_vtxbuf; + uint32_t mask = context->changed.vtxbuf; + unsigned i; + + DBG("mask=%x\n", mask); + + if (context->dummy_vbo_bound_at >= 0) { + if (!context->vbo_bound_done) { + dummy_vtxbuf.buffer.resource = device->dummy_vbo; + dummy_vtxbuf.stride = 0; + dummy_vtxbuf.is_user_buffer = false; + dummy_vtxbuf.buffer_offset = 0; + pipe->set_vertex_buffers(pipe, context->dummy_vbo_bound_at, + 1, &dummy_vtxbuf); + context->vbo_bound_done = TRUE; + } + mask &= ~(1 << context->dummy_vbo_bound_at); + } + + for (i = 0; mask; mask >>= 1, ++i) { + if (mask & 1) { + if (context->vtxbuf[i].buffer.resource) + pipe->set_vertex_buffers(pipe, i, 1, &context->vtxbuf[i]); + else + pipe->set_vertex_buffers(pipe, i, 1, NULL); + } + } + + context->changed.vtxbuf = 0; +} + +static inline boolean +update_sampler_derived(struct nine_context *context, unsigned s) +{ + boolean changed = FALSE; + + if (context->samp[s][NINED3DSAMP_SHADOW] != context->texture[s].shadow) { + changed = TRUE; + context->samp[s][NINED3DSAMP_SHADOW] = context->texture[s].shadow; + } + + if (context->samp[s][NINED3DSAMP_CUBETEX] != + (context->texture[s].type == D3DRTYPE_CUBETEXTURE)) { + changed = TRUE; + context->samp[s][NINED3DSAMP_CUBETEX] = + context->texture[s].type == D3DRTYPE_CUBETEXTURE; + } + + if (context->samp[s][D3DSAMP_MIPFILTER] != D3DTEXF_NONE) { + int lod = context->samp[s][D3DSAMP_MAXMIPLEVEL] - context->texture[s].lod; + if (lod < 0) + lod = 0; + if (context->samp[s][NINED3DSAMP_MINLOD] != lod) { + changed = TRUE; + context->samp[s][NINED3DSAMP_MINLOD] = lod; + } + } else { + context->changed.sampler[s] &= ~0x300; /* lod changes irrelevant */ + } + + return changed; +} + +/* TODO: add sRGB override to pipe_sampler_state ? */ +static void +update_textures_and_samplers(struct NineDevice9 *device) +{ + struct nine_context *context = &device->context; + struct pipe_sampler_view *view[NINE_MAX_SAMPLERS]; + unsigned num_textures; + unsigned i; + boolean commit_samplers; + uint16_t sampler_mask = context->ps ? context->ps->sampler_mask : + device->ff.ps->sampler_mask; + + /* TODO: Can we reduce iterations here ? */ + + commit_samplers = FALSE; + context->bound_samplers_mask_ps = 0; + for (num_textures = 0, i = 0; i < NINE_MAX_SAMPLERS_PS; ++i) { + const unsigned s = NINE_SAMPLER_PS(i); + int sRGB; + + if (!context->texture[s].enabled && !(sampler_mask & (1 << i))) { + view[i] = NULL; + continue; + } + + if (context->texture[s].enabled) { + sRGB = context->samp[s][D3DSAMP_SRGBTEXTURE] ? 1 : 0; + + view[i] = context->texture[s].view[sRGB]; + num_textures = i + 1; + + if (update_sampler_derived(context, s) || (context->changed.sampler[s] & 0x05fe)) { + context->changed.sampler[s] = 0; + commit_samplers = TRUE; + nine_convert_sampler_state(context->cso, s, context->samp[s]); + } + } else { + /* Bind dummy sampler. We do not bind dummy sampler when + * it is not needed because it could add overhead. The + * dummy sampler should have r=g=b=0 and a=1. We do not + * unbind dummy sampler directly when they are not needed + * anymore, but they're going to be removed as long as texture + * or sampler states are changed. */ + view[i] = device->dummy_sampler_view; + num_textures = i + 1; + + cso_single_sampler(context->cso, PIPE_SHADER_FRAGMENT, + s - NINE_SAMPLER_PS(0), &device->dummy_sampler_state); + + commit_samplers = TRUE; + context->changed.sampler[s] = ~0; + } + + context->bound_samplers_mask_ps |= (1 << s); + } + + cso_set_sampler_views(context->cso, PIPE_SHADER_FRAGMENT, num_textures, view); + + if (commit_samplers) + cso_single_sampler_done(context->cso, PIPE_SHADER_FRAGMENT); + + commit_samplers = FALSE; + sampler_mask = context->programmable_vs ? context->vs->sampler_mask : 0; + context->bound_samplers_mask_vs = 0; + for (num_textures = 0, i = 0; i < NINE_MAX_SAMPLERS_VS; ++i) { + const unsigned s = NINE_SAMPLER_VS(i); + int sRGB; + + if (!context->texture[s].enabled && !(sampler_mask & (1 << i))) { + view[i] = NULL; + continue; + } + + if (context->texture[s].enabled) { + sRGB = context->samp[s][D3DSAMP_SRGBTEXTURE] ? 1 : 0; + + view[i] = context->texture[s].view[sRGB]; + num_textures = i + 1; + + if (update_sampler_derived(context, s) || (context->changed.sampler[s] & 0x05fe)) { + context->changed.sampler[s] = 0; + commit_samplers = TRUE; + nine_convert_sampler_state(context->cso, s, context->samp[s]); + } + } else { + /* Bind dummy sampler. We do not bind dummy sampler when + * it is not needed because it could add overhead. The + * dummy sampler should have r=g=b=0 and a=1. We do not + * unbind dummy sampler directly when they are not needed + * anymore, but they're going to be removed as long as texture + * or sampler states are changed. */ + view[i] = device->dummy_sampler_view; + num_textures = i + 1; + + cso_single_sampler(context->cso, PIPE_SHADER_VERTEX, + s - NINE_SAMPLER_VS(0), &device->dummy_sampler_state); + + commit_samplers = TRUE; + context->changed.sampler[s] = ~0; + } + + context->bound_samplers_mask_vs |= (1 << i); + } + + cso_set_sampler_views(context->cso, PIPE_SHADER_VERTEX, num_textures, view); + + if (commit_samplers) + cso_single_sampler_done(context->cso, PIPE_SHADER_VERTEX); +} + +/* State commit only */ + +static inline void +commit_blend(struct NineDevice9 *device) +{ + struct nine_context *context = &device->context; + + cso_set_blend(context->cso, &context->pipe_data.blend); +} + +static inline void +commit_dsa(struct NineDevice9 *device) +{ + struct nine_context *context = &device->context; + + cso_set_depth_stencil_alpha(context->cso, &context->pipe_data.dsa); +} + +static inline void +commit_scissor(struct NineDevice9 *device) +{ + struct nine_context *context = &device->context; + struct pipe_context *pipe = context->pipe; + + pipe->set_scissor_states(pipe, 0, 1, &context->scissor); +} + +static inline void +commit_rasterizer(struct NineDevice9 *device) +{ + struct nine_context *context = &device->context; + + cso_set_rasterizer(context->cso, &context->pipe_data.rast); +} + +static inline void +commit_vs_constants(struct NineDevice9 *device) +{ + struct nine_context *context = &device->context; + struct pipe_context *pipe = context->pipe; + + if (unlikely(!context->programmable_vs)) + pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 0, &context->pipe_data.cb_vs_ff); + else { + if (context->swvp) { + pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 0, &context->pipe_data.cb0_swvp); + pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 1, &context->pipe_data.cb1_swvp); + pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 2, &context->pipe_data.cb2_swvp); + pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 3, &context->pipe_data.cb3_swvp); + } else { + pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 0, &context->pipe_data.cb_vs); + } + } +} + +static inline void +commit_ps_constants(struct NineDevice9 *device) +{ + struct nine_context *context = &device->context; + struct pipe_context *pipe = context->pipe; + + if (unlikely(!context->ps)) + pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, 0, &context->pipe_data.cb_ps_ff); + else + pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, 0, &context->pipe_data.cb_ps); +} + +static inline void +commit_vs(struct NineDevice9 *device) +{ + struct nine_context *context = &device->context; + + context->pipe->bind_vs_state(context->pipe, context->cso_shader.vs); +} + + +static inline void +commit_ps(struct NineDevice9 *device) +{ + struct nine_context *context = &device->context; + + context->pipe->bind_fs_state(context->pipe, context->cso_shader.ps); +} +/* State Update */ + +#define NINE_STATE_SHADER_CHANGE_VS \ + (NINE_STATE_VS | \ + NINE_STATE_TEXTURE | \ + NINE_STATE_VS_PARAMS_MISC | \ + NINE_STATE_SWVP) + +#define NINE_STATE_SHADER_CHANGE_PS \ + (NINE_STATE_PS | \ + NINE_STATE_TEXTURE | \ + NINE_STATE_PS_PARAMS_MISC) + +#define NINE_STATE_FREQUENT \ + (NINE_STATE_RASTERIZER | \ + NINE_STATE_TEXTURE | \ + NINE_STATE_SAMPLER | \ + NINE_STATE_VS_CONST | \ + NINE_STATE_PS_CONST | \ + NINE_STATE_MULTISAMPLE) + +#define NINE_STATE_COMMON \ + (NINE_STATE_FB | \ + NINE_STATE_BLEND | \ + NINE_STATE_DSA | \ + NINE_STATE_VIEWPORT | \ + NINE_STATE_VDECL | \ + NINE_STATE_IDXBUF | \ + NINE_STATE_STREAMFREQ) + +#define NINE_STATE_RARE \ + (NINE_STATE_SCISSOR | \ + NINE_STATE_BLEND_COLOR | \ + NINE_STATE_STENCIL_REF | \ + NINE_STATE_SAMPLE_MASK) + +static void +nine_update_state(struct NineDevice9 *device) +{ + struct nine_context *context = &device->context; + struct pipe_context *pipe = context->pipe; + uint32_t group; + + DBG("changed state groups: %x\n", context->changed.group); + + /* NOTE: We may want to use the cso cache for everything, or let + * NineDevice9.RestoreNonCSOState actually set the states, then we wouldn't + * have to care about state being clobbered here and could merge this back + * into update_textures. Except, we also need to re-validate textures that + * may be dirty anyway, even if no texture bindings changed. + */ + + /* ff_update may change VS/PS dirty bits */ + if (unlikely(!context->programmable_vs || !context->ps)) + nine_ff_update(device); + group = context->changed.group; + + if (group & (NINE_STATE_SHADER_CHANGE_VS | NINE_STATE_SHADER_CHANGE_PS)) { + if (group & NINE_STATE_SHADER_CHANGE_VS) + group |= prepare_vs(device, (group & NINE_STATE_VS) != 0); /* may set NINE_STATE_RASTERIZER and NINE_STATE_SAMPLER*/ + if (group & NINE_STATE_SHADER_CHANGE_PS) + group |= prepare_ps(device, (group & NINE_STATE_PS) != 0); + } + + if (group & (NINE_STATE_COMMON | NINE_STATE_VS)) { + if (group & NINE_STATE_FB) + update_framebuffer(device, FALSE); + if (group & NINE_STATE_BLEND) + prepare_blend(device); + if (group & NINE_STATE_DSA) + prepare_dsa(device); + if (group & NINE_STATE_VIEWPORT) + update_viewport(device); + if (group & (NINE_STATE_VDECL | NINE_STATE_VS | NINE_STATE_STREAMFREQ)) + update_vertex_elements(device); + } + + if (likely(group & (NINE_STATE_FREQUENT | NINE_STATE_VS | NINE_STATE_PS | NINE_STATE_SWVP))) { + if (group & NINE_STATE_MULTISAMPLE) + group |= check_multisample(device); + if (group & NINE_STATE_RASTERIZER) + prepare_rasterizer(device); + if (group & (NINE_STATE_TEXTURE | NINE_STATE_SAMPLER)) + update_textures_and_samplers(device); + if ((group & (NINE_STATE_VS_CONST | NINE_STATE_VS | NINE_STATE_SWVP)) && context->programmable_vs) + prepare_vs_constants_userbuf(device); + if ((group & (NINE_STATE_PS_CONST | NINE_STATE_PS)) && context->ps) + prepare_ps_constants_userbuf(device); + } + + if (context->changed.vtxbuf) + update_vertex_buffers(device); + + if (context->commit & NINE_STATE_COMMIT_BLEND) + commit_blend(device); + if (context->commit & NINE_STATE_COMMIT_DSA) + commit_dsa(device); + if (context->commit & NINE_STATE_COMMIT_RASTERIZER) + commit_rasterizer(device); + if (context->commit & NINE_STATE_COMMIT_CONST_VS) + commit_vs_constants(device); + if (context->commit & NINE_STATE_COMMIT_CONST_PS) + commit_ps_constants(device); + if (context->commit & NINE_STATE_COMMIT_VS) + commit_vs(device); + if (context->commit & NINE_STATE_COMMIT_PS) + commit_ps(device); + + context->commit = 0; + + if (unlikely(context->changed.ucp)) { + pipe->set_clip_state(pipe, &context->clip); + context->changed.ucp = FALSE; + } + + if (unlikely(group & NINE_STATE_RARE)) { + if (group & NINE_STATE_SCISSOR) + commit_scissor(device); + if (group & NINE_STATE_BLEND_COLOR) { + struct pipe_blend_color color; + d3dcolor_to_rgba(&color.color[0], context->rs[D3DRS_BLENDFACTOR]); + pipe->set_blend_color(pipe, &color); + } + if (group & NINE_STATE_SAMPLE_MASK) { + if (context->rt[0]->desc.MultiSampleType <= D3DMULTISAMPLE_NONMASKABLE) { + pipe->set_sample_mask(pipe, ~0); + } else { + pipe->set_sample_mask(pipe, context->rs[D3DRS_MULTISAMPLEMASK]); + } + } + if (group & NINE_STATE_STENCIL_REF) { + struct pipe_stencil_ref ref; + ref.ref_value[0] = context->rs[D3DRS_STENCILREF]; + ref.ref_value[1] = ref.ref_value[0]; + pipe->set_stencil_ref(pipe, &ref); + } + } + + context->changed.group &= + (NINE_STATE_FF | NINE_STATE_VS_CONST | NINE_STATE_PS_CONST); + + DBG("finished\n"); +} + +#define RESZ_CODE 0x7fa05000 + +static void +NineDevice9_ResolveZ( struct NineDevice9 *device ) +{ + struct nine_context *context = &device->context; + const struct util_format_description *desc; + struct NineSurface9 *source = context->ds; + struct pipe_resource *src, *dst; + struct pipe_blit_info blit; + + DBG("RESZ resolve\n"); + + if (!source || !context->texture[0].enabled || + context->texture[0].type != D3DRTYPE_TEXTURE) + return; + + src = source->base.resource; + dst = context->texture[0].resource; + + if (!src || !dst) + return; + + /* check dst is depth format. we know already for src */ + desc = util_format_description(dst->format); + if (desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS) + return; + + memset(&blit, 0, sizeof(blit)); + blit.src.resource = src; + blit.src.level = 0; + blit.src.format = src->format; + blit.src.box.z = 0; + blit.src.box.depth = 1; + blit.src.box.x = 0; + blit.src.box.y = 0; + blit.src.box.width = src->width0; + blit.src.box.height = src->height0; + + blit.dst.resource = dst; + blit.dst.level = 0; + blit.dst.format = dst->format; + blit.dst.box.z = 0; + blit.dst.box.depth = 1; + blit.dst.box.x = 0; + blit.dst.box.y = 0; + blit.dst.box.width = dst->width0; + blit.dst.box.height = dst->height0; + + blit.mask = PIPE_MASK_ZS; + blit.filter = PIPE_TEX_FILTER_NEAREST; + blit.scissor_enable = FALSE; + + context->pipe->blit(context->pipe, &blit); +} + +#define ALPHA_TO_COVERAGE_ENABLE MAKEFOURCC('A', '2', 'M', '1') +#define ALPHA_TO_COVERAGE_DISABLE MAKEFOURCC('A', '2', 'M', '0') + +/* Nine_context functions. + * Serialized through CSMT macros. + */ + +static void +nine_context_set_texture_apply(struct NineDevice9 *device, + DWORD stage, + BOOL enabled, + BOOL shadow, + DWORD lod, + D3DRESOURCETYPE type, + uint8_t pstype, + struct pipe_resource *res, + struct pipe_sampler_view *view0, + struct pipe_sampler_view *view1); +static void +nine_context_set_stream_source_apply(struct NineDevice9 *device, + UINT StreamNumber, + struct pipe_resource *res, + UINT OffsetInBytes, + UINT Stride); + +static void +nine_context_set_indices_apply(struct NineDevice9 *device, + struct pipe_resource *res, + UINT IndexSize, + UINT OffsetInBytes); + +static void +nine_context_set_pixel_shader_constant_i_transformed(struct NineDevice9 *device, + UINT StartRegister, + const int *pConstantData, + unsigned pConstantData_size, + UINT Vector4iCount); + +CSMT_ITEM_NO_WAIT(nine_context_set_render_state, + ARG_VAL(D3DRENDERSTATETYPE, State), + ARG_VAL(DWORD, Value)) +{ + struct nine_context *context = &device->context; + + /* Amd hacks (equivalent to GL extensions) */ + if (unlikely(State == D3DRS_POINTSIZE)) { + if (Value == RESZ_CODE) { + NineDevice9_ResolveZ(device); + return; + } + + if (Value == ALPHA_TO_COVERAGE_ENABLE || + Value == ALPHA_TO_COVERAGE_DISABLE) { + context->rs[NINED3DRS_ALPHACOVERAGE] = (Value == ALPHA_TO_COVERAGE_ENABLE); + context->changed.group |= NINE_STATE_BLEND; + return; + } + } + + /* NV hack */ + if (unlikely(State == D3DRS_ADAPTIVETESS_Y)) { + if (Value == D3DFMT_ATOC || (Value == D3DFMT_UNKNOWN && context->rs[NINED3DRS_ALPHACOVERAGE])) { + context->rs[NINED3DRS_ALPHACOVERAGE] = (Value == D3DFMT_ATOC) ? 3 : 0; + context->rs[NINED3DRS_ALPHACOVERAGE] &= context->rs[D3DRS_ALPHATESTENABLE] ? 3 : 2; + context->changed.group |= NINE_STATE_BLEND; + return; + } + } + if (unlikely(State == D3DRS_ALPHATESTENABLE && (context->rs[NINED3DRS_ALPHACOVERAGE] & 2))) { + DWORD alphacoverage_prev = context->rs[NINED3DRS_ALPHACOVERAGE]; + context->rs[NINED3DRS_ALPHACOVERAGE] = (Value ? 3 : 2); + if (context->rs[NINED3DRS_ALPHACOVERAGE] != alphacoverage_prev) + context->changed.group |= NINE_STATE_BLEND; + } + + context->rs[State] = nine_fix_render_state_value(State, Value); + context->changed.group |= nine_render_state_group[State]; +} + +CSMT_ITEM_NO_WAIT(nine_context_set_texture_apply, + ARG_VAL(DWORD, stage), + ARG_VAL(BOOL, enabled), + ARG_VAL(BOOL, shadow), + ARG_VAL(DWORD, lod), + ARG_VAL(D3DRESOURCETYPE, type), + ARG_VAL(uint8_t, pstype), + ARG_BIND_RES(struct pipe_resource, res), + ARG_BIND_VIEW(struct pipe_sampler_view, view0), + ARG_BIND_VIEW(struct pipe_sampler_view, view1)) +{ + struct nine_context *context = &device->context; + + context->texture[stage].enabled = enabled; + context->samplers_shadow &= ~(1 << stage); + context->samplers_shadow |= shadow << stage; + context->texture[stage].shadow = shadow; + context->texture[stage].lod = lod; + context->texture[stage].type = type; + context->texture[stage].pstype = pstype; + pipe_resource_reference(&context->texture[stage].resource, res); + pipe_sampler_view_reference(&context->texture[stage].view[0], view0); + pipe_sampler_view_reference(&context->texture[stage].view[1], view1); + + context->changed.group |= NINE_STATE_TEXTURE; +} + +void +nine_context_set_texture(struct NineDevice9 *device, + DWORD Stage, + struct NineBaseTexture9 *tex) +{ + BOOL enabled = FALSE; + BOOL shadow = FALSE; + DWORD lod = 0; + D3DRESOURCETYPE type = D3DRTYPE_TEXTURE; + uint8_t pstype = 0; + struct pipe_resource *res = NULL; + struct pipe_sampler_view *view0 = NULL, *view1 = NULL; + + /* For managed pool, the data can be initially incomplete. + * In that case, the texture is rebound later + * (in NineBaseTexture9_Validate/NineBaseTexture9_UploadSelf). */ + if (tex && tex->base.resource) { + enabled = TRUE; + shadow = tex->shadow; + lod = tex->managed.lod; + type = tex->base.type; + pstype = tex->pstype; + res = tex->base.resource; + view0 = NineBaseTexture9_GetSamplerView(tex, 0); + view1 = NineBaseTexture9_GetSamplerView(tex, 1); + } + + nine_context_set_texture_apply(device, Stage, enabled, + shadow, lod, type, pstype, + res, view0, view1); +} + +CSMT_ITEM_NO_WAIT(nine_context_set_sampler_state, + ARG_VAL(DWORD, Sampler), + ARG_VAL(D3DSAMPLERSTATETYPE, Type), + ARG_VAL(DWORD, Value)) +{ + struct nine_context *context = &device->context; + + if (unlikely(!nine_check_sampler_state_value(Type, Value))) + return; + + context->samp[Sampler][Type] = Value; + context->changed.group |= NINE_STATE_SAMPLER; + context->changed.sampler[Sampler] |= 1 << Type; +} + +CSMT_ITEM_NO_WAIT(nine_context_set_stream_source_apply, + ARG_VAL(UINT, StreamNumber), + ARG_BIND_RES(struct pipe_resource, res), + ARG_VAL(UINT, OffsetInBytes), + ARG_VAL(UINT, Stride)) +{ + struct nine_context *context = &device->context; + const unsigned i = StreamNumber; + + context->vtxbuf[i].stride = Stride; + context->vtxbuf[i].buffer_offset = OffsetInBytes; + pipe_resource_reference(&context->vtxbuf[i].buffer.resource, res); + + context->changed.vtxbuf |= 1 << StreamNumber; +} + +void +nine_context_set_stream_source(struct NineDevice9 *device, + UINT StreamNumber, + struct NineVertexBuffer9 *pVBuf9, + UINT OffsetInBytes, + UINT Stride) +{ + struct pipe_resource *res = NULL; + unsigned offset = 0; + + if (pVBuf9) + res = NineVertexBuffer9_GetResource(pVBuf9, &offset); + /* in the future when there is internal offset, add it + * to OffsetInBytes */ + + nine_context_set_stream_source_apply(device, StreamNumber, + res, offset + OffsetInBytes, + Stride); +} + +CSMT_ITEM_NO_WAIT(nine_context_set_stream_source_freq, + ARG_VAL(UINT, StreamNumber), + ARG_VAL(UINT, Setting)) +{ + struct nine_context *context = &device->context; + + context->stream_freq[StreamNumber] = Setting; + + if (Setting & D3DSTREAMSOURCE_INSTANCEDATA) + context->stream_instancedata_mask |= 1 << StreamNumber; + else + context->stream_instancedata_mask &= ~(1 << StreamNumber); + + if (StreamNumber != 0) + context->changed.group |= NINE_STATE_STREAMFREQ; +} + +CSMT_ITEM_NO_WAIT(nine_context_set_indices_apply, + ARG_BIND_RES(struct pipe_resource, res), + ARG_VAL(UINT, IndexSize), + ARG_VAL(UINT, OffsetInBytes)) +{ + struct nine_context *context = &device->context; + + context->index_size = IndexSize; + context->index_offset = OffsetInBytes; + pipe_resource_reference(&context->idxbuf, res); + + context->changed.group |= NINE_STATE_IDXBUF; +} + +void +nine_context_set_indices(struct NineDevice9 *device, + struct NineIndexBuffer9 *idxbuf) +{ + struct pipe_resource *res = NULL; + UINT IndexSize = 0; + unsigned OffsetInBytes = 0; + + if (idxbuf) { + res = NineIndexBuffer9_GetBuffer(idxbuf, &OffsetInBytes); + IndexSize = idxbuf->index_size; + } + + nine_context_set_indices_apply(device, res, IndexSize, OffsetInBytes); +} + +CSMT_ITEM_NO_WAIT(nine_context_set_vertex_declaration, + ARG_BIND_REF(struct NineVertexDeclaration9, vdecl)) +{ + struct nine_context *context = &device->context; + BOOL was_programmable_vs = context->programmable_vs; + + nine_bind(&context->vdecl, vdecl); + + context->programmable_vs = context->vs && !(context->vdecl && context->vdecl->position_t); + if (was_programmable_vs != context->programmable_vs) { + context->commit |= NINE_STATE_COMMIT_CONST_VS; + context->changed.group |= NINE_STATE_VS; + } + + context->changed.group |= NINE_STATE_VDECL; +} + +CSMT_ITEM_NO_WAIT(nine_context_set_vertex_shader, + ARG_BIND_REF(struct NineVertexShader9, pShader)) +{ + struct nine_context *context = &device->context; + BOOL was_programmable_vs = context->programmable_vs; + + nine_bind(&context->vs, pShader); + + context->programmable_vs = context->vs && !(context->vdecl && context->vdecl->position_t); + + /* ff -> non-ff: commit back non-ff constants */ + if (!was_programmable_vs && context->programmable_vs) + context->commit |= NINE_STATE_COMMIT_CONST_VS; + + context->changed.group |= NINE_STATE_VS; +} + +CSMT_ITEM_NO_WAIT(nine_context_set_vertex_shader_constant_f, + ARG_VAL(UINT, StartRegister), + ARG_MEM(float, pConstantData), + ARG_MEM_SIZE(unsigned, pConstantData_size), + ARG_VAL(UINT, Vector4fCount)) +{ + struct nine_context *context = &device->context; + float *vs_const_f = device->may_swvp ? context->vs_const_f_swvp : context->vs_const_f; + + memcpy(&vs_const_f[StartRegister * 4], + pConstantData, + pConstantData_size); + + if (device->may_swvp) { + Vector4fCount = MIN2(StartRegister + Vector4fCount, NINE_MAX_CONST_F) - StartRegister; + if (StartRegister < NINE_MAX_CONST_F) + memcpy(&context->vs_const_f[StartRegister * 4], + pConstantData, + Vector4fCount * 4 * sizeof(context->vs_const_f[0])); + } + + context->changed.vs_const_f = TRUE; + context->changed.group |= NINE_STATE_VS_CONST; +} + +CSMT_ITEM_NO_WAIT(nine_context_set_vertex_shader_constant_i, + ARG_VAL(UINT, StartRegister), + ARG_MEM(int, pConstantData), + ARG_MEM_SIZE(unsigned, pConstantData_size), + ARG_VAL(UINT, Vector4iCount)) +{ + struct nine_context *context = &device->context; + int i; + + if (device->driver_caps.vs_integer) { + memcpy(&context->vs_const_i[4 * StartRegister], + pConstantData, + pConstantData_size); + } else { + for (i = 0; i < Vector4iCount; i++) { + context->vs_const_i[4 * (StartRegister + i)] = fui((float)(pConstantData[4 * i])); + context->vs_const_i[4 * (StartRegister + i) + 1] = fui((float)(pConstantData[4 * i + 1])); + context->vs_const_i[4 * (StartRegister + i) + 2] = fui((float)(pConstantData[4 * i + 2])); + context->vs_const_i[4 * (StartRegister + i) + 3] = fui((float)(pConstantData[4 * i + 3])); + } + } + + context->changed.vs_const_i = TRUE; + context->changed.group |= NINE_STATE_VS_CONST | NINE_STATE_VS_PARAMS_MISC; +} + +CSMT_ITEM_NO_WAIT(nine_context_set_vertex_shader_constant_b, + ARG_VAL(UINT, StartRegister), + ARG_MEM(BOOL, pConstantData), + ARG_MEM_SIZE(unsigned, pConstantData_size), + ARG_VAL(UINT, BoolCount)) +{ + struct nine_context *context = &device->context; + int i; + uint32_t bool_true = device->driver_caps.vs_integer ? 0xFFFFFFFF : fui(1.0f); + + (void) pConstantData_size; + + for (i = 0; i < BoolCount; i++) + context->vs_const_b[StartRegister + i] = pConstantData[i] ? bool_true : 0; + + context->changed.vs_const_b = TRUE; + context->changed.group |= NINE_STATE_VS_CONST | NINE_STATE_VS_PARAMS_MISC; +} + +CSMT_ITEM_NO_WAIT(nine_context_set_pixel_shader, + ARG_BIND_REF(struct NinePixelShader9, ps)) +{ + struct nine_context *context = &device->context; + unsigned old_mask = context->ps ? context->ps->rt_mask : 1; + unsigned mask; + + /* ff -> non-ff: commit back non-ff constants */ + if (!context->ps && ps) + context->commit |= NINE_STATE_COMMIT_CONST_PS; + + nine_bind(&context->ps, ps); + + context->changed.group |= NINE_STATE_PS; + + mask = context->ps ? context->ps->rt_mask : 1; + /* We need to update cbufs if the pixel shader would + * write to different render targets */ + if (mask != old_mask) + context->changed.group |= NINE_STATE_FB; +} + +CSMT_ITEM_NO_WAIT(nine_context_set_pixel_shader_constant_f, + ARG_VAL(UINT, StartRegister), + ARG_MEM(float, pConstantData), + ARG_MEM_SIZE(unsigned, pConstantData_size), + ARG_VAL(UINT, Vector4fCount)) +{ + struct nine_context *context = &device->context; + + memcpy(&context->ps_const_f[StartRegister * 4], + pConstantData, + pConstantData_size); + + context->changed.ps_const_f = TRUE; + context->changed.group |= NINE_STATE_PS_CONST; +} + +/* For stateblocks */ +CSMT_ITEM_NO_WAIT(nine_context_set_pixel_shader_constant_i_transformed, + ARG_VAL(UINT, StartRegister), + ARG_MEM(int, pConstantData), + ARG_MEM_SIZE(unsigned, pConstantData_size), + ARG_VAL(UINT, Vector4iCount)) +{ + struct nine_context *context = &device->context; + + memcpy(&context->ps_const_i[StartRegister][0], + pConstantData, + Vector4iCount * sizeof(context->ps_const_i[0])); + + context->changed.ps_const_i = TRUE; + context->changed.group |= NINE_STATE_PS_CONST | NINE_STATE_PS_PARAMS_MISC; +} + +CSMT_ITEM_NO_WAIT(nine_context_set_pixel_shader_constant_i, + ARG_VAL(UINT, StartRegister), + ARG_MEM(int, pConstantData), + ARG_MEM_SIZE(unsigned, pConstantData_size), + ARG_VAL(UINT, Vector4iCount)) +{ + struct nine_context *context = &device->context; + int i; + + if (device->driver_caps.ps_integer) { + memcpy(&context->ps_const_i[StartRegister][0], + pConstantData, + pConstantData_size); + } else { + for (i = 0; i < Vector4iCount; i++) { + context->ps_const_i[StartRegister+i][0] = fui((float)(pConstantData[4*i])); + context->ps_const_i[StartRegister+i][1] = fui((float)(pConstantData[4*i+1])); + context->ps_const_i[StartRegister+i][2] = fui((float)(pConstantData[4*i+2])); + context->ps_const_i[StartRegister+i][3] = fui((float)(pConstantData[4*i+3])); + } + } + context->changed.ps_const_i = TRUE; + context->changed.group |= NINE_STATE_PS_CONST | NINE_STATE_PS_PARAMS_MISC; +} + +CSMT_ITEM_NO_WAIT(nine_context_set_pixel_shader_constant_b, + ARG_VAL(UINT, StartRegister), + ARG_MEM(BOOL, pConstantData), + ARG_MEM_SIZE(unsigned, pConstantData_size), + ARG_VAL(UINT, BoolCount)) +{ + struct nine_context *context = &device->context; + int i; + uint32_t bool_true = device->driver_caps.ps_integer ? 0xFFFFFFFF : fui(1.0f); + + (void) pConstantData_size; + + for (i = 0; i < BoolCount; i++) + context->ps_const_b[StartRegister + i] = pConstantData[i] ? bool_true : 0; + + context->changed.ps_const_b = TRUE; + context->changed.group |= NINE_STATE_PS_CONST | NINE_STATE_PS_PARAMS_MISC; +} + +/* XXX: use resource, as resource might change */ +CSMT_ITEM_NO_WAIT(nine_context_set_render_target, + ARG_VAL(DWORD, RenderTargetIndex), + ARG_BIND_REF(struct NineSurface9, rt)) +{ + struct nine_context *context = &device->context; + const unsigned i = RenderTargetIndex; + + if (i == 0) { + context->viewport.X = 0; + context->viewport.Y = 0; + context->viewport.Width = rt->desc.Width; + context->viewport.Height = rt->desc.Height; + context->viewport.MinZ = 0.0f; + context->viewport.MaxZ = 1.0f; + + context->scissor.minx = 0; + context->scissor.miny = 0; + context->scissor.maxx = rt->desc.Width; + context->scissor.maxy = rt->desc.Height; + + context->changed.group |= NINE_STATE_VIEWPORT | NINE_STATE_SCISSOR | NINE_STATE_MULTISAMPLE; + + if (context->rt[0] && + (context->rt[0]->desc.MultiSampleType <= D3DMULTISAMPLE_NONMASKABLE) != + (rt->desc.MultiSampleType <= D3DMULTISAMPLE_NONMASKABLE)) + context->changed.group |= NINE_STATE_SAMPLE_MASK; + } + + if (context->rt[i] != rt) { + nine_bind(&context->rt[i], rt); + context->changed.group |= NINE_STATE_FB; + } +} + +/* XXX: use resource instead of ds, as resource might change */ +CSMT_ITEM_NO_WAIT(nine_context_set_depth_stencil, + ARG_BIND_REF(struct NineSurface9, ds)) +{ + struct nine_context *context = &device->context; + + nine_bind(&context->ds, ds); + context->changed.group |= NINE_STATE_FB; +} + +CSMT_ITEM_NO_WAIT(nine_context_set_viewport, + ARG_COPY_REF(D3DVIEWPORT9, viewport)) +{ + struct nine_context *context = &device->context; + + context->viewport = *viewport; + context->changed.group |= NINE_STATE_VIEWPORT; +} + +CSMT_ITEM_NO_WAIT(nine_context_set_scissor, + ARG_COPY_REF(struct pipe_scissor_state, scissor)) +{ + struct nine_context *context = &device->context; + + context->scissor = *scissor; + context->changed.group |= NINE_STATE_SCISSOR; +} + +CSMT_ITEM_NO_WAIT(nine_context_set_transform, + ARG_VAL(D3DTRANSFORMSTATETYPE, State), + ARG_COPY_REF(D3DMATRIX, pMatrix)) +{ + struct nine_context *context = &device->context; + D3DMATRIX *M = nine_state_access_transform(&context->ff, State, TRUE); + + *M = *pMatrix; + context->ff.changed.transform[State / 32] |= 1 << (State % 32); + context->changed.group |= NINE_STATE_FF; +} + +CSMT_ITEM_NO_WAIT(nine_context_set_material, + ARG_COPY_REF(D3DMATERIAL9, pMaterial)) +{ + struct nine_context *context = &device->context; + + context->ff.material = *pMaterial; + context->changed.group |= NINE_STATE_FF_MATERIAL; +} + +CSMT_ITEM_NO_WAIT(nine_context_set_light, + ARG_VAL(DWORD, Index), + ARG_COPY_REF(D3DLIGHT9, pLight)) +{ + struct nine_context *context = &device->context; + + (void)nine_state_set_light(&context->ff, Index, pLight); + context->changed.group |= NINE_STATE_FF_LIGHTING; +} + + +/* For stateblocks */ +static void +nine_context_light_enable_stateblock(struct NineDevice9 *device, + const uint16_t active_light[NINE_MAX_LIGHTS_ACTIVE], /* TODO: use pointer that convey size for csmt */ + unsigned int num_lights_active) +{ + struct nine_context *context = &device->context; + + /* TODO: Use CSMT_* to avoid calling nine_csmt_process */ + nine_csmt_process(device); + memcpy(context->ff.active_light, active_light, NINE_MAX_LIGHTS_ACTIVE * sizeof(context->ff.active_light[0])); + context->ff.num_lights_active = num_lights_active; + context->changed.group |= NINE_STATE_FF_LIGHTING; +} + +CSMT_ITEM_NO_WAIT(nine_context_light_enable, + ARG_VAL(DWORD, Index), + ARG_VAL(BOOL, Enable)) +{ + struct nine_context *context = &device->context; + + nine_state_light_enable(&context->ff, Index, Enable); + context->changed.group |= NINE_STATE_FF_LIGHTING; +} + +CSMT_ITEM_NO_WAIT(nine_context_set_texture_stage_state, + ARG_VAL(DWORD, Stage), + ARG_VAL(D3DTEXTURESTAGESTATETYPE, Type), + ARG_VAL(DWORD, Value)) +{ + struct nine_context *context = &device->context; + int bumpmap_index = -1; + + context->ff.tex_stage[Stage][Type] = Value; + switch (Type) { + case D3DTSS_BUMPENVMAT00: + bumpmap_index = 4 * Stage; + break; + case D3DTSS_BUMPENVMAT01: + bumpmap_index = 4 * Stage + 1; + break; + case D3DTSS_BUMPENVMAT10: + bumpmap_index = 4 * Stage + 2; + break; + case D3DTSS_BUMPENVMAT11: + bumpmap_index = 4 * Stage + 3; + break; + case D3DTSS_BUMPENVLSCALE: + bumpmap_index = 4 * 8 + 2 * Stage; + break; + case D3DTSS_BUMPENVLOFFSET: + bumpmap_index = 4 * 8 + 2 * Stage + 1; + break; + case D3DTSS_TEXTURETRANSFORMFLAGS: + context->changed.group |= NINE_STATE_PS_PARAMS_MISC; + break; + default: + break; + } + + if (bumpmap_index >= 0) { + context->bumpmap_vars[bumpmap_index] = Value; + context->changed.group |= NINE_STATE_PS_CONST; + } + + context->changed.group |= NINE_STATE_FF_PS_CONSTS; + context->ff.changed.tex_stage[Stage][Type / 32] |= 1 << (Type % 32); +} + +CSMT_ITEM_NO_WAIT(nine_context_set_clip_plane, + ARG_VAL(DWORD, Index), + ARG_COPY_REF(struct nine_clipplane, pPlane)) +{ + struct nine_context *context = &device->context; + + memcpy(&context->clip.ucp[Index][0], pPlane, sizeof(context->clip.ucp[0])); + context->changed.ucp = TRUE; +} + +CSMT_ITEM_NO_WAIT(nine_context_set_swvp, + ARG_VAL(boolean, swvp)) +{ + struct nine_context *context = &device->context; + + context->swvp = swvp; + context->changed.group |= NINE_STATE_SWVP; +} + +/* Do not write to nine_context directly. Slower, + * but works with csmt. TODO: write a special csmt version that + * would record the list of commands as much as possible, + * and use the version above else. + */ +void +nine_context_apply_stateblock(struct NineDevice9 *device, + const struct nine_state *src) +{ + int i; + + /* No need to apply src->changed.group, since all calls do + * set context->changed.group */ + + for (i = 0; i < ARRAY_SIZE(src->changed.rs); ++i) { + uint32_t m = src->changed.rs[i]; + while (m) { + const int r = ffs(m) - 1; + m &= ~(1 << r); + nine_context_set_render_state(device, i * 32 + r, src->rs_advertised[i * 32 + r]); + } + } + + /* Textures */ + if (src->changed.texture) { + uint32_t m = src->changed.texture; + unsigned s; + + for (s = 0; m; ++s, m >>= 1) { + struct NineBaseTexture9 *tex = src->texture[s]; + if (!(m & 1)) + continue; + nine_context_set_texture(device, s, tex); + } + } + + /* Sampler state */ + if (src->changed.group & NINE_STATE_SAMPLER) { + unsigned s; + + for (s = 0; s < NINE_MAX_SAMPLERS; ++s) { + uint32_t m = src->changed.sampler[s]; + while (m) { + const int i = ffs(m) - 1; + m &= ~(1 << i); + nine_context_set_sampler_state(device, s, i, src->samp_advertised[s][i]); + } + } + } + + /* Vertex buffers */ + if (src->changed.vtxbuf | src->changed.stream_freq) { + uint32_t m = src->changed.vtxbuf | src->changed.stream_freq; + for (i = 0; m; ++i, m >>= 1) { + if (src->changed.vtxbuf & (1 << i)) + nine_context_set_stream_source(device, i, src->stream[i], src->vtxbuf[i].buffer_offset, src->vtxbuf[i].stride); + if (src->changed.stream_freq & (1 << i)) + nine_context_set_stream_source_freq(device, i, src->stream_freq[i]); + } + } + + /* Index buffer */ + if (src->changed.group & NINE_STATE_IDXBUF) + nine_context_set_indices(device, src->idxbuf); + + /* Vertex declaration */ + if ((src->changed.group & NINE_STATE_VDECL) && src->vdecl) + nine_context_set_vertex_declaration(device, src->vdecl); + + /* Vertex shader */ + if (src->changed.group & NINE_STATE_VS) + nine_context_set_vertex_shader(device, src->vs); + + /* Pixel shader */ + if (src->changed.group & NINE_STATE_PS) + nine_context_set_pixel_shader(device, src->ps); + + /* Vertex constants */ + if (src->changed.group & NINE_STATE_VS_CONST) { + struct nine_range *r; + for (r = src->changed.vs_const_f; r; r = r->next) + nine_context_set_vertex_shader_constant_f(device, r->bgn, + &src->vs_const_f[r->bgn * 4], + sizeof(float[4]) * (r->end - r->bgn), + r->end - r->bgn); + for (r = src->changed.vs_const_i; r; r = r->next) + nine_context_set_vertex_shader_constant_i(device, r->bgn, + &src->vs_const_i[r->bgn * 4], + sizeof(int[4]) * (r->end - r->bgn), + r->end - r->bgn); + for (r = src->changed.vs_const_b; r; r = r->next) + nine_context_set_vertex_shader_constant_b(device, r->bgn, + &src->vs_const_b[r->bgn * 4], + sizeof(BOOL) * (r->end - r->bgn), + r->end - r->bgn); + } + + /* Pixel constants */ + if (src->changed.group & NINE_STATE_PS_CONST) { + struct nine_range *r; + for (r = src->changed.ps_const_f; r; r = r->next) + nine_context_set_pixel_shader_constant_f(device, r->bgn, + &src->ps_const_f[r->bgn * 4], + sizeof(float[4]) * (r->end - r->bgn), + r->end - r->bgn); + if (src->changed.ps_const_i) { + uint16_t m = src->changed.ps_const_i; + for (i = ffs(m) - 1, m >>= i; m; ++i, m >>= 1) + if (m & 1) + nine_context_set_pixel_shader_constant_i_transformed(device, i, + src->ps_const_i[i], sizeof(int[4]), 1); + } + if (src->changed.ps_const_b) { + uint16_t m = src->changed.ps_const_b; + for (i = ffs(m) - 1, m >>= i; m; ++i, m >>= 1) + if (m & 1) + nine_context_set_pixel_shader_constant_b(device, i, + &src->ps_const_b[i], sizeof(BOOL), 1); + } + } + + /* Viewport */ + if (src->changed.group & NINE_STATE_VIEWPORT) + nine_context_set_viewport(device, &src->viewport); + + /* Scissor */ + if (src->changed.group & NINE_STATE_SCISSOR) + nine_context_set_scissor(device, &src->scissor); + + /* User Clip Planes */ + if (src->changed.ucp) + for (i = 0; i < PIPE_MAX_CLIP_PLANES; ++i) + if (src->changed.ucp & (1 << i)) + nine_context_set_clip_plane(device, i, (struct nine_clipplane*)&src->clip.ucp[i][0]); + + if (!(src->changed.group & NINE_STATE_FF)) + return; + + /* Fixed function state. */ + + if (src->changed.group & NINE_STATE_FF_MATERIAL) + nine_context_set_material(device, &src->ff.material); + + if (src->changed.group & NINE_STATE_FF_PS_CONSTS) { + unsigned s; + for (s = 0; s < NINE_MAX_TEXTURE_STAGES; ++s) { + for (i = 0; i < NINED3DTSS_COUNT; ++i) + if (src->ff.changed.tex_stage[s][i / 32] & (1 << (i % 32))) + nine_context_set_texture_stage_state(device, s, i, src->ff.tex_stage[s][i]); + } + } + if (src->changed.group & NINE_STATE_FF_LIGHTING) { + for (i = 0; i < src->ff.num_lights; ++i) + if (src->ff.light[i].Type != NINED3DLIGHT_INVALID) + nine_context_set_light(device, i, &src->ff.light[i]); + + nine_context_light_enable_stateblock(device, src->ff.active_light, src->ff.num_lights_active); + } + if (src->changed.group & NINE_STATE_FF_VSTRANSF) { + for (i = 0; i < ARRAY_SIZE(src->ff.changed.transform); ++i) { + unsigned s; + if (!src->ff.changed.transform[i]) + continue; + for (s = i * 32; s < (i * 32 + 32); ++s) { + if (!(src->ff.changed.transform[i] & (1 << (s % 32)))) + continue; + /* MaxVertexBlendMatrixIndex is 8, which means + * we don't read past index D3DTS_WORLDMATRIX(8). + * swvp is supposed to allow all 256, but we don't + * implement it for now. */ + if (s > D3DTS_WORLDMATRIX(8)) + break; + nine_context_set_transform(device, s, + nine_state_access_transform( + (struct nine_ff_state *)&src->ff, + s, FALSE)); + } + } + } +} + +static void +nine_update_state_framebuffer_clear(struct NineDevice9 *device) +{ + struct nine_context *context = &device->context; + + if (context->changed.group & NINE_STATE_FB) + update_framebuffer(device, TRUE); +} + +CSMT_ITEM_NO_WAIT(nine_context_clear_fb, + ARG_VAL(DWORD, Count), + ARG_COPY_REF(D3DRECT, pRects), + ARG_VAL(DWORD, Flags), + ARG_VAL(D3DCOLOR, Color), + ARG_VAL(float, Z), + ARG_VAL(DWORD, Stencil)) +{ + struct nine_context *context = &device->context; + const int sRGB = context->rs[D3DRS_SRGBWRITEENABLE] ? 1 : 0; + struct pipe_surface *cbuf, *zsbuf; + struct pipe_context *pipe = context->pipe; + struct NineSurface9 *zsbuf_surf = context->ds; + struct NineSurface9 *rt; + unsigned bufs = 0; + unsigned r, i; + union pipe_color_union rgba; + unsigned rt_mask = 0; + D3DRECT rect; + + nine_update_state_framebuffer_clear(device); + + if (Flags & D3DCLEAR_TARGET) bufs |= PIPE_CLEAR_COLOR; + /* Ignore Z buffer if not bound */ + if (context->pipe_data.fb.zsbuf != NULL) { + if (Flags & D3DCLEAR_ZBUFFER) bufs |= PIPE_CLEAR_DEPTH; + if (Flags & D3DCLEAR_STENCIL) bufs |= PIPE_CLEAR_STENCIL; + } + if (!bufs) + return; + d3dcolor_to_pipe_color_union(&rgba, Color); + + rect.x1 = context->viewport.X; + rect.y1 = context->viewport.Y; + rect.x2 = context->viewport.Width + rect.x1; + rect.y2 = context->viewport.Height + rect.y1; + + /* Both rectangles apply, which is weird, but that's D3D9. */ + if (context->rs[D3DRS_SCISSORTESTENABLE]) { + rect.x1 = MAX2(rect.x1, context->scissor.minx); + rect.y1 = MAX2(rect.y1, context->scissor.miny); + rect.x2 = MIN2(rect.x2, context->scissor.maxx); + rect.y2 = MIN2(rect.y2, context->scissor.maxy); + } + + if (Count) { + /* Maybe apps like to specify a large rect ? */ + if (pRects[0].x1 <= rect.x1 && pRects[0].x2 >= rect.x2 && + pRects[0].y1 <= rect.y1 && pRects[0].y2 >= rect.y2) { + DBG("First rect covers viewport.\n"); + Count = 0; + pRects = NULL; + } + } + + if (rect.x1 >= context->pipe_data.fb.width || rect.y1 >= context->pipe_data.fb.height) + return; + + for (i = 0; i < device->caps.NumSimultaneousRTs; ++i) { + if (context->rt[i] && context->rt[i]->desc.Format != D3DFMT_NULL) + rt_mask |= 1 << i; + } + + /* fast path, clears everything at once */ + if (!Count && + (!(bufs & PIPE_CLEAR_COLOR) || (rt_mask == context->rt_mask)) && + rect.x1 == 0 && rect.y1 == 0 && + /* Case we clear only render target. Check clear region vs rt. */ + ((!(bufs & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL)) && + rect.x2 >= context->pipe_data.fb.width && + rect.y2 >= context->pipe_data.fb.height) || + /* Case we clear depth buffer (and eventually rt too). + * depth buffer size is always >= rt size. Compare to clear region */ + ((bufs & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL)) && + rect.x2 >= zsbuf_surf->desc.Width && + rect.y2 >= zsbuf_surf->desc.Height))) { + DBG("Clear fast path\n"); + pipe->clear(pipe, bufs, NULL, &rgba, Z, Stencil); + return; + } + + if (!Count) { + Count = 1; + pRects = ▭ + } + + for (i = 0; i < device->caps.NumSimultaneousRTs; ++i) { + rt = context->rt[i]; + if (!rt || rt->desc.Format == D3DFMT_NULL || + !(bufs & PIPE_CLEAR_COLOR)) + continue; /* save space, compiler should hoist this */ + cbuf = NineSurface9_GetSurface(rt, sRGB); + for (r = 0; r < Count; ++r) { + /* Don't trust users to pass these in the right order. */ + unsigned x1 = MIN2(pRects[r].x1, pRects[r].x2); + unsigned y1 = MIN2(pRects[r].y1, pRects[r].y2); + unsigned x2 = MAX2(pRects[r].x1, pRects[r].x2); + unsigned y2 = MAX2(pRects[r].y1, pRects[r].y2); +#ifndef NINE_LAX + /* Drop negative rectangles (like wine expects). */ + if (pRects[r].x1 > pRects[r].x2) continue; + if (pRects[r].y1 > pRects[r].y2) continue; +#endif + + x1 = MAX2(x1, rect.x1); + y1 = MAX2(y1, rect.y1); + x2 = MIN3(x2, rect.x2, rt->desc.Width); + y2 = MIN3(y2, rect.y2, rt->desc.Height); + + DBG("Clearing (%u..%u)x(%u..%u)\n", x1, x2, y1, y2); + pipe->clear_render_target(pipe, cbuf, &rgba, + x1, y1, x2 - x1, y2 - y1, false); + } + } + if (!(bufs & PIPE_CLEAR_DEPTHSTENCIL)) + return; + + bufs &= PIPE_CLEAR_DEPTHSTENCIL; + + for (r = 0; r < Count; ++r) { + unsigned x1 = MIN2(pRects[r].x1, pRects[r].x2); + unsigned y1 = MIN2(pRects[r].y1, pRects[r].y2); + unsigned x2 = MAX2(pRects[r].x1, pRects[r].x2); + unsigned y2 = MAX2(pRects[r].y1, pRects[r].y2); +#ifndef NINE_LAX + /* Drop negative rectangles. */ + if (pRects[r].x1 > pRects[r].x2) continue; + if (pRects[r].y1 > pRects[r].y2) continue; +#endif + + x1 = MIN2(x1, rect.x1); + y1 = MIN2(y1, rect.y1); + x2 = MIN3(x2, rect.x2, zsbuf_surf->desc.Width); + y2 = MIN3(y2, rect.y2, zsbuf_surf->desc.Height); + + zsbuf = NineSurface9_GetSurface(zsbuf_surf, 0); + assert(zsbuf); + pipe->clear_depth_stencil(pipe, zsbuf, bufs, Z, Stencil, + x1, y1, x2 - x1, y2 - y1, false); + } + return; +} + + +static inline void +init_draw_info(struct pipe_draw_info *info, + struct NineDevice9 *dev, D3DPRIMITIVETYPE type, UINT count) +{ + info->mode = d3dprimitivetype_to_pipe_prim(type); + info->count = prim_count_to_vertex_count(type, count); + info->start_instance = 0; + info->instance_count = 1; + if (dev->context.stream_instancedata_mask & dev->context.stream_usage_mask) + info->instance_count = MAX2(dev->context.stream_freq[0] & 0x7FFFFF, 1); + info->primitive_restart = FALSE; + info->has_user_indices = FALSE; + info->restart_index = 0; + info->count_from_stream_output = NULL; + info->indirect = NULL; +} + +CSMT_ITEM_NO_WAIT(nine_context_draw_primitive, + ARG_VAL(D3DPRIMITIVETYPE, PrimitiveType), + ARG_VAL(UINT, StartVertex), + ARG_VAL(UINT, PrimitiveCount)) +{ + struct nine_context *context = &device->context; + struct pipe_draw_info info; + + nine_update_state(device); + + init_draw_info(&info, device, PrimitiveType, PrimitiveCount); + info.index_size = 0; + info.start = StartVertex; + info.index_bias = 0; + info.min_index = info.start; + info.max_index = info.count - 1; + info.index.resource = NULL; + + context->pipe->draw_vbo(context->pipe, &info); +} + +CSMT_ITEM_NO_WAIT(nine_context_draw_indexed_primitive, + ARG_VAL(D3DPRIMITIVETYPE, PrimitiveType), + ARG_VAL(INT, BaseVertexIndex), + ARG_VAL(UINT, MinVertexIndex), + ARG_VAL(UINT, NumVertices), + ARG_VAL(UINT, StartIndex), + ARG_VAL(UINT, PrimitiveCount)) +{ + struct nine_context *context = &device->context; + struct pipe_draw_info info; + + nine_update_state(device); + + init_draw_info(&info, device, PrimitiveType, PrimitiveCount); + info.index_size = context->index_size; + info.start = context->index_offset / context->index_size + StartIndex; + info.index_bias = BaseVertexIndex; + /* These don't include index bias: */ + info.min_index = MinVertexIndex; + info.max_index = MinVertexIndex + NumVertices - 1; + info.index.resource = context->idxbuf; + + context->pipe->draw_vbo(context->pipe, &info); +} + +CSMT_ITEM_NO_WAIT(nine_context_draw_primitive_from_vtxbuf, + ARG_VAL(D3DPRIMITIVETYPE, PrimitiveType), + ARG_VAL(UINT, PrimitiveCount), + ARG_BIND_VBUF(struct pipe_vertex_buffer, vtxbuf)) +{ + struct nine_context *context = &device->context; + struct pipe_draw_info info; + + nine_update_state(device); + + init_draw_info(&info, device, PrimitiveType, PrimitiveCount); + info.index_size = 0; + info.start = 0; + info.index_bias = 0; + info.min_index = 0; + info.max_index = info.count - 1; + info.index.resource = NULL; + + context->pipe->set_vertex_buffers(context->pipe, 0, 1, vtxbuf); + + context->pipe->draw_vbo(context->pipe, &info); +} + +CSMT_ITEM_NO_WAIT(nine_context_draw_indexed_primitive_from_vtxbuf_idxbuf, + ARG_VAL(D3DPRIMITIVETYPE, PrimitiveType), + ARG_VAL(UINT, MinVertexIndex), + ARG_VAL(UINT, NumVertices), + ARG_VAL(UINT, PrimitiveCount), + ARG_BIND_VBUF(struct pipe_vertex_buffer, vbuf), + ARG_BIND_RES(struct pipe_resource, ibuf), + ARG_VAL(void *, user_ibuf), + ARG_VAL(UINT, index_offset), + ARG_VAL(UINT, index_size)) +{ + struct nine_context *context = &device->context; + struct pipe_draw_info info; + + nine_update_state(device); + + init_draw_info(&info, device, PrimitiveType, PrimitiveCount); + info.index_size = index_size; + info.start = index_offset / info.index_size; + info.index_bias = 0; + info.min_index = MinVertexIndex; + info.max_index = MinVertexIndex + NumVertices - 1; + info.has_user_indices = ibuf == NULL; + if (ibuf) + info.index.resource = ibuf; + else + info.index.user = user_ibuf; + + context->pipe->set_vertex_buffers(context->pipe, 0, 1, vbuf); + + context->pipe->draw_vbo(context->pipe, &info); +} + +CSMT_ITEM_NO_WAIT(nine_context_resource_copy_region, + ARG_BIND_REF(struct NineUnknown, dst), + ARG_BIND_REF(struct NineUnknown, src), + ARG_BIND_RES(struct pipe_resource, dst_res), + ARG_VAL(unsigned, dst_level), + ARG_COPY_REF(struct pipe_box, dst_box), + ARG_BIND_RES(struct pipe_resource, src_res), + ARG_VAL(unsigned, src_level), + ARG_COPY_REF(struct pipe_box, src_box)) +{ + struct nine_context *context = &device->context; + + (void) dst; + (void) src; + + context->pipe->resource_copy_region(context->pipe, + dst_res, dst_level, + dst_box->x, dst_box->y, dst_box->z, + src_res, src_level, + src_box); +} + +CSMT_ITEM_NO_WAIT(nine_context_blit, + ARG_BIND_REF(struct NineUnknown, dst), + ARG_BIND_REF(struct NineUnknown, src), + ARG_BIND_BLIT(struct pipe_blit_info, blit)) +{ + struct nine_context *context = &device->context; + + (void) dst; + (void) src; + + context->pipe->blit(context->pipe, blit); +} + +CSMT_ITEM_NO_WAIT(nine_context_clear_render_target, + ARG_BIND_REF(struct NineSurface9, surface), + ARG_VAL(D3DCOLOR, color), + ARG_VAL(UINT, x), + ARG_VAL(UINT, y), + ARG_VAL(UINT, width), + ARG_VAL(UINT, height)) +{ + struct nine_context *context = &device->context; + struct pipe_surface *surf; + union pipe_color_union rgba; + + d3dcolor_to_pipe_color_union(&rgba, color); + surf = NineSurface9_GetSurface(surface, 0); + context->pipe->clear_render_target(context->pipe, surf, &rgba, x, y, width, height, false); +} + +CSMT_ITEM_NO_WAIT(nine_context_gen_mipmap, + ARG_BIND_REF(struct NineUnknown, dst), + ARG_BIND_RES(struct pipe_resource, res), + ARG_VAL(UINT, base_level), + ARG_VAL(UINT, last_level), + ARG_VAL(UINT, first_layer), + ARG_VAL(UINT, last_layer), + ARG_VAL(UINT, filter)) +{ + struct nine_context *context = &device->context; + + /* We just bind dst for the bind count */ + (void)dst; + + util_gen_mipmap(context->pipe, res, res->format, base_level, + last_level, first_layer, last_layer, filter); +} + +CSMT_ITEM_NO_WAIT_WITH_COUNTER(nine_context_range_upload, + ARG_BIND_REF(struct NineUnknown, src_ref), + ARG_BIND_RES(struct pipe_resource, res), + ARG_VAL(unsigned, offset), + ARG_VAL(unsigned, size), + ARG_VAL(const void *, data)) +{ + struct nine_context *context = &device->context; + + /* Binding src_ref avoids release before upload */ + (void)src_ref; + + context->pipe->buffer_subdata(context->pipe, res, 0, offset, size, data); +} + +CSMT_ITEM_NO_WAIT_WITH_COUNTER(nine_context_box_upload, + ARG_BIND_REF(struct NineUnknown, src_ref), + ARG_BIND_RES(struct pipe_resource, res), + ARG_VAL(unsigned, level), + ARG_COPY_REF(struct pipe_box, dst_box), + ARG_VAL(enum pipe_format, src_format), + ARG_VAL(const void *, src), + ARG_VAL(unsigned, src_stride), + ARG_VAL(unsigned, src_layer_stride), + ARG_COPY_REF(struct pipe_box, src_box)) +{ + struct nine_context *context = &device->context; + struct pipe_context *pipe = context->pipe; + struct pipe_transfer *transfer = NULL; + uint8_t *map; + + /* Binding src_ref avoids release before upload */ + (void)src_ref; + + map = pipe->transfer_map(pipe, + res, + level, + PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE, + dst_box, &transfer); + if (!map) + return; + + /* Note: if formats are the sames, it will revert + * to normal memcpy */ + (void) util_format_translate_3d(res->format, + map, transfer->stride, + transfer->layer_stride, + 0, 0, 0, + src_format, + src, src_stride, + src_layer_stride, + src_box->x, src_box->y, src_box->z, + dst_box->width, dst_box->height, + dst_box->depth); + + pipe_transfer_unmap(pipe, transfer); +} + +struct pipe_query * +nine_context_create_query(struct NineDevice9 *device, unsigned query_type) +{ + struct pipe_context *pipe; + struct pipe_query *res; + + pipe = nine_context_get_pipe_acquire(device); + res = pipe->create_query(pipe, query_type, 0); + nine_context_get_pipe_release(device); + return res; +} + +CSMT_ITEM_DO_WAIT(nine_context_destroy_query, + ARG_REF(struct pipe_query, query)) +{ + struct nine_context *context = &device->context; + + context->pipe->destroy_query(context->pipe, query); +} + +CSMT_ITEM_NO_WAIT_WITH_COUNTER(nine_context_begin_query, + ARG_REF(struct pipe_query, query)) +{ + struct nine_context *context = &device->context; + + (void) context->pipe->begin_query(context->pipe, query); +} + +CSMT_ITEM_NO_WAIT_WITH_COUNTER(nine_context_end_query, + ARG_REF(struct pipe_query, query)) +{ + struct nine_context *context = &device->context; + + (void) context->pipe->end_query(context->pipe, query); +} + +boolean +nine_context_get_query_result(struct NineDevice9 *device, struct pipe_query *query, + unsigned *counter, boolean flush, boolean wait, + union pipe_query_result *result) +{ + struct pipe_context *pipe; + boolean ret; + + if (wait) + nine_csmt_process(device); + else if (p_atomic_read(counter) > 0) { + if (flush && device->csmt_active) + nine_queue_flush(device->csmt_ctx->pool); + DBG("Pending begin/end. Returning\n"); + return false; + } + + pipe = nine_context_get_pipe_acquire(device); + ret = pipe->get_query_result(pipe, query, wait, result); + nine_context_get_pipe_release(device); + + DBG("Query result %s\n", ret ? "found" : "not yet available"); + return ret; +} + +/* State defaults */ + +static const DWORD nine_render_state_defaults[NINED3DRS_LAST + 1] = +{ + /* [D3DRS_ZENABLE] = D3DZB_TRUE; wine: auto_depth_stencil */ + [D3DRS_ZENABLE] = D3DZB_FALSE, + [D3DRS_FILLMODE] = D3DFILL_SOLID, + [D3DRS_SHADEMODE] = D3DSHADE_GOURAUD, +/* [D3DRS_LINEPATTERN] = 0x00000000, */ + [D3DRS_ZWRITEENABLE] = TRUE, + [D3DRS_ALPHATESTENABLE] = FALSE, + [D3DRS_LASTPIXEL] = TRUE, + [D3DRS_SRCBLEND] = D3DBLEND_ONE, + [D3DRS_DESTBLEND] = D3DBLEND_ZERO, + [D3DRS_CULLMODE] = D3DCULL_CCW, + [D3DRS_ZFUNC] = D3DCMP_LESSEQUAL, + [D3DRS_ALPHAFUNC] = D3DCMP_ALWAYS, + [D3DRS_ALPHAREF] = 0, + [D3DRS_DITHERENABLE] = FALSE, + [D3DRS_ALPHABLENDENABLE] = FALSE, + [D3DRS_FOGENABLE] = FALSE, + [D3DRS_SPECULARENABLE] = FALSE, +/* [D3DRS_ZVISIBLE] = 0, */ + [D3DRS_FOGCOLOR] = 0, + [D3DRS_FOGTABLEMODE] = D3DFOG_NONE, + [D3DRS_FOGSTART] = 0x00000000, + [D3DRS_FOGEND] = 0x3F800000, + [D3DRS_FOGDENSITY] = 0x3F800000, +/* [D3DRS_EDGEANTIALIAS] = FALSE, */ + [D3DRS_RANGEFOGENABLE] = FALSE, + [D3DRS_STENCILENABLE] = FALSE, + [D3DRS_STENCILFAIL] = D3DSTENCILOP_KEEP, + [D3DRS_STENCILZFAIL] = D3DSTENCILOP_KEEP, + [D3DRS_STENCILPASS] = D3DSTENCILOP_KEEP, + [D3DRS_STENCILREF] = 0, + [D3DRS_STENCILMASK] = 0xFFFFFFFF, + [D3DRS_STENCILFUNC] = D3DCMP_ALWAYS, + [D3DRS_STENCILWRITEMASK] = 0xFFFFFFFF, + [D3DRS_TEXTUREFACTOR] = 0xFFFFFFFF, + [D3DRS_WRAP0] = 0, + [D3DRS_WRAP1] = 0, + [D3DRS_WRAP2] = 0, + [D3DRS_WRAP3] = 0, + [D3DRS_WRAP4] = 0, + [D3DRS_WRAP5] = 0, + [D3DRS_WRAP6] = 0, + [D3DRS_WRAP7] = 0, + [D3DRS_CLIPPING] = TRUE, + [D3DRS_LIGHTING] = TRUE, + [D3DRS_AMBIENT] = 0, + [D3DRS_FOGVERTEXMODE] = D3DFOG_NONE, + [D3DRS_COLORVERTEX] = TRUE, + [D3DRS_LOCALVIEWER] = TRUE, + [D3DRS_NORMALIZENORMALS] = FALSE, + [D3DRS_DIFFUSEMATERIALSOURCE] = D3DMCS_COLOR1, + [D3DRS_SPECULARMATERIALSOURCE] = D3DMCS_COLOR2, + [D3DRS_AMBIENTMATERIALSOURCE] = D3DMCS_MATERIAL, + [D3DRS_EMISSIVEMATERIALSOURCE] = D3DMCS_MATERIAL, + [D3DRS_VERTEXBLEND] = D3DVBF_DISABLE, + [D3DRS_CLIPPLANEENABLE] = 0, +/* [D3DRS_SOFTWAREVERTEXPROCESSING] = FALSE, */ + [D3DRS_POINTSIZE] = 0x3F800000, + [D3DRS_POINTSIZE_MIN] = 0x3F800000, + [D3DRS_POINTSPRITEENABLE] = FALSE, + [D3DRS_POINTSCALEENABLE] = FALSE, + [D3DRS_POINTSCALE_A] = 0x3F800000, + [D3DRS_POINTSCALE_B] = 0x00000000, + [D3DRS_POINTSCALE_C] = 0x00000000, + [D3DRS_MULTISAMPLEANTIALIAS] = TRUE, + [D3DRS_MULTISAMPLEMASK] = 0xFFFFFFFF, + [D3DRS_PATCHEDGESTYLE] = D3DPATCHEDGE_DISCRETE, +/* [D3DRS_PATCHSEGMENTS] = 0x3F800000, */ + [D3DRS_DEBUGMONITORTOKEN] = 0xDEADCAFE, + [D3DRS_POINTSIZE_MAX] = 0x3F800000, /* depends on cap */ + [D3DRS_INDEXEDVERTEXBLENDENABLE] = FALSE, + [D3DRS_COLORWRITEENABLE] = 0x0000000f, + [D3DRS_TWEENFACTOR] = 0x00000000, + [D3DRS_BLENDOP] = D3DBLENDOP_ADD, + [D3DRS_POSITIONDEGREE] = D3DDEGREE_CUBIC, + [D3DRS_NORMALDEGREE] = D3DDEGREE_LINEAR, + [D3DRS_SCISSORTESTENABLE] = FALSE, + [D3DRS_SLOPESCALEDEPTHBIAS] = 0, + [D3DRS_MINTESSELLATIONLEVEL] = 0x3F800000, + [D3DRS_MAXTESSELLATIONLEVEL] = 0x3F800000, + [D3DRS_ANTIALIASEDLINEENABLE] = FALSE, + [D3DRS_ADAPTIVETESS_X] = 0x00000000, + [D3DRS_ADAPTIVETESS_Y] = 0x00000000, + [D3DRS_ADAPTIVETESS_Z] = 0x3F800000, + [D3DRS_ADAPTIVETESS_W] = 0x00000000, + [D3DRS_ENABLEADAPTIVETESSELLATION] = FALSE, + [D3DRS_TWOSIDEDSTENCILMODE] = FALSE, + [D3DRS_CCW_STENCILFAIL] = D3DSTENCILOP_KEEP, + [D3DRS_CCW_STENCILZFAIL] = D3DSTENCILOP_KEEP, + [D3DRS_CCW_STENCILPASS] = D3DSTENCILOP_KEEP, + [D3DRS_CCW_STENCILFUNC] = D3DCMP_ALWAYS, + [D3DRS_COLORWRITEENABLE1] = 0x0000000F, + [D3DRS_COLORWRITEENABLE2] = 0x0000000F, + [D3DRS_COLORWRITEENABLE3] = 0x0000000F, + [D3DRS_BLENDFACTOR] = 0xFFFFFFFF, + [D3DRS_SRGBWRITEENABLE] = 0, + [D3DRS_DEPTHBIAS] = 0, + [D3DRS_WRAP8] = 0, + [D3DRS_WRAP9] = 0, + [D3DRS_WRAP10] = 0, + [D3DRS_WRAP11] = 0, + [D3DRS_WRAP12] = 0, + [D3DRS_WRAP13] = 0, + [D3DRS_WRAP14] = 0, + [D3DRS_WRAP15] = 0, + [D3DRS_SEPARATEALPHABLENDENABLE] = FALSE, + [D3DRS_SRCBLENDALPHA] = D3DBLEND_ONE, + [D3DRS_DESTBLENDALPHA] = D3DBLEND_ZERO, + [D3DRS_BLENDOPALPHA] = D3DBLENDOP_ADD, + [NINED3DRS_VSPOINTSIZE] = FALSE, + [NINED3DRS_RTMASK] = 0xf, + [NINED3DRS_ALPHACOVERAGE] = FALSE, + [NINED3DRS_MULTISAMPLE] = FALSE +}; +static const DWORD nine_tex_stage_state_defaults[NINED3DTSS_LAST + 1] = +{ + [D3DTSS_COLOROP] = D3DTOP_DISABLE, + [D3DTSS_ALPHAOP] = D3DTOP_DISABLE, + [D3DTSS_COLORARG1] = D3DTA_TEXTURE, + [D3DTSS_COLORARG2] = D3DTA_CURRENT, + [D3DTSS_COLORARG0] = D3DTA_CURRENT, + [D3DTSS_ALPHAARG1] = D3DTA_TEXTURE, + [D3DTSS_ALPHAARG2] = D3DTA_CURRENT, + [D3DTSS_ALPHAARG0] = D3DTA_CURRENT, + [D3DTSS_RESULTARG] = D3DTA_CURRENT, + [D3DTSS_BUMPENVMAT00] = 0, + [D3DTSS_BUMPENVMAT01] = 0, + [D3DTSS_BUMPENVMAT10] = 0, + [D3DTSS_BUMPENVMAT11] = 0, + [D3DTSS_BUMPENVLSCALE] = 0, + [D3DTSS_BUMPENVLOFFSET] = 0, + [D3DTSS_TEXCOORDINDEX] = 0, + [D3DTSS_TEXTURETRANSFORMFLAGS] = D3DTTFF_DISABLE, +}; +static const DWORD nine_samp_state_defaults[NINED3DSAMP_LAST + 1] = +{ + [D3DSAMP_ADDRESSU] = D3DTADDRESS_WRAP, + [D3DSAMP_ADDRESSV] = D3DTADDRESS_WRAP, + [D3DSAMP_ADDRESSW] = D3DTADDRESS_WRAP, + [D3DSAMP_BORDERCOLOR] = 0, + [D3DSAMP_MAGFILTER] = D3DTEXF_POINT, + [D3DSAMP_MINFILTER] = D3DTEXF_POINT, + [D3DSAMP_MIPFILTER] = D3DTEXF_NONE, + [D3DSAMP_MIPMAPLODBIAS] = 0, + [D3DSAMP_MAXMIPLEVEL] = 0, + [D3DSAMP_MAXANISOTROPY] = 1, + [D3DSAMP_SRGBTEXTURE] = 0, + [D3DSAMP_ELEMENTINDEX] = 0, + [D3DSAMP_DMAPOFFSET] = 0, + [NINED3DSAMP_MINLOD] = 0, + [NINED3DSAMP_SHADOW] = 0, + [NINED3DSAMP_CUBETEX] = 0 +}; + +/* Note: The following 4 functions assume there is no + * pending commands */ + +void nine_state_restore_non_cso(struct NineDevice9 *device) +{ + struct nine_context *context = &device->context; + + context->changed.group = NINE_STATE_ALL; + context->changed.vtxbuf = (1ULL << device->caps.MaxStreams) - 1; + context->changed.ucp = TRUE; + context->commit |= NINE_STATE_COMMIT_CONST_VS | NINE_STATE_COMMIT_CONST_PS; +} + +void +nine_state_set_defaults(struct NineDevice9 *device, const D3DCAPS9 *caps, + boolean is_reset) +{ + struct nine_state *state = &device->state; + struct nine_context *context = &device->context; + unsigned s; + + /* Initialize defaults. + */ + memcpy(context->rs, nine_render_state_defaults, sizeof(context->rs)); + + for (s = 0; s < ARRAY_SIZE(state->ff.tex_stage); ++s) { + memcpy(&state->ff.tex_stage[s], nine_tex_stage_state_defaults, + sizeof(state->ff.tex_stage[s])); + state->ff.tex_stage[s][D3DTSS_TEXCOORDINDEX] = s; + } + state->ff.tex_stage[0][D3DTSS_COLOROP] = D3DTOP_MODULATE; + state->ff.tex_stage[0][D3DTSS_ALPHAOP] = D3DTOP_SELECTARG1; + + for (s = 0; s < ARRAY_SIZE(state->ff.tex_stage); ++s) + memcpy(&context->ff.tex_stage[s], state->ff.tex_stage[s], + sizeof(state->ff.tex_stage[s])); + + memset(&context->bumpmap_vars, 0, sizeof(context->bumpmap_vars)); + + for (s = 0; s < NINE_MAX_SAMPLERS; ++s) { + memcpy(&context->samp[s], nine_samp_state_defaults, + sizeof(context->samp[s])); + memcpy(&state->samp_advertised[s], nine_samp_state_defaults, + sizeof(state->samp_advertised[s])); + } + + memset(state->vs_const_f, 0, VS_CONST_F_SIZE(device)); + memset(context->vs_const_f, 0, device->vs_const_size); + if (context->vs_const_f_swvp) + memset(context->vs_const_f_swvp, 0, NINE_MAX_CONST_F_SWVP * sizeof(float[4])); + memset(state->vs_const_i, 0, VS_CONST_I_SIZE(device)); + memset(context->vs_const_i, 0, VS_CONST_I_SIZE(device)); + memset(state->vs_const_b, 0, VS_CONST_B_SIZE(device)); + memset(context->vs_const_b, 0, VS_CONST_B_SIZE(device)); + memset(state->ps_const_f, 0, device->ps_const_size); + memset(context->ps_const_f, 0, device->ps_const_size); + memset(state->ps_const_i, 0, sizeof(state->ps_const_i)); + memset(context->ps_const_i, 0, sizeof(context->ps_const_i)); + memset(state->ps_const_b, 0, sizeof(state->ps_const_b)); + memset(context->ps_const_b, 0, sizeof(context->ps_const_b)); + + /* Cap dependent initial state: + */ + context->rs[D3DRS_POINTSIZE_MAX] = fui(caps->MaxPointSize); + + memcpy(state->rs_advertised, context->rs, sizeof(context->rs)); + + /* Set changed flags to initialize driver. + */ + context->changed.group = NINE_STATE_ALL; + context->changed.vtxbuf = (1ULL << device->caps.MaxStreams) - 1; + context->changed.ucp = TRUE; + + context->ff.changed.transform[0] = ~0; + context->ff.changed.transform[D3DTS_WORLD / 32] |= 1 << (D3DTS_WORLD % 32); + + if (!is_reset) { + state->viewport.MinZ = context->viewport.MinZ = 0.0f; + state->viewport.MaxZ = context->viewport.MaxZ = 1.0f; + } + + for (s = 0; s < NINE_MAX_SAMPLERS; ++s) + context->changed.sampler[s] = ~0; + + if (!is_reset) { + context->dummy_vbo_bound_at = -1; + context->vbo_bound_done = FALSE; + } +} + +void +nine_device_state_clear(struct NineDevice9 *device) +{ + struct nine_state *state = &device->state; + unsigned i; + + for (i = 0; i < ARRAY_SIZE(state->rt); ++i) + nine_bind(&state->rt[i], NULL); + nine_bind(&state->ds, NULL); + nine_bind(&state->vs, NULL); + nine_bind(&state->ps, NULL); + nine_bind(&state->vdecl, NULL); + for (i = 0; i < PIPE_MAX_ATTRIBS; ++i) + NineBindBufferToDevice(device, + (struct NineBuffer9 **)&state->stream[i], + NULL); + NineBindBufferToDevice(device, + (struct NineBuffer9 **)&state->idxbuf, + NULL); + + for (i = 0; i < NINE_MAX_SAMPLERS; ++i) + NineBindTextureToDevice(device, &state->texture[i], NULL); +} + +void +nine_context_clear(struct NineDevice9 *device) +{ + struct nine_context *context = &device->context; + struct pipe_context *pipe = context->pipe; + struct cso_context *cso = context->cso; + unsigned i; + + /* Early device ctor failure. Nothing to do */ + if (!pipe || !cso) + return; + + pipe->bind_vs_state(pipe, NULL); + pipe->bind_fs_state(pipe, NULL); + + /* Don't unbind constant buffers, they're device-private and + * do not change on Reset. + */ + + cso_set_samplers(cso, PIPE_SHADER_VERTEX, 0, NULL); + cso_set_samplers(cso, PIPE_SHADER_FRAGMENT, 0, NULL); + + cso_set_sampler_views(cso, PIPE_SHADER_VERTEX, 0, NULL); + cso_set_sampler_views(cso, PIPE_SHADER_FRAGMENT, 0, NULL); + + pipe->set_vertex_buffers(pipe, 0, device->caps.MaxStreams, NULL); + + for (i = 0; i < ARRAY_SIZE(context->rt); ++i) + nine_bind(&context->rt[i], NULL); + nine_bind(&context->ds, NULL); + nine_bind(&context->vs, NULL); + nine_bind(&context->ps, NULL); + nine_bind(&context->vdecl, NULL); + for (i = 0; i < PIPE_MAX_ATTRIBS; ++i) + pipe_vertex_buffer_unreference(&context->vtxbuf[i]); + pipe_resource_reference(&context->idxbuf, NULL); + pipe_resource_reference(&context->pipe_data.cb_vs.buffer, NULL); + pipe_resource_reference(&context->pipe_data.cb_ps.buffer, NULL); + + for (i = 0; i < NINE_MAX_SAMPLERS; ++i) { + context->texture[i].enabled = FALSE; + pipe_resource_reference(&context->texture[i].resource, + NULL); + pipe_sampler_view_reference(&context->texture[i].view[0], + NULL); + pipe_sampler_view_reference(&context->texture[i].view[1], + NULL); + } +} + +void +nine_state_init_sw(struct NineDevice9 *device) +{ + struct pipe_context *pipe_sw = device->pipe_sw; + struct pipe_rasterizer_state rast; + struct pipe_blend_state blend; + struct pipe_depth_stencil_alpha_state dsa; + struct pipe_framebuffer_state fb; + + /* Only used with Streamout */ + memset(&rast, 0, sizeof(rast)); + rast.rasterizer_discard = true; + rast.point_quad_rasterization = 1; /* to make llvmpipe happy */ + cso_set_rasterizer(device->cso_sw, &rast); + + /* dummy settings */ + memset(&blend, 0, sizeof(blend)); + memset(&dsa, 0, sizeof(dsa)); + memset(&fb, 0, sizeof(fb)); + cso_set_blend(device->cso_sw, &blend); + cso_set_depth_stencil_alpha(device->cso_sw, &dsa); + cso_set_framebuffer(device->cso_sw, &fb); + cso_set_viewport_dims(device->cso_sw, 1.0, 1.0, false); + cso_set_fragment_shader_handle(device->cso_sw, util_make_empty_fragment_shader(pipe_sw)); +} + +/* There is duplication with update_vertex_elements. + * TODO: Share the code */ + +static void +update_vertex_elements_sw(struct NineDevice9 *device) +{ + struct nine_state *state = &device->state; + const struct NineVertexDeclaration9 *vdecl = device->state.vdecl; + const struct NineVertexShader9 *vs; + unsigned n, b, i; + int index; + char vdecl_index_map[16]; /* vs->num_inputs <= 16 */ + char used_streams[device->caps.MaxStreams]; + int dummy_vbo_stream = -1; + BOOL need_dummy_vbo = FALSE; + struct cso_velems_state ve; + bool programmable_vs = state->vs && !(state->vdecl && state->vdecl->position_t); + + memset(vdecl_index_map, -1, 16); + memset(used_streams, 0, device->caps.MaxStreams); + vs = programmable_vs ? device->state.vs : device->ff.vs; + + if (vdecl) { + for (n = 0; n < vs->num_inputs; ++n) { + DBG("looking up input %u (usage %u) from vdecl(%p)\n", + n, vs->input_map[n].ndecl, vdecl); + + for (i = 0; i < vdecl->nelems; i++) { + if (vdecl->usage_map[i] == vs->input_map[n].ndecl) { + vdecl_index_map[n] = i; + used_streams[vdecl->elems[i].vertex_buffer_index] = 1; + break; + } + } + if (vdecl_index_map[n] < 0) + need_dummy_vbo = TRUE; + } + } else { + /* No vertex declaration. Likely will never happen in practice, + * but we need not crash on this */ + need_dummy_vbo = TRUE; + } + + if (need_dummy_vbo) { + for (i = 0; i < device->caps.MaxStreams; i++ ) { + if (!used_streams[i]) { + dummy_vbo_stream = i; + break; + } + } + } + /* TODO handle dummy_vbo */ + assert (!need_dummy_vbo); + + for (n = 0; n < vs->num_inputs; ++n) { + index = vdecl_index_map[n]; + if (index >= 0) { + ve.velems[n] = vdecl->elems[index]; + b = ve.velems[n].vertex_buffer_index; + /* XXX wine just uses 1 here: */ + if (state->stream_freq[b] & D3DSTREAMSOURCE_INSTANCEDATA) + ve.velems[n].instance_divisor = state->stream_freq[b] & 0x7FFFFF; + } else { + /* if the vertex declaration is incomplete compared to what the + * vertex shader needs, we bind a dummy vbo with 0 0 0 0. + * This is not precised by the spec, but is the behaviour + * tested on win */ + ve.velems[n].vertex_buffer_index = dummy_vbo_stream; + ve.velems[n].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + ve.velems[n].src_offset = 0; + ve.velems[n].instance_divisor = 0; + } + } + + ve.count = vs->num_inputs; + cso_set_vertex_elements(device->cso_sw, &ve); +} + +static void +update_vertex_buffers_sw(struct NineDevice9 *device, int start_vertice, int num_vertices) +{ + struct pipe_context *pipe = nine_context_get_pipe_acquire(device); + struct pipe_context *pipe_sw = device->pipe_sw; + struct nine_state *state = &device->state; + struct nine_state_sw_internal *sw_internal = &device->state_sw_internal; + struct pipe_vertex_buffer vtxbuf; + uint32_t mask = 0xf; + unsigned i; + + DBG("mask=%x\n", mask); + + /* TODO: handle dummy_vbo_bound_at */ + + for (i = 0; mask; mask >>= 1, ++i) { + if (mask & 1) { + if (state->stream[i]) { + unsigned offset; + struct pipe_resource *buf; + struct pipe_box box; + void *userbuf; + + vtxbuf = state->vtxbuf[i]; + buf = NineVertexBuffer9_GetResource(state->stream[i], &offset); + + DBG("Locking %p (offset %d, length %d)\n", buf, + vtxbuf.buffer_offset, num_vertices * vtxbuf.stride); + + u_box_1d(vtxbuf.buffer_offset + offset + start_vertice * vtxbuf.stride, + num_vertices * vtxbuf.stride, &box); + + userbuf = pipe->transfer_map(pipe, buf, 0, PIPE_TRANSFER_READ, &box, + &(sw_internal->transfers_so[i])); + vtxbuf.is_user_buffer = true; + vtxbuf.buffer.user = userbuf; + + if (!device->driver_caps.user_sw_vbufs) { + vtxbuf.buffer.resource = NULL; + vtxbuf.is_user_buffer = false; + u_upload_data(device->pipe_sw->stream_uploader, + 0, + box.width, + 16, + userbuf, + &(vtxbuf.buffer_offset), + &(vtxbuf.buffer.resource)); + u_upload_unmap(device->pipe_sw->stream_uploader); + } + pipe_sw->set_vertex_buffers(pipe_sw, i, 1, &vtxbuf); + pipe_vertex_buffer_unreference(&vtxbuf); + } else + pipe_sw->set_vertex_buffers(pipe_sw, i, 1, NULL); + } + } + nine_context_get_pipe_release(device); +} + +static void +update_vs_constants_sw(struct NineDevice9 *device) +{ + struct nine_state *state = &device->state; + struct pipe_context *pipe_sw = device->pipe_sw; + + DBG("updating\n"); + + { + struct pipe_constant_buffer cb; + const void *buf; + + cb.buffer = NULL; + cb.buffer_offset = 0; + cb.buffer_size = 4096 * sizeof(float[4]); + cb.user_buffer = state->vs_const_f; + + if (state->vs->lconstf.ranges) { + const struct nine_lconstf *lconstf = &device->state.vs->lconstf; + const struct nine_range *r = lconstf->ranges; + unsigned n = 0; + float *dst = device->state.vs_lconstf_temp; + float *src = (float *)cb.user_buffer; + memcpy(dst, src, 8192 * sizeof(float[4])); + while (r) { + unsigned p = r->bgn; + unsigned c = r->end - r->bgn; + memcpy(&dst[p * 4], &lconstf->data[n * 4], c * 4 * sizeof(float)); + n += c; + r = r->next; + } + cb.user_buffer = dst; + } + + buf = cb.user_buffer; + + pipe_sw->set_constant_buffer(pipe_sw, PIPE_SHADER_VERTEX, 0, &cb); + if (cb.buffer) + pipe_resource_reference(&cb.buffer, NULL); + + cb.user_buffer = (char *)buf + 4096 * sizeof(float[4]); + + pipe_sw->set_constant_buffer(pipe_sw, PIPE_SHADER_VERTEX, 1, &cb); + if (cb.buffer) + pipe_resource_reference(&cb.buffer, NULL); + } + + { + struct pipe_constant_buffer cb; + + cb.buffer = NULL; + cb.buffer_offset = 0; + cb.buffer_size = 2048 * sizeof(float[4]); + cb.user_buffer = state->vs_const_i; + + pipe_sw->set_constant_buffer(pipe_sw, PIPE_SHADER_VERTEX, 2, &cb); + if (cb.buffer) + pipe_resource_reference(&cb.buffer, NULL); + } + + { + struct pipe_constant_buffer cb; + + cb.buffer = NULL; + cb.buffer_offset = 0; + cb.buffer_size = 512 * sizeof(float[4]); + cb.user_buffer = state->vs_const_b; + + pipe_sw->set_constant_buffer(pipe_sw, PIPE_SHADER_VERTEX, 3, &cb); + if (cb.buffer) + pipe_resource_reference(&cb.buffer, NULL); + } + + { + struct pipe_constant_buffer cb; + const D3DVIEWPORT9 *vport = &device->state.viewport; + float viewport_data[8] = {(float)vport->Width * 0.5f, + (float)vport->Height * -0.5f, vport->MaxZ - vport->MinZ, 0.f, + (float)vport->Width * 0.5f + (float)vport->X, + (float)vport->Height * 0.5f + (float)vport->Y, + vport->MinZ, 0.f}; + + cb.buffer = NULL; + cb.buffer_offset = 0; + cb.buffer_size = 2 * sizeof(float[4]); + cb.user_buffer = viewport_data; + + { + u_upload_data(device->pipe_sw->const_uploader, + 0, + cb.buffer_size, + 16, + cb.user_buffer, + &(cb.buffer_offset), + &(cb.buffer)); + u_upload_unmap(device->pipe_sw->const_uploader); + cb.user_buffer = NULL; + } + + pipe_sw->set_constant_buffer(pipe_sw, PIPE_SHADER_VERTEX, 4, &cb); + if (cb.buffer) + pipe_resource_reference(&cb.buffer, NULL); + } + +} + +void +nine_state_prepare_draw_sw(struct NineDevice9 *device, struct NineVertexDeclaration9 *vdecl_out, + int start_vertice, int num_vertices, struct pipe_stream_output_info *so) +{ + struct nine_state *state = &device->state; + bool programmable_vs = state->vs && !(state->vdecl && state->vdecl->position_t); + struct NineVertexShader9 *vs = programmable_vs ? device->state.vs : device->ff.vs; + + assert(programmable_vs); + + DBG("Preparing draw\n"); + cso_set_vertex_shader_handle(device->cso_sw, + NineVertexShader9_GetVariantProcessVertices(vs, vdecl_out, so)); + update_vertex_elements_sw(device); + update_vertex_buffers_sw(device, start_vertice, num_vertices); + update_vs_constants_sw(device); + DBG("Preparation succeeded\n"); +} + +void +nine_state_after_draw_sw(struct NineDevice9 *device) +{ + struct nine_state_sw_internal *sw_internal = &device->state_sw_internal; + struct pipe_context *pipe = nine_context_get_pipe_acquire(device); + struct pipe_context *pipe_sw = device->pipe_sw; + int i; + + for (i = 0; i < 4; i++) { + pipe_sw->set_vertex_buffers(pipe_sw, i, 1, NULL); + if (sw_internal->transfers_so[i]) + pipe->transfer_unmap(pipe, sw_internal->transfers_so[i]); + sw_internal->transfers_so[i] = NULL; + } + nine_context_get_pipe_release(device); +} + +void +nine_state_destroy_sw(struct NineDevice9 *device) +{ + (void) device; + /* Everything destroyed with cso */ +} + +/* +static const DWORD nine_render_states_pixel[] = +{ + D3DRS_ALPHABLENDENABLE, + D3DRS_ALPHAFUNC, + D3DRS_ALPHAREF, + D3DRS_ALPHATESTENABLE, + D3DRS_ANTIALIASEDLINEENABLE, + D3DRS_BLENDFACTOR, + D3DRS_BLENDOP, + D3DRS_BLENDOPALPHA, + D3DRS_CCW_STENCILFAIL, + D3DRS_CCW_STENCILPASS, + D3DRS_CCW_STENCILZFAIL, + D3DRS_COLORWRITEENABLE, + D3DRS_COLORWRITEENABLE1, + D3DRS_COLORWRITEENABLE2, + D3DRS_COLORWRITEENABLE3, + D3DRS_DEPTHBIAS, + D3DRS_DESTBLEND, + D3DRS_DESTBLENDALPHA, + D3DRS_DITHERENABLE, + D3DRS_FILLMODE, + D3DRS_FOGDENSITY, + D3DRS_FOGEND, + D3DRS_FOGSTART, + D3DRS_LASTPIXEL, + D3DRS_SCISSORTESTENABLE, + D3DRS_SEPARATEALPHABLENDENABLE, + D3DRS_SHADEMODE, + D3DRS_SLOPESCALEDEPTHBIAS, + D3DRS_SRCBLEND, + D3DRS_SRCBLENDALPHA, + D3DRS_SRGBWRITEENABLE, + D3DRS_STENCILENABLE, + D3DRS_STENCILFAIL, + D3DRS_STENCILFUNC, + D3DRS_STENCILMASK, + D3DRS_STENCILPASS, + D3DRS_STENCILREF, + D3DRS_STENCILWRITEMASK, + D3DRS_STENCILZFAIL, + D3DRS_TEXTUREFACTOR, + D3DRS_TWOSIDEDSTENCILMODE, + D3DRS_WRAP0, + D3DRS_WRAP1, + D3DRS_WRAP10, + D3DRS_WRAP11, + D3DRS_WRAP12, + D3DRS_WRAP13, + D3DRS_WRAP14, + D3DRS_WRAP15, + D3DRS_WRAP2, + D3DRS_WRAP3, + D3DRS_WRAP4, + D3DRS_WRAP5, + D3DRS_WRAP6, + D3DRS_WRAP7, + D3DRS_WRAP8, + D3DRS_WRAP9, + D3DRS_ZENABLE, + D3DRS_ZFUNC, + D3DRS_ZWRITEENABLE +}; +*/ +const uint32_t nine_render_states_pixel[(NINED3DRS_LAST + 31) / 32] = +{ + 0x0f99c380, 0x1ff00070, 0x00000000, 0x00000000, + 0x000000ff, 0xde01c900, 0x0003ffcf +}; + +/* +static const DWORD nine_render_states_vertex[] = +{ + D3DRS_ADAPTIVETESS_W, + D3DRS_ADAPTIVETESS_X, + D3DRS_ADAPTIVETESS_Y, + D3DRS_ADAPTIVETESS_Z, + D3DRS_AMBIENT, + D3DRS_AMBIENTMATERIALSOURCE, + D3DRS_CLIPPING, + D3DRS_CLIPPLANEENABLE, + D3DRS_COLORVERTEX, + D3DRS_CULLMODE, + D3DRS_DIFFUSEMATERIALSOURCE, + D3DRS_EMISSIVEMATERIALSOURCE, + D3DRS_ENABLEADAPTIVETESSELLATION, + D3DRS_FOGCOLOR, + D3DRS_FOGDENSITY, + D3DRS_FOGENABLE, + D3DRS_FOGEND, + D3DRS_FOGSTART, + D3DRS_FOGTABLEMODE, + D3DRS_FOGVERTEXMODE, + D3DRS_INDEXEDVERTEXBLENDENABLE, + D3DRS_LIGHTING, + D3DRS_LOCALVIEWER, + D3DRS_MAXTESSELLATIONLEVEL, + D3DRS_MINTESSELLATIONLEVEL, + D3DRS_MULTISAMPLEANTIALIAS, + D3DRS_MULTISAMPLEMASK, + D3DRS_NORMALDEGREE, + D3DRS_NORMALIZENORMALS, + D3DRS_PATCHEDGESTYLE, + D3DRS_POINTSCALE_A, + D3DRS_POINTSCALE_B, + D3DRS_POINTSCALE_C, + D3DRS_POINTSCALEENABLE, + D3DRS_POINTSIZE, + D3DRS_POINTSIZE_MAX, + D3DRS_POINTSIZE_MIN, + D3DRS_POINTSPRITEENABLE, + D3DRS_POSITIONDEGREE, + D3DRS_RANGEFOGENABLE, + D3DRS_SHADEMODE, + D3DRS_SPECULARENABLE, + D3DRS_SPECULARMATERIALSOURCE, + D3DRS_TWEENFACTOR, + D3DRS_VERTEXBLEND +}; +*/ +const uint32_t nine_render_states_vertex[(NINED3DRS_LAST + 31) / 32] = +{ + 0x30400200, 0x0001007c, 0x00000000, 0x00000000, + 0xfd9efb00, 0x01fc34cf, 0x00000000 +}; + +/* TODO: put in the right values */ +const uint32_t nine_render_state_group[NINED3DRS_LAST + 1] = +{ + [D3DRS_ZENABLE] = NINE_STATE_DSA | NINE_STATE_MULTISAMPLE, + [D3DRS_FILLMODE] = NINE_STATE_RASTERIZER, + [D3DRS_SHADEMODE] = NINE_STATE_RASTERIZER, + [D3DRS_ZWRITEENABLE] = NINE_STATE_DSA, + [D3DRS_ALPHATESTENABLE] = NINE_STATE_DSA, + [D3DRS_LASTPIXEL] = NINE_STATE_RASTERIZER, + [D3DRS_SRCBLEND] = NINE_STATE_BLEND, + [D3DRS_DESTBLEND] = NINE_STATE_BLEND, + [D3DRS_CULLMODE] = NINE_STATE_RASTERIZER, + [D3DRS_ZFUNC] = NINE_STATE_DSA, + [D3DRS_ALPHAREF] = NINE_STATE_DSA, + [D3DRS_ALPHAFUNC] = NINE_STATE_DSA, + [D3DRS_DITHERENABLE] = NINE_STATE_BLEND, + [D3DRS_ALPHABLENDENABLE] = NINE_STATE_BLEND, + [D3DRS_FOGENABLE] = NINE_STATE_FF_SHADER | NINE_STATE_VS_PARAMS_MISC | NINE_STATE_PS_PARAMS_MISC | NINE_STATE_PS_CONST, + [D3DRS_SPECULARENABLE] = NINE_STATE_FF_LIGHTING, + [D3DRS_FOGCOLOR] = NINE_STATE_FF_PS_CONSTS | NINE_STATE_PS_CONST, + [D3DRS_FOGTABLEMODE] = NINE_STATE_FF_SHADER | NINE_STATE_PS_PARAMS_MISC | NINE_STATE_PS_CONST, + [D3DRS_FOGSTART] = NINE_STATE_FF_VS_OTHER | NINE_STATE_FF_PS_CONSTS | NINE_STATE_PS_CONST, + [D3DRS_FOGEND] = NINE_STATE_FF_VS_OTHER | NINE_STATE_FF_PS_CONSTS | NINE_STATE_PS_CONST, + [D3DRS_FOGDENSITY] = NINE_STATE_FF_VS_OTHER | NINE_STATE_FF_PS_CONSTS | NINE_STATE_PS_CONST, + [D3DRS_RANGEFOGENABLE] = NINE_STATE_FF_SHADER, + [D3DRS_STENCILENABLE] = NINE_STATE_DSA | NINE_STATE_MULTISAMPLE, + [D3DRS_STENCILFAIL] = NINE_STATE_DSA, + [D3DRS_STENCILZFAIL] = NINE_STATE_DSA, + [D3DRS_STENCILPASS] = NINE_STATE_DSA, + [D3DRS_STENCILFUNC] = NINE_STATE_DSA, + [D3DRS_STENCILREF] = NINE_STATE_STENCIL_REF, + [D3DRS_STENCILMASK] = NINE_STATE_DSA, + [D3DRS_STENCILWRITEMASK] = NINE_STATE_DSA, + [D3DRS_TEXTUREFACTOR] = NINE_STATE_FF_PS_CONSTS, + [D3DRS_WRAP0] = NINE_STATE_UNHANDLED, /* cylindrical wrap is crazy */ + [D3DRS_WRAP1] = NINE_STATE_UNHANDLED, + [D3DRS_WRAP2] = NINE_STATE_UNHANDLED, + [D3DRS_WRAP3] = NINE_STATE_UNHANDLED, + [D3DRS_WRAP4] = NINE_STATE_UNHANDLED, + [D3DRS_WRAP5] = NINE_STATE_UNHANDLED, + [D3DRS_WRAP6] = NINE_STATE_UNHANDLED, + [D3DRS_WRAP7] = NINE_STATE_UNHANDLED, + [D3DRS_CLIPPING] = 0, /* software vertex processing only */ + [D3DRS_LIGHTING] = NINE_STATE_FF_LIGHTING, + [D3DRS_AMBIENT] = NINE_STATE_FF_LIGHTING | NINE_STATE_FF_MATERIAL, + [D3DRS_FOGVERTEXMODE] = NINE_STATE_FF_SHADER, + [D3DRS_COLORVERTEX] = NINE_STATE_FF_LIGHTING, + [D3DRS_LOCALVIEWER] = NINE_STATE_FF_LIGHTING, + [D3DRS_NORMALIZENORMALS] = NINE_STATE_FF_SHADER, + [D3DRS_DIFFUSEMATERIALSOURCE] = NINE_STATE_FF_LIGHTING, + [D3DRS_SPECULARMATERIALSOURCE] = NINE_STATE_FF_LIGHTING, + [D3DRS_AMBIENTMATERIALSOURCE] = NINE_STATE_FF_LIGHTING, + [D3DRS_EMISSIVEMATERIALSOURCE] = NINE_STATE_FF_LIGHTING, + [D3DRS_VERTEXBLEND] = NINE_STATE_FF_SHADER, + [D3DRS_CLIPPLANEENABLE] = NINE_STATE_RASTERIZER, + [D3DRS_POINTSIZE] = NINE_STATE_RASTERIZER | NINE_STATE_FF_VS_OTHER, + [D3DRS_POINTSIZE_MIN] = NINE_STATE_RASTERIZER | NINE_STATE_FF_VS_OTHER | NINE_STATE_VS_PARAMS_MISC, + [D3DRS_POINTSPRITEENABLE] = NINE_STATE_RASTERIZER, + [D3DRS_POINTSCALEENABLE] = NINE_STATE_FF_SHADER, + [D3DRS_POINTSCALE_A] = NINE_STATE_FF_VS_OTHER, + [D3DRS_POINTSCALE_B] = NINE_STATE_FF_VS_OTHER, + [D3DRS_POINTSCALE_C] = NINE_STATE_FF_VS_OTHER, + [D3DRS_MULTISAMPLEANTIALIAS] = NINE_STATE_MULTISAMPLE, + [D3DRS_MULTISAMPLEMASK] = NINE_STATE_SAMPLE_MASK, + [D3DRS_PATCHEDGESTYLE] = NINE_STATE_UNHANDLED, + [D3DRS_DEBUGMONITORTOKEN] = NINE_STATE_UNHANDLED, + [D3DRS_POINTSIZE_MAX] = NINE_STATE_RASTERIZER | NINE_STATE_FF_VS_OTHER | NINE_STATE_VS_PARAMS_MISC, + [D3DRS_INDEXEDVERTEXBLENDENABLE] = NINE_STATE_FF_SHADER, + [D3DRS_COLORWRITEENABLE] = NINE_STATE_BLEND, + [D3DRS_TWEENFACTOR] = NINE_STATE_FF_VS_OTHER, + [D3DRS_BLENDOP] = NINE_STATE_BLEND, + [D3DRS_POSITIONDEGREE] = NINE_STATE_UNHANDLED, + [D3DRS_NORMALDEGREE] = NINE_STATE_UNHANDLED, + [D3DRS_SCISSORTESTENABLE] = NINE_STATE_RASTERIZER, + [D3DRS_SLOPESCALEDEPTHBIAS] = NINE_STATE_RASTERIZER, + [D3DRS_ANTIALIASEDLINEENABLE] = NINE_STATE_RASTERIZER, + [D3DRS_MINTESSELLATIONLEVEL] = NINE_STATE_UNHANDLED, + [D3DRS_MAXTESSELLATIONLEVEL] = NINE_STATE_UNHANDLED, + [D3DRS_ADAPTIVETESS_X] = NINE_STATE_UNHANDLED, + [D3DRS_ADAPTIVETESS_Y] = NINE_STATE_UNHANDLED, + [D3DRS_ADAPTIVETESS_Z] = NINE_STATE_UNHANDLED, + [D3DRS_ADAPTIVETESS_W] = NINE_STATE_UNHANDLED, + [D3DRS_ENABLEADAPTIVETESSELLATION] = NINE_STATE_UNHANDLED, + [D3DRS_TWOSIDEDSTENCILMODE] = NINE_STATE_DSA, + [D3DRS_CCW_STENCILFAIL] = NINE_STATE_DSA, + [D3DRS_CCW_STENCILZFAIL] = NINE_STATE_DSA, + [D3DRS_CCW_STENCILPASS] = NINE_STATE_DSA, + [D3DRS_CCW_STENCILFUNC] = NINE_STATE_DSA, + [D3DRS_COLORWRITEENABLE1] = NINE_STATE_BLEND, + [D3DRS_COLORWRITEENABLE2] = NINE_STATE_BLEND, + [D3DRS_COLORWRITEENABLE3] = NINE_STATE_BLEND, + [D3DRS_BLENDFACTOR] = NINE_STATE_BLEND_COLOR, + [D3DRS_SRGBWRITEENABLE] = NINE_STATE_FB, + [D3DRS_DEPTHBIAS] = NINE_STATE_RASTERIZER, + [D3DRS_WRAP8] = NINE_STATE_UNHANDLED, /* cylwrap has to be done via GP */ + [D3DRS_WRAP9] = NINE_STATE_UNHANDLED, + [D3DRS_WRAP10] = NINE_STATE_UNHANDLED, + [D3DRS_WRAP11] = NINE_STATE_UNHANDLED, + [D3DRS_WRAP12] = NINE_STATE_UNHANDLED, + [D3DRS_WRAP13] = NINE_STATE_UNHANDLED, + [D3DRS_WRAP14] = NINE_STATE_UNHANDLED, + [D3DRS_WRAP15] = NINE_STATE_UNHANDLED, + [D3DRS_SEPARATEALPHABLENDENABLE] = NINE_STATE_BLEND, + [D3DRS_SRCBLENDALPHA] = NINE_STATE_BLEND, + [D3DRS_DESTBLENDALPHA] = NINE_STATE_BLEND, + [D3DRS_BLENDOPALPHA] = NINE_STATE_BLEND +}; + +/* Misc */ + +static D3DMATRIX nine_state_identity = { .m[0] = { 1, 0, 0, 0 }, + .m[1] = { 0, 1, 0, 0 }, + .m[2] = { 0, 0, 1, 0 }, + .m[3] = { 0, 0, 0, 1 } }; + +void +nine_state_resize_transform(struct nine_ff_state *ff_state, unsigned N) +{ + unsigned n = ff_state->num_transforms; + + if (N <= n) + return; + + ff_state->transform = REALLOC(ff_state->transform, + n * sizeof(D3DMATRIX), + N * sizeof(D3DMATRIX)); + for (; n < N; ++n) + ff_state->transform[n] = nine_state_identity; + ff_state->num_transforms = N; +} + +D3DMATRIX * +nine_state_access_transform(struct nine_ff_state *ff_state, D3DTRANSFORMSTATETYPE t, + boolean alloc) +{ + unsigned index; + + switch (t) { + case D3DTS_VIEW: index = 0; break; + case D3DTS_PROJECTION: index = 1; break; + case D3DTS_TEXTURE0: index = 2; break; + case D3DTS_TEXTURE1: index = 3; break; + case D3DTS_TEXTURE2: index = 4; break; + case D3DTS_TEXTURE3: index = 5; break; + case D3DTS_TEXTURE4: index = 6; break; + case D3DTS_TEXTURE5: index = 7; break; + case D3DTS_TEXTURE6: index = 8; break; + case D3DTS_TEXTURE7: index = 9; break; + default: + if (!(t >= D3DTS_WORLDMATRIX(0) && t <= D3DTS_WORLDMATRIX(255))) + return NULL; + index = 10 + (t - D3DTS_WORLDMATRIX(0)); + break; + } + + if (index >= ff_state->num_transforms) { + if (!alloc) + return &nine_state_identity; + nine_state_resize_transform(ff_state, index + 1); + } + return &ff_state->transform[index]; +} + +HRESULT +nine_state_set_light(struct nine_ff_state *ff_state, DWORD Index, + const D3DLIGHT9 *pLight) +{ + if (Index >= ff_state->num_lights) { + unsigned n = ff_state->num_lights; + unsigned N = Index + 1; + + ff_state->light = REALLOC(ff_state->light, n * sizeof(D3DLIGHT9), + N * sizeof(D3DLIGHT9)); + if (!ff_state->light) + return E_OUTOFMEMORY; + ff_state->num_lights = N; + + for (; n < Index; ++n) { + memset(&ff_state->light[n], 0, sizeof(D3DLIGHT9)); + ff_state->light[n].Type = (D3DLIGHTTYPE)NINED3DLIGHT_INVALID; + } + } + ff_state->light[Index] = *pLight; + + if (pLight->Type == D3DLIGHT_SPOT && pLight->Theta >= pLight->Phi) { + DBG("Warning: clamping D3DLIGHT9.Theta\n"); + ff_state->light[Index].Theta = ff_state->light[Index].Phi; + } + return D3D_OK; +} + +HRESULT +nine_state_light_enable(struct nine_ff_state *ff_state, + DWORD Index, BOOL Enable) +{ + unsigned i; + + user_assert(Index < ff_state->num_lights, D3DERR_INVALIDCALL); + + for (i = 0; i < ff_state->num_lights_active; ++i) { + if (ff_state->active_light[i] == Index) + break; + } + + if (Enable) { + if (i < ff_state->num_lights_active) + return D3D_OK; + /* XXX wine thinks this should still succeed: + */ + user_assert(i < NINE_MAX_LIGHTS_ACTIVE, D3DERR_INVALIDCALL); + + ff_state->active_light[i] = Index; + ff_state->num_lights_active++; + } else { + if (i == ff_state->num_lights_active) + return D3D_OK; + --ff_state->num_lights_active; + for (; i < ff_state->num_lights_active; ++i) + ff_state->active_light[i] = ff_state->active_light[i + 1]; + } + + return D3D_OK; +} + +#define D3DRS_TO_STRING_CASE(n) case D3DRS_##n: return "D3DRS_"#n +const char *nine_d3drs_to_string(DWORD State) +{ + switch (State) { + D3DRS_TO_STRING_CASE(ZENABLE); + D3DRS_TO_STRING_CASE(FILLMODE); + D3DRS_TO_STRING_CASE(SHADEMODE); + D3DRS_TO_STRING_CASE(ZWRITEENABLE); + D3DRS_TO_STRING_CASE(ALPHATESTENABLE); + D3DRS_TO_STRING_CASE(LASTPIXEL); + D3DRS_TO_STRING_CASE(SRCBLEND); + D3DRS_TO_STRING_CASE(DESTBLEND); + D3DRS_TO_STRING_CASE(CULLMODE); + D3DRS_TO_STRING_CASE(ZFUNC); + D3DRS_TO_STRING_CASE(ALPHAREF); + D3DRS_TO_STRING_CASE(ALPHAFUNC); + D3DRS_TO_STRING_CASE(DITHERENABLE); + D3DRS_TO_STRING_CASE(ALPHABLENDENABLE); + D3DRS_TO_STRING_CASE(FOGENABLE); + D3DRS_TO_STRING_CASE(SPECULARENABLE); + D3DRS_TO_STRING_CASE(FOGCOLOR); + D3DRS_TO_STRING_CASE(FOGTABLEMODE); + D3DRS_TO_STRING_CASE(FOGSTART); + D3DRS_TO_STRING_CASE(FOGEND); + D3DRS_TO_STRING_CASE(FOGDENSITY); + D3DRS_TO_STRING_CASE(RANGEFOGENABLE); + D3DRS_TO_STRING_CASE(STENCILENABLE); + D3DRS_TO_STRING_CASE(STENCILFAIL); + D3DRS_TO_STRING_CASE(STENCILZFAIL); + D3DRS_TO_STRING_CASE(STENCILPASS); + D3DRS_TO_STRING_CASE(STENCILFUNC); + D3DRS_TO_STRING_CASE(STENCILREF); + D3DRS_TO_STRING_CASE(STENCILMASK); + D3DRS_TO_STRING_CASE(STENCILWRITEMASK); + D3DRS_TO_STRING_CASE(TEXTUREFACTOR); + D3DRS_TO_STRING_CASE(WRAP0); + D3DRS_TO_STRING_CASE(WRAP1); + D3DRS_TO_STRING_CASE(WRAP2); + D3DRS_TO_STRING_CASE(WRAP3); + D3DRS_TO_STRING_CASE(WRAP4); + D3DRS_TO_STRING_CASE(WRAP5); + D3DRS_TO_STRING_CASE(WRAP6); + D3DRS_TO_STRING_CASE(WRAP7); + D3DRS_TO_STRING_CASE(CLIPPING); + D3DRS_TO_STRING_CASE(LIGHTING); + D3DRS_TO_STRING_CASE(AMBIENT); + D3DRS_TO_STRING_CASE(FOGVERTEXMODE); + D3DRS_TO_STRING_CASE(COLORVERTEX); + D3DRS_TO_STRING_CASE(LOCALVIEWER); + D3DRS_TO_STRING_CASE(NORMALIZENORMALS); + D3DRS_TO_STRING_CASE(DIFFUSEMATERIALSOURCE); + D3DRS_TO_STRING_CASE(SPECULARMATERIALSOURCE); + D3DRS_TO_STRING_CASE(AMBIENTMATERIALSOURCE); + D3DRS_TO_STRING_CASE(EMISSIVEMATERIALSOURCE); + D3DRS_TO_STRING_CASE(VERTEXBLEND); + D3DRS_TO_STRING_CASE(CLIPPLANEENABLE); + D3DRS_TO_STRING_CASE(POINTSIZE); + D3DRS_TO_STRING_CASE(POINTSIZE_MIN); + D3DRS_TO_STRING_CASE(POINTSPRITEENABLE); + D3DRS_TO_STRING_CASE(POINTSCALEENABLE); + D3DRS_TO_STRING_CASE(POINTSCALE_A); + D3DRS_TO_STRING_CASE(POINTSCALE_B); + D3DRS_TO_STRING_CASE(POINTSCALE_C); + D3DRS_TO_STRING_CASE(MULTISAMPLEANTIALIAS); + D3DRS_TO_STRING_CASE(MULTISAMPLEMASK); + D3DRS_TO_STRING_CASE(PATCHEDGESTYLE); + D3DRS_TO_STRING_CASE(DEBUGMONITORTOKEN); + D3DRS_TO_STRING_CASE(POINTSIZE_MAX); + D3DRS_TO_STRING_CASE(INDEXEDVERTEXBLENDENABLE); + D3DRS_TO_STRING_CASE(COLORWRITEENABLE); + D3DRS_TO_STRING_CASE(TWEENFACTOR); + D3DRS_TO_STRING_CASE(BLENDOP); + D3DRS_TO_STRING_CASE(POSITIONDEGREE); + D3DRS_TO_STRING_CASE(NORMALDEGREE); + D3DRS_TO_STRING_CASE(SCISSORTESTENABLE); + D3DRS_TO_STRING_CASE(SLOPESCALEDEPTHBIAS); + D3DRS_TO_STRING_CASE(ANTIALIASEDLINEENABLE); + D3DRS_TO_STRING_CASE(MINTESSELLATIONLEVEL); + D3DRS_TO_STRING_CASE(MAXTESSELLATIONLEVEL); + D3DRS_TO_STRING_CASE(ADAPTIVETESS_X); + D3DRS_TO_STRING_CASE(ADAPTIVETESS_Y); + D3DRS_TO_STRING_CASE(ADAPTIVETESS_Z); + D3DRS_TO_STRING_CASE(ADAPTIVETESS_W); + D3DRS_TO_STRING_CASE(ENABLEADAPTIVETESSELLATION); + D3DRS_TO_STRING_CASE(TWOSIDEDSTENCILMODE); + D3DRS_TO_STRING_CASE(CCW_STENCILFAIL); + D3DRS_TO_STRING_CASE(CCW_STENCILZFAIL); + D3DRS_TO_STRING_CASE(CCW_STENCILPASS); + D3DRS_TO_STRING_CASE(CCW_STENCILFUNC); + D3DRS_TO_STRING_CASE(COLORWRITEENABLE1); + D3DRS_TO_STRING_CASE(COLORWRITEENABLE2); + D3DRS_TO_STRING_CASE(COLORWRITEENABLE3); + D3DRS_TO_STRING_CASE(BLENDFACTOR); + D3DRS_TO_STRING_CASE(SRGBWRITEENABLE); + D3DRS_TO_STRING_CASE(DEPTHBIAS); + D3DRS_TO_STRING_CASE(WRAP8); + D3DRS_TO_STRING_CASE(WRAP9); + D3DRS_TO_STRING_CASE(WRAP10); + D3DRS_TO_STRING_CASE(WRAP11); + D3DRS_TO_STRING_CASE(WRAP12); + D3DRS_TO_STRING_CASE(WRAP13); + D3DRS_TO_STRING_CASE(WRAP14); + D3DRS_TO_STRING_CASE(WRAP15); + D3DRS_TO_STRING_CASE(SEPARATEALPHABLENDENABLE); + D3DRS_TO_STRING_CASE(SRCBLENDALPHA); + D3DRS_TO_STRING_CASE(DESTBLENDALPHA); + D3DRS_TO_STRING_CASE(BLENDOPALPHA); + default: + return "(invalid)"; + } +} diff --git a/src/gallium/frontends/nine/nine_state.h b/src/gallium/frontends/nine/nine_state.h new file mode 100644 index 00000000000..d8fa2f80c4d --- /dev/null +++ b/src/gallium/frontends/nine/nine_state.h @@ -0,0 +1,672 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _NINE_STATE_H_ +#define _NINE_STATE_H_ + +#include "d3d9.h" +#include "nine_defines.h" +#include "pipe/p_state.h" +#include "util/list.h" + +#define NINED3DSAMP_MINLOD (D3DSAMP_DMAPOFFSET + 1) +#define NINED3DSAMP_SHADOW (D3DSAMP_DMAPOFFSET + 2) +#define NINED3DSAMP_CUBETEX (D3DSAMP_DMAPOFFSET + 3) + +#define NINED3DRS_VSPOINTSIZE (D3DRS_BLENDOPALPHA + 1) +#define NINED3DRS_RTMASK (D3DRS_BLENDOPALPHA + 2) +/* ALPHACOVERAGE: + * bit 0: enable alpha coverage + * bit 1: ATOC is on + */ +#define NINED3DRS_ALPHACOVERAGE (D3DRS_BLENDOPALPHA + 3) +#define NINED3DRS_MULTISAMPLE (D3DRS_BLENDOPALPHA + 4) + +#define D3DRS_LAST D3DRS_BLENDOPALPHA +#define D3DSAMP_LAST D3DSAMP_DMAPOFFSET +#define NINED3DRS_LAST NINED3DRS_MULTISAMPLE /* 214 */ +#define NINED3DSAMP_LAST NINED3DSAMP_CUBETEX /* 16 */ +#define NINED3DTSS_LAST D3DTSS_CONSTANT +#define NINED3DTS_LAST D3DTS_WORLDMATRIX(255) + +#define D3DRS_COUNT (D3DRS_LAST + 1) +#define D3DSAMP_COUNT (D3DSAMP_LAST + 1) +#define NINED3DRS_COUNT (NINED3DRS_LAST + 1) +#define NINED3DSAMP_COUNT (NINED3DSAMP_LAST + 1) +#define NINED3DTSS_COUNT (NINED3DTSS_LAST + 1) +#define NINED3DTS_COUNT (NINED3DTS_LAST + 1) + +#define NINE_STATE_FB (1 << 0) +#define NINE_STATE_VIEWPORT (1 << 1) +#define NINE_STATE_SCISSOR (1 << 2) +#define NINE_STATE_RASTERIZER (1 << 3) +#define NINE_STATE_BLEND (1 << 4) +#define NINE_STATE_DSA (1 << 5) +#define NINE_STATE_VS (1 << 6) +#define NINE_STATE_VS_CONST (1 << 7) +#define NINE_STATE_PS (1 << 8) +#define NINE_STATE_PS_CONST (1 << 9) +#define NINE_STATE_TEXTURE (1 << 10) +#define NINE_STATE_SAMPLER (1 << 11) +#define NINE_STATE_VDECL (1 << 12) +#define NINE_STATE_IDXBUF (1 << 13) +#define NINE_STATE_STREAMFREQ (1 << 14) +#define NINE_STATE_BLEND_COLOR (1 << 17) +#define NINE_STATE_STENCIL_REF (1 << 18) +#define NINE_STATE_SAMPLE_MASK (1 << 19) +#define NINE_STATE_FF (0x1f << 20) +#define NINE_STATE_FF_VS (0x17 << 20) +#define NINE_STATE_FF_PS (0x08 << 20) +#define NINE_STATE_FF_LIGHTING (1 << 20) +#define NINE_STATE_FF_MATERIAL (1 << 21) +#define NINE_STATE_FF_VSTRANSF (1 << 22) +#define NINE_STATE_FF_PS_CONSTS (1 << 23) +#define NINE_STATE_FF_VS_OTHER (1 << 24) +#define NINE_STATE_VS_PARAMS_MISC (1 << 25) +#define NINE_STATE_PS_PARAMS_MISC (1 << 26) +#define NINE_STATE_MULTISAMPLE (1 << 27) +#define NINE_STATE_SWVP (1 << 28) +#define NINE_STATE_ALL 0x1fffffff +#define NINE_STATE_UNHANDLED (1 << 29) + +/* These states affect the ff shader key, + * which we recompute everytime. */ +#define NINE_STATE_FF_SHADER 0 + +#define NINE_STATE_COMMIT_DSA (1 << 0) +#define NINE_STATE_COMMIT_RASTERIZER (1 << 1) +#define NINE_STATE_COMMIT_BLEND (1 << 2) +#define NINE_STATE_COMMIT_CONST_VS (1 << 3) +#define NINE_STATE_COMMIT_CONST_PS (1 << 4) +#define NINE_STATE_COMMIT_VS (1 << 5) +#define NINE_STATE_COMMIT_PS (1 << 6) + + +#define NINE_MAX_SIMULTANEOUS_RENDERTARGETS 4 +#define NINE_MAX_CONST_F_PS3 224 +#define NINE_MAX_CONST_F 256 +#define NINE_MAX_CONST_I 16 +#define NINE_MAX_CONST_B 16 +#define NINE_MAX_CONST_F_SWVP 8192 +#define NINE_MAX_CONST_I_SWVP 2048 +#define NINE_MAX_CONST_B_SWVP 2048 +#define NINE_MAX_CONST_ALL 276 /* B consts count only 1/4 th */ + +#define NINE_CONST_I_BASE(nconstf) \ + ((nconstf) * 4 * sizeof(float)) +#define NINE_CONST_B_BASE(nconstf) \ + ((nconstf) * 4 * sizeof(float) + \ + NINE_MAX_CONST_I * 4 * sizeof(int)) + +#define VS_CONST_F_SIZE(device) (device->may_swvp ? (NINE_MAX_CONST_F_SWVP * sizeof(float[4])) : (NINE_MAX_CONST_F * sizeof(float[4]))) +#define VS_CONST_I_SIZE(device) (device->may_swvp ? (NINE_MAX_CONST_I_SWVP * sizeof(int[4])) : (NINE_MAX_CONST_I * sizeof(int[4]))) +#define VS_CONST_B_SIZE(device) (device->may_swvp ? (NINE_MAX_CONST_B_SWVP * sizeof(BOOL)) : (NINE_MAX_CONST_B * sizeof(BOOL))) + + +#define NINE_MAX_TEXTURE_STAGES 8 + +#define NINE_MAX_LIGHTS 65536 +#define NINE_MAX_LIGHTS_ACTIVE 8 + +#define NINED3DLIGHT_INVALID (D3DLIGHT_DIRECTIONAL + 1) + +#define NINE_MAX_SAMPLERS_PS 16 +#define NINE_MAX_SAMPLERS_VS 4 +#define NINE_MAX_SAMPLERS 21 /* PS + DMAP + VS */ +#define NINE_SAMPLER_PS(s) ( 0 + (s)) +#define NINE_SAMPLER_DMAP 16 +#define NINE_SAMPLER_VS(s) (17 + (s)) +#define NINE_PS_SAMPLERS_MASK 0x00ffff +#define NINE_VS_SAMPLERS_MASK 0x1e0000 + +struct nine_ff_state { + struct { + uint32_t tex_stage[NINE_MAX_TEXTURE_STAGES][(NINED3DTSS_COUNT + 31) / 32]; /* stateblocks only */ + uint32_t transform[(NINED3DTS_COUNT + 31) / 32]; + } changed; + + D3DMATRIX *transform; /* access only via nine_state_access_transform */ + unsigned num_transforms; + + /* XXX: Do state blocks just change the set of active lights or do we + * have to store which lights have been disabled, too ? + */ + D3DLIGHT9 *light; + uint16_t active_light[NINE_MAX_LIGHTS_ACTIVE]; /* 8 */ + unsigned num_lights; + unsigned num_lights_active; + + D3DMATERIAL9 material; + + DWORD tex_stage[NINE_MAX_TEXTURE_STAGES][NINED3DTSS_COUNT]; +}; + +struct nine_state +{ + struct { + uint32_t group; + uint32_t rs[(NINED3DRS_COUNT + 31) / 32]; + uint32_t vtxbuf; + uint32_t stream_freq; + uint32_t texture; + uint16_t sampler[NINE_MAX_SAMPLERS]; + struct nine_range *vs_const_f; + struct nine_range *ps_const_f; + struct nine_range *vs_const_i; + uint16_t ps_const_i; /* NINE_MAX_CONST_I == 16 */ + struct nine_range *vs_const_b; + uint16_t ps_const_b; /* NINE_MAX_CONST_B == 16 */ + uint8_t ucp; + } changed; /* stateblocks only */ + + struct NineSurface9 *rt[NINE_MAX_SIMULTANEOUS_RENDERTARGETS]; + struct NineSurface9 *ds; + + D3DVIEWPORT9 viewport; + + struct pipe_scissor_state scissor; + + /* NOTE: vs, ps will be NULL for FF and are set in device->ff.vs,ps instead + * (XXX: or is it better to reference FF shaders here, too ?) + * NOTE: const_f contains extra space for const_i,b to use as user constbuf + */ + struct NineVertexShader9 *vs; + float *vs_const_f; + int *vs_const_i; + BOOL *vs_const_b; + float *vs_lconstf_temp; /* ProcessVertices */ + + struct NinePixelShader9 *ps; + float *ps_const_f; + int ps_const_i[NINE_MAX_CONST_I][4]; + BOOL ps_const_b[NINE_MAX_CONST_B]; + + struct NineVertexDeclaration9 *vdecl; + + struct NineIndexBuffer9 *idxbuf; + struct NineVertexBuffer9 *stream[PIPE_MAX_ATTRIBS]; + struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS]; /* vtxbuf.buffer unused */ + UINT stream_freq[PIPE_MAX_ATTRIBS]; + + struct pipe_clip_state clip; + + DWORD rs_advertised[NINED3DRS_COUNT]; /* the ones apps get with GetRenderState */ + + struct NineBaseTexture9 *texture[NINE_MAX_SAMPLERS]; /* PS, DMAP, VS */ + + DWORD samp_advertised[NINE_MAX_SAMPLERS][D3DSAMP_COUNT]; + + struct nine_ff_state ff; +}; + +struct nine_context { + struct { + uint32_t group; + uint16_t sampler[NINE_MAX_SAMPLERS]; + uint32_t vtxbuf; + BOOL vs_const_f; + BOOL vs_const_i; + BOOL vs_const_b; + BOOL ps_const_f; + BOOL ps_const_i; + BOOL ps_const_b; + BOOL ucp; + } changed; + + uint32_t bumpmap_vars[6 * NINE_MAX_TEXTURE_STAGES]; + + struct NineSurface9 *rt[NINE_MAX_SIMULTANEOUS_RENDERTARGETS]; + struct NineSurface9 *ds; + + struct { + void *vs; + unsigned *vs_const_ranges; + unsigned vs_const_used_size; + void *ps; + unsigned *ps_const_ranges; + unsigned ps_const_used_size; + } cso_shader; + + struct pipe_context *pipe; + struct cso_context *cso; + + uint8_t rt_mask; + + D3DVIEWPORT9 viewport; + + struct pipe_scissor_state scissor; + + struct NineVertexShader9 *vs; + BOOL programmable_vs; + float *vs_const_f; + float *vs_const_f_swvp; + int *vs_const_i; + BOOL *vs_const_b; + float *vs_lconstf_temp; + + struct NinePixelShader9 *ps; + float *ps_const_f; + int ps_const_i[NINE_MAX_CONST_I][4]; + BOOL ps_const_b[NINE_MAX_CONST_B]; + float *ps_lconstf_temp; + + struct NineVertexDeclaration9 *vdecl; + + struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS]; + UINT stream_freq[PIPE_MAX_ATTRIBS]; + uint32_t stream_instancedata_mask; /* derived from stream_freq */ + uint32_t stream_usage_mask; /* derived from VS and vdecl */ + + struct pipe_resource *idxbuf; + unsigned index_offset; + unsigned index_size; + + struct pipe_clip_state clip; + + DWORD rs[NINED3DRS_COUNT]; + + struct { + BOOL enabled; + BOOL shadow; + DWORD lod; + D3DRESOURCETYPE type; + struct pipe_resource *resource; + struct pipe_sampler_view *view[2]; + uint8_t pstype; + } texture[NINE_MAX_SAMPLERS]; + + DWORD samp[NINE_MAX_SAMPLERS][NINED3DSAMP_COUNT]; + + uint32_t samplers_shadow; + + uint8_t bound_samplers_mask_vs; + uint16_t bound_samplers_mask_ps; + + int dummy_vbo_bound_at; /* -1 = not bound , >= 0 = bound index */ + boolean vbo_bound_done; + + boolean inline_constants; + + struct nine_ff_state ff; + + /* software vertex processing */ + boolean swvp; + + uint32_t commit; + struct { + struct pipe_framebuffer_state fb; + struct pipe_depth_stencil_alpha_state dsa; + struct pipe_rasterizer_state rast; + struct pipe_blend_state blend; + struct pipe_constant_buffer cb_vs; + struct pipe_constant_buffer cb0_swvp; + struct pipe_constant_buffer cb1_swvp; + struct pipe_constant_buffer cb2_swvp; + struct pipe_constant_buffer cb3_swvp; + struct pipe_constant_buffer cb_ps; + struct pipe_constant_buffer cb_vs_ff; + struct pipe_constant_buffer cb_ps_ff; + } pipe_data; +}; + +struct nine_state_sw_internal { + struct pipe_transfer *transfers_so[4]; +}; + +struct nine_clipplane { + float plane[4]; +}; +/* map D3DRS -> NINE_STATE_x + */ +extern const uint32_t nine_render_state_group[NINED3DRS_COUNT]; + +/* for D3DSBT_PIXEL/VERTEX: + */ +extern const uint32_t nine_render_states_pixel[(NINED3DRS_COUNT + 31) / 32]; +extern const uint32_t nine_render_states_vertex[(NINED3DRS_COUNT + 31) / 32]; + +struct NineDevice9; + +/* Internal multithreading: When enabled, the nine_context functions + * will append work to a worker thread when possible. Only the worker + * thread can access struct nine_context. */ + +void +nine_context_set_render_state(struct NineDevice9 *device, + D3DRENDERSTATETYPE State, + DWORD Value); + +void +nine_context_set_texture(struct NineDevice9 *device, + DWORD Stage, + struct NineBaseTexture9 *tex); + +void +nine_context_set_sampler_state(struct NineDevice9 *device, + DWORD Sampler, + D3DSAMPLERSTATETYPE Type, + DWORD Value); + +void +nine_context_set_stream_source(struct NineDevice9 *device, + UINT StreamNumber, + struct NineVertexBuffer9 *pVBuf9, + UINT OffsetInBytes, + UINT Stride); + +void +nine_context_set_stream_source_freq(struct NineDevice9 *device, + UINT StreamNumber, + UINT Setting); + +void +nine_context_set_indices(struct NineDevice9 *device, + struct NineIndexBuffer9 *idxbuf); + +void +nine_context_set_vertex_declaration(struct NineDevice9 *device, + struct NineVertexDeclaration9 *vdecl); + +void +nine_context_set_vertex_shader(struct NineDevice9 *device, + struct NineVertexShader9 *pShader); + +void +nine_context_set_vertex_shader_constant_f(struct NineDevice9 *device, + UINT StartRegister, + const float *pConstantData, + const unsigned pConstantData_size, + UINT Vector4fCount); + +void +nine_context_set_vertex_shader_constant_i(struct NineDevice9 *device, + UINT StartRegister, + const int *pConstantData, + const unsigned pConstantData_size, + UINT Vector4iCount); + +void +nine_context_set_vertex_shader_constant_b(struct NineDevice9 *device, + UINT StartRegister, + const BOOL *pConstantData, + const unsigned pConstantData_size, + UINT BoolCount); + +void +nine_context_set_pixel_shader(struct NineDevice9 *device, + struct NinePixelShader9* ps); + +void +nine_context_set_pixel_shader_constant_f(struct NineDevice9 *device, + UINT StartRegister, + const float *pConstantData, + const unsigned pConstantData_size, + UINT Vector4fCount); + +void +nine_context_set_pixel_shader_constant_i(struct NineDevice9 *device, + UINT StartRegister, + const int *pConstantData, + const unsigned pConstantData_size, + UINT Vector4iCount); + +void +nine_context_set_pixel_shader_constant_b(struct NineDevice9 *device, + UINT StartRegister, + const BOOL *pConstantData, + const unsigned pConstantData_size, + UINT BoolCount); + +void +nine_context_set_viewport(struct NineDevice9 *device, + const D3DVIEWPORT9 *viewport); + +void +nine_context_set_scissor(struct NineDevice9 *device, + const struct pipe_scissor_state *scissor); + +void +nine_context_set_transform(struct NineDevice9 *device, + D3DTRANSFORMSTATETYPE State, + const D3DMATRIX *pMatrix); + +void +nine_context_set_material(struct NineDevice9 *device, + const D3DMATERIAL9 *pMaterial); + +void +nine_context_set_light(struct NineDevice9 *device, + DWORD Index, + const D3DLIGHT9 *pLight); + +void +nine_context_light_enable(struct NineDevice9 *device, + DWORD Index, + BOOL Enable); + +void +nine_context_set_texture_stage_state(struct NineDevice9 *device, + DWORD Stage, + D3DTEXTURESTAGESTATETYPE Type, + DWORD Value); + +void +nine_context_set_render_target(struct NineDevice9 *device, + DWORD RenderTargetIndex, + struct NineSurface9 *rt); + +void +nine_context_set_depth_stencil(struct NineDevice9 *device, + struct NineSurface9 *ds); + +void +nine_context_set_clip_plane(struct NineDevice9 *device, + DWORD Index, + const struct nine_clipplane *pPlane); + +void +nine_context_set_swvp(struct NineDevice9 *device, + boolean swvp); + +void +nine_context_apply_stateblock(struct NineDevice9 *device, + const struct nine_state *src); + +void +nine_context_clear_fb(struct NineDevice9 *device, DWORD Count, + const D3DRECT *pRects, DWORD Flags, + D3DCOLOR Color, float Z, DWORD Stencil); + +void +nine_context_draw_primitive(struct NineDevice9 *device, + D3DPRIMITIVETYPE PrimitiveType, + UINT StartVertex, + UINT PrimitiveCount); + +void +nine_context_draw_indexed_primitive(struct NineDevice9 *device, + D3DPRIMITIVETYPE PrimitiveType, + INT BaseVertexIndex, + UINT MinVertexIndex, + UINT NumVertices, + UINT StartIndex, + UINT PrimitiveCount); + +void +nine_context_draw_primitive_from_vtxbuf(struct NineDevice9 *device, + D3DPRIMITIVETYPE PrimitiveType, + UINT PrimitiveCount, + struct pipe_vertex_buffer *vtxbuf); + +void +nine_context_draw_indexed_primitive_from_vtxbuf_idxbuf(struct NineDevice9 *device, + D3DPRIMITIVETYPE PrimitiveType, + UINT MinVertexIndex, + UINT NumVertices, + UINT PrimitiveCount, + struct pipe_vertex_buffer *vbuf, + struct pipe_resource *ibuf, + void *user_ibuf, + unsigned index_offset, + unsigned index_size); + +void +nine_context_resource_copy_region(struct NineDevice9 *device, + struct NineUnknown *dst, + struct NineUnknown *src, + struct pipe_resource* dst_res, + unsigned dst_level, + const struct pipe_box *dst_box, + struct pipe_resource* src_res, + unsigned src_level, + const struct pipe_box *src_box); + +void +nine_context_blit(struct NineDevice9 *device, + struct NineUnknown *dst, + struct NineUnknown *src, + struct pipe_blit_info *blit); + +void +nine_context_clear_render_target(struct NineDevice9 *device, + struct NineSurface9 *surface, + D3DCOLOR color, + UINT x, + UINT y, + UINT width, + UINT height); + +void +nine_context_gen_mipmap(struct NineDevice9 *device, + struct NineUnknown *dst, + struct pipe_resource *res, + UINT base_level, UINT last_level, + UINT first_layer, UINT last_layer, + UINT filter); + +void +nine_context_range_upload(struct NineDevice9 *device, + unsigned *counter, + struct NineUnknown *src_ref, + struct pipe_resource *res, + unsigned offset, + unsigned size, + const void *data); + +void +nine_context_box_upload(struct NineDevice9 *device, + unsigned *counter, + struct NineUnknown *src_ref, + struct pipe_resource *res, + unsigned level, + const struct pipe_box *dst_box, + enum pipe_format src_format, + const void *src, unsigned src_stride, + unsigned src_layer_stride, + const struct pipe_box *src_box); + +struct pipe_query * +nine_context_create_query(struct NineDevice9 *device, unsigned query_type); + +void +nine_context_destroy_query(struct NineDevice9 *device, struct pipe_query *query); + +void +nine_context_begin_query(struct NineDevice9 *device, unsigned *counter, struct pipe_query *query); + +void +nine_context_end_query(struct NineDevice9 *device, unsigned *counter, struct pipe_query *query); + +boolean +nine_context_get_query_result(struct NineDevice9 *device, struct pipe_query *query, + unsigned *counter, boolean flush, boolean wait, + union pipe_query_result *result); + +void nine_state_restore_non_cso(struct NineDevice9 *device); +void nine_state_set_defaults(struct NineDevice9 *, const D3DCAPS9 *, + boolean is_reset); +void nine_device_state_clear(struct NineDevice9 *); +void nine_context_clear(struct NineDevice9 *); + +void nine_state_init_sw(struct NineDevice9 *device); +void nine_state_prepare_draw_sw(struct NineDevice9 *device, + struct NineVertexDeclaration9 *vdecl_out, + int start_vertice, + int num_vertices, + struct pipe_stream_output_info *so); +void nine_state_after_draw_sw(struct NineDevice9 *device); +void nine_state_destroy_sw(struct NineDevice9 *device); + +void +nine_state_resize_transform(struct nine_ff_state *ff_state, unsigned N); + +/* If @alloc is FALSE, the return value may be a const identity matrix. + * Therefore, do not modify if you set alloc to FALSE ! + */ +D3DMATRIX * +nine_state_access_transform(struct nine_ff_state *, D3DTRANSFORMSTATETYPE, + boolean alloc); + +HRESULT +nine_state_set_light(struct nine_ff_state *, DWORD, const D3DLIGHT9 *); + +HRESULT +nine_state_light_enable(struct nine_ff_state *, + DWORD, BOOL); + +const char *nine_d3drs_to_string(DWORD State); + +/* CSMT functions */ +struct csmt_context; + +struct csmt_context * +nine_csmt_create( struct NineDevice9 *This ); + +void +nine_csmt_destroy( struct NineDevice9 *This, struct csmt_context *ctx ); + +void +nine_csmt_process( struct NineDevice9 *This ); + + +/* Get the pipe_context (should not be called from the worker thread). + * All the work in the worker thread is finished before returning. */ +struct pipe_context * +nine_context_get_pipe( struct NineDevice9 *device ); + +/* Can be called from all threads */ +struct pipe_context * +nine_context_get_pipe_multithread( struct NineDevice9 *device ); + + +/* Get the pipe_context (should not be called from the worker thread). + * All the work in the worker thread is paused before returning. + * It is neccessary to release in order to restart the thread. + * This is intended for use of the nine_context pipe_context that don't + * need the worker thread to finish all queued job. */ +struct pipe_context * +nine_context_get_pipe_acquire( struct NineDevice9 *device ); + +void +nine_context_get_pipe_release( struct NineDevice9 *device ); + +#endif /* _NINE_STATE_H_ */ diff --git a/src/gallium/frontends/nine/nineexoverlayextension.c b/src/gallium/frontends/nine/nineexoverlayextension.c new file mode 100644 index 00000000000..6a4f287e9a3 --- /dev/null +++ b/src/gallium/frontends/nine/nineexoverlayextension.c @@ -0,0 +1,46 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "nineexoverlayextension.h" + +#define DBG_CHANNEL DBG_OVERLAYEXTENSION + +HRESULT NINE_WINAPI +Nine9ExOverlayExtension_CheckDeviceOverlayType( struct Nine9ExOverlayExtension *This, + UINT Adapter, + D3DDEVTYPE DevType, + UINT OverlayWidth, + UINT OverlayHeight, + D3DFORMAT OverlayFormat, + D3DDISPLAYMODEEX *pDisplayMode, + D3DDISPLAYROTATION DisplayRotation, + D3DOVERLAYCAPS *pOverlayCaps ) +{ + STUB(D3DERR_INVALIDCALL); +} + +IDirect3D9ExOverlayExtensionVtbl Nine9ExOverlayExtension_vtable = { + (void *)NineUnknown_QueryInterface, + (void *)NineUnknown_AddRef, + (void *)NineUnknown_Release, + (void *)Nine9ExOverlayExtension_CheckDeviceOverlayType +}; diff --git a/src/gallium/frontends/nine/nineexoverlayextension.h b/src/gallium/frontends/nine/nineexoverlayextension.h new file mode 100644 index 00000000000..f528f1d3ca9 --- /dev/null +++ b/src/gallium/frontends/nine/nineexoverlayextension.h @@ -0,0 +1,49 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _NINE_NINEEXOVERLAYEXTENSION_H_ +#define _NINE_NINEEXOVERLAYEXTENSION_H_ + +#include "iunknown.h" + +struct Nine9ExOverlayExtension +{ + struct NineUnknown base; +}; +static inline struct Nine9ExOverlayExtension * +Nine9ExOverlayExtension( void *data ) +{ + return (struct Nine9ExOverlayExtension *)data; +} + +HRESULT NINE_WINAPI +Nine9ExOverlayExtension_CheckDeviceOverlayType( struct Nine9ExOverlayExtension *This, + UINT Adapter, + D3DDEVTYPE DevType, + UINT OverlayWidth, + UINT OverlayHeight, + D3DFORMAT OverlayFormat, + D3DDISPLAYMODEEX *pDisplayMode, + D3DDISPLAYROTATION DisplayRotation, + D3DOVERLAYCAPS *pOverlayCaps ); + +#endif /* _NINE_NINEEXOVERLAYEXTENSION_H_ */ diff --git a/src/gallium/frontends/nine/pixelshader9.c b/src/gallium/frontends/nine/pixelshader9.c new file mode 100644 index 00000000000..4b85c738f79 --- /dev/null +++ b/src/gallium/frontends/nine/pixelshader9.c @@ -0,0 +1,256 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "nine_helpers.h" +#include "nine_shader.h" + +#include "pixelshader9.h" + +#include "device9.h" +#include "pipe/p_context.h" + +#define DBG_CHANNEL DBG_PIXELSHADER + +HRESULT +NinePixelShader9_ctor( struct NinePixelShader9 *This, + struct NineUnknownParams *pParams, + const DWORD *pFunction, void *cso ) +{ + struct NineDevice9 *device; + struct nine_shader_info info; + struct pipe_context *pipe; + HRESULT hr; + + DBG("This=%p pParams=%p pFunction=%p cso=%p\n", This, pParams, pFunction, cso); + + hr = NineUnknown_ctor(&This->base, pParams); + if (FAILED(hr)) + return hr; + + if (cso) { + This->ff_cso = cso; + return D3D_OK; + } + device = This->base.device; + + info.type = PIPE_SHADER_FRAGMENT; + info.byte_code = pFunction; + info.const_i_base = NINE_CONST_I_BASE(device->max_ps_const_f) / 16; + info.const_b_base = NINE_CONST_B_BASE(device->max_ps_const_f) / 16; + info.sampler_mask_shadow = 0x0; + info.sampler_ps1xtypes = 0x0; + info.fog_enable = 0; + info.projected = 0; + info.add_constants_defs.c_combination = NULL; + info.add_constants_defs.int_const_added = NULL; + info.add_constants_defs.bool_const_added = NULL; + info.process_vertices = false; + info.swvp_on = false; + + pipe = nine_context_get_pipe_acquire(device); + hr = nine_translate_shader(device, &info, pipe); + nine_context_get_pipe_release(device); + if (FAILED(hr)) + return hr; + This->byte_code.version = info.version; + + This->byte_code.tokens = mem_dup(pFunction, info.byte_size); + if (!This->byte_code.tokens) + return E_OUTOFMEMORY; + This->byte_code.size = info.byte_size; + + This->variant.cso = info.cso; + This->variant.const_ranges = info.const_ranges; + This->variant.const_used_size = info.const_used_size; + This->last_cso = info.cso; + This->last_const_ranges = info.const_ranges; + This->last_const_used_size = info.const_used_size; + This->last_key = 0; + + This->sampler_mask = info.sampler_mask; + This->rt_mask = info.rt_mask; + This->bumpenvmat_needed = info.bumpenvmat_needed; + + memcpy(This->int_slots_used, info.int_slots_used, sizeof(This->int_slots_used)); + memcpy(This->bool_slots_used, info.bool_slots_used, sizeof(This->bool_slots_used)); + + This->const_int_slots = info.const_int_slots; + This->const_bool_slots = info.const_bool_slots; + + This->c_combinations = NULL; + + /* no constant relative addressing for ps */ + assert(info.lconstf.data == NULL); + assert(info.lconstf.ranges == NULL); + + return D3D_OK; +} + +void +NinePixelShader9_dtor( struct NinePixelShader9 *This ) +{ + DBG("This=%p\n", This); + + if (This->base.device) { + struct pipe_context *pipe = nine_context_get_pipe_multithread(This->base.device); + struct nine_shader_variant *var = &This->variant; + + do { + if (var->cso) { + if (This->base.device->context.cso_shader.ps == var->cso) + pipe->bind_fs_state(pipe, NULL); + pipe->delete_fs_state(pipe, var->cso); + FREE(var->const_ranges); + } + var = var->next; + } while (var); + + if (This->ff_cso) { + if (This->ff_cso == This->base.device->context.cso_shader.ps) + pipe->bind_fs_state(pipe, NULL); + pipe->delete_fs_state(pipe, This->ff_cso); + } + } + nine_shader_variants_free(&This->variant); + + nine_shader_constant_combination_free(This->c_combinations); + + FREE((void *)This->byte_code.tokens); /* const_cast */ + + NineUnknown_dtor(&This->base); +} + +HRESULT NINE_WINAPI +NinePixelShader9_GetFunction( struct NinePixelShader9 *This, + void *pData, + UINT *pSizeOfData ) +{ + DBG("This=%p pData=%p pSizeOfData=%p\n", This, pData, pSizeOfData); + + user_assert(pSizeOfData, D3DERR_INVALIDCALL); + + if (!pData) { + *pSizeOfData = This->byte_code.size; + return D3D_OK; + } + user_assert(*pSizeOfData >= This->byte_code.size, D3DERR_INVALIDCALL); + + memcpy(pData, This->byte_code.tokens, This->byte_code.size); + + return D3D_OK; +} + +void * +NinePixelShader9_GetVariant( struct NinePixelShader9 *This, + unsigned **const_ranges, + unsigned *const_used_size ) +{ + /* GetVariant is called from nine_context, thus we can + * get pipe directly */ + struct pipe_context *pipe = This->base.device->context.pipe; + void *cso; + uint64_t key; + + key = This->next_key; + if (key == This->last_key) { + *const_ranges = This->last_const_ranges; + *const_used_size = This->last_const_used_size; + return This->last_cso; + } + + cso = nine_shader_variant_get(&This->variant, const_ranges, const_used_size, key); + if (!cso) { + struct NineDevice9 *device = This->base.device; + struct nine_shader_info info; + HRESULT hr; + + info.type = PIPE_SHADER_FRAGMENT; + info.const_i_base = NINE_CONST_I_BASE(device->max_ps_const_f) / 16; + info.const_b_base = NINE_CONST_B_BASE(device->max_ps_const_f) / 16; + info.byte_code = This->byte_code.tokens; + info.sampler_mask_shadow = key & 0xffff; + /* intended overlap with sampler_mask_shadow */ + if (unlikely(This->byte_code.version < 0x20)) { + if (This->byte_code.version < 0x14) { + info.sampler_ps1xtypes = (key >> 4) & 0xff; + info.projected = (key >> 12) & 0xff; + } else { + info.sampler_ps1xtypes = (key >> 6) & 0xfff; + info.projected = 0; + } + } else { + info.sampler_ps1xtypes = 0; + info.projected = 0; + } + info.fog_enable = device->context.rs[D3DRS_FOGENABLE]; + info.fog_mode = device->context.rs[D3DRS_FOGTABLEMODE]; + info.force_color_in_centroid = (key >> 22) & 1; + info.add_constants_defs.c_combination = + nine_shader_constant_combination_get(This->c_combinations, (key >> 24) & 0xff); + info.add_constants_defs.int_const_added = &This->int_slots_used; + info.add_constants_defs.bool_const_added = &This->bool_slots_used; + info.process_vertices = false; + info.swvp_on = false; + + hr = nine_translate_shader(This->base.device, &info, pipe); + if (FAILED(hr)) + return NULL; + nine_shader_variant_add(&This->variant, key, info.cso, + info.const_ranges, info.const_used_size); + cso = info.cso; + *const_ranges = info.const_ranges; + *const_used_size = info.const_used_size; + } + + This->last_key = key; + This->last_cso = cso; + This->last_const_ranges = *const_ranges; + This->last_const_used_size = *const_used_size; + + return cso; +} + +IDirect3DPixelShader9Vtbl NinePixelShader9_vtable = { + (void *)NineUnknown_QueryInterface, + (void *)NineUnknown_AddRef, + (void *)NineUnknown_Release, + (void *)NineUnknown_GetDevice, + (void *)NinePixelShader9_GetFunction +}; + +static const GUID *NinePixelShader9_IIDs[] = { + &IID_IDirect3DPixelShader9, + &IID_IUnknown, + NULL +}; + +HRESULT +NinePixelShader9_new( struct NineDevice9 *pDevice, + struct NinePixelShader9 **ppOut, + const DWORD *pFunction, void *cso ) +{ + if (cso) { /* ff shader. Needs to start with bind count */ + NINE_DEVICE_CHILD_BIND_NEW(PixelShader9, ppOut, pDevice, pFunction, cso); + } else { + NINE_DEVICE_CHILD_NEW(PixelShader9, ppOut, pDevice, pFunction, cso); + } +} diff --git a/src/gallium/frontends/nine/pixelshader9.h b/src/gallium/frontends/nine/pixelshader9.h new file mode 100644 index 00000000000..6bac90be7a9 --- /dev/null +++ b/src/gallium/frontends/nine/pixelshader9.h @@ -0,0 +1,158 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _NINE_PIXELSHADER9_H_ +#define _NINE_PIXELSHADER9_H_ + +#include "iunknown.h" +#include "nine_shader.h" +#include "nine_state.h" +#include "basetexture9.h" +#include "nine_ff.h" +#include "surface9.h" + +struct nine_lconstf; + +struct NinePixelShader9 +{ + struct NineUnknown base; + struct nine_shader_variant variant; + + struct { + const DWORD *tokens; + DWORD size; + uint8_t version; /* (major << 4) | minor */ + } byte_code; + + uint8_t bumpenvmat_needed; + uint16_t sampler_mask; + uint8_t rt_mask; + + boolean int_slots_used[NINE_MAX_CONST_I]; + boolean bool_slots_used[NINE_MAX_CONST_B]; + + unsigned const_int_slots; + unsigned const_bool_slots; + + struct nine_shader_constant_combination *c_combinations; + + uint64_t ff_key[6]; + void *ff_cso; + + uint64_t last_key; + void *last_cso; + unsigned *last_const_ranges; + unsigned last_const_used_size; /* in bytes */ + + uint64_t next_key; +}; +static inline struct NinePixelShader9 * +NinePixelShader9( void *data ) +{ + return (struct NinePixelShader9 *)data; +} + +static inline BOOL +NinePixelShader9_UpdateKey( struct NinePixelShader9 *ps, + struct nine_context *context ) +{ + uint16_t samplers_shadow; + uint16_t samplers_ps1_types; + uint8_t projected; + uint64_t key; + BOOL res; + + samplers_shadow = (uint16_t)((context->samplers_shadow & NINE_PS_SAMPLERS_MASK) >> NINE_SAMPLER_PS(0)); + key = samplers_shadow & ps->sampler_mask; + + if (unlikely(ps->byte_code.version < 0x20)) { + /* variable targets */ + uint32_t m = ps->sampler_mask; + samplers_ps1_types = 0; + while (m) { + int s = ffs(m) - 1; + m &= ~(1 << s); + samplers_ps1_types |= (context->texture[s].enabled ? context->texture[s].pstype : 1) << (s * 2); + } + /* Note: For ps 1.X, only samplers 0 1 2 and 3 are available (except 1.4 where 4 and 5 are available). + * ps < 1.4: samplers_shadow 4b, samplers_ps1_types 8b, projected 8b + * ps 1.4: samplers_shadow 6b, samplers_ps1_types 12b + * Tot ps X.X samplers_shadow + extra: 20b */ + assert((ps->byte_code.version < 0x14 && !(ps->sampler_mask & 0xFFF0)) || !(ps->sampler_mask & 0xFFC0)); + + if (unlikely(ps->byte_code.version < 0x14)) { + key |= samplers_ps1_types << 4; + projected = nine_ff_get_projected_key_programmable(context); + key |= ((uint64_t) projected) << 12; + } else { + key |= samplers_ps1_types << 6; + } + } + + if (ps->byte_code.version < 0x30) { + key |= ((uint64_t)context->rs[D3DRS_FOGENABLE]) << 20; + key |= ((uint64_t)context->rs[D3DRS_FOGTABLEMODE]) << 21; + } + + /* centroid interpolation automatically used for color ps inputs */ + if (context->rt[0]->base.info.nr_samples) + key |= ((uint64_t)1) << 22; + + if ((ps->const_int_slots > 0 || ps->const_bool_slots > 0) && context->inline_constants) + key |= ((uint64_t)nine_shader_constant_combination_key(&ps->c_combinations, + ps->int_slots_used, + ps->bool_slots_used, + (void *)context->ps_const_i, + context->ps_const_b)) << 24; + + res = ps->last_key != key; + if (res) + ps->next_key = key; + return res; +} + +void * +NinePixelShader9_GetVariant( struct NinePixelShader9 *ps, + unsigned **const_ranges, + unsigned *const_used_size ); + +/*** public ***/ + +HRESULT +NinePixelShader9_new( struct NineDevice9 *pDevice, + struct NinePixelShader9 **ppOut, + const DWORD *pFunction, void *cso ); + +HRESULT +NinePixelShader9_ctor( struct NinePixelShader9 *, + struct NineUnknownParams *pParams, + const DWORD *pFunction, void *cso ); + +void +NinePixelShader9_dtor( struct NinePixelShader9 * ); + +HRESULT NINE_WINAPI +NinePixelShader9_GetFunction( struct NinePixelShader9 *This, + void *pData, + UINT *pSizeOfData ); + +#endif /* _NINE_PIXELSHADER9_H_ */ diff --git a/src/gallium/frontends/nine/query9.c b/src/gallium/frontends/nine/query9.c new file mode 100644 index 00000000000..d98db9eba7e --- /dev/null +++ b/src/gallium/frontends/nine/query9.c @@ -0,0 +1,314 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "device9.h" +#include "nine_state.h" +#include "query9.h" +#include "nine_helpers.h" +#include "pipe/p_screen.h" +#include "pipe/p_context.h" +#include "util/u_math.h" +#include "nine_dump.h" + +#define DBG_CHANNEL DBG_QUERY + +static inline unsigned +d3dquerytype_to_pipe_query(struct pipe_screen *screen, D3DQUERYTYPE type) +{ + switch (type) { + case D3DQUERYTYPE_EVENT: + return PIPE_QUERY_GPU_FINISHED; + case D3DQUERYTYPE_OCCLUSION: + return screen->get_param(screen, PIPE_CAP_OCCLUSION_QUERY) ? + PIPE_QUERY_OCCLUSION_COUNTER : PIPE_QUERY_TYPES; + case D3DQUERYTYPE_TIMESTAMP: + return screen->get_param(screen, PIPE_CAP_QUERY_TIMESTAMP) ? + PIPE_QUERY_TIMESTAMP : PIPE_QUERY_TYPES; + case D3DQUERYTYPE_TIMESTAMPDISJOINT: + case D3DQUERYTYPE_TIMESTAMPFREQ: + return screen->get_param(screen, PIPE_CAP_QUERY_TIMESTAMP) ? + PIPE_QUERY_TIMESTAMP_DISJOINT : PIPE_QUERY_TYPES; + case D3DQUERYTYPE_VERTEXSTATS: + return screen->get_param(screen, + PIPE_CAP_QUERY_PIPELINE_STATISTICS) ? + PIPE_QUERY_PIPELINE_STATISTICS : PIPE_QUERY_TYPES; + default: + return PIPE_QUERY_TYPES; /* Query not supported */ + } +} + +#define GET_DATA_SIZE_CASE2(a, b) case D3DQUERYTYPE_##a: return sizeof(D3DDEVINFO_##b) +#define GET_DATA_SIZE_CASET(a, b) case D3DQUERYTYPE_##a: return sizeof(b) +static inline DWORD +nine_query_result_size(D3DQUERYTYPE type) +{ + switch (type) { + GET_DATA_SIZE_CASE2(VERTEXSTATS, D3DVERTEXSTATS); + GET_DATA_SIZE_CASET(EVENT, BOOL); + GET_DATA_SIZE_CASET(OCCLUSION, DWORD); + GET_DATA_SIZE_CASET(TIMESTAMP, UINT64); + GET_DATA_SIZE_CASET(TIMESTAMPDISJOINT, BOOL); + GET_DATA_SIZE_CASET(TIMESTAMPFREQ, UINT64); + default: + assert(0); + return 0; + } +} + +HRESULT +nine_is_query_supported(struct pipe_screen *screen, D3DQUERYTYPE type) +{ + const unsigned ptype = d3dquerytype_to_pipe_query(screen, type); + + user_assert(ptype != ~0, D3DERR_INVALIDCALL); + + if (ptype == PIPE_QUERY_TYPES) { + DBG("Query type %u (%s) not supported.\n", + type, nine_D3DQUERYTYPE_to_str(type)); + return D3DERR_NOTAVAILABLE; + } + return D3D_OK; +} + +HRESULT +NineQuery9_ctor( struct NineQuery9 *This, + struct NineUnknownParams *pParams, + D3DQUERYTYPE Type ) +{ + struct NineDevice9 *device = pParams->device; + const unsigned ptype = d3dquerytype_to_pipe_query(device->screen, Type); + HRESULT hr; + + DBG("This=%p pParams=%p Type=%d\n", This, pParams, Type); + + hr = NineUnknown_ctor(&This->base, pParams); + if (FAILED(hr)) + return hr; + + This->state = NINE_QUERY_STATE_FRESH; + This->type = Type; + + user_assert(ptype != ~0, D3DERR_INVALIDCALL); + + if (ptype < PIPE_QUERY_TYPES) { + This->pq = nine_context_create_query(device, ptype); + if (!This->pq) + return E_OUTOFMEMORY; + } else { + assert(0); /* we have checked this case before */ + } + + This->instant = + Type == D3DQUERYTYPE_EVENT || + Type == D3DQUERYTYPE_RESOURCEMANAGER || + Type == D3DQUERYTYPE_TIMESTAMP || + Type == D3DQUERYTYPE_TIMESTAMPFREQ || + Type == D3DQUERYTYPE_VCACHE || + Type == D3DQUERYTYPE_VERTEXSTATS; + + This->result_size = nine_query_result_size(Type); + + return D3D_OK; +} + +void +NineQuery9_dtor( struct NineQuery9 *This ) +{ + struct NineDevice9 *device = This->base.device; + + DBG("This=%p\n", This); + + if (This->pq) { + if (This->state == NINE_QUERY_STATE_RUNNING) + nine_context_end_query(device, &This->counter, This->pq); + nine_context_destroy_query(device, This->pq); + } + + NineUnknown_dtor(&This->base); +} + +D3DQUERYTYPE NINE_WINAPI +NineQuery9_GetType( struct NineQuery9 *This ) +{ + return This->type; +} + +DWORD NINE_WINAPI +NineQuery9_GetDataSize( struct NineQuery9 *This ) +{ + return This->result_size; +} + +HRESULT NINE_WINAPI +NineQuery9_Issue( struct NineQuery9 *This, + DWORD dwIssueFlags ) +{ + struct NineDevice9 *device = This->base.device; + + DBG("This=%p dwIssueFlags=%d\n", This, dwIssueFlags); + + user_assert((dwIssueFlags == D3DISSUE_BEGIN) || + (dwIssueFlags == 0) || + (dwIssueFlags == D3DISSUE_END), D3DERR_INVALIDCALL); + + /* Wine tests: always return D3D_OK on D3DISSUE_BEGIN + * even when the call is supposed to be forbidden */ + if (dwIssueFlags == D3DISSUE_BEGIN && This->instant) + return D3D_OK; + + if (dwIssueFlags == D3DISSUE_BEGIN) { + if (This->state == NINE_QUERY_STATE_RUNNING) + nine_context_end_query(device, &This->counter, This->pq); + nine_context_begin_query(device, &This->counter, This->pq); + This->state = NINE_QUERY_STATE_RUNNING; + } else { + if (This->state != NINE_QUERY_STATE_RUNNING && + This->type != D3DQUERYTYPE_EVENT && + This->type != D3DQUERYTYPE_TIMESTAMP) + nine_context_begin_query(device, &This->counter, This->pq); + nine_context_end_query(device, &This->counter, This->pq); + This->state = NINE_QUERY_STATE_ENDED; + } + return D3D_OK; +} + +union nine_query_result +{ + D3DDEVINFO_D3DVERTEXSTATS vertexstats; + DWORD dw; + BOOL b; + UINT64 u64; +}; + +HRESULT NINE_WINAPI +NineQuery9_GetData( struct NineQuery9 *This, + void *pData, + DWORD dwSize, + DWORD dwGetDataFlags ) +{ + struct NineDevice9 *device = This->base.device; + boolean ok, wait_query_result = FALSE; + union pipe_query_result presult; + union nine_query_result nresult; + + DBG("This=%p pData=%p dwSize=%d dwGetDataFlags=%d\n", + This, pData, dwSize, dwGetDataFlags); + + /* according to spec we should return D3DERR_INVALIDCALL here, but + * wine returns S_FALSE because it is apparently the behaviour + * on windows */ + user_assert(This->state != NINE_QUERY_STATE_RUNNING, S_FALSE); + user_assert(dwSize == 0 || pData, D3DERR_INVALIDCALL); + user_assert(dwGetDataFlags == 0 || + dwGetDataFlags == D3DGETDATA_FLUSH, D3DERR_INVALIDCALL); + + if (This->state == NINE_QUERY_STATE_FRESH) { + /* App forgot calling Issue. call it for it. + * However Wine states that return value should + * be S_OK, so wait for the result to return S_OK. */ + NineQuery9_Issue(This, D3DISSUE_END); + wait_query_result = TRUE; + } + + /* The documention mentions no special case for D3DQUERYTYPE_TIMESTAMP. + * However Windows tests show that the query always succeeds when + * D3DGETDATA_FLUSH is specified. */ + if (This->type == D3DQUERYTYPE_TIMESTAMP && + (dwGetDataFlags & D3DGETDATA_FLUSH)) + wait_query_result = TRUE; + + + /* Note: We ignore dwGetDataFlags, because get_query_result will + * flush automatically if needed */ + + ok = nine_context_get_query_result(device, This->pq, &This->counter, + !!(dwGetDataFlags & D3DGETDATA_FLUSH), + wait_query_result, &presult); + + if (!ok) return S_FALSE; + + if (!dwSize) + return S_OK; + + switch (This->type) { + case D3DQUERYTYPE_EVENT: + nresult.b = presult.b; + break; + case D3DQUERYTYPE_OCCLUSION: + nresult.dw = presult.u64; + break; + case D3DQUERYTYPE_TIMESTAMP: + nresult.u64 = presult.u64; + break; + case D3DQUERYTYPE_TIMESTAMPDISJOINT: + nresult.b = presult.timestamp_disjoint.disjoint; + break; + case D3DQUERYTYPE_TIMESTAMPFREQ: + /* Applications use it to convert the TIMESTAMP value to time. + AMD drivers on win seem to return the actual hardware clock + resolution and corresponding values in TIMESTAMP. + However, this behaviour is not easy to replicate here. + So instead we do what wine and opengl do, and use + nanoseconds TIMESTAMPs. + (Which is also the unit used by PIPE_QUERY_TIMESTAMP.) + */ + nresult.u64 = 1000000000; + break; + case D3DQUERYTYPE_VERTEXSTATS: + nresult.vertexstats.NumRenderedTriangles = + presult.pipeline_statistics.c_invocations; + nresult.vertexstats.NumExtraClippingTriangles = + presult.pipeline_statistics.c_primitives; + break; + default: + assert(0); + break; + } + memcpy(pData, &nresult, MIN2(sizeof(nresult), dwSize)); + + return S_OK; +} + +IDirect3DQuery9Vtbl NineQuery9_vtable = { + (void *)NineUnknown_QueryInterface, + (void *)NineUnknown_AddRef, + (void *)NineUnknown_Release, + (void *)NineUnknown_GetDevice, /* actually part of Query9 iface */ + (void *)NineQuery9_GetType, + (void *)NineQuery9_GetDataSize, + (void *)NineQuery9_Issue, + (void *)NineQuery9_GetData +}; + +static const GUID *NineQuery9_IIDs[] = { + &IID_IDirect3DQuery9, + &IID_IUnknown, + NULL +}; + +HRESULT +NineQuery9_new( struct NineDevice9 *pDevice, + struct NineQuery9 **ppOut, + D3DQUERYTYPE Type ) +{ + NINE_DEVICE_CHILD_NEW(Query9, ppOut, pDevice, Type); +} diff --git a/src/gallium/frontends/nine/query9.h b/src/gallium/frontends/nine/query9.h new file mode 100644 index 00000000000..cc6c717390d --- /dev/null +++ b/src/gallium/frontends/nine/query9.h @@ -0,0 +1,83 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _NINE_QUERY9_H_ +#define _NINE_QUERY9_H_ + +#include "iunknown.h" + +enum nine_query_state +{ + NINE_QUERY_STATE_FRESH = 0, + NINE_QUERY_STATE_RUNNING, + NINE_QUERY_STATE_ENDED, +}; + +struct NineQuery9 +{ + struct NineUnknown base; + struct pipe_query *pq; + DWORD result_size; + D3DQUERYTYPE type; + enum nine_query_state state; + boolean instant; /* true if D3DISSUE_BEGIN is not needed / invalid */ + unsigned counter; /* Number of pending Begin/End (0 if internal multithreading off) */ +}; +static inline struct NineQuery9 * +NineQuery9( void *data ) +{ + return (struct NineQuery9 *)data; +} + +HRESULT +nine_is_query_supported(struct pipe_screen *screen, D3DQUERYTYPE); + +HRESULT +NineQuery9_new( struct NineDevice9 *Device, + struct NineQuery9 **ppOut, + D3DQUERYTYPE); + +HRESULT +NineQuery9_ctor( struct NineQuery9 *, + struct NineUnknownParams *pParams, + D3DQUERYTYPE Type ); + +void +NineQuery9_dtor( struct NineQuery9 * ); + +D3DQUERYTYPE NINE_WINAPI +NineQuery9_GetType( struct NineQuery9 *This ); + +DWORD NINE_WINAPI +NineQuery9_GetDataSize( struct NineQuery9 *This ); + +HRESULT NINE_WINAPI +NineQuery9_Issue( struct NineQuery9 *This, + DWORD dwIssueFlags ); + +HRESULT NINE_WINAPI +NineQuery9_GetData( struct NineQuery9 *This, + void *pData, + DWORD dwSize, + DWORD dwGetDataFlags ); + +#endif /* _NINE_QUERY9_H_ */ diff --git a/src/gallium/frontends/nine/resource9.c b/src/gallium/frontends/nine/resource9.c new file mode 100644 index 00000000000..852801624a9 --- /dev/null +++ b/src/gallium/frontends/nine/resource9.c @@ -0,0 +1,171 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "resource9.h" +#include "device9.h" +#include "nine_helpers.h" +#include "nine_defines.h" + +#include "util/u_inlines.h" +#include "util/u_resource.h" + +#include "pipe/p_screen.h" + +#define DBG_CHANNEL DBG_RESOURCE + +HRESULT +NineResource9_ctor( struct NineResource9 *This, + struct NineUnknownParams *pParams, + struct pipe_resource *initResource, + BOOL Allocate, + D3DRESOURCETYPE Type, + D3DPOOL Pool, + DWORD Usage) +{ + struct pipe_screen *screen; + HRESULT hr; + + DBG("This=%p pParams=%p initResource=%p Allocate=%d " + "Type=%d Pool=%d Usage=%d\n", + This, pParams, initResource, (int) Allocate, + Type, Pool, Usage); + + hr = NineUnknown_ctor(&This->base, pParams); + if (FAILED(hr)) + return hr; + + This->info.screen = screen = This->base.device->screen; + if (initResource) + pipe_resource_reference(&This->resource, initResource); + + if (Allocate) { + assert(!initResource); + + /* On Windows it is possible allocation fails when + * IDirect3DDevice9::GetAvailableTextureMem() still reports + * enough free space. + * + * Some games allocate surfaces + * in a loop until they receive D3DERR_OUTOFVIDEOMEMORY to measure + * the available texture memory size. + * + * We are not using the drivers VRAM statistics because: + * * This would add overhead to each resource allocation. + * * Freeing memory is lazy and takes some time, but applications + * expects the memory counter to change immediately after allocating + * or freeing memory. + * + * Vertexbuffers and indexbuffers are not accounted ! + */ + if (This->info.target != PIPE_BUFFER) { + This->size = util_resource_size(&This->info); + + p_atomic_add(&This->base.device->available_texture_mem, -This->size); + if (This->base.device->available_texture_mem <= + This->base.device->available_texture_limit) { + return D3DERR_OUTOFVIDEOMEMORY; + } + } + + DBG("(%p) Creating pipe_resource.\n", This); + This->resource = screen->resource_create(screen, &This->info); + if (!This->resource) + return D3DERR_OUTOFVIDEOMEMORY; + } + + This->type = Type; + This->pool = Pool; + This->usage = Usage; + This->priority = 0; + + return D3D_OK; +} + +void +NineResource9_dtor( struct NineResource9 *This ) +{ + DBG("This=%p\n", This); + + /* NOTE: We do have to use refcounting, the driver might + * still hold a reference. */ + pipe_resource_reference(&This->resource, NULL); + + /* NOTE: size is 0, unless something has actually been allocated */ + if (This->base.device) + p_atomic_add(&This->base.device->available_texture_mem, This->size); + + NineUnknown_dtor(&This->base); +} + +struct pipe_resource * +NineResource9_GetResource( struct NineResource9 *This ) +{ + return This->resource; +} + +D3DPOOL +NineResource9_GetPool( struct NineResource9 *This ) +{ + return This->pool; +} + +DWORD NINE_WINAPI +NineResource9_SetPriority( struct NineResource9 *This, + DWORD PriorityNew ) +{ + DWORD prev; + DBG("This=%p, PriorityNew=%d\n", This, PriorityNew); + + if (This->pool != D3DPOOL_MANAGED || This->type == D3DRTYPE_SURFACE) + return 0; + + prev = This->priority; + This->priority = PriorityNew; + return prev; +} + +DWORD NINE_WINAPI +NineResource9_GetPriority( struct NineResource9 *This ) +{ + if (This->pool != D3DPOOL_MANAGED || This->type == D3DRTYPE_SURFACE) + return 0; + + return This->priority; +} + +/* NOTE: Don't forget to adjust locked vtable if you change this ! */ +void NINE_WINAPI +NineResource9_PreLoad( struct NineResource9 *This ) +{ + if (This->pool != D3DPOOL_MANAGED) + return; + /* We don't treat managed vertex or index buffers different from + * default ones (are managed vertex buffers even allowed ?), and + * the PreLoad for textures is overridden by superclass. + */ +} + +D3DRESOURCETYPE NINE_WINAPI +NineResource9_GetType( struct NineResource9 *This ) +{ + return This->type; +} diff --git a/src/gallium/frontends/nine/resource9.h b/src/gallium/frontends/nine/resource9.h new file mode 100644 index 00000000000..9fed45476fb --- /dev/null +++ b/src/gallium/frontends/nine/resource9.h @@ -0,0 +1,89 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _NINE_RESOURCE9_H_ +#define _NINE_RESOURCE9_H_ + +#include "iunknown.h" +#include "pipe/p_state.h" + +struct pipe_screen; +struct hash_table; +struct NineDevice9; + +struct NineResource9 +{ + struct NineUnknown base; + + struct pipe_resource *resource; /* device resource */ + + D3DRESOURCETYPE type; + D3DPOOL pool; + DWORD priority; + DWORD usage; + + struct pipe_resource info; /* resource configuration */ + + long long size; +}; +static inline struct NineResource9 * +NineResource9( void *data ) +{ + return (struct NineResource9 *)data; +} + +HRESULT +NineResource9_ctor( struct NineResource9 *This, + struct NineUnknownParams *pParams, + struct pipe_resource *initResource, + BOOL Allocate, + D3DRESOURCETYPE Type, + D3DPOOL Pool, + DWORD Usage); + +void +NineResource9_dtor( struct NineResource9 *This ); + +/*** Nine private methods ***/ + +struct pipe_resource * +NineResource9_GetResource( struct NineResource9 *This ); + +D3DPOOL +NineResource9_GetPool( struct NineResource9 *This ); + +/*** Direct3D public methods ***/ + +DWORD NINE_WINAPI +NineResource9_SetPriority( struct NineResource9 *This, + DWORD PriorityNew ); + +DWORD NINE_WINAPI +NineResource9_GetPriority( struct NineResource9 *This ); + +void NINE_WINAPI +NineResource9_PreLoad( struct NineResource9 *This ); + +D3DRESOURCETYPE NINE_WINAPI +NineResource9_GetType( struct NineResource9 *This ); + +#endif /* _NINE_RESOURCE9_H_ */ diff --git a/src/gallium/frontends/nine/stateblock9.c b/src/gallium/frontends/nine/stateblock9.c new file mode 100644 index 00000000000..c7bdc86e9d0 --- /dev/null +++ b/src/gallium/frontends/nine/stateblock9.c @@ -0,0 +1,602 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "stateblock9.h" +#include "device9.h" +#include "basetexture9.h" +#include "nine_helpers.h" +#include "vertexdeclaration9.h" +#include "vertexbuffer9.h" +#include "indexbuffer9.h" + +#define DBG_CHANNEL DBG_STATEBLOCK + +/* XXX TODO: handling of lights is broken */ + +HRESULT +NineStateBlock9_ctor( struct NineStateBlock9 *This, + struct NineUnknownParams *pParams, + enum nine_stateblock_type type ) +{ + HRESULT hr = NineUnknown_ctor(&This->base, pParams); + + DBG("This=%p pParams=%p type=%d\n", This, pParams, type); + + if (FAILED(hr)) + return hr; + + This->type = type; + + This->state.vs_const_f = MALLOC(VS_CONST_F_SIZE(This->base.device)); + This->state.ps_const_f = MALLOC(This->base.device->ps_const_size); + This->state.vs_const_i = MALLOC(VS_CONST_I_SIZE(This->base.device)); + This->state.vs_const_b = MALLOC(VS_CONST_B_SIZE(This->base.device)); + if (!This->state.vs_const_f || !This->state.ps_const_f || + !This->state.vs_const_i || !This->state.vs_const_b) + return E_OUTOFMEMORY; + + return D3D_OK; +} + +void +NineStateBlock9_dtor( struct NineStateBlock9 *This ) +{ + struct nine_state *state = &This->state; + struct nine_range *r; + struct nine_range_pool *pool = &This->base.device->range_pool; + unsigned i; + + for (i = 0; i < ARRAY_SIZE(state->rt); ++i) + nine_bind(&state->rt[i], NULL); + nine_bind(&state->ds, NULL); + nine_bind(&state->vs, NULL); + nine_bind(&state->ps, NULL); + nine_bind(&state->vdecl, NULL); + for (i = 0; i < PIPE_MAX_ATTRIBS; ++i) + nine_bind(&state->stream[i], NULL); + + nine_bind(&state->idxbuf, NULL); + for (i = 0; i < NINE_MAX_SAMPLERS; ++i) + nine_bind(&state->texture[i], NULL); + + FREE(state->vs_const_f); + FREE(state->ps_const_f); + FREE(state->vs_const_i); + FREE(state->vs_const_b); + + FREE(state->ff.light); + + FREE(state->ff.transform); + + if (This->state.changed.ps_const_f) { + for (r = This->state.changed.ps_const_f; r->next; r = r->next); + nine_range_pool_put_chain(pool, This->state.changed.ps_const_f, r); + } + if (This->state.changed.vs_const_f) { + for (r = This->state.changed.vs_const_f; r->next; r = r->next); + nine_range_pool_put_chain(pool, This->state.changed.vs_const_f, r); + } + if (This->state.changed.vs_const_i) { + for (r = This->state.changed.vs_const_i; r->next; r = r->next); + nine_range_pool_put_chain(pool, This->state.changed.vs_const_i, r); + } + if (This->state.changed.vs_const_b) { + for (r = This->state.changed.vs_const_b; r->next; r = r->next); + nine_range_pool_put_chain(pool, This->state.changed.vs_const_b, r); + } + + NineUnknown_dtor(&This->base); +} + +static void +NineStateBlock9_BindBuffer( struct NineDevice9 *device, + boolean applyToDevice, + struct NineBuffer9 **slot, + struct NineBuffer9 *buf ) +{ + if (applyToDevice) + NineBindBufferToDevice(device, slot, buf); + else + nine_bind(slot, buf); +} + +static void +NineStateBlock9_BindTexture( struct NineDevice9 *device, + boolean applyToDevice, + struct NineBaseTexture9 **slot, + struct NineBaseTexture9 *tex ) +{ + if (applyToDevice) + NineBindTextureToDevice(device, slot, tex); + else + nine_bind(slot, tex); +} + +/* Copy state marked changed in @mask from @src to @dst. + * If @apply is false, updating dst->changed can be omitted. + * TODO: compare ? + */ +static void +nine_state_copy_common(struct NineDevice9 *device, + struct nine_state *dst, + struct nine_state *src, + struct nine_state *mask, /* aliases either src or dst */ + const boolean apply, + struct nine_range_pool *pool) +{ + unsigned i, s; + + DBG("apply:%d changed.group: %x\n", (int)apply, (int)mask->changed.group ); + + /* device changed.* are unused. + * Instead nine_context_apply_stateblock is used and will + * internally set the right context->changed fields. + * Uncomment these only if we want to apply a stateblock onto a stateblock. + * + * if (apply) + * dst->changed.group |= mask->changed.group; + */ + + if (mask->changed.group & NINE_STATE_VIEWPORT) + dst->viewport = src->viewport; + if (mask->changed.group & NINE_STATE_SCISSOR) + dst->scissor = src->scissor; + + if (mask->changed.group & NINE_STATE_VS) + nine_bind(&dst->vs, src->vs); + if (mask->changed.group & NINE_STATE_PS) + nine_bind(&dst->ps, src->ps); + + /* Vertex constants. + * + * Various possibilities for optimization here, like creating a per-SB + * constant buffer, or memcmp'ing for changes. + * Will do that later depending on what works best for specific apps. + * + * Note: Currently when we apply stateblocks, it's always on the device state. + * Should it affect recording stateblocks ? Since it's on device state, there + * is no need to copy which ranges are dirty. If it turns out we should affect + * recording stateblocks, the info should be copied. + */ + if (mask->changed.group & NINE_STATE_VS_CONST) { + struct nine_range *r; + for (r = mask->changed.vs_const_f; r; r = r->next) { + memcpy(&dst->vs_const_f[r->bgn * 4], + &src->vs_const_f[r->bgn * 4], + (r->end - r->bgn) * 4 * sizeof(float)); + } + for (r = mask->changed.vs_const_i; r; r = r->next) { + memcpy(&dst->vs_const_i[r->bgn * 4], + &src->vs_const_i[r->bgn * 4], + (r->end - r->bgn) * 4 * sizeof(int)); + } + for (r = mask->changed.vs_const_b; r; r = r->next) { + memcpy(&dst->vs_const_b[r->bgn], + &src->vs_const_b[r->bgn], + (r->end - r->bgn) * sizeof(int)); + } + } + + /* Pixel constants. */ + if (mask->changed.group & NINE_STATE_PS_CONST) { + struct nine_range *r; + for (r = mask->changed.ps_const_f; r; r = r->next) { + memcpy(&dst->ps_const_f[r->bgn * 4], + &src->ps_const_f[r->bgn * 4], + (r->end - r->bgn) * 4 * sizeof(float)); + } + if (mask->changed.ps_const_i) { + uint16_t m = mask->changed.ps_const_i; + for (i = ffs(m) - 1, m >>= i; m; ++i, m >>= 1) + if (m & 1) + memcpy(dst->ps_const_i[i], src->ps_const_i[i], 4 * sizeof(int)); + } + if (mask->changed.ps_const_b) { + uint16_t m = mask->changed.ps_const_b; + for (i = ffs(m) - 1, m >>= i; m; ++i, m >>= 1) + if (m & 1) + dst->ps_const_b[i] = src->ps_const_b[i]; + } + } + + /* Render states. + * TODO: Maybe build a list ? + */ + for (i = 0; i < ARRAY_SIZE(mask->changed.rs); ++i) { + uint32_t m = mask->changed.rs[i]; + /* if (apply) + * dst->changed.rs[i] |= m; */ + while (m) { + const int r = ffs(m) - 1; + m &= ~(1 << r); + DBG("State %d %s = %d\n", i * 32 + r, nine_d3drs_to_string(i * 32 + r), (int)src->rs_advertised[i * 32 + r]); + dst->rs_advertised[i * 32 + r] = src->rs_advertised[i * 32 + r]; + } + } + + + /* Clip planes. */ + if (mask->changed.ucp) { + DBG("ucp: %x\n", mask->changed.ucp); + for (i = 0; i < PIPE_MAX_CLIP_PLANES; ++i) + if (mask->changed.ucp & (1 << i)) + memcpy(dst->clip.ucp[i], + src->clip.ucp[i], sizeof(src->clip.ucp[0])); + /* if (apply) + * dst->changed.ucp |= mask->changed.ucp;*/ + } + + /* Sampler state. */ + if (mask->changed.group & NINE_STATE_SAMPLER) { + for (s = 0; s < NINE_MAX_SAMPLERS; ++s) { + if (mask->changed.sampler[s] == 0x3ffe) { + memcpy(&dst->samp_advertised[s], &src->samp_advertised[s], sizeof(dst->samp_advertised[s])); + } else { + uint32_t m = mask->changed.sampler[s]; + DBG("samp %d: changed = %x\n", i, (int)m); + while (m) { + const int i = ffs(m) - 1; + m &= ~(1 << i); + dst->samp_advertised[s][i] = src->samp_advertised[s][i]; + } + } + /* if (apply) + * dst->changed.sampler[s] |= mask->changed.sampler[s];*/ + } + } + + /* Index buffer. */ + if (mask->changed.group & NINE_STATE_IDXBUF) + NineStateBlock9_BindBuffer(device, + apply, + (struct NineBuffer9 **)&dst->idxbuf, + (struct NineBuffer9 *)src->idxbuf); + + /* Vertex streams. */ + if (mask->changed.vtxbuf | mask->changed.stream_freq) { + DBG("vtxbuf/stream_freq: %x/%x\n", mask->changed.vtxbuf, mask->changed.stream_freq); + uint32_t m = mask->changed.vtxbuf | mask->changed.stream_freq; + for (i = 0; m; ++i, m >>= 1) { + if (mask->changed.vtxbuf & (1 << i)) { + NineStateBlock9_BindBuffer(device, + apply, + (struct NineBuffer9 **)&dst->stream[i], + (struct NineBuffer9 *)src->stream[i]); + if (src->stream[i]) { + dst->vtxbuf[i].buffer_offset = src->vtxbuf[i].buffer_offset; + dst->vtxbuf[i].stride = src->vtxbuf[i].stride; + } + } + if (mask->changed.stream_freq & (1 << i)) + dst->stream_freq[i] = src->stream_freq[i]; + } + /* + * if (apply) { + * dst->changed.vtxbuf |= mask->changed.vtxbuf; + * dst->changed.stream_freq |= mask->changed.stream_freq; + * }*/ + } + + /* Textures */ + if (mask->changed.texture) { + uint32_t m = mask->changed.texture; + for (s = 0; m; ++s, m >>= 1) + if (m & 1) + NineStateBlock9_BindTexture(device, apply, &dst->texture[s], src->texture[s]); + } + + if (!(mask->changed.group & NINE_STATE_FF)) + return; + WARN_ONCE("Fixed function state not handled properly by StateBlocks.\n"); + + /* Fixed function state. */ + + if (mask->changed.group & NINE_STATE_FF_MATERIAL) + dst->ff.material = src->ff.material; + + if (mask->changed.group & NINE_STATE_FF_PS_CONSTS) { + for (s = 0; s < NINE_MAX_TEXTURE_STAGES; ++s) { + for (i = 0; i < NINED3DTSS_COUNT; ++i) + if (mask->ff.changed.tex_stage[s][i / 32] & (1 << (i % 32))) + dst->ff.tex_stage[s][i] = src->ff.tex_stage[s][i]; + /* + * if (apply) { + * TODO: it's 32 exactly, just offset by 1 as 0 is unused + * dst->ff.changed.tex_stage[s][0] |= + * mask->ff.changed.tex_stage[s][0]; + * dst->ff.changed.tex_stage[s][1] |= + * mask->ff.changed.tex_stage[s][1]; + * }*/ + } + } + if (mask->changed.group & NINE_STATE_FF_LIGHTING) { + unsigned num_lights = MAX2(dst->ff.num_lights, src->ff.num_lights); + /* Can happen in Capture() if device state has created new lights after + * the stateblock was created. + * Can happen in Apply() if the stateblock had recorded the creation of + * new lights. */ + if (dst->ff.num_lights < num_lights) { + dst->ff.light = REALLOC(dst->ff.light, + dst->ff.num_lights * sizeof(D3DLIGHT9), + num_lights * sizeof(D3DLIGHT9)); + memset(&dst->ff.light[dst->ff.num_lights], 0, (num_lights - dst->ff.num_lights) * sizeof(D3DLIGHT9)); + /* if mask == dst, a Type of 0 will trigger + * "dst->ff.light[i] = src->ff.light[i];" later, + * which is what we want in that case. */ + if (mask != dst) { + for (i = dst->ff.num_lights; i < num_lights; ++i) + dst->ff.light[i].Type = (D3DLIGHTTYPE)NINED3DLIGHT_INVALID; + } + dst->ff.num_lights = num_lights; + } + /* Can happen in Capture() if the stateblock had recorded the creation of + * new lights. + * Can happen in Apply() if device state has created new lights after + * the stateblock was created. */ + if (src->ff.num_lights < num_lights) { + src->ff.light = REALLOC(src->ff.light, + src->ff.num_lights * sizeof(D3DLIGHT9), + num_lights * sizeof(D3DLIGHT9)); + memset(&src->ff.light[src->ff.num_lights], 0, (num_lights - src->ff.num_lights) * sizeof(D3DLIGHT9)); + for (i = src->ff.num_lights; i < num_lights; ++i) + src->ff.light[i].Type = (D3DLIGHTTYPE)NINED3DLIGHT_INVALID; + src->ff.num_lights = num_lights; + } + /* Note: mask is either src or dst, so at this point src, dst and mask + * have num_lights lights. */ + for (i = 0; i < num_lights; ++i) + if (mask->ff.light[i].Type != NINED3DLIGHT_INVALID) + dst->ff.light[i] = src->ff.light[i]; + + memcpy(dst->ff.active_light, src->ff.active_light, sizeof(src->ff.active_light) ); + dst->ff.num_lights_active = src->ff.num_lights_active; + } + if (mask->changed.group & NINE_STATE_FF_VSTRANSF) { + for (i = 0; i < ARRAY_SIZE(mask->ff.changed.transform); ++i) { + if (!mask->ff.changed.transform[i]) + continue; + for (s = i * 32; s < (i * 32 + 32); ++s) { + if (!(mask->ff.changed.transform[i] & (1 << (s % 32)))) + continue; + *nine_state_access_transform(&dst->ff, s, TRUE) = + *nine_state_access_transform(&src->ff, s, FALSE); + } + /* if (apply) + * dst->ff.changed.transform[i] |= mask->ff.changed.transform[i];*/ + } + } +} + +static void +nine_state_copy_common_all(struct NineDevice9 *device, + struct nine_state *dst, + struct nine_state *src, + struct nine_state *help, + const boolean apply, + struct nine_range_pool *pool, + const int MaxStreams) +{ + unsigned i; + + /* if (apply) + * dst->changed.group |= src->changed.group; + */ + + dst->viewport = src->viewport; + dst->scissor = src->scissor; + + nine_bind(&dst->vs, src->vs); + nine_bind(&dst->ps, src->ps); + + /* Vertex constants. + * + * Various possibilities for optimization here, like creating a per-SB + * constant buffer, or memcmp'ing for changes. + * Will do that later depending on what works best for specific apps. + */ + if (1) { + memcpy(&dst->vs_const_f[0], + &src->vs_const_f[0], VS_CONST_F_SIZE(device)); + + memcpy(dst->vs_const_i, src->vs_const_i, VS_CONST_I_SIZE(device)); + memcpy(dst->vs_const_b, src->vs_const_b, VS_CONST_B_SIZE(device)); + } + + /* Pixel constants. */ + if (1) { + struct nine_range *r = help->changed.ps_const_f; + memcpy(&dst->ps_const_f[0], + &src->ps_const_f[0], (r->end - r->bgn) * 4 * sizeof(float)); + + memcpy(dst->ps_const_i, src->ps_const_i, sizeof(dst->ps_const_i)); + memcpy(dst->ps_const_b, src->ps_const_b, sizeof(dst->ps_const_b)); + } + + /* Render states. */ + memcpy(dst->rs_advertised, src->rs_advertised, sizeof(dst->rs_advertised)); + /* if (apply) + * memcpy(dst->changed.rs, src->changed.rs, sizeof(dst->changed.rs));*/ + + + /* Clip planes. */ + memcpy(&dst->clip, &src->clip, sizeof(dst->clip)); + /* if (apply) + * dst->changed.ucp = src->changed.ucp;*/ + + /* Sampler state. */ + memcpy(dst->samp_advertised, src->samp_advertised, sizeof(dst->samp_advertised)); + /* if (apply) + * memcpy(dst->changed.sampler, + * src->changed.sampler, sizeof(dst->changed.sampler));*/ + + /* Index buffer. */ + NineStateBlock9_BindBuffer(device, + apply, + (struct NineBuffer9 **)&dst->idxbuf, + (struct NineBuffer9 *)src->idxbuf); + + /* Vertex streams. */ + if (1) { + for (i = 0; i < ARRAY_SIZE(dst->stream); ++i) { + NineStateBlock9_BindBuffer(device, + apply, + (struct NineBuffer9 **)&dst->stream[i], + (struct NineBuffer9 *)src->stream[i]); + if (src->stream[i]) { + dst->vtxbuf[i].buffer_offset = src->vtxbuf[i].buffer_offset; + dst->vtxbuf[i].stride = src->vtxbuf[i].stride; + } + dst->stream_freq[i] = src->stream_freq[i]; + } + /* if (apply) { + * dst->changed.vtxbuf = (1ULL << MaxStreams) - 1; + * dst->changed.stream_freq = (1ULL << MaxStreams) - 1; + * }*/ + } + + /* Textures */ + if (1) { + for (i = 0; i < NINE_MAX_SAMPLERS; i++) + NineStateBlock9_BindTexture(device, apply, &dst->texture[i], src->texture[i]); + } + + /* keep this check in case we want to disable FF */ + if (!(help->changed.group & NINE_STATE_FF)) + return; + WARN_ONCE("Fixed function state not handled properly by StateBlocks.\n"); + + /* Fixed function state. */ + dst->ff.material = src->ff.material; + + memcpy(dst->ff.tex_stage, src->ff.tex_stage, sizeof(dst->ff.tex_stage)); + /* if (apply) TODO: memset + * memcpy(dst->ff.changed.tex_stage, + * src->ff.changed.tex_stage, sizeof(dst->ff.changed.tex_stage));*/ + + /* Lights. */ + if (1) { + if (dst->ff.num_lights < src->ff.num_lights) { + dst->ff.light = REALLOC(dst->ff.light, + dst->ff.num_lights * sizeof(D3DLIGHT9), + src->ff.num_lights * sizeof(D3DLIGHT9)); + dst->ff.num_lights = src->ff.num_lights; + } + memcpy(dst->ff.light, + src->ff.light, src->ff.num_lights * sizeof(dst->ff.light[0])); + + memcpy(dst->ff.active_light, src->ff.active_light, sizeof(src->ff.active_light) ); + dst->ff.num_lights_active = src->ff.num_lights_active; + } + + /* Transforms. */ + if (1) { + /* Increase dst size if required (to copy the new states). + * Increase src size if required (to initialize missing transforms). + */ + if (dst->ff.num_transforms != src->ff.num_transforms) { + int num_transforms = MAX2(src->ff.num_transforms, dst->ff.num_transforms); + nine_state_resize_transform(&src->ff, num_transforms); + nine_state_resize_transform(&dst->ff, num_transforms); + } + memcpy(dst->ff.transform, + src->ff.transform, dst->ff.num_transforms * sizeof(D3DMATRIX)); + /* Apply is always used on device state. + * src is then the D3DSBT_ALL stateblock which + * ff.changed.transform indicates all matrices are dirty. + * + * if (apply) + * memcpy(dst->ff.changed.transform, + * src->ff.changed.transform, sizeof(dst->ff.changed.transform));*/ + } +} + +/* Capture those bits of current device state that have been changed between + * BeginStateBlock and EndStateBlock. + */ +HRESULT NINE_WINAPI +NineStateBlock9_Capture( struct NineStateBlock9 *This ) +{ + struct NineDevice9 *device = This->base.device; + struct nine_state *dst = &This->state; + struct nine_state *src = &device->state; + const int MaxStreams = device->caps.MaxStreams; + + DBG("This=%p\n", This); + + if (This->type == NINESBT_ALL) + nine_state_copy_common_all(device, dst, src, dst, FALSE, NULL, MaxStreams); + else + nine_state_copy_common(device, dst, src, dst, FALSE, NULL); + + if (dst->changed.group & NINE_STATE_VDECL) + nine_bind(&dst->vdecl, src->vdecl); + + return D3D_OK; +} + +/* Set state managed by this StateBlock as current device state. */ +HRESULT NINE_WINAPI +NineStateBlock9_Apply( struct NineStateBlock9 *This ) +{ + struct NineDevice9 *device = This->base.device; + struct nine_state *dst = &device->state; + struct nine_state *src = &This->state; + struct nine_range_pool *pool = &device->range_pool; + const int MaxStreams = device->caps.MaxStreams; + + DBG("This=%p\n", This); + + if (This->type == NINESBT_ALL) + nine_state_copy_common_all(device, dst, src, src, TRUE, pool, MaxStreams); + else + nine_state_copy_common(device, dst, src, src, TRUE, pool); + + nine_context_apply_stateblock(device, src); + + if ((src->changed.group & NINE_STATE_VDECL) && src->vdecl) + nine_bind(&dst->vdecl, src->vdecl); + + return D3D_OK; +} + +IDirect3DStateBlock9Vtbl NineStateBlock9_vtable = { + (void *)NineUnknown_QueryInterface, + (void *)NineUnknown_AddRef, + (void *)NineUnknown_Release, + (void *)NineUnknown_GetDevice, /* actually part of StateBlock9 iface */ + (void *)NineStateBlock9_Capture, + (void *)NineStateBlock9_Apply +}; + +static const GUID *NineStateBlock9_IIDs[] = { + &IID_IDirect3DStateBlock9, + &IID_IUnknown, + NULL +}; + +HRESULT +NineStateBlock9_new( struct NineDevice9 *pDevice, + struct NineStateBlock9 **ppOut, + enum nine_stateblock_type type) +{ + NINE_DEVICE_CHILD_NEW(StateBlock9, ppOut, pDevice, type); +} diff --git a/src/gallium/frontends/nine/stateblock9.h b/src/gallium/frontends/nine/stateblock9.h new file mode 100644 index 00000000000..ffcc2d99a53 --- /dev/null +++ b/src/gallium/frontends/nine/stateblock9.h @@ -0,0 +1,71 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _NINE_STATEBLOCK9_H_ +#define _NINE_STATEBLOCK9_H_ + +#include "iunknown.h" + +#include "nine_state.h" + +enum nine_stateblock_type +{ + NINESBT_ALL, + NINESBT_VERTEXSTATE, + NINESBT_PIXELSTATE, + NINESBT_CUSTOM +}; + +struct NineStateBlock9 +{ + struct NineUnknown base; + + struct nine_state state; + + enum nine_stateblock_type type; +}; +static inline struct NineStateBlock9 * +NineStateBlock9( void *data ) +{ + return (struct NineStateBlock9 *)data; +} + +HRESULT +NineStateBlock9_new( struct NineDevice9 *, + struct NineStateBlock9 **ppOut, + enum nine_stateblock_type); + +HRESULT +NineStateBlock9_ctor( struct NineStateBlock9 *, + struct NineUnknownParams *pParams, + enum nine_stateblock_type type ); + +void +NineStateBlock9_dtor( struct NineStateBlock9 * ); + +HRESULT NINE_WINAPI +NineStateBlock9_Capture( struct NineStateBlock9 *This ); + +HRESULT NINE_WINAPI +NineStateBlock9_Apply( struct NineStateBlock9 *This ); + +#endif /* _NINE_STATEBLOCK9_H_ */ diff --git a/src/gallium/frontends/nine/surface9.c b/src/gallium/frontends/nine/surface9.c new file mode 100644 index 00000000000..db74de2823a --- /dev/null +++ b/src/gallium/frontends/nine/surface9.c @@ -0,0 +1,863 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "iunknown.h" +#include "surface9.h" +#include "device9.h" + +/* for marking dirty */ +#include "basetexture9.h" +#include "texture9.h" +#include "cubetexture9.h" + +#include "nine_helpers.h" +#include "nine_pipe.h" +#include "nine_dump.h" +#include "nine_state.h" + +#include "pipe/p_context.h" +#include "pipe/p_screen.h" +#include "pipe/p_state.h" + +#include "util/u_math.h" +#include "util/u_inlines.h" +#include "util/u_surface.h" + +#define DBG_CHANNEL DBG_SURFACE + +static void +NineSurface9_CreatePipeSurfaces( struct NineSurface9 *This ); + +HRESULT +NineSurface9_ctor( struct NineSurface9 *This, + struct NineUnknownParams *pParams, + struct NineUnknown *pContainer, + struct pipe_resource *pResource, + void *user_buffer, + uint8_t TextureType, + unsigned Level, + unsigned Layer, + D3DSURFACE_DESC *pDesc ) +{ + HRESULT hr; + bool allocate = !pContainer && pDesc->Format != D3DFMT_NULL; + D3DMULTISAMPLE_TYPE multisample_type; + + DBG("This=%p pDevice=%p pResource=%p Level=%u Layer=%u pDesc=%p\n", + This, pParams->device, pResource, Level, Layer, pDesc); + + /* Mark this as a special surface held by another internal resource. */ + pParams->container = pContainer; + /* Make sure there's a Desc */ + assert(pDesc); + + assert(allocate || pResource || user_buffer || + pDesc->Format == D3DFMT_NULL); + assert(!allocate || (!pResource && !user_buffer)); + assert(!pResource || !user_buffer); + assert(!user_buffer || pDesc->Pool != D3DPOOL_DEFAULT); + assert(!pResource || pDesc->Pool == D3DPOOL_DEFAULT); + /* Allocation only from create_zs_or_rt_surface with params 0 0 0 */ + assert(!allocate || (Level == 0 && Layer == 0 && TextureType == 0)); + + This->data = (uint8_t *)user_buffer; + + multisample_type = pDesc->MultiSampleType; + + /* Map MultiSampleQuality to MultiSampleType */ + hr = d3dmultisample_type_check(pParams->device->screen, + pDesc->Format, + &multisample_type, + pDesc->MultiSampleQuality, + NULL); + if (FAILED(hr)) { + return hr; + } + + /* TODO: this is (except width and height) duplicate from + * container info (in the pContainer case). Some refactoring is + * needed to avoid duplication */ + This->base.info.screen = pParams->device->screen; + This->base.info.target = PIPE_TEXTURE_2D; + This->base.info.width0 = pDesc->Width; + This->base.info.height0 = pDesc->Height; + This->base.info.depth0 = 1; + This->base.info.last_level = 0; + This->base.info.array_size = 1; + This->base.info.nr_samples = multisample_type; + This->base.info.nr_storage_samples = multisample_type; + This->base.info.usage = PIPE_USAGE_DEFAULT; + This->base.info.bind = PIPE_BIND_SAMPLER_VIEW; /* StretchRect */ + + if (pDesc->Usage & D3DUSAGE_RENDERTARGET) { + This->base.info.bind |= PIPE_BIND_RENDER_TARGET; + } else if (pDesc->Usage & D3DUSAGE_DEPTHSTENCIL) { + if (!depth_stencil_format(pDesc->Format)) + return D3DERR_INVALIDCALL; + This->base.info.bind = d3d9_get_pipe_depth_format_bindings(pDesc->Format); + if (TextureType) + This->base.info.bind |= PIPE_BIND_SAMPLER_VIEW; + } + + This->base.info.flags = 0; + This->base.info.format = d3d9_to_pipe_format_checked(This->base.info.screen, + pDesc->Format, + This->base.info.target, + This->base.info.nr_samples, + This->base.info.bind, + FALSE, + pDesc->Pool == D3DPOOL_SCRATCH); + + if (This->base.info.format == PIPE_FORMAT_NONE && pDesc->Format != D3DFMT_NULL) + return D3DERR_INVALIDCALL; + + if (allocate && compressed_format(pDesc->Format)) { + const unsigned w = util_format_get_blockwidth(This->base.info.format); + const unsigned h = util_format_get_blockheight(This->base.info.format); + + /* Note: In the !allocate case, the test could fail (lower levels of a texture) */ + user_assert(!(pDesc->Width % w) && !(pDesc->Height % h), D3DERR_INVALIDCALL); + } + + /* Get true format */ + This->format_internal = d3d9_to_pipe_format_checked(This->base.info.screen, + pDesc->Format, + This->base.info.target, + This->base.info.nr_samples, + This->base.info.bind, + FALSE, + TRUE); + if (This->base.info.format != This->format_internal || + /* DYNAMIC Textures requires same stride as ram buffers. + * Do not use workaround by default as it eats more virtual space */ + (pParams->device->workarounds.dynamic_texture_workaround && + pDesc->Pool == D3DPOOL_DEFAULT && pDesc->Usage & D3DUSAGE_DYNAMIC)) { + This->data_internal = align_calloc( + nine_format_get_level_alloc_size(This->format_internal, + pDesc->Width, + pDesc->Height, + 0), 32); + if (!This->data_internal) + return E_OUTOFMEMORY; + This->stride_internal = nine_format_get_stride(This->format_internal, + pDesc->Width); + } + + if ((allocate && pDesc->Pool != D3DPOOL_DEFAULT) || pDesc->Format == D3DFMT_NULL) { + /* Ram buffer with no parent. Has to allocate the resource itself */ + assert(!user_buffer); + This->data = align_calloc( + nine_format_get_level_alloc_size(This->base.info.format, + pDesc->Width, + pDesc->Height, + 0), 32); + if (!This->data) + return E_OUTOFMEMORY; + } + + hr = NineResource9_ctor(&This->base, pParams, pResource, + allocate && (pDesc->Pool == D3DPOOL_DEFAULT), + D3DRTYPE_SURFACE, pDesc->Pool, pDesc->Usage); + + if (FAILED(hr)) + return hr; + + This->transfer = NULL; + + This->texture = TextureType; + This->level = Level; + This->level_actual = Level; + This->layer = Layer; + This->desc = *pDesc; + + This->stride = nine_format_get_stride(This->base.info.format, pDesc->Width); + + if (This->base.resource && (pDesc->Usage & D3DUSAGE_DYNAMIC)) + This->base.resource->flags |= NINE_RESOURCE_FLAG_LOCKABLE; + + if (This->base.resource && (pDesc->Usage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL))) + NineSurface9_CreatePipeSurfaces(This); + + /* TODO: investigate what else exactly needs to be cleared */ + if (This->base.resource && (pDesc->Usage & D3DUSAGE_RENDERTARGET)) + nine_context_clear_render_target(pParams->device, This, 0, 0, 0, pDesc->Width, pDesc->Height); + + NineSurface9_Dump(This); + + return D3D_OK; +} + +void +NineSurface9_dtor( struct NineSurface9 *This ) +{ + DBG("This=%p\n", This); + + if (This->transfer) { + struct pipe_context *pipe = nine_context_get_pipe_multithread(This->base.base.device); + pipe->transfer_unmap(pipe, This->transfer); + This->transfer = NULL; + } + + /* Note: Following condition cannot happen currently, since we + * refcount the surface in the functions increasing + * pending_uploads_counter. */ + if (p_atomic_read(&This->pending_uploads_counter)) + nine_csmt_process(This->base.base.device); + + pipe_surface_reference(&This->surface[0], NULL); + pipe_surface_reference(&This->surface[1], NULL); + + /* Release system memory when we have to manage it (no parent) */ + if (!This->base.base.container && This->data) + align_free(This->data); + if (This->data_internal) + align_free(This->data_internal); + NineResource9_dtor(&This->base); +} + +static void +NineSurface9_CreatePipeSurfaces( struct NineSurface9 *This ) +{ + struct pipe_context *pipe; + struct pipe_screen *screen = NineDevice9_GetScreen(This->base.base.device); + struct pipe_resource *resource = This->base.resource; + struct pipe_surface templ; + enum pipe_format srgb_format; + + assert(This->desc.Pool == D3DPOOL_DEFAULT); + assert(resource); + + srgb_format = util_format_srgb(resource->format); + if (srgb_format == PIPE_FORMAT_NONE || + !screen->is_format_supported(screen, srgb_format, + resource->target, 0, 0, resource->bind)) + srgb_format = resource->format; + + memset(&templ, 0, sizeof(templ)); + templ.format = resource->format; + templ.u.tex.level = This->level; + templ.u.tex.first_layer = This->layer; + templ.u.tex.last_layer = This->layer; + + pipe = nine_context_get_pipe_acquire(This->base.base.device); + + This->surface[0] = pipe->create_surface(pipe, resource, &templ); + + memset(&templ, 0, sizeof(templ)); + templ.format = srgb_format; + templ.u.tex.level = This->level; + templ.u.tex.first_layer = This->layer; + templ.u.tex.last_layer = This->layer; + + This->surface[1] = pipe->create_surface(pipe, resource, &templ); + + nine_context_get_pipe_release(This->base.base.device); + + assert(This->surface[0]); /* TODO: Handle failure */ + assert(This->surface[1]); +} + +#if defined(DEBUG) || !defined(NDEBUG) +void +NineSurface9_Dump( struct NineSurface9 *This ) +{ + struct NineBaseTexture9 *tex; + GUID id = IID_IDirect3DBaseTexture9; + REFIID ref = &id; + + DBG("\nNineSurface9(%p->%p/%p): Pool=%s Type=%s Usage=%s\n" + "Dims=%ux%u Format=%s Stride=%u Lockable=%i\n" + "Level=%u(%u), Layer=%u\n", This, This->base.resource, This->data, + nine_D3DPOOL_to_str(This->desc.Pool), + nine_D3DRTYPE_to_str(This->desc.Type), + nine_D3DUSAGE_to_str(This->desc.Usage), + This->desc.Width, This->desc.Height, + d3dformat_to_string(This->desc.Format), This->stride, + This->base.resource && + (This->base.resource->flags & NINE_RESOURCE_FLAG_LOCKABLE), + This->level, This->level_actual, This->layer); + + if (!This->base.base.container) + return; + NineUnknown_QueryInterface(This->base.base.container, ref, (void **)&tex); + if (tex) { + NineBaseTexture9_Dump(tex); + NineUnknown_Release(NineUnknown(tex)); + } +} +#endif /* DEBUG || !NDEBUG */ + +HRESULT NINE_WINAPI +NineSurface9_GetContainer( struct NineSurface9 *This, + REFIID riid, + void **ppContainer ) +{ + HRESULT hr; + char guid_str[64]; + + DBG("This=%p riid=%p id=%s ppContainer=%p\n", + This, riid, riid ? GUID_sprintf(guid_str, riid) : "", ppContainer); + + (void)guid_str; + + if (!ppContainer) return E_POINTER; + + /* Return device for OffscreenPlainSurface, DepthStencilSurface and RenderTarget */ + if (!NineUnknown(This)->container) { + *ppContainer = NineUnknown(This)->device; + NineUnknown_AddRef(NineUnknown(*ppContainer)); + + return D3D_OK; + } + + hr = NineUnknown_QueryInterface(NineUnknown(This)->container, riid, ppContainer); + if (FAILED(hr)) + DBG("QueryInterface FAILED!\n"); + return hr; +} + +void +NineSurface9_MarkContainerDirty( struct NineSurface9 *This ) +{ + if (This->texture) { + struct NineBaseTexture9 *tex = + NineBaseTexture9(This->base.base.container); + assert(tex); + assert(This->texture == D3DRTYPE_TEXTURE || + This->texture == D3DRTYPE_CUBETEXTURE); + if (This->base.pool == D3DPOOL_MANAGED) + tex->managed.dirty = TRUE; + else + if (This->base.usage & D3DUSAGE_AUTOGENMIPMAP) + tex->dirty_mip = TRUE; + + BASETEX_REGISTER_UPDATE(tex); + } +} + +HRESULT NINE_WINAPI +NineSurface9_GetDesc( struct NineSurface9 *This, + D3DSURFACE_DESC *pDesc ) +{ + user_assert(pDesc != NULL, E_POINTER); + *pDesc = This->desc; + return D3D_OK; +} + +/* Add the dirty rects to the source texture */ +inline void +NineSurface9_AddDirtyRect( struct NineSurface9 *This, + const struct pipe_box *box ) +{ + RECT dirty_rect; + + DBG("This=%p box=%p\n", This, box); + + assert (This->base.pool != D3DPOOL_MANAGED || + This->texture == D3DRTYPE_CUBETEXTURE || + This->texture == D3DRTYPE_TEXTURE); + + if (This->base.pool == D3DPOOL_DEFAULT) + return; + + /* Add a dirty rect to level 0 of the parent texture */ + dirty_rect.left = box->x << This->level_actual; + dirty_rect.right = dirty_rect.left + (box->width << This->level_actual); + dirty_rect.top = box->y << This->level_actual; + dirty_rect.bottom = dirty_rect.top + (box->height << This->level_actual); + + if (This->texture == D3DRTYPE_TEXTURE) { + struct NineTexture9 *tex = + NineTexture9(This->base.base.container); + + NineTexture9_AddDirtyRect(tex, &dirty_rect); + } else if (This->texture == D3DRTYPE_CUBETEXTURE) { + struct NineCubeTexture9 *ctex = + NineCubeTexture9(This->base.base.container); + + NineCubeTexture9_AddDirtyRect(ctex, This->layer, &dirty_rect); + } +} + +static inline unsigned +NineSurface9_GetSystemMemOffset(enum pipe_format format, unsigned stride, + int x, int y) +{ + unsigned x_offset = util_format_get_stride(format, x); + + y = util_format_get_nblocksy(format, y); + + return y * stride + x_offset; +} + +HRESULT NINE_WINAPI +NineSurface9_LockRect( struct NineSurface9 *This, + D3DLOCKED_RECT *pLockedRect, + const RECT *pRect, + DWORD Flags ) +{ + struct pipe_resource *resource = This->base.resource; + struct pipe_context *pipe; + struct pipe_box box; + unsigned usage; + + DBG("This=%p pLockedRect=%p pRect=%p[%u..%u,%u..%u] Flags=%s\n", This, + pLockedRect, pRect, + pRect ? pRect->left : 0, pRect ? pRect->right : 0, + pRect ? pRect->top : 0, pRect ? pRect->bottom : 0, + nine_D3DLOCK_to_str(Flags)); + NineSurface9_Dump(This); + + /* check if it's already locked */ + user_assert(This->lock_count == 0, D3DERR_INVALIDCALL); + + /* set pBits to NULL after lock_count check */ + user_assert(pLockedRect, E_POINTER); + pLockedRect->pBits = NULL; + +#ifdef NINE_STRICT + user_assert(This->base.pool != D3DPOOL_DEFAULT || + (resource && (resource->flags & NINE_RESOURCE_FLAG_LOCKABLE)), + D3DERR_INVALIDCALL); +#endif + user_assert(!(Flags & ~(D3DLOCK_DISCARD | + D3DLOCK_DONOTWAIT | + D3DLOCK_NO_DIRTY_UPDATE | + D3DLOCK_NOOVERWRITE | + D3DLOCK_NOSYSLOCK | /* ignored */ + D3DLOCK_READONLY)), D3DERR_INVALIDCALL); + user_assert(!((Flags & D3DLOCK_DISCARD) && (Flags & D3DLOCK_READONLY)), + D3DERR_INVALIDCALL); + + user_assert(This->desc.MultiSampleType == D3DMULTISAMPLE_NONE, + D3DERR_INVALIDCALL); + + if (pRect && This->desc.Pool == D3DPOOL_DEFAULT && + util_format_is_compressed(This->base.info.format)) { + const unsigned w = util_format_get_blockwidth(This->base.info.format); + const unsigned h = util_format_get_blockheight(This->base.info.format); + user_assert((pRect->left == 0 && pRect->right == This->desc.Width && + pRect->top == 0 && pRect->bottom == This->desc.Height) || + (!(pRect->left % w) && !(pRect->right % w) && + !(pRect->top % h) && !(pRect->bottom % h)), + D3DERR_INVALIDCALL); + } + + if (Flags & D3DLOCK_DISCARD) { + usage = PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE; + } else { + usage = (Flags & D3DLOCK_READONLY) ? + PIPE_TRANSFER_READ : PIPE_TRANSFER_READ_WRITE; + } + if (Flags & D3DLOCK_DONOTWAIT) + usage |= PIPE_TRANSFER_DONTBLOCK; + + if (pRect) { + /* Windows XP accepts invalid locking rectangles, Windows 7 rejects + * them. Use Windows XP behaviour for now. */ + rect_to_pipe_box(&box, pRect); + } else { + u_box_origin_2d(This->desc.Width, This->desc.Height, &box); + } + box.z = This->layer; + + user_warn(This->desc.Format == D3DFMT_NULL); + + if (p_atomic_read(&This->pending_uploads_counter)) + nine_csmt_process(This->base.base.device); + + if (This->data_internal || This->data) { + enum pipe_format format = This->base.info.format; + unsigned stride = This->stride; + uint8_t *data = This->data; + if (This->data_internal) { + format = This->format_internal; + stride = This->stride_internal; + data = This->data_internal; + } + DBG("returning system memory\n"); + /* ATI1 and ATI2 need special handling, because of d3d9 bug. + * We must advertise to the application as if it is uncompressed + * and bpp 8, and the app has a workaround to work with the fact + * that it is actually compressed. */ + if (is_ATI1_ATI2(format)) { + pLockedRect->Pitch = This->desc.Width; + pLockedRect->pBits = data + box.y * This->desc.Width + box.x; + } else { + pLockedRect->Pitch = stride; + pLockedRect->pBits = data + + NineSurface9_GetSystemMemOffset(format, + stride, + box.x, + box.y); + } + } else { + bool no_refs = !p_atomic_read(&This->base.base.bind) && + !(This->base.base.container && p_atomic_read(&This->base.base.container->bind)); + DBG("mapping pipe_resource %p (level=%u usage=%x)\n", + resource, This->level, usage); + + /* if the object is not bound internally, there can't be any pending + * operation with the surface in the queue */ + if (no_refs) + pipe = nine_context_get_pipe_acquire(This->base.base.device); + else + pipe = NineDevice9_GetPipe(This->base.base.device); + pLockedRect->pBits = pipe->transfer_map(pipe, resource, + This->level, usage, &box, + &This->transfer); + if (no_refs) + nine_context_get_pipe_release(This->base.base.device); + if (!This->transfer) { + DBG("transfer_map failed\n"); + if (Flags & D3DLOCK_DONOTWAIT) + return D3DERR_WASSTILLDRAWING; + return D3DERR_INVALIDCALL; + } + pLockedRect->Pitch = This->transfer->stride; + } + + if (!(Flags & (D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_READONLY))) { + NineSurface9_MarkContainerDirty(This); + NineSurface9_AddDirtyRect(This, &box); + } + + ++This->lock_count; + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineSurface9_UnlockRect( struct NineSurface9 *This ) +{ + struct pipe_box dst_box, src_box; + struct pipe_context *pipe; + DBG("This=%p lock_count=%u\n", This, This->lock_count); + user_assert(This->lock_count, D3DERR_INVALIDCALL); + if (This->transfer) { + pipe = nine_context_get_pipe_acquire(This->base.base.device); + pipe->transfer_unmap(pipe, This->transfer); + nine_context_get_pipe_release(This->base.base.device); + This->transfer = NULL; + } + --This->lock_count; + + if (This->data_internal) { + if (This->data) { + (void) util_format_translate(This->base.info.format, + This->data, This->stride, + 0, 0, + This->format_internal, + This->data_internal, + This->stride_internal, + 0, 0, + This->desc.Width, This->desc.Height); + } else { + u_box_2d_zslice(0, 0, This->layer, + This->desc.Width, This->desc.Height, &dst_box); + u_box_2d_zslice(0, 0, 0, + This->desc.Width, This->desc.Height, &src_box); + + nine_context_box_upload(This->base.base.device, + &This->pending_uploads_counter, + (struct NineUnknown *)This, + This->base.resource, + This->level, + &dst_box, + This->format_internal, + This->data_internal, + This->stride_internal, + 0, /* depth = 1 */ + &src_box); + } + } + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineSurface9_GetDC( struct NineSurface9 *This, + HDC *phdc ) +{ + STUB(D3DERR_INVALIDCALL); +} + +HRESULT NINE_WINAPI +NineSurface9_ReleaseDC( struct NineSurface9 *This, + HDC hdc ) +{ + STUB(D3DERR_INVALIDCALL); +} + +IDirect3DSurface9Vtbl NineSurface9_vtable = { + (void *)NineUnknown_QueryInterface, + (void *)NineUnknown_AddRef, + (void *)NineUnknown_Release, + (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */ + (void *)NineUnknown_SetPrivateData, + (void *)NineUnknown_GetPrivateData, + (void *)NineUnknown_FreePrivateData, + (void *)NineResource9_SetPriority, + (void *)NineResource9_GetPriority, + (void *)NineResource9_PreLoad, + (void *)NineResource9_GetType, + (void *)NineSurface9_GetContainer, + (void *)NineSurface9_GetDesc, + (void *)NineSurface9_LockRect, + (void *)NineSurface9_UnlockRect, + (void *)NineSurface9_GetDC, + (void *)NineSurface9_ReleaseDC +}; + +/* When this function is called, we have already checked + * The copy regions fit the surfaces */ +void +NineSurface9_CopyMemToDefault( struct NineSurface9 *This, + struct NineSurface9 *From, + const POINT *pDestPoint, + const RECT *pSourceRect ) +{ + struct pipe_resource *r_dst = This->base.resource; + struct pipe_box dst_box, src_box; + int src_x, src_y, dst_x, dst_y, copy_width, copy_height; + + assert(This->base.pool == D3DPOOL_DEFAULT && + From->base.pool == D3DPOOL_SYSTEMMEM); + + if (pDestPoint) { + dst_x = pDestPoint->x; + dst_y = pDestPoint->y; + } else { + dst_x = 0; + dst_y = 0; + } + + if (pSourceRect) { + src_x = pSourceRect->left; + src_y = pSourceRect->top; + copy_width = pSourceRect->right - pSourceRect->left; + copy_height = pSourceRect->bottom - pSourceRect->top; + } else { + src_x = 0; + src_y = 0; + copy_width = From->desc.Width; + copy_height = From->desc.Height; + } + + u_box_2d_zslice(dst_x, dst_y, This->layer, + copy_width, copy_height, &dst_box); + u_box_2d_zslice(src_x, src_y, 0, + copy_width, copy_height, &src_box); + + nine_context_box_upload(This->base.base.device, + &From->pending_uploads_counter, + (struct NineUnknown *)From, + r_dst, + This->level, + &dst_box, + From->base.info.format, + From->data, From->stride, + 0, /* depth = 1 */ + &src_box); + if (From->texture == D3DRTYPE_TEXTURE) { + struct NineTexture9 *tex = + NineTexture9(From->base.base.container); + /* D3DPOOL_SYSTEMMEM with buffer content passed + * from the user: execute the upload right now. + * It is possible it is enough to delay upload + * until the surface refcount is 0, but the + * bind refcount may not be 0, and thus the dtor + * is not executed (and doesn't trigger the + * pending_uploads_counter check). */ + if (!tex->managed_buffer) + nine_csmt_process(This->base.base.device); + } + + if (This->data_internal) + (void) util_format_translate(This->format_internal, + This->data_internal, + This->stride_internal, + dst_x, dst_y, + From->base.info.format, + From->data, From->stride, + src_x, src_y, + copy_width, copy_height); + + NineSurface9_MarkContainerDirty(This); +} + +void +NineSurface9_CopyDefaultToMem( struct NineSurface9 *This, + struct NineSurface9 *From ) +{ + struct pipe_context *pipe; + struct pipe_resource *r_src = From->base.resource; + struct pipe_transfer *transfer; + struct pipe_box src_box; + uint8_t *p_dst; + const uint8_t *p_src; + + assert(This->base.pool == D3DPOOL_SYSTEMMEM && + From->base.pool == D3DPOOL_DEFAULT); + + assert(This->desc.Width == From->desc.Width); + assert(This->desc.Height == From->desc.Height); + + u_box_origin_2d(This->desc.Width, This->desc.Height, &src_box); + src_box.z = From->layer; + + if (p_atomic_read(&This->pending_uploads_counter)) + nine_csmt_process(This->base.base.device); + + pipe = NineDevice9_GetPipe(This->base.base.device); + p_src = pipe->transfer_map(pipe, r_src, From->level, + PIPE_TRANSFER_READ, + &src_box, &transfer); + p_dst = This->data; + + assert (p_src && p_dst); + + util_copy_rect(p_dst, This->base.info.format, + This->stride, 0, 0, + This->desc.Width, This->desc.Height, + p_src, + transfer->stride, 0, 0); + + pipe->transfer_unmap(pipe, transfer); +} + + +/* Gladly, rendering to a MANAGED surface is not permitted, so we will + * never have to do the reverse, i.e. download the surface. + */ +HRESULT +NineSurface9_UploadSelf( struct NineSurface9 *This, + const struct pipe_box *damaged ) +{ + struct pipe_resource *res = This->base.resource; + struct pipe_box box; + + DBG("This=%p damaged=%p\n", This, damaged); + + assert(This->base.pool == D3DPOOL_MANAGED); + + if (damaged) { + box = *damaged; + box.z = This->layer; + box.depth = 1; + } else { + box.x = 0; + box.y = 0; + box.z = This->layer; + box.width = This->desc.Width; + box.height = This->desc.Height; + box.depth = 1; + } + + nine_context_box_upload(This->base.base.device, + &This->pending_uploads_counter, + (struct NineUnknown *)This, + res, + This->level, + &box, + res->format, + This->data, This->stride, + 0, /* depth = 1 */ + &box); + + return D3D_OK; +} + +/* Currently nine_context uses the NineSurface9 + * fields when it is render target. Any modification requires + * pending commands with the surface to be executed. If the bind + * count is 0, there is no pending commands. */ +#define PROCESS_IF_BOUND(surf) \ + if (surf->base.base.bind) \ + nine_csmt_process(surf->base.base.device); + +void +NineSurface9_SetResource( struct NineSurface9 *This, + struct pipe_resource *resource, unsigned level ) +{ + /* No need to call PROCESS_IF_BOUND, because SetResource is used only + * for MANAGED textures, and they are not render targets. */ + assert(This->base.pool == D3DPOOL_MANAGED); + This->level = level; + pipe_resource_reference(&This->base.resource, resource); +} + +void +NineSurface9_SetMultiSampleType( struct NineSurface9 *This, + D3DMULTISAMPLE_TYPE mst ) +{ + PROCESS_IF_BOUND(This); + This->desc.MultiSampleType = mst; +} + +void +NineSurface9_SetResourceResize( struct NineSurface9 *This, + struct pipe_resource *resource ) +{ + assert(This->level == 0 && This->level_actual == 0); + assert(!This->lock_count); + assert(This->desc.Pool == D3DPOOL_DEFAULT); + assert(!This->texture); + + PROCESS_IF_BOUND(This); + pipe_resource_reference(&This->base.resource, resource); + + This->desc.Width = This->base.info.width0 = resource->width0; + This->desc.Height = This->base.info.height0 = resource->height0; + This->base.info.nr_samples = resource->nr_samples; + This->base.info.nr_storage_samples = resource->nr_storage_samples; + + This->stride = nine_format_get_stride(This->base.info.format, + This->desc.Width); + + pipe_surface_reference(&This->surface[0], NULL); + pipe_surface_reference(&This->surface[1], NULL); + if (resource) + NineSurface9_CreatePipeSurfaces(This); +} + + +static const GUID *NineSurface9_IIDs[] = { + &IID_IDirect3DSurface9, + &IID_IDirect3DResource9, + &IID_IUnknown, + NULL +}; + +HRESULT +NineSurface9_new( struct NineDevice9 *pDevice, + struct NineUnknown *pContainer, + struct pipe_resource *pResource, + void *user_buffer, + uint8_t TextureType, + unsigned Level, + unsigned Layer, + D3DSURFACE_DESC *pDesc, + struct NineSurface9 **ppOut ) +{ + NINE_DEVICE_CHILD_NEW(Surface9, ppOut, pDevice, /* args */ + pContainer, pResource, user_buffer, + TextureType, Level, Layer, pDesc); +} diff --git a/src/gallium/frontends/nine/surface9.h b/src/gallium/frontends/nine/surface9.h new file mode 100644 index 00000000000..ee700603bd8 --- /dev/null +++ b/src/gallium/frontends/nine/surface9.h @@ -0,0 +1,178 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _NINE_SURFACE9_H_ +#define _NINE_SURFACE9_H_ + +#include "resource9.h" + +#include "pipe/p_state.h" +#include "util/list.h" +#include "util/u_rect.h" +#include "util/u_inlines.h" + +struct NineSurface9 +{ + struct NineResource9 base; + + /* G3D state */ + struct pipe_transfer *transfer; + struct pipe_surface *surface[2]; /* created on-demand (linear, sRGB) */ + int lock_count; + uint8_t texture; /* rtype of container BaseTex or 0 */ + + /* resource description */ + unsigned level; /* refers to the pipe_resource (SetLOD !) */ + unsigned level_actual; /* refers to the NineTexture */ + unsigned layer; + D3DSURFACE_DESC desc; + + uint8_t *data; /* system memory backing */ + uint8_t *data_internal; /* for conversions */ + enum pipe_format format_internal; + unsigned stride; /* for system memory backing */ + unsigned stride_internal; + + unsigned pending_uploads_counter; /* pending uploads */ +}; +static inline struct NineSurface9 * +NineSurface9( void *data ) +{ + return (struct NineSurface9 *)data; +} + +HRESULT +NineSurface9_new( struct NineDevice9 *pDevice, + struct NineUnknown *pContainer, + struct pipe_resource *pResource, + void *user_buffer, + uint8_t TextureType, /* 0 if pContainer isn't BaseTexure9 */ + unsigned Level, + unsigned Layer, + D3DSURFACE_DESC *pDesc, + struct NineSurface9 **ppOut ); + +HRESULT +NineSurface9_ctor( struct NineSurface9 *This, + struct NineUnknownParams *pParams, + struct NineUnknown *pContainer, + struct pipe_resource *pResource, + void *user_buffer, + uint8_t TextureType, + unsigned Level, + unsigned Layer, + D3DSURFACE_DESC *pDesc ); + +void +NineSurface9_dtor( struct NineSurface9 *This ); + +/*** Nine private ***/ + +void +NineSurface9_MarkContainerDirty( struct NineSurface9 *This ); + +static inline struct pipe_surface * +NineSurface9_GetSurface( struct NineSurface9 *This, int sRGB ) +{ + assert(This->surface[sRGB]); + return This->surface[sRGB]; +} + +static inline struct pipe_resource * +NineSurface9_GetResource( struct NineSurface9 *This ) +{ + return This->base.resource; +} + +void +NineSurface9_SetResource( struct NineSurface9 *This, + struct pipe_resource *resource, unsigned level ); + +void +NineSurface9_SetMultiSampleType( struct NineSurface9 *This, + D3DMULTISAMPLE_TYPE mst ); + +void +NineSurface9_SetResourceResize( struct NineSurface9 *This, + struct pipe_resource *resource ); + +void +NineSurface9_AddDirtyRect( struct NineSurface9 *This, + const struct pipe_box *box ); + +HRESULT +NineSurface9_UploadSelf( struct NineSurface9 *This, + const struct pipe_box *damaged ); + +void +NineSurface9_CopyMemToDefault( struct NineSurface9 *This, + struct NineSurface9 *From, + const POINT *pDestPoint, + const RECT *pSourceRect ); + +void +NineSurface9_CopyDefaultToMem( struct NineSurface9 *This, + struct NineSurface9 *From ); + +static inline boolean +NineSurface9_IsOffscreenPlain (struct NineSurface9 *This ) +{ + return This->base.usage == 0 && !This->texture; +} + +#if defined(DEBUG) || !defined(NDEBUG) +void +NineSurface9_Dump( struct NineSurface9 *This ); +#else +static inline void +NineSurface9_Dump( struct NineSurface9 *This ) { } +#endif + +/*** Direct3D public ***/ + +HRESULT NINE_WINAPI +NineSurface9_GetContainer( struct NineSurface9 *This, + REFIID riid, + void **ppContainer ); + +HRESULT NINE_WINAPI +NineSurface9_GetDesc( struct NineSurface9 *This, + D3DSURFACE_DESC *pDesc ); + +HRESULT NINE_WINAPI +NineSurface9_LockRect( struct NineSurface9 *This, + D3DLOCKED_RECT *pLockedRect, + const RECT *pRect, + DWORD Flags ); + +HRESULT NINE_WINAPI +NineSurface9_UnlockRect( struct NineSurface9 *This ); + +HRESULT NINE_WINAPI +NineSurface9_GetDC( struct NineSurface9 *This, + HDC *phdc ); + +HRESULT NINE_WINAPI +NineSurface9_ReleaseDC( struct NineSurface9 *This, + HDC hdc ); + +#endif /* _NINE_SURFACE9_H_ */ diff --git a/src/gallium/frontends/nine/swapchain9.c b/src/gallium/frontends/nine/swapchain9.c new file mode 100644 index 00000000000..e3426b481cd --- /dev/null +++ b/src/gallium/frontends/nine/swapchain9.c @@ -0,0 +1,1300 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "swapchain9.h" +#include "surface9.h" +#include "device9.h" + +#include "nine_helpers.h" +#include "nine_pipe.h" +#include "nine_dump.h" + +#include "util/u_atomic.h" +#include "util/u_inlines.h" +#include "util/u_surface.h" +#include "hud/hud_context.h" +#include "frontend/drm_driver.h" + +#include "threadpool.h" + +#define DBG_CHANNEL DBG_SWAPCHAIN + +#define UNTESTED(n) DBG("UNTESTED point %d. Please tell if it worked\n", n) + +HRESULT +NineSwapChain9_ctor( struct NineSwapChain9 *This, + struct NineUnknownParams *pParams, + BOOL implicit, + ID3DPresent *pPresent, + D3DPRESENT_PARAMETERS *pPresentationParameters, + struct d3dadapter9_context *pCTX, + HWND hFocusWindow, + D3DDISPLAYMODEEX *mode ) +{ + HRESULT hr; + int i; + + DBG("This=%p pDevice=%p pPresent=%p pCTX=%p hFocusWindow=%p\n", + This, pParams->device, pPresent, pCTX, hFocusWindow); + + hr = NineUnknown_ctor(&This->base, pParams); + if (FAILED(hr)) + return hr; + + This->screen = NineDevice9_GetScreen(This->base.device); + This->implicit = implicit; + This->actx = pCTX; + This->present = pPresent; + This->mode = NULL; + + ID3DPresent_AddRef(pPresent); + if (This->base.device->minor_version_num > 2) { + D3DPRESENT_PARAMETERS2 params2; + + memset(¶ms2, 0, sizeof(D3DPRESENT_PARAMETERS2)); + params2.AllowDISCARDDelayedRelease = This->actx->discard_delayed_release; + params2.TearFreeDISCARD = This->actx->tearfree_discard; + ID3DPresent_SetPresentParameters2(pPresent, ¶ms2); + } + + if (!pPresentationParameters->hDeviceWindow) + pPresentationParameters->hDeviceWindow = hFocusWindow; + + This->rendering_done = FALSE; + This->pool = NULL; + for (i = 0; i < D3DPRESENT_BACK_BUFFERS_MAX_EX + 1; i++) { + This->pending_presentation[i] = calloc(1, sizeof(BOOL)); + if (!This->pending_presentation[i]) + return E_OUTOFMEMORY; + } + return NineSwapChain9_Resize(This, pPresentationParameters, mode); +} + +static D3DWindowBuffer * +D3DWindowBuffer_create(struct NineSwapChain9 *This, + struct pipe_resource *resource, + int depth, + int for_frontbuffer_reading) +{ + D3DWindowBuffer *ret; + struct pipe_context *pipe = nine_context_get_pipe_acquire(This->base.device); + struct winsys_handle whandle; + int stride, dmaBufFd; + HRESULT hr; + + memset(&whandle, 0, sizeof(whandle)); + whandle.type = WINSYS_HANDLE_TYPE_FD; + This->screen->resource_get_handle(This->screen, pipe, resource, + &whandle, + for_frontbuffer_reading ? + PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE : + PIPE_HANDLE_USAGE_EXPLICIT_FLUSH); + nine_context_get_pipe_release(This->base.device); + stride = whandle.stride; + dmaBufFd = whandle.handle; + hr = ID3DPresent_NewD3DWindowBufferFromDmaBuf(This->present, + dmaBufFd, + resource->width0, + resource->height0, + stride, + depth, + 32, + &ret); + assert (SUCCEEDED(hr)); + + if (FAILED(hr)) { + ERR("Failed to create new D3DWindowBufferFromDmaBuf\n"); + return NULL; + } + return ret; +} + +static void +D3DWindowBuffer_release(struct NineSwapChain9 *This, + D3DWindowBuffer *present_handle) +{ + int i; + + /* IsBufferReleased API not available */ + if (This->base.device->minor_version_num <= 2) { + ID3DPresent_DestroyD3DWindowBuffer(This->present, present_handle); + return; + } + + /* Add it to the 'pending release' list */ + for (i = 0; i < D3DPRESENT_BACK_BUFFERS_MAX_EX + 1; i++) { + if (!This->present_handles_pending_release[i]) { + This->present_handles_pending_release[i] = present_handle; + break; + } + } + if (i == (D3DPRESENT_BACK_BUFFERS_MAX_EX + 1)) { + ERR("Server not releasing buffers...\n"); + assert(false); + } + + /* Destroy elements of the list released by the server */ + for (i = 0; i < D3DPRESENT_BACK_BUFFERS_MAX_EX + 1; i++) { + if (This->present_handles_pending_release[i] && + ID3DPresent_IsBufferReleased(This->present, This->present_handles_pending_release[i])) { + /* WaitBufferReleased also waits the presentation feedback + * (which should arrive at about the same time), + * while IsBufferReleased doesn't. DestroyD3DWindowBuffer unfortunately + * checks it to release immediately all data, else the release + * is postponed for This->present release. To avoid leaks (we may handle + * a lot of resize), call WaitBufferReleased. */ + ID3DPresent_WaitBufferReleased(This->present, This->present_handles_pending_release[i]); + ID3DPresent_DestroyD3DWindowBuffer(This->present, This->present_handles_pending_release[i]); + This->present_handles_pending_release[i] = NULL; + } + } +} + +static int +NineSwapChain9_GetBackBufferCountForParams( struct NineSwapChain9 *This, + D3DPRESENT_PARAMETERS *pParams ); + +HRESULT +NineSwapChain9_Resize( struct NineSwapChain9 *This, + D3DPRESENT_PARAMETERS *pParams, + D3DDISPLAYMODEEX *mode ) +{ + struct NineDevice9 *pDevice = This->base.device; + D3DSURFACE_DESC desc; + HRESULT hr; + struct pipe_resource *resource, tmplt; + enum pipe_format pf; + BOOL has_present_buffers = FALSE; + int depth; + unsigned i, oldBufferCount, newBufferCount; + D3DMULTISAMPLE_TYPE multisample_type; + + DBG("This=%p pParams=%p\n", This, pParams); + user_assert(pParams != NULL, E_POINTER); + user_assert(pParams->SwapEffect, D3DERR_INVALIDCALL); + user_assert((pParams->SwapEffect != D3DSWAPEFFECT_COPY) || + (pParams->BackBufferCount <= 1), D3DERR_INVALIDCALL); + user_assert(pDevice->ex || pParams->BackBufferCount <= + D3DPRESENT_BACK_BUFFERS_MAX, D3DERR_INVALIDCALL); + user_assert(!pDevice->ex || pParams->BackBufferCount <= + D3DPRESENT_BACK_BUFFERS_MAX_EX, D3DERR_INVALIDCALL); + user_assert(pDevice->ex || + (pParams->SwapEffect == D3DSWAPEFFECT_FLIP) || + (pParams->SwapEffect == D3DSWAPEFFECT_COPY) || + (pParams->SwapEffect == D3DSWAPEFFECT_DISCARD), D3DERR_INVALIDCALL); + + DBG("pParams(%p):\n" + "BackBufferWidth: %u\n" + "BackBufferHeight: %u\n" + "BackBufferFormat: %s\n" + "BackBufferCount: %u\n" + "MultiSampleType: %u\n" + "MultiSampleQuality: %u\n" + "SwapEffect: %u\n" + "hDeviceWindow: %p\n" + "Windowed: %i\n" + "EnableAutoDepthStencil: %i\n" + "AutoDepthStencilFormat: %s\n" + "Flags: %s\n" + "FullScreen_RefreshRateInHz: %u\n" + "PresentationInterval: %x\n", pParams, + pParams->BackBufferWidth, pParams->BackBufferHeight, + d3dformat_to_string(pParams->BackBufferFormat), + pParams->BackBufferCount, + pParams->MultiSampleType, pParams->MultiSampleQuality, + pParams->SwapEffect, pParams->hDeviceWindow, pParams->Windowed, + pParams->EnableAutoDepthStencil, + d3dformat_to_string(pParams->AutoDepthStencilFormat), + nine_D3DPRESENTFLAG_to_str(pParams->Flags), + pParams->FullScreen_RefreshRateInHz, + pParams->PresentationInterval); + + if (pParams->BackBufferCount == 0) { + pParams->BackBufferCount = 1; + } + + if (pParams->BackBufferFormat == D3DFMT_UNKNOWN) { + pParams->BackBufferFormat = D3DFMT_A8R8G8B8; + } + + This->desired_fences = This->actx->throttling ? This->actx->throttling_value + 1 : 0; + /* +1 because we add the fence of the current buffer before popping an old one */ + if (This->desired_fences > DRI_SWAP_FENCES_MAX) + This->desired_fences = DRI_SWAP_FENCES_MAX; + + if (This->actx->vblank_mode == 0) + pParams->PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; + else if (This->actx->vblank_mode == 3) + pParams->PresentationInterval = D3DPRESENT_INTERVAL_ONE; + + if (mode && This->mode) { + *(This->mode) = *mode; + } else if (mode) { + This->mode = malloc(sizeof(D3DDISPLAYMODEEX)); + memcpy(This->mode, mode, sizeof(D3DDISPLAYMODEEX)); + } else { + free(This->mode); + This->mode = NULL; + } + + /* Note: It is the role of the backend to fill if necessary + * BackBufferWidth and BackBufferHeight */ + hr = ID3DPresent_SetPresentParameters(This->present, pParams, This->mode); + if (hr != D3D_OK) + return hr; + + oldBufferCount = This->num_back_buffers; + newBufferCount = NineSwapChain9_GetBackBufferCountForParams(This, pParams); + + multisample_type = pParams->MultiSampleType; + + /* Map MultiSampleQuality to MultiSampleType */ + hr = d3dmultisample_type_check(This->screen, pParams->BackBufferFormat, + &multisample_type, + pParams->MultiSampleQuality, + NULL); + if (FAILED(hr)) { + return hr; + } + + pf = d3d9_to_pipe_format_checked(This->screen, pParams->BackBufferFormat, + PIPE_TEXTURE_2D, multisample_type, + PIPE_BIND_RENDER_TARGET, FALSE, FALSE); + + if (This->actx->linear_framebuffer || + (pf != PIPE_FORMAT_B8G8R8X8_UNORM && + pf != PIPE_FORMAT_B8G8R8A8_UNORM) || + pParams->SwapEffect != D3DSWAPEFFECT_DISCARD || + multisample_type >= 2 || + (This->actx->ref && This->actx->ref == This->screen)) + has_present_buffers = TRUE; + + /* Note: the buffer depth has to match the window depth. + * In practice, ARGB buffers can be used with windows + * of depth 24. Windows of depth 32 are extremely rare. + * So even if the buffer is ARGB, say it is depth 24. + * It is common practice, for example that's how + * glamor implements depth 24. + * TODO: handle windows with other depths. Not possible in the short term. + * For example 16 bits.*/ + depth = 24; + + memset(&tmplt, 0, sizeof(tmplt)); + tmplt.target = PIPE_TEXTURE_2D; + tmplt.width0 = pParams->BackBufferWidth; + tmplt.height0 = pParams->BackBufferHeight; + tmplt.depth0 = 1; + tmplt.last_level = 0; + tmplt.array_size = 1; + tmplt.usage = PIPE_USAGE_DEFAULT; + tmplt.flags = 0; + + desc.Type = D3DRTYPE_SURFACE; + desc.Pool = D3DPOOL_DEFAULT; + desc.MultiSampleType = pParams->MultiSampleType; + desc.MultiSampleQuality = pParams->MultiSampleQuality; + desc.Width = pParams->BackBufferWidth; + desc.Height = pParams->BackBufferHeight; + + for (i = 0; i < oldBufferCount; i++) { + if (This->tasks[i]) + _mesa_threadpool_wait_for_task(This->pool, &(This->tasks[i])); + } + memset(This->tasks, 0, sizeof(This->tasks)); + + if (This->pool) { + _mesa_threadpool_destroy(This, This->pool); + This->pool = NULL; + } + This->enable_threadpool = This->actx->thread_submit && (pParams->SwapEffect != D3DSWAPEFFECT_COPY); + if (This->enable_threadpool) + This->pool = _mesa_threadpool_create(This); + if (!This->pool) + This->enable_threadpool = FALSE; + + for (i = 0; i < oldBufferCount; i++) { + D3DWindowBuffer_release(This, This->present_handles[i]); + This->present_handles[i] = NULL; + if (This->present_buffers[i]) + pipe_resource_reference(&(This->present_buffers[i]), NULL); + } + + if (newBufferCount != oldBufferCount) { + for (i = newBufferCount; i < oldBufferCount; + ++i) + NineUnknown_Detach(NineUnknown(This->buffers[i])); + + for (i = oldBufferCount; i < newBufferCount; ++i) { + This->buffers[i] = NULL; + This->present_handles[i] = NULL; + } + } + This->num_back_buffers = newBufferCount; + + for (i = 0; i < newBufferCount; ++i) { + tmplt.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; + tmplt.nr_samples = multisample_type; + tmplt.nr_storage_samples = multisample_type; + if (!has_present_buffers) + tmplt.bind |= NINE_BIND_PRESENTBUFFER_FLAGS; + tmplt.format = d3d9_to_pipe_format_checked(This->screen, + pParams->BackBufferFormat, + PIPE_TEXTURE_2D, + tmplt.nr_samples, + tmplt.bind, FALSE, FALSE); + if (tmplt.format == PIPE_FORMAT_NONE) + return D3DERR_INVALIDCALL; + resource = This->screen->resource_create(This->screen, &tmplt); + if (!resource) { + DBG("Failed to create pipe_resource.\n"); + return D3DERR_OUTOFVIDEOMEMORY; + } + if (pParams->Flags & D3DPRESENTFLAG_LOCKABLE_BACKBUFFER) + resource->flags |= NINE_RESOURCE_FLAG_LOCKABLE; + if (This->buffers[i]) { + NineSurface9_SetMultiSampleType(This->buffers[i], desc.MultiSampleType); + NineSurface9_SetResourceResize(This->buffers[i], resource); + if (has_present_buffers) + pipe_resource_reference(&resource, NULL); + } else { + desc.Format = pParams->BackBufferFormat; + desc.Usage = D3DUSAGE_RENDERTARGET; + hr = NineSurface9_new(pDevice, NineUnknown(This), resource, NULL, 0, + 0, 0, &desc, &This->buffers[i]); + if (has_present_buffers) + pipe_resource_reference(&resource, NULL); + if (FAILED(hr)) { + DBG("Failed to create RT surface.\n"); + return hr; + } + This->buffers[i]->base.base.forward = FALSE; + } + if (has_present_buffers) { + tmplt.format = PIPE_FORMAT_B8G8R8X8_UNORM; + tmplt.bind = NINE_BIND_PRESENTBUFFER_FLAGS; + tmplt.nr_samples = 0; + tmplt.nr_storage_samples = 0; + if (This->actx->linear_framebuffer) + tmplt.bind |= PIPE_BIND_LINEAR; + if (pParams->SwapEffect != D3DSWAPEFFECT_DISCARD) + tmplt.bind |= PIPE_BIND_RENDER_TARGET; + resource = This->screen->resource_create(This->screen, &tmplt); + pipe_resource_reference(&(This->present_buffers[i]), resource); + } + This->present_handles[i] = D3DWindowBuffer_create(This, resource, depth, false); + pipe_resource_reference(&resource, NULL); + if (!This->present_handles[i]) { + return D3DERR_DRIVERINTERNALERROR; + } + } + if (pParams->EnableAutoDepthStencil) { + tmplt.bind = d3d9_get_pipe_depth_format_bindings(pParams->AutoDepthStencilFormat); + tmplt.nr_samples = multisample_type; + tmplt.nr_storage_samples = multisample_type; + tmplt.format = d3d9_to_pipe_format_checked(This->screen, + pParams->AutoDepthStencilFormat, + PIPE_TEXTURE_2D, + tmplt.nr_samples, + tmplt.bind, + FALSE, FALSE); + + if (tmplt.format == PIPE_FORMAT_NONE) + return D3DERR_INVALIDCALL; + + if (This->zsbuf) { + resource = This->screen->resource_create(This->screen, &tmplt); + if (!resource) { + DBG("Failed to create pipe_resource for depth buffer.\n"); + return D3DERR_OUTOFVIDEOMEMORY; + } + + NineSurface9_SetMultiSampleType(This->zsbuf, desc.MultiSampleType); + NineSurface9_SetResourceResize(This->zsbuf, resource); + pipe_resource_reference(&resource, NULL); + } else { + hr = NineDevice9_CreateDepthStencilSurface(pDevice, + pParams->BackBufferWidth, + pParams->BackBufferHeight, + pParams->AutoDepthStencilFormat, + pParams->MultiSampleType, + pParams->MultiSampleQuality, + 0, + (IDirect3DSurface9 **)&This->zsbuf, + NULL); + if (FAILED(hr)) { + DBG("Failed to create ZS surface.\n"); + return hr; + } + NineUnknown_ConvertRefToBind(NineUnknown(This->zsbuf)); + } + } + + This->params = *pParams; + + return D3D_OK; +} + +/* Throttling: code adapted from the dri state tracker */ + +/** + * swap_fences_pop_front - pull a fence from the throttle queue + * + * If the throttle queue is filled to the desired number of fences, + * pull fences off the queue until the number is less than the desired + * number of fences, and return the last fence pulled. + */ +static struct pipe_fence_handle * +swap_fences_pop_front(struct NineSwapChain9 *This) +{ + struct pipe_screen *screen = This->screen; + struct pipe_fence_handle *fence = NULL; + + if (This->desired_fences == 0) + return NULL; + + if (This->cur_fences >= This->desired_fences) { + screen->fence_reference(screen, &fence, This->swap_fences[This->tail]); + screen->fence_reference(screen, &This->swap_fences[This->tail++], NULL); + This->tail &= DRI_SWAP_FENCES_MASK; + --This->cur_fences; + } + return fence; +} + + +/** + * swap_fences_see_front - same than swap_fences_pop_front without + * pulling + * + */ + +static struct pipe_fence_handle * +swap_fences_see_front(struct NineSwapChain9 *This) +{ + struct pipe_screen *screen = This->screen; + struct pipe_fence_handle *fence = NULL; + + if (This->desired_fences == 0) + return NULL; + + if (This->cur_fences >= This->desired_fences) { + screen->fence_reference(screen, &fence, This->swap_fences[This->tail]); + } + return fence; +} + + +/** + * swap_fences_push_back - push a fence onto the throttle queue at the back + * + * push a fence onto the throttle queue and pull fences of the queue + * so that the desired number of fences are on the queue. + */ +static void +swap_fences_push_back(struct NineSwapChain9 *This, + struct pipe_fence_handle *fence) +{ + struct pipe_screen *screen = This->screen; + + if (!fence || This->desired_fences == 0) + return; + + while(This->cur_fences == This->desired_fences) + swap_fences_pop_front(This); + + This->cur_fences++; + screen->fence_reference(screen, &This->swap_fences[This->head++], + fence); + This->head &= DRI_SWAP_FENCES_MASK; +} + + +/** + * swap_fences_unref - empty the throttle queue + * + * pulls fences of the throttle queue until it is empty. + */ +static void +swap_fences_unref(struct NineSwapChain9 *This) +{ + struct pipe_screen *screen = This->screen; + + while(This->cur_fences) { + screen->fence_reference(screen, &This->swap_fences[This->tail++], NULL); + This->tail &= DRI_SWAP_FENCES_MASK; + --This->cur_fences; + } +} + +void +NineSwapChain9_dtor( struct NineSwapChain9 *This ) +{ + unsigned i; + + DBG("This=%p\n", This); + + if (This->pool) + _mesa_threadpool_destroy(This, This->pool); + + for (i = 0; i < D3DPRESENT_BACK_BUFFERS_MAX_EX + 1; i++) { + if (This->pending_presentation[i]) + FREE(This->pending_presentation[i]); + } + + for (i = 0; i < D3DPRESENT_BACK_BUFFERS_MAX_EX + 1; i++) { + if (This->present_handles_pending_release[i]) + ID3DPresent_DestroyD3DWindowBuffer(This->present, This->present_handles_pending_release[i]); + } + + for (i = 0; i < This->num_back_buffers; i++) { + if (This->buffers[i]) + NineUnknown_Detach(NineUnknown(This->buffers[i])); + if (This->present_handles[i]) + ID3DPresent_DestroyD3DWindowBuffer(This->present, This->present_handles[i]); + if (This->present_buffers[i]) + pipe_resource_reference(&(This->present_buffers[i]), NULL); + } + if (This->zsbuf) + NineUnknown_Unbind(NineUnknown(This->zsbuf)); + + if (This->present) + ID3DPresent_Release(This->present); + + swap_fences_unref(This); + NineUnknown_dtor(&This->base); +} + +static void +create_present_buffer( struct NineSwapChain9 *This, + unsigned int width, unsigned int height, + struct pipe_resource **resource, + D3DWindowBuffer **present_handle) +{ + struct pipe_resource tmplt; + + memset(&tmplt, 0, sizeof(tmplt)); + tmplt.target = PIPE_TEXTURE_2D; + tmplt.width0 = width; + tmplt.height0 = height; + tmplt.depth0 = 1; + tmplt.last_level = 0; + tmplt.array_size = 1; + tmplt.usage = PIPE_USAGE_DEFAULT; + tmplt.flags = 0; + tmplt.format = PIPE_FORMAT_B8G8R8X8_UNORM; + tmplt.bind = NINE_BIND_BACKBUFFER_FLAGS | + NINE_BIND_PRESENTBUFFER_FLAGS; + tmplt.nr_samples = 0; + if (This->actx->linear_framebuffer) + tmplt.bind |= PIPE_BIND_LINEAR; + *resource = This->screen->resource_create(This->screen, &tmplt); + + *present_handle = D3DWindowBuffer_create(This, *resource, 24, true); + + if (!*present_handle) { + pipe_resource_reference(resource, NULL); + } +} + +static void +handle_draw_cursor_and_hud( struct NineSwapChain9 *This, struct pipe_resource *resource) +{ + struct NineDevice9 *device = This->base.device; + struct pipe_blit_info blit; + struct pipe_context *pipe; + + if (device->cursor.software && device->cursor.visible && device->cursor.w) { + memset(&blit, 0, sizeof(blit)); + blit.src.resource = device->cursor.image; + blit.src.level = 0; + blit.src.format = device->cursor.image->format; + blit.src.box.x = 0; + blit.src.box.y = 0; + blit.src.box.z = 0; + blit.src.box.depth = 1; + blit.src.box.width = device->cursor.w; + blit.src.box.height = device->cursor.h; + + blit.dst.resource = resource; + blit.dst.level = 0; + blit.dst.format = resource->format; + blit.dst.box.z = 0; + blit.dst.box.depth = 1; + + blit.mask = PIPE_MASK_RGBA; + blit.filter = PIPE_TEX_FILTER_NEAREST; + blit.scissor_enable = FALSE; + + /* NOTE: blit messes up when box.x + box.width < 0, fix driver + * NOTE2: device->cursor.pos contains coordinates relative to the screen. + * This happens to be also the position of the cursor when we are fullscreen. + * We don't use sw cursor for Windowed mode */ + blit.dst.box.x = MAX2(device->cursor.pos.x, 0) - device->cursor.hotspot.x; + blit.dst.box.y = MAX2(device->cursor.pos.y, 0) - device->cursor.hotspot.y; + blit.dst.box.width = blit.src.box.width; + blit.dst.box.height = blit.src.box.height; + + DBG("Blitting cursor(%ux%u) to (%i,%i).\n", + blit.src.box.width, blit.src.box.height, + blit.dst.box.x, blit.dst.box.y); + + blit.alpha_blend = TRUE; + pipe = NineDevice9_GetPipe(This->base.device); + pipe->blit(pipe, &blit); + } + + if (device->hud && resource) { + /* Implicit use of context pipe */ + (void)NineDevice9_GetPipe(This->base.device); + hud_run(device->hud, NULL, resource); /* XXX: no offset */ + /* HUD doesn't clobber stipple */ + nine_state_restore_non_cso(device); + } +} + +struct end_present_struct { + struct pipe_screen *screen; + struct pipe_fence_handle *fence_to_wait; + ID3DPresent *present; + D3DWindowBuffer *present_handle; + BOOL *pending_presentation; + HWND hDestWindowOverride; +}; + +static void work_present(void *data) +{ + struct end_present_struct *work = data; + if (work->fence_to_wait) { + (void) work->screen->fence_finish(work->screen, NULL, work->fence_to_wait, PIPE_TIMEOUT_INFINITE); + work->screen->fence_reference(work->screen, &(work->fence_to_wait), NULL); + } + ID3DPresent_PresentBuffer(work->present, work->present_handle, work->hDestWindowOverride, NULL, NULL, NULL, 0); + p_atomic_set(work->pending_presentation, FALSE); + free(work); +} + +static void pend_present(struct NineSwapChain9 *This, + struct pipe_fence_handle *fence, + HWND hDestWindowOverride) +{ + struct end_present_struct *work = calloc(1, sizeof(struct end_present_struct)); + + work->screen = This->screen; + This->screen->fence_reference(This->screen, &work->fence_to_wait, fence); + work->present = This->present; + work->present_handle = This->present_handles[0]; + work->hDestWindowOverride = hDestWindowOverride; + work->pending_presentation = This->pending_presentation[0]; + p_atomic_set(work->pending_presentation, TRUE); + This->tasks[0] = _mesa_threadpool_queue_task(This->pool, work_present, work); + + return; +} + +static inline HRESULT +present( struct NineSwapChain9 *This, + const RECT *pSourceRect, + const RECT *pDestRect, + HWND hDestWindowOverride, + const RGNDATA *pDirtyRegion, + DWORD dwFlags ) +{ + struct pipe_context *pipe; + struct pipe_resource *resource; + struct pipe_fence_handle *fence; + HRESULT hr; + struct pipe_blit_info blit; + int target_width, target_height, target_depth, i; + + DBG("present: This=%p pSourceRect=%p pDestRect=%p " + "pDirtyRegion=%p hDestWindowOverride=%p" + "dwFlags=%d resource=%p\n", + This, pSourceRect, pDestRect, pDirtyRegion, + hDestWindowOverride, (int)dwFlags, This->buffers[0]->base.resource); + + if (pSourceRect) + DBG("pSourceRect = (%u..%u)x(%u..%u)\n", + pSourceRect->left, pSourceRect->right, + pSourceRect->top, pSourceRect->bottom); + if (pDestRect) + DBG("pDestRect = (%u..%u)x(%u..%u)\n", + pDestRect->left, pDestRect->right, + pDestRect->top, pDestRect->bottom); + + /* TODO: in the case the source and destination rect have different size: + * We need to allocate a new buffer, and do a blit to it to resize. + * We can't use the present_buffer for that since when we created it, + * we couldn't guess which size would have been needed. + * If pDestRect or pSourceRect is null, we have to check the sizes + * from the source size, and the destination window size. + * In this case, either resize rngdata, or pass NULL instead + */ + /* Note: This->buffers[0]->level should always be 0 */ + + if (This->rendering_done) + goto bypass_rendering; + + resource = This->buffers[0]->base.resource; + + if (This->params.SwapEffect == D3DSWAPEFFECT_DISCARD) + handle_draw_cursor_and_hud(This, resource); + + hr = ID3DPresent_GetWindowInfo(This->present, hDestWindowOverride, &target_width, &target_height, &target_depth); + (void)target_depth; + + /* Can happen with old Wine (presentation can still succeed), + * or at window destruction. + * Also disable for very old wine as D3DWindowBuffer_release + * cannot do the DestroyD3DWindowBuffer workaround. */ + if (FAILED(hr) || target_width == 0 || target_height == 0 || + This->base.device->minor_version_num <= 2) { + target_width = resource->width0; + target_height = resource->height0; + } + + /* Switch to using presentation buffers on window resize. + * Note: Most apps should resize the d3d back buffers when + * a window resize is detected, which will result in a call to + * NineSwapChain9_Resize. Thus everything will get released, + * and it will switch back to not using separate presentation + * buffers. */ + if (!This->present_buffers[0] && + (target_width != resource->width0 || target_height != resource->height0)) { + BOOL failure = false; + struct pipe_resource *new_resource[This->num_back_buffers]; + D3DWindowBuffer *new_handles[This->num_back_buffers]; + for (i = 0; i < This->num_back_buffers; i++) { + /* Note: if (!new_handles[i]), new_resource[i] + * gets released and contains NULL */ + create_present_buffer(This, target_width, target_height, &new_resource[i], &new_handles[i]); + if (!new_handles[i]) + failure = true; + } + if (failure) { + for (i = 0; i < This->num_back_buffers; i++) { + if (new_resource[i]) + pipe_resource_reference(&new_resource[i], NULL); + if (new_handles[i]) + D3DWindowBuffer_release(This, new_handles[i]); + } + } else { + for (i = 0; i < This->num_back_buffers; i++) { + D3DWindowBuffer_release(This, This->present_handles[i]); + This->present_handles[i] = new_handles[i]; + pipe_resource_reference(&This->present_buffers[i], new_resource[i]); + pipe_resource_reference(&new_resource[i], NULL); + } + } + } + + pipe = NineDevice9_GetPipe(This->base.device); + + if (This->present_buffers[0]) { + memset(&blit, 0, sizeof(blit)); + blit.src.resource = resource; + blit.src.level = 0; + blit.src.format = resource->format; + blit.src.box.z = 0; + blit.src.box.depth = 1; + blit.src.box.x = 0; + blit.src.box.y = 0; + blit.src.box.width = resource->width0; + blit.src.box.height = resource->height0; + + /* Reallocate a new presentation buffer if the target window + * size has changed */ + if (target_width != This->present_buffers[0]->width0 || + target_height != This->present_buffers[0]->height0) { + struct pipe_resource *new_resource; + D3DWindowBuffer *new_handle; + + create_present_buffer(This, target_width, target_height, &new_resource, &new_handle); + /* Switch to the new buffer */ + if (new_handle) { + D3DWindowBuffer_release(This, This->present_handles[0]); + This->present_handles[0] = new_handle; + pipe_resource_reference(&This->present_buffers[0], new_resource); + pipe_resource_reference(&new_resource, NULL); + } + } + + resource = This->present_buffers[0]; + + blit.dst.resource = resource; + blit.dst.level = 0; + blit.dst.format = resource->format; + blit.dst.box.z = 0; + blit.dst.box.depth = 1; + blit.dst.box.x = 0; + blit.dst.box.y = 0; + blit.dst.box.width = resource->width0; + blit.dst.box.height = resource->height0; + + blit.mask = PIPE_MASK_RGBA; + blit.filter = (blit.dst.box.width == blit.src.box.width && + blit.dst.box.height == blit.src.box.height) ? + PIPE_TEX_FILTER_NEAREST : PIPE_TEX_FILTER_LINEAR; + blit.scissor_enable = FALSE; + blit.alpha_blend = FALSE; + + pipe->blit(pipe, &blit); + } + + /* The resource we present has to resolve fast clears + * if needed (and other things) */ + pipe->flush_resource(pipe, resource); + + if (This->params.SwapEffect != D3DSWAPEFFECT_DISCARD) + handle_draw_cursor_and_hud(This, resource); + + fence = NULL; + pipe->flush(pipe, &fence, PIPE_FLUSH_END_OF_FRAME); + + /* Present now for thread_submit, because we have the fence. + * It's possible we return WASSTILLDRAWING and still Present, + * but it should be fine. */ + if (This->enable_threadpool) + pend_present(This, fence, hDestWindowOverride); + if (fence) { + swap_fences_push_back(This, fence); + This->screen->fence_reference(This->screen, &fence, NULL); + } + + This->rendering_done = TRUE; +bypass_rendering: + + if (dwFlags & D3DPRESENT_DONOTWAIT) { + UNTESTED(2); + BOOL still_draw = FALSE; + fence = swap_fences_see_front(This); + if (fence) { + still_draw = !This->screen->fence_finish(This->screen, NULL, fence, 0); + This->screen->fence_reference(This->screen, &fence, NULL); + } + if (still_draw) + return D3DERR_WASSTILLDRAWING; + } + + /* Throttle rendering if needed */ + fence = swap_fences_pop_front(This); + if (fence) { + (void) This->screen->fence_finish(This->screen, NULL, fence, PIPE_TIMEOUT_INFINITE); + This->screen->fence_reference(This->screen, &fence, NULL); + } + + This->rendering_done = FALSE; + + if (!This->enable_threadpool) { + This->tasks[0]=NULL; + + hr = ID3DPresent_PresentBuffer(This->present, This->present_handles[0], hDestWindowOverride, pSourceRect, pDestRect, pDirtyRegion, dwFlags); + + if (FAILED(hr)) { UNTESTED(3);return hr; } + } + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineSwapChain9_Present( struct NineSwapChain9 *This, + const RECT *pSourceRect, + const RECT *pDestRect, + HWND hDestWindowOverride, + const RGNDATA *pDirtyRegion, + DWORD dwFlags ) +{ + struct pipe_resource *res = NULL; + D3DWindowBuffer *handle_temp; + struct threadpool_task *task_temp; + BOOL *pending_presentation_temp; + int i; + HRESULT hr; + + DBG("This=%p pSourceRect=%p pDestRect=%p hDestWindowOverride=%p " + "pDirtyRegion=%p dwFlags=%d\n", + This, pSourceRect, pDestRect, hDestWindowOverride, + pDirtyRegion,dwFlags); + + if (This->base.device->ex) { + if (NineSwapChain9_GetOccluded(This)) { + DBG("Present is occluded. Returning S_PRESENT_OCCLUDED.\n"); + return S_PRESENT_OCCLUDED; + } + } else { + if (NineSwapChain9_GetOccluded(This) || + NineSwapChain9_ResolutionMismatch(This)) { + This->base.device->device_needs_reset = TRUE; + } + if (This->base.device->device_needs_reset) { + DBG("Device is lost. Returning D3DERR_DEVICELOST.\n"); + return D3DERR_DEVICELOST; + } + } + + nine_csmt_process(This->base.device); + + hr = present(This, pSourceRect, pDestRect, + hDestWindowOverride, pDirtyRegion, dwFlags); + if (hr == D3DERR_WASSTILLDRAWING) + return hr; + + if (This->base.device->minor_version_num > 2 && + This->actx->discard_delayed_release && + This->params.SwapEffect == D3DSWAPEFFECT_DISCARD && + This->params.PresentationInterval == D3DPRESENT_INTERVAL_IMMEDIATE) { + int next_buffer = -1; + + while (next_buffer == -1) { + /* Find a free backbuffer */ + for (i = 1; i < This->num_back_buffers; i++) { + if (!p_atomic_read(This->pending_presentation[i]) && + ID3DPresent_IsBufferReleased(This->present, This->present_handles[i])) { + DBG("Found buffer released: %d\n", i); + next_buffer = i; + break; + } + } + if (next_buffer == -1) { + DBG("Found no buffer released. Waiting for event\n"); + ID3DPresent_WaitBufferReleaseEvent(This->present); + } + } + + /* Free the task (we already checked it is finished) */ + if (This->tasks[next_buffer]) + _mesa_threadpool_wait_for_task(This->pool, &(This->tasks[next_buffer])); + assert(!*This->pending_presentation[next_buffer] && !This->tasks[next_buffer]); + This->tasks[next_buffer] = This->tasks[0]; + This->tasks[0] = NULL; + pending_presentation_temp = This->pending_presentation[next_buffer]; + This->pending_presentation[next_buffer] = This->pending_presentation[0]; + This->pending_presentation[0] = pending_presentation_temp; + + /* Switch with the released buffer */ + pipe_resource_reference(&res, This->buffers[0]->base.resource); + NineSurface9_SetResourceResize( + This->buffers[0], This->buffers[next_buffer]->base.resource); + NineSurface9_SetResourceResize( + This->buffers[next_buffer], res); + pipe_resource_reference(&res, NULL); + + if (This->present_buffers[0]) { + pipe_resource_reference(&res, This->present_buffers[0]); + pipe_resource_reference(&This->present_buffers[0], This->present_buffers[next_buffer]); + pipe_resource_reference(&This->present_buffers[next_buffer], res); + pipe_resource_reference(&res, NULL); + } + + handle_temp = This->present_handles[0]; + This->present_handles[0] = This->present_handles[next_buffer]; + This->present_handles[next_buffer] = handle_temp; + } else { + switch (This->params.SwapEffect) { + case D3DSWAPEFFECT_OVERLAY: /* Not implemented, fallback to FLIP */ + case D3DSWAPEFFECT_FLIPEX: /* Allows optimizations over FLIP for windowed mode. */ + case D3DSWAPEFFECT_DISCARD: /* Allows optimizations over FLIP */ + case D3DSWAPEFFECT_FLIP: + /* rotate the queue */ + pipe_resource_reference(&res, This->buffers[0]->base.resource); + for (i = 1; i < This->num_back_buffers; i++) { + NineSurface9_SetResourceResize(This->buffers[i - 1], + This->buffers[i]->base.resource); + } + NineSurface9_SetResourceResize( + This->buffers[This->num_back_buffers - 1], res); + pipe_resource_reference(&res, NULL); + + if (This->present_buffers[0]) { + pipe_resource_reference(&res, This->present_buffers[0]); + for (i = 1; i < This->num_back_buffers; i++) + pipe_resource_reference(&(This->present_buffers[i-1]), This->present_buffers[i]); + pipe_resource_reference(&(This->present_buffers[This->num_back_buffers - 1]), res); + pipe_resource_reference(&res, NULL); + } + + handle_temp = This->present_handles[0]; + for (i = 1; i < This->num_back_buffers; i++) { + This->present_handles[i-1] = This->present_handles[i]; + } + This->present_handles[This->num_back_buffers - 1] = handle_temp; + task_temp = This->tasks[0]; + for (i = 1; i < This->num_back_buffers; i++) { + This->tasks[i-1] = This->tasks[i]; + } + This->tasks[This->num_back_buffers - 1] = task_temp; + pending_presentation_temp = This->pending_presentation[0]; + for (i = 1; i < This->num_back_buffers; i++) { + This->pending_presentation[i-1] = This->pending_presentation[i]; + } + This->pending_presentation[This->num_back_buffers - 1] = pending_presentation_temp; + break; + + case D3DSWAPEFFECT_COPY: + /* do nothing */ + break; + } + + if (This->tasks[0]) + _mesa_threadpool_wait_for_task(This->pool, &(This->tasks[0])); + assert(!*This->pending_presentation[0]); + + ID3DPresent_WaitBufferReleased(This->present, This->present_handles[0]); + } + + This->base.device->context.changed.group |= NINE_STATE_FB; + + return hr; +} + +HRESULT NINE_WINAPI +NineSwapChain9_GetFrontBufferData( struct NineSwapChain9 *This, + IDirect3DSurface9 *pDestSurface ) +{ + struct NineSurface9 *dest_surface = NineSurface9(pDestSurface); + struct NineDevice9 *pDevice = This->base.device; + unsigned int width, height; + struct pipe_resource *temp_resource; + struct NineSurface9 *temp_surface; + D3DWindowBuffer *temp_handle; + D3DSURFACE_DESC desc; + HRESULT hr; + + DBG("GetFrontBufferData: This=%p pDestSurface=%p\n", + This, pDestSurface); + + user_assert(dest_surface->base.pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL); + + width = dest_surface->desc.Width; + height = dest_surface->desc.Height; + + /* Note: front window size and destination size are supposed + * to match. However it's not very clear what should get taken in Windowed + * mode. It may need a fix */ + create_present_buffer(This, width, height, &temp_resource, &temp_handle); + + if (!temp_resource || !temp_handle) { + return D3DERR_INVALIDCALL; + } + + desc.Type = D3DRTYPE_SURFACE; + desc.Pool = D3DPOOL_DEFAULT; + desc.MultiSampleType = D3DMULTISAMPLE_NONE; + desc.MultiSampleQuality = 0; + desc.Width = width; + desc.Height = height; + /* NineSurface9_CopyDefaultToMem needs same format. */ + desc.Format = dest_surface->desc.Format; + desc.Usage = D3DUSAGE_RENDERTARGET; + hr = NineSurface9_new(pDevice, NineUnknown(This), temp_resource, NULL, 0, + 0, 0, &desc, &temp_surface); + pipe_resource_reference(&temp_resource, NULL); + if (FAILED(hr)) { + DBG("Failed to create temp FrontBuffer surface.\n"); + return hr; + } + + ID3DPresent_FrontBufferCopy(This->present, temp_handle); + + NineSurface9_CopyDefaultToMem(dest_surface, temp_surface); + + ID3DPresent_DestroyD3DWindowBuffer(This->present, temp_handle); + NineUnknown_Destroy(NineUnknown(temp_surface)); + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineSwapChain9_GetBackBuffer( struct NineSwapChain9 *This, + UINT iBackBuffer, + D3DBACKBUFFER_TYPE Type, + IDirect3DSurface9 **ppBackBuffer ) +{ + DBG("GetBackBuffer: This=%p iBackBuffer=%d Type=%d ppBackBuffer=%p\n", + This, iBackBuffer, Type, ppBackBuffer); + (void)user_error(Type == D3DBACKBUFFER_TYPE_MONO); + /* don't touch ppBackBuffer on error */ + user_assert(ppBackBuffer != NULL, D3DERR_INVALIDCALL); + user_assert(iBackBuffer < This->params.BackBufferCount, D3DERR_INVALIDCALL); + + NineUnknown_AddRef(NineUnknown(This->buffers[iBackBuffer])); + *ppBackBuffer = (IDirect3DSurface9 *)This->buffers[iBackBuffer]; + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineSwapChain9_GetRasterStatus( struct NineSwapChain9 *This, + D3DRASTER_STATUS *pRasterStatus ) +{ + DBG("GetRasterStatus: This=%p pRasterStatus=%p\n", + This, pRasterStatus); + user_assert(pRasterStatus != NULL, E_POINTER); + return ID3DPresent_GetRasterStatus(This->present, pRasterStatus); +} + +HRESULT NINE_WINAPI +NineSwapChain9_GetDisplayMode( struct NineSwapChain9 *This, + D3DDISPLAYMODE *pMode ) +{ + D3DDISPLAYMODEEX mode; + D3DDISPLAYROTATION rot; + HRESULT hr; + + DBG("GetDisplayMode: This=%p pMode=%p\n", + This, pMode); + user_assert(pMode != NULL, E_POINTER); + + hr = ID3DPresent_GetDisplayMode(This->present, &mode, &rot); + if (SUCCEEDED(hr)) { + pMode->Width = mode.Width; + pMode->Height = mode.Height; + pMode->RefreshRate = mode.RefreshRate; + pMode->Format = mode.Format; + } + return hr; +} + +HRESULT NINE_WINAPI +NineSwapChain9_GetPresentParameters( struct NineSwapChain9 *This, + D3DPRESENT_PARAMETERS *pPresentationParameters ) +{ + DBG("GetPresentParameters: This=%p pPresentationParameters=%p\n", + This, pPresentationParameters); + user_assert(pPresentationParameters != NULL, E_POINTER); + *pPresentationParameters = This->params; + return D3D_OK; +} + +IDirect3DSwapChain9Vtbl NineSwapChain9_vtable = { + (void *)NineUnknown_QueryInterface, + (void *)NineUnknown_AddRef, + (void *)NineUnknown_Release, + (void *)NineSwapChain9_Present, + (void *)NineSwapChain9_GetFrontBufferData, + (void *)NineSwapChain9_GetBackBuffer, + (void *)NineSwapChain9_GetRasterStatus, + (void *)NineSwapChain9_GetDisplayMode, + (void *)NineUnknown_GetDevice, /* actually part of SwapChain9 iface */ + (void *)NineSwapChain9_GetPresentParameters +}; + +static const GUID *NineSwapChain9_IIDs[] = { + &IID_IDirect3DSwapChain9, + &IID_IUnknown, + NULL +}; + +HRESULT +NineSwapChain9_new( struct NineDevice9 *pDevice, + BOOL implicit, + ID3DPresent *pPresent, + D3DPRESENT_PARAMETERS *pPresentationParameters, + struct d3dadapter9_context *pCTX, + HWND hFocusWindow, + struct NineSwapChain9 **ppOut ) +{ + NINE_DEVICE_CHILD_NEW(SwapChain9, ppOut, pDevice, /* args */ + implicit, pPresent, pPresentationParameters, + pCTX, hFocusWindow, NULL); +} + +BOOL +NineSwapChain9_GetOccluded( struct NineSwapChain9 *This ) +{ + if (This->base.device->minor_version_num > 0) { + return ID3DPresent_GetWindowOccluded(This->present); + } + + return FALSE; +} + +BOOL +NineSwapChain9_ResolutionMismatch( struct NineSwapChain9 *This ) +{ + if (This->base.device->minor_version_num > 1) { + return ID3DPresent_ResolutionMismatch(This->present); + } + + return FALSE; +} + +HANDLE +NineSwapChain9_CreateThread( struct NineSwapChain9 *This, + void *pFuncAddress, + void *pParam ) +{ + if (This->base.device->minor_version_num > 1) { + return ID3DPresent_CreateThread(This->present, pFuncAddress, pParam); + } + + return NULL; +} + +void +NineSwapChain9_WaitForThread( struct NineSwapChain9 *This, + HANDLE thread ) +{ + if (This->base.device->minor_version_num > 1) { + (void) ID3DPresent_WaitForThread(This->present, thread); + } +} + +static int +NineSwapChain9_GetBackBufferCountForParams( struct NineSwapChain9 *This, + D3DPRESENT_PARAMETERS *pParams ) +{ + int count = pParams->BackBufferCount; + + /* When we have flip behaviour, d3d9 expects we get back the screen buffer when we flip. + * Here we don't get back the initial content of the screen. To emulate the behaviour + * we allocate an additional buffer */ + if (pParams->SwapEffect != D3DSWAPEFFECT_COPY) + count++; + /* With DISCARD, as there is no guarantee about the buffer contents, we can use + * an arbitrary number of buffers */ + if (pParams->SwapEffect == D3DSWAPEFFECT_DISCARD) { + /* thread_submit's can have maximum count or This->actx->throttling_value + 1 + * frames in flight being rendered and not shown. + * Do not let count decrease that number */ + if (This->actx->thread_submit && count < This->desired_fences) + count = This->desired_fences; + /* When we enable AllowDISCARDDelayedRelease, we must ensure + * to have at least 4 buffers to meet INTERVAL_IMMEDIATE, + * since the display server/compositor can hold 3 buffers + * without releasing them: + * . Buffer on screen. + * . Buffer scheduled kernel side to be next on screen. + * . Last buffer sent. */ + if (This->base.device->minor_version_num > 2 && + This->actx->discard_delayed_release && + pParams->PresentationInterval == D3DPRESENT_INTERVAL_IMMEDIATE) { + if (This->actx->thread_submit && count < 4) + count = 4; + /* When thread_submit is not used, 5 buffers are actually needed, + * because in case a pageflip is missed because rendering wasn't finished, + * the Xserver will hold 4 buffers. */ + else if (!This->actx->thread_submit && count < 5) + count = 5; + } + } + + return count; +} diff --git a/src/gallium/frontends/nine/swapchain9.h b/src/gallium/frontends/nine/swapchain9.h new file mode 100644 index 00000000000..a6146445bdd --- /dev/null +++ b/src/gallium/frontends/nine/swapchain9.h @@ -0,0 +1,158 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _NINE_SWAPCHAIN9_H_ +#define _NINE_SWAPCHAIN9_H_ + +#include "iunknown.h" +#include "adapter9.h" + +#include "d3dadapter/d3dadapter9.h" + +#include "threadpool.h" + +struct NineDevice9; +struct NineSurface9; +struct nine_winsys_swapchain; +struct blit_state; + +#define DRI_SWAP_FENCES_MAX 4 +#define DRI_SWAP_FENCES_MASK 3 + +struct NineSwapChain9 +{ + struct NineUnknown base; + + /* G3D stuff */ + struct pipe_screen *screen; + + /* presentation backend */ + ID3DPresent *present; + D3DPRESENT_PARAMETERS params; + D3DDISPLAYMODEEX *mode; + struct d3dadapter9_context *actx; + BOOL implicit; + unsigned num_back_buffers; + + /* buffer handles */ + struct NineSurface9 *buffers[D3DPRESENT_BACK_BUFFERS_MAX_EX + 1]; /* 0 to BackBufferCount-1 : the back buffers. BackBufferCount : additional buffer */ + struct pipe_resource *present_buffers[D3DPRESENT_BACK_BUFFERS_MAX_EX + 1]; + D3DWindowBuffer *present_handles[D3DPRESENT_BACK_BUFFERS_MAX_EX + 1]; + D3DWindowBuffer *present_handles_pending_release[D3DPRESENT_BACK_BUFFERS_MAX_EX + 1]; + + struct pipe_fence_handle *swap_fences[DRI_SWAP_FENCES_MAX]; + unsigned int cur_fences; + unsigned int head; + unsigned int tail; + unsigned int desired_fences; + + BOOL rendering_done; + + struct NineSurface9 *zsbuf; + + D3DGAMMARAMP gamma; + + struct threadpool *pool; + struct threadpool_task *tasks[D3DPRESENT_BACK_BUFFERS_MAX_EX + 1]; + BOOL *pending_presentation[D3DPRESENT_BACK_BUFFERS_MAX_EX + 1]; + BOOL enable_threadpool; +}; + +static inline struct NineSwapChain9 * +NineSwapChain9( void *data ) +{ + return (struct NineSwapChain9 *)data; +} + +HRESULT +NineSwapChain9_new( struct NineDevice9 *pDevice, + BOOL implicit, + ID3DPresent *pPresent, + D3DPRESENT_PARAMETERS *pPresentationParameters, + struct d3dadapter9_context *pCTX, + HWND hFocusWindow, + struct NineSwapChain9 **ppOut ); + +HRESULT +NineSwapChain9_ctor( struct NineSwapChain9 *This, + struct NineUnknownParams *pParams, + BOOL implicit, + ID3DPresent *pPresent, + D3DPRESENT_PARAMETERS *pPresentationParameters, + struct d3dadapter9_context *pCTX, + HWND hFocusWindow, + D3DDISPLAYMODEEX *mode ); + +void +NineSwapChain9_dtor( struct NineSwapChain9 *This ); + +HRESULT +NineSwapChain9_Resize( struct NineSwapChain9 *This, + D3DPRESENT_PARAMETERS *pParams, + D3DDISPLAYMODEEX *mode ); + +HRESULT NINE_WINAPI +NineSwapChain9_Present( struct NineSwapChain9 *This, + const RECT *pSourceRect, + const RECT *pDestRect, + HWND hDestWindowOverride, + const RGNDATA *pDirtyRegion, + DWORD dwFlags ); + +HRESULT NINE_WINAPI +NineSwapChain9_GetFrontBufferData( struct NineSwapChain9 *This, + IDirect3DSurface9 *pDestSurface ); + +HRESULT NINE_WINAPI +NineSwapChain9_GetBackBuffer( struct NineSwapChain9 *This, + UINT iBackBuffer, + D3DBACKBUFFER_TYPE Type, + IDirect3DSurface9 **ppBackBuffer ); + +HRESULT NINE_WINAPI +NineSwapChain9_GetRasterStatus( struct NineSwapChain9 *This, + D3DRASTER_STATUS *pRasterStatus ); + +HRESULT NINE_WINAPI +NineSwapChain9_GetDisplayMode( struct NineSwapChain9 *This, + D3DDISPLAYMODE *pMode ); + +HRESULT NINE_WINAPI +NineSwapChain9_GetPresentParameters( struct NineSwapChain9 *This, + D3DPRESENT_PARAMETERS *pPresentationParameters ); + +BOOL +NineSwapChain9_GetOccluded( struct NineSwapChain9 *This ); + +BOOL +NineSwapChain9_ResolutionMismatch( struct NineSwapChain9 *This ); + +HANDLE +NineSwapChain9_CreateThread( struct NineSwapChain9 *This, + void *pFuncAddress, + void *pParam ); + +void +NineSwapChain9_WaitForThread( struct NineSwapChain9 *This, + HANDLE thread ); + +#endif /* _NINE_SWAPCHAIN9_H_ */ diff --git a/src/gallium/frontends/nine/swapchain9ex.c b/src/gallium/frontends/nine/swapchain9ex.c new file mode 100644 index 00000000000..309402cbb7b --- /dev/null +++ b/src/gallium/frontends/nine/swapchain9ex.c @@ -0,0 +1,117 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "swapchain9ex.h" +#include "device9.h" + +#include "nine_helpers.h" + +#define DBG_CHANNEL DBG_SWAPCHAIN + +static HRESULT +NineSwapChain9Ex_ctor( struct NineSwapChain9Ex *This, + struct NineUnknownParams *pParams, + BOOL implicit, + ID3DPresent *pPresent, + D3DPRESENT_PARAMETERS *pPresentationParameters, + struct d3dadapter9_context *pCTX, + HWND hFocusWindow, + D3DDISPLAYMODEEX *mode ) +{ + DBG("This=%p pParams=%p implicit=%d pPresent=%p pPresentationParameters=%p " + "pCTX=%p hFocusWindow=%p mode=%p", + This, pParams, (int) implicit, pPresent, pPresentationParameters, pCTX, hFocusWindow, mode); + + return NineSwapChain9_ctor(&This->base, pParams, implicit, pPresent, + pPresentationParameters, pCTX, hFocusWindow, mode); +} + +static void +NineSwapChain9Ex_dtor( struct NineSwapChain9Ex *This ) +{ + NineSwapChain9_dtor(&This->base); +} + +HRESULT NINE_WINAPI +NineSwapChain9Ex_GetLastPresentCount( struct NineSwapChain9Ex *This, + UINT *pLastPresentCount ) +{ + STUB(D3DERR_INVALIDCALL); +} + +HRESULT NINE_WINAPI +NineSwapChain9Ex_GetPresentStats( struct NineSwapChain9Ex *This, + D3DPRESENTSTATS *pPresentationStatistics ) +{ + STUB(D3DERR_INVALIDCALL); +} + +HRESULT NINE_WINAPI +NineSwapChain9Ex_GetDisplayModeEx( struct NineSwapChain9Ex *This, + D3DDISPLAYMODEEX *pMode, + D3DDISPLAYROTATION *pRotation ) +{ + D3DDISPLAYROTATION rot; + + user_assert(pMode != NULL, E_POINTER); + if (!pRotation) { pRotation = &rot; } + + return ID3DPresent_GetDisplayMode(This->base.present, pMode, pRotation); +} + +IDirect3DSwapChain9ExVtbl NineSwapChain9Ex_vtable = { + (void *)NineUnknown_QueryInterface, + (void *)NineUnknown_AddRef, + (void *)NineUnknown_Release, + (void *)NineSwapChain9_Present, + (void *)NineSwapChain9_GetFrontBufferData, + (void *)NineSwapChain9_GetBackBuffer, + (void *)NineSwapChain9_GetRasterStatus, + (void *)NineSwapChain9_GetDisplayMode, + (void *)NineUnknown_GetDevice, /* actually part of NineSwapChain9 iface */ + (void *)NineSwapChain9_GetPresentParameters, + (void *)NineSwapChain9Ex_GetLastPresentCount, + (void *)NineSwapChain9Ex_GetPresentStats, + (void *)NineSwapChain9Ex_GetDisplayModeEx +}; + +static const GUID *NineSwapChain9Ex_IIDs[] = { + &IID_IDirect3DSwapChain9Ex, + &IID_IDirect3DSwapChain9, + &IID_IUnknown, + NULL +}; + +HRESULT +NineSwapChain9Ex_new( struct NineDevice9 *pDevice, + BOOL implicit, + ID3DPresent *pPresent, + D3DPRESENT_PARAMETERS *pPresentationParameters, + struct d3dadapter9_context *pCTX, + HWND hFocusWindow, + D3DDISPLAYMODEEX *mode, + struct NineSwapChain9Ex **ppOut ) +{ + NINE_DEVICE_CHILD_NEW(SwapChain9Ex, ppOut, pDevice, /* args */ + implicit, pPresent, pPresentationParameters, + pCTX, hFocusWindow, mode); +} diff --git a/src/gallium/frontends/nine/swapchain9ex.h b/src/gallium/frontends/nine/swapchain9ex.h new file mode 100644 index 00000000000..a15d9d2c01e --- /dev/null +++ b/src/gallium/frontends/nine/swapchain9ex.h @@ -0,0 +1,61 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _NINE_SWAPCHAIN9EX_H_ +#define _NINE_SWAPCHAIN9EX_H_ + +#include "swapchain9.h" + +struct NineSwapChain9Ex +{ + struct NineSwapChain9 base; +}; +static inline struct NineSwapChain9Ex * +NineSwapChain9Ex( void *data ) +{ + return (struct NineSwapChain9Ex *)data; +} + +HRESULT +NineSwapChain9Ex_new( struct NineDevice9 *pDevice, + BOOL implicit, + ID3DPresent *pPresent, + D3DPRESENT_PARAMETERS *pPresentationParameters, + struct d3dadapter9_context *pCTX, + HWND hFocusWindow, + D3DDISPLAYMODEEX *mode, + struct NineSwapChain9Ex **ppOut ); + +HRESULT NINE_WINAPI +NineSwapChain9Ex_GetLastPresentCount( struct NineSwapChain9Ex *This, + UINT *pLastPresentCount ); + +HRESULT NINE_WINAPI +NineSwapChain9Ex_GetPresentStats( struct NineSwapChain9Ex *This, + D3DPRESENTSTATS *pPresentationStatistics ); + +HRESULT NINE_WINAPI +NineSwapChain9Ex_GetDisplayModeEx( struct NineSwapChain9Ex *This, + D3DDISPLAYMODEEX *pMode, + D3DDISPLAYROTATION *pRotation ); + +#endif /* _NINE_SWAPCHAIN9EX_H_ */ diff --git a/src/gallium/frontends/nine/texture9.c b/src/gallium/frontends/nine/texture9.c new file mode 100644 index 00000000000..fca5e603230 --- /dev/null +++ b/src/gallium/frontends/nine/texture9.c @@ -0,0 +1,393 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "c99_alloca.h" + +#include "device9.h" +#include "surface9.h" +#include "texture9.h" +#include "nine_helpers.h" +#include "nine_pipe.h" +#include "nine_dump.h" + +#include "pipe/p_state.h" +#include "pipe/p_context.h" +#include "pipe/p_screen.h" +#include "util/u_inlines.h" +#include "util/u_resource.h" + +#define DBG_CHANNEL DBG_TEXTURE + +static HRESULT +NineTexture9_ctor( struct NineTexture9 *This, + struct NineUnknownParams *pParams, + UINT Width, UINT Height, UINT Levels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + HANDLE *pSharedHandle ) +{ + struct pipe_screen *screen = pParams->device->screen; + struct pipe_resource *info = &This->base.base.info; + enum pipe_format pf; + unsigned *level_offsets; + unsigned l; + D3DSURFACE_DESC sfdesc; + HRESULT hr; + void *user_buffer = NULL, *user_buffer_for_level; + + DBG("(%p) Width=%u Height=%u Levels=%u Usage=%s Format=%s Pool=%s " + "pSharedHandle=%p\n", This, Width, Height, Levels, + nine_D3DUSAGE_to_str(Usage), + d3dformat_to_string(Format), nine_D3DPOOL_to_str(Pool), pSharedHandle); + + user_assert(Width && Height, D3DERR_INVALIDCALL); + + /* pSharedHandle: can be non-null for ex only. + * D3DPOOL_SYSTEMMEM: Levels must be 1 + * D3DPOOL_DEFAULT: no restriction for Levels + * Other Pools are forbidden. */ + user_assert(!pSharedHandle || pParams->device->ex, D3DERR_INVALIDCALL); + user_assert(!pSharedHandle || + (Pool == D3DPOOL_SYSTEMMEM && Levels == 1) || + Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); + + user_assert(!(Usage & D3DUSAGE_AUTOGENMIPMAP) || + (Pool != D3DPOOL_SYSTEMMEM && Pool != D3DPOOL_SCRATCH && Levels <= 1), + D3DERR_INVALIDCALL); + + /* TODO: implement pSharedHandle for D3DPOOL_DEFAULT (cross process + * buffer sharing). + * + * Gem names may have fit but they're depreciated and won't work on render-nodes. + * One solution is to use shm buffers. We would use a /dev/shm file, fill the first + * values to tell it is a nine buffer, the size, which function created it, etc, + * and then it would contain the data. The handle would be a number, corresponding to + * the file to read (/dev/shm/nine-share-4 for example would be 4). + * + * Wine just ignores the argument, which works only if the app creates the handle + * and won't use it. Instead of failing, we support that situation by putting an + * invalid handle, that we would fail to import. Please note that we don't advertise + * the flag indicating the support for that feature, but apps seem to not care. + */ + + if (pSharedHandle && Pool == D3DPOOL_DEFAULT) { + if (!*pSharedHandle) { + DBG("Creating Texture with invalid handle. Importing will fail\n."); + *pSharedHandle = (HANDLE)1; /* Wine would keep it NULL */ + pSharedHandle = NULL; + } else { + ERR("Application tries to use cross-process sharing feature. Nine " + "doesn't support it"); + return D3DERR_INVALIDCALL; + } + } + + if (Usage & D3DUSAGE_AUTOGENMIPMAP) + Levels = 0; + + pf = d3d9_to_pipe_format_checked(screen, Format, PIPE_TEXTURE_2D, 0, + PIPE_BIND_SAMPLER_VIEW, FALSE, + Pool == D3DPOOL_SCRATCH); + + if (Format != D3DFMT_NULL && pf == PIPE_FORMAT_NONE) + return D3DERR_INVALIDCALL; + + if (compressed_format(Format)) { + const unsigned w = util_format_get_blockwidth(pf); + const unsigned h = util_format_get_blockheight(pf); + + user_assert(!(Width % w) && !(Height % h), D3DERR_INVALIDCALL); + } + + info->screen = screen; + info->target = PIPE_TEXTURE_2D; + info->format = pf; + info->width0 = Width; + info->height0 = Height; + info->depth0 = 1; + if (Levels) + info->last_level = Levels - 1; + else + info->last_level = util_logbase2(MAX2(Width, Height)); + info->array_size = 1; + info->nr_samples = 0; + info->nr_storage_samples = 0; + info->bind = PIPE_BIND_SAMPLER_VIEW; + info->usage = PIPE_USAGE_DEFAULT; + info->flags = 0; + + if (Usage & D3DUSAGE_RENDERTARGET) + info->bind |= PIPE_BIND_RENDER_TARGET; + if (Usage & D3DUSAGE_DEPTHSTENCIL) + info->bind |= PIPE_BIND_DEPTH_STENCIL; + + if (Usage & D3DUSAGE_DYNAMIC) { + info->usage = PIPE_USAGE_DYNAMIC; + } + + if (Usage & D3DUSAGE_SOFTWAREPROCESSING) + DBG("Application asked for Software Vertex Processing, " + "but this is unimplemented\n"); + + if (pSharedHandle && *pSharedHandle) { /* Pool == D3DPOOL_SYSTEMMEM */ + user_buffer = (void *)*pSharedHandle; + level_offsets = alloca(sizeof(unsigned) * (info->last_level + 1)); + (void) nine_format_get_size_and_offsets(pf, level_offsets, + Width, Height, + info->last_level); + } else if (Pool != D3DPOOL_DEFAULT) { + /* TODO: For D3DUSAGE_AUTOGENMIPMAP, it is likely we only have to + * allocate only for the first level, since it is the only lockable + * level. Check apps don't crash if we allocate smaller buffer (some + * apps access sublevels of texture even if they locked only first + * level) */ + level_offsets = alloca(sizeof(unsigned) * (info->last_level + 1)); + user_buffer = align_calloc( + nine_format_get_size_and_offsets(pf, level_offsets, + Width, Height, + info->last_level), 32); + This->managed_buffer = user_buffer; + if (!This->managed_buffer) + return E_OUTOFMEMORY; + } + + This->surfaces = CALLOC(info->last_level + 1, sizeof(*This->surfaces)); + if (!This->surfaces) + return E_OUTOFMEMORY; + + hr = NineBaseTexture9_ctor(&This->base, pParams, NULL, D3DRTYPE_TEXTURE, Format, Pool, Usage); + if (FAILED(hr)) + return hr; + This->base.pstype = (Height == 1) ? 1 : 0; + + /* Create all the surfaces right away. + * They manage backing storage, and transfers (LockRect) are deferred + * to them. + */ + sfdesc.Format = Format; + sfdesc.Type = D3DRTYPE_SURFACE; + sfdesc.Usage = Usage; + sfdesc.Pool = Pool; + sfdesc.MultiSampleType = D3DMULTISAMPLE_NONE; + sfdesc.MultiSampleQuality = 0; + + for (l = 0; l <= info->last_level; ++l) { + sfdesc.Width = u_minify(Width, l); + sfdesc.Height = u_minify(Height, l); + /* Some apps expect the memory to be allocated in + * continous blocks */ + user_buffer_for_level = user_buffer ? user_buffer + + level_offsets[l] : NULL; + + hr = NineSurface9_new(This->base.base.base.device, NineUnknown(This), + This->base.base.resource, user_buffer_for_level, + D3DRTYPE_TEXTURE, l, 0, + &sfdesc, &This->surfaces[l]); + if (FAILED(hr)) + return hr; + } + + /* Textures start initially dirty */ + This->dirty_rect.width = Width; + This->dirty_rect.height = Height; + This->dirty_rect.depth = 1; /* widht == 0 means empty, depth stays 1 */ + + if (pSharedHandle && !*pSharedHandle) {/* Pool == D3DPOOL_SYSTEMMEM */ + *pSharedHandle = This->surfaces[0]->data; + } + + return D3D_OK; +} + +static void +NineTexture9_dtor( struct NineTexture9 *This ) +{ + unsigned l; + + DBG("This=%p\n", This); + + if (This->surfaces) { + /* The surfaces should have 0 references and be unbound now. */ + for (l = 0; l <= This->base.base.info.last_level; ++l) + if (This->surfaces[l]) + NineUnknown_Destroy(&This->surfaces[l]->base.base); + FREE(This->surfaces); + } + + if (This->managed_buffer) + align_free(This->managed_buffer); + + NineBaseTexture9_dtor(&This->base); +} + +HRESULT NINE_WINAPI +NineTexture9_GetLevelDesc( struct NineTexture9 *This, + UINT Level, + D3DSURFACE_DESC *pDesc ) +{ + DBG("This=%p Level=%d pDesc=%p\n", This, Level, pDesc); + + user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); + user_assert(Level == 0 || !(This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP), + D3DERR_INVALIDCALL); + + *pDesc = This->surfaces[Level]->desc; + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineTexture9_GetSurfaceLevel( struct NineTexture9 *This, + UINT Level, + IDirect3DSurface9 **ppSurfaceLevel ) +{ + DBG("This=%p Level=%d ppSurfaceLevel=%p\n", This, Level, ppSurfaceLevel); + + user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); + user_assert(Level == 0 || !(This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP), + D3DERR_INVALIDCALL); + + NineUnknown_AddRef(NineUnknown(This->surfaces[Level])); + *ppSurfaceLevel = (IDirect3DSurface9 *)This->surfaces[Level]; + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineTexture9_LockRect( struct NineTexture9 *This, + UINT Level, + D3DLOCKED_RECT *pLockedRect, + const RECT *pRect, + DWORD Flags ) +{ + DBG("This=%p Level=%u pLockedRect=%p pRect=%p Flags=%d\n", + This, Level, pLockedRect, pRect, Flags); + + user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); + user_assert(Level == 0 || !(This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP), + D3DERR_INVALIDCALL); + + return NineSurface9_LockRect(This->surfaces[Level], pLockedRect, + pRect, Flags); +} + +HRESULT NINE_WINAPI +NineTexture9_UnlockRect( struct NineTexture9 *This, + UINT Level ) +{ + DBG("This=%p Level=%u\n", This, Level); + + user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); + + return NineSurface9_UnlockRect(This->surfaces[Level]); +} + +HRESULT NINE_WINAPI +NineTexture9_AddDirtyRect( struct NineTexture9 *This, + const RECT *pDirtyRect ) +{ + DBG("This=%p pDirtyRect=%p[(%u,%u)-(%u,%u)]\n", This, pDirtyRect, + pDirtyRect ? pDirtyRect->left : 0, pDirtyRect ? pDirtyRect->top : 0, + pDirtyRect ? pDirtyRect->right : 0, pDirtyRect ? pDirtyRect->bottom : 0); + + /* Tracking dirty regions on DEFAULT resources is pointless, + * because we always write to the final storage. Just marked it dirty in + * case we need to generate mip maps. + */ + if (This->base.base.pool == D3DPOOL_DEFAULT) { + if (This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP) { + This->base.dirty_mip = TRUE; + BASETEX_REGISTER_UPDATE(&This->base); + } + return D3D_OK; + } + + if (This->base.base.pool == D3DPOOL_MANAGED) { + This->base.managed.dirty = TRUE; + BASETEX_REGISTER_UPDATE(&This->base); + } + + if (!pDirtyRect) { + u_box_origin_2d(This->base.base.info.width0, + This->base.base.info.height0, &This->dirty_rect); + } else { + if (This->dirty_rect.width == 0) { + rect_to_pipe_box_clamp(&This->dirty_rect, pDirtyRect); + } else { + struct pipe_box box; + rect_to_pipe_box_clamp(&box, pDirtyRect); + u_box_union_2d(&This->dirty_rect, &This->dirty_rect, &box); + } + (void) u_box_clip_2d(&This->dirty_rect, &This->dirty_rect, + This->base.base.info.width0, + This->base.base.info.height0); + } + return D3D_OK; +} + +IDirect3DTexture9Vtbl NineTexture9_vtable = { + (void *)NineUnknown_QueryInterface, + (void *)NineUnknown_AddRef, + (void *)NineUnknown_Release, + (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */ + (void *)NineUnknown_SetPrivateData, + (void *)NineUnknown_GetPrivateData, + (void *)NineUnknown_FreePrivateData, + (void *)NineResource9_SetPriority, + (void *)NineResource9_GetPriority, + (void *)NineBaseTexture9_PreLoad, + (void *)NineResource9_GetType, + (void *)NineBaseTexture9_SetLOD, + (void *)NineBaseTexture9_GetLOD, + (void *)NineBaseTexture9_GetLevelCount, + (void *)NineBaseTexture9_SetAutoGenFilterType, + (void *)NineBaseTexture9_GetAutoGenFilterType, + (void *)NineBaseTexture9_GenerateMipSubLevels, + (void *)NineTexture9_GetLevelDesc, + (void *)NineTexture9_GetSurfaceLevel, + (void *)NineTexture9_LockRect, + (void *)NineTexture9_UnlockRect, + (void *)NineTexture9_AddDirtyRect +}; + +static const GUID *NineTexture9_IIDs[] = { + &IID_IDirect3DTexture9, + &IID_IDirect3DBaseTexture9, + &IID_IDirect3DResource9, + &IID_IUnknown, + NULL +}; + +HRESULT +NineTexture9_new( struct NineDevice9 *pDevice, + UINT Width, UINT Height, UINT Levels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + struct NineTexture9 **ppOut, + HANDLE *pSharedHandle ) +{ + NINE_DEVICE_CHILD_NEW(Texture9, ppOut, pDevice, + Width, Height, Levels, + Usage, Format, Pool, pSharedHandle); +} diff --git a/src/gallium/frontends/nine/texture9.h b/src/gallium/frontends/nine/texture9.h new file mode 100644 index 00000000000..3911f26d468 --- /dev/null +++ b/src/gallium/frontends/nine/texture9.h @@ -0,0 +1,76 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _NINE_TEXTURE9_H_ +#define _NINE_TEXTURE9_H_ + +#include "basetexture9.h" +#include "surface9.h" + +struct NineTexture9 +{ + struct NineBaseTexture9 base; + struct NineSurface9 **surfaces; + struct pipe_box dirty_rect; /* covers all mip levels */ + uint8_t *managed_buffer; +}; +static inline struct NineTexture9 * +NineTexture9( void *data ) +{ + return (struct NineTexture9 *)data; +} + +HRESULT +NineTexture9_new( struct NineDevice9 *pDevice, + UINT Width, UINT Height, UINT Levels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + struct NineTexture9 **ppOut, + HANDLE *pSharedHandle ); + +HRESULT NINE_WINAPI +NineTexture9_GetLevelDesc( struct NineTexture9 *This, + UINT Level, + D3DSURFACE_DESC *pDesc ); + +HRESULT NINE_WINAPI +NineTexture9_GetSurfaceLevel( struct NineTexture9 *This, + UINT Level, + IDirect3DSurface9 **ppSurfaceLevel ); + +HRESULT NINE_WINAPI +NineTexture9_LockRect( struct NineTexture9 *This, + UINT Level, + D3DLOCKED_RECT *pLockedRect, + const RECT *pRect, + DWORD Flags ); + +HRESULT NINE_WINAPI +NineTexture9_UnlockRect( struct NineTexture9 *This, + UINT Level ); + +HRESULT NINE_WINAPI +NineTexture9_AddDirtyRect( struct NineTexture9 *This, + const RECT *pDirtyRect ); + +#endif /* _NINE_TEXTURE9_H_ */ diff --git a/src/gallium/frontends/nine/threadpool.c b/src/gallium/frontends/nine/threadpool.c new file mode 100644 index 00000000000..eb852b65dc6 --- /dev/null +++ b/src/gallium/frontends/nine/threadpool.c @@ -0,0 +1,200 @@ +/* + * Copyright © 2012 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "swapchain9.h" +#include "surface9.h" +#include "device9.h" + +#include "nine_helpers.h" +#include "nine_pipe.h" +#include "nine_dump.h" + +#include "util/u_inlines.h" +#include "util/u_surface.h" +#include "hud/hud_context.h" +#include "frontend/drm_driver.h" + +#include "os/os_thread.h" +#include "threadpool.h" + +/* POSIX thread function */ +static void * +threadpool_worker(void *data) +{ + struct threadpool *pool = data; + + pthread_mutex_lock(&pool->m); + + while (!pool->shutdown) { + struct threadpool_task *task; + + /* Block (dropping the lock) until new work arrives for us. */ + while (!pool->workqueue && !pool->shutdown) + pthread_cond_wait(&pool->new_work, &pool->m); + + if (pool->shutdown) + break; + + /* Pull the first task from the list. We don't free it -- it now lacks + * a reference other than the worker creator's, whose responsibility it + * is to call threadpool_wait_for_work() to free it. + */ + task = pool->workqueue; + pool->workqueue = task->next; + + /* Call the task's work func. */ + pthread_mutex_unlock(&pool->m); + task->work(task->data); + pthread_mutex_lock(&pool->m); + task->finished = TRUE; + pthread_cond_broadcast(&task->finish); + } + + pthread_mutex_unlock(&pool->m); + + return NULL; +} + +/* Windows thread function */ +static DWORD NINE_WINAPI +wthreadpool_worker(void *data) +{ + threadpool_worker(data); + + return 0; +} + +struct threadpool * +_mesa_threadpool_create(struct NineSwapChain9 *swapchain) +{ + struct threadpool *pool = calloc(1, sizeof(*pool)); + + if (!pool) + return NULL; + + pthread_mutex_init(&pool->m, NULL); + pthread_cond_init(&pool->new_work, NULL); + + /* This uses WINE's CreateThread, so the thread function needs to use + * the Windows ABI */ + pool->wthread = NineSwapChain9_CreateThread(swapchain, wthreadpool_worker, pool); + if (!pool->wthread) { + /* using pthread as fallback */ + pthread_create(&pool->pthread, NULL, threadpool_worker, pool); + } + return pool; +} + +void +_mesa_threadpool_destroy(struct NineSwapChain9 *swapchain, struct threadpool *pool) +{ + if (!pool) + return; + + pthread_mutex_lock(&pool->m); + pool->shutdown = TRUE; + pthread_cond_broadcast(&pool->new_work); + pthread_mutex_unlock(&pool->m); + + if (pool->wthread) { + NineSwapChain9_WaitForThread(swapchain, pool->wthread); + } else { + pthread_join(pool->pthread, NULL); + } + + pthread_cond_destroy(&pool->new_work); + pthread_mutex_destroy(&pool->m); + free(pool); +} + +/** + * Queues a request for the work function to be asynchronously executed by the + * thread pool. + * + * The work func will get the "data" argument as its parameter -- any + * communication between the caller and the work function will occur through + * that. + * + * If there is an error, the work function is called immediately and NULL is + * returned. + */ +struct threadpool_task * +_mesa_threadpool_queue_task(struct threadpool *pool, + threadpool_task_func work, void *data) +{ + struct threadpool_task *task, *previous; + + if (!pool) { + work(data); + return NULL; + } + + task = calloc(1, sizeof(*task)); + if (!task) { + work(data); + return NULL; + } + + task->work = work; + task->data = data; + task->next = NULL; + pthread_cond_init(&task->finish, NULL); + + pthread_mutex_lock(&pool->m); + + if (!pool->workqueue) { + pool->workqueue = task; + } else { + previous = pool->workqueue; + while (previous && previous->next) + previous = previous->next; + + previous->next = task; + } + pthread_cond_signal(&pool->new_work); + pthread_mutex_unlock(&pool->m); + + return task; +} + +/** + * Blocks on the completion of the given task and frees the task. + */ +void +_mesa_threadpool_wait_for_task(struct threadpool *pool, + struct threadpool_task **task_handle) +{ + struct threadpool_task *task = *task_handle; + + if (!pool || !task) + return; + + pthread_mutex_lock(&pool->m); + while (!task->finished) + pthread_cond_wait(&task->finish, &pool->m); + pthread_mutex_unlock(&pool->m); + + pthread_cond_destroy(&task->finish); + free(task); + *task_handle = NULL; +} diff --git a/src/gallium/frontends/nine/threadpool.h b/src/gallium/frontends/nine/threadpool.h new file mode 100644 index 00000000000..6f8f8c455d0 --- /dev/null +++ b/src/gallium/frontends/nine/threadpool.h @@ -0,0 +1,60 @@ +/* + * Copyright © 2012 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef _THREADPOOL_H_ +#define _THREADPOOL_H_ + +#include + +struct NineSwapChain9; + +#define MAXTHREADS 1 + +struct threadpool { + pthread_mutex_t m; + pthread_cond_t new_work; + + HANDLE wthread; + pthread_t pthread; + struct threadpool_task *workqueue; + BOOL shutdown; +}; + +typedef void (*threadpool_task_func)(void *data); + +struct threadpool_task { + threadpool_task_func work; + void *data; + struct threadpool_task *next; + pthread_cond_t finish; + BOOL finished; +}; + +struct threadpool *_mesa_threadpool_create(struct NineSwapChain9 *swapchain); +void _mesa_threadpool_destroy(struct NineSwapChain9 *swapchain, struct threadpool *pool); +struct threadpool_task *_mesa_threadpool_queue_task(struct threadpool *pool, + threadpool_task_func func, + void *data); +void _mesa_threadpool_wait_for_task(struct threadpool *pool, + struct threadpool_task **task); +#endif diff --git a/src/gallium/frontends/nine/vertexbuffer9.c b/src/gallium/frontends/nine/vertexbuffer9.c new file mode 100644 index 00000000000..df1d1717539 --- /dev/null +++ b/src/gallium/frontends/nine/vertexbuffer9.c @@ -0,0 +1,126 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "vertexbuffer9.h" +#include "device9.h" +#include "nine_helpers.h" +#include "nine_pipe.h" + +#include "pipe/p_screen.h" +#include "pipe/p_context.h" +#include "pipe/p_state.h" +#include "pipe/p_defines.h" +#include "pipe/p_format.h" +#include "util/u_box.h" + +#define DBG_CHANNEL DBG_VERTEXBUFFER + +HRESULT +NineVertexBuffer9_ctor( struct NineVertexBuffer9 *This, + struct NineUnknownParams *pParams, + D3DVERTEXBUFFER_DESC *pDesc ) +{ + HRESULT hr; + + DBG("This=%p Size=0x%x Usage=%x Pool=%u\n", This, + pDesc->Size, pDesc->Usage, pDesc->Pool); + + hr = NineBuffer9_ctor(&This->base, pParams, D3DRTYPE_VERTEXBUFFER, + pDesc->Usage, pDesc->Size, pDesc->Pool); + if (FAILED(hr)) + return hr; + + pDesc->Type = D3DRTYPE_VERTEXBUFFER; + pDesc->Format = D3DFMT_VERTEXDATA; + This->desc = *pDesc; + + return D3D_OK; +} + +void +NineVertexBuffer9_dtor( struct NineVertexBuffer9 *This ) +{ + NineBuffer9_dtor(&This->base); +} + +struct pipe_resource * +NineVertexBuffer9_GetResource( struct NineVertexBuffer9 *This, unsigned *offset ) +{ + return NineBuffer9_GetResource(&This->base, offset); +} + +HRESULT NINE_WINAPI +NineVertexBuffer9_Lock( struct NineVertexBuffer9 *This, + UINT OffsetToLock, + UINT SizeToLock, + void **ppbData, + DWORD Flags ) +{ + return NineBuffer9_Lock(&This->base, OffsetToLock, SizeToLock, ppbData, Flags); +} + +HRESULT NINE_WINAPI +NineVertexBuffer9_Unlock( struct NineVertexBuffer9 *This ) +{ + return NineBuffer9_Unlock(&This->base); +} + +HRESULT NINE_WINAPI +NineVertexBuffer9_GetDesc( struct NineVertexBuffer9 *This, + D3DVERTEXBUFFER_DESC *pDesc ) +{ + user_assert(pDesc, E_POINTER); + *pDesc = This->desc; + return D3D_OK; +} + +IDirect3DVertexBuffer9Vtbl NineVertexBuffer9_vtable = { + (void *)NineUnknown_QueryInterface, + (void *)NineUnknown_AddRef, + (void *)NineUnknown_Release, + (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */ + (void *)NineUnknown_SetPrivateData, + (void *)NineUnknown_GetPrivateData, + (void *)NineUnknown_FreePrivateData, + (void *)NineResource9_SetPriority, + (void *)NineResource9_GetPriority, + (void *)NineResource9_PreLoad, + (void *)NineResource9_GetType, + (void *)NineVertexBuffer9_Lock, + (void *)NineVertexBuffer9_Unlock, + (void *)NineVertexBuffer9_GetDesc +}; + +static const GUID *NineVertexBuffer9_IIDs[] = { + &IID_IDirect3DVertexBuffer9, + &IID_IDirect3DResource9, + &IID_IUnknown, + NULL +}; + +HRESULT +NineVertexBuffer9_new( struct NineDevice9 *pDevice, + D3DVERTEXBUFFER_DESC *pDesc, + struct NineVertexBuffer9 **ppOut ) +{ + NINE_DEVICE_CHILD_NEW(VertexBuffer9, ppOut, /* args */ pDevice, pDesc); +} diff --git a/src/gallium/frontends/nine/vertexbuffer9.h b/src/gallium/frontends/nine/vertexbuffer9.h new file mode 100644 index 00000000000..2991dbadd07 --- /dev/null +++ b/src/gallium/frontends/nine/vertexbuffer9.h @@ -0,0 +1,79 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _NINE_VERTEXBUFFER9_H_ +#define _NINE_VERTEXBUFFER9_H_ +#include "resource9.h" +#include "buffer9.h" + +struct pipe_screen; +struct pipe_context; +struct pipe_transfer; + +struct NineVertexBuffer9 +{ + struct NineBuffer9 base; + + /* G3D */ + struct pipe_context *pipe; + D3DVERTEXBUFFER_DESC desc; +}; +static inline struct NineVertexBuffer9 * +NineVertexBuffer9( void *data ) +{ + return (struct NineVertexBuffer9 *)data; +} + +HRESULT +NineVertexBuffer9_new( struct NineDevice9 *pDevice, + D3DVERTEXBUFFER_DESC *pDesc, + struct NineVertexBuffer9 **ppOut ); + +HRESULT +NineVertexBuffer9_ctor( struct NineVertexBuffer9 *This, + struct NineUnknownParams *pParams, + D3DVERTEXBUFFER_DESC *pDesc ); + +void +NineVertexBuffer9_dtor( struct NineVertexBuffer9 *This ); +/*** Nine private ***/ + +struct pipe_resource * +NineVertexBuffer9_GetResource( struct NineVertexBuffer9 *This, unsigned *offset ); + +/*** Direct3D public ***/ + +HRESULT NINE_WINAPI +NineVertexBuffer9_Lock( struct NineVertexBuffer9 *This, + UINT OffsetToLock, + UINT SizeToLock, + void **ppbData, + DWORD Flags ); + +HRESULT NINE_WINAPI +NineVertexBuffer9_Unlock( struct NineVertexBuffer9 *This ); + +HRESULT NINE_WINAPI +NineVertexBuffer9_GetDesc( struct NineVertexBuffer9 *This, + D3DVERTEXBUFFER_DESC *pDesc ); + +#endif /* _NINE_VERTEXBUFFER9_H_ */ diff --git a/src/gallium/frontends/nine/vertexdeclaration9.c b/src/gallium/frontends/nine/vertexdeclaration9.c new file mode 100644 index 00000000000..9beeff290b3 --- /dev/null +++ b/src/gallium/frontends/nine/vertexdeclaration9.c @@ -0,0 +1,531 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "vertexdeclaration9.h" +#include "vertexbuffer9.h" +#include "device9.h" +#include "nine_helpers.h" +#include "nine_shader.h" + +#include "pipe/p_format.h" +#include "pipe/p_context.h" +#include "util/u_math.h" +#include "util/format/u_format.h" +#include "translate/translate.h" + +#define DBG_CHANNEL DBG_VERTEXDECLARATION + +static inline enum pipe_format decltype_format(BYTE type) +{ + switch (type) { + case D3DDECLTYPE_FLOAT1: return PIPE_FORMAT_R32_FLOAT; + case D3DDECLTYPE_FLOAT2: return PIPE_FORMAT_R32G32_FLOAT; + case D3DDECLTYPE_FLOAT3: return PIPE_FORMAT_R32G32B32_FLOAT; + case D3DDECLTYPE_FLOAT4: return PIPE_FORMAT_R32G32B32A32_FLOAT; + case D3DDECLTYPE_D3DCOLOR: return PIPE_FORMAT_B8G8R8A8_UNORM; + case D3DDECLTYPE_UBYTE4: return PIPE_FORMAT_R8G8B8A8_USCALED; + case D3DDECLTYPE_SHORT2: return PIPE_FORMAT_R16G16_SSCALED; + case D3DDECLTYPE_SHORT4: return PIPE_FORMAT_R16G16B16A16_SSCALED; + case D3DDECLTYPE_UBYTE4N: return PIPE_FORMAT_R8G8B8A8_UNORM; + case D3DDECLTYPE_SHORT2N: return PIPE_FORMAT_R16G16_SNORM; + case D3DDECLTYPE_SHORT4N: return PIPE_FORMAT_R16G16B16A16_SNORM; + case D3DDECLTYPE_USHORT2N: return PIPE_FORMAT_R16G16_UNORM; + case D3DDECLTYPE_USHORT4N: return PIPE_FORMAT_R16G16B16A16_UNORM; + case D3DDECLTYPE_UDEC3: return PIPE_FORMAT_R10G10B10X2_USCALED; + case D3DDECLTYPE_DEC3N: return PIPE_FORMAT_R10G10B10X2_SNORM; + case D3DDECLTYPE_FLOAT16_2: return PIPE_FORMAT_R16G16_FLOAT; + case D3DDECLTYPE_FLOAT16_4: return PIPE_FORMAT_R16G16B16A16_FLOAT; + default: + assert(!"Implementation error !"); + } + return PIPE_FORMAT_NONE; +} + +static inline unsigned decltype_size(BYTE type) +{ + switch (type) { + case D3DDECLTYPE_FLOAT1: return 1 * sizeof(float); + case D3DDECLTYPE_FLOAT2: return 2 * sizeof(float); + case D3DDECLTYPE_FLOAT3: return 3 * sizeof(float); + case D3DDECLTYPE_FLOAT4: return 4 * sizeof(float); + case D3DDECLTYPE_D3DCOLOR: return 1 * sizeof(DWORD); + case D3DDECLTYPE_UBYTE4: return 4 * sizeof(BYTE); + case D3DDECLTYPE_SHORT2: return 2 * sizeof(short); + case D3DDECLTYPE_SHORT4: return 4 * sizeof(short); + case D3DDECLTYPE_UBYTE4N: return 4 * sizeof(BYTE); + case D3DDECLTYPE_SHORT2N: return 2 * sizeof(short); + case D3DDECLTYPE_SHORT4N: return 4 * sizeof(short); + case D3DDECLTYPE_USHORT2N: return 2 * sizeof(short); + case D3DDECLTYPE_USHORT4N: return 4 * sizeof(short); + case D3DDECLTYPE_UDEC3: return 4; + case D3DDECLTYPE_DEC3N: return 4; + case D3DDECLTYPE_FLOAT16_2: return 2 * 2; + case D3DDECLTYPE_FLOAT16_4: return 4 * 2; + default: + assert(!"Implementation error !"); + } + return 0; +} + +/* Actually, arbitrary usage index values are permitted, but a + * simple lookup table won't work in that case. Let's just wait + * with making this more generic until we need it. + */ +static inline boolean +nine_d3ddeclusage_check(unsigned usage, unsigned usage_idx) +{ + switch (usage) { + case D3DDECLUSAGE_POSITIONT: + case D3DDECLUSAGE_TESSFACTOR: + case D3DDECLUSAGE_DEPTH: + case D3DDECLUSAGE_NORMAL: + case D3DDECLUSAGE_TANGENT: + case D3DDECLUSAGE_BINORMAL: + case D3DDECLUSAGE_POSITION: + case D3DDECLUSAGE_BLENDWEIGHT: + case D3DDECLUSAGE_BLENDINDICES: + case D3DDECLUSAGE_COLOR: + return TRUE; + case D3DDECLUSAGE_PSIZE: + case D3DDECLUSAGE_FOG: + case D3DDECLUSAGE_SAMPLE: + return usage_idx <= 0; + case D3DDECLUSAGE_TEXCOORD: + return usage_idx <= 15; + default: + return FALSE; + } +} + +#define NINE_DECLUSAGE_CASE0(n) case D3DDECLUSAGE_##n: return NINE_DECLUSAGE_##n +#define NINE_DECLUSAGE_CASEi(n) case D3DDECLUSAGE_##n: return NINE_DECLUSAGE_i(n, usage_idx) +uint16_t +nine_d3d9_to_nine_declusage(unsigned usage, unsigned usage_idx) +{ + if (!nine_d3ddeclusage_check(usage, usage_idx)) + ERR("D3DDECLUSAGE_%u[%u]\n",usage,usage_idx); + assert(nine_d3ddeclusage_check(usage, usage_idx)); + switch (usage) { + NINE_DECLUSAGE_CASEi(POSITION); + NINE_DECLUSAGE_CASEi(BLENDWEIGHT); + NINE_DECLUSAGE_CASEi(BLENDINDICES); + NINE_DECLUSAGE_CASEi(NORMAL); + NINE_DECLUSAGE_CASE0(PSIZE); + NINE_DECLUSAGE_CASEi(TEXCOORD); + NINE_DECLUSAGE_CASEi(TANGENT); + NINE_DECLUSAGE_CASEi(BINORMAL); + NINE_DECLUSAGE_CASE0(TESSFACTOR); + NINE_DECLUSAGE_CASEi(POSITIONT); + NINE_DECLUSAGE_CASEi(COLOR); + NINE_DECLUSAGE_CASE0(DEPTH); + NINE_DECLUSAGE_CASE0(FOG); + NINE_DECLUSAGE_CASE0(SAMPLE); + default: + assert(!"Invalid DECLUSAGE."); + return NINE_DECLUSAGE_NONE; + } +} + +static const char *nine_declusage_names[] = +{ + [NINE_DECLUSAGE_POSITION] = "POSITION", + [NINE_DECLUSAGE_BLENDWEIGHT] = "BLENDWEIGHT", + [NINE_DECLUSAGE_BLENDINDICES] = "BLENDINDICES", + [NINE_DECLUSAGE_NORMAL] = "NORMAL", + [NINE_DECLUSAGE_PSIZE] = "PSIZE", + [NINE_DECLUSAGE_TEXCOORD] = "TEXCOORD", + [NINE_DECLUSAGE_TANGENT] = "TANGENT", + [NINE_DECLUSAGE_BINORMAL] = "BINORMAL", + [NINE_DECLUSAGE_TESSFACTOR] = "TESSFACTOR", + [NINE_DECLUSAGE_POSITIONT] = "POSITIONT", + [NINE_DECLUSAGE_COLOR] = "DIFFUSE", + [NINE_DECLUSAGE_DEPTH] = "DEPTH", + [NINE_DECLUSAGE_FOG] = "FOG", + [NINE_DECLUSAGE_NONE] = "(NONE)", +}; +static inline const char * +nine_declusage_name(unsigned ndcl) +{ + return nine_declusage_names[ndcl % NINE_DECLUSAGE_COUNT]; +} + +HRESULT +NineVertexDeclaration9_ctor( struct NineVertexDeclaration9 *This, + struct NineUnknownParams *pParams, + const D3DVERTEXELEMENT9 *pElements ) +{ + const D3DCAPS9 *caps; + unsigned i, nelems; + DBG("This=%p pParams=%p pElements=%p\n", This, pParams, pElements); + + /* wine */ + for (nelems = 0; + pElements[nelems].Stream != 0xFF; + ++nelems) { + user_assert(pElements[nelems].Type != D3DDECLTYPE_UNUSED, E_FAIL); + user_assert(!(pElements[nelems].Offset & 3), E_FAIL); + } + + caps = NineDevice9_GetCaps(pParams->device); + user_assert(nelems <= caps->MaxStreams, D3DERR_INVALIDCALL); + + HRESULT hr = NineUnknown_ctor(&This->base, pParams); + if (FAILED(hr)) { return hr; } + + This->nelems = nelems; + This->decls = CALLOC(This->nelems+1, sizeof(D3DVERTEXELEMENT9)); + This->elems = CALLOC(This->nelems, sizeof(struct pipe_vertex_element)); + This->usage_map = CALLOC(This->nelems, sizeof(uint16_t)); + if (!This->decls || !This->elems || !This->usage_map) { return E_OUTOFMEMORY; } + memcpy(This->decls, pElements, sizeof(D3DVERTEXELEMENT9)*(This->nelems+1)); + + for (i = 0; i < This->nelems; ++i) { + uint16_t usage = nine_d3d9_to_nine_declusage(This->decls[i].Usage, + This->decls[i].UsageIndex); + This->usage_map[i] = usage; + + if (This->decls[i].Usage == D3DDECLUSAGE_POSITIONT) + This->position_t = TRUE; + + This->elems[i].src_offset = This->decls[i].Offset; + This->elems[i].instance_divisor = 0; + This->elems[i].vertex_buffer_index = This->decls[i].Stream; + This->elems[i].src_format = decltype_format(This->decls[i].Type); + /* XXX Remember Method (tesselation), Usage, UsageIndex */ + + DBG("VERTEXELEMENT[%u]: Stream=%u Offset=%u Type=%s DeclUsage=%s%d\n", i, + This->decls[i].Stream, + This->decls[i].Offset, + util_format_name(This->elems[i].src_format), + nine_declusage_name(usage), + usage / NINE_DECLUSAGE_COUNT); + } + + return D3D_OK; +} + +void +NineVertexDeclaration9_dtor( struct NineVertexDeclaration9 *This ) +{ + DBG("This=%p\n", This); + + FREE(This->decls); + FREE(This->elems); + FREE(This->usage_map); + + NineUnknown_dtor(&This->base); +} + +HRESULT NINE_WINAPI +NineVertexDeclaration9_GetDeclaration( struct NineVertexDeclaration9 *This, + D3DVERTEXELEMENT9 *pElement, + UINT *pNumElements ) +{ + if (!pElement) { + user_assert(pNumElements, D3DERR_INVALIDCALL); + *pNumElements = This->nelems+1; + return D3D_OK; + } + if (pNumElements) { *pNumElements = This->nelems+1; } + memcpy(pElement, This->decls, sizeof(D3DVERTEXELEMENT9)*(This->nelems+1)); + return D3D_OK; +} + +IDirect3DVertexDeclaration9Vtbl NineVertexDeclaration9_vtable = { + (void *)NineUnknown_QueryInterface, + (void *)NineUnknown_AddRef, + (void *)NineUnknown_Release, + (void *)NineUnknown_GetDevice, /* actually part of VertexDecl9 iface */ + (void *)NineVertexDeclaration9_GetDeclaration +}; + +static const GUID *NineVertexDeclaration9_IIDs[] = { + &IID_IDirect3DVertexDeclaration9, + &IID_IUnknown, + NULL +}; + +HRESULT +NineVertexDeclaration9_new( struct NineDevice9 *pDevice, + const D3DVERTEXELEMENT9 *pElements, + struct NineVertexDeclaration9 **ppOut ) +{ + NINE_DEVICE_CHILD_NEW(VertexDeclaration9, ppOut, /* args */ pDevice, pElements); +} + +HRESULT +NineVertexDeclaration9_new_from_fvf( struct NineDevice9 *pDevice, + DWORD FVF, + struct NineVertexDeclaration9 **ppOut ) +{ + D3DVERTEXELEMENT9 elems[16], decl_end = D3DDECL_END(); + unsigned texcount, i, betas, nelems = 0; + BYTE beta_index = 0xFF; + + switch (FVF & D3DFVF_POSITION_MASK) { + case D3DFVF_XYZ: /* simple XYZ */ + case D3DFVF_XYZB1: + case D3DFVF_XYZB2: + case D3DFVF_XYZB3: + case D3DFVF_XYZB4: + case D3DFVF_XYZB5: /* XYZ with beta values */ + elems[nelems].Type = D3DDECLTYPE_FLOAT3; + elems[nelems].Usage = D3DDECLUSAGE_POSITION; + elems[nelems].UsageIndex = 0; + ++nelems; + /* simple XYZ has no beta values. break. */ + if ((FVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) { break; } + + betas = (((FVF & D3DFVF_XYZB5)-D3DFVF_XYZB1)>>1)+1; + if (FVF & D3DFVF_LASTBETA_D3DCOLOR) { + beta_index = D3DDECLTYPE_D3DCOLOR; + } else if (FVF & D3DFVF_LASTBETA_UBYTE4) { + beta_index = D3DDECLTYPE_UBYTE4; + } else if ((FVF & D3DFVF_XYZB5) == D3DFVF_XYZB5) { + beta_index = D3DDECLTYPE_FLOAT1; + } + if (beta_index != 0xFF) { --betas; } + + if (betas > 0) { + switch (betas) { + case 1: elems[nelems].Type = D3DDECLTYPE_FLOAT1; break; + case 2: elems[nelems].Type = D3DDECLTYPE_FLOAT2; break; + case 3: elems[nelems].Type = D3DDECLTYPE_FLOAT3; break; + case 4: elems[nelems].Type = D3DDECLTYPE_FLOAT4; break; + default: + assert(!"Implementation error!"); + } + elems[nelems].Usage = D3DDECLUSAGE_BLENDWEIGHT; + elems[nelems].UsageIndex = 0; + ++nelems; + } + + if (beta_index != 0xFF) { + elems[nelems].Type = beta_index; + elems[nelems].Usage = D3DDECLUSAGE_BLENDINDICES; + elems[nelems].UsageIndex = 0; + ++nelems; + } + break; + + case D3DFVF_XYZW: /* simple XYZW */ + case D3DFVF_XYZRHW: /* pretransformed XYZW */ + elems[nelems].Type = D3DDECLTYPE_FLOAT4; + elems[nelems].Usage = + ((FVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZW) ? + D3DDECLUSAGE_POSITION : D3DDECLUSAGE_POSITIONT; + elems[nelems].UsageIndex = 0; + ++nelems; + break; + + default: + (void)user_error(!"Position doesn't match any known combination"); + } + + /* normals, psize and colors */ + if (FVF & D3DFVF_NORMAL) { + elems[nelems].Type = D3DDECLTYPE_FLOAT3; + elems[nelems].Usage = D3DDECLUSAGE_NORMAL; + elems[nelems].UsageIndex = 0; + ++nelems; + } + if (FVF & D3DFVF_PSIZE) { + elems[nelems].Type = D3DDECLTYPE_FLOAT1; + elems[nelems].Usage = D3DDECLUSAGE_PSIZE; + elems[nelems].UsageIndex = 0; + ++nelems; + } + if (FVF & D3DFVF_DIFFUSE) { + elems[nelems].Type = D3DDECLTYPE_D3DCOLOR; + elems[nelems].Usage = D3DDECLUSAGE_COLOR; + elems[nelems].UsageIndex = 0; + ++nelems; + } + if (FVF & D3DFVF_SPECULAR) { + elems[nelems].Type = D3DDECLTYPE_D3DCOLOR; + elems[nelems].Usage = D3DDECLUSAGE_COLOR; + elems[nelems].UsageIndex = 1; + ++nelems; + } + + /* textures */ + texcount = (FVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT; + if (user_error(texcount <= 8)) { texcount = 8; } + + for (i = 0; i < texcount; ++i) { + switch ((FVF >> (16+i*2)) & 0x3) { + case D3DFVF_TEXTUREFORMAT1: + elems[nelems].Type = D3DDECLTYPE_FLOAT1; + break; + + case D3DFVF_TEXTUREFORMAT2: + elems[nelems].Type = D3DDECLTYPE_FLOAT2; + break; + + case D3DFVF_TEXTUREFORMAT3: + elems[nelems].Type = D3DDECLTYPE_FLOAT3; + break; + + case D3DFVF_TEXTUREFORMAT4: + elems[nelems].Type = D3DDECLTYPE_FLOAT4; + break; + + default: + assert(!"Implementation error!"); + } + elems[nelems].Usage = D3DDECLUSAGE_TEXCOORD; + elems[nelems].UsageIndex = i; + ++nelems; + } + + /* fill out remaining data */ + for (i = 0; i < nelems; ++i) { + elems[i].Stream = 0; + elems[i].Offset = (i == 0) ? 0 : (elems[i-1].Offset + + decltype_size(elems[i-1].Type)); + elems[i].Method = D3DDECLMETHOD_DEFAULT; + } + elems[nelems++] = decl_end; + + NINE_DEVICE_CHILD_NEW(VertexDeclaration9, ppOut, /* args */ pDevice, elems); +} + +void +NineVertexDeclaration9_FillStreamOutputInfo( + struct NineVertexDeclaration9 *This, + struct nine_vs_output_info *ShaderOutputsInfo, + unsigned numOutputs, + struct pipe_stream_output_info *so ) +{ + unsigned so_outputs = 0; + int i, j; + + memset(so, 0, sizeof(struct pipe_stream_output_info)); + + for (i = 0; i < numOutputs; i++) { + BYTE output_semantic = ShaderOutputsInfo[i].output_semantic; + unsigned output_semantic_index = ShaderOutputsInfo[i].output_semantic_index; + + for (j = 0; j < This->nelems; j++) { + if ((This->decls[j].Usage == output_semantic || + (output_semantic == D3DDECLUSAGE_POSITION && + This->decls[j].Usage == D3DDECLUSAGE_POSITIONT)) && + This->decls[j].UsageIndex == output_semantic_index) { + DBG("Matching %s %d: o%d -> %d\n", + nine_declusage_name(nine_d3d9_to_nine_declusage(This->decls[j].Usage, 0)), + This->decls[j].UsageIndex, i, j); + so->output[so_outputs].register_index = ShaderOutputsInfo[i].output_index; + so->output[so_outputs].start_component = 0; + if (ShaderOutputsInfo[i].mask & 8) + so->output[so_outputs].num_components = 4; + else if (ShaderOutputsInfo[i].mask & 4) + so->output[so_outputs].num_components = 3; + else if (ShaderOutputsInfo[i].mask & 2) + so->output[so_outputs].num_components = 2; + else + so->output[so_outputs].num_components = 1; + so->output[so_outputs].output_buffer = 0; + so->output[so_outputs].dst_offset = so_outputs * sizeof(float[4])/4; + so->output[so_outputs].stream = 0; + so_outputs++; + break; + } + } + } + + so->num_outputs = so_outputs; + so->stride[0] = so_outputs * sizeof(float[4])/4; +} + +/* ProcessVertices runs stream output into a temporary buffer to capture + * all outputs. + * Now we have to convert them to the format and order set by the vertex + * declaration, for which we use u_translate. + * This is necessary if the vertex declaration contains elements using a + * non float32 format, because stream output only supports f32/u32/s32. + */ +HRESULT +NineVertexDeclaration9_ConvertStreamOutput( + struct NineVertexDeclaration9 *This, + struct NineVertexBuffer9 *pDstBuf, + UINT DestIndex, + UINT VertexCount, + void *pSrcBuf, + const struct pipe_stream_output_info *so ) +{ + struct translate *translate; + struct translate_key transkey; + HRESULT hr; + unsigned i; + void *dst_map; + + DBG("This=%p pDstBuf=%p DestIndex=%u VertexCount=%u pSrcBuf=%p so=%p\n", + This, pDstBuf, DestIndex, VertexCount, pSrcBuf, so); + + transkey.output_stride = 0; + for (i = 0; i < This->nelems; ++i) { + enum pipe_format format; + + switch (so->output[i].num_components) { + case 1: format = PIPE_FORMAT_R32_FLOAT; break; + case 2: format = PIPE_FORMAT_R32G32_FLOAT; break; + case 3: format = PIPE_FORMAT_R32G32B32_FLOAT; break; + default: + assert(so->output[i].num_components == 4); + format = PIPE_FORMAT_R32G32B32A32_FLOAT; + break; + } + transkey.element[i].type = TRANSLATE_ELEMENT_NORMAL; + transkey.element[i].input_format = format; + transkey.element[i].input_buffer = 0; + transkey.element[i].input_offset = so->output[i].dst_offset * 4; + transkey.element[i].instance_divisor = 0; + + transkey.element[i].output_format = This->elems[i].src_format; + transkey.element[i].output_offset = This->elems[i].src_offset; + transkey.output_stride += + util_format_get_blocksize(This->elems[i].src_format); + + assert(!(transkey.output_stride & 3)); + } + transkey.nr_elements = This->nelems; + + translate = translate_create(&transkey); + if (!translate) + return E_OUTOFMEMORY; + + hr = NineVertexBuffer9_Lock(pDstBuf, + transkey.output_stride * DestIndex, + transkey.output_stride * VertexCount, + &dst_map, D3DLOCK_DISCARD); + if (FAILED(hr)) + goto out; + + translate->set_buffer(translate, 0, pSrcBuf, so->stride[0] * 4, ~0); + + translate->run(translate, 0, VertexCount, 0, 0, dst_map); + + NineVertexBuffer9_Unlock(pDstBuf); +out: + translate->release(translate); /* TODO: cache these */ + return hr; +} diff --git a/src/gallium/frontends/nine/vertexdeclaration9.h b/src/gallium/frontends/nine/vertexdeclaration9.h new file mode 100644 index 00000000000..7b94f846fe7 --- /dev/null +++ b/src/gallium/frontends/nine/vertexdeclaration9.h @@ -0,0 +1,99 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _NINE_VERTEXDECLARATION9_H_ +#define _NINE_VERTEXDECLARATION9_H_ + +#include "nine_defines.h" +#include "iunknown.h" + +struct pipe_resource; +struct pipe_vertex_element; +struct pipe_stream_output_info; +struct NineDevice9; +struct NineVertexBuffer9; +struct nine_vs_output_info; + +struct NineVertexDeclaration9 +{ + struct NineUnknown base; + + /* G3D state */ + struct pipe_vertex_element *elems; + unsigned nelems; + + /* index -> DECLUSAGE, for selecting the vertex element + * for each VS input */ + uint16_t *usage_map; + + D3DVERTEXELEMENT9 *decls; + DWORD fvf; + + BOOL position_t; +}; +static inline struct NineVertexDeclaration9 * +NineVertexDeclaration9( void *data ) +{ + return (struct NineVertexDeclaration9 *)data; +} + +HRESULT +NineVertexDeclaration9_new( struct NineDevice9 *pDevice, + const D3DVERTEXELEMENT9 *pElements, + struct NineVertexDeclaration9 **ppOut ); + +HRESULT +NineVertexDeclaration9_new_from_fvf( struct NineDevice9 *pDevice, + DWORD FVF, + struct NineVertexDeclaration9 **ppOut ); + +HRESULT +NineVertexDeclaration9_ctor( struct NineVertexDeclaration9 *This, + struct NineUnknownParams *pParams, + const D3DVERTEXELEMENT9 *pElements ); + +void +NineVertexDeclaration9_dtor( struct NineVertexDeclaration9 *This ); + +HRESULT NINE_WINAPI +NineVertexDeclaration9_GetDeclaration( struct NineVertexDeclaration9 *This, + D3DVERTEXELEMENT9 *pElement, + UINT *pNumElements ); + +void +NineVertexDeclaration9_FillStreamOutputInfo( + struct NineVertexDeclaration9 *This, + struct nine_vs_output_info *ShaderOutputsInfo, + unsigned numOutputs, + struct pipe_stream_output_info *so ); + +/* Convert stream output data to the vertex declaration's format. */ +HRESULT +NineVertexDeclaration9_ConvertStreamOutput( + struct NineVertexDeclaration9 *This, + struct NineVertexBuffer9 *pDstBuf, + UINT DestIndex, + UINT VertexCount, + void *pSrcBuf, + const struct pipe_stream_output_info *so ); + +#endif /* _NINE_VERTEXDECLARATION9_H_ */ diff --git a/src/gallium/frontends/nine/vertexshader9.c b/src/gallium/frontends/nine/vertexshader9.c new file mode 100644 index 00000000000..600e298a393 --- /dev/null +++ b/src/gallium/frontends/nine/vertexshader9.c @@ -0,0 +1,304 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "nine_helpers.h" +#include "nine_shader.h" + +#include "vertexdeclaration9.h" +#include "vertexshader9.h" + +#include "device9.h" +#include "pipe/p_context.h" +#include "cso_cache/cso_context.h" + +#define DBG_CHANNEL DBG_VERTEXSHADER + +HRESULT +NineVertexShader9_ctor( struct NineVertexShader9 *This, + struct NineUnknownParams *pParams, + const DWORD *pFunction, void *cso ) +{ + struct NineDevice9 *device; + struct nine_shader_info info; + struct pipe_context *pipe; + HRESULT hr; + unsigned i; + + DBG("This=%p pParams=%p pFunction=%p cso=%p\n", + This, pParams, pFunction, cso); + + hr = NineUnknown_ctor(&This->base, pParams); + if (FAILED(hr)) + return hr; + + if (cso) { + This->ff_cso = cso; + return D3D_OK; + } + + device = This->base.device; + + info.type = PIPE_SHADER_VERTEX; + info.byte_code = pFunction; + info.const_i_base = NINE_CONST_I_BASE(device->max_vs_const_f) / 16; + info.const_b_base = NINE_CONST_B_BASE(device->max_vs_const_f) / 16; + info.sampler_mask_shadow = 0x0; + info.sampler_ps1xtypes = 0x0; + info.fog_enable = 0; + info.point_size_min = 0; + info.point_size_max = 0; + info.add_constants_defs.c_combination = NULL; + info.add_constants_defs.int_const_added = NULL; + info.add_constants_defs.bool_const_added = NULL; + info.swvp_on = !!(device->params.BehaviorFlags & D3DCREATE_SOFTWARE_VERTEXPROCESSING); + info.process_vertices = false; + + pipe = nine_context_get_pipe_acquire(device); + hr = nine_translate_shader(device, &info, pipe); + if (hr == D3DERR_INVALIDCALL && + (device->params.BehaviorFlags & D3DCREATE_MIXED_VERTEXPROCESSING)) { + /* Retry with a swvp shader. It will require swvp to be on. */ + info.swvp_on = true; + hr = nine_translate_shader(device, &info, pipe); + } + nine_context_get_pipe_release(device); + if (hr == D3DERR_INVALIDCALL) + ERR("Encountered buggy shader\n"); + if (FAILED(hr)) + return hr; + This->byte_code.version = info.version; + This->swvp_only = info.swvp_on; + + This->byte_code.tokens = mem_dup(pFunction, info.byte_size); + if (!This->byte_code.tokens) + return E_OUTOFMEMORY; + This->byte_code.size = info.byte_size; + + This->variant.cso = info.cso; + This->variant.const_ranges = info.const_ranges; + This->variant.const_used_size = info.const_used_size; + This->last_cso = info.cso; + This->last_const_ranges = info.const_ranges; + This->last_const_used_size = info.const_used_size; + This->last_key = (uint32_t) (info.swvp_on << 9); + + This->lconstf = info.lconstf; + This->sampler_mask = info.sampler_mask; + This->position_t = info.position_t; + This->point_size = info.point_size; + + memcpy(This->int_slots_used, info.int_slots_used, sizeof(This->int_slots_used)); + memcpy(This->bool_slots_used, info.bool_slots_used, sizeof(This->bool_slots_used)); + + This->const_int_slots = info.const_int_slots; + This->const_bool_slots = info.const_bool_slots; + + This->c_combinations = NULL; + + for (i = 0; i < info.num_inputs && i < ARRAY_SIZE(This->input_map); ++i) + This->input_map[i].ndecl = info.input_map[i]; + This->num_inputs = i; + + return D3D_OK; +} + +void +NineVertexShader9_dtor( struct NineVertexShader9 *This ) +{ + DBG("This=%p\n", This); + + if (This->base.device) { + struct pipe_context *pipe = nine_context_get_pipe_multithread(This->base.device); + struct nine_shader_variant *var = &This->variant; + struct nine_shader_variant_so *var_so = &This->variant_so; + + do { + if (var->cso) { + if (This->base.device->context.cso_shader.vs == var->cso) + pipe->bind_vs_state(pipe, NULL); + pipe->delete_vs_state(pipe, var->cso); + FREE(var->const_ranges); + } + var = var->next; + } while (var); + + while (var_so && var_so->vdecl) { + if (var_so->cso) { + This->base.device->pipe_sw->delete_vs_state(This->base.device->pipe_sw, var_so->cso); + } + var_so = var_so->next; + } + + if (This->ff_cso) { + if (This->ff_cso == This->base.device->context.cso_shader.vs) + pipe->bind_vs_state(pipe, NULL); + pipe->delete_vs_state(pipe, This->ff_cso); + } + } + nine_shader_variants_free(&This->variant); + nine_shader_variants_so_free(&This->variant_so); + + nine_shader_constant_combination_free(This->c_combinations); + + FREE((void *)This->byte_code.tokens); /* const_cast */ + + FREE(This->lconstf.data); + FREE(This->lconstf.ranges); + + NineUnknown_dtor(&This->base); +} + +HRESULT NINE_WINAPI +NineVertexShader9_GetFunction( struct NineVertexShader9 *This, + void *pData, + UINT *pSizeOfData ) +{ + user_assert(pSizeOfData, D3DERR_INVALIDCALL); + + if (!pData) { + *pSizeOfData = This->byte_code.size; + return D3D_OK; + } + user_assert(*pSizeOfData >= This->byte_code.size, D3DERR_INVALIDCALL); + + memcpy(pData, This->byte_code.tokens, This->byte_code.size); + + return D3D_OK; +} + +void * +NineVertexShader9_GetVariant( struct NineVertexShader9 *This, + unsigned **const_ranges, + unsigned *const_used_size ) +{ + /* GetVariant is called from nine_context, thus we can + * get pipe directly */ + struct pipe_context *pipe = This->base.device->context.pipe; + void *cso; + uint64_t key; + + key = This->next_key; + if (key == This->last_key) { + *const_ranges = This->last_const_ranges; + *const_used_size = This->last_const_used_size; + return This->last_cso; + } + + cso = nine_shader_variant_get(&This->variant, const_ranges, const_used_size, key); + if (!cso) { + struct NineDevice9 *device = This->base.device; + struct nine_shader_info info; + HRESULT hr; + + info.type = PIPE_SHADER_VERTEX; + info.const_i_base = NINE_CONST_I_BASE(device->max_vs_const_f) / 16; + info.const_b_base = NINE_CONST_B_BASE(device->max_vs_const_f) / 16; + info.byte_code = This->byte_code.tokens; + info.sampler_mask_shadow = key & 0xf; + info.fog_enable = device->context.rs[D3DRS_FOGENABLE]; + info.point_size_min = asfloat(device->context.rs[D3DRS_POINTSIZE_MIN]); + info.point_size_max = asfloat(device->context.rs[D3DRS_POINTSIZE_MAX]); + info.add_constants_defs.c_combination = + nine_shader_constant_combination_get(This->c_combinations, (key >> 16) & 0xff); + info.add_constants_defs.int_const_added = &This->int_slots_used; + info.add_constants_defs.bool_const_added = &This->bool_slots_used; + info.swvp_on = device->context.swvp; + info.process_vertices = false; + + hr = nine_translate_shader(This->base.device, &info, pipe); + if (FAILED(hr)) + return NULL; + nine_shader_variant_add(&This->variant, key, info.cso, + info.const_ranges, info.const_used_size); + cso = info.cso; + *const_ranges = info.const_ranges; + *const_used_size = info.const_used_size; + } + + This->last_key = key; + This->last_cso = cso; + This->last_const_ranges = *const_ranges; + This->last_const_used_size = *const_used_size; + + return cso; +} + +void * +NineVertexShader9_GetVariantProcessVertices( struct NineVertexShader9 *This, + struct NineVertexDeclaration9 *vdecl_out, + struct pipe_stream_output_info *so ) +{ + struct nine_shader_info info; + HRESULT hr; + void *cso; + + cso = nine_shader_variant_so_get(&This->variant_so, vdecl_out, so); + if (cso) + return cso; + + info.type = PIPE_SHADER_VERTEX; + info.const_i_base = 0; + info.const_b_base = 0; + info.byte_code = This->byte_code.tokens; + info.sampler_mask_shadow = 0; + info.fog_enable = false; + info.point_size_min = 0; + info.point_size_max = 0; + info.add_constants_defs.c_combination = NULL; + info.add_constants_defs.int_const_added = NULL; + info.add_constants_defs.bool_const_added = NULL; + info.swvp_on = true; + info.vdecl_out = vdecl_out; + info.process_vertices = true; + hr = nine_translate_shader(This->base.device, &info, This->base.device->pipe_sw); + if (FAILED(hr)) + return NULL; + *so = info.so; + nine_shader_variant_so_add(&This->variant_so, vdecl_out, so, info.cso); + return info.cso; +} + +IDirect3DVertexShader9Vtbl NineVertexShader9_vtable = { + (void *)NineUnknown_QueryInterface, + (void *)NineUnknown_AddRef, + (void *)NineUnknown_Release, + (void *)NineUnknown_GetDevice, + (void *)NineVertexShader9_GetFunction +}; + +static const GUID *NineVertexShader9_IIDs[] = { + &IID_IDirect3DVertexShader9, + &IID_IUnknown, + NULL +}; + +HRESULT +NineVertexShader9_new( struct NineDevice9 *pDevice, + struct NineVertexShader9 **ppOut, + const DWORD *pFunction, void *cso ) +{ + if (cso) { + NINE_DEVICE_CHILD_BIND_NEW(VertexShader9, ppOut, pDevice, pFunction, cso); + } else { + NINE_DEVICE_CHILD_NEW(VertexShader9, ppOut, pDevice, pFunction, cso); + } +} diff --git a/src/gallium/frontends/nine/vertexshader9.h b/src/gallium/frontends/nine/vertexshader9.h new file mode 100644 index 00000000000..cbbd34979c9 --- /dev/null +++ b/src/gallium/frontends/nine/vertexshader9.h @@ -0,0 +1,155 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _NINE_VERTEXSHADER9_H_ +#define _NINE_VERTEXSHADER9_H_ + +#include "util/u_half.h" + +#include "iunknown.h" +#include "device9.h" +#include "nine_helpers.h" +#include "nine_shader.h" +#include "nine_state.h" + +struct NineVertexDeclaration9; + +struct NineVertexShader9 +{ + struct NineUnknown base; + struct nine_shader_variant variant; + + struct { + uint16_t ndecl; /* NINE_DECLUSAGE_x */ + } input_map[PIPE_MAX_ATTRIBS]; + unsigned num_inputs; + + struct { + const DWORD *tokens; + DWORD size; + uint8_t version; /* (major << 4) | minor */ + } byte_code; + + uint8_t sampler_mask; + + boolean position_t; /* if true, disable vport transform */ + boolean point_size; /* if true, set rasterizer.point_size_per_vertex to 1 */ + boolean swvp_only; + + struct nine_lconstf lconstf; + + boolean int_slots_used[NINE_MAX_CONST_I]; + boolean bool_slots_used[NINE_MAX_CONST_B]; + + unsigned const_int_slots; + unsigned const_bool_slots; + + struct nine_shader_constant_combination *c_combinations; + + uint64_t ff_key[3]; + void *ff_cso; + + uint64_t last_key; + void *last_cso; + unsigned *last_const_ranges; + unsigned last_const_used_size; /* in bytes */ + + uint64_t next_key; + + /* so */ + struct nine_shader_variant_so variant_so; +}; +static inline struct NineVertexShader9 * +NineVertexShader9( void *data ) +{ + return (struct NineVertexShader9 *)data; +} + +static inline BOOL +NineVertexShader9_UpdateKey( struct NineVertexShader9 *vs, + struct NineDevice9 *device ) +{ + struct nine_context *context = &(device->context); + uint8_t samplers_shadow; + uint64_t key; + BOOL res; + + samplers_shadow = (uint8_t)((context->samplers_shadow & NINE_VS_SAMPLERS_MASK) >> NINE_SAMPLER_VS(0)); + samplers_shadow &= vs->sampler_mask; + key = samplers_shadow; + + if (vs->byte_code.version < 0x30) + key |= (uint32_t) ((!!context->rs[D3DRS_FOGENABLE]) << 8); + key |= (uint32_t) (context->swvp << 9); + + if ((vs->const_int_slots > 0 || vs->const_bool_slots > 0) && context->inline_constants && !context->swvp) + key |= ((uint64_t)nine_shader_constant_combination_key(&vs->c_combinations, + vs->int_slots_used, + vs->bool_slots_used, + context->vs_const_i, + context->vs_const_b)) << 16; + + /* We want to use a 64 bits key for performance. + * Use compressed float16 values for the pointsize min/max in the key. + * Shaders do not usually output psize.*/ + if (vs->point_size) { + key |= ((uint64_t)util_float_to_half(asfloat(context->rs[D3DRS_POINTSIZE_MIN]))) << 32; + key |= ((uint64_t)util_float_to_half(asfloat(context->rs[D3DRS_POINTSIZE_MAX]))) << 48; + } + + res = vs->last_key != key; + if (res) + vs->next_key = key; + return res; +} + +void * +NineVertexShader9_GetVariant( struct NineVertexShader9 *vs, + unsigned **const_ranges, + unsigned *const_used_size ); + +void * +NineVertexShader9_GetVariantProcessVertices( struct NineVertexShader9 *vs, + struct NineVertexDeclaration9 *vdecl_out, + struct pipe_stream_output_info *so ); + +/*** public ***/ + +HRESULT +NineVertexShader9_new( struct NineDevice9 *pDevice, + struct NineVertexShader9 **ppOut, + const DWORD *pFunction, void *cso ); + +HRESULT +NineVertexShader9_ctor( struct NineVertexShader9 *, + struct NineUnknownParams *pParams, + const DWORD *pFunction, void *cso ); + +void +NineVertexShader9_dtor( struct NineVertexShader9 * ); + +HRESULT NINE_WINAPI +NineVertexShader9_GetFunction( struct NineVertexShader9 *This, + void *pData, + UINT *pSizeOfData ); + +#endif /* _NINE_VERTEXSHADER9_H_ */ diff --git a/src/gallium/frontends/nine/volume9.c b/src/gallium/frontends/nine/volume9.c new file mode 100644 index 00000000000..4a3d0c88f10 --- /dev/null +++ b/src/gallium/frontends/nine/volume9.c @@ -0,0 +1,558 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "device9.h" +#include "volume9.h" +#include "basetexture9.h" /* for marking dirty */ +#include "volumetexture9.h" +#include "nine_helpers.h" +#include "nine_pipe.h" +#include "nine_dump.h" + +#include "util/format/u_format.h" +#include "util/u_surface.h" + +#define DBG_CHANNEL DBG_VOLUME + + +static HRESULT +NineVolume9_AllocateData( struct NineVolume9 *This ) +{ + unsigned size = This->layer_stride * This->desc.Depth; + + DBG("(%p(This=%p),level=%u) Allocating 0x%x bytes of system memory.\n", + This->base.container, This, This->level, size); + + This->data = (uint8_t *)align_calloc(size, 32); + if (!This->data) + return E_OUTOFMEMORY; + return D3D_OK; +} + +static HRESULT +NineVolume9_ctor( struct NineVolume9 *This, + struct NineUnknownParams *pParams, + struct NineUnknown *pContainer, + struct pipe_resource *pResource, + unsigned Level, + D3DVOLUME_DESC *pDesc ) +{ + HRESULT hr; + + assert(pContainer); /* stand-alone volumes can't be created */ + + DBG("This=%p pContainer=%p pDevice=%p pResource=%p Level=%u pDesc=%p\n", + This, pContainer, pParams->device, pResource, Level, pDesc); + + /* Mark this as a special surface held by another internal resource. */ + pParams->container = pContainer; + + user_assert(!(pDesc->Usage & D3DUSAGE_DYNAMIC) || + (pDesc->Pool != D3DPOOL_MANAGED), D3DERR_INVALIDCALL); + + assert(pResource || pDesc->Pool != D3DPOOL_DEFAULT); + + hr = NineUnknown_ctor(&This->base, pParams); + if (FAILED(hr)) + return hr; + + pipe_resource_reference(&This->resource, pResource); + + This->transfer = NULL; + This->lock_count = 0; + + This->level = Level; + This->level_actual = Level; + This->desc = *pDesc; + + This->info.screen = pParams->device->screen; + This->info.target = PIPE_TEXTURE_3D; + This->info.width0 = pDesc->Width; + This->info.height0 = pDesc->Height; + This->info.depth0 = pDesc->Depth; + This->info.last_level = 0; + This->info.array_size = 1; + This->info.nr_samples = 0; + This->info.nr_storage_samples = 0; + This->info.usage = PIPE_USAGE_DEFAULT; + This->info.bind = PIPE_BIND_SAMPLER_VIEW; + This->info.flags = 0; + This->info.format = d3d9_to_pipe_format_checked(This->info.screen, + pDesc->Format, + This->info.target, + This->info.nr_samples, + This->info.bind, FALSE, + pDesc->Pool == D3DPOOL_SCRATCH); + + if (This->info.format == PIPE_FORMAT_NONE) + return D3DERR_DRIVERINTERNALERROR; + + This->stride = util_format_get_stride(This->info.format, pDesc->Width); + This->stride = align(This->stride, 4); + This->layer_stride = util_format_get_2d_size(This->info.format, + This->stride, pDesc->Height); + + /* Get true format */ + This->format_internal = d3d9_to_pipe_format_checked(This->info.screen, + pDesc->Format, + This->info.target, + This->info.nr_samples, + This->info.bind, FALSE, + TRUE); + if (This->info.format != This->format_internal || + /* DYNAMIC Textures requires same stride as ram buffers. + * Do not use workaround by default as it eats more virtual space */ + (pParams->device->workarounds.dynamic_texture_workaround && + pDesc->Pool == D3DPOOL_DEFAULT && pDesc->Usage & D3DUSAGE_DYNAMIC)) { + This->stride_internal = nine_format_get_stride(This->format_internal, + pDesc->Width); + This->layer_stride_internal = util_format_get_2d_size(This->format_internal, + This->stride_internal, + pDesc->Height); + This->data_internal = align_calloc(This->layer_stride_internal * + This->desc.Depth, 32); + if (!This->data_internal) + return E_OUTOFMEMORY; + } + + if (!This->resource) { + hr = NineVolume9_AllocateData(This); + if (FAILED(hr)) + return hr; + } + return D3D_OK; +} + +static void +NineVolume9_dtor( struct NineVolume9 *This ) +{ + DBG("This=%p\n", This); + + if (This->transfer) { + struct pipe_context *pipe = nine_context_get_pipe_multithread(This->base.device); + pipe->transfer_unmap(pipe, This->transfer); + This->transfer = NULL; + } + + /* Note: Following condition cannot happen currently, since we + * refcount the volume in the functions increasing + * pending_uploads_counter. */ + if (p_atomic_read(&This->pending_uploads_counter)) + nine_csmt_process(This->base.device); + + if (This->data) + align_free(This->data); + if (This->data_internal) + align_free(This->data_internal); + + pipe_resource_reference(&This->resource, NULL); + + NineUnknown_dtor(&This->base); +} + +HRESULT NINE_WINAPI +NineVolume9_GetContainer( struct NineVolume9 *This, + REFIID riid, + void **ppContainer ) +{ + char guid_str[64]; + + DBG("This=%p riid=%p id=%s ppContainer=%p\n", + This, riid, riid ? GUID_sprintf(guid_str, riid) : "", ppContainer); + + (void)guid_str; + + if (!NineUnknown(This)->container) + return E_NOINTERFACE; + return NineUnknown_QueryInterface(NineUnknown(This)->container, riid, ppContainer); +} + +static inline void +NineVolume9_MarkContainerDirty( struct NineVolume9 *This ) +{ + struct NineBaseTexture9 *tex; +#if defined(DEBUG) || !defined(NDEBUG) + /* This is always contained by a NineVolumeTexture9. */ + GUID id = IID_IDirect3DVolumeTexture9; + REFIID ref = &id; + assert(NineUnknown_QueryInterface(This->base.container, ref, (void **)&tex) + == S_OK); + assert(NineUnknown_Release(NineUnknown(tex)) != 0); +#endif + + tex = NineBaseTexture9(This->base.container); + assert(tex); + if (This->desc.Pool == D3DPOOL_MANAGED) + tex->managed.dirty = TRUE; + + BASETEX_REGISTER_UPDATE(tex); +} + +HRESULT NINE_WINAPI +NineVolume9_GetDesc( struct NineVolume9 *This, + D3DVOLUME_DESC *pDesc ) +{ + user_assert(pDesc != NULL, E_POINTER); + *pDesc = This->desc; + return D3D_OK; +} + +inline void +NineVolume9_AddDirtyRegion( struct NineVolume9 *This, + const struct pipe_box *box ) +{ + D3DBOX dirty_region; + struct NineVolumeTexture9 *tex = NineVolumeTexture9(This->base.container); + + if (!box) { + NineVolumeTexture9_AddDirtyBox(tex, NULL); + } else { + dirty_region.Left = box->x << This->level_actual; + dirty_region.Top = box->y << This->level_actual; + dirty_region.Front = box->z << This->level_actual; + dirty_region.Right = dirty_region.Left + (box->width << This->level_actual); + dirty_region.Bottom = dirty_region.Top + (box->height << This->level_actual); + dirty_region.Back = dirty_region.Front + (box->depth << This->level_actual); + NineVolumeTexture9_AddDirtyBox(tex, &dirty_region); + } +} + +static inline unsigned +NineVolume9_GetSystemMemOffset(enum pipe_format format, unsigned stride, + unsigned layer_stride, + int x, int y, int z) +{ + unsigned x_offset = util_format_get_stride(format, x); + + y = util_format_get_nblocksy(format, y); + + return z * layer_stride + y * stride + x_offset; +} + +HRESULT NINE_WINAPI +NineVolume9_LockBox( struct NineVolume9 *This, + D3DLOCKED_BOX *pLockedVolume, + const D3DBOX *pBox, + DWORD Flags ) +{ + struct pipe_context *pipe; + struct pipe_resource *resource = This->resource; + struct pipe_box box; + unsigned usage; + + DBG("This=%p(%p) pLockedVolume=%p pBox=%p[%u..%u,%u..%u,%u..%u] Flags=%s\n", + This, This->base.container, pLockedVolume, pBox, + pBox ? pBox->Left : 0, pBox ? pBox->Right : 0, + pBox ? pBox->Top : 0, pBox ? pBox->Bottom : 0, + pBox ? pBox->Front : 0, pBox ? pBox->Back : 0, + nine_D3DLOCK_to_str(Flags)); + + /* check if it's already locked */ + user_assert(This->lock_count == 0, D3DERR_INVALIDCALL); + + /* set pBits to NULL after lock_count check */ + user_assert(pLockedVolume, E_POINTER); + pLockedVolume->pBits = NULL; + + user_assert(This->desc.Pool != D3DPOOL_DEFAULT || + (This->desc.Usage & D3DUSAGE_DYNAMIC), D3DERR_INVALIDCALL); + + user_assert(!((Flags & D3DLOCK_DISCARD) && (Flags & D3DLOCK_READONLY)), + D3DERR_INVALIDCALL); + + if (pBox && compressed_format (This->desc.Format)) { /* For volume all pools are checked */ + const unsigned w = util_format_get_blockwidth(This->info.format); + const unsigned h = util_format_get_blockheight(This->info.format); + user_assert((pBox->Left == 0 && pBox->Right == This->desc.Width && + pBox->Top == 0 && pBox->Bottom == This->desc.Height) || + (!(pBox->Left % w) && !(pBox->Right % w) && + !(pBox->Top % h) && !(pBox->Bottom % h)), + D3DERR_INVALIDCALL); + } + + if (Flags & D3DLOCK_DISCARD) { + usage = PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE; + } else { + usage = (Flags & D3DLOCK_READONLY) ? + PIPE_TRANSFER_READ : PIPE_TRANSFER_READ_WRITE; + } + if (Flags & D3DLOCK_DONOTWAIT) + usage |= PIPE_TRANSFER_DONTBLOCK; + + if (pBox) { + user_assert(pBox->Right > pBox->Left, D3DERR_INVALIDCALL); + user_assert(pBox->Bottom > pBox->Top, D3DERR_INVALIDCALL); + user_assert(pBox->Back > pBox->Front, D3DERR_INVALIDCALL); + user_assert(pBox->Right <= This->desc.Width, D3DERR_INVALIDCALL); + user_assert(pBox->Bottom <= This->desc.Height, D3DERR_INVALIDCALL); + user_assert(pBox->Back <= This->desc.Depth, D3DERR_INVALIDCALL); + + d3dbox_to_pipe_box(&box, pBox); + if (u_box_clip_2d(&box, &box, This->desc.Width, This->desc.Height) < 0) { + DBG("Locked volume intersection empty.\n"); + return D3DERR_INVALIDCALL; + } + } else { + u_box_3d(0, 0, 0, This->desc.Width, This->desc.Height, This->desc.Depth, + &box); + } + + if (p_atomic_read(&This->pending_uploads_counter)) + nine_csmt_process(This->base.device); + + if (This->data_internal || This->data) { + enum pipe_format format = This->info.format; + unsigned stride = This->stride; + unsigned layer_stride = This->layer_stride; + uint8_t *data = This->data; + if (This->data_internal) { + format = This->format_internal; + stride = This->stride_internal; + layer_stride = This->layer_stride_internal; + data = This->data_internal; + } + pLockedVolume->RowPitch = stride; + pLockedVolume->SlicePitch = layer_stride; + pLockedVolume->pBits = data + + NineVolume9_GetSystemMemOffset(format, stride, + layer_stride, + box.x, box.y, box.z); + } else { + bool no_refs = !p_atomic_read(&This->base.bind) && + !p_atomic_read(&This->base.container->bind); + if (no_refs) + pipe = nine_context_get_pipe_acquire(This->base.device); + else + pipe = NineDevice9_GetPipe(This->base.device); + pLockedVolume->pBits = + pipe->transfer_map(pipe, resource, This->level, usage, + &box, &This->transfer); + if (no_refs) + nine_context_get_pipe_release(This->base.device); + if (!This->transfer) { + if (Flags & D3DLOCK_DONOTWAIT) + return D3DERR_WASSTILLDRAWING; + return D3DERR_DRIVERINTERNALERROR; + } + pLockedVolume->RowPitch = This->transfer->stride; + pLockedVolume->SlicePitch = This->transfer->layer_stride; + } + + if (!(Flags & (D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_READONLY))) { + NineVolume9_MarkContainerDirty(This); + NineVolume9_AddDirtyRegion(This, &box); + } + + ++This->lock_count; + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineVolume9_UnlockBox( struct NineVolume9 *This ) +{ + struct pipe_context *pipe; + + DBG("This=%p lock_count=%u\n", This, This->lock_count); + user_assert(This->lock_count, D3DERR_INVALIDCALL); + if (This->transfer) { + pipe = nine_context_get_pipe_acquire(This->base.device); + pipe->transfer_unmap(pipe, This->transfer); + This->transfer = NULL; + nine_context_get_pipe_release(This->base.device); + } + --This->lock_count; + + if (This->data_internal) { + struct pipe_box box; + + u_box_3d(0, 0, 0, This->desc.Width, This->desc.Height, This->desc.Depth, + &box); + + + if (This->data) { + (void) util_format_translate_3d(This->info.format, + This->data, This->stride, + This->layer_stride, + 0, 0, 0, + This->format_internal, + This->data_internal, + This->stride_internal, + This->layer_stride_internal, + 0, 0, 0, + This->desc.Width, This->desc.Height, + This->desc.Depth); + } else { + nine_context_box_upload(This->base.device, + &This->pending_uploads_counter, + (struct NineUnknown *)This, + This->resource, + This->level, + &box, + This->format_internal, + This->data_internal, + This->stride_internal, + This->layer_stride_internal, + &box); + } + } + + return D3D_OK; +} + +/* When this function is called, we have already checked + * The copy regions fit the volumes */ +void +NineVolume9_CopyMemToDefault( struct NineVolume9 *This, + struct NineVolume9 *From, + unsigned dstx, unsigned dsty, unsigned dstz, + struct pipe_box *pSrcBox ) +{ + struct pipe_resource *r_dst = This->resource; + struct pipe_box src_box; + struct pipe_box dst_box; + + DBG("This=%p From=%p dstx=%u dsty=%u dstz=%u pSrcBox=%p\n", + This, From, dstx, dsty, dstz, pSrcBox); + + assert(This->desc.Pool == D3DPOOL_DEFAULT && + From->desc.Pool == D3DPOOL_SYSTEMMEM); + + dst_box.x = dstx; + dst_box.y = dsty; + dst_box.z = dstz; + + if (pSrcBox) { + src_box = *pSrcBox; + } else { + src_box.x = 0; + src_box.y = 0; + src_box.z = 0; + src_box.width = From->desc.Width; + src_box.height = From->desc.Height; + src_box.depth = From->desc.Depth; + } + + dst_box.width = src_box.width; + dst_box.height = src_box.height; + dst_box.depth = src_box.depth; + + nine_context_box_upload(This->base.device, + &From->pending_uploads_counter, + (struct NineUnknown *)From, + r_dst, + This->level, + &dst_box, + From->info.format, + From->data, From->stride, + From->layer_stride, + &src_box); + + if (This->data_internal) + (void) util_format_translate_3d(This->format_internal, + This->data_internal, + This->stride_internal, + This->layer_stride_internal, + dstx, dsty, dstz, + From->info.format, + From->data, From->stride, + From->layer_stride, + src_box.x, src_box.y, + src_box.z, + src_box.width, + src_box.height, + src_box.depth); + + NineVolume9_MarkContainerDirty(This); + + return; +} + +HRESULT +NineVolume9_UploadSelf( struct NineVolume9 *This, + const struct pipe_box *damaged ) +{ + struct pipe_resource *res = This->resource; + struct pipe_box box; + + DBG("This=%p damaged=%p data=%p res=%p\n", This, damaged, + This->data, res); + + assert(This->desc.Pool == D3DPOOL_MANAGED); + assert(res); + + if (damaged) { + box = *damaged; + } else { + box.x = 0; + box.y = 0; + box.z = 0; + box.width = This->desc.Width; + box.height = This->desc.Height; + box.depth = This->desc.Depth; + } + + nine_context_box_upload(This->base.device, + &This->pending_uploads_counter, + (struct NineUnknown *)This, + res, + This->level, + &box, + res->format, + This->data, This->stride, + This->layer_stride, + &box); + + return D3D_OK; +} + + +IDirect3DVolume9Vtbl NineVolume9_vtable = { + (void *)NineUnknown_QueryInterface, + (void *)NineUnknown_AddRef, + (void *)NineUnknown_Release, + (void *)NineUnknown_GetDevice, /* actually part of Volume9 iface */ + (void *)NineUnknown_SetPrivateData, + (void *)NineUnknown_GetPrivateData, + (void *)NineUnknown_FreePrivateData, + (void *)NineVolume9_GetContainer, + (void *)NineVolume9_GetDesc, + (void *)NineVolume9_LockBox, + (void *)NineVolume9_UnlockBox +}; + +static const GUID *NineVolume9_IIDs[] = { + &IID_IDirect3DVolume9, + &IID_IUnknown, + NULL +}; + +HRESULT +NineVolume9_new( struct NineDevice9 *pDevice, + struct NineUnknown *pContainer, + struct pipe_resource *pResource, + unsigned Level, + D3DVOLUME_DESC *pDesc, + struct NineVolume9 **ppOut ) +{ + NINE_DEVICE_CHILD_NEW(Volume9, ppOut, pDevice, /* args */ + pContainer, pResource, Level, pDesc); +} diff --git a/src/gallium/frontends/nine/volume9.h b/src/gallium/frontends/nine/volume9.h new file mode 100644 index 00000000000..77060f22112 --- /dev/null +++ b/src/gallium/frontends/nine/volume9.h @@ -0,0 +1,118 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _NINE_VOLUME9_H_ +#define _NINE_VOLUME9_H_ + +#include "iunknown.h" + +#include "pipe/p_state.h" +#include "util/u_inlines.h" + +struct hash_table; + +struct NineDevice9; + +struct NineVolume9 +{ + struct NineUnknown base; + + struct pipe_resource *resource; + unsigned level; + unsigned level_actual; + + uint8_t *data; /* system memory backing */ + uint8_t *data_internal; /* for conversions */ + + D3DVOLUME_DESC desc; + struct pipe_resource info; + enum pipe_format format_internal; + unsigned stride; + unsigned stride_internal; + unsigned layer_stride; + unsigned layer_stride_internal; + + struct pipe_transfer *transfer; + unsigned lock_count; + + unsigned pending_uploads_counter; /* pending uploads */ +}; +static inline struct NineVolume9 * +NineVolume9( void *data ) +{ + return (struct NineVolume9 *)data; +} + +HRESULT +NineVolume9_new( struct NineDevice9 *pDevice, + struct NineUnknown *pContainer, + struct pipe_resource *pResource, + unsigned Level, + D3DVOLUME_DESC *pDesc, + struct NineVolume9 **ppOut ); + +/*** Nine private ***/ + +static inline void +NineVolume9_SetResource( struct NineVolume9 *This, + struct pipe_resource *resource, unsigned level ) +{ + This->level = level; + pipe_resource_reference(&This->resource, resource); +} + +void +NineVolume9_AddDirtyRegion( struct NineVolume9 *This, + const struct pipe_box *box ); + +void +NineVolume9_CopyMemToDefault( struct NineVolume9 *This, + struct NineVolume9 *From, + unsigned dstx, unsigned dsty, unsigned dstz, + struct pipe_box *pSrcBox ); + +HRESULT +NineVolume9_UploadSelf( struct NineVolume9 *This, + const struct pipe_box *damaged ); + + +/*** Direct3D public ***/ + +HRESULT NINE_WINAPI +NineVolume9_GetContainer( struct NineVolume9 *This, + REFIID riid, + void **ppContainer ); + +HRESULT NINE_WINAPI +NineVolume9_GetDesc( struct NineVolume9 *This, + D3DVOLUME_DESC *pDesc ); + +HRESULT NINE_WINAPI +NineVolume9_LockBox( struct NineVolume9 *This, + D3DLOCKED_BOX *pLockedVolume, + const D3DBOX *pBox, + DWORD Flags ); + +HRESULT NINE_WINAPI +NineVolume9_UnlockBox( struct NineVolume9 *This ); + +#endif /* _NINE_VOLUME9_H_ */ diff --git a/src/gallium/frontends/nine/volumetexture9.c b/src/gallium/frontends/nine/volumetexture9.c new file mode 100644 index 00000000000..c7191bce688 --- /dev/null +++ b/src/gallium/frontends/nine/volumetexture9.c @@ -0,0 +1,293 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "device9.h" +#include "volumetexture9.h" +#include "nine_helpers.h" +#include "nine_pipe.h" + +#define DBG_CHANNEL DBG_VOLUMETEXTURE + +static HRESULT +NineVolumeTexture9_ctor( struct NineVolumeTexture9 *This, + struct NineUnknownParams *pParams, + UINT Width, UINT Height, UINT Depth, UINT Levels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + HANDLE *pSharedHandle ) +{ + struct pipe_resource *info = &This->base.base.info; + struct pipe_screen *screen = pParams->device->screen; + enum pipe_format pf; + unsigned l; + D3DVOLUME_DESC voldesc; + HRESULT hr; + + DBG("This=%p pParams=%p Width=%u Height=%u Depth=%u Levels=%u " + "Usage=%d Format=%d Pool=%d pSharedHandle=%p\n", + This, pParams, Width, Height, Depth, Levels, + Usage, Format, Pool, pSharedHandle); + + user_assert(Width && Height && Depth, D3DERR_INVALIDCALL); + + /* user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); */ + user_assert(!pSharedHandle, D3DERR_INVALIDCALL); /* TODO */ + + /* An IDirect3DVolume9 cannot be bound as a render target can it ? */ + user_assert(!(Usage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL)), + D3DERR_INVALIDCALL); + user_assert(!(Usage & D3DUSAGE_AUTOGENMIPMAP), D3DERR_INVALIDCALL); + + pf = d3d9_to_pipe_format_checked(screen, Format, PIPE_TEXTURE_3D, 0, + PIPE_BIND_SAMPLER_VIEW, FALSE, + Pool == D3DPOOL_SCRATCH); + + if (pf == PIPE_FORMAT_NONE) + return D3DERR_INVALIDCALL; + + /* We support ATI1 and ATI2 hacks only for 2D and Cube textures */ + if (Format == D3DFMT_ATI1 || Format == D3DFMT_ATI2) + return D3DERR_INVALIDCALL; + + if (compressed_format(Format)) { + const unsigned w = util_format_get_blockwidth(pf); + const unsigned h = util_format_get_blockheight(pf); + /* Compressed formats are not compressed on depth component */ + user_assert(!(Width % w) && !(Height % h), D3DERR_INVALIDCALL); + } + + info->screen = pParams->device->screen; + info->target = PIPE_TEXTURE_3D; + info->format = pf; + info->width0 = Width; + info->height0 = Height; + info->depth0 = Depth; + if (Levels) + info->last_level = Levels - 1; + else + info->last_level = util_logbase2(MAX2(MAX2(Width, Height), Depth)); + info->array_size = 1; + info->nr_samples = 0; + info->nr_storage_samples = 0; + info->bind = PIPE_BIND_SAMPLER_VIEW; + info->usage = PIPE_USAGE_DEFAULT; + info->flags = 0; + + if (Usage & D3DUSAGE_DYNAMIC) { + info->usage = PIPE_USAGE_DYNAMIC; + } + if (Usage & D3DUSAGE_SOFTWAREPROCESSING) + DBG("Application asked for Software Vertex Processing, " + "but this is unimplemented\n"); + + This->volumes = CALLOC(info->last_level + 1, sizeof(*This->volumes)); + if (!This->volumes) + return E_OUTOFMEMORY; + This->base.pstype = 3; + + hr = NineBaseTexture9_ctor(&This->base, pParams, NULL, + D3DRTYPE_VOLUMETEXTURE, Format, Pool, Usage); + if (FAILED(hr)) + return hr; + + voldesc.Format = Format; + voldesc.Type = D3DRTYPE_VOLUME; + voldesc.Usage = Usage; + voldesc.Pool = Pool; + for (l = 0; l <= info->last_level; ++l) { + voldesc.Width = u_minify(Width, l); + voldesc.Height = u_minify(Height, l); + voldesc.Depth = u_minify(Depth, l); + + hr = NineVolume9_new(This->base.base.base.device, NineUnknown(This), + This->base.base.resource, l, + &voldesc, &This->volumes[l]); + if (FAILED(hr)) + return hr; + } + + /* Textures start initially dirty */ + NineVolumeTexture9_AddDirtyBox(This, NULL); + + return D3D_OK; +} + +static void +NineVolumeTexture9_dtor( struct NineVolumeTexture9 *This ) +{ + unsigned l; + + DBG("This=%p\n", This); + + if (This->volumes) { + for (l = 0; l <= This->base.base.info.last_level; ++l) + if (This->volumes[l]) + NineUnknown_Destroy(&This->volumes[l]->base); + FREE(This->volumes); + } + + NineBaseTexture9_dtor(&This->base); +} + +HRESULT NINE_WINAPI +NineVolumeTexture9_GetLevelDesc( struct NineVolumeTexture9 *This, + UINT Level, + D3DVOLUME_DESC *pDesc ) +{ + user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); + + *pDesc = This->volumes[Level]->desc; + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineVolumeTexture9_GetVolumeLevel( struct NineVolumeTexture9 *This, + UINT Level, + IDirect3DVolume9 **ppVolumeLevel ) +{ + user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); + + NineUnknown_AddRef(NineUnknown(This->volumes[Level])); + *ppVolumeLevel = (IDirect3DVolume9 *)This->volumes[Level]; + + return D3D_OK; +} + +HRESULT NINE_WINAPI +NineVolumeTexture9_LockBox( struct NineVolumeTexture9 *This, + UINT Level, + D3DLOCKED_BOX *pLockedVolume, + const D3DBOX *pBox, + DWORD Flags ) +{ + DBG("This=%p Level=%u pLockedVolume=%p pBox=%p Flags=%d\n", + This, Level, pLockedVolume, pBox, Flags); + + user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); + + return NineVolume9_LockBox(This->volumes[Level], pLockedVolume, pBox, + Flags); +} + +HRESULT NINE_WINAPI +NineVolumeTexture9_UnlockBox( struct NineVolumeTexture9 *This, + UINT Level ) +{ + DBG("This=%p Level=%u\n", This, Level); + + user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); + + return NineVolume9_UnlockBox(This->volumes[Level]); +} + +HRESULT NINE_WINAPI +NineVolumeTexture9_AddDirtyBox( struct NineVolumeTexture9 *This, + const D3DBOX *pDirtyBox ) +{ + DBG("This=%p pDirtybox=%p\n", This, pDirtyBox); + + if (This->base.base.pool == D3DPOOL_DEFAULT) { + return D3D_OK; + } + + if (This->base.base.pool == D3DPOOL_MANAGED) { + This->base.managed.dirty = TRUE; + BASETEX_REGISTER_UPDATE(&This->base); + } + + if (!pDirtyBox) { + This->dirty_box.x = 0; + This->dirty_box.y = 0; + This->dirty_box.z = 0; + This->dirty_box.width = This->base.base.info.width0; + This->dirty_box.height = This->base.base.info.height0; + This->dirty_box.depth = This->base.base.info.depth0; + } else { + if (This->dirty_box.width == 0) { + d3dbox_to_pipe_box(&This->dirty_box, pDirtyBox); + } else { + struct pipe_box box; + d3dbox_to_pipe_box(&box, pDirtyBox); + u_box_union_3d(&This->dirty_box, &This->dirty_box, &box); + } + This->dirty_box.x = MAX2(This->dirty_box.x, 0); + This->dirty_box.y = MAX2(This->dirty_box.y, 0); + This->dirty_box.z = MAX2(This->dirty_box.z, 0); + This->dirty_box.width = MIN2(This->dirty_box.width, + This->base.base.info.width0 - This->dirty_box.x); + This->dirty_box.height = MIN2(This->dirty_box.height, + This->base.base.info.height0 - This->dirty_box.y); + This->dirty_box.depth = MIN2(This->dirty_box.depth, + This->base.base.info.depth0 - This->dirty_box.z); + } + return D3D_OK; +} + +IDirect3DVolumeTexture9Vtbl NineVolumeTexture9_vtable = { + (void *)NineUnknown_QueryInterface, + (void *)NineUnknown_AddRef, + (void *)NineUnknown_Release, + (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */ + (void *)NineUnknown_SetPrivateData, + (void *)NineUnknown_GetPrivateData, + (void *)NineUnknown_FreePrivateData, + (void *)NineResource9_SetPriority, + (void *)NineResource9_GetPriority, + (void *)NineBaseTexture9_PreLoad, + (void *)NineResource9_GetType, + (void *)NineBaseTexture9_SetLOD, + (void *)NineBaseTexture9_GetLOD, + (void *)NineBaseTexture9_GetLevelCount, + (void *)NineBaseTexture9_SetAutoGenFilterType, + (void *)NineBaseTexture9_GetAutoGenFilterType, + (void *)NineBaseTexture9_GenerateMipSubLevels, + (void *)NineVolumeTexture9_GetLevelDesc, + (void *)NineVolumeTexture9_GetVolumeLevel, + (void *)NineVolumeTexture9_LockBox, + (void *)NineVolumeTexture9_UnlockBox, + (void *)NineVolumeTexture9_AddDirtyBox +}; + +static const GUID *NineVolumeTexture9_IIDs[] = { + &IID_IDirect3DVolumeTexture9, + &IID_IDirect3DBaseTexture9, + &IID_IDirect3DResource9, + &IID_IUnknown, + NULL +}; + +HRESULT +NineVolumeTexture9_new( struct NineDevice9 *pDevice, + UINT Width, UINT Height, UINT Depth, UINT Levels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + struct NineVolumeTexture9 **ppOut, + HANDLE *pSharedHandle ) +{ + NINE_DEVICE_CHILD_NEW(VolumeTexture9, ppOut, pDevice, + Width, Height, Depth, Levels, + Usage, Format, Pool, pSharedHandle); +} + diff --git a/src/gallium/frontends/nine/volumetexture9.h b/src/gallium/frontends/nine/volumetexture9.h new file mode 100644 index 00000000000..dfe564cfc18 --- /dev/null +++ b/src/gallium/frontends/nine/volumetexture9.h @@ -0,0 +1,75 @@ +/* + * Copyright 2011 Joakim Sindholt + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _NINE_VOLUMETEXTURE9_H_ +#define _NINE_VOLUMETEXTURE9_H_ + +#include "basetexture9.h" +#include "volume9.h" + +struct NineVolumeTexture9 +{ + struct NineBaseTexture9 base; + struct NineVolume9 **volumes; + struct pipe_box dirty_box; +}; +static inline struct NineVolumeTexture9 * +NineVolumeTexture9( void *data ) +{ + return (struct NineVolumeTexture9 *)data; +} + +HRESULT +NineVolumeTexture9_new( struct NineDevice9 *pDevice, + UINT Width, UINT Height, UINT Depth, UINT Levels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + struct NineVolumeTexture9 **ppOut, + HANDLE *pSharedHandle ); + +HRESULT NINE_WINAPI +NineVolumeTexture9_GetLevelDesc( struct NineVolumeTexture9 *This, + UINT Level, + D3DVOLUME_DESC *pDesc ); + +HRESULT NINE_WINAPI +NineVolumeTexture9_GetVolumeLevel( struct NineVolumeTexture9 *This, + UINT Level, + IDirect3DVolume9 **ppVolumeLevel ); + +HRESULT NINE_WINAPI +NineVolumeTexture9_LockBox( struct NineVolumeTexture9 *This, + UINT Level, + D3DLOCKED_BOX *pLockedVolume, + const D3DBOX *pBox, + DWORD Flags ); + +HRESULT NINE_WINAPI +NineVolumeTexture9_UnlockBox( struct NineVolumeTexture9 *This, + UINT Level ); + +HRESULT NINE_WINAPI +NineVolumeTexture9_AddDirtyBox( struct NineVolumeTexture9 *This, + const D3DBOX *pDirtyBox ); + +#endif /* _NINE_VOLUMETEXTURE9_H_ */ diff --git a/src/gallium/frontends/omx/Makefile.sources b/src/gallium/frontends/omx/Makefile.sources new file mode 100644 index 00000000000..0fb1d9a4d76 --- /dev/null +++ b/src/gallium/frontends/omx/Makefile.sources @@ -0,0 +1,9 @@ +C_SOURCES := \ + vid_dec_common.c \ + vid_dec_common.h \ + vid_dec_h264_common.c \ + vid_dec_h264_common.h \ + vid_omx_common.c \ + vid_omx_common.h \ + vid_enc_common.c \ + vid_enc_common.h diff --git a/src/gallium/frontends/omx/bellagio/Makefile.sources b/src/gallium/frontends/omx/bellagio/Makefile.sources new file mode 100644 index 00000000000..ab60ce803cb --- /dev/null +++ b/src/gallium/frontends/omx/bellagio/Makefile.sources @@ -0,0 +1,10 @@ +C_SOURCES := \ + entrypoint.c \ + entrypoint.h \ + vid_dec.c \ + vid_dec.h \ + vid_dec_mpeg12.c \ + vid_dec_h264.c \ + vid_dec_h265.c \ + vid_enc.c \ + vid_enc.h diff --git a/src/gallium/frontends/omx/bellagio/entrypoint.c b/src/gallium/frontends/omx/bellagio/entrypoint.c new file mode 100644 index 00000000000..5c75e8dadaa --- /dev/null +++ b/src/gallium/frontends/omx/bellagio/entrypoint.c @@ -0,0 +1,69 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/* + * Authors: + * Christian König + * + */ + +#include "entrypoint.h" +#include "vid_dec.h" +#include "vid_enc.h" + +int omx_component_library_Setup(stLoaderComponentType **stComponents) +{ + OMX_ERRORTYPE r; + + if (stComponents == NULL) + return 2; + + /* component 0 - video decoder */ + r = vid_dec_LoaderComponent(stComponents[0]); + if (r != OMX_ErrorNone) + return OMX_ErrorInsufficientResources; + + /* component 1 - video encoder */ + r = vid_enc_LoaderComponent(stComponents[1]); + if (r != OMX_ErrorNone) + return OMX_ErrorInsufficientResources; + + return 2; +} + +OMX_ERRORTYPE omx_workaround_Destructor(OMX_COMPONENTTYPE *comp) +{ + omx_base_component_PrivateType* priv = (omx_base_component_PrivateType*)comp->pComponentPrivate; + + priv->state = OMX_StateInvalid; + tsem_up(priv->messageSem); + + /* wait for thread to exit */ + pthread_join(priv->messageHandlerThread, NULL); + + return omx_base_component_Destructor(comp); +} diff --git a/src/gallium/frontends/omx/bellagio/entrypoint.h b/src/gallium/frontends/omx/bellagio/entrypoint.h new file mode 100644 index 00000000000..d566d1eb5a3 --- /dev/null +++ b/src/gallium/frontends/omx/bellagio/entrypoint.h @@ -0,0 +1,45 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/* + * Authors: + * Christian König + * + */ + +#ifndef OMX_ENTRYPOINT_H +#define OMX_ENTRYPOINT_H + +#include + +#include "vl/vl_winsys.h" + +PUBLIC extern int omx_component_library_Setup(stLoaderComponentType **stComponents); + +OMX_ERRORTYPE omx_workaround_Destructor(OMX_COMPONENTTYPE *comp); + +#endif diff --git a/src/gallium/frontends/omx/bellagio/vid_dec.c b/src/gallium/frontends/omx/bellagio/vid_dec.c new file mode 100644 index 00000000000..2eedf937cd9 --- /dev/null +++ b/src/gallium/frontends/omx/bellagio/vid_dec.c @@ -0,0 +1,508 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/* + * Authors: + * Christian König + * + */ + + +#include + +#include + +/* bellagio defines a DEBUG macro that we don't want */ +#ifndef DEBUG +#include +#undef DEBUG +#else +#include +#endif + +#include "pipe/p_screen.h" +#include "pipe/p_video_codec.h" +#include "util/u_memory.h" +#include "util/u_surface.h" +#include "vl/vl_video_buffer.h" +#include "vl/vl_vlc.h" + +#include "entrypoint.h" +#include "vid_dec.h" +#include "vid_omx_common.h" +#include "vid_dec_h264_common.h" + +static OMX_ERRORTYPE vid_dec_Constructor(OMX_COMPONENTTYPE *comp, OMX_STRING name); +static OMX_ERRORTYPE vid_dec_Destructor(OMX_COMPONENTTYPE *comp); +static OMX_ERRORTYPE vid_dec_SetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param); +static OMX_ERRORTYPE vid_dec_GetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param); +static OMX_ERRORTYPE vid_dec_MessageHandler(OMX_COMPONENTTYPE *comp, internalRequestMessageType *msg); +static OMX_ERRORTYPE vid_dec_DecodeBuffer(omx_base_PortType *port, OMX_BUFFERHEADERTYPE *buf); +static OMX_ERRORTYPE vid_dec_FreeDecBuffer(omx_base_PortType *port, OMX_U32 idx, OMX_BUFFERHEADERTYPE *buf); +static void vid_dec_FrameDecoded(OMX_COMPONENTTYPE *comp, OMX_BUFFERHEADERTYPE* input, OMX_BUFFERHEADERTYPE* output); + +OMX_ERRORTYPE vid_dec_LoaderComponent(stLoaderComponentType *comp) +{ + comp->componentVersion.s.nVersionMajor = 0; + comp->componentVersion.s.nVersionMinor = 0; + comp->componentVersion.s.nRevision = 0; + comp->componentVersion.s.nStep = 1; + comp->name_specific_length = 3; + + comp->name = CALLOC(1, OMX_MAX_STRINGNAME_SIZE); + if (comp->name == NULL) + goto error; + + comp->name_specific = CALLOC(comp->name_specific_length, sizeof(char *)); + if (comp->name_specific == NULL) + goto error; + + comp->role_specific = CALLOC(comp->name_specific_length, sizeof(char *)); + if (comp->role_specific == NULL) + goto error; + + comp->name_specific[0] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE); + if (comp->name_specific[0] == NULL) + goto error_specific; + + comp->name_specific[1] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE); + if (comp->name_specific[1] == NULL) + goto error_specific; + + comp->name_specific[2] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE); + if (comp->name_specific[2] == NULL) + goto error_specific; + + comp->role_specific[0] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE); + if (comp->role_specific[0] == NULL) + goto error_specific; + + comp->role_specific[1] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE); + if (comp->role_specific[1] == NULL) + goto error_specific; + + comp->role_specific[2] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE); + if (comp->role_specific[2] == NULL) + goto error_specific; + + strcpy(comp->name, OMX_VID_DEC_BASE_NAME); + strcpy(comp->name_specific[0], OMX_VID_DEC_MPEG2_NAME); + strcpy(comp->name_specific[1], OMX_VID_DEC_AVC_NAME); + strcpy(comp->name_specific[2], OMX_VID_DEC_HEVC_NAME); + + strcpy(comp->role_specific[0], OMX_VID_DEC_MPEG2_ROLE); + strcpy(comp->role_specific[1], OMX_VID_DEC_AVC_ROLE); + strcpy(comp->role_specific[2], OMX_VID_DEC_HEVC_ROLE); + + comp->constructor = vid_dec_Constructor; + + return OMX_ErrorNone; + +error_specific: + FREE(comp->role_specific[2]); + FREE(comp->role_specific[1]); + FREE(comp->role_specific[0]); + FREE(comp->name_specific[2]); + FREE(comp->name_specific[1]); + FREE(comp->name_specific[0]); + +error: + FREE(comp->role_specific); + FREE(comp->name_specific); + + FREE(comp->name); + + return OMX_ErrorInsufficientResources; +} + +static OMX_ERRORTYPE vid_dec_Constructor(OMX_COMPONENTTYPE *comp, OMX_STRING name) +{ + vid_dec_PrivateType *priv; + omx_base_video_PortType *port; + struct pipe_screen *screen; + OMX_ERRORTYPE r; + int i; + + assert(!comp->pComponentPrivate); + + priv = comp->pComponentPrivate = CALLOC(1, sizeof(vid_dec_PrivateType)); + if (!priv) + return OMX_ErrorInsufficientResources; + + r = omx_base_filter_Constructor(comp, name); + if (r) + return r; + + priv->profile = PIPE_VIDEO_PROFILE_UNKNOWN; + + if (!strcmp(name, OMX_VID_DEC_MPEG2_NAME)) + priv->profile = PIPE_VIDEO_PROFILE_MPEG2_MAIN; + + if (!strcmp(name, OMX_VID_DEC_AVC_NAME)) + priv->profile = PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH; + + if (!strcmp(name, OMX_VID_DEC_HEVC_NAME)) + priv->profile = PIPE_VIDEO_PROFILE_HEVC_MAIN; + + priv->BufferMgmtCallback = vid_dec_FrameDecoded; + priv->messageHandler = vid_dec_MessageHandler; + priv->destructor = vid_dec_Destructor; + + comp->SetParameter = vid_dec_SetParameter; + comp->GetParameter = vid_dec_GetParameter; + + priv->screen = omx_get_screen(); + if (!priv->screen) + return OMX_ErrorInsufficientResources; + + screen = priv->screen->pscreen; + priv->pipe = pipe_create_multimedia_context(screen); + if (!priv->pipe) + return OMX_ErrorInsufficientResources; + + if (!vl_compositor_init(&priv->compositor, priv->pipe)) { + priv->pipe->destroy(priv->pipe); + priv->pipe = NULL; + return OMX_ErrorInsufficientResources; + } + + if (!vl_compositor_init_state(&priv->cstate, priv->pipe)) { + vl_compositor_cleanup(&priv->compositor); + priv->pipe->destroy(priv->pipe); + priv->pipe = NULL; + return OMX_ErrorInsufficientResources; + } + + priv->sPortTypesParam[OMX_PortDomainVideo].nStartPortNumber = 0; + priv->sPortTypesParam[OMX_PortDomainVideo].nPorts = 2; + priv->ports = CALLOC(2, sizeof(omx_base_PortType *)); + if (!priv->ports) + return OMX_ErrorInsufficientResources; + + for (i = 0; i < 2; ++i) { + priv->ports[i] = CALLOC(1, sizeof(omx_base_video_PortType)); + if (!priv->ports[i]) + return OMX_ErrorInsufficientResources; + + base_video_port_Constructor(comp, &priv->ports[i], i, i == 0); + } + + port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; + strcpy(port->sPortParam.format.video.cMIMEType,"video/MPEG2"); + port->sPortParam.nBufferCountMin = 8; + port->sPortParam.nBufferCountActual = 8; + port->sPortParam.nBufferSize = DEFAULT_OUT_BUFFER_SIZE; + port->sPortParam.format.video.nFrameWidth = 176; + port->sPortParam.format.video.nFrameHeight = 144; + port->sPortParam.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG2; + port->sVideoParam.eCompressionFormat = OMX_VIDEO_CodingMPEG2; + port->Port_SendBufferFunction = vid_dec_DecodeBuffer; + port->Port_FreeBuffer = vid_dec_FreeDecBuffer; + + port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]; + port->sPortParam.nBufferCountActual = 8; + port->sPortParam.nBufferCountMin = 4; + port->sPortParam.format.video.nFrameWidth = 176; + port->sPortParam.format.video.nFrameHeight = 144; + port->sPortParam.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; + port->sVideoParam.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; + + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE vid_dec_Destructor(OMX_COMPONENTTYPE *comp) +{ + vid_dec_PrivateType* priv = comp->pComponentPrivate; + int i; + + if (priv->ports) { + for (i = 0; i < priv->sPortTypesParam[OMX_PortDomainVideo].nPorts; ++i) { + if(priv->ports[i]) + priv->ports[i]->PortDestructor(priv->ports[i]); + } + FREE(priv->ports); + priv->ports=NULL; + } + + if (priv->pipe) { + vl_compositor_cleanup_state(&priv->cstate); + vl_compositor_cleanup(&priv->compositor); + priv->pipe->destroy(priv->pipe); + } + + if (priv->screen) + omx_put_screen(); + + return omx_workaround_Destructor(comp); +} + +static OMX_ERRORTYPE vid_dec_SetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param) +{ + OMX_COMPONENTTYPE *comp = handle; + vid_dec_PrivateType *priv = comp->pComponentPrivate; + OMX_ERRORTYPE r; + + if (!param) + return OMX_ErrorBadParameter; + + switch(idx) { + case OMX_IndexParamPortDefinition: { + OMX_PARAM_PORTDEFINITIONTYPE *def = param; + + r = omx_base_component_SetParameter(handle, idx, param); + if (r) + return r; + + if (def->nPortIndex == OMX_BASE_FILTER_INPUTPORT_INDEX) { + omx_base_video_PortType *port; + unsigned framesize = def->format.video.nFrameWidth * def->format.video.nFrameHeight; + + port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; + port->sPortParam.nBufferSize = framesize * 512 / (16*16); + + port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]; + port->sPortParam.format.video.nFrameWidth = def->format.video.nFrameWidth; + port->sPortParam.format.video.nFrameHeight = def->format.video.nFrameHeight; + port->sPortParam.format.video.nStride = def->format.video.nFrameWidth; + port->sPortParam.format.video.nSliceHeight = def->format.video.nFrameHeight; + port->sPortParam.nBufferSize = framesize*3/2; + + priv->callbacks->EventHandler(comp, priv->callbackData, OMX_EventPortSettingsChanged, + OMX_BASE_FILTER_OUTPUTPORT_INDEX, 0, NULL); + } + break; + } + case OMX_IndexParamStandardComponentRole: { + OMX_PARAM_COMPONENTROLETYPE *role = param; + + r = checkHeader(param, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (r) + return r; + + if (!strcmp((char *)role->cRole, OMX_VID_DEC_MPEG2_ROLE)) { + priv->profile = PIPE_VIDEO_PROFILE_MPEG2_MAIN; + } else if (!strcmp((char *)role->cRole, OMX_VID_DEC_AVC_ROLE)) { + priv->profile = PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH; + } else if (!strcmp((char *)role->cRole, OMX_VID_DEC_HEVC_ROLE)) { + priv->profile = PIPE_VIDEO_PROFILE_HEVC_MAIN; + } else { + return OMX_ErrorBadParameter; + } + + break; + } + case OMX_IndexParamVideoPortFormat: { + OMX_VIDEO_PARAM_PORTFORMATTYPE *format = param; + omx_base_video_PortType *port; + + r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); + if (r) + return r; + + if (format->nPortIndex > 1) + return OMX_ErrorBadPortIndex; + + port = (omx_base_video_PortType *)priv->ports[format->nPortIndex]; + memcpy(&port->sVideoParam, format, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); + break; + } + default: + return omx_base_component_SetParameter(handle, idx, param); + } + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE vid_dec_GetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param) +{ + OMX_COMPONENTTYPE *comp = handle; + vid_dec_PrivateType *priv = comp->pComponentPrivate; + OMX_ERRORTYPE r; + + if (!param) + return OMX_ErrorBadParameter; + + switch(idx) { + case OMX_IndexParamStandardComponentRole: { + OMX_PARAM_COMPONENTROLETYPE *role = param; + + r = checkHeader(param, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (r) + return r; + + if (priv->profile == PIPE_VIDEO_PROFILE_MPEG2_MAIN) + strcpy((char *)role->cRole, OMX_VID_DEC_MPEG2_ROLE); + else if (priv->profile == PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH) + strcpy((char *)role->cRole, OMX_VID_DEC_AVC_ROLE); + else if (priv->profile == PIPE_VIDEO_PROFILE_HEVC_MAIN) + strcpy((char *)role->cRole, OMX_VID_DEC_HEVC_ROLE); + + break; + } + + case OMX_IndexParamVideoInit: + r = checkHeader(param, sizeof(OMX_PORT_PARAM_TYPE)); + if (r) + return r; + + memcpy(param, &priv->sPortTypesParam[OMX_PortDomainVideo], sizeof(OMX_PORT_PARAM_TYPE)); + break; + + case OMX_IndexParamVideoPortFormat: { + OMX_VIDEO_PARAM_PORTFORMATTYPE *format = param; + omx_base_video_PortType *port; + + r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); + if (r) + return r; + + if (format->nPortIndex > 1) + return OMX_ErrorBadPortIndex; + + port = (omx_base_video_PortType *)priv->ports[format->nPortIndex]; + memcpy(format, &port->sVideoParam, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); + break; + } + + default: + return omx_base_component_GetParameter(handle, idx, param); + + } + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE vid_dec_MessageHandler(OMX_COMPONENTTYPE* comp, internalRequestMessageType *msg) +{ + vid_dec_PrivateType* priv = comp->pComponentPrivate; + + if (msg->messageType == OMX_CommandStateSet) { + if ((msg->messageParam == OMX_StateIdle ) && (priv->state == OMX_StateLoaded)) { + if (priv->profile == PIPE_VIDEO_PROFILE_MPEG2_MAIN) + vid_dec_mpeg12_Init(priv); + else if (priv->profile == PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH) + vid_dec_h264_Init(priv); + else if (priv->profile == PIPE_VIDEO_PROFILE_HEVC_MAIN) + vid_dec_h265_Init(priv); + + } else if ((msg->messageParam == OMX_StateLoaded) && (priv->state == OMX_StateIdle)) { + if (priv->shadow) { + priv->shadow->destroy(priv->shadow); + priv->shadow = NULL; + } + if (priv->codec) { + priv->codec->destroy(priv->codec); + priv->codec = NULL; + } + } + } + + return omx_base_component_MessageHandler(comp, msg); +} + +static OMX_ERRORTYPE vid_dec_DecodeBuffer(omx_base_PortType *port, OMX_BUFFERHEADERTYPE *buf) +{ + OMX_COMPONENTTYPE* comp = port->standCompContainer; + vid_dec_PrivateType *priv = comp->pComponentPrivate; + unsigned i = priv->num_in_buffers++; + OMX_ERRORTYPE r; + + priv->in_buffers[i] = buf; + priv->sizes[i] = buf->nFilledLen; + priv->inputs[i] = buf->pBuffer; + priv->timestamps[i] = buf->nTimeStamp; + + while (priv->num_in_buffers > (!!(buf->nFlags & OMX_BUFFERFLAG_EOS) ? 0 : 1)) { + bool eos = !!(priv->in_buffers[0]->nFlags & OMX_BUFFERFLAG_EOS); + unsigned min_bits_left = eos ? 32 : MAX2(buf->nFilledLen * 8, 32); + struct vl_vlc vlc; + + vl_vlc_init(&vlc, priv->num_in_buffers, priv->inputs, priv->sizes); + + if (priv->slice) + priv->bytes_left = vl_vlc_bits_left(&vlc) / 8; + + while (vl_vlc_bits_left(&vlc) > min_bits_left) { + priv->Decode(priv, &vlc, min_bits_left); + vl_vlc_fillbits(&vlc); + } + + if (priv->slice) { + unsigned bytes = priv->bytes_left - vl_vlc_bits_left(&vlc) / 8; + + priv->codec->decode_bitstream(priv->codec, priv->target, &priv->picture.base, + 1, &priv->slice, &bytes); + + if (priv->num_in_buffers) + priv->slice = priv->inputs[1]; + else + priv->slice = NULL; + } + + if (eos && priv->frame_started) + priv->EndFrame(priv); + + if (priv->frame_finished) { + priv->frame_finished = false; + priv->in_buffers[0]->nFilledLen = priv->in_buffers[0]->nAllocLen; + r = base_port_SendBufferFunction(port, priv->in_buffers[0]); + } else if (eos) { + vid_dec_FreeInputPortPrivate(priv->in_buffers[0]); + priv->in_buffers[0]->nFilledLen = priv->in_buffers[0]->nAllocLen; + r = base_port_SendBufferFunction(port, priv->in_buffers[0]); + } else { + priv->in_buffers[0]->nFilledLen = 0; + r = port->ReturnBufferFunction(port, priv->in_buffers[0]); + } + + if (--priv->num_in_buffers) { + unsigned delta = MIN2((min_bits_left - vl_vlc_bits_left(&vlc)) / 8, priv->sizes[1]); + + priv->in_buffers[0] = priv->in_buffers[1]; + priv->sizes[0] = priv->sizes[1] - delta; + priv->inputs[0] = priv->inputs[1] + delta; + priv->timestamps[0] = priv->timestamps[1]; + } + + if (r) + return r; + } + + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE vid_dec_FreeDecBuffer(omx_base_PortType *port, OMX_U32 idx, OMX_BUFFERHEADERTYPE *buf) +{ + vid_dec_FreeInputPortPrivate(buf); + return base_port_FreeBuffer(port, idx, buf); +} + +static void vid_dec_FrameDecoded(OMX_COMPONENTTYPE *comp, OMX_BUFFERHEADERTYPE* input, + OMX_BUFFERHEADERTYPE* output) +{ + vid_dec_PrivateType *priv = comp->pComponentPrivate; + + vid_dec_FrameDecoded_common(priv, input, output); +} diff --git a/src/gallium/frontends/omx/bellagio/vid_dec.h b/src/gallium/frontends/omx/bellagio/vid_dec.h new file mode 100644 index 00000000000..247217810b5 --- /dev/null +++ b/src/gallium/frontends/omx/bellagio/vid_dec.h @@ -0,0 +1,70 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/* + * Authors: + * Christian König + * + */ + +#ifndef OMX_VID_DEC_H +#define OMX_VID_DEC_H + +#include + +#include +#include + +#include "os/os_thread.h" + +#include "vid_dec_common.h" + +#define OMX_VID_DEC_BASE_NAME "OMX.mesa.video_decoder" + +#define OMX_VID_DEC_MPEG2_NAME "OMX.mesa.video_decoder.mpeg2" +#define OMX_VID_DEC_MPEG2_ROLE "video_decoder.mpeg2" + +#define OMX_VID_DEC_AVC_NAME "OMX.mesa.video_decoder.avc" +#define OMX_VID_DEC_AVC_ROLE "video_decoder.avc" + +#define OMX_VID_DEC_HEVC_NAME "OMX.mesa.video_decoder.hevc" +#define OMX_VID_DEC_HEVC_ROLE "video_decoder.hevc" + +#define OMX_VID_DEC_TIMESTAMP_INVALID ((OMX_TICKS) -1) + +OMX_ERRORTYPE vid_dec_LoaderComponent(stLoaderComponentType *comp); + +/* vid_dec_mpeg12.c */ +void vid_dec_mpeg12_Init(vid_dec_PrivateType *priv); + +/* vid_dec_h264.c */ +void vid_dec_h264_Init(vid_dec_PrivateType *priv); + +/* vid_dec_h265.c */ +void vid_dec_h265_Init(vid_dec_PrivateType *priv); + +#endif diff --git a/src/gallium/frontends/omx/bellagio/vid_dec_h264.c b/src/gallium/frontends/omx/bellagio/vid_dec_h264.c new file mode 100644 index 00000000000..1a198a97e96 --- /dev/null +++ b/src/gallium/frontends/omx/bellagio/vid_dec_h264.c @@ -0,0 +1,55 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/* + * Authors: + * Christian König + * + */ + +#include "pipe/p_video_codec.h" +#include "util/u_memory.h" +#include "util/u_video.h" +#include "vl/vl_rbsp.h" +#include "vl/vl_zscan.h" + +#include "entrypoint.h" +#include "vid_dec.h" +#include "vid_dec_h264_common.h" + +void vid_dec_h264_Init(vid_dec_PrivateType *priv) +{ + priv->picture.base.profile = PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH; + + priv->Decode = vid_dec_h264_Decode; + priv->EndFrame = vid_dec_h264_EndFrame; + priv->Flush = vid_dec_h264_Flush; + + list_inithead(&priv->codec_data.h264.dpb_list); + priv->picture.h264.field_order_cnt[0] = priv->picture.h264.field_order_cnt[1] = INT_MAX; + priv->first_buf_in_frame = true; +} diff --git a/src/gallium/frontends/omx/bellagio/vid_dec_h265.c b/src/gallium/frontends/omx/bellagio/vid_dec_h265.c new file mode 100644 index 00000000000..c50be7804cb --- /dev/null +++ b/src/gallium/frontends/omx/bellagio/vid_dec_h265.c @@ -0,0 +1,1013 @@ +/************************************************************************** + * + * Copyright 2016 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "pipe/p_video_codec.h" +#include "util/u_memory.h" +#include "util/u_video.h" +#include "vl/vl_rbsp.h" + +#include "entrypoint.h" +#include "vid_dec.h" + +#define DPB_MAX_SIZE 32 +#define MAX_NUM_REF_PICS 16 + +enum { + NAL_UNIT_TYPE_TRAIL_N = 0, + NAL_UNIT_TYPE_TRAIL_R = 1, + NAL_UNIT_TYPE_TSA_N = 2, + NAL_UNIT_TYPE_TSA_R = 3, + NAL_UNIT_TYPE_STSA_N = 4, + NAL_UNIT_TYPE_STSA_R = 5, + NAL_UNIT_TYPE_RADL_N = 6, + NAL_UNIT_TYPE_RADL_R = 7, + NAL_UNIT_TYPE_RASL_N = 8, + NAL_UNIT_TYPE_RASL_R = 9, + NAL_UNIT_TYPE_BLA_W_LP = 16, + NAL_UNIT_TYPE_BLA_W_RADL = 17, + NAL_UNIT_TYPE_BLA_N_LP = 18, + NAL_UNIT_TYPE_IDR_W_RADL = 19, + NAL_UNIT_TYPE_IDR_N_LP = 20, + NAL_UNIT_TYPE_CRA = 21, + NAL_UNIT_TYPE_SPS = 33, + NAL_UNIT_TYPE_PPS = 34, +}; + +static const uint8_t Default_8x8_Intra[64] = { + 16, 16, 16, 16, 17, 18, 21, 24, + 16, 16, 16, 16, 17, 19, 22, 25, + 16, 16, 17, 18, 20, 22, 25, 29, + 16, 16, 18, 21, 24, 27, 31, 36, + 17, 17, 20, 24, 30, 35, 41, 47, + 18, 19, 22, 27, 35, 44, 54, 65, + 21, 22, 25, 31, 41, 54, 70, 88, + 24, 25, 29, 36, 47, 65, 88, 115 +}; + +static const uint8_t Default_8x8_Inter[64] = { + 16, 16, 16, 16, 17, 18, 20, 24, + 16, 16, 16, 17, 18, 20, 24, 25, + 16, 16, 17, 18, 20, 24, 25, 28, + 16, 17, 18, 20, 24, 25, 28, 33, + 17, 18, 20, 24, 25, 28, 33, 41, + 18, 20, 24, 25, 28, 33, 41, 54, + 20, 24, 25, 28, 33, 41, 54, 71, + 24, 25, 28, 33, 41, 54, 71, 91 +}; + +struct dpb_list { + struct list_head list; + struct pipe_video_buffer *buffer; + OMX_TICKS timestamp; + unsigned poc; +}; + +struct ref_pic_set { + unsigned num_pics; + unsigned num_neg_pics; + unsigned num_pos_pics; + unsigned num_delta_poc; + int delta_poc[MAX_NUM_REF_PICS]; + bool used[MAX_NUM_REF_PICS]; +}; + +static bool is_idr_picture(unsigned nal_unit_type) +{ + return (nal_unit_type == NAL_UNIT_TYPE_IDR_W_RADL || + nal_unit_type == NAL_UNIT_TYPE_IDR_N_LP); +} + +/* broken link access picture */ +static bool is_bla_picture(unsigned nal_unit_type) +{ + return (nal_unit_type == NAL_UNIT_TYPE_BLA_W_LP || + nal_unit_type == NAL_UNIT_TYPE_BLA_W_RADL || + nal_unit_type == NAL_UNIT_TYPE_BLA_N_LP); +} + +/* random access point picture */ +static bool is_rap_picture(unsigned nal_unit_type) +{ + return (nal_unit_type >= NAL_UNIT_TYPE_BLA_W_LP && + nal_unit_type <= NAL_UNIT_TYPE_CRA); +} + +static bool is_slice_picture(unsigned nal_unit_type) +{ + return (nal_unit_type <= NAL_UNIT_TYPE_RASL_R || + is_rap_picture(nal_unit_type)); +} + +static void set_poc(vid_dec_PrivateType *priv, + unsigned nal_unit_type, int i) +{ + priv->picture.h265.CurrPicOrderCntVal = i; + + if (priv->codec_data.h265.temporal_id == 0 && + (nal_unit_type == NAL_UNIT_TYPE_TRAIL_R || + nal_unit_type == NAL_UNIT_TYPE_TSA_R || + nal_unit_type == NAL_UNIT_TYPE_STSA_R || + is_rap_picture(nal_unit_type))) + priv->codec_data.h265.slice_prev_poc = i; +} + +static unsigned get_poc(vid_dec_PrivateType *priv) +{ + return priv->picture.h265.CurrPicOrderCntVal; +} + +static void profile_tier(struct vl_rbsp *rbsp) +{ + int i; + + /* general_profile_space */ + vl_rbsp_u(rbsp, 2); + + /* general_tier_flag */ + vl_rbsp_u(rbsp, 1); + + /* general_profile_idc */ + vl_rbsp_u(rbsp, 5); + + /* general_profile_compatibility_flag */ + for(i = 0; i < 32; ++i) + vl_rbsp_u(rbsp, 1); + + /* general_progressive_source_flag */ + vl_rbsp_u(rbsp, 1); + + /* general_interlaced_source_flag */ + vl_rbsp_u(rbsp, 1); + + /* general_non_packed_constraint_flag */ + vl_rbsp_u(rbsp, 1); + + /* general_frame_only_constraint_flag */ + vl_rbsp_u(rbsp, 1); + + /* general_reserved_zero_44bits */ + vl_rbsp_u(rbsp, 16); + vl_rbsp_u(rbsp, 16); + vl_rbsp_u(rbsp, 12); +} + +static unsigned profile_tier_level(struct vl_rbsp *rbsp, + int max_sublayers_minus1) +{ + bool sub_layer_profile_present_flag[6]; + bool sub_layer_level_present_flag[6]; + unsigned level_idc; + int i; + + profile_tier(rbsp); + + /* general_level_idc */ + level_idc = vl_rbsp_u(rbsp, 8); + + for (i = 0; i < max_sublayers_minus1; ++i) { + sub_layer_profile_present_flag[i] = vl_rbsp_u(rbsp, 1); + sub_layer_level_present_flag[i] = vl_rbsp_u(rbsp, 1); + } + + if (max_sublayers_minus1 > 0) + for (i = max_sublayers_minus1; i < 8; ++i) + /* reserved_zero_2bits */ + vl_rbsp_u(rbsp, 2); + + for (i = 0; i < max_sublayers_minus1; ++i) { + if (sub_layer_profile_present_flag[i]) + profile_tier(rbsp); + + if (sub_layer_level_present_flag[i]) + /* sub_layer_level_idc */ + vl_rbsp_u(rbsp, 8); + } + + return level_idc; +} + +static void scaling_list_data(vid_dec_PrivateType *priv, + struct vl_rbsp *rbsp, struct pipe_h265_sps *sps) +{ + unsigned size_id, matrix_id; + unsigned scaling_list_len[4] = { 16, 64, 64, 64 }; + uint8_t scaling_list4x4[6][64] = { }; + int i; + + uint8_t (*scaling_list_data[4])[6][64] = { + (uint8_t (*)[6][64])scaling_list4x4, + (uint8_t (*)[6][64])sps->ScalingList8x8, + (uint8_t (*)[6][64])sps->ScalingList16x16, + (uint8_t (*)[6][64])sps->ScalingList32x32 + }; + uint8_t (*scaling_list_dc_coeff[2])[6] = { + (uint8_t (*)[6])sps->ScalingListDCCoeff16x16, + (uint8_t (*)[6])sps->ScalingListDCCoeff32x32 + }; + + for (size_id = 0; size_id < 4; ++size_id) { + + for (matrix_id = 0; matrix_id < ((size_id == 3) ? 2 : 6); ++matrix_id) { + bool scaling_list_pred_mode_flag = vl_rbsp_u(rbsp, 1); + + if (!scaling_list_pred_mode_flag) { + /* scaling_list_pred_matrix_id_delta */; + unsigned matrix_id_with_delta = matrix_id - vl_rbsp_ue(rbsp); + + if (matrix_id != matrix_id_with_delta) { + memcpy((*scaling_list_data[size_id])[matrix_id], + (*scaling_list_data[size_id])[matrix_id_with_delta], + scaling_list_len[size_id]); + if (size_id > 1) + (*scaling_list_dc_coeff[size_id - 2])[matrix_id] = + (*scaling_list_dc_coeff[size_id - 2])[matrix_id_with_delta]; + } else { + const uint8_t *d; + + if (size_id == 0) + memset((*scaling_list_data[0])[matrix_id], 16, 16); + else { + if (size_id < 3) + d = (matrix_id < 3) ? Default_8x8_Intra : Default_8x8_Inter; + else + d = (matrix_id < 1) ? Default_8x8_Intra : Default_8x8_Inter; + memcpy((*scaling_list_data[size_id])[matrix_id], d, + scaling_list_len[size_id]); + } + if (size_id > 1) + (*scaling_list_dc_coeff[size_id - 2])[matrix_id] = 16; + } + } else { + int next_coef = 8; + int coef_num = MIN2(64, (1 << (4 + (size_id << 1)))); + + if (size_id > 1) { + /* scaling_list_dc_coef_minus8 */ + next_coef = vl_rbsp_se(rbsp) + 8; + (*scaling_list_dc_coeff[size_id - 2])[matrix_id] = next_coef; + } + + for (i = 0; i < coef_num; ++i) { + /* scaling_list_delta_coef */ + next_coef = (next_coef + vl_rbsp_se(rbsp) + 256) % 256; + (*scaling_list_data[size_id])[matrix_id][i] = next_coef; + } + } + } + } + + for (i = 0; i < 6; ++i) + memcpy(sps->ScalingList4x4[i], scaling_list4x4[i], 16); + + return; +} + +static void st_ref_pic_set(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp, + struct ref_pic_set *rps, struct pipe_h265_sps *sps, + unsigned idx) +{ + bool inter_rps_pred_flag; + unsigned delta_idx_minus1; + int delta_poc; + int i; + + inter_rps_pred_flag = (idx != 0) ? (vl_rbsp_u(rbsp, 1)) : false; + + if (inter_rps_pred_flag) { + struct ref_pic_set *ref_rps; + unsigned sign, abs; + int delta_rps; + bool used; + int j; + + if (idx == sps->num_short_term_ref_pic_sets) + delta_idx_minus1 = vl_rbsp_ue(rbsp); + else + delta_idx_minus1 = 0; + + ref_rps = (struct ref_pic_set *) + priv->codec_data.h265.ref_pic_set_list + idx - (delta_idx_minus1 + 1); + + /* delta_rps_sign */ + sign = vl_rbsp_u(rbsp, 1); + /* abs_delta_rps_minus1 */ + abs = vl_rbsp_ue(rbsp); + delta_rps = (1 - 2 * sign) * (abs + 1); + + rps->num_neg_pics = 0; + rps->num_pos_pics = 0; + rps->num_pics = 0; + + for(i = 0 ; i <= ref_rps->num_pics; ++i) { + /* used_by_curr_pic_flag */ + if (!vl_rbsp_u(rbsp, 1)) + /* use_delta_flag */ + vl_rbsp_u(rbsp, 1); + else { + delta_poc = delta_rps + + ((i < ref_rps->num_pics)? ref_rps->delta_poc[i] : 0); + rps->delta_poc[rps->num_pics] = delta_poc; + rps->used[rps->num_pics] = true; + if (delta_poc < 0) + rps->num_neg_pics++; + else + rps->num_pos_pics++; + rps->num_pics++; + } + } + + rps->num_delta_poc = ref_rps->num_pics; + + /* sort delta poc */ + for (i = 1; i < rps->num_pics; ++i) { + delta_poc = rps->delta_poc[i]; + used = rps->used[i]; + for (j = i - 1; j >= 0; j--) { + if (delta_poc < rps->delta_poc[j]) { + rps->delta_poc[j + 1] = rps->delta_poc[j]; + rps->used[j + 1] = rps->used[j]; + rps->delta_poc[j] = delta_poc; + rps->used[j] = used; + } + } + } + + for (i = 0 , j = rps->num_neg_pics - 1; + i < rps->num_neg_pics >> 1; i++, j--) { + delta_poc = rps->delta_poc[i]; + used = rps->used[i]; + rps->delta_poc[i] = rps->delta_poc[j]; + rps->used[i] = rps->used[j]; + rps->delta_poc[j] = delta_poc; + rps->used[j] = used; + } + } else { + /* num_negative_pics */ + rps->num_neg_pics = vl_rbsp_ue(rbsp); + /* num_positive_pics */ + rps->num_pos_pics = vl_rbsp_ue(rbsp); + rps->num_pics = rps->num_neg_pics + rps->num_pos_pics; + + delta_poc = 0; + for(i = 0 ; i < rps->num_neg_pics; ++i) { + /* delta_poc_s0_minus1 */ + delta_poc -= (vl_rbsp_ue(rbsp) + 1); + rps->delta_poc[i] = delta_poc; + /* used_by_curr_pic_s0_flag */ + rps->used[i] = vl_rbsp_u(rbsp, 1); + } + + delta_poc = 0; + for(i = rps->num_neg_pics; i < rps->num_pics; ++i) { + /* delta_poc_s1_minus1 */ + delta_poc += (vl_rbsp_ue(rbsp) + 1); + rps->delta_poc[i] = delta_poc; + /* used_by_curr_pic_s1_flag */ + rps->used[i] = vl_rbsp_u(rbsp, 1); + } + } +} + +static struct pipe_h265_sps *seq_parameter_set_id(vid_dec_PrivateType *priv, + struct vl_rbsp *rbsp) +{ + unsigned id = vl_rbsp_ue(rbsp); + + if (id >= ARRAY_SIZE(priv->codec_data.h265.sps)) + return NULL; + + return &priv->codec_data.h265.sps[id]; +} + +static void seq_parameter_set(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp) +{ + struct pipe_h265_sps *sps; + int sps_max_sub_layers_minus1; + unsigned i; + + /* sps_video_parameter_set_id */ + vl_rbsp_u(rbsp, 4); + + /* sps_max_sub_layers_minus1 */ + sps_max_sub_layers_minus1 = vl_rbsp_u(rbsp, 3); + + assert(sps_max_sub_layers_minus1 <= 6); + + /* sps_temporal_id_nesting_flag */ + vl_rbsp_u(rbsp, 1); + + priv->codec_data.h265.level_idc = + profile_tier_level(rbsp, sps_max_sub_layers_minus1); + + sps = seq_parameter_set_id(priv, rbsp); + if (!sps) + return; + + memset(sps, 0, sizeof(*sps)); + + sps->chroma_format_idc = vl_rbsp_ue(rbsp); + + if (sps->chroma_format_idc == 3) + sps->separate_colour_plane_flag = vl_rbsp_u(rbsp, 1); + + priv->codec_data.h265.pic_width_in_luma_samples = + sps->pic_width_in_luma_samples = vl_rbsp_ue(rbsp); + + priv->codec_data.h265.pic_height_in_luma_samples = + sps->pic_height_in_luma_samples = vl_rbsp_ue(rbsp); + + /* conformance_window_flag */ + if (vl_rbsp_u(rbsp, 1)) { + /* conf_win_left_offset */ + vl_rbsp_ue(rbsp); + /* conf_win_right_offset */ + vl_rbsp_ue(rbsp); + /* conf_win_top_offset */ + vl_rbsp_ue(rbsp); + /* conf_win_bottom_offset */ + vl_rbsp_ue(rbsp); + } + + sps->bit_depth_luma_minus8 = vl_rbsp_ue(rbsp); + sps->bit_depth_chroma_minus8 = vl_rbsp_ue(rbsp); + sps->log2_max_pic_order_cnt_lsb_minus4 = vl_rbsp_ue(rbsp); + + /* sps_sub_layer_ordering_info_present_flag */ + i = vl_rbsp_u(rbsp, 1) ? 0 : sps_max_sub_layers_minus1; + for (; i <= sps_max_sub_layers_minus1; ++i) { + sps->sps_max_dec_pic_buffering_minus1 = vl_rbsp_ue(rbsp); + /* sps_max_num_reorder_pics */ + vl_rbsp_ue(rbsp); + /* sps_max_latency_increase_plus */ + vl_rbsp_ue(rbsp); + } + + sps->log2_min_luma_coding_block_size_minus3 = vl_rbsp_ue(rbsp); + sps->log2_diff_max_min_luma_coding_block_size = vl_rbsp_ue(rbsp); + sps->log2_min_transform_block_size_minus2 = vl_rbsp_ue(rbsp); + sps->log2_diff_max_min_transform_block_size = vl_rbsp_ue(rbsp); + sps->max_transform_hierarchy_depth_inter = vl_rbsp_ue(rbsp); + sps->max_transform_hierarchy_depth_intra = vl_rbsp_ue(rbsp); + + sps->scaling_list_enabled_flag = vl_rbsp_u(rbsp, 1); + if (sps->scaling_list_enabled_flag) + /* sps_scaling_list_data_present_flag */ + if (vl_rbsp_u(rbsp, 1)) + scaling_list_data(priv, rbsp, sps); + + sps->amp_enabled_flag = vl_rbsp_u(rbsp, 1); + sps->sample_adaptive_offset_enabled_flag = vl_rbsp_u(rbsp, 1); + sps->pcm_enabled_flag = vl_rbsp_u(rbsp, 1); + if (sps->pcm_enabled_flag) { + sps->pcm_sample_bit_depth_luma_minus1 = vl_rbsp_u(rbsp, 4); + sps->pcm_sample_bit_depth_chroma_minus1 = vl_rbsp_u(rbsp, 4); + sps->log2_min_pcm_luma_coding_block_size_minus3 = vl_rbsp_ue(rbsp); + sps->log2_diff_max_min_pcm_luma_coding_block_size = vl_rbsp_ue(rbsp); + sps->pcm_loop_filter_disabled_flag = vl_rbsp_u(rbsp, 1); + } + + sps->num_short_term_ref_pic_sets = vl_rbsp_ue(rbsp); + + for (i = 0; i < sps->num_short_term_ref_pic_sets; ++i) { + struct ref_pic_set *rps; + + rps = (struct ref_pic_set *) + priv->codec_data.h265.ref_pic_set_list + i; + st_ref_pic_set(priv, rbsp, rps, sps, i); + } + + sps->long_term_ref_pics_present_flag = vl_rbsp_u(rbsp, 1); + if (sps->long_term_ref_pics_present_flag) { + sps->num_long_term_ref_pics_sps = vl_rbsp_ue(rbsp); + for (i = 0; i < sps->num_long_term_ref_pics_sps; ++i) { + /* lt_ref_pic_poc_lsb_sps */ + vl_rbsp_u(rbsp, sps->log2_max_pic_order_cnt_lsb_minus4 + 4); + /* used_by_curr_pic_lt_sps_flag */ + vl_rbsp_u(rbsp, 1); + } + } + + sps->sps_temporal_mvp_enabled_flag = vl_rbsp_u(rbsp, 1); + sps->strong_intra_smoothing_enabled_flag = vl_rbsp_u(rbsp, 1); +} + +static struct pipe_h265_pps *pic_parameter_set_id(vid_dec_PrivateType *priv, + struct vl_rbsp *rbsp) +{ + unsigned id = vl_rbsp_ue(rbsp); + + if (id >= ARRAY_SIZE(priv->codec_data.h265.pps)) + return NULL; + + return &priv->codec_data.h265.pps[id]; +} + +static void picture_parameter_set(vid_dec_PrivateType *priv, + struct vl_rbsp *rbsp) +{ + struct pipe_h265_sps *sps; + struct pipe_h265_pps *pps; + int i; + + pps = pic_parameter_set_id(priv, rbsp); + if (!pps) + return; + + memset(pps, 0, sizeof(*pps)); + sps = pps->sps = seq_parameter_set_id(priv, rbsp); + if (!sps) + return; + + pps->dependent_slice_segments_enabled_flag = vl_rbsp_u(rbsp, 1); + pps->output_flag_present_flag = vl_rbsp_u(rbsp, 1); + pps->num_extra_slice_header_bits = vl_rbsp_u(rbsp, 3); + pps->sign_data_hiding_enabled_flag = vl_rbsp_u(rbsp, 1); + pps->cabac_init_present_flag = vl_rbsp_u(rbsp, 1); + + pps->num_ref_idx_l0_default_active_minus1 = vl_rbsp_ue(rbsp); + pps->num_ref_idx_l1_default_active_minus1 = vl_rbsp_ue(rbsp); + pps->init_qp_minus26 = vl_rbsp_se(rbsp); + pps->constrained_intra_pred_flag = vl_rbsp_u(rbsp, 1); + pps->transform_skip_enabled_flag = vl_rbsp_u(rbsp, 1); + + pps->cu_qp_delta_enabled_flag = vl_rbsp_u(rbsp, 1); + if (pps->cu_qp_delta_enabled_flag) + pps->diff_cu_qp_delta_depth = vl_rbsp_ue(rbsp); + + pps->pps_cb_qp_offset = vl_rbsp_se(rbsp); + pps->pps_cr_qp_offset = vl_rbsp_se(rbsp); + pps->pps_slice_chroma_qp_offsets_present_flag = vl_rbsp_u(rbsp, 1); + + pps->weighted_pred_flag = vl_rbsp_u(rbsp, 1); + pps->weighted_bipred_flag = vl_rbsp_u(rbsp, 1); + + pps->transquant_bypass_enabled_flag = vl_rbsp_u(rbsp, 1); + pps->tiles_enabled_flag = vl_rbsp_u(rbsp, 1); + pps->entropy_coding_sync_enabled_flag = vl_rbsp_u(rbsp, 1); + + if (pps->tiles_enabled_flag) { + pps->num_tile_columns_minus1 = vl_rbsp_ue(rbsp); + pps->num_tile_rows_minus1 = vl_rbsp_ue(rbsp); + + pps->uniform_spacing_flag = vl_rbsp_u(rbsp, 1); + if (!pps->uniform_spacing_flag) { + for (i = 0; i < pps->num_tile_columns_minus1; ++i) + pps->column_width_minus1[i] = vl_rbsp_ue(rbsp); + + for (i = 0; i < pps->num_tile_rows_minus1; ++i) + pps->row_height_minus1[i] = vl_rbsp_ue(rbsp); + } + + if (!pps->num_tile_columns_minus1 || !pps->num_tile_rows_minus1) + pps->loop_filter_across_tiles_enabled_flag = vl_rbsp_u(rbsp, 1); + } + + pps->pps_loop_filter_across_slices_enabled_flag = vl_rbsp_u(rbsp, 1); + + pps->deblocking_filter_control_present_flag = vl_rbsp_u(rbsp, 1); + if (pps->deblocking_filter_control_present_flag) { + pps->deblocking_filter_override_enabled_flag = vl_rbsp_u(rbsp, 1); + pps->pps_deblocking_filter_disabled_flag = vl_rbsp_u(rbsp, 1); + if (!pps->pps_deblocking_filter_disabled_flag) { + pps->pps_beta_offset_div2 = vl_rbsp_se(rbsp); + pps->pps_tc_offset_div2 = vl_rbsp_se(rbsp); + } + } + + /* pps_scaling_list_data_present_flag */ + if (vl_rbsp_u(rbsp, 1)) + scaling_list_data(priv, rbsp, sps); + + pps->lists_modification_present_flag = vl_rbsp_u(rbsp, 1); + pps->log2_parallel_merge_level_minus2 = vl_rbsp_ue(rbsp); + pps->slice_segment_header_extension_present_flag = vl_rbsp_u(rbsp, 1); +} + +static void vid_dec_h265_BeginFrame(vid_dec_PrivateType *priv) +{ + if (priv->frame_started) + return; + + if (!priv->codec) { + struct pipe_video_codec templat = {}; + omx_base_video_PortType *port = (omx_base_video_PortType *) + priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; + + templat.profile = priv->profile; + templat.entrypoint = PIPE_VIDEO_ENTRYPOINT_BITSTREAM; + templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; + templat.expect_chunked_decode = true; + templat.width = priv->codec_data.h265.pic_width_in_luma_samples; + templat.height = priv->codec_data.h265.pic_height_in_luma_samples; + templat.level = priv->codec_data.h265.level_idc; + priv->codec = priv->pipe->create_video_codec(priv->pipe, &templat); + + /* disable transcode tunnel if video size is different from coded size */ + if (priv->codec_data.h265.pic_width_in_luma_samples != + port->sPortParam.format.video.nFrameWidth || + priv->codec_data.h265.pic_height_in_luma_samples != + port->sPortParam.format.video.nFrameHeight) + priv->disable_tunnel = true; + } + + vid_dec_NeedTarget(priv); + + if (priv->first_buf_in_frame) + priv->timestamp = priv->timestamps[0]; + priv->first_buf_in_frame = false; + + priv->codec->begin_frame(priv->codec, priv->target, &priv->picture.base); + priv->frame_started = true; +} + +static struct pipe_video_buffer *vid_dec_h265_Flush(vid_dec_PrivateType *priv, + OMX_TICKS *timestamp) +{ + struct dpb_list *entry, *result = NULL; + struct pipe_video_buffer *buf; + + /* search for the lowest poc and break on zeros */ + LIST_FOR_EACH_ENTRY(entry, &priv->codec_data.h265.dpb_list, list) { + + if (result && entry->poc == 0) + break; + + if (!result || entry->poc < result->poc) + result = entry; + } + + if (!result) + return NULL; + + buf = result->buffer; + if (timestamp) + *timestamp = result->timestamp; + + --priv->codec_data.h265.dpb_num; + list_del(&result->list); + FREE(result); + + return buf; +} + +static void vid_dec_h265_EndFrame(vid_dec_PrivateType *priv) +{ + struct dpb_list *entry = NULL; + struct pipe_video_buffer *tmp; + struct ref_pic_set *rps; + int i; + OMX_TICKS timestamp; + + if (!priv->frame_started) + return; + + priv->picture.h265.NumPocStCurrBefore = 0; + priv->picture.h265.NumPocStCurrAfter = 0; + memset(priv->picture.h265.RefPicSetStCurrBefore, 0, 8); + memset(priv->picture.h265.RefPicSetStCurrAfter, 0, 8); + for (i = 0; i < MAX_NUM_REF_PICS; ++i) { + priv->picture.h265.ref[i] = NULL; + priv->picture.h265.PicOrderCntVal[i] = 0; + } + + rps = priv->codec_data.h265.rps; + + if (rps) { + unsigned bf = 0, af = 0; + + priv->picture.h265.NumDeltaPocsOfRefRpsIdx = rps->num_delta_poc; + for (i = 0; i < rps->num_pics; ++i) { + priv->picture.h265.PicOrderCntVal[i] = + rps->delta_poc[i] + get_poc(priv); + + LIST_FOR_EACH_ENTRY(entry, &priv->codec_data.h265.dpb_list, list) { + if (entry->poc == priv->picture.h265.PicOrderCntVal[i]) { + priv->picture.h265.ref[i] = entry->buffer; + break; + } + } + + if (rps->used[i]) { + if (i < rps->num_neg_pics) { + priv->picture.h265.NumPocStCurrBefore++; + priv->picture.h265.RefPicSetStCurrBefore[bf++] = i; + } else { + priv->picture.h265.NumPocStCurrAfter++; + priv->picture.h265.RefPicSetStCurrAfter[af++] = i; + } + } + } + } + + priv->codec->end_frame(priv->codec, priv->target, &priv->picture.base); + priv->frame_started = false; + + /* add the decoded picture to the dpb list */ + entry = CALLOC_STRUCT(dpb_list); + if (!entry) + return; + + priv->first_buf_in_frame = true; + entry->buffer = priv->target; + entry->timestamp = priv->timestamp; + entry->poc = get_poc(priv); + + list_addtail(&entry->list, &priv->codec_data.h265.dpb_list); + ++priv->codec_data.h265.dpb_num; + priv->target = NULL; + + if (priv->codec_data.h265.dpb_num <= DPB_MAX_SIZE) + return; + + tmp = priv->in_buffers[0]->pInputPortPrivate; + priv->in_buffers[0]->pInputPortPrivate = vid_dec_h265_Flush(priv, ×tamp); + priv->in_buffers[0]->nTimeStamp = timestamp; + priv->target = tmp; + priv->frame_finished = priv->in_buffers[0]->pInputPortPrivate != NULL; + if (priv->frame_finished && + (priv->in_buffers[0]->nFlags & OMX_BUFFERFLAG_EOS)) + FREE(priv->codec_data.h265.ref_pic_set_list); +} + +static void slice_header(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp, + unsigned nal_unit_type) +{ + struct pipe_h265_pps *pps; + struct pipe_h265_sps *sps; + bool first_slice_segment_in_pic_flag; + bool dependent_slice_segment_flag = false; + struct ref_pic_set *rps; + unsigned poc_lsb, poc_msb, slice_prev_poc; + unsigned max_poc_lsb, prev_poc_lsb, prev_poc_msb; + unsigned num_st_rps; + int i; + + if (priv->picture.h265.IDRPicFlag != is_idr_picture(nal_unit_type)) + vid_dec_h265_EndFrame(priv); + + priv->picture.h265.IDRPicFlag = is_idr_picture(nal_unit_type); + + first_slice_segment_in_pic_flag = vl_rbsp_u(rbsp, 1); + + if (is_rap_picture(nal_unit_type)) + /* no_output_of_prior_pics_flag */ + vl_rbsp_u(rbsp, 1); + + pps = pic_parameter_set_id(priv, rbsp); + if (!pps) + return; + + sps = pps->sps; + if (!sps) + return; + + if (pps != priv->picture.h265.pps) + vid_dec_h265_EndFrame(priv); + + priv->picture.h265.pps = pps; + + if (priv->picture.h265.RAPPicFlag != is_rap_picture(nal_unit_type)) + vid_dec_h265_EndFrame(priv); + priv->picture.h265.RAPPicFlag = is_rap_picture(nal_unit_type); + + num_st_rps = sps->num_short_term_ref_pic_sets; + + if (priv->picture.h265.CurrRpsIdx != num_st_rps) + vid_dec_h265_EndFrame(priv); + priv->picture.h265.CurrRpsIdx = num_st_rps; + + if (!first_slice_segment_in_pic_flag) { + int size, num; + int bits_slice_segment_address = 0; + + if (pps->dependent_slice_segments_enabled_flag) + dependent_slice_segment_flag = vl_rbsp_u(rbsp, 1); + + size = 1 << (sps->log2_min_luma_coding_block_size_minus3 + 3 + + sps->log2_diff_max_min_luma_coding_block_size); + + num = ((sps->pic_width_in_luma_samples + size - 1) / size) * + ((sps->pic_height_in_luma_samples + size - 1) / size); + + while (num > (1 << bits_slice_segment_address)) + bits_slice_segment_address++; + + /* slice_segment_address */ + vl_rbsp_u(rbsp, bits_slice_segment_address); + } + + if (dependent_slice_segment_flag) + return; + + for (i = 0; i < pps->num_extra_slice_header_bits; ++i) + /* slice_reserved_flag */ + vl_rbsp_u(rbsp, 1); + + /* slice_type */ + vl_rbsp_ue(rbsp); + + if (pps->output_flag_present_flag) + /* pic output flag */ + vl_rbsp_u(rbsp, 1); + + if (sps->separate_colour_plane_flag) + /* colour_plane_id */ + vl_rbsp_u(rbsp, 2); + + if (is_idr_picture(nal_unit_type)) { + set_poc(priv, nal_unit_type, 0); + return; + } + + /* slice_pic_order_cnt_lsb */ + poc_lsb = + vl_rbsp_u(rbsp, sps->log2_max_pic_order_cnt_lsb_minus4 + 4); + + slice_prev_poc = (int)priv->codec_data.h265.slice_prev_poc; + max_poc_lsb = 1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4); + + prev_poc_lsb = slice_prev_poc & (max_poc_lsb - 1); + prev_poc_msb = slice_prev_poc - prev_poc_lsb; + + if ((poc_lsb < prev_poc_lsb) && + ((prev_poc_lsb - poc_lsb ) >= (max_poc_lsb / 2))) + poc_msb = prev_poc_msb + max_poc_lsb; + + else if ((poc_lsb > prev_poc_lsb ) && + ((poc_lsb - prev_poc_lsb) > (max_poc_lsb / 2))) + poc_msb = prev_poc_msb - max_poc_lsb; + + else + poc_msb = prev_poc_msb; + + if (is_bla_picture(nal_unit_type)) + poc_msb = 0; + + if (get_poc(priv) != poc_msb + poc_lsb) + vid_dec_h265_EndFrame(priv); + + set_poc(priv, nal_unit_type, (poc_msb + poc_lsb)); + + /* short_term_ref_pic_set_sps_flag */ + if (!vl_rbsp_u(rbsp, 1)) { + rps = (struct ref_pic_set *) + priv->codec_data.h265.ref_pic_set_list + num_st_rps; + st_ref_pic_set(priv, rbsp, rps, sps, num_st_rps); + + } else if (num_st_rps > 1) { + int num_bits = 0; + unsigned idx; + + while ((1 << num_bits) < num_st_rps) + num_bits++; + + if (num_bits > 0) + /* short_term_ref_pic_set_idx */ + idx = vl_rbsp_u(rbsp, num_bits); + else + idx = 0; + + rps = (struct ref_pic_set *) + priv->codec_data.h265.ref_pic_set_list + idx; + } else + rps = (struct ref_pic_set *) + priv->codec_data.h265.ref_pic_set_list; + + if (is_bla_picture(nal_unit_type)) { + rps->num_neg_pics = 0; + rps->num_pos_pics = 0; + rps->num_pics = 0; + } + + priv->codec_data.h265.rps = rps; + + return; +} + +static void vid_dec_h265_Decode(vid_dec_PrivateType *priv, + struct vl_vlc *vlc, + unsigned min_bits_left) +{ + unsigned nal_unit_type; + unsigned nuh_layer_id; + unsigned nuh_temporal_id_plus1; + + if (!vl_vlc_search_byte(vlc, vl_vlc_bits_left(vlc) - min_bits_left, 0x00)) + return; + + if (vl_vlc_peekbits(vlc, 24) != 0x000001) { + vl_vlc_eatbits(vlc, 8); + return; + } + + if (priv->slice) { + unsigned bytes = priv->bytes_left - (vl_vlc_bits_left(vlc) / 8); + + priv->codec->decode_bitstream(priv->codec, priv->target, + &priv->picture.base, 1, + &priv->slice, &bytes); + priv->slice = NULL; + } + + vl_vlc_eatbits(vlc, 24); + + /* forbidden_zero_bit */ + vl_vlc_eatbits(vlc, 1); + + if (vl_vlc_valid_bits(vlc) < 15) + vl_vlc_fillbits(vlc); + + nal_unit_type = vl_vlc_get_uimsbf(vlc, 6); + + /* nuh_layer_id */ + nuh_layer_id = vl_vlc_get_uimsbf(vlc, 6); + + /* nuh_temporal_id_plus1 */ + nuh_temporal_id_plus1 = vl_vlc_get_uimsbf(vlc, 3); + priv->codec_data.h265.temporal_id = nuh_temporal_id_plus1 - 1; + + if (!is_slice_picture(nal_unit_type)) + vid_dec_h265_EndFrame(priv); + + if (nal_unit_type == NAL_UNIT_TYPE_SPS) { + struct vl_rbsp rbsp; + + vl_rbsp_init(&rbsp, vlc, ~0); + seq_parameter_set(priv, &rbsp); + + } else if (nal_unit_type == NAL_UNIT_TYPE_PPS) { + struct vl_rbsp rbsp; + + vl_rbsp_init(&rbsp, vlc, ~0); + picture_parameter_set(priv, &rbsp); + + } else if (is_slice_picture(nal_unit_type)) { + unsigned bits = vl_vlc_valid_bits(vlc); + unsigned bytes = bits / 8 + 5; + struct vl_rbsp rbsp; + uint8_t buf[9]; + const void *ptr = buf; + unsigned i; + + buf[0] = 0x0; + buf[1] = 0x0; + buf[2] = 0x1; + buf[3] = nal_unit_type << 1 | nuh_layer_id >> 5; + buf[4] = nuh_layer_id << 3 | nuh_temporal_id_plus1; + for (i = 5; i < bytes; ++i) + buf[i] = vl_vlc_peekbits(vlc, bits) >> ((bytes - i - 1) * 8); + + priv->bytes_left = (vl_vlc_bits_left(vlc) - bits) / 8; + priv->slice = vlc->data; + + vl_rbsp_init(&rbsp, vlc, 128); + slice_header(priv, &rbsp, nal_unit_type); + + vid_dec_h265_BeginFrame(priv); + + priv->codec->decode_bitstream(priv->codec, priv->target, + &priv->picture.base, 1, + &ptr, &bytes); + } + + /* resync to byte boundary */ + vl_vlc_eatbits(vlc, vl_vlc_valid_bits(vlc) % 8); +} + +void vid_dec_h265_Init(vid_dec_PrivateType *priv) +{ + priv->picture.base.profile = PIPE_VIDEO_PROFILE_HEVC_MAIN; + + list_inithead(&priv->codec_data.h265.dpb_list); + priv->codec_data.h265.ref_pic_set_list = (struct ref_pic_set *) + CALLOC(MAX_NUM_REF_PICS, sizeof(struct ref_pic_set)); + + priv->Decode = vid_dec_h265_Decode; + priv->EndFrame = vid_dec_h265_EndFrame; + priv->Flush = vid_dec_h265_Flush; + priv->first_buf_in_frame = true; +} diff --git a/src/gallium/frontends/omx/bellagio/vid_dec_mpeg12.c b/src/gallium/frontends/omx/bellagio/vid_dec_mpeg12.c new file mode 100644 index 00000000000..f64c2b83fa5 --- /dev/null +++ b/src/gallium/frontends/omx/bellagio/vid_dec_mpeg12.c @@ -0,0 +1,383 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/* + * Authors: + * Christian König + * + */ + +#include "pipe/p_video_codec.h" +#include "vl/vl_vlc.h" +#include "vl/vl_zscan.h" + +#include "vid_dec.h" + +static uint8_t default_intra_matrix[64] = { + 8, 16, 19, 22, 26, 27, 29, 34, + 16, 16, 22, 24, 27, 29, 34, 37, + 19, 22, 26, 27, 29, 34, 34, 38, + 22, 22, 26, 27, 29, 34, 37, 40, + 22, 26, 27, 29, 32, 35, 40, 48, + 26, 27, 29, 32, 35, 40, 48, 58, + 26, 27, 29, 34, 38, 46, 56, 69, + 27, 29, 35, 38, 46, 56, 69, 83 +}; + +static uint8_t default_non_intra_matrix[64] = { + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16 +}; + +static void vid_dec_mpeg12_Decode(vid_dec_PrivateType *priv, struct vl_vlc *vlc, unsigned min_bits_left); +static void vid_dec_mpeg12_EndFrame(vid_dec_PrivateType *priv); +static struct pipe_video_buffer *vid_dec_mpeg12_Flush(vid_dec_PrivateType *priv, OMX_TICKS *timestamp); + +void vid_dec_mpeg12_Init(vid_dec_PrivateType *priv) +{ + struct pipe_video_codec templat = {}; + omx_base_video_PortType *port; + + port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; + templat.profile = priv->profile; + templat.entrypoint = PIPE_VIDEO_ENTRYPOINT_BITSTREAM; + templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; + templat.max_references = 2; + templat.expect_chunked_decode = true; + templat.width = port->sPortParam.format.video.nFrameWidth; + templat.height = port->sPortParam.format.video.nFrameHeight; + + priv->codec = priv->pipe->create_video_codec(priv->pipe, &templat); + + priv->picture.base.profile = PIPE_VIDEO_PROFILE_MPEG2_MAIN; + priv->picture.mpeg12.intra_matrix = default_intra_matrix; + priv->picture.mpeg12.non_intra_matrix = default_non_intra_matrix; + + priv->Decode = vid_dec_mpeg12_Decode; + priv->EndFrame = vid_dec_mpeg12_EndFrame; + priv->Flush = vid_dec_mpeg12_Flush; +} + +static void BeginFrame(vid_dec_PrivateType *priv) +{ + if (priv->picture.mpeg12.picture_coding_type != PIPE_MPEG12_PICTURE_CODING_TYPE_B) { + priv->picture.mpeg12.ref[0] = priv->picture.mpeg12.ref[1]; + priv->picture.mpeg12.ref[1] = NULL; + } + + if (priv->target == priv->picture.mpeg12.ref[0]) { + struct pipe_video_buffer *tmp = priv->target; + priv->target = priv->shadow; + priv->shadow = tmp; + } + + vid_dec_NeedTarget(priv); + + priv->codec->begin_frame(priv->codec, priv->target, &priv->picture.base); + priv->frame_started = true; +} + +static void vid_dec_mpeg12_EndFrame(vid_dec_PrivateType *priv) +{ + struct pipe_video_buffer *done; + + priv->codec->end_frame(priv->codec, priv->target, &priv->picture.base); + priv->frame_started = false; + + if (priv->picture.mpeg12.picture_coding_type != PIPE_MPEG12_PICTURE_CODING_TYPE_B) { + + priv->picture.mpeg12.ref[1] = priv->target; + done = priv->picture.mpeg12.ref[0]; + if (!done) { + priv->target = NULL; + return; + } + + } else + done = priv->target; + + priv->frame_finished = true; + priv->target = priv->in_buffers[0]->pInputPortPrivate; + priv->in_buffers[0]->pInputPortPrivate = done; +} + +static struct pipe_video_buffer *vid_dec_mpeg12_Flush(vid_dec_PrivateType *priv, OMX_TICKS *timestamp) +{ + struct pipe_video_buffer *result = priv->picture.mpeg12.ref[1]; + priv->picture.mpeg12.ref[1] = NULL; + if (timestamp) + *timestamp = OMX_VID_DEC_TIMESTAMP_INVALID; + return result; +} + +static void vid_dec_mpeg12_Decode(vid_dec_PrivateType *priv, struct vl_vlc *vlc, unsigned min_bits_left) +{ + uint8_t code; + unsigned i; + + if (!vl_vlc_search_byte(vlc, vl_vlc_bits_left(vlc) - min_bits_left, 0x00)) + return; + + if (vl_vlc_peekbits(vlc, 24) != 0x000001) { + vl_vlc_eatbits(vlc, 8); + return; + } + + if (priv->slice) { + unsigned bytes = priv->bytes_left - (vl_vlc_bits_left(vlc) / 8); + priv->codec->decode_bitstream(priv->codec, priv->target, &priv->picture.base, + 1, &priv->slice, &bytes); + priv->slice = NULL; + } + + vl_vlc_eatbits(vlc, 24); + code = vl_vlc_get_uimsbf(vlc, 8); + + if (priv->frame_started && (code == 0x00 || code > 0xAF)) + vid_dec_mpeg12_EndFrame(priv); + + if (code == 0xB3) { + /* sequence header code */ + vl_vlc_fillbits(vlc); + + /* horizontal_size_value */ + vl_vlc_get_uimsbf(vlc, 12); + + /* vertical_size_value */ + vl_vlc_get_uimsbf(vlc, 12); + + /* aspect_ratio_information */ + vl_vlc_get_uimsbf(vlc, 4); + + /* frame_rate_code */ + vl_vlc_get_uimsbf(vlc, 4); + + vl_vlc_fillbits(vlc); + + /* bit_rate_value */ + vl_vlc_get_uimsbf(vlc, 18); + + /* marker_bit */ + vl_vlc_get_uimsbf(vlc, 1); + + /* vbv_buffer_size_value */ + vl_vlc_get_uimsbf(vlc, 10); + + /* constrained_parameters_flag */ + vl_vlc_get_uimsbf(vlc, 1); + + vl_vlc_fillbits(vlc); + + /* load_intra_quantiser_matrix */ + if (vl_vlc_get_uimsbf(vlc, 1)) { + /* intra_quantiser_matrix */ + priv->picture.mpeg12.intra_matrix = priv->codec_data.mpeg12.intra_matrix; + for (i = 0; i < 64; ++i) { + priv->codec_data.mpeg12.intra_matrix[vl_zscan_normal[i]] = vl_vlc_get_uimsbf(vlc, 8); + vl_vlc_fillbits(vlc); + } + } else + priv->picture.mpeg12.intra_matrix = default_intra_matrix; + + /* load_non_intra_quantiser_matrix */ + if (vl_vlc_get_uimsbf(vlc, 1)) { + /* non_intra_quantiser_matrix */ + priv->picture.mpeg12.non_intra_matrix = priv->codec_data.mpeg12.non_intra_matrix; + for (i = 0; i < 64; ++i) { + priv->codec_data.mpeg12.non_intra_matrix[i] = vl_vlc_get_uimsbf(vlc, 8); + vl_vlc_fillbits(vlc); + } + } else + priv->picture.mpeg12.non_intra_matrix = default_non_intra_matrix; + + } else if (code == 0x00) { + /* picture start code */ + vl_vlc_fillbits(vlc); + + /* temporal_reference */ + vl_vlc_get_uimsbf(vlc, 10); + + priv->picture.mpeg12.picture_coding_type = vl_vlc_get_uimsbf(vlc, 3); + + /* vbv_delay */ + vl_vlc_get_uimsbf(vlc, 16); + + vl_vlc_fillbits(vlc); + if (priv->picture.mpeg12.picture_coding_type == 2 || + priv->picture.mpeg12.picture_coding_type == 3) { + priv->picture.mpeg12.full_pel_forward_vector = vl_vlc_get_uimsbf(vlc, 1); + /* forward_f_code */ + priv->picture.mpeg12.f_code[0][0] = vl_vlc_get_uimsbf(vlc, 3) - 1; + priv->picture.mpeg12.f_code[0][1] = priv->picture.mpeg12.f_code[0][0]; + } else { + priv->picture.mpeg12.full_pel_forward_vector = 0; + priv->picture.mpeg12.f_code[0][1] = priv->picture.mpeg12.f_code[0][0] = 14; + } + + if (priv->picture.mpeg12.picture_coding_type == 3) { + priv->picture.mpeg12.full_pel_backward_vector = vl_vlc_get_uimsbf(vlc, 1); + /* backward_f_code */ + priv->picture.mpeg12.f_code[1][0] = vl_vlc_get_uimsbf(vlc, 3) - 1; + priv->picture.mpeg12.f_code[1][1] = priv->picture.mpeg12.f_code[1][0]; + } else { + priv->picture.mpeg12.full_pel_backward_vector = 0; + priv->picture.mpeg12.f_code[0][1] = priv->picture.mpeg12.f_code[0][0] = 14; + } + + /* extra_bit_picture */ + while (vl_vlc_get_uimsbf(vlc, 1)) { + /* extra_information_picture */ + vl_vlc_get_uimsbf(vlc, 8); + vl_vlc_fillbits(vlc); + } + + } else if (code == 0xB5) { + /* extension start code */ + vl_vlc_fillbits(vlc); + + /* extension_start_code_identifier */ + switch (vl_vlc_get_uimsbf(vlc, 4)) { + case 0x3: /* quant matrix extension */ + + /* load_intra_quantiser_matrix */ + if (vl_vlc_get_uimsbf(vlc, 1)) { + /* intra_quantiser_matrix */ + priv->picture.mpeg12.intra_matrix = priv->codec_data.mpeg12.intra_matrix; + for (i = 0; i < 64; ++i) { + priv->codec_data.mpeg12.intra_matrix[vl_zscan_normal[i]] = vl_vlc_get_uimsbf(vlc, 8); + vl_vlc_fillbits(vlc); + } + } else + priv->picture.mpeg12.intra_matrix = default_intra_matrix; + + /* load_non_intra_quantiser_matrix */ + if (vl_vlc_get_uimsbf(vlc, 1)) { + /* non_intra_quantiser_matrix */ + priv->picture.mpeg12.non_intra_matrix = priv->codec_data.mpeg12.non_intra_matrix; + for (i = 0; i < 64; ++i) { + priv->codec_data.mpeg12.non_intra_matrix[i] = vl_vlc_get_uimsbf(vlc, 8); + vl_vlc_fillbits(vlc); + } + } else + priv->picture.mpeg12.intra_matrix = default_non_intra_matrix; + + break; + + case 0x8: /* picture coding extension */ + + priv->picture.mpeg12.f_code[0][0] = vl_vlc_get_uimsbf(vlc, 4) - 1; + priv->picture.mpeg12.f_code[0][1] = vl_vlc_get_uimsbf(vlc, 4) - 1; + priv->picture.mpeg12.f_code[1][0] = vl_vlc_get_uimsbf(vlc, 4) - 1; + priv->picture.mpeg12.f_code[1][1] = vl_vlc_get_uimsbf(vlc, 4) - 1; + priv->picture.mpeg12.intra_dc_precision = vl_vlc_get_uimsbf(vlc, 2); + priv->picture.mpeg12.picture_structure = vl_vlc_get_uimsbf(vlc, 2); + priv->picture.mpeg12.top_field_first = vl_vlc_get_uimsbf(vlc, 1); + priv->picture.mpeg12.frame_pred_frame_dct = vl_vlc_get_uimsbf(vlc, 1); + priv->picture.mpeg12.concealment_motion_vectors = vl_vlc_get_uimsbf(vlc, 1); + priv->picture.mpeg12.q_scale_type = vl_vlc_get_uimsbf(vlc, 1); + priv->picture.mpeg12.intra_vlc_format = vl_vlc_get_uimsbf(vlc, 1); + priv->picture.mpeg12.alternate_scan = vl_vlc_get_uimsbf(vlc, 1); + + /* repeat_first_field */ + vl_vlc_get_uimsbf(vlc, 1); + + /* chroma_420_type */ + vl_vlc_get_uimsbf(vlc, 1); + + vl_vlc_fillbits(vlc); + + /* progressive_frame */ + vl_vlc_get_uimsbf(vlc, 1); + + /* composite_display_flag */ + if (vl_vlc_get_uimsbf(vlc, 1)) { + + /* v_axis */ + vl_vlc_get_uimsbf(vlc, 1); + + /* field_sequence */ + vl_vlc_get_uimsbf(vlc, 3); + + /* sub_carrier */ + vl_vlc_get_uimsbf(vlc, 1); + + /* burst_amplitude */ + vl_vlc_get_uimsbf(vlc, 7); + + /* sub_carrier_phase */ + vl_vlc_get_uimsbf(vlc, 8); + } + break; + } + + } else if (code <= 0xAF) { + /* slice start */ + unsigned bytes = (vl_vlc_valid_bits(vlc) / 8) + 4; + uint8_t buf[12]; + const void *ptr = buf; + unsigned i; + + if (!priv->frame_started) + BeginFrame(priv); + + buf[0] = 0x00; + buf[1] = 0x00; + buf[2] = 0x01; + buf[3] = code; + for (i = 4; i < bytes; ++i) + buf[i] = vl_vlc_get_uimsbf(vlc, 8); + + priv->codec->decode_bitstream(priv->codec, priv->target, &priv->picture.base, + 1, &ptr, &bytes); + + priv->bytes_left = vl_vlc_bits_left(vlc) / 8; + priv->slice = vlc->data; + + } else if (code == 0xB2) { + /* user data start */ + + } else if (code == 0xB4) { + /* sequence error */ + } else if (code == 0xB7) { + /* sequence end */ + } else if (code == 0xB8) { + /* group start */ + } else if (code >= 0xB9) { + /* system start */ + } else { + /* reserved */ + } + + /* resync to byte boundary */ + vl_vlc_eatbits(vlc, vl_vlc_valid_bits(vlc) % 8); +} diff --git a/src/gallium/frontends/omx/bellagio/vid_enc.c b/src/gallium/frontends/omx/bellagio/vid_enc.c new file mode 100644 index 00000000000..7f4a673d3cd --- /dev/null +++ b/src/gallium/frontends/omx/bellagio/vid_enc.c @@ -0,0 +1,940 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/* + * Authors: + * Christian König + * + */ + + +#include + +#include + +/* bellagio defines a DEBUG macro that we don't want */ +#ifndef DEBUG +#include +#undef DEBUG +#else +#include +#endif + +#include + +#include "pipe/p_screen.h" +#include "pipe/p_video_codec.h" +#include "util/u_memory.h" + +#include "entrypoint.h" +#include "vid_enc.h" +#include "vid_omx_common.h" +#include "vid_enc_common.h" + +static OMX_ERRORTYPE vid_enc_Constructor(OMX_COMPONENTTYPE *comp, OMX_STRING name); +static OMX_ERRORTYPE vid_enc_Destructor(OMX_COMPONENTTYPE *comp); +static OMX_ERRORTYPE vid_enc_SetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param); +static OMX_ERRORTYPE vid_enc_GetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param); +static OMX_ERRORTYPE vid_enc_SetConfig(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR config); +static OMX_ERRORTYPE vid_enc_GetConfig(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR config); +static OMX_ERRORTYPE vid_enc_MessageHandler(OMX_COMPONENTTYPE *comp, internalRequestMessageType *msg); +static OMX_ERRORTYPE vid_enc_AllocateInBuffer(omx_base_PortType *port, OMX_INOUT OMX_BUFFERHEADERTYPE **buf, + OMX_IN OMX_U32 idx, OMX_IN OMX_PTR private, OMX_IN OMX_U32 size); +static OMX_ERRORTYPE vid_enc_UseInBuffer(omx_base_PortType *port, OMX_BUFFERHEADERTYPE **buf, OMX_U32 idx, + OMX_PTR private, OMX_U32 size, OMX_U8 *mem); +static OMX_ERRORTYPE vid_enc_FreeInBuffer(omx_base_PortType *port, OMX_U32 idx, OMX_BUFFERHEADERTYPE *buf); +static OMX_ERRORTYPE vid_enc_EncodeFrame(omx_base_PortType *port, OMX_BUFFERHEADERTYPE *buf); +static OMX_ERRORTYPE vid_enc_AllocateOutBuffer(omx_base_PortType *comp, OMX_INOUT OMX_BUFFERHEADERTYPE **buf, + OMX_IN OMX_U32 idx, OMX_IN OMX_PTR private, OMX_IN OMX_U32 size); +static OMX_ERRORTYPE vid_enc_FreeOutBuffer(omx_base_PortType *port, OMX_U32 idx, OMX_BUFFERHEADERTYPE *buf); +static void vid_enc_BufferEncoded(OMX_COMPONENTTYPE *comp, OMX_BUFFERHEADERTYPE* input, OMX_BUFFERHEADERTYPE* output); + +OMX_ERRORTYPE vid_enc_LoaderComponent(stLoaderComponentType *comp) +{ + comp->componentVersion.s.nVersionMajor = 0; + comp->componentVersion.s.nVersionMinor = 0; + comp->componentVersion.s.nRevision = 0; + comp->componentVersion.s.nStep = 1; + comp->name_specific_length = 1; + comp->constructor = vid_enc_Constructor; + + comp->name = CALLOC(1, OMX_MAX_STRINGNAME_SIZE); + if (!comp->name) + return OMX_ErrorInsufficientResources; + + comp->name_specific = CALLOC(1, sizeof(char *)); + if (!comp->name_specific) + goto error_arrays; + + comp->role_specific = CALLOC(1, sizeof(char *)); + if (!comp->role_specific) + goto error_arrays; + + comp->name_specific[0] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE); + if (comp->name_specific[0] == NULL) + goto error_specific; + + comp->role_specific[0] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE); + if (comp->role_specific[0] == NULL) + goto error_specific; + + strcpy(comp->name, OMX_VID_ENC_BASE_NAME); + strcpy(comp->name_specific[0], OMX_VID_ENC_AVC_NAME); + strcpy(comp->role_specific[0], OMX_VID_ENC_AVC_ROLE); + + return OMX_ErrorNone; + +error_specific: + FREE(comp->role_specific[0]); + FREE(comp->name_specific[0]); + +error_arrays: + FREE(comp->role_specific); + FREE(comp->name_specific); + + FREE(comp->name); + + return OMX_ErrorInsufficientResources; +} + +static OMX_ERRORTYPE vid_enc_Constructor(OMX_COMPONENTTYPE *comp, OMX_STRING name) +{ + vid_enc_PrivateType *priv; + omx_base_video_PortType *port; + struct pipe_screen *screen; + OMX_ERRORTYPE r; + int i; + + assert(!comp->pComponentPrivate); + + priv = comp->pComponentPrivate = CALLOC(1, sizeof(vid_enc_PrivateType)); + if (!priv) + return OMX_ErrorInsufficientResources; + + r = omx_base_filter_Constructor(comp, name); + if (r) + return r; + + priv->BufferMgmtCallback = vid_enc_BufferEncoded; + priv->messageHandler = vid_enc_MessageHandler; + priv->destructor = vid_enc_Destructor; + + comp->SetParameter = vid_enc_SetParameter; + comp->GetParameter = vid_enc_GetParameter; + comp->GetConfig = vid_enc_GetConfig; + comp->SetConfig = vid_enc_SetConfig; + + priv->screen = omx_get_screen(); + if (!priv->screen) + return OMX_ErrorInsufficientResources; + + screen = priv->screen->pscreen; + if (!screen->get_video_param(screen, PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH, + PIPE_VIDEO_ENTRYPOINT_ENCODE, PIPE_VIDEO_CAP_SUPPORTED)) + return OMX_ErrorBadParameter; + + priv->s_pipe = pipe_create_multimedia_context(screen); + if (!priv->s_pipe) + return OMX_ErrorInsufficientResources; + + enc_InitCompute_common(priv); + + if (!vl_compositor_init(&priv->compositor, priv->s_pipe)) { + priv->s_pipe->destroy(priv->s_pipe); + priv->s_pipe = NULL; + return OMX_ErrorInsufficientResources; + } + + if (!vl_compositor_init_state(&priv->cstate, priv->s_pipe)) { + vl_compositor_cleanup(&priv->compositor); + priv->s_pipe->destroy(priv->s_pipe); + priv->s_pipe = NULL; + return OMX_ErrorInsufficientResources; + } + + priv->t_pipe = pipe_create_multimedia_context(screen); + if (!priv->t_pipe) + return OMX_ErrorInsufficientResources; + + priv->sPortTypesParam[OMX_PortDomainVideo].nStartPortNumber = 0; + priv->sPortTypesParam[OMX_PortDomainVideo].nPorts = 2; + priv->ports = CALLOC(2, sizeof(omx_base_PortType *)); + if (!priv->ports) + return OMX_ErrorInsufficientResources; + + for (i = 0; i < 2; ++i) { + priv->ports[i] = CALLOC(1, sizeof(omx_base_video_PortType)); + if (!priv->ports[i]) + return OMX_ErrorInsufficientResources; + + base_video_port_Constructor(comp, &priv->ports[i], i, i == 0); + } + + port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; + port->sPortParam.format.video.nFrameWidth = 176; + port->sPortParam.format.video.nFrameHeight = 144; + port->sPortParam.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; + port->sVideoParam.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; + port->sPortParam.nBufferCountActual = 8; + port->sPortParam.nBufferCountMin = 4; + + port->Port_SendBufferFunction = vid_enc_EncodeFrame; + port->Port_AllocateBuffer = vid_enc_AllocateInBuffer; + port->Port_UseBuffer = vid_enc_UseInBuffer; + port->Port_FreeBuffer = vid_enc_FreeInBuffer; + + port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]; + strcpy(port->sPortParam.format.video.cMIMEType,"video/H264"); + port->sPortParam.format.video.nFrameWidth = 176; + port->sPortParam.format.video.nFrameHeight = 144; + port->sPortParam.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC; + port->sVideoParam.eCompressionFormat = OMX_VIDEO_CodingAVC; + + port->Port_AllocateBuffer = vid_enc_AllocateOutBuffer; + port->Port_FreeBuffer = vid_enc_FreeOutBuffer; + + priv->bitrate.eControlRate = OMX_Video_ControlRateDisable; + priv->bitrate.nTargetBitrate = 0; + + priv->quant.nQpI = OMX_VID_ENC_QUANT_I_FRAMES_DEFAULT; + priv->quant.nQpP = OMX_VID_ENC_QUANT_P_FRAMES_DEFAULT; + priv->quant.nQpB = OMX_VID_ENC_QUANT_B_FRAMES_DEFAULT; + + priv->profile_level.eProfile = OMX_VIDEO_AVCProfileBaseline; + priv->profile_level.eLevel = OMX_VIDEO_AVCLevel51; + + priv->force_pic_type.IntraRefreshVOP = OMX_FALSE; + priv->frame_num = 0; + priv->pic_order_cnt = 0; + priv->restricted_b_frames = debug_get_bool_option("OMX_USE_RESTRICTED_B_FRAMES", FALSE); + + priv->scale.xWidth = OMX_VID_ENC_SCALING_WIDTH_DEFAULT; + priv->scale.xHeight = OMX_VID_ENC_SCALING_WIDTH_DEFAULT; + + list_inithead(&priv->free_tasks); + list_inithead(&priv->used_tasks); + list_inithead(&priv->b_frames); + list_inithead(&priv->stacked_tasks); + + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE vid_enc_Destructor(OMX_COMPONENTTYPE *comp) +{ + vid_enc_PrivateType* priv = comp->pComponentPrivate; + int i; + + enc_ReleaseTasks(&priv->free_tasks); + enc_ReleaseTasks(&priv->used_tasks); + enc_ReleaseTasks(&priv->b_frames); + enc_ReleaseTasks(&priv->stacked_tasks); + + if (priv->ports) { + for (i = 0; i < priv->sPortTypesParam[OMX_PortDomainVideo].nPorts; ++i) { + if(priv->ports[i]) + priv->ports[i]->PortDestructor(priv->ports[i]); + } + FREE(priv->ports); + priv->ports=NULL; + } + + for (i = 0; i < OMX_VID_ENC_NUM_SCALING_BUFFERS; ++i) + if (priv->scale_buffer[i]) + priv->scale_buffer[i]->destroy(priv->scale_buffer[i]); + + if (priv->s_pipe) { + vl_compositor_cleanup_state(&priv->cstate); + vl_compositor_cleanup(&priv->compositor); + enc_ReleaseCompute_common(priv); + priv->s_pipe->destroy(priv->s_pipe); + } + + if (priv->t_pipe) + priv->t_pipe->destroy(priv->t_pipe); + + if (priv->screen) + omx_put_screen(); + + return omx_workaround_Destructor(comp); +} + +static OMX_ERRORTYPE enc_AllocateBackTexture(omx_base_PortType *port, + struct pipe_resource **resource, + struct pipe_transfer **transfer, + OMX_U8 **map) +{ + OMX_COMPONENTTYPE* comp = port->standCompContainer; + vid_enc_PrivateType *priv = comp->pComponentPrivate; + struct pipe_resource buf_templ; + struct pipe_box box = {}; + OMX_U8 *ptr; + + memset(&buf_templ, 0, sizeof buf_templ); + buf_templ.target = PIPE_TEXTURE_2D; + buf_templ.format = PIPE_FORMAT_I8_UNORM; + buf_templ.bind = PIPE_BIND_LINEAR; + buf_templ.usage = PIPE_USAGE_STAGING; + buf_templ.flags = 0; + buf_templ.width0 = port->sPortParam.format.video.nFrameWidth; + buf_templ.height0 = port->sPortParam.format.video.nFrameHeight * 3 / 2; + buf_templ.depth0 = 1; + buf_templ.array_size = 1; + + *resource = priv->s_pipe->screen->resource_create(priv->s_pipe->screen, &buf_templ); + if (!*resource) + return OMX_ErrorInsufficientResources; + + box.width = (*resource)->width0; + box.height = (*resource)->height0; + box.depth = (*resource)->depth0; + ptr = priv->s_pipe->transfer_map(priv->s_pipe, *resource, 0, PIPE_TRANSFER_WRITE, &box, transfer); + if (map) + *map = ptr; + + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE vid_enc_SetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param) +{ + OMX_COMPONENTTYPE *comp = handle; + vid_enc_PrivateType *priv = comp->pComponentPrivate; + OMX_ERRORTYPE r; + + if (!param) + return OMX_ErrorBadParameter; + + switch(idx) { + case OMX_IndexParamPortDefinition: { + OMX_PARAM_PORTDEFINITIONTYPE *def = param; + + r = omx_base_component_SetParameter(handle, idx, param); + if (r) + return r; + + if (def->nPortIndex == OMX_BASE_FILTER_INPUTPORT_INDEX) { + omx_base_video_PortType *port; + unsigned framesize; + struct pipe_resource *resource; + struct pipe_transfer *transfer; + + port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; + enc_AllocateBackTexture(priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX], + &resource, &transfer, NULL); + port->sPortParam.format.video.nStride = transfer->stride; + pipe_transfer_unmap(priv->s_pipe, transfer); + pipe_resource_reference(&resource, NULL); + + framesize = port->sPortParam.format.video.nStride * + port->sPortParam.format.video.nFrameHeight; + port->sPortParam.format.video.nSliceHeight = port->sPortParam.format.video.nFrameHeight; + port->sPortParam.nBufferSize = framesize * 3 / 2; + + port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]; + port->sPortParam.nBufferSize = framesize * 512 / (16*16); + + priv->frame_rate = def->format.video.xFramerate; + + priv->callbacks->EventHandler(comp, priv->callbackData, OMX_EventPortSettingsChanged, + OMX_BASE_FILTER_OUTPUTPORT_INDEX, 0, NULL); + } + break; + } + case OMX_IndexParamStandardComponentRole: { + OMX_PARAM_COMPONENTROLETYPE *role = param; + + r = checkHeader(param, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (r) + return r; + + if (strcmp((char *)role->cRole, OMX_VID_ENC_AVC_ROLE)) { + return OMX_ErrorBadParameter; + } + + break; + } + case OMX_IndexParamVideoBitrate: { + OMX_VIDEO_PARAM_BITRATETYPE *bitrate = param; + + r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_BITRATETYPE)); + if (r) + return r; + + priv->bitrate = *bitrate; + + break; + } + case OMX_IndexParamVideoQuantization: { + OMX_VIDEO_PARAM_QUANTIZATIONTYPE *quant = param; + + r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_QUANTIZATIONTYPE)); + if (r) + return r; + + priv->quant = *quant; + + break; + } + case OMX_IndexParamVideoProfileLevelCurrent: { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *profile_level = param; + + r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (r) + return r; + + priv->profile_level = *profile_level; + + break; + } + default: + return omx_base_component_SetParameter(handle, idx, param); + } + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE vid_enc_GetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param) +{ + OMX_COMPONENTTYPE *comp = handle; + vid_enc_PrivateType *priv = comp->pComponentPrivate; + OMX_ERRORTYPE r; + + if (!param) + return OMX_ErrorBadParameter; + + switch(idx) { + case OMX_IndexParamStandardComponentRole: { + OMX_PARAM_COMPONENTROLETYPE *role = param; + + r = checkHeader(param, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (r) + return r; + + strcpy((char *)role->cRole, OMX_VID_ENC_AVC_ROLE); + break; + } + case OMX_IndexParamVideoInit: + r = checkHeader(param, sizeof(OMX_PORT_PARAM_TYPE)); + if (r) + return r; + + memcpy(param, &priv->sPortTypesParam[OMX_PortDomainVideo], sizeof(OMX_PORT_PARAM_TYPE)); + break; + + case OMX_IndexParamVideoPortFormat: { + OMX_VIDEO_PARAM_PORTFORMATTYPE *format = param; + omx_base_video_PortType *port; + + r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); + if (r) + return r; + + if (format->nPortIndex > 1) + return OMX_ErrorBadPortIndex; + if (format->nIndex >= 1) + return OMX_ErrorNoMore; + + port = (omx_base_video_PortType *)priv->ports[format->nPortIndex]; + memcpy(format, &port->sVideoParam, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); + break; + } + case OMX_IndexParamVideoBitrate: { + OMX_VIDEO_PARAM_BITRATETYPE *bitrate = param; + + r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_BITRATETYPE)); + if (r) + return r; + + bitrate->eControlRate = priv->bitrate.eControlRate; + bitrate->nTargetBitrate = priv->bitrate.nTargetBitrate; + + break; + } + case OMX_IndexParamVideoQuantization: { + OMX_VIDEO_PARAM_QUANTIZATIONTYPE *quant = param; + + r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_QUANTIZATIONTYPE)); + if (r) + return r; + + quant->nQpI = priv->quant.nQpI; + quant->nQpP = priv->quant.nQpP; + quant->nQpB = priv->quant.nQpB; + + break; + } + case OMX_IndexParamVideoProfileLevelCurrent: { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *profile_level = param; + + r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (r) + return r; + + profile_level->eProfile = priv->profile_level.eProfile; + profile_level->eLevel = priv->profile_level.eLevel; + + break; + } + default: + return omx_base_component_GetParameter(handle, idx, param); + } + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE vid_enc_SetConfig(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR config) +{ + OMX_COMPONENTTYPE *comp = handle; + vid_enc_PrivateType *priv = comp->pComponentPrivate; + OMX_ERRORTYPE r; + int i; + + if (!config) + return OMX_ErrorBadParameter; + + switch(idx) { + case OMX_IndexConfigVideoIntraVOPRefresh: { + OMX_CONFIG_INTRAREFRESHVOPTYPE *type = config; + + r = checkHeader(config, sizeof(OMX_CONFIG_INTRAREFRESHVOPTYPE)); + if (r) + return r; + + priv->force_pic_type = *type; + + break; + } + case OMX_IndexConfigCommonScale: { + OMX_CONFIG_SCALEFACTORTYPE *scale = config; + + r = checkHeader(config, sizeof(OMX_CONFIG_SCALEFACTORTYPE)); + if (r) + return r; + + if (scale->xWidth < 176 || scale->xHeight < 144) + return OMX_ErrorBadParameter; + + for (i = 0; i < OMX_VID_ENC_NUM_SCALING_BUFFERS; ++i) { + if (priv->scale_buffer[i]) { + priv->scale_buffer[i]->destroy(priv->scale_buffer[i]); + priv->scale_buffer[i] = NULL; + } + } + + priv->scale = *scale; + if (priv->scale.xWidth != 0xffffffff && priv->scale.xHeight != 0xffffffff) { + struct pipe_video_buffer templat = {}; + + templat.buffer_format = PIPE_FORMAT_NV12; + templat.width = priv->scale.xWidth; + templat.height = priv->scale.xHeight; + templat.interlaced = false; + for (i = 0; i < OMX_VID_ENC_NUM_SCALING_BUFFERS; ++i) { + priv->scale_buffer[i] = priv->s_pipe->create_video_buffer(priv->s_pipe, &templat); + if (!priv->scale_buffer[i]) + return OMX_ErrorInsufficientResources; + } + } + + break; + } + default: + return omx_base_component_SetConfig(handle, idx, config); + } + + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE vid_enc_GetConfig(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR config) +{ + OMX_COMPONENTTYPE *comp = handle; + vid_enc_PrivateType *priv = comp->pComponentPrivate; + OMX_ERRORTYPE r; + + if (!config) + return OMX_ErrorBadParameter; + + switch(idx) { + case OMX_IndexConfigCommonScale: { + OMX_CONFIG_SCALEFACTORTYPE *scale = config; + + r = checkHeader(config, sizeof(OMX_CONFIG_SCALEFACTORTYPE)); + if (r) + return r; + + scale->xWidth = priv->scale.xWidth; + scale->xHeight = priv->scale.xHeight; + + break; + } + default: + return omx_base_component_GetConfig(handle, idx, config); + } + + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE vid_enc_MessageHandler(OMX_COMPONENTTYPE* comp, internalRequestMessageType *msg) +{ + vid_enc_PrivateType* priv = comp->pComponentPrivate; + + if (msg->messageType == OMX_CommandStateSet) { + if ((msg->messageParam == OMX_StateIdle ) && (priv->state == OMX_StateLoaded)) { + + struct pipe_video_codec templat = {}; + omx_base_video_PortType *port; + + port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; + + templat.profile = enc_TranslateOMXProfileToPipe(priv->profile_level.eProfile); + templat.level = enc_TranslateOMXLevelToPipe(priv->profile_level.eLevel); + templat.entrypoint = PIPE_VIDEO_ENTRYPOINT_ENCODE; + templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; + templat.width = priv->scale_buffer[priv->current_scale_buffer] ? + priv->scale.xWidth : port->sPortParam.format.video.nFrameWidth; + templat.height = priv->scale_buffer[priv->current_scale_buffer] ? + priv->scale.xHeight : port->sPortParam.format.video.nFrameHeight; + + if (templat.profile == PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE) { + struct pipe_screen *screen = priv->screen->pscreen; + templat.max_references = 1; + priv->stacked_frames_num = + screen->get_video_param(screen, + PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH, + PIPE_VIDEO_ENTRYPOINT_ENCODE, + PIPE_VIDEO_CAP_STACKED_FRAMES); + } else { + templat.max_references = OMX_VID_ENC_P_PERIOD_DEFAULT; + priv->stacked_frames_num = 1; + } + priv->codec = priv->s_pipe->create_video_codec(priv->s_pipe, &templat); + + } else if ((msg->messageParam == OMX_StateLoaded) && (priv->state == OMX_StateIdle)) { + if (priv->codec) { + priv->codec->destroy(priv->codec); + priv->codec = NULL; + } + } + } + + return omx_base_component_MessageHandler(comp, msg); +} + +static OMX_ERRORTYPE vid_enc_AllocateInBuffer(omx_base_PortType *port, OMX_INOUT OMX_BUFFERHEADERTYPE **buf, + OMX_IN OMX_U32 idx, OMX_IN OMX_PTR private, OMX_IN OMX_U32 size) +{ + struct input_buf_private *inp; + OMX_ERRORTYPE r; + + r = base_port_AllocateBuffer(port, buf, idx, private, size); + if (r) + return r; + + inp = (*buf)->pInputPortPrivate = CALLOC_STRUCT(input_buf_private); + if (!inp) { + base_port_FreeBuffer(port, idx, *buf); + return OMX_ErrorInsufficientResources; + } + + list_inithead(&inp->tasks); + + FREE((*buf)->pBuffer); + r = enc_AllocateBackTexture(port, &inp->resource, &inp->transfer, &(*buf)->pBuffer); + if (r) { + FREE(inp); + base_port_FreeBuffer(port, idx, *buf); + return r; + } + + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE vid_enc_UseInBuffer(omx_base_PortType *port, OMX_BUFFERHEADERTYPE **buf, OMX_U32 idx, + OMX_PTR private, OMX_U32 size, OMX_U8 *mem) +{ + struct input_buf_private *inp; + OMX_ERRORTYPE r; + + r = base_port_UseBuffer(port, buf, idx, private, size, mem); + if (r) + return r; + + inp = (*buf)->pInputPortPrivate = CALLOC_STRUCT(input_buf_private); + if (!inp) { + base_port_FreeBuffer(port, idx, *buf); + return OMX_ErrorInsufficientResources; + } + + list_inithead(&inp->tasks); + + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE vid_enc_FreeInBuffer(omx_base_PortType *port, OMX_U32 idx, OMX_BUFFERHEADERTYPE *buf) +{ + OMX_COMPONENTTYPE* comp = port->standCompContainer; + vid_enc_PrivateType *priv = comp->pComponentPrivate; + struct input_buf_private *inp = buf->pInputPortPrivate; + + if (inp) { + enc_ReleaseTasks(&inp->tasks); + if (inp->transfer) + pipe_transfer_unmap(priv->s_pipe, inp->transfer); + pipe_resource_reference(&inp->resource, NULL); + FREE(inp); + } + buf->pBuffer = NULL; + + return base_port_FreeBuffer(port, idx, buf); +} + +static OMX_ERRORTYPE vid_enc_AllocateOutBuffer(omx_base_PortType *port, OMX_INOUT OMX_BUFFERHEADERTYPE **buf, + OMX_IN OMX_U32 idx, OMX_IN OMX_PTR private, OMX_IN OMX_U32 size) +{ + OMX_ERRORTYPE r; + + r = base_port_AllocateBuffer(port, buf, idx, private, size); + if (r) + return r; + + FREE((*buf)->pBuffer); + (*buf)->pBuffer = NULL; + (*buf)->pOutputPortPrivate = CALLOC(1, sizeof(struct output_buf_private)); + if (!(*buf)->pOutputPortPrivate) { + base_port_FreeBuffer(port, idx, *buf); + return OMX_ErrorInsufficientResources; + } + + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE vid_enc_FreeOutBuffer(omx_base_PortType *port, OMX_U32 idx, OMX_BUFFERHEADERTYPE *buf) +{ + OMX_COMPONENTTYPE* comp = port->standCompContainer; + vid_enc_PrivateType *priv = comp->pComponentPrivate; + + if (buf->pOutputPortPrivate) { + struct output_buf_private *outp = buf->pOutputPortPrivate; + if (outp->transfer) + pipe_transfer_unmap(priv->t_pipe, outp->transfer); + pipe_resource_reference(&outp->bitstream, NULL); + FREE(outp); + buf->pOutputPortPrivate = NULL; + } + buf->pBuffer = NULL; + + return base_port_FreeBuffer(port, idx, buf); +} + +static struct encode_task *enc_NeedTask(omx_base_PortType *port) +{ + OMX_VIDEO_PORTDEFINITIONTYPE *def = &port->sPortParam.format.video; + OMX_COMPONENTTYPE* comp = port->standCompContainer; + vid_enc_PrivateType *priv = comp->pComponentPrivate; + + return enc_NeedTask_common(priv, def); +} + +static OMX_ERRORTYPE enc_LoadImage(omx_base_PortType *port, OMX_BUFFERHEADERTYPE *buf, + struct pipe_video_buffer *vbuf) +{ + OMX_COMPONENTTYPE* comp = port->standCompContainer; + vid_enc_PrivateType *priv = comp->pComponentPrivate; + OMX_VIDEO_PORTDEFINITIONTYPE *def = &port->sPortParam.format.video; + return enc_LoadImage_common(priv, def, buf, vbuf); +} + +static void enc_ScaleInput(omx_base_PortType *port, struct pipe_video_buffer **vbuf, unsigned *size) +{ + OMX_COMPONENTTYPE* comp = port->standCompContainer; + vid_enc_PrivateType *priv = comp->pComponentPrivate; + OMX_VIDEO_PORTDEFINITIONTYPE *def = &port->sPortParam.format.video; + enc_ScaleInput_common(priv, def, vbuf, size); +} + +static void enc_ControlPicture(omx_base_PortType *port, struct pipe_h264_enc_picture_desc *picture) +{ + OMX_COMPONENTTYPE* comp = port->standCompContainer; + vid_enc_PrivateType *priv = comp->pComponentPrivate; + enc_ControlPicture_common(priv, picture); +} + +static void enc_HandleTask(omx_base_PortType *port, struct encode_task *task, + enum pipe_h264_enc_picture_type picture_type) +{ + OMX_COMPONENTTYPE* comp = port->standCompContainer; + vid_enc_PrivateType *priv = comp->pComponentPrivate; + unsigned size = priv->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]->sPortParam.nBufferSize; + struct pipe_video_buffer *vbuf = task->buf; + struct pipe_h264_enc_picture_desc picture = {}; + + /* -------------- scale input image --------- */ + enc_ScaleInput(port, &vbuf, &size); + priv->s_pipe->flush(priv->s_pipe, NULL, 0); + + /* -------------- allocate output buffer --------- */ + task->bitstream = pipe_buffer_create(priv->s_pipe->screen, + PIPE_BIND_VERTEX_BUFFER, + PIPE_USAGE_STAGING, /* map for read */ + size); + + picture.picture_type = picture_type; + picture.pic_order_cnt = task->pic_order_cnt; + picture.base.profile = enc_TranslateOMXProfileToPipe(priv->profile_level.eProfile); + picture.base.entry_point = PIPE_VIDEO_ENTRYPOINT_ENCODE; + if (priv->restricted_b_frames && picture_type == PIPE_H264_ENC_PICTURE_TYPE_B) + picture.not_referenced = true; + enc_ControlPicture(port, &picture); + + /* -------------- encode frame --------- */ + priv->codec->begin_frame(priv->codec, vbuf, &picture.base); + priv->codec->encode_bitstream(priv->codec, vbuf, task->bitstream, &task->feedback); + priv->codec->end_frame(priv->codec, vbuf, &picture.base); +} + +static void enc_ClearBframes(omx_base_PortType *port, struct input_buf_private *inp) +{ + OMX_COMPONENTTYPE* comp = port->standCompContainer; + vid_enc_PrivateType *priv = comp->pComponentPrivate; + struct encode_task *task; + + if (list_is_empty(&priv->b_frames)) + return; + + task = LIST_ENTRY(struct encode_task, priv->b_frames.prev, list); + list_del(&task->list); + + /* promote last from to P frame */ + priv->ref_idx_l0 = priv->ref_idx_l1; + enc_HandleTask(port, task, PIPE_H264_ENC_PICTURE_TYPE_P); + list_addtail(&task->list, &inp->tasks); + priv->ref_idx_l1 = priv->frame_num++; + + /* handle B frames */ + LIST_FOR_EACH_ENTRY(task, &priv->b_frames, list) { + enc_HandleTask(port, task, PIPE_H264_ENC_PICTURE_TYPE_B); + if (!priv->restricted_b_frames) + priv->ref_idx_l0 = priv->frame_num; + priv->frame_num++; + } + + enc_MoveTasks(&priv->b_frames, &inp->tasks); +} + +static OMX_ERRORTYPE vid_enc_EncodeFrame(omx_base_PortType *port, OMX_BUFFERHEADERTYPE *buf) +{ + OMX_COMPONENTTYPE* comp = port->standCompContainer; + vid_enc_PrivateType *priv = comp->pComponentPrivate; + struct input_buf_private *inp = buf->pInputPortPrivate; + enum pipe_h264_enc_picture_type picture_type; + struct encode_task *task; + unsigned stacked_num = 0; + OMX_ERRORTYPE err; + + enc_MoveTasks(&inp->tasks, &priv->free_tasks); + task = enc_NeedTask(port); + if (!task) + return OMX_ErrorInsufficientResources; + + if (buf->nFilledLen == 0) { + if (buf->nFlags & OMX_BUFFERFLAG_EOS) { + buf->nFilledLen = buf->nAllocLen; + enc_ClearBframes(port, inp); + enc_MoveTasks(&priv->stacked_tasks, &inp->tasks); + priv->codec->flush(priv->codec); + } + return base_port_SendBufferFunction(port, buf); + } + + if (buf->pOutputPortPrivate) { + struct pipe_video_buffer *vbuf = buf->pOutputPortPrivate; + buf->pOutputPortPrivate = task->buf; + task->buf = vbuf; + } else { + /* ------- load input image into video buffer ---- */ + err = enc_LoadImage(port, buf, task->buf); + if (err != OMX_ErrorNone) { + FREE(task); + return err; + } + } + + /* -------------- determine picture type --------- */ + if (!(priv->pic_order_cnt % OMX_VID_ENC_IDR_PERIOD_DEFAULT) || + priv->force_pic_type.IntraRefreshVOP) { + enc_ClearBframes(port, inp); + picture_type = PIPE_H264_ENC_PICTURE_TYPE_IDR; + priv->force_pic_type.IntraRefreshVOP = OMX_FALSE; + priv->frame_num = 0; + } else if (priv->codec->profile == PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE || + !(priv->pic_order_cnt % OMX_VID_ENC_P_PERIOD_DEFAULT) || + (buf->nFlags & OMX_BUFFERFLAG_EOS)) { + picture_type = PIPE_H264_ENC_PICTURE_TYPE_P; + } else { + picture_type = PIPE_H264_ENC_PICTURE_TYPE_B; + } + + task->pic_order_cnt = priv->pic_order_cnt++; + + if (picture_type == PIPE_H264_ENC_PICTURE_TYPE_B) { + /* put frame at the tail of the queue */ + list_addtail(&task->list, &priv->b_frames); + } else { + /* handle I or P frame */ + priv->ref_idx_l0 = priv->ref_idx_l1; + enc_HandleTask(port, task, picture_type); + list_addtail(&task->list, &priv->stacked_tasks); + LIST_FOR_EACH_ENTRY(task, &priv->stacked_tasks, list) { + ++stacked_num; + } + if (stacked_num == priv->stacked_frames_num) { + struct encode_task *t; + t = LIST_ENTRY(struct encode_task, priv->stacked_tasks.next, list); + list_del(&t->list); + list_addtail(&t->list, &inp->tasks); + } + priv->ref_idx_l1 = priv->frame_num++; + + /* handle B frames */ + LIST_FOR_EACH_ENTRY(task, &priv->b_frames, list) { + enc_HandleTask(port, task, PIPE_H264_ENC_PICTURE_TYPE_B); + if (!priv->restricted_b_frames) + priv->ref_idx_l0 = priv->frame_num; + priv->frame_num++; + } + + enc_MoveTasks(&priv->b_frames, &inp->tasks); + } + + if (list_is_empty(&inp->tasks)) + return port->ReturnBufferFunction(port, buf); + else + return base_port_SendBufferFunction(port, buf); +} + +static void vid_enc_BufferEncoded(OMX_COMPONENTTYPE *comp, OMX_BUFFERHEADERTYPE* input, OMX_BUFFERHEADERTYPE* output) +{ + vid_enc_PrivateType *priv = comp->pComponentPrivate; + vid_enc_BufferEncoded_common(priv, input, output); +} diff --git a/src/gallium/frontends/omx/bellagio/vid_enc.h b/src/gallium/frontends/omx/bellagio/vid_enc.h new file mode 100644 index 00000000000..4d2b867261b --- /dev/null +++ b/src/gallium/frontends/omx/bellagio/vid_enc.h @@ -0,0 +1,48 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/* + * Authors: + * Christian König + * + */ + +#ifndef OMX_VID_ENC_H +#define OMX_VID_ENC_H + +#include +#include + +#include + +#define OMX_VID_ENC_BASE_NAME "OMX.mesa.video_encoder" +#define OMX_VID_ENC_AVC_NAME "OMX.mesa.video_encoder.avc" +#define OMX_VID_ENC_AVC_ROLE "video_encoder.avc" + +OMX_ERRORTYPE vid_enc_LoaderComponent(stLoaderComponentType *comp); + +#endif diff --git a/src/gallium/frontends/omx/meson.build b/src/gallium/frontends/omx/meson.build new file mode 100644 index 00000000000..35866c1cba0 --- /dev/null +++ b/src/gallium/frontends/omx/meson.build @@ -0,0 +1,71 @@ +# Copyright © 2017, 2019 Intel Corporation + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +inc_st_omx = [inc_include, inc_src, inc_mapi, inc_mesa, inc_gallium, inc_gallium_aux] +dep_st_omx = [ + dep_omx, dep_x11_xcb, dep_xcb, dep_xcb_dri2, dep_xcb_dri3, dep_libdrm, +] + +files_omx = files( + 'vid_dec_common.c', + 'vid_dec_h264_common.c', + 'vid_enc_common.c', + 'vid_omx_common.c' +) + +if with_gallium_omx == 'bellagio' + files_omx += files( + 'bellagio/entrypoint.c', + 'bellagio/vid_dec.c', + 'bellagio/vid_dec_mpeg12.c', + 'bellagio/vid_dec_h264.c', + 'bellagio/vid_dec_h265.c', + 'bellagio/vid_enc.c' + ) +elif with_gallium_omx == 'tizonia' + files_omx += files( + 'tizonia/entrypoint.c', + 'tizonia/h264d.c', + 'tizonia/h264dprc.c', + 'tizonia/h264dinport.c', + 'tizonia/h264e.c', + 'tizonia/h264eprc.c', + 'tizonia/h264einport.c', + 'tizonia/h264eoutport.c' + ) + inc_st_omx = [ + inc_st_omx, + inc_dri_common, + inc_loader, + inc_gbm, + inc_st_dri, + inc_egl, + inc_egl_dri2, + ] + dep_st_omx = [dep_st_omx, dep_omx_other] +endif + +libomx_st = static_library( + 'omx_st', + files_omx, + c_args : [c_vis_args, '-fcommon'], + include_directories : inc_st_omx, + dependencies : dep_st_omx, +) diff --git a/src/gallium/frontends/omx/tizonia/Makefile.sources b/src/gallium/frontends/omx/tizonia/Makefile.sources new file mode 100644 index 00000000000..7e039d3c5ad --- /dev/null +++ b/src/gallium/frontends/omx/tizonia/Makefile.sources @@ -0,0 +1,22 @@ +C_SOURCES := \ + entrypoint.c \ + entrypoint.h \ + h264d.c \ + h264d.h \ + h264dprc.c \ + h264dprc.h \ + h264dinport.c \ + h264dinport.h \ + h264dinport_decls.h \ + h264e.c \ + h264e.h \ + h264eprc.c \ + h264eprc.h \ + h264einport.h \ + h264einport.c \ + h264einport_decls.h \ + h264einport.h \ + h264eoutport.c \ + h264eoutport_decls.h \ + h264eoutport.h \ + names.h diff --git a/src/gallium/frontends/omx/tizonia/entrypoint.c b/src/gallium/frontends/omx/tizonia/entrypoint.c new file mode 100644 index 00000000000..a6c2c45b39e --- /dev/null +++ b/src/gallium/frontends/omx/tizonia/entrypoint.c @@ -0,0 +1,158 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#include "vid_dec_h264_common.h" +#include "entrypoint.h" +#include "h264d.h" +#include "h264dprc.h" +#include "h264dinport.h" +#include "h264e.h" +#include "h264eprc.h" +#include "h264einport.h" +#include "h264eoutport.h" +#include "names.h" + +#include "util/u_debug.h" + +DEBUG_GET_ONCE_BOOL_OPTION(mesa_enable_omx_eglimage, + "MESA_ENABLE_OMX_EGLIMAGE", + false) + +static OMX_BOOL egl_image_validation_hook(const OMX_HANDLETYPE ap_hdl, + OMX_U32 pid, OMX_PTR ap_eglimage, + void *ap_args) +{ + const void * p_krn = NULL; + const tiz_port_t * p_port = NULL; + + assert(ap_hdl); + assert(ap_eglimage); + assert(!ap_args); + + if (!debug_get_option_mesa_enable_omx_eglimage()) { + return OMX_FALSE; + } + + p_krn = tiz_get_krn(ap_hdl); + p_port = tiz_krn_get_port(p_krn, pid); + + const OMX_VIDEO_PORTDEFINITIONTYPE * p_video_portdef + = &(p_port->portdef_.format.video); + + if (!p_video_portdef->pNativeWindow) { + return OMX_FALSE; + } + + return OMX_TRUE; +} + +OMX_ERRORTYPE OMX_ComponentInit (OMX_HANDLETYPE ap_hdl) +{ + tiz_role_factory_t h264d_role; + tiz_role_factory_t h264e_role; + const tiz_role_factory_t * rf_list[] = {&h264d_role, &h264e_role}; + tiz_type_factory_t h264dprc_type; + tiz_type_factory_t h264d_inport_type; + tiz_type_factory_t h264eprc_type; + tiz_type_factory_t h264e_inport_type; + tiz_type_factory_t h264e_outport_type; + const tiz_type_factory_t * tf_list[] = {&h264dprc_type, + &h264d_inport_type, + &h264eprc_type, + &h264e_inport_type, + &h264e_outport_type}; + const tiz_eglimage_hook_t egl_validation_hook = { + OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX, + egl_image_validation_hook, + NULL + }; + + /* Settings for roles */ + strcpy ((OMX_STRING) h264d_role.role, OMX_VID_DEC_AVC_ROLE); + h264d_role.pf_cport = instantiate_h264d_config_port; + h264d_role.pf_port[0] = instantiate_h264d_input_port; + h264d_role.pf_port[1] = instantiate_h264d_output_port; + h264d_role.nports = 2; + h264d_role.pf_proc = instantiate_h264d_processor; + + strcpy ((OMX_STRING) h264e_role.role, OMX_VID_ENC_AVC_ROLE); + h264e_role.pf_cport = instantiate_h264e_config_port; + h264e_role.pf_port[0] = instantiate_h264e_input_port; + h264e_role.pf_port[1] = instantiate_h264e_output_port; + h264e_role.nports = 2; + h264e_role.pf_proc = instantiate_h264e_processor; + + /* Settings for classes */ + strcpy ((OMX_STRING) h264dprc_type.class_name, "h264dprc_class"); + h264dprc_type.pf_class_init = h264d_prc_class_init; + strcpy ((OMX_STRING) h264dprc_type.object_name, "h264dprc"); + h264dprc_type.pf_object_init = h264d_prc_init; + + strcpy ((OMX_STRING) h264d_inport_type.class_name, "h264dinport_class"); + h264d_inport_type.pf_class_init = h264d_inport_class_init; + strcpy ((OMX_STRING) h264d_inport_type.object_name, "h264dinport"); + h264d_inport_type.pf_object_init = h264d_inport_init; + + strcpy ((OMX_STRING) h264eprc_type.class_name, "h264eprc_class"); + h264eprc_type.pf_class_init = h264e_prc_class_init; + strcpy ((OMX_STRING) h264eprc_type.object_name, "h264eprc"); + h264eprc_type.pf_object_init = h264e_prc_init; + + strcpy ((OMX_STRING) h264e_inport_type.class_name, "h264einport_class"); + h264e_inport_type.pf_class_init = h264e_inport_class_init; + strcpy ((OMX_STRING) h264e_inport_type.object_name, "h264einport"); + h264e_inport_type.pf_object_init = h264e_inport_init; + + strcpy ((OMX_STRING) h264e_outport_type.class_name, "h264eoutport_class"); + h264e_outport_type.pf_class_init = h264e_outport_class_init; + strcpy ((OMX_STRING) h264e_outport_type.object_name, "h264eoutport"); + h264e_outport_type.pf_object_init = h264e_outport_init; + + /* Initialize the component infrastructure */ + tiz_comp_init (ap_hdl, OMX_VID_COMP_NAME); + + /* Classes need to be registered first */ + tiz_comp_register_types (ap_hdl, tf_list, 5); + + /* Register the component roles */ + tiz_comp_register_roles (ap_hdl, rf_list, 2); + + /* Register egl image validation hook for the decoder */ + tiz_check_omx (tiz_comp_register_role_eglimage_hook + (ap_hdl, (const OMX_U8 *) OMX_VID_DEC_AVC_ROLE, + &egl_validation_hook)); + + return OMX_ErrorNone; +} diff --git a/src/gallium/frontends/omx/tizonia/entrypoint.h b/src/gallium/frontends/omx/tizonia/entrypoint.h new file mode 100644 index 00000000000..740a89dbffc --- /dev/null +++ b/src/gallium/frontends/omx/tizonia/entrypoint.h @@ -0,0 +1,35 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef OMX_TIZ_ENTRYPOINT_H +#define OMX_TIZ_ENTRYPOINT_H + +#include "vl/vl_winsys.h" + +PUBLIC OMX_ERRORTYPE OMX_ComponentInit(OMX_HANDLETYPE ap_hdl); + +#endif diff --git a/src/gallium/frontends/omx/tizonia/h264d.c b/src/gallium/frontends/omx/tizonia/h264d.c new file mode 100644 index 00000000000..92019a7a4bd --- /dev/null +++ b/src/gallium/frontends/omx/tizonia/h264d.c @@ -0,0 +1,176 @@ +/************************************************************************** + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include + +#include "vid_dec_h264_common.h" + +#include "h264dprc.h" +#include "h264d.h" +#include "names.h" + +static OMX_VERSIONTYPE h264_decoder_version = {{0, 0, 0, 1}}; + +OMX_PTR instantiate_h264d_input_port(OMX_HANDLETYPE ap_hdl) +{ + OMX_VIDEO_PORTDEFINITIONTYPE portdef; + OMX_VIDEO_PARAM_AVCTYPE avctype; + OMX_VIDEO_CODINGTYPE encodings[] = { + OMX_VIDEO_CodingAVC, + OMX_VIDEO_CodingMax + }; + OMX_COLOR_FORMATTYPE formats[] = { + OMX_COLOR_FormatUnused, + OMX_COLOR_FormatMax + }; + tiz_port_options_t avc_port_opts = { + OMX_PortDomainVideo, + OMX_DirInput, + OMX_VID_DEC_AVC_INPUT_PORT_MIN_BUF_COUNT, + OMX_VID_DEC_AVC_PORT_MIN_INPUT_BUF_SIZE, + OMX_VID_DEC_AVC_PORT_NONCONTIGUOUS, + OMX_VID_DEC_AVC_PORT_ALIGNMENT, + OMX_VID_DEC_AVC_PORT_SUPPLIERPREF, + {OMX_VID_DEC_AVC_INPUT_PORT_INDEX, NULL, NULL, NULL}, + 1 /* slave port */ + }; + OMX_VIDEO_AVCLEVELTYPE levels[] = { + OMX_VIDEO_AVCLevel1, + OMX_VIDEO_AVCLevel1b, + OMX_VIDEO_AVCLevel11, + OMX_VIDEO_AVCLevel12, + OMX_VIDEO_AVCLevel13, + OMX_VIDEO_AVCLevel2, + OMX_VIDEO_AVCLevel21, + OMX_VIDEO_AVCLevel22, + OMX_VIDEO_AVCLevel3, + OMX_VIDEO_AVCLevel31, + OMX_VIDEO_AVCLevel32, + OMX_VIDEO_AVCLevel4, + OMX_VIDEO_AVCLevel41, + OMX_VIDEO_AVCLevel42, + OMX_VIDEO_AVCLevel5, + OMX_VIDEO_AVCLevel51, + OMX_VIDEO_AVCLevelMax + }; + + portdef.pNativeRender = NULL; + portdef.nFrameWidth = OMX_VID_DEC_AVC_DEFAULT_FRAME_WIDTH; + portdef.nFrameHeight = OMX_VID_DEC_AVC_DEFAULT_FRAME_HEIGHT; + portdef.nStride = 0; + portdef.nSliceHeight = 0; + portdef.nBitrate = 64000; + portdef.xFramerate = OMX_VID_DEC_AVC_DEFAULT_FRAME_RATE; + portdef.bFlagErrorConcealment = OMX_FALSE; + portdef.eCompressionFormat = OMX_VIDEO_CodingAVC; + portdef.eColorFormat = OMX_COLOR_FormatUnused; + portdef.pNativeWindow = NULL; + + avctype.nSize = sizeof (OMX_VIDEO_PARAM_AVCTYPE); + avctype.nVersion.nVersion = OMX_VERSION; + avctype.nPortIndex = OMX_VID_DEC_AVC_INPUT_PORT_INDEX; + avctype.eProfile = OMX_VIDEO_AVCProfileHigh; + /* Encoder related, decide if need to initialise these */ + avctype.nSliceHeaderSpacing = 0; + avctype.nPFrames = 0; + avctype.nBFrames = 0; + avctype.bUseHadamard = OMX_FALSE; + avctype.nRefFrames = 1; + avctype.nRefIdx10ActiveMinus1 = 1; + avctype.nRefIdx11ActiveMinus1 = 0; + avctype.bEnableUEP = OMX_FALSE; + avctype.bEnableFMO = OMX_FALSE; + avctype.bEnableASO = OMX_FALSE; + avctype.bEnableRS = OMX_FALSE; + avctype.eLevel = OMX_VIDEO_AVCLevel51; + avctype.nAllowedPictureTypes = 2; + avctype.bFrameMBsOnly = OMX_FALSE; + avctype.bMBAFF = OMX_FALSE; + avctype.bEntropyCodingCABAC = OMX_FALSE; + avctype.bWeightedPPrediction = OMX_FALSE; + avctype.nWeightedBipredicitonMode = 0; + avctype.bconstIpred = OMX_FALSE; + avctype.bDirect8x8Inference = OMX_FALSE; + avctype.bDirectSpatialTemporal = OMX_FALSE; + avctype.nCabacInitIdc = 0; + avctype.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable; + + return factory_new (tiz_get_type(ap_hdl, "h264dinport"), + &avc_port_opts, &portdef, + &encodings, &formats, &avctype, &levels, + NULL /* OMX_VIDEO_PARAM_BITRATETYPE */, + NULL /* OMX_VIDEO_PARAM_QUANTIZATIONTYPE */); +} + +OMX_PTR instantiate_h264d_output_port(OMX_HANDLETYPE ap_hdl) +{ + OMX_VIDEO_PORTDEFINITIONTYPE portdef; + OMX_VIDEO_CODINGTYPE encodings[] = { + OMX_VIDEO_CodingUnused, + OMX_VIDEO_CodingMax + }; + OMX_COLOR_FORMATTYPE formats[] = { + OMX_COLOR_FormatYUV420SemiPlanar, + OMX_COLOR_FormatMax + }; + tiz_port_options_t rawvideo_port_opts = { + OMX_PortDomainVideo, + OMX_DirOutput, + OMX_VID_DEC_AVC_OUTPUT_PORT_MIN_BUF_COUNT, + OMX_VID_DEC_AVC_PORT_MIN_OUTPUT_BUF_SIZE, + OMX_VID_DEC_AVC_PORT_NONCONTIGUOUS, + OMX_VID_DEC_AVC_PORT_ALIGNMENT, + OMX_VID_DEC_AVC_PORT_SUPPLIERPREF, + {OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX, NULL, NULL, NULL}, + 0 /* Master port */ + }; + + portdef.pNativeRender = NULL; + portdef.nFrameWidth = OMX_VID_DEC_AVC_DEFAULT_FRAME_WIDTH; + portdef.nFrameHeight = OMX_VID_DEC_AVC_DEFAULT_FRAME_HEIGHT; + portdef.nStride = 0; + portdef.nSliceHeight = 0; + portdef.nBitrate = 64000; + portdef.xFramerate = OMX_VID_DEC_AVC_DEFAULT_FRAME_RATE; + portdef.bFlagErrorConcealment = OMX_FALSE; + portdef.eCompressionFormat = OMX_VIDEO_CodingUnused; + portdef.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; + portdef.pNativeWindow = NULL; + + return factory_new(tiz_get_type(ap_hdl, "tizvideoport"), + &rawvideo_port_opts, &portdef, + &encodings, &formats); +} + +OMX_PTR instantiate_h264d_config_port(OMX_HANDLETYPE ap_hdl) +{ + return factory_new(tiz_get_type(ap_hdl, "tizconfigport"), + NULL, /* this port does not take options */ + OMX_VID_COMP_NAME, h264_decoder_version); +} + +OMX_PTR instantiate_h264d_processor(OMX_HANDLETYPE ap_hdl) +{ + return factory_new(tiz_get_type(ap_hdl, "h264dprc")); +} diff --git a/src/gallium/frontends/omx/tizonia/h264d.h b/src/gallium/frontends/omx/tizonia/h264d.h new file mode 100644 index 00000000000..1733425d45c --- /dev/null +++ b/src/gallium/frontends/omx/tizonia/h264d.h @@ -0,0 +1,40 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef H264D_H +#define H264D_H + +#include +#include +#include + +OMX_PTR instantiate_h264d_config_port(OMX_HANDLETYPE ap_hdl); +OMX_PTR instantiate_h264d_input_port(OMX_HANDLETYPE ap_hdl); +OMX_PTR instantiate_h264d_output_port(OMX_HANDLETYPE ap_hdl); +OMX_PTR instantiate_h264d_processor(OMX_HANDLETYPE ap_hdl); + +#endif /* H264D_H */ diff --git a/src/gallium/frontends/omx/tizonia/h264dinport.c b/src/gallium/frontends/omx/tizonia/h264dinport.c new file mode 100644 index 00000000000..858ae761560 --- /dev/null +++ b/src/gallium/frontends/omx/tizonia/h264dinport.c @@ -0,0 +1,147 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include +#include +#include + +#include +#include + +#include "vl/vl_winsys.h" + +#include "h264d.h" +#include "h264dinport.h" +#include "h264dinport_decls.h" +#include "vid_dec_common.h" + +/* + * h264dinport class + */ + +static void * h264d_inport_ctor(void * ap_obj, va_list * app) +{ + return super_ctor(typeOf(ap_obj, "h264dinport"), ap_obj, app); +} + +static void * h264d_inport_dtor(void * ap_obj) +{ + return super_dtor(typeOf(ap_obj, "h264dinport"), ap_obj); +} + +/* + * from tiz_api + */ + +static OMX_ERRORTYPE h264d_inport_SetParameter(const void * ap_obj, OMX_HANDLETYPE ap_hdl, + OMX_INDEXTYPE a_index, OMX_PTR ap_struct) +{ + OMX_ERRORTYPE err = OMX_ErrorNone; + + assert(ap_obj); + assert(ap_hdl); + assert(ap_struct); + + if (a_index == OMX_IndexParamPortDefinition) { + vid_dec_PrivateType * p_prc = tiz_get_prc(ap_hdl); + OMX_VIDEO_PORTDEFINITIONTYPE * p_def = &(p_prc->out_port_def_.format.video); + OMX_PARAM_PORTDEFINITIONTYPE * i_def = (OMX_PARAM_PORTDEFINITIONTYPE *) ap_struct; + + /* Make changes only if there is a resolution change */ + if ((p_def->nFrameWidth == i_def->format.video.nFrameWidth) && + (p_def->nFrameHeight == i_def->format.video.nFrameHeight) && + (p_def->eCompressionFormat == i_def->format.video.eCompressionFormat)) + return err; + + /* Set some default values if not set */ + if (i_def->format.video.nStride == 0) + i_def->format.video.nStride = i_def->format.video.nFrameWidth; + if (i_def->format.video.nSliceHeight == 0) + i_def->format.video.nSliceHeight = i_def->format.video.nFrameHeight; + + err = super_SetParameter(typeOf (ap_obj, "h264dinport"), ap_obj, + ap_hdl, a_index, ap_struct); + if (err == OMX_ErrorNone) { + tiz_port_t * p_obj = (tiz_port_t *) ap_obj; + + /* Set desired buffer size that will be used when allocating input buffers */ + p_obj->portdef_.nBufferSize = i_def->format.video.nFrameWidth * i_def->format.video.nFrameHeight * 512 / (16*16); + + /* Get a locally copy of port def. Useful for the early return above */ + tiz_check_omx(tiz_api_GetParameter(tiz_get_krn(handleOf(p_prc)), handleOf(p_prc), + OMX_IndexParamPortDefinition, &(p_prc->out_port_def_))); + } + } + + return err; +} + +/* + * h264dinport_class + */ + +static void * h264d_inport_class_ctor(void * ap_obj, va_list * app) +{ + /* NOTE: Class methods might be added in the future. None for now. */ + return super_ctor (typeOf (ap_obj, "h264dinport_class"), ap_obj, app); +} + +/* + * initialization + */ + +void * h264d_inport_class_init(void * ap_tos, void * ap_hdl) +{ + void * tizavcport = tiz_get_type(ap_hdl, "tizavcport"); + void * h264dinport_class + = factory_new(classOf(tizavcport), "h264dinport_class", + classOf(tizavcport), sizeof(h264d_inport_class_t), + ap_tos, ap_hdl, ctor, h264d_inport_class_ctor, 0); + return h264dinport_class; +} + +void * h264d_inport_init(void * ap_tos, void * ap_hdl) +{ + void * tizavcport = tiz_get_type (ap_hdl, "tizavcport"); + void * h264dinport_class = tiz_get_type (ap_hdl, "h264dinport_class"); + void * h264dinport = factory_new + /* TIZ_CLASS_COMMENT: class type, class name, parent, size */ + (h264dinport_class, "h264dinport", tizavcport, + sizeof (h264d_inport_t), + /* TIZ_CLASS_COMMENT: class constructor */ + ap_tos, ap_hdl, + /* TIZ_CLASS_COMMENT: class constructor */ + ctor, h264d_inport_ctor, + /* TIZ_CLASS_COMMENT: class destructor */ + dtor, h264d_inport_dtor, + /* TIZ_CLASS_COMMENT: */ + tiz_api_SetParameter, h264d_inport_SetParameter, + /* TIZ_CLASS_COMMENT: stop value*/ + 0); + + return h264dinport; +} diff --git a/src/gallium/frontends/omx/tizonia/h264dinport.h b/src/gallium/frontends/omx/tizonia/h264dinport.h new file mode 100644 index 00000000000..f158e4e1038 --- /dev/null +++ b/src/gallium/frontends/omx/tizonia/h264dinport.h @@ -0,0 +1,31 @@ +/************************************************************************** + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef H264DINPORT_H +#define H264DINPORT_H + +void * h264d_inport_class_init(void * ap_tos, void * ap_hdl); +void * h264d_inport_init(void * ap_tos, void * ap_hdl); + +#endif /* H264DINPORT_H */ diff --git a/src/gallium/frontends/omx/tizonia/h264dinport_decls.h b/src/gallium/frontends/omx/tizonia/h264dinport_decls.h new file mode 100644 index 00000000000..0194f6e3d09 --- /dev/null +++ b/src/gallium/frontends/omx/tizonia/h264dinport_decls.h @@ -0,0 +1,48 @@ +/************************************************************************** + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef H264DINPORT_DECLS_H +#define H264DINPORT_DECLS_H + +#include +#include + +#include + +typedef struct h264d_inport h264d_inport_t; +struct h264d_inport +{ + /* Object */ + const tiz_avcport_t _; +}; + +typedef struct h264d_inport_class h264d_inport_class_t; +struct h264d_inport_class +{ + /* Class */ + const tiz_avcport_class_t _; + /* NOTE: Class methods might be added in the future */ +}; + +#endif /* H264DINPORT_DECLS_H */ diff --git a/src/gallium/frontends/omx/tizonia/h264dprc.c b/src/gallium/frontends/omx/tizonia/h264dprc.c new file mode 100644 index 00000000000..c5df994b8c3 --- /dev/null +++ b/src/gallium/frontends/omx/tizonia/h264dprc.c @@ -0,0 +1,615 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include +#include +#include + +#include "entrypoint.h" +#include "h264d.h" +#include "h264dprc.h" +#include "vid_omx_common.h" +#include "vid_dec_common.h" +#include "vid_dec_h264_common.h" + +#include "vl/vl_video_buffer.h" +#include "vl/vl_compositor.h" +#include "util/u_hash_table.h" +#include "util/u_surface.h" + +#include "dri_screen.h" +#include "egl_dri2.h" + +unsigned dec_frame_delta; + +static enum pipe_error hash_table_clear_item_callback(void *key, void *value, void *data) +{ + struct pipe_video_buffer *video_buffer = (struct pipe_video_buffer *)value; + video_buffer->destroy(video_buffer); + return PIPE_OK; +} + +static void release_input_headers(vid_dec_PrivateType* priv) { + int i; + for (i = 0; i < priv->num_in_buffers; i++) { + assert(!priv->in_port_disabled_); + if (priv->in_buffers[i]->pInputPortPrivate) { + vid_dec_FreeInputPortPrivate(priv->in_buffers[i]); + } + (void) tiz_krn_release_buffer (tiz_get_krn (handleOf (priv)), + OMX_VID_DEC_AVC_INPUT_PORT_INDEX, + priv->in_buffers[i]); + priv->in_buffers[i] = NULL; + } + priv->p_inhdr_ = NULL; + priv->num_in_buffers = 0; +} + +static void release_output_header(vid_dec_PrivateType* priv) { + if (priv->p_outhdr_) { + assert(!priv->out_port_disabled_); + (void) tiz_krn_release_buffer (tiz_get_krn (handleOf (priv)), + OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX, + priv->p_outhdr_); + priv->p_outhdr_ = NULL; + } +} + +static OMX_ERRORTYPE h264d_release_all_headers(vid_dec_PrivateType* priv) +{ + assert(priv); + release_input_headers(priv); + release_output_header(priv); + + return OMX_ErrorNone; +} + +static void h264d_buffer_emptied(vid_dec_PrivateType* priv, OMX_BUFFERHEADERTYPE * p_hdr) +{ + assert(priv); + assert(priv->in_buffers[0] == p_hdr); + + if (!priv->out_port_disabled_) { + assert (p_hdr->nFilledLen == 0); + p_hdr->nOffset = 0; + + if ((p_hdr->nFlags & OMX_BUFFERFLAG_EOS) != 0) { + priv->eos_ = true; + } + + (void) tiz_krn_release_buffer (tiz_get_krn (handleOf (priv)), 0, p_hdr); + priv->p_inhdr_ = NULL; + priv->in_buffers[0] = NULL; + } +} + +static void h264d_buffer_filled(vid_dec_PrivateType* priv, OMX_BUFFERHEADERTYPE * p_hdr) +{ + assert(priv); + assert(p_hdr); + assert(priv->p_outhdr_ == p_hdr); + + if (!priv->in_port_disabled_) { + p_hdr->nOffset = 0; + + if (priv->eos_) { + /* EOS has been received and all the input data has been consumed + * already, so its time to propagate the EOS flag */ + priv->p_outhdr_->nFlags |= OMX_BUFFERFLAG_EOS; + priv->eos_ = false; + } + + (void) tiz_krn_release_buffer(tiz_get_krn (handleOf (priv)), + OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX, + p_hdr); + priv->p_outhdr_ = NULL; + } +} + +static bool h264d_shift_buffers_left(vid_dec_PrivateType* priv) { + if (--priv->num_in_buffers) { + priv->in_buffers[0] = priv->in_buffers[1]; + priv->sizes[0] = priv->sizes[1] - dec_frame_delta; + priv->inputs[0] = priv->inputs[1] + dec_frame_delta; + priv->timestamps[0] = priv->timestamps[1]; + + return true; + } + return false; +} + +static OMX_BUFFERHEADERTYPE * get_input_buffer(vid_dec_PrivateType* priv) { + assert(priv); + + if (priv->in_port_disabled_) { + return NULL; + } + + if (priv->num_in_buffers > 1) { + /* The input buffer wasn't cleared last time. */ + h264d_buffer_emptied(priv, priv->in_buffers[0]); + if (priv->in_buffers[0]) { + /* Failed to release buffer */ + return NULL; + } + h264d_shift_buffers_left(priv); + } + + /* Decode_frame expects new buffers each time */ + assert(priv->p_inhdr_ || priv->first_buf_in_frame); + tiz_krn_claim_buffer(tiz_get_krn (handleOf (priv)), + OMX_VID_DEC_AVC_INPUT_PORT_INDEX, 0, + &priv->p_inhdr_); + return priv->p_inhdr_; +} + +static struct pipe_resource * st_omx_pipe_texture_from_eglimage(EGLDisplay egldisplay, + EGLImage eglimage) +{ + _EGLDisplay *disp = egldisplay; + struct dri2_egl_display *dri2_egl_dpy = disp->DriverData; + __DRIscreen *_dri_screen = dri2_egl_dpy->dri_screen; + struct dri_screen *st_dri_screen = dri_screen(_dri_screen); + __DRIimage *_dri_image = st_dri_screen->lookup_egl_image(st_dri_screen, eglimage); + + return _dri_image->texture; +} + +static void get_eglimage(vid_dec_PrivateType* priv) { + OMX_PTR p_eglimage = NULL; + OMX_NATIVE_WINDOWTYPE * p_egldisplay = NULL; + const tiz_port_t * p_port = NULL; + struct pipe_video_buffer templat = {}; + struct pipe_video_buffer *video_buffer = NULL; + struct pipe_resource * p_res = NULL; + struct pipe_resource *resources[VL_NUM_COMPONENTS]; + + if (OMX_ErrorNone == + tiz_krn_claim_eglimage(tiz_get_krn (handleOf (priv)), + OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX, + priv->p_outhdr_, &p_eglimage)) { + priv->use_eglimage = true; + p_port = tiz_krn_get_port(tiz_get_krn (handleOf (priv)), + OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX); + p_egldisplay = p_port->portdef_.format.video.pNativeWindow; + + if (!util_hash_table_get(priv->video_buffer_map, priv->p_outhdr_)) { + p_res = st_omx_pipe_texture_from_eglimage(p_egldisplay, p_eglimage); + + assert(p_res); + + memset(&templat, 0, sizeof(templat)); + templat.buffer_format = p_res->format; + templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_NONE; + templat.width = p_res->width0; + templat.height = p_res->height0; + templat.interlaced = 0; + + memset(resources, 0, sizeof(resources)); + pipe_resource_reference(&resources[0], p_res); + + video_buffer = vl_video_buffer_create_ex2(priv->pipe, &templat, resources); + + assert(video_buffer); + assert(video_buffer->buffer_format == p_res->format); + + _mesa_hash_table_insert(priv->video_buffer_map, priv->p_outhdr_, video_buffer); + } + } else { + (void) tiz_krn_release_buffer(tiz_get_krn (handleOf (priv)), + OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX, + priv->p_outhdr_); + priv->p_outhdr_ = NULL; + } +} + +static OMX_BUFFERHEADERTYPE * get_output_buffer(vid_dec_PrivateType* priv) { + assert (priv); + + if (priv->out_port_disabled_) { + return NULL; + } + + if (!priv->p_outhdr_) { + if (OMX_ErrorNone + == tiz_krn_claim_buffer(tiz_get_krn (handleOf (priv)), + OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX, 0, + &priv->p_outhdr_)) { + if (priv->p_outhdr_) { + /* Check pBuffer nullity to know if an eglimage has been registered. */ + if (!priv->p_outhdr_->pBuffer) { + get_eglimage(priv); + } + } + } + } + return priv->p_outhdr_; +} + +static void reset_stream_parameters(vid_dec_PrivateType* apriv) +{ + assert(apriv); + TIZ_INIT_OMX_PORT_STRUCT(apriv->out_port_def_, + OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX); + + tiz_api_GetParameter (tiz_get_krn (handleOf (apriv)), handleOf (apriv), + OMX_IndexParamPortDefinition, &(apriv->out_port_def_)); + + apriv->p_inhdr_ = 0; + apriv->num_in_buffers = 0; + apriv->first_buf_in_frame = true; + apriv->eos_ = false; + apriv->frame_finished = false; + apriv->frame_started = false; + apriv->picture.h264.field_order_cnt[0] = apriv->picture.h264.field_order_cnt[1] = INT_MAX; + apriv->slice = NULL; +} + +/* Replacement for bellagio's omx_base_filter_BufferMgmtFunction */ +static void h264d_manage_buffers(vid_dec_PrivateType* priv) { + bool next_is_eos = priv->num_in_buffers == 2 ? !!(priv->in_buffers[1]->nFlags & OMX_BUFFERFLAG_EOS) : false; + vid_dec_FrameDecoded_common(priv, priv->in_buffers[0], priv->p_outhdr_); + + priv->p_outhdr_->nTimeStamp = priv->in_buffers[0]->nTimeStamp; + + /* Realase output buffer if filled or eos + Keep if two input buffers are being decoded */ + if ((!next_is_eos) && ((priv->p_outhdr_->nFilledLen > 0) || priv->use_eglimage || priv->eos_)) { + h264d_buffer_filled(priv, priv->p_outhdr_); + } + + /* Release input buffer if possible */ + if (priv->in_buffers[0]->nFilledLen == 0) { + h264d_buffer_emptied(priv, priv->in_buffers[0]); + } +} + +static OMX_ERRORTYPE decode_frame(vid_dec_PrivateType*priv, + OMX_BUFFERHEADERTYPE *in_buf) +{ + unsigned i = priv->num_in_buffers++; + priv->in_buffers[i] = in_buf; + priv->sizes[i] = in_buf->nFilledLen; + priv->inputs[i] = in_buf->pBuffer; + priv->timestamps[i] = in_buf->nTimeStamp; + + while (priv->num_in_buffers > (!!(in_buf->nFlags & OMX_BUFFERFLAG_EOS) ? 0 : 1)) { + priv->eos_ = !!(priv->in_buffers[0]->nFlags & OMX_BUFFERFLAG_EOS); + unsigned min_bits_left = priv->eos_ ? 32 : MAX2(in_buf->nFilledLen * 8, 32); + struct vl_vlc vlc; + + vl_vlc_init(&vlc, priv->num_in_buffers, priv->inputs, priv->sizes); + + if (priv->slice) + priv->bytes_left = vl_vlc_bits_left(&vlc) / 8; + + while (vl_vlc_bits_left (&vlc) > min_bits_left) { + vid_dec_h264_Decode(priv, &vlc, min_bits_left); + vl_vlc_fillbits(&vlc); + } + + if (priv->slice) { + unsigned bytes = priv->bytes_left - vl_vlc_bits_left(&vlc) / 8; + + priv->codec->decode_bitstream(priv->codec, priv->target, &priv->picture.base, + 1, &priv->slice, &bytes); + + if (priv->num_in_buffers) + priv->slice = priv->inputs[1]; + else + priv->slice = NULL; + } + + if (priv->eos_ && priv->frame_started) + vid_dec_h264_EndFrame(priv); + + if (priv->frame_finished) { + priv->frame_finished = false; + h264d_manage_buffers(priv); + } else if (priv->eos_) { + vid_dec_FreeInputPortPrivate(priv->in_buffers[0]); + h264d_manage_buffers(priv); + } else { + priv->in_buffers[0]->nFilledLen = 0; + h264d_buffer_emptied(priv, priv->in_buffers[0]); + } + + if (priv->out_port_disabled_) { + /* In case out port is disabled, h264d_buffer_emptied will fail to release input port. + * We need to wait before shifting the buffers in that case and check in + * get_input_buffer when out port is enabled to release and shift the buffers. + * Infinite looping occurs if buffer is not released */ + if (priv->num_in_buffers == 2) { + /* Set the delta value for use in get_input_buffer before exiting */ + dec_frame_delta = MIN2((min_bits_left - vl_vlc_bits_left(&vlc)) / 8, priv->sizes[1]); + } + break; + } + + h264d_shift_buffers_left(priv); + } + + return OMX_ErrorNone; +} + +/* + * h264dprc + */ + +static void * h264d_prc_ctor(void *ap_obj, va_list * app) +{ + vid_dec_PrivateType*priv = super_ctor(typeOf (ap_obj, "h264dprc"), ap_obj, app); + assert(priv); + priv->p_inhdr_ = 0; + priv->p_outhdr_ = 0; + priv->first_buf_in_frame = true; + priv->eos_ = false; + priv->in_port_disabled_ = false; + priv->out_port_disabled_ = false; + priv->picture.base.profile = PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH; + priv->profile = PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH; + reset_stream_parameters(priv); + + return priv; +} + +static void * h264d_prc_dtor(void *ap_obj) +{ + return super_dtor(typeOf(ap_obj, "h264dprc"), ap_obj); +} + +static OMX_ERRORTYPE h264d_prc_allocate_resources(void *ap_obj, OMX_U32 a_pid) +{ + vid_dec_PrivateType*priv = ap_obj; + struct pipe_screen *screen; + vl_csc_matrix csc; + + assert (priv); + + priv->screen = omx_get_screen(); + if (!priv->screen) + return OMX_ErrorInsufficientResources; + + screen = priv->screen->pscreen; + priv->pipe = pipe_create_multimedia_context(screen); + if (!priv->pipe) + return OMX_ErrorInsufficientResources; + + if (!vl_compositor_init(&priv->compositor, priv->pipe)) { + priv->pipe->destroy(priv->pipe); + priv->pipe = NULL; + return OMX_ErrorInsufficientResources; + } + + if (!vl_compositor_init_state(&priv->cstate, priv->pipe)) { + vl_compositor_cleanup(&priv->compositor); + priv->pipe->destroy(priv->pipe); + priv->pipe = NULL; + return OMX_ErrorInsufficientResources; + } + + vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601, NULL, true, &csc); + if (!vl_compositor_set_csc_matrix(&priv->cstate, (const vl_csc_matrix *)&csc, 1.0f, 0.0f)) { + vl_compositor_cleanup(&priv->compositor); + priv->pipe->destroy(priv->pipe); + priv->pipe = NULL; + return OMX_ErrorInsufficientResources; + } + + list_inithead(&priv->codec_data.h264.dpb_list); + + priv->video_buffer_map = util_hash_table_create_ptr_keys(); + + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE h264d_prc_deallocate_resources(void *ap_obj) +{ + vid_dec_PrivateType*priv = ap_obj; + assert(priv); + + /* Clear hash table */ + util_hash_table_foreach(priv->video_buffer_map, + &hash_table_clear_item_callback, + NULL); + _mesa_hash_table_destroy(priv->video_buffer_map, NULL); + + if (priv->pipe) { + vl_compositor_cleanup_state(&priv->cstate); + vl_compositor_cleanup(&priv->compositor); + priv->pipe->destroy(priv->pipe); + } + + if (priv->screen) + omx_put_screen(); + + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE h264d_prc_prepare_to_transfer(void *ap_obj, OMX_U32 a_pid) +{ + vid_dec_PrivateType*priv = ap_obj; + assert(priv); + + TIZ_INIT_OMX_PORT_STRUCT(priv->out_port_def_, + OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX); + tiz_check_omx( + tiz_api_GetParameter(tiz_get_krn(handleOf(priv)), handleOf(priv), + OMX_IndexParamPortDefinition, &(priv->out_port_def_))); + + priv->first_buf_in_frame = true; + priv->eos_ = false; + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE h264d_prc_transfer_and_process(void *ap_obj, OMX_U32 a_pid) +{ + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE h264d_prc_stop_and_return(void *ap_obj) +{ + vid_dec_PrivateType*priv = (vid_dec_PrivateType*) ap_obj; + return h264d_release_all_headers (priv); +} + +static OMX_ERRORTYPE h264d_prc_buffers_ready(const void *ap_obj) +{ + vid_dec_PrivateType*priv = (vid_dec_PrivateType*) ap_obj; + OMX_BUFFERHEADERTYPE *in_buf = NULL; + OMX_BUFFERHEADERTYPE *out_buf = NULL; + + assert(priv); + + /* Set parameters if start of stream */ + if (!priv->eos_ && priv->first_buf_in_frame && (in_buf = get_input_buffer(priv))) { + decode_frame(priv, in_buf); + } + + /* Don't get input buffer if output buffer not found */ + while (!priv->eos_ && (out_buf = get_output_buffer(priv)) && (in_buf = get_input_buffer(priv))) { + if (!priv->out_port_disabled_) { + decode_frame(priv, in_buf); + } + } + + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE h264d_prc_port_flush(const void *ap_obj, OMX_U32 a_pid) +{ + vid_dec_PrivateType*priv = (vid_dec_PrivateType*) ap_obj; + if (OMX_ALL == a_pid || OMX_VID_DEC_AVC_INPUT_PORT_INDEX == a_pid) { + release_input_headers(priv); + reset_stream_parameters(priv); + } + if (OMX_ALL == a_pid || OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX == a_pid) { + release_output_header(priv); + } + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE h264d_prc_port_disable(const void *ap_obj, OMX_U32 a_pid) +{ + vid_dec_PrivateType*priv = (vid_dec_PrivateType*) ap_obj; + assert(priv); + if (OMX_ALL == a_pid || OMX_VID_DEC_AVC_INPUT_PORT_INDEX == a_pid) { + /* Release all buffers */ + h264d_release_all_headers(priv); + reset_stream_parameters(priv); + priv->in_port_disabled_ = true; + } + if (OMX_ALL == a_pid || OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX == a_pid) { + release_output_header(priv); + priv->out_port_disabled_ = true; + } + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE h264d_prc_port_enable(const void *ap_obj, OMX_U32 a_pid) +{ + vid_dec_PrivateType* priv = (vid_dec_PrivateType*) ap_obj; + assert(priv); + if (OMX_ALL == a_pid || OMX_VID_DEC_AVC_INPUT_PORT_INDEX == a_pid) { + if (priv->in_port_disabled_) { + reset_stream_parameters(priv); + priv->in_port_disabled_ = false; + } + } + if (OMX_ALL == a_pid || OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX == a_pid) { + priv->out_port_disabled_ = false; + } + return OMX_ErrorNone; +} + +/* + * h264d_prc_class + */ + +static void * h264d_prc_class_ctor(void *ap_obj, va_list * app) +{ + /* NOTE: Class methods might be added in the future. None for now. */ + return super_ctor(typeOf(ap_obj, "h264dprc_class"), ap_obj, app); +} + +/* + * initialization + */ + +void * h264d_prc_class_init(void * ap_tos, void * ap_hdl) +{ + void * tizprc = tiz_get_type(ap_hdl, "tizprc"); + void * h264dprc_class = factory_new + /* TIZ_CLASS_COMMENT: class type, class name, parent, size */ + (classOf(tizprc), "h264dprc_class", classOf(tizprc), + sizeof(h264d_prc_class_t), + /* TIZ_CLASS_COMMENT: */ + ap_tos, ap_hdl, + /* TIZ_CLASS_COMMENT: class constructor */ + ctor, h264d_prc_class_ctor, + /* TIZ_CLASS_COMMENT: stop value*/ + 0); + return h264dprc_class; +} + +void * h264d_prc_init(void * ap_tos, void * ap_hdl) +{ + void * tizprc = tiz_get_type(ap_hdl, "tizprc"); + void * h264dprc_class = tiz_get_type(ap_hdl, "h264dprc_class"); + TIZ_LOG_CLASS (h264dprc_class); + void * h264dprc = factory_new + /* TIZ_CLASS_COMMENT: class type, class name, parent, size */ + (h264dprc_class, "h264dprc", tizprc, sizeof(vid_dec_PrivateType), + /* TIZ_CLASS_COMMENT: */ + ap_tos, ap_hdl, + /* TIZ_CLASS_COMMENT: class constructor */ + ctor, h264d_prc_ctor, + /* TIZ_CLASS_COMMENT: class destructor */ + dtor, h264d_prc_dtor, + /* TIZ_CLASS_COMMENT: */ + tiz_srv_allocate_resources, h264d_prc_allocate_resources, + /* TIZ_CLASS_COMMENT: */ + tiz_srv_deallocate_resources, h264d_prc_deallocate_resources, + /* TIZ_CLASS_COMMENT: */ + tiz_srv_prepare_to_transfer, h264d_prc_prepare_to_transfer, + /* TIZ_CLASS_COMMENT: */ + tiz_srv_transfer_and_process, h264d_prc_transfer_and_process, + /* TIZ_CLASS_COMMENT: */ + tiz_srv_stop_and_return, h264d_prc_stop_and_return, + /* TIZ_CLASS_COMMENT: */ + tiz_prc_buffers_ready, h264d_prc_buffers_ready, + /* TIZ_CLASS_COMMENT: */ + tiz_prc_port_flush, h264d_prc_port_flush, + /* TIZ_CLASS_COMMENT: */ + tiz_prc_port_disable, h264d_prc_port_disable, + /* TIZ_CLASS_COMMENT: */ + tiz_prc_port_enable, h264d_prc_port_enable, + /* TIZ_CLASS_COMMENT: stop value*/ + 0); + + return h264dprc; +} diff --git a/src/gallium/frontends/omx/tizonia/h264dprc.h b/src/gallium/frontends/omx/tizonia/h264dprc.h new file mode 100644 index 00000000000..08af5491a3e --- /dev/null +++ b/src/gallium/frontends/omx/tizonia/h264dprc.h @@ -0,0 +1,31 @@ +/************************************************************************** + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef H264DPRC_H +#define H264DPRC_H + +void * h264d_prc_class_init(void * ap_tos, void * ap_hdl); +void * h264d_prc_init(void * ap_tos, void * ap_hdl); + +#endif /* H264DPRC_H */ diff --git a/src/gallium/frontends/omx/tizonia/h264e.c b/src/gallium/frontends/omx/tizonia/h264e.c new file mode 100644 index 00000000000..8ff4b14c53c --- /dev/null +++ b/src/gallium/frontends/omx/tizonia/h264e.c @@ -0,0 +1,184 @@ +/************************************************************************** + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include + +#include "h264eprc.h" +#include "h264e.h" +#include "names.h" +#include "vid_enc_common.h" + +static OMX_VERSIONTYPE h264e_encoder_version = {{0, 0, 0, 1}}; + +OMX_PTR instantiate_h264e_input_port(OMX_HANDLETYPE ap_hdl) +{ + OMX_VIDEO_PORTDEFINITIONTYPE portdef; + OMX_VIDEO_CODINGTYPE encodings[] = { + OMX_VIDEO_CodingUnused, + OMX_VIDEO_CodingMax + }; + OMX_COLOR_FORMATTYPE formats[] = { + OMX_COLOR_FormatYUV420SemiPlanar, + OMX_COLOR_FormatMax + }; + tiz_port_options_t rawvideo_port_opts = { + OMX_PortDomainVideo, + OMX_DirInput, + OMX_VID_ENC_AVC_INPUT_PORT_MIN_BUF_COUNT, + OMX_VID_ENC_AVC_PORT_MIN_INPUT_BUF_SIZE, + OMX_VID_ENC_AVC_PORT_NONCONTIGUOUS, + OMX_VID_ENC_AVC_PORT_ALIGNMENT, + OMX_VID_ENC_AVC_PORT_SUPPLIERPREF, + {OMX_VID_ENC_AVC_INPUT_PORT_INDEX, NULL, NULL, NULL}, + 1 /* Slave port */ + }; + + portdef.pNativeRender = NULL; + portdef.nFrameWidth = OMX_VID_ENC_AVC_DEFAULT_FRAME_WIDTH; + portdef.nFrameHeight = OMX_VID_ENC_AVC_DEFAULT_FRAME_HEIGHT; + portdef.nStride = 0; + portdef.nSliceHeight = 0; + portdef.nBitrate = 64000; + portdef.xFramerate = 15; + portdef.bFlagErrorConcealment = OMX_FALSE; + portdef.eCompressionFormat = OMX_VIDEO_CodingUnused; + portdef.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; + portdef.pNativeWindow = NULL; + + return factory_new(tiz_get_type(ap_hdl, "h264einport"), + &rawvideo_port_opts, &portdef, + &encodings, &formats); +} + +OMX_PTR instantiate_h264e_output_port(OMX_HANDLETYPE ap_hdl) +{ + OMX_VIDEO_PORTDEFINITIONTYPE portdef; + OMX_VIDEO_PARAM_AVCTYPE avctype; + OMX_VIDEO_PARAM_BITRATETYPE bitrate; + OMX_VIDEO_PARAM_QUANTIZATIONTYPE quant; + + OMX_VIDEO_CODINGTYPE encodings[] = { + OMX_VIDEO_CodingAVC, + OMX_VIDEO_CodingMax + }; + OMX_COLOR_FORMATTYPE formats[] = { + OMX_COLOR_FormatUnused, + OMX_COLOR_FormatMax + }; + tiz_port_options_t avc_port_opts = { + OMX_PortDomainVideo, + OMX_DirOutput, + OMX_VID_ENC_AVC_OUTPUT_PORT_MIN_BUF_COUNT, + OMX_VID_ENC_AVC_PORT_MIN_OUTPUT_BUF_SIZE, + OMX_VID_ENC_AVC_PORT_NONCONTIGUOUS, + OMX_VID_ENC_AVC_PORT_ALIGNMENT, + OMX_VID_ENC_AVC_PORT_SUPPLIERPREF, + {OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX, NULL, NULL, NULL}, + 0 /* Master port */ + }; + OMX_VIDEO_AVCLEVELTYPE levels[] = { + OMX_VIDEO_AVCLevel51, + OMX_VIDEO_AVCLevel1, + OMX_VIDEO_AVCLevel1b, + OMX_VIDEO_AVCLevel11, + OMX_VIDEO_AVCLevel12, + OMX_VIDEO_AVCLevel13, + OMX_VIDEO_AVCLevel2, + OMX_VIDEO_AVCLevel21, + OMX_VIDEO_AVCLevel22, + OMX_VIDEO_AVCLevel3, + OMX_VIDEO_AVCLevel31, + OMX_VIDEO_AVCLevel32, + OMX_VIDEO_AVCLevel4, + OMX_VIDEO_AVCLevel41, + OMX_VIDEO_AVCLevel42, + OMX_VIDEO_AVCLevel5, + OMX_VIDEO_AVCLevelMax + }; + + /* Values set from as given in specification */ + portdef.pNativeRender = NULL; + portdef.nFrameWidth = OMX_VID_ENC_AVC_DEFAULT_FRAME_WIDTH; + portdef.nFrameHeight = OMX_VID_ENC_AVC_DEFAULT_FRAME_HEIGHT; + portdef.nStride = 0; + portdef.nSliceHeight = 0; + portdef.nBitrate = 64000; + portdef.xFramerate = 15; + portdef.bFlagErrorConcealment = OMX_FALSE; + portdef.eCompressionFormat = OMX_VIDEO_CodingAVC; + portdef.eColorFormat = OMX_COLOR_FormatUnused; + portdef.pNativeWindow = NULL; + + bitrate.eControlRate = OMX_Video_ControlRateDisable; + bitrate.nTargetBitrate = 0; + + quant.nQpI = OMX_VID_ENC_QUANT_I_FRAMES_DEFAULT; + quant.nQpP = OMX_VID_ENC_QUANT_P_FRAMES_DEFAULT; + quant.nQpB = OMX_VID_ENC_QUANT_B_FRAMES_DEFAULT; + + avctype.nSize = sizeof (OMX_VIDEO_PARAM_AVCTYPE); + avctype.nVersion.nVersion = OMX_VERSION; + avctype.nPortIndex = OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX; + avctype.eProfile = OMX_VIDEO_AVCProfileBaseline; + avctype.nSliceHeaderSpacing = 0; + avctype.nPFrames = 0; + avctype.nBFrames = 0; + avctype.bUseHadamard = OMX_TRUE; + avctype.nRefFrames = 1; + avctype.nRefIdx10ActiveMinus1 = 1; + avctype.nRefIdx11ActiveMinus1 = 0; + avctype.bEnableUEP = OMX_FALSE; + avctype.bEnableFMO = OMX_FALSE; + avctype.bEnableASO = OMX_FALSE; + avctype.bEnableRS = OMX_FALSE; + avctype.eLevel = OMX_VIDEO_AVCLevel51; + avctype.nAllowedPictureTypes = 2; + avctype.bFrameMBsOnly = OMX_FALSE; + avctype.bMBAFF = OMX_FALSE; + avctype.bEntropyCodingCABAC = OMX_FALSE; + avctype.bWeightedPPrediction = OMX_FALSE; + avctype.nWeightedBipredicitonMode = 0; + avctype.bconstIpred = OMX_FALSE; + avctype.bDirect8x8Inference = OMX_FALSE; + avctype.bDirectSpatialTemporal = OMX_FALSE; + avctype.nCabacInitIdc = 0; + avctype.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable; + + return factory_new(tiz_get_type(ap_hdl, "h264eoutport"), + &avc_port_opts, &portdef, + &encodings, &formats, &avctype, &levels, + &bitrate, &quant); +} + +OMX_PTR instantiate_h264e_config_port(OMX_HANDLETYPE ap_hdl) +{ + return factory_new(tiz_get_type(ap_hdl, "tizconfigport"), + NULL, /* this port does not take options */ + OMX_VID_COMP_NAME, h264e_encoder_version); +} + +OMX_PTR instantiate_h264e_processor(OMX_HANDLETYPE ap_hdl) +{ + return factory_new(tiz_get_type(ap_hdl, "h264eprc")); +} diff --git a/src/gallium/frontends/omx/tizonia/h264e.h b/src/gallium/frontends/omx/tizonia/h264e.h new file mode 100644 index 00000000000..de8316c726d --- /dev/null +++ b/src/gallium/frontends/omx/tizonia/h264e.h @@ -0,0 +1,55 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef H264E_H +#define H264E_H + +#include +#include +#include + +#define OMX_VID_ENC_AVC_ROLE "video_encoder.avc" + +/* With libtizonia, port indexes must start at index 0 */ +#define OMX_VID_ENC_AVC_INPUT_PORT_INDEX 0 +#define OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX 1 +#define OMX_VID_ENC_AVC_DEFAULT_FRAME_WIDTH 176 +#define OMX_VID_ENC_AVC_DEFAULT_FRAME_HEIGHT 144 +#define OMX_VID_ENC_AVC_INPUT_PORT_MIN_BUF_COUNT 8 +#define OMX_VID_ENC_AVC_OUTPUT_PORT_MIN_BUF_COUNT 2 +#define OMX_VID_ENC_AVC_PORT_MIN_INPUT_BUF_SIZE 4 * 1024 +#define OMX_VID_ENC_AVC_PORT_MIN_OUTPUT_BUF_SIZE 345600 +#define OMX_VID_ENC_AVC_PORT_NONCONTIGUOUS OMX_FALSE +#define OMX_VID_ENC_AVC_PORT_ALIGNMENT 0 +#define OMX_VID_ENC_AVC_PORT_SUPPLIERPREF OMX_BufferSupplyInput + +OMX_PTR instantiate_h264e_config_port(OMX_HANDLETYPE ap_hdl); +OMX_PTR instantiate_h264e_input_port(OMX_HANDLETYPE ap_hdl); +OMX_PTR instantiate_h264e_output_port(OMX_HANDLETYPE ap_hdl); +OMX_PTR instantiate_h264e_processor(OMX_HANDLETYPE ap_hdl); + +#endif /* H264E_H */ diff --git a/src/gallium/frontends/omx/tizonia/h264einport.c b/src/gallium/frontends/omx/tizonia/h264einport.c new file mode 100644 index 00000000000..609a1782b6b --- /dev/null +++ b/src/gallium/frontends/omx/tizonia/h264einport.c @@ -0,0 +1,216 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include +#include +#include + +#include +#include + +#include "vl/vl_winsys.h" + +#include "h264e.h" +#include "h264einport.h" +#include "h264einport_decls.h" +#include "vid_enc_common.h" + +static OMX_ERRORTYPE enc_AllocateBackTexture(OMX_HANDLETYPE ap_hdl, + OMX_U32 idx, + struct pipe_resource **resource, + struct pipe_transfer **transfer, + OMX_U8 **map) +{ + vid_enc_PrivateType * priv = tiz_get_prc(ap_hdl); + tiz_port_t * port = tiz_krn_get_port(tiz_get_krn(ap_hdl), idx); + struct pipe_resource buf_templ; + struct pipe_box box = {}; + OMX_U8 *ptr; + + memset(&buf_templ, 0, sizeof buf_templ); + buf_templ.target = PIPE_TEXTURE_2D; + buf_templ.format = PIPE_FORMAT_I8_UNORM; + buf_templ.bind = PIPE_BIND_LINEAR; + buf_templ.usage = PIPE_USAGE_STAGING; + buf_templ.flags = 0; + buf_templ.width0 = port->portdef_.format.video.nFrameWidth; + buf_templ.height0 = port->portdef_.format.video.nFrameHeight * 3 / 2; + buf_templ.depth0 = 1; + buf_templ.array_size = 1; + + *resource = priv->s_pipe->screen->resource_create(priv->s_pipe->screen, &buf_templ); + if (!*resource) + return OMX_ErrorInsufficientResources; + + box.width = (*resource)->width0; + box.height = (*resource)->height0; + box.depth = (*resource)->depth0; + ptr = priv->s_pipe->transfer_map(priv->s_pipe, *resource, 0, PIPE_TRANSFER_WRITE, &box, transfer); + if (map) + *map = ptr; + + return OMX_ErrorNone; +} + +/* + * h264einport class + */ + +static void * h264e_inport_ctor(void * ap_obj, va_list * app) +{ + return super_ctor(typeOf(ap_obj, "h264einport"), ap_obj, app); +} + +static void * h264e_inport_dtor(void * ap_obj) +{ + return super_dtor(typeOf(ap_obj, "h264einport"), ap_obj); +} + +/* + * from tiz_api + */ + +static OMX_ERRORTYPE h264e_inport_AllocateBuffer(const void * ap_obj, OMX_HANDLETYPE ap_hdl, + OMX_BUFFERHEADERTYPE ** buf, OMX_U32 idx, + OMX_PTR private, OMX_U32 size) +{ + struct input_buf_private *inp; + OMX_ERRORTYPE r; + + r = super_UseBuffer(typeOf(ap_obj, "h264einport"), ap_obj, ap_hdl, + buf, idx, private, size, NULL); + if (r) + return r; + + inp = (*buf)->pInputPortPrivate = CALLOC_STRUCT(input_buf_private); + if (!inp) { + super_FreeBuffer(typeOf(ap_obj, "h264einport"), ap_obj, ap_hdl, idx, *buf); + return OMX_ErrorInsufficientResources; + } + + list_inithead(&inp->tasks); + + r = enc_AllocateBackTexture(ap_hdl, idx, &inp->resource, &inp->transfer, &(*buf)->pBuffer); + + if (r) { + FREE(inp); + super_FreeBuffer(typeOf(ap_obj, "h264einport"), ap_obj, ap_hdl, idx, *buf); + return r; + } + + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE h264e_inport_UseBuffer(const void * ap_obj, OMX_HANDLETYPE ap_hdl, + OMX_BUFFERHEADERTYPE **buf, OMX_U32 idx, + OMX_PTR private, OMX_U32 size, OMX_U8 *mem) +{ + struct input_buf_private *inp; + OMX_ERRORTYPE r; + + r = super_UseBuffer(typeOf(ap_obj, "h264einport"), ap_obj, ap_hdl, + buf, idx, private, size, mem); + if (r) + return r; + + inp = (*buf)->pInputPortPrivate = CALLOC_STRUCT(input_buf_private); + if (!inp) { + super_FreeBuffer(typeOf(ap_obj, "h264einport"), ap_obj, ap_hdl, idx, *buf); + return OMX_ErrorInsufficientResources; + } + + list_inithead(&inp->tasks); + + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE h264e_inport_FreeBuffer(const void * ap_obj, OMX_HANDLETYPE ap_hdl, + OMX_U32 idx, OMX_BUFFERHEADERTYPE *buf) +{ + vid_enc_PrivateType *priv = tiz_get_prc(ap_hdl); + struct input_buf_private *inp = buf->pInputPortPrivate; + + if (inp) { + enc_ReleaseTasks(&inp->tasks); + if (inp->transfer) + pipe_transfer_unmap(priv->s_pipe, inp->transfer); + pipe_resource_reference(&inp->resource, NULL); + FREE(inp); + } + + return super_FreeBuffer(typeOf(ap_obj, "h264einport"), ap_obj, ap_hdl, idx, buf); +} + +/* + * h264einport_class + */ + +static void * h264e_inport_class_ctor(void * ap_obj, va_list * app) +{ + /* NOTE: Class methods might be added in the future. None for now. */ + return super_ctor (typeOf (ap_obj, "h264einport_class"), ap_obj, app); +} + +/* + * initialization + */ + +void * h264e_inport_class_init(void * ap_tos, void * ap_hdl) +{ + void * tizvideoport = tiz_get_type(ap_hdl, "tizvideoport"); + void * h264einport_class + = factory_new(classOf(tizvideoport), "h264einport_class", + classOf(tizvideoport), sizeof(h264e_inport_class_t), + ap_tos, ap_hdl, ctor, h264e_inport_class_ctor, 0); + return h264einport_class; +} + +void * h264e_inport_init(void * ap_tos, void * ap_hdl) +{ + void * tizvideoport = tiz_get_type (ap_hdl, "tizvideoport"); + void * h264einport_class = tiz_get_type (ap_hdl, "h264einport_class"); + void * h264einport = factory_new + /* TIZ_CLASS_COMMENT: class type, class name, parent, size */ + (h264einport_class, "h264einport", tizvideoport, + sizeof (h264e_inport_t), + /* TIZ_CLASS_COMMENT: class constructor */ + ap_tos, ap_hdl, + /* TIZ_CLASS_COMMENT: class constructor */ + ctor, h264e_inport_ctor, + /* TIZ_CLASS_COMMENT: class destructor */ + dtor, h264e_inport_dtor, + /* TIZ_CLASS_COMMENT: */ + tiz_api_AllocateBuffer, h264e_inport_AllocateBuffer, + /* TIZ_CLASS_COMMENT: */ + tiz_api_UseBuffer, h264e_inport_UseBuffer, + /* TIZ_CLASS_COMMENT: */ + tiz_api_FreeBuffer, h264e_inport_FreeBuffer, + /* TIZ_CLASS_COMMENT: stop value*/ + 0); + + return h264einport; +} diff --git a/src/gallium/frontends/omx/tizonia/h264einport.h b/src/gallium/frontends/omx/tizonia/h264einport.h new file mode 100644 index 00000000000..3dd89061970 --- /dev/null +++ b/src/gallium/frontends/omx/tizonia/h264einport.h @@ -0,0 +1,31 @@ +/************************************************************************** + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef H264EINPORT_H +#define H264EINPORT_H + +void * h264e_inport_class_init(void * ap_tos, void * ap_hdl); +void * h264e_inport_init(void * ap_tos, void * ap_hdl); + +#endif /* H264EINPORT_H */ diff --git a/src/gallium/frontends/omx/tizonia/h264einport_decls.h b/src/gallium/frontends/omx/tizonia/h264einport_decls.h new file mode 100644 index 00000000000..9efaf742b84 --- /dev/null +++ b/src/gallium/frontends/omx/tizonia/h264einport_decls.h @@ -0,0 +1,48 @@ +/************************************************************************** + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef H264EINPORT_DECLS_H +#define H264EINPORT_DECLS_H + +#include +#include + +#include + +typedef struct h264e_inport h264e_inport_t; +struct h264e_inport +{ + /* Object */ + const tiz_videoport_t _; +}; + +typedef struct h264e_inport_class h264e_inport_class_t; +struct h264e_inport_class +{ + /* Class */ + const tiz_videoport_class_t _; + /* NOTE: Class methods might be added in the future */ +}; + +#endif /* H264EINPORT_DECLS_H */ diff --git a/src/gallium/frontends/omx/tizonia/h264eoutport.c b/src/gallium/frontends/omx/tizonia/h264eoutport.c new file mode 100644 index 00000000000..775e04278a4 --- /dev/null +++ b/src/gallium/frontends/omx/tizonia/h264eoutport.c @@ -0,0 +1,143 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include +#include +#include + +#include + +#include "vl/vl_winsys.h" + +#include "h264eoutport.h" +#include "h264eoutport_decls.h" +#include "vid_enc_common.h" + +/* + * h264eoutport class + */ + +static void * h264e_outport_ctor(void * ap_obj, va_list * app) +{ + return super_ctor(typeOf(ap_obj, "h264eoutport"), ap_obj, app); +} + +static void * h264e_outport_dtor(void * ap_obj) +{ + return super_dtor(typeOf(ap_obj, "h264eoutport"), ap_obj); +} + +/* + * from tiz_api + */ + +static OMX_ERRORTYPE h264e_outport_AllocateBuffer(const void * ap_obj, OMX_HANDLETYPE ap_hdl, + OMX_BUFFERHEADERTYPE ** buf, OMX_U32 idx, + OMX_PTR private, OMX_U32 size) +{ + OMX_ERRORTYPE r; + + r = super_UseBuffer(typeOf(ap_obj, "h264eoutport"), ap_obj, ap_hdl, + buf, idx, private, size, NULL); + if (r) + return r; + + (*buf)->pBuffer = NULL; + (*buf)->pOutputPortPrivate = CALLOC(1, sizeof(struct output_buf_private)); + if (!(*buf)->pOutputPortPrivate) { + super_FreeBuffer(typeOf(ap_obj, "h264eoutport"), ap_obj, ap_hdl, idx, *buf); + return OMX_ErrorInsufficientResources; + } + + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE h264e_outport_FreeBuffer(const void * ap_obj, OMX_HANDLETYPE ap_hdl, + OMX_U32 idx, OMX_BUFFERHEADERTYPE *buf) +{ + vid_enc_PrivateType *priv = tiz_get_prc(ap_hdl); + struct output_buf_private *outp = buf->pOutputPortPrivate; + + if (outp) { + if (outp->transfer) + pipe_transfer_unmap(priv->t_pipe, outp->transfer); + pipe_resource_reference(&outp->bitstream, NULL); + FREE(outp); + buf->pOutputPortPrivate = NULL; + } + buf->pBuffer = NULL; + + return super_FreeBuffer(typeOf(ap_obj, "h264eoutport"), ap_obj, ap_hdl, idx, buf); +} + +/* + * h264e_outport_class + */ + +static void * h264e_outport_class_ctor(void * ap_obj, va_list * app) +{ + /* NOTE: Class methods might be added in the future. None for now. */ + return super_ctor(typeOf(ap_obj, "h264eoutport_class"), ap_obj, app); +} + +/* + * initialization + */ + +void * h264e_outport_class_init(void * ap_tos, void * ap_hdl) +{ + void * tizavcport = tiz_get_type(ap_hdl, "tizavcport"); + void * h264eoutport_class + = factory_new (classOf(tizavcport), "h264eoutport_class", + classOf(tizavcport), sizeof(h264e_outport_class_t), + ap_tos, ap_hdl, ctor, h264e_outport_class_ctor, 0); + return h264eoutport_class; +} + +void * h264e_outport_init(void * ap_tos, void * ap_hdl) +{ + void * tizavcport = tiz_get_type(ap_hdl, "tizavcport"); + void * h264eoutport_class = tiz_get_type(ap_hdl, "h264eoutport_class"); + void * h264eoutport = factory_new + /* TIZ_CLASS_COMMENT: class type, class name, parent, size */ + (h264eoutport_class, "h264eoutport", tizavcport, + sizeof(h264e_outport_t), + /* TIZ_CLASS_COMMENT: class constructor */ + ap_tos, ap_hdl, + /* TIZ_CLASS_COMMENT: class constructor */ + ctor, h264e_outport_ctor, + /* TIZ_CLASS_COMMENT: class destructor */ + dtor, h264e_outport_dtor, + /* TIZ_CLASS_COMMENT: */ + tiz_api_AllocateBuffer, h264e_outport_AllocateBuffer, + /* TIZ_CLASS_COMMENT: */ + tiz_api_FreeBuffer, h264e_outport_FreeBuffer, + /* TIZ_CLASS_COMMENT: stop value*/ + 0); + + return h264eoutport; +} diff --git a/src/gallium/frontends/omx/tizonia/h264eoutport.h b/src/gallium/frontends/omx/tizonia/h264eoutport.h new file mode 100644 index 00000000000..afbf9fed3f7 --- /dev/null +++ b/src/gallium/frontends/omx/tizonia/h264eoutport.h @@ -0,0 +1,31 @@ +/************************************************************************** + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef H264EOUTPORT_H +#define H264EOUTPORT_H + +void * h264e_outport_class_init(void * ap_tos, void * ap_hdl); +void * h264e_outport_init(void * ap_tos, void * ap_hdl); + +#endif /* H264EOUTPORT_H */ diff --git a/src/gallium/frontends/omx/tizonia/h264eoutport_decls.h b/src/gallium/frontends/omx/tizonia/h264eoutport_decls.h new file mode 100644 index 00000000000..28c9e06a0f7 --- /dev/null +++ b/src/gallium/frontends/omx/tizonia/h264eoutport_decls.h @@ -0,0 +1,48 @@ +/************************************************************************** + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef H264EOUTPORT_DECLS_H +#define H264EOUTPORT_DECLS_H + +#include +#include + +#include + +typedef struct h264e_outport h264e_outport_t; +struct h264e_outport +{ + /* Object */ + const tiz_avcport_t _; +}; + +typedef struct h264e_outport_class h264e_outport_class_t; +struct h264e_outport_class +{ + /* Class */ + const tiz_avcport_class_t _; + /* NOTE: Class methods might be added in the future */ +}; + +#endif /* H264EOUTPORT_DECLS_H */ diff --git a/src/gallium/frontends/omx/tizonia/h264eprc.c b/src/gallium/frontends/omx/tizonia/h264eprc.c new file mode 100644 index 00000000000..b52e489f21c --- /dev/null +++ b/src/gallium/frontends/omx/tizonia/h264eprc.c @@ -0,0 +1,698 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include +#include +#include + +#include "pipe/p_screen.h" +#include "pipe/p_video_codec.h" +#include "util/u_memory.h" + +#include "entrypoint.h" +#include "h264e.h" +#include "h264eprc.h" +#include "vid_omx_common.h" +#include "vid_enc_common.h" + +static OMX_ERRORTYPE init_port_structs(vid_enc_PrivateType * priv) { + const void * p_krn = NULL; + + assert(priv); + + /* Initialisation */ + TIZ_INIT_OMX_PORT_STRUCT(priv->in_port_def_, + OMX_VID_ENC_AVC_INPUT_PORT_INDEX); + TIZ_INIT_OMX_PORT_STRUCT(priv->out_port_def_, + OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX); + TIZ_INIT_OMX_PORT_STRUCT(priv->bitrate, + OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX); + TIZ_INIT_OMX_PORT_STRUCT(priv->quant, + OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX); + TIZ_INIT_OMX_PORT_STRUCT(priv->profile_level, + OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX); + + /* Get values */ + p_krn = tiz_get_krn(handleOf(priv)); + + tiz_check_omx( + tiz_api_GetParameter(p_krn, handleOf(priv), + OMX_IndexParamPortDefinition, &(priv->in_port_def_))); + tiz_check_omx( + tiz_api_GetParameter(p_krn, handleOf(priv), + OMX_IndexParamPortDefinition, &(priv->out_port_def_))); + tiz_check_omx( + tiz_api_GetParameter(p_krn, handleOf(priv), + OMX_IndexParamVideoBitrate, &(priv->bitrate))); + tiz_check_omx( + tiz_api_GetParameter(p_krn, handleOf(priv), + OMX_IndexParamVideoQuantization, &(priv->quant))); + tiz_check_omx( + tiz_api_GetParameter(p_krn, handleOf(priv), + OMX_IndexParamVideoProfileLevelCurrent, &(priv->profile_level))); + + return OMX_ErrorNone; +} + +static OMX_BUFFERHEADERTYPE * get_input_buffer(vid_enc_PrivateType * priv) { + assert(priv); + + if (priv->in_port_disabled_) { + return NULL; + } + + assert(!priv->p_inhdr_); /* encode_frame expects new buffers every time */ + + tiz_krn_claim_buffer(tiz_get_krn(handleOf(priv)), + OMX_VID_ENC_AVC_INPUT_PORT_INDEX, 0, + &priv->p_inhdr_); + return priv->p_inhdr_; +} + +static OMX_BUFFERHEADERTYPE * get_output_buffer(vid_enc_PrivateType * priv) { + assert(priv); + + if (priv->out_port_disabled_) { + return NULL; + } + + if (!priv->p_outhdr_) { + tiz_krn_claim_buffer(tiz_get_krn(handleOf(priv)), + OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX, 0, + &priv->p_outhdr_); + } + return priv->p_outhdr_; +} + +static OMX_ERRORTYPE h264e_buffer_emptied(vid_enc_PrivateType * priv, OMX_BUFFERHEADERTYPE * p_hdr) +{ + OMX_ERRORTYPE r = OMX_ErrorNone; + + assert(priv); + assert(priv->p_inhdr_ == p_hdr); + + if (!priv->out_port_disabled_) { + p_hdr->nOffset = 0; + + if ((p_hdr->nFlags & OMX_BUFFERFLAG_EOS) != 0) { + priv->eos_ = true; + } + + r = tiz_krn_release_buffer(tiz_get_krn(handleOf(priv)), 0, p_hdr); + priv->p_inhdr_ = NULL; + } + + return r; +} + +static OMX_ERRORTYPE h264e_buffer_filled(vid_enc_PrivateType * priv, OMX_BUFFERHEADERTYPE * p_hdr) +{ + OMX_ERRORTYPE r = OMX_ErrorNone; + + assert(priv); + assert(priv->p_outhdr_ == p_hdr); + assert(p_hdr); + + if (!priv->in_port_disabled_) { + p_hdr->nOffset = 0; + + if (priv->eos_) { + /* EOS has been received and all the input data has been consumed + * already, so its time to propagate the EOS flag */ + priv->p_outhdr_->nFlags |= OMX_BUFFERFLAG_EOS; + } + + r = tiz_krn_release_buffer(tiz_get_krn(handleOf(priv)), + OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX, + p_hdr); + priv->p_outhdr_ = NULL; + } + + return r; +} + + +static void release_input_header(vid_enc_PrivateType * priv) { + assert(!priv->in_port_disabled_); + if (priv->p_inhdr_) { + (void) tiz_krn_release_buffer(tiz_get_krn(handleOf(priv)), + OMX_VID_ENC_AVC_INPUT_PORT_INDEX, + priv->p_inhdr_); + } + priv->p_inhdr_ = NULL; +} + +static void release_output_header(vid_enc_PrivateType * priv) { + if (priv->p_outhdr_) { + assert(!priv->out_port_disabled_); + (void) tiz_krn_release_buffer(tiz_get_krn(handleOf(priv)), + OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX, + priv->p_outhdr_); + priv->p_outhdr_ = NULL; + } +} + +static OMX_ERRORTYPE h264e_release_all_headers(vid_enc_PrivateType * priv) +{ + assert(priv); + + release_input_header(priv); + release_output_header(priv); + + return OMX_ErrorNone; +} + +static void reset_stream_parameters(vid_enc_PrivateType * priv) +{ + assert(priv); + init_port_structs(priv); + priv->p_inhdr_ = 0; + priv->p_outhdr_ = 0; + priv->eos_ = false; +} + +/* Replacement for bellagio's omx_base_filter_BufferMgmtFunction */ +static OMX_ERRORTYPE h264e_manage_buffers(vid_enc_PrivateType* priv) { + OMX_BUFFERHEADERTYPE * in_buf = priv->p_inhdr_; + OMX_BUFFERHEADERTYPE * out_buf = priv->p_outhdr_; + OMX_ERRORTYPE r = OMX_ErrorNone; + + if (in_buf->nFilledLen > 0) { + vid_enc_BufferEncoded_common(priv, in_buf, out_buf); + } else { + in_buf->nFilledLen = 0; + } + + out_buf->nTimeStamp = in_buf->nTimeStamp; + + /* Release input buffer if possible */ + if (in_buf->nFilledLen == 0) { + r = h264e_buffer_emptied(priv, in_buf); + } + + /* Realase output buffer if filled or eos */ + if ((out_buf->nFilledLen != 0) || priv->eos_) { + r = h264e_buffer_filled(priv, out_buf); + } + + return r; +} + +static struct encode_task *enc_NeedTask(vid_enc_PrivateType * priv) +{ + OMX_VIDEO_PORTDEFINITIONTYPE *def = &priv->in_port_def_.format.video; + + return enc_NeedTask_common(priv, def); +} + +static void enc_ScaleInput(vid_enc_PrivateType * priv, struct pipe_video_buffer **vbuf, unsigned *size) +{ + OMX_VIDEO_PORTDEFINITIONTYPE *def = &priv->in_port_def_.format.video; + enc_ScaleInput_common(priv, def, vbuf, size); +} + +static void enc_HandleTask(vid_enc_PrivateType * priv, struct encode_task *task, + enum pipe_h264_enc_picture_type picture_type) +{ + unsigned size = priv->out_port_def_.nBufferSize; + struct pipe_video_buffer *vbuf = task->buf; + struct pipe_h264_enc_picture_desc picture = {}; + + /* -------------- scale input image --------- */ + enc_ScaleInput(priv, &vbuf, &size); + priv->s_pipe->flush(priv->s_pipe, NULL, 0); + + /* -------------- allocate output buffer --------- */ + task->bitstream = pipe_buffer_create(priv->s_pipe->screen, + PIPE_BIND_VERTEX_BUFFER, + PIPE_USAGE_STAGING, /* map for read */ + size); + + picture.picture_type = picture_type; + picture.pic_order_cnt = task->pic_order_cnt; + if (priv->restricted_b_frames && picture_type == PIPE_H264_ENC_PICTURE_TYPE_B) + picture.not_referenced = true; + enc_ControlPicture_common(priv, &picture); + + /* -------------- encode frame --------- */ + priv->codec->begin_frame(priv->codec, vbuf, &picture.base); + priv->codec->encode_bitstream(priv->codec, vbuf, task->bitstream, &task->feedback); + priv->codec->end_frame(priv->codec, vbuf, &picture.base); +} + +static void enc_ClearBframes(vid_enc_PrivateType * priv, struct input_buf_private *inp) +{ + struct encode_task *task; + + if (list_is_empty(&priv->b_frames)) + return; + + task = LIST_ENTRY(struct encode_task, priv->b_frames.prev, list); + list_del(&task->list); + + /* promote last from to P frame */ + priv->ref_idx_l0 = priv->ref_idx_l1; + enc_HandleTask(priv, task, PIPE_H264_ENC_PICTURE_TYPE_P); + list_addtail(&task->list, &inp->tasks); + priv->ref_idx_l1 = priv->frame_num++; + + /* handle B frames */ + LIST_FOR_EACH_ENTRY(task, &priv->b_frames, list) { + enc_HandleTask(priv, task, PIPE_H264_ENC_PICTURE_TYPE_B); + if (!priv->restricted_b_frames) + priv->ref_idx_l0 = priv->frame_num; + priv->frame_num++; + } + + enc_MoveTasks(&priv->b_frames, &inp->tasks); +} + +static OMX_ERRORTYPE enc_LoadImage(vid_enc_PrivateType * priv, OMX_BUFFERHEADERTYPE *buf, + struct pipe_video_buffer *vbuf) +{ + OMX_VIDEO_PORTDEFINITIONTYPE *def = &priv->in_port_def_.format.video; + return enc_LoadImage_common(priv, def, buf, vbuf); +} + +static OMX_ERRORTYPE encode_frame(vid_enc_PrivateType * priv, OMX_BUFFERHEADERTYPE * in_buf) +{ + struct input_buf_private *inp = in_buf->pInputPortPrivate; + enum pipe_h264_enc_picture_type picture_type; + struct encode_task *task; + unsigned stacked_num = 0; + OMX_ERRORTYPE err; + + enc_MoveTasks(&inp->tasks, &priv->free_tasks); + task = enc_NeedTask(priv); + if (!task) + return OMX_ErrorInsufficientResources; + + /* EOS */ + if (in_buf->nFilledLen == 0) { + if (in_buf->nFlags & OMX_BUFFERFLAG_EOS) { + in_buf->nFilledLen = in_buf->nAllocLen; + enc_ClearBframes(priv, inp); + enc_MoveTasks(&priv->stacked_tasks, &inp->tasks); + priv->codec->flush(priv->codec); + } + return h264e_manage_buffers(priv); + } + + if (in_buf->pOutputPortPrivate) { + struct pipe_video_buffer *vbuf = in_buf->pOutputPortPrivate; + in_buf->pOutputPortPrivate = task->buf; + task->buf = vbuf; + } else { + /* ------- load input image into video buffer ---- */ + err = enc_LoadImage(priv, in_buf, task->buf); + if (err != OMX_ErrorNone) { + FREE(task); + return err; + } + } + + /* -------------- determine picture type --------- */ + if (!(priv->pic_order_cnt % OMX_VID_ENC_IDR_PERIOD_DEFAULT) || + priv->force_pic_type.IntraRefreshVOP) { + enc_ClearBframes(priv, inp); + picture_type = PIPE_H264_ENC_PICTURE_TYPE_IDR; + priv->force_pic_type.IntraRefreshVOP = OMX_FALSE; + priv->frame_num = 0; + } else if (priv->codec->profile == PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE || + !(priv->pic_order_cnt % OMX_VID_ENC_P_PERIOD_DEFAULT) || + (in_buf->nFlags & OMX_BUFFERFLAG_EOS)) { + picture_type = PIPE_H264_ENC_PICTURE_TYPE_P; + } else { + picture_type = PIPE_H264_ENC_PICTURE_TYPE_B; + } + + task->pic_order_cnt = priv->pic_order_cnt++; + + if (picture_type == PIPE_H264_ENC_PICTURE_TYPE_B) { + /* put frame at the tail of the queue */ + list_addtail(&task->list, &priv->b_frames); + } else { + /* handle I or P frame */ + priv->ref_idx_l0 = priv->ref_idx_l1; + enc_HandleTask(priv, task, picture_type); + list_addtail(&task->list, &priv->stacked_tasks); + LIST_FOR_EACH_ENTRY(task, &priv->stacked_tasks, list) { + ++stacked_num; + } + if (stacked_num == priv->stacked_frames_num) { + struct encode_task *t; + t = LIST_ENTRY(struct encode_task, priv->stacked_tasks.next, list); + list_del(&t->list); + list_addtail(&t->list, &inp->tasks); + } + priv->ref_idx_l1 = priv->frame_num++; + + /* handle B frames */ + LIST_FOR_EACH_ENTRY(task, &priv->b_frames, list) { + enc_HandleTask(priv, task, PIPE_H264_ENC_PICTURE_TYPE_B); + if (!priv->restricted_b_frames) + priv->ref_idx_l0 = priv->frame_num; + priv->frame_num++; + } + + enc_MoveTasks(&priv->b_frames, &inp->tasks); + } + + if (list_is_empty(&inp->tasks)) { + return h264e_buffer_emptied(priv, in_buf); + } else { + return h264e_manage_buffers(priv); + } +} + +static OMX_ERRORTYPE h264e_prc_create_encoder(void *ap_obj) +{ + vid_enc_PrivateType *priv = ap_obj; + struct pipe_screen *screen; + + priv->screen = omx_get_screen(); + if (!priv->screen) + return OMX_ErrorInsufficientResources; + + screen = priv->screen->pscreen; + if (!screen->get_video_param(screen, PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH, + PIPE_VIDEO_ENTRYPOINT_ENCODE, PIPE_VIDEO_CAP_SUPPORTED)) + return OMX_ErrorBadParameter; + + priv->s_pipe = pipe_create_multimedia_context(screen); + if (!priv->s_pipe) + return OMX_ErrorInsufficientResources; + + enc_InitCompute_common(priv); + + if (!vl_compositor_init(&priv->compositor, priv->s_pipe)) { + priv->s_pipe->destroy(priv->s_pipe); + priv->s_pipe = NULL; + return OMX_ErrorInsufficientResources; + } + + if (!vl_compositor_init_state(&priv->cstate, priv->s_pipe)) { + vl_compositor_cleanup(&priv->compositor); + priv->s_pipe->destroy(priv->s_pipe); + priv->s_pipe = NULL; + return OMX_ErrorInsufficientResources; + } + + priv->t_pipe = pipe_create_multimedia_context(screen); + if (!priv->t_pipe) + return OMX_ErrorInsufficientResources; + + list_inithead(&priv->free_tasks); + list_inithead(&priv->used_tasks); + list_inithead(&priv->b_frames); + list_inithead(&priv->stacked_tasks); + + return OMX_ErrorNone; +} + +static void h264e_prc_destroy_encoder(void *ap_obj) +{ + vid_enc_PrivateType *priv = ap_obj; + int i; + + assert (priv); + + enc_ReleaseTasks(&priv->free_tasks); + enc_ReleaseTasks(&priv->used_tasks); + enc_ReleaseTasks(&priv->b_frames); + enc_ReleaseTasks(&priv->stacked_tasks); + + for (i = 0; i < OMX_VID_ENC_NUM_SCALING_BUFFERS; ++i) + if (priv->scale_buffer[i]) + priv->scale_buffer[i]->destroy(priv->scale_buffer[i]); + + if (priv->s_pipe) { + vl_compositor_cleanup_state(&priv->cstate); + vl_compositor_cleanup(&priv->compositor); + enc_ReleaseCompute_common(priv); + priv->s_pipe->destroy(priv->s_pipe); + } + + if (priv->t_pipe) + priv->t_pipe->destroy(priv->t_pipe); + + if (priv->screen) + omx_put_screen(); +} + +/* + * h264eprc + */ + +static void * h264e_prc_ctor(void *ap_obj, va_list * app) +{ + vid_enc_PrivateType *priv = super_ctor(typeOf(ap_obj, "h264eprc"), ap_obj, app); + assert (priv); + + if (h264e_prc_create_encoder(ap_obj) != OMX_ErrorNone) + return priv; + + priv->p_inhdr_ = 0; + priv->p_outhdr_ = 0; + priv->profile_level.eProfile = OMX_VIDEO_AVCProfileBaseline; + priv->profile_level.eLevel = OMX_VIDEO_AVCLevel51; + priv->force_pic_type.IntraRefreshVOP = OMX_FALSE; + priv->frame_num = 0; + priv->pic_order_cnt = 0; + priv->restricted_b_frames = debug_get_bool_option("OMX_USE_RESTRICTED_B_FRAMES", FALSE); + priv->scale.xWidth = OMX_VID_ENC_SCALING_WIDTH_DEFAULT; + priv->scale.xHeight = OMX_VID_ENC_SCALING_WIDTH_DEFAULT; + priv->in_port_disabled_ = false; + priv->out_port_disabled_ = false; + reset_stream_parameters(priv); + + return priv; +} + +static void * h264e_prc_dtor(void *ap_obj) +{ + h264e_prc_destroy_encoder(ap_obj); + return super_dtor(typeOf(ap_obj, "h264eprc"), ap_obj); +} + +static OMX_ERRORTYPE h264e_prc_allocate_resources(void *ap_obj, OMX_U32 a_pid) +{ + vid_enc_PrivateType *priv = ap_obj; + + assert(priv); + if (!priv->screen) + return OMX_ErrorInsufficientResources; + + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE h264e_prc_deallocate_resources(void *ap_obj) +{ + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE h264e_prc_prepare_to_transfer(void *ap_obj, OMX_U32 a_pid) +{ + vid_enc_PrivateType *priv = ap_obj; + + assert(priv); + + init_port_structs(priv); + + priv->eos_ = false; + + struct pipe_video_codec templat = {}; + + templat.profile = enc_TranslateOMXProfileToPipe(priv->profile_level.eProfile); + templat.level = enc_TranslateOMXLevelToPipe(priv->profile_level.eLevel); + templat.entrypoint = PIPE_VIDEO_ENTRYPOINT_ENCODE; + templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; + templat.width = priv->scale_buffer[priv->current_scale_buffer] ? + priv->scale.xWidth : priv->in_port_def_.format.video.nFrameWidth; + templat.height = priv->scale_buffer[priv->current_scale_buffer] ? + priv->scale.xHeight : priv->in_port_def_.format.video.nFrameHeight; + + if (templat.profile == PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE) { + struct pipe_screen *screen = priv->screen->pscreen; + templat.max_references = 1; + priv->stacked_frames_num = + screen->get_video_param(screen, + PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH, + PIPE_VIDEO_ENTRYPOINT_ENCODE, + PIPE_VIDEO_CAP_STACKED_FRAMES); + } else { + templat.max_references = OMX_VID_ENC_P_PERIOD_DEFAULT; + priv->stacked_frames_num = 1; + } + priv->codec = priv->s_pipe->create_video_codec(priv->s_pipe, &templat); + + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE h264e_prc_transfer_and_process(void *ap_obj, OMX_U32 a_pid) +{ + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE h264e_prc_stop_and_return(void *ap_obj) +{ + vid_enc_PrivateType *priv = (vid_enc_PrivateType *) ap_obj; + return h264e_release_all_headers(priv); +} + +static OMX_ERRORTYPE h264e_prc_buffers_ready(const void *ap_obj) +{ + vid_enc_PrivateType *priv = (vid_enc_PrivateType *) ap_obj; + OMX_BUFFERHEADERTYPE *in_buf = NULL; + OMX_BUFFERHEADERTYPE *out_buf = NULL; + OMX_ERRORTYPE r = OMX_ErrorNone; + + assert(priv); + + /* Don't get input buffer if output buffer not found */ + while (!priv->eos_ && (out_buf = get_output_buffer(priv)) && (in_buf = get_input_buffer(priv))) { + if (!priv->out_port_disabled_) { + r = encode_frame(priv, in_buf); + } + } + + return r; +} + +static OMX_ERRORTYPE h264e_prc_port_flush(const void *ap_obj, OMX_U32 a_pid) +{ + vid_enc_PrivateType *priv = (vid_enc_PrivateType *) ap_obj; + if (OMX_ALL == a_pid || OMX_VID_ENC_AVC_INPUT_PORT_INDEX == a_pid) { + release_input_header(priv); + reset_stream_parameters(priv); + } + if (OMX_ALL == a_pid || OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX == a_pid) { + release_output_header(priv); + } + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE h264e_prc_port_disable(const void *ap_obj, OMX_U32 a_pid) +{ + vid_enc_PrivateType *priv = (vid_enc_PrivateType *) ap_obj; + assert(priv); + if (OMX_ALL == a_pid || OMX_VID_ENC_AVC_INPUT_PORT_INDEX == a_pid) { + /* Release all buffers */ + h264e_release_all_headers(priv); + reset_stream_parameters(priv); + priv->in_port_disabled_ = true; + } + if (OMX_ALL == a_pid || OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX == a_pid) { + release_output_header(priv); + priv->out_port_disabled_ = true; + } + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE h264e_prc_port_enable(const void *ap_obj, OMX_U32 a_pid) +{ + vid_enc_PrivateType * priv = (vid_enc_PrivateType *) ap_obj; + assert(priv); + if (OMX_ALL == a_pid || OMX_VID_ENC_AVC_INPUT_PORT_INDEX == a_pid) { + if (priv->in_port_disabled_) { + reset_stream_parameters(priv); + priv->in_port_disabled_ = false; + } + } + if (OMX_ALL == a_pid || OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX == a_pid) { + priv->out_port_disabled_ = false; + } + return OMX_ErrorNone; +} + +/* + * h264e_prc_class + */ + +static void * h264e_prc_class_ctor(void *ap_obj, va_list * app) +{ + /* NOTE: Class methods might be added in the future. None for now. */ + return super_ctor(typeOf(ap_obj, "h264eprc_class"), ap_obj, app); +} + +/* + * initialization + */ + +void * h264e_prc_class_init(void * ap_tos, void * ap_hdl) +{ + void * tizprc = tiz_get_type(ap_hdl, "tizprc"); + void * h264eprc_class = factory_new + /* TIZ_CLASS_COMMENT: class type, class name, parent, size */ + (classOf(tizprc), "h264eprc_class", classOf(tizprc), + sizeof(h264e_prc_class_t), + /* TIZ_CLASS_COMMENT: */ + ap_tos, ap_hdl, + /* TIZ_CLASS_COMMENT: class constructor */ + ctor, h264e_prc_class_ctor, + /* TIZ_CLASS_COMMENT: stop value*/ + 0); + return h264eprc_class; +} + +void * h264e_prc_init(void * ap_tos, void * ap_hdl) +{ + void * tizprc = tiz_get_type(ap_hdl, "tizprc"); + void * h264eprc_class = tiz_get_type(ap_hdl, "h264eprc_class"); + TIZ_LOG_CLASS (h264eprc_class); + void * h264eprc = factory_new + /* TIZ_CLASS_COMMENT: class type, class name, parent, size */ + (h264eprc_class, "h264eprc", tizprc, sizeof(vid_enc_PrivateType), + /* TIZ_CLASS_COMMENT: */ + ap_tos, ap_hdl, + /* TIZ_CLASS_COMMENT: class constructor */ + ctor, h264e_prc_ctor, + /* TIZ_CLASS_COMMENT: class destructor */ + dtor, h264e_prc_dtor, + /* TIZ_CLASS_COMMENT: */ + tiz_srv_allocate_resources, h264e_prc_allocate_resources, + /* TIZ_CLASS_COMMENT: */ + tiz_srv_deallocate_resources, h264e_prc_deallocate_resources, + /* TIZ_CLASS_COMMENT: */ + tiz_srv_prepare_to_transfer, h264e_prc_prepare_to_transfer, + /* TIZ_CLASS_COMMENT: */ + tiz_srv_transfer_and_process, h264e_prc_transfer_and_process, + /* TIZ_CLASS_COMMENT: */ + tiz_srv_stop_and_return, h264e_prc_stop_and_return, + /* TIZ_CLASS_COMMENT: */ + tiz_prc_buffers_ready, h264e_prc_buffers_ready, + /* TIZ_CLASS_COMMENT: */ + tiz_prc_port_flush, h264e_prc_port_flush, + /* TIZ_CLASS_COMMENT: */ + tiz_prc_port_disable, h264e_prc_port_disable, + /* TIZ_CLASS_COMMENT: */ + tiz_prc_port_enable, h264e_prc_port_enable, + /* TIZ_CLASS_COMMENT: stop value*/ + 0); + + return h264eprc; +} diff --git a/src/gallium/frontends/omx/tizonia/h264eprc.h b/src/gallium/frontends/omx/tizonia/h264eprc.h new file mode 100644 index 00000000000..c5bc151a825 --- /dev/null +++ b/src/gallium/frontends/omx/tizonia/h264eprc.h @@ -0,0 +1,31 @@ +/************************************************************************** + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef H264EPRC_H +#define H264EPRC_H + +void * h264e_prc_class_init(void * ap_tos, void * ap_hdl); +void * h264e_prc_init(void * ap_tos, void * ap_hdl); + +#endif /* H264EPRC_H */ diff --git a/src/gallium/frontends/omx/tizonia/names.h b/src/gallium/frontends/omx/tizonia/names.h new file mode 100644 index 00000000000..edde7df396a --- /dev/null +++ b/src/gallium/frontends/omx/tizonia/names.h @@ -0,0 +1,30 @@ +/************************************************************************** + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef OMX_TIZ_NAMES_H +#define OMX_TIZ_NAMES_H + +#define OMX_VID_COMP_NAME "OMX.mesa.video.all" + +#endif diff --git a/src/gallium/frontends/omx/vid_dec_common.c b/src/gallium/frontends/omx/vid_dec_common.c new file mode 100644 index 00000000000..5ca544f8386 --- /dev/null +++ b/src/gallium/frontends/omx/vid_dec_common.c @@ -0,0 +1,156 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#if ENABLE_ST_OMX_TIZONIA +#include +#endif + +#include "util/u_memory.h" +#include "vl/vl_winsys.h" +#include "vl/vl_video_buffer.h" +#include "util/u_surface.h" + +#include "vid_dec_common.h" +#include "vid_dec_h264_common.h" + +void vid_dec_NeedTarget(vid_dec_PrivateType *priv) +{ + struct pipe_video_buffer templat = {}; + struct vl_screen *omx_screen; + struct pipe_screen *pscreen; + + omx_screen = priv->screen; + assert(omx_screen); + + pscreen = omx_screen->pscreen; + assert(pscreen); + + if (!priv->target) { + memset(&templat, 0, sizeof(templat)); + + templat.width = priv->codec->width; + templat.height = priv->codec->height; + templat.buffer_format = pscreen->get_video_param( + pscreen, + PIPE_VIDEO_PROFILE_UNKNOWN, + PIPE_VIDEO_ENTRYPOINT_BITSTREAM, + PIPE_VIDEO_CAP_PREFERED_FORMAT + ); + templat.interlaced = pscreen->get_video_param( + pscreen, + PIPE_VIDEO_PROFILE_UNKNOWN, + PIPE_VIDEO_ENTRYPOINT_BITSTREAM, + PIPE_VIDEO_CAP_PREFERS_INTERLACED + ); + + priv->target = priv->pipe->create_video_buffer(priv->pipe, &templat); + } +} + +void vid_dec_FillOutput(vid_dec_PrivateType *priv, struct pipe_video_buffer *buf, + OMX_BUFFERHEADERTYPE* output) +{ +#if ENABLE_ST_OMX_TIZONIA + tiz_port_t *out_port = tiz_krn_get_port(tiz_get_krn(handleOf(priv)), + OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX); + OMX_VIDEO_PORTDEFINITIONTYPE *def = &out_port->portdef_.format.video; +#else + omx_base_PortType *port = priv->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]; + OMX_VIDEO_PORTDEFINITIONTYPE *def = &port->sPortParam.format.video; +#endif + + struct pipe_sampler_view **views; + unsigned i, j; + unsigned width, height; + + views = buf->get_sampler_view_planes(buf); + +#if ENABLE_ST_OMX_TIZONIA + if (!output->pBuffer) { + struct pipe_video_buffer *dst_buf = NULL; + struct pipe_surface **dst_surface = NULL; + struct u_rect src_rect; + struct u_rect dst_rect; + struct vl_compositor *compositor = &priv->compositor; + struct vl_compositor_state *s = &priv->cstate; + enum vl_compositor_deinterlace deinterlace = VL_COMPOSITOR_WEAVE; + + dst_buf = util_hash_table_get(priv->video_buffer_map, output); + assert(dst_buf); + + dst_surface = dst_buf->get_surfaces(dst_buf); + assert(views); + + src_rect.x0 = 0; + src_rect.y0 = 0; + src_rect.x1 = def->nFrameWidth; + src_rect.y1 = def->nFrameHeight; + + dst_rect.x0 = 0; + dst_rect.y0 = 0; + dst_rect.x1 = def->nFrameWidth; + dst_rect.y1 = def->nFrameHeight; + + vl_compositor_clear_layers(s); + vl_compositor_set_buffer_layer(s, compositor, 0, buf, + &src_rect, NULL, deinterlace); + vl_compositor_set_layer_dst_area(s, 0, &dst_rect); + vl_compositor_render(s, compositor, dst_surface[0], NULL, false); + + priv->pipe->flush(priv->pipe, NULL, 0); + + return; + } +#endif + + for (i = 0; i < 2 /* NV12 */; i++) { + if (!views[i]) continue; + width = def->nFrameWidth; + height = def->nFrameHeight; + vl_video_buffer_adjust_size(&width, &height, i, + pipe_format_to_chroma_format(buf->buffer_format), + buf->interlaced); + for (j = 0; j < views[i]->texture->array_size; ++j) { + struct pipe_box box = {0, 0, j, width, height, 1}; + struct pipe_transfer *transfer; + uint8_t *map, *dst; + map = priv->pipe->transfer_map(priv->pipe, views[i]->texture, 0, + PIPE_TRANSFER_READ, &box, &transfer); + if (!map) + return; + + dst = ((uint8_t*)output->pBuffer + output->nOffset) + j * def->nStride + + i * def->nFrameWidth * def->nFrameHeight; + util_copy_rect(dst, + views[i]->texture->format, + def->nStride * views[i]->texture->array_size, 0, 0, + box.width, box.height, map, transfer->stride, 0, 0); + + pipe_transfer_unmap(priv->pipe, transfer); + } + } +} diff --git a/src/gallium/frontends/omx/vid_dec_common.h b/src/gallium/frontends/omx/vid_dec_common.h new file mode 100644 index 00000000000..26091e3e6f9 --- /dev/null +++ b/src/gallium/frontends/omx/vid_dec_common.h @@ -0,0 +1,197 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef VID_DEC_COMMON_H +#define VID_DEC_COMMON_H + +#include "util/list.h" + +#include "vl/vl_compositor.h" +#include "vl/vl_rbsp.h" +#include "vl/vl_zscan.h" + +#include +#include + +#if ENABLE_ST_OMX_BELLAGIO + +#include +#include +#include + +DERIVEDCLASS(vid_dec_PrivateType, omx_base_filter_PrivateType) +#define vid_dec_PrivateType_FIELDS omx_base_filter_PrivateType_FIELDS \ + enum pipe_video_profile profile; \ + struct vl_screen *screen; \ + struct pipe_context *pipe; \ + struct pipe_video_codec *codec; \ + void (*Decode)(vid_dec_PrivateType *priv, struct vl_vlc *vlc, unsigned min_bits_left); \ + void (*EndFrame)(vid_dec_PrivateType *priv); \ + struct pipe_video_buffer *(*Flush)(vid_dec_PrivateType *priv, OMX_TICKS *timestamp); \ + struct pipe_video_buffer *target, *shadow; \ + union { \ + struct { \ + uint8_t intra_matrix[64]; \ + uint8_t non_intra_matrix[64]; \ + } mpeg12; \ + struct { \ + unsigned nal_ref_idc; \ + bool IdrPicFlag; \ + unsigned idr_pic_id; \ + unsigned pic_order_cnt_lsb; \ + unsigned pic_order_cnt_msb; \ + unsigned delta_pic_order_cnt_bottom; \ + unsigned delta_pic_order_cnt[2]; \ + unsigned prevFrameNumOffset; \ + struct pipe_h264_sps sps[32]; \ + struct pipe_h264_pps pps[256]; \ + struct list_head dpb_list; \ + unsigned dpb_num; \ + } h264; \ + struct { \ + unsigned temporal_id; \ + unsigned level_idc; \ + unsigned pic_width_in_luma_samples; \ + unsigned pic_height_in_luma_samples; \ + bool IdrPicFlag; \ + int slice_prev_poc; \ + void *ref_pic_set_list; \ + void *rps; \ + struct pipe_h265_sps sps[16]; \ + struct pipe_h265_pps pps[64]; \ + struct list_head dpb_list; \ + unsigned dpb_num; \ + } h265; \ + } codec_data; \ + union { \ + struct pipe_picture_desc base; \ + struct pipe_mpeg12_picture_desc mpeg12; \ + struct pipe_h264_picture_desc h264; \ + struct pipe_h265_picture_desc h265; \ + } picture; \ + unsigned num_in_buffers; \ + OMX_BUFFERHEADERTYPE *in_buffers[2]; \ + const void *inputs[2]; \ + unsigned sizes[2]; \ + OMX_TICKS timestamps[2]; \ + OMX_TICKS timestamp; \ + bool first_buf_in_frame; \ + bool frame_finished; \ + bool frame_started; \ + unsigned bytes_left; \ + const void *slice; \ + bool disable_tunnel; \ + struct vl_compositor compositor; \ + struct vl_compositor_state cstate; +ENDCLASS(vid_dec_PrivateType) + +#else + +#include +#include + +#include "util/list.h" +#include "util/u_hash_table.h" + +#include "pipe/p_video_state.h" + +typedef struct h264d_prc_class h264d_prc_class_t; +struct h264d_prc_class +{ + /* Class */ + const tiz_prc_class_t _; + /* NOTE: Class methods might be added in the future */ +}; + +typedef struct h264d_stream_info h264d_stream_info_t; +struct h264d_stream_info +{ + unsigned int width; + unsigned int height; +}; + +typedef struct h264d_prc vid_dec_PrivateType; +struct h264d_prc +{ + /* Object */ + const tiz_prc_t _; + OMX_BUFFERHEADERTYPE *in_buffers[2]; + OMX_BUFFERHEADERTYPE *p_inhdr_; + OMX_BUFFERHEADERTYPE *p_outhdr_; + OMX_PARAM_PORTDEFINITIONTYPE out_port_def_; + const void *inputs[2]; + unsigned sizes[2]; + OMX_TICKS timestamps[2]; + OMX_TICKS timestamp; + bool eos_; + bool in_port_disabled_; + bool out_port_disabled_; + struct vl_screen *screen; + struct pipe_context *pipe; + struct pipe_video_codec *codec; + struct pipe_video_buffer *target; + enum pipe_video_profile profile; + struct hash_table *video_buffer_map; + union { + struct { + unsigned nal_ref_idc; + bool IdrPicFlag; + unsigned idr_pic_id; + unsigned pic_order_cnt_lsb; + unsigned pic_order_cnt_msb; + unsigned delta_pic_order_cnt_bottom; + unsigned delta_pic_order_cnt[2]; + unsigned prevFrameNumOffset; + struct pipe_h264_sps sps[32]; + struct pipe_h264_pps pps[256]; + struct list_head dpb_list; + unsigned dpb_num; + } h264; + } codec_data; + union { + struct pipe_picture_desc base; + struct pipe_h264_picture_desc h264; + } picture; + h264d_stream_info_t stream_info; + unsigned num_in_buffers; + bool first_buf_in_frame; + bool frame_finished; + bool frame_started; + unsigned bytes_left; + const void *slice; + bool disable_tunnel; + struct vl_compositor compositor; + struct vl_compositor_state cstate; + bool use_eglimage; +}; + +#endif + +void vid_dec_NeedTarget(vid_dec_PrivateType* priv); +void vid_dec_FillOutput(vid_dec_PrivateType* priv, struct pipe_video_buffer* buf, + OMX_BUFFERHEADERTYPE* output); +#endif diff --git a/src/gallium/frontends/omx/vid_dec_h264_common.c b/src/gallium/frontends/omx/vid_dec_h264_common.c new file mode 100644 index 00000000000..4074099cdd3 --- /dev/null +++ b/src/gallium/frontends/omx/vid_dec_h264_common.c @@ -0,0 +1,1137 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#if ENABLE_ST_OMX_TIZONIA +#include +#endif + +#include "util/u_memory.h" + +#include "vid_dec_h264_common.h" + +static void vid_dec_h264_BeginFrame(vid_dec_PrivateType *priv) +{ + //TODO: sane buffer handling + + if (priv->frame_started) + return; + + if (!priv->codec) { + struct pipe_video_codec templat = {}; + templat.profile = priv->profile; + templat.entrypoint = PIPE_VIDEO_ENTRYPOINT_BITSTREAM; + templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; + templat.max_references = priv->picture.h264.num_ref_frames; + templat.expect_chunked_decode = true; +#if ENABLE_ST_OMX_BELLAGIO + omx_base_video_PortType *port; + port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; + templat.width = port->sPortParam.format.video.nFrameWidth; + templat.height = port->sPortParam.format.video.nFrameHeight; +#else + templat.width = priv->out_port_def_.format.video.nFrameWidth; + templat.height = priv->out_port_def_.format.video.nFrameHeight; +#endif + templat.level = priv->picture.h264.pps->sps->level_idc; + + priv->codec = priv->pipe->create_video_codec(priv->pipe, &templat); + } + + vid_dec_NeedTarget(priv); + + if (priv->first_buf_in_frame) + priv->timestamp = priv->timestamps[0]; + priv->first_buf_in_frame = false; + + priv->picture.h264.num_ref_frames = priv->picture.h264.pps->sps->max_num_ref_frames; + + priv->picture.h264.slice_count = 0; + priv->codec->begin_frame(priv->codec, priv->target, &priv->picture.base); + priv->frame_started = true; +} + +struct pipe_video_buffer *vid_dec_h264_Flush(vid_dec_PrivateType *priv, + OMX_TICKS *timestamp) +{ + struct dpb_list *entry, *result = NULL; + struct pipe_video_buffer *buf; + + /* search for the lowest poc and break on zeros */ + LIST_FOR_EACH_ENTRY(entry, &priv->codec_data.h264.dpb_list, list) { + + if (result && entry->poc == 0) + break; + + if (!result || entry->poc < result->poc) + result = entry; + } + + if (!result) + return NULL; + + buf = result->buffer; + if (timestamp) + *timestamp = result->timestamp; + + --priv->codec_data.h264.dpb_num; + list_del(&result->list); + FREE(result); + + return buf; +} + +void vid_dec_h264_EndFrame(vid_dec_PrivateType *priv) +{ + struct dpb_list *entry; + struct pipe_video_buffer *tmp; + bool top_field_first; + OMX_TICKS timestamp = 0; + + if (!priv->frame_started) + return; + + priv->codec->end_frame(priv->codec, priv->target, &priv->picture.base); + priv->frame_started = false; + + // TODO: implement frame number handling + priv->picture.h264.frame_num_list[0] = priv->picture.h264.frame_num; + priv->picture.h264.field_order_cnt_list[0][0] = priv->picture.h264.frame_num; + priv->picture.h264.field_order_cnt_list[0][1] = priv->picture.h264.frame_num; + + top_field_first = priv->picture.h264.field_order_cnt[0] < priv->picture.h264.field_order_cnt[1]; + + if (priv->picture.h264.field_pic_flag && priv->picture.h264.bottom_field_flag != top_field_first) + return; + + /* add the decoded picture to the dpb list */ + entry = CALLOC_STRUCT(dpb_list); + if (!entry) + return; + + priv->first_buf_in_frame = true; + entry->buffer = priv->target; + entry->timestamp = priv->timestamp; + entry->poc = MIN2(priv->picture.h264.field_order_cnt[0], priv->picture.h264.field_order_cnt[1]); + list_addtail(&entry->list, &priv->codec_data.h264.dpb_list); + ++priv->codec_data.h264.dpb_num; + priv->target = NULL; + priv->picture.h264.field_order_cnt[0] = priv->picture.h264.field_order_cnt[1] = INT_MAX; + + if (priv->codec_data.h264.dpb_num <= DPB_MAX_SIZE) + return; + + tmp = priv->in_buffers[0]->pInputPortPrivate; + priv->in_buffers[0]->pInputPortPrivate = vid_dec_h264_Flush(priv, ×tamp); + priv->in_buffers[0]->nTimeStamp = timestamp; + priv->target = tmp; + priv->frame_finished = priv->in_buffers[0]->pInputPortPrivate != NULL; +} + +static void vui_parameters(struct vl_rbsp *rbsp) +{ + // TODO +} + +static void scaling_list(struct vl_rbsp *rbsp, uint8_t *scalingList, unsigned sizeOfScalingList, + const uint8_t *defaultList, const uint8_t *fallbackList) +{ + unsigned lastScale = 8, nextScale = 8; + const int *list; + unsigned i; + + /* (pic|seq)_scaling_list_present_flag[i] */ + if (!vl_rbsp_u(rbsp, 1)) { + if (fallbackList) + memcpy(scalingList, fallbackList, sizeOfScalingList); + return; + } + + list = (sizeOfScalingList == 16) ? vl_zscan_normal_16 : vl_zscan_normal; + for (i = 0; i < sizeOfScalingList; ++i ) { + + if (nextScale != 0) { + signed delta_scale = vl_rbsp_se(rbsp); + nextScale = (lastScale + delta_scale + 256) % 256; + if (i == 0 && nextScale == 0) { + memcpy(scalingList, defaultList, sizeOfScalingList); + return; + } + } + scalingList[list[i]] = nextScale == 0 ? lastScale : nextScale; + lastScale = scalingList[list[i]]; + } +} + +static struct pipe_h264_sps *seq_parameter_set_id(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp) +{ + unsigned id = vl_rbsp_ue(rbsp); + if (id >= ARRAY_SIZE(priv->codec_data.h264.sps)) + return NULL; /* invalid seq_parameter_set_id */ + + return &priv->codec_data.h264.sps[id]; +} + +static void seq_parameter_set(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp) +{ + struct pipe_h264_sps *sps; + unsigned profile_idc, level_idc; + unsigned i; + + /* Sequence parameter set */ + profile_idc = vl_rbsp_u(rbsp, 8); + + /* constraint_set0_flag */ + vl_rbsp_u(rbsp, 1); + + /* constraint_set1_flag */ + vl_rbsp_u(rbsp, 1); + + /* constraint_set2_flag */ + vl_rbsp_u(rbsp, 1); + + /* constraint_set3_flag */ + vl_rbsp_u(rbsp, 1); + + /* constraint_set4_flag */ + vl_rbsp_u(rbsp, 1); + + /* constraint_set5_flag */ + vl_rbsp_u(rbsp, 1); + + /* reserved_zero_2bits */ + vl_rbsp_u(rbsp, 2); + + /* level_idc */ + level_idc = vl_rbsp_u(rbsp, 8); + + sps = seq_parameter_set_id(priv, rbsp); + if (!sps) + return; + + memset(sps, 0, sizeof(*sps)); + memset(sps->ScalingList4x4, 16, sizeof(sps->ScalingList4x4)); + memset(sps->ScalingList8x8, 16, sizeof(sps->ScalingList8x8)); + + sps->level_idc = level_idc; + + if (profile_idc == 100 || profile_idc == 110 || profile_idc == 122 || profile_idc == 244 || + profile_idc == 44 || profile_idc == 83 || profile_idc == 86 || profile_idc == 118 || + profile_idc == 128 || profile_idc == 138) { + + sps->chroma_format_idc = vl_rbsp_ue(rbsp); + + if (sps->chroma_format_idc == 3) + sps->separate_colour_plane_flag = vl_rbsp_u(rbsp, 1); + + sps->bit_depth_luma_minus8 = vl_rbsp_ue(rbsp); + + sps->bit_depth_chroma_minus8 = vl_rbsp_ue(rbsp); + + /* qpprime_y_zero_transform_bypass_flag */ + vl_rbsp_u(rbsp, 1); + + sps->seq_scaling_matrix_present_flag = vl_rbsp_u(rbsp, 1); + if (sps->seq_scaling_matrix_present_flag) { + + scaling_list(rbsp, sps->ScalingList4x4[0], 16, Default_4x4_Intra, Default_4x4_Intra); + scaling_list(rbsp, sps->ScalingList4x4[1], 16, Default_4x4_Intra, sps->ScalingList4x4[0]); + scaling_list(rbsp, sps->ScalingList4x4[2], 16, Default_4x4_Intra, sps->ScalingList4x4[1]); + scaling_list(rbsp, sps->ScalingList4x4[3], 16, Default_4x4_Inter, Default_4x4_Inter); + scaling_list(rbsp, sps->ScalingList4x4[4], 16, Default_4x4_Inter, sps->ScalingList4x4[3]); + scaling_list(rbsp, sps->ScalingList4x4[5], 16, Default_4x4_Inter, sps->ScalingList4x4[4]); + + scaling_list(rbsp, sps->ScalingList8x8[0], 64, Default_8x8_Intra, Default_8x8_Intra); + scaling_list(rbsp, sps->ScalingList8x8[1], 64, Default_8x8_Inter, Default_8x8_Inter); + if (sps->chroma_format_idc == 3) { + scaling_list(rbsp, sps->ScalingList8x8[2], 64, Default_8x8_Intra, sps->ScalingList8x8[0]); + scaling_list(rbsp, sps->ScalingList8x8[3], 64, Default_8x8_Inter, sps->ScalingList8x8[1]); + scaling_list(rbsp, sps->ScalingList8x8[4], 64, Default_8x8_Intra, sps->ScalingList8x8[2]); + scaling_list(rbsp, sps->ScalingList8x8[5], 64, Default_8x8_Inter, sps->ScalingList8x8[3]); + } + } + } else if (profile_idc == 183) + sps->chroma_format_idc = 0; + else + sps->chroma_format_idc = 1; + + sps->log2_max_frame_num_minus4 = vl_rbsp_ue(rbsp); + + sps->pic_order_cnt_type = vl_rbsp_ue(rbsp); + + if (sps->pic_order_cnt_type == 0) + sps->log2_max_pic_order_cnt_lsb_minus4 = vl_rbsp_ue(rbsp); + else if (sps->pic_order_cnt_type == 1) { + sps->delta_pic_order_always_zero_flag = vl_rbsp_u(rbsp, 1); + + sps->offset_for_non_ref_pic = vl_rbsp_se(rbsp); + + sps->offset_for_top_to_bottom_field = vl_rbsp_se(rbsp); + + sps->num_ref_frames_in_pic_order_cnt_cycle = vl_rbsp_ue(rbsp); + + for (i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; ++i) + sps->offset_for_ref_frame[i] = vl_rbsp_se(rbsp); + } + + sps->max_num_ref_frames = vl_rbsp_ue(rbsp); + + /* gaps_in_frame_num_value_allowed_flag */ + vl_rbsp_u(rbsp, 1); + + /* pic_width_in_mbs_minus1 */ + ASSERTED int pic_width_in_samplesl = (vl_rbsp_ue(rbsp) + 1) * 16; + assert(pic_width_in_samplesl); + + /* pic_height_in_map_units_minus1 */ + ASSERTED int pic_height_in_map_units = vl_rbsp_ue(rbsp) + 1; + assert(pic_height_in_map_units); + + sps->frame_mbs_only_flag = vl_rbsp_u(rbsp, 1); + if (!sps->frame_mbs_only_flag) + sps->mb_adaptive_frame_field_flag = vl_rbsp_u(rbsp, 1); + + sps->direct_8x8_inference_flag = vl_rbsp_u(rbsp, 1); + +#if ENABLE_ST_OMX_TIZONIA + priv->stream_info.width = pic_width_in_samplesl; + + int frame_height_in_mbs = (2 - sps->frame_mbs_only_flag) * pic_height_in_map_units; + int pic_height_in_mbs = frame_height_in_mbs / ( 1 + priv->picture.h264.field_pic_flag ); + int pic_height_in_samplesl = pic_height_in_mbs * 16; + priv->stream_info.height = pic_height_in_samplesl; + + + /* frame_cropping_flag */ + if (vl_rbsp_u(rbsp, 1)) { + unsigned frame_crop_left_offset = vl_rbsp_ue(rbsp); + unsigned frame_crop_right_offset = vl_rbsp_ue(rbsp); + unsigned frame_crop_top_offset = vl_rbsp_ue(rbsp); + unsigned frame_crop_bottom_offset = vl_rbsp_ue(rbsp); + + priv->stream_info.width -= (frame_crop_left_offset + frame_crop_right_offset) * 2; + priv->stream_info.height -= (frame_crop_top_offset + frame_crop_bottom_offset) * 2; + } +#else + /* frame_cropping_flag */ + if (vl_rbsp_u(rbsp, 1)) { + /* frame_crop_left_offset */ + vl_rbsp_ue(rbsp); + + /* frame_crop_right_offset */ + vl_rbsp_ue(rbsp); + + /* frame_crop_top_offset */ + vl_rbsp_ue(rbsp); + + /* frame_crop_bottom_offset */ + vl_rbsp_ue(rbsp); + } +#endif + + /* vui_parameters_present_flag */ + if (vl_rbsp_u(rbsp, 1)) + vui_parameters(rbsp); +} + +static struct pipe_h264_pps *pic_parameter_set_id(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp) +{ + unsigned id = vl_rbsp_ue(rbsp); + if (id >= ARRAY_SIZE(priv->codec_data.h264.pps)) + return NULL; /* invalid pic_parameter_set_id */ + + return &priv->codec_data.h264.pps[id]; +} + +static void picture_parameter_set(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp) +{ + struct pipe_h264_sps *sps; + struct pipe_h264_pps *pps; + unsigned i; + + pps = pic_parameter_set_id(priv, rbsp); + if (!pps) + return; + + memset(pps, 0, sizeof(*pps)); + + sps = pps->sps = seq_parameter_set_id(priv, rbsp); + if (!sps) + return; + + memcpy(pps->ScalingList4x4, sps->ScalingList4x4, sizeof(pps->ScalingList4x4)); + memcpy(pps->ScalingList8x8, sps->ScalingList8x8, sizeof(pps->ScalingList8x8)); + + pps->entropy_coding_mode_flag = vl_rbsp_u(rbsp, 1); + + pps->bottom_field_pic_order_in_frame_present_flag = vl_rbsp_u(rbsp, 1); + + pps->num_slice_groups_minus1 = vl_rbsp_ue(rbsp); + if (pps->num_slice_groups_minus1 > 0) { + pps->slice_group_map_type = vl_rbsp_ue(rbsp); + + if (pps->slice_group_map_type == 0) { + + for (i = 0; i <= pps->num_slice_groups_minus1; ++i) + /* run_length_minus1[i] */ + vl_rbsp_ue(rbsp); + + } else if (pps->slice_group_map_type == 2) { + + for (i = 0; i <= pps->num_slice_groups_minus1; ++i) { + /* top_left[i] */ + vl_rbsp_ue(rbsp); + + /* bottom_right[i] */ + vl_rbsp_ue(rbsp); + } + + } else if (pps->slice_group_map_type >= 3 && pps->slice_group_map_type <= 5) { + + /* slice_group_change_direction_flag */ + vl_rbsp_u(rbsp, 1); + + pps->slice_group_change_rate_minus1 = vl_rbsp_ue(rbsp); + + } else if (pps->slice_group_map_type == 6) { + + unsigned pic_size_in_map_units_minus1; + + pic_size_in_map_units_minus1 = vl_rbsp_ue(rbsp); + + for (i = 0; i <= pic_size_in_map_units_minus1; ++i) + /* slice_group_id[i] */ + vl_rbsp_u(rbsp, log2(pps->num_slice_groups_minus1 + 1)); + } + } + + pps->num_ref_idx_l0_default_active_minus1 = vl_rbsp_ue(rbsp); + + pps->num_ref_idx_l1_default_active_minus1 = vl_rbsp_ue(rbsp); + + pps->weighted_pred_flag = vl_rbsp_u(rbsp, 1); + + pps->weighted_bipred_idc = vl_rbsp_u(rbsp, 2); + + pps->pic_init_qp_minus26 = vl_rbsp_se(rbsp); + + /* pic_init_qs_minus26 */ + vl_rbsp_se(rbsp); + + pps->chroma_qp_index_offset = vl_rbsp_se(rbsp); + + pps->deblocking_filter_control_present_flag = vl_rbsp_u(rbsp, 1); + + pps->constrained_intra_pred_flag = vl_rbsp_u(rbsp, 1); + + pps->redundant_pic_cnt_present_flag = vl_rbsp_u(rbsp, 1); + + if (vl_rbsp_more_data(rbsp)) { + pps->transform_8x8_mode_flag = vl_rbsp_u(rbsp, 1); + + /* pic_scaling_matrix_present_flag */ + if (vl_rbsp_u(rbsp, 1)) { + + scaling_list(rbsp, pps->ScalingList4x4[0], 16, Default_4x4_Intra, + sps->seq_scaling_matrix_present_flag ? NULL : Default_4x4_Intra); + scaling_list(rbsp, pps->ScalingList4x4[1], 16, Default_4x4_Intra, pps->ScalingList4x4[0]); + scaling_list(rbsp, pps->ScalingList4x4[2], 16, Default_4x4_Intra, pps->ScalingList4x4[1]); + scaling_list(rbsp, pps->ScalingList4x4[3], 16, Default_4x4_Inter, + sps->seq_scaling_matrix_present_flag ? NULL : Default_4x4_Inter); + scaling_list(rbsp, pps->ScalingList4x4[4], 16, Default_4x4_Inter, pps->ScalingList4x4[3]); + scaling_list(rbsp, pps->ScalingList4x4[5], 16, Default_4x4_Inter, pps->ScalingList4x4[4]); + + if (pps->transform_8x8_mode_flag) { + scaling_list(rbsp, pps->ScalingList8x8[0], 64, Default_8x8_Intra, + sps->seq_scaling_matrix_present_flag ? NULL : Default_8x8_Intra); + scaling_list(rbsp, pps->ScalingList8x8[1], 64, Default_8x8_Inter, + sps->seq_scaling_matrix_present_flag ? NULL : Default_8x8_Inter); + if (sps->chroma_format_idc == 3) { + scaling_list(rbsp, pps->ScalingList8x8[2], 64, Default_8x8_Intra, pps->ScalingList8x8[0]); + scaling_list(rbsp, pps->ScalingList8x8[3], 64, Default_8x8_Inter, pps->ScalingList8x8[1]); + scaling_list(rbsp, pps->ScalingList8x8[4], 64, Default_8x8_Intra, pps->ScalingList8x8[2]); + scaling_list(rbsp, pps->ScalingList8x8[5], 64, Default_8x8_Inter, pps->ScalingList8x8[3]); + } + } + } + + pps->second_chroma_qp_index_offset = vl_rbsp_se(rbsp); + } +} + +static void ref_pic_list_mvc_modification(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp) +{ + // TODO + assert(0); +} + +static void ref_pic_list_modification(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp, + enum pipe_h264_slice_type slice_type) +{ + unsigned modification_of_pic_nums_idc; + + if (slice_type != 2 && slice_type != 4) { + /* ref_pic_list_modification_flag_l0 */ + if (vl_rbsp_u(rbsp, 1)) { + do { + modification_of_pic_nums_idc = vl_rbsp_ue(rbsp); + if (modification_of_pic_nums_idc == 0 || + modification_of_pic_nums_idc == 1) + /* abs_diff_pic_num_minus1 */ + vl_rbsp_ue(rbsp); + else if (modification_of_pic_nums_idc == 2) + /* long_term_pic_num */ + vl_rbsp_ue(rbsp); + } while (modification_of_pic_nums_idc != 3); + } + } + + if (slice_type == 1) { + /* ref_pic_list_modification_flag_l1 */ + if (vl_rbsp_u(rbsp, 1)) { + do { + modification_of_pic_nums_idc = vl_rbsp_ue(rbsp); + if (modification_of_pic_nums_idc == 0 || + modification_of_pic_nums_idc == 1) + /* abs_diff_pic_num_minus1 */ + vl_rbsp_ue(rbsp); + else if (modification_of_pic_nums_idc == 2) + /* long_term_pic_num */ + vl_rbsp_ue(rbsp); + } while (modification_of_pic_nums_idc != 3); + } + } +} + +static void pred_weight_table(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp, + struct pipe_h264_sps *sps, enum pipe_h264_slice_type slice_type) +{ + unsigned ChromaArrayType = sps->separate_colour_plane_flag ? 0 : sps->chroma_format_idc; + unsigned i, j; + + /* luma_log2_weight_denom */ + vl_rbsp_ue(rbsp); + + if (ChromaArrayType != 0) + /* chroma_log2_weight_denom */ + vl_rbsp_ue(rbsp); + + for (i = 0; i <= priv->picture.h264.num_ref_idx_l0_active_minus1; ++i) { + /* luma_weight_l0_flag */ + if (vl_rbsp_u(rbsp, 1)) { + /* luma_weight_l0[i] */ + vl_rbsp_se(rbsp); + /* luma_offset_l0[i] */ + vl_rbsp_se(rbsp); + } + if (ChromaArrayType != 0) { + /* chroma_weight_l0_flag */ + if (vl_rbsp_u(rbsp, 1)) { + for (j = 0; j < 2; ++j) { + /* chroma_weight_l0[i][j] */ + vl_rbsp_se(rbsp); + /* chroma_offset_l0[i][j] */ + vl_rbsp_se(rbsp); + } + } + } + } + + if (slice_type == 1) { + for (i = 0; i <= priv->picture.h264.num_ref_idx_l1_active_minus1; ++i) { + /* luma_weight_l1_flag */ + if (vl_rbsp_u(rbsp, 1)) { + /* luma_weight_l1[i] */ + vl_rbsp_se(rbsp); + /* luma_offset_l1[i] */ + vl_rbsp_se(rbsp); + } + if (ChromaArrayType != 0) { + /* chroma_weight_l1_flag */ + if (vl_rbsp_u(rbsp, 1)) { + for (j = 0; j < 2; ++j) { + /* chroma_weight_l1[i][j] */ + vl_rbsp_se(rbsp); + /* chroma_offset_l1[i][j] */ + vl_rbsp_se(rbsp); + } + } + } + } + } +} + +static void dec_ref_pic_marking(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp, + bool IdrPicFlag) +{ + unsigned memory_management_control_operation; + + if (IdrPicFlag) { + /* no_output_of_prior_pics_flag */ + vl_rbsp_u(rbsp, 1); + /* long_term_reference_flag */ + vl_rbsp_u(rbsp, 1); + } else { + /* adaptive_ref_pic_marking_mode_flag */ + if (vl_rbsp_u(rbsp, 1)) { + do { + memory_management_control_operation = vl_rbsp_ue(rbsp); + + if (memory_management_control_operation == 1 || + memory_management_control_operation == 3) + /* difference_of_pic_nums_minus1 */ + vl_rbsp_ue(rbsp); + + if (memory_management_control_operation == 2) + /* long_term_pic_num */ + vl_rbsp_ue(rbsp); + + if (memory_management_control_operation == 3 || + memory_management_control_operation == 6) + /* long_term_frame_idx */ + vl_rbsp_ue(rbsp); + + if (memory_management_control_operation == 4) + /* max_long_term_frame_idx_plus1 */ + vl_rbsp_ue(rbsp); + } while (memory_management_control_operation != 0); + } + } +} + +static void slice_header(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp, + unsigned nal_ref_idc, unsigned nal_unit_type) +{ + enum pipe_h264_slice_type slice_type; + struct pipe_h264_pps *pps; + struct pipe_h264_sps *sps; + unsigned frame_num, prevFrameNum; + bool IdrPicFlag = nal_unit_type == 5; + + if (IdrPicFlag != priv->codec_data.h264.IdrPicFlag) + vid_dec_h264_EndFrame(priv); + + priv->codec_data.h264.IdrPicFlag = IdrPicFlag; + + /* first_mb_in_slice */ + vl_rbsp_ue(rbsp); + + slice_type = vl_rbsp_ue(rbsp) % 5; + + /* get picture parameter set */ + pps = pic_parameter_set_id(priv, rbsp); + if (!pps) + return; + + /* get sequence parameter set */ + sps = pps->sps; + if (!sps) + return; + + if (pps != priv->picture.h264.pps) + vid_dec_h264_EndFrame(priv); + + priv->picture.h264.pps = pps; + + if (sps->separate_colour_plane_flag == 1 ) + /* colour_plane_id */ + vl_rbsp_u(rbsp, 2); + + /* frame number handling */ + frame_num = vl_rbsp_u(rbsp, sps->log2_max_frame_num_minus4 + 4); + + if (frame_num != priv->picture.h264.frame_num) + vid_dec_h264_EndFrame(priv); + + prevFrameNum = priv->picture.h264.frame_num; + priv->picture.h264.frame_num = frame_num; + + priv->picture.h264.field_pic_flag = 0; + priv->picture.h264.bottom_field_flag = 0; + + if (!sps->frame_mbs_only_flag) { + unsigned field_pic_flag = vl_rbsp_u(rbsp, 1); + + if (!field_pic_flag && field_pic_flag != priv->picture.h264.field_pic_flag) + vid_dec_h264_EndFrame(priv); + + priv->picture.h264.field_pic_flag = field_pic_flag; + + if (priv->picture.h264.field_pic_flag) { + unsigned bottom_field_flag = vl_rbsp_u(rbsp, 1); + + if (bottom_field_flag != priv->picture.h264.bottom_field_flag) + vid_dec_h264_EndFrame(priv); + + priv->picture.h264.bottom_field_flag = bottom_field_flag; + } + } + + if (IdrPicFlag) { + /* set idr_pic_id */ + unsigned idr_pic_id = vl_rbsp_ue(rbsp); + + if (idr_pic_id != priv->codec_data.h264.idr_pic_id) + vid_dec_h264_EndFrame(priv); + + priv->codec_data.h264.idr_pic_id = idr_pic_id; + } + + if (sps->pic_order_cnt_type == 0) { + /* pic_order_cnt_lsb */ + unsigned log2_max_pic_order_cnt_lsb = sps->log2_max_pic_order_cnt_lsb_minus4 + 4; + unsigned max_pic_order_cnt_lsb = 1 << log2_max_pic_order_cnt_lsb; + int pic_order_cnt_lsb = vl_rbsp_u(rbsp, log2_max_pic_order_cnt_lsb); + int pic_order_cnt_msb; + + if (pic_order_cnt_lsb != priv->codec_data.h264.pic_order_cnt_lsb) + vid_dec_h264_EndFrame(priv); + + if (IdrPicFlag) { + priv->codec_data.h264.pic_order_cnt_msb = 0; + priv->codec_data.h264.pic_order_cnt_lsb = 0; + } + + if ((pic_order_cnt_lsb < priv->codec_data.h264.pic_order_cnt_lsb) && + (priv->codec_data.h264.pic_order_cnt_lsb - pic_order_cnt_lsb) >= (max_pic_order_cnt_lsb / 2)) + pic_order_cnt_msb = priv->codec_data.h264.pic_order_cnt_msb + max_pic_order_cnt_lsb; + + else if ((pic_order_cnt_lsb > priv->codec_data.h264.pic_order_cnt_lsb) && + (pic_order_cnt_lsb - priv->codec_data.h264.pic_order_cnt_lsb) > (max_pic_order_cnt_lsb / 2)) + pic_order_cnt_msb = priv->codec_data.h264.pic_order_cnt_msb - max_pic_order_cnt_lsb; + + else + pic_order_cnt_msb = priv->codec_data.h264.pic_order_cnt_msb; + + priv->codec_data.h264.pic_order_cnt_msb = pic_order_cnt_msb; + priv->codec_data.h264.pic_order_cnt_lsb = pic_order_cnt_lsb; + + if (pps->bottom_field_pic_order_in_frame_present_flag && !priv->picture.h264.field_pic_flag) { + /* delta_pic_oreder_cnt_bottom */ + unsigned delta_pic_order_cnt_bottom = vl_rbsp_se(rbsp); + + if (delta_pic_order_cnt_bottom != priv->codec_data.h264.delta_pic_order_cnt_bottom) + vid_dec_h264_EndFrame(priv); + + priv->codec_data.h264.delta_pic_order_cnt_bottom = delta_pic_order_cnt_bottom; + } + + if (!priv->picture.h264.field_pic_flag) { + priv->picture.h264.field_order_cnt[0] = pic_order_cnt_msb + pic_order_cnt_lsb; + priv->picture.h264.field_order_cnt[1] = priv->picture.h264.field_order_cnt [0] + + priv->codec_data.h264.delta_pic_order_cnt_bottom; + } else if (!priv->picture.h264.bottom_field_flag) + priv->picture.h264.field_order_cnt[0] = pic_order_cnt_msb + pic_order_cnt_lsb; + else + priv->picture.h264.field_order_cnt[1] = pic_order_cnt_msb + pic_order_cnt_lsb; + + } else if (sps->pic_order_cnt_type == 1) { + /* delta_pic_order_cnt[0] */ + unsigned MaxFrameNum = 1 << (sps->log2_max_frame_num_minus4 + 4); + unsigned FrameNumOffset, absFrameNum, expectedPicOrderCnt; + + if (!sps->delta_pic_order_always_zero_flag) { + unsigned delta_pic_order_cnt[2]; + + delta_pic_order_cnt[0] = vl_rbsp_se(rbsp); + + if (delta_pic_order_cnt[0] != priv->codec_data.h264.delta_pic_order_cnt[0]) + vid_dec_h264_EndFrame(priv); + + priv->codec_data.h264.delta_pic_order_cnt[0] = delta_pic_order_cnt[0]; + + if (pps->bottom_field_pic_order_in_frame_present_flag && !priv->picture.h264.field_pic_flag) { + /* delta_pic_order_cnt[1] */ + delta_pic_order_cnt[1] = vl_rbsp_se(rbsp); + + if (delta_pic_order_cnt[1] != priv->codec_data.h264.delta_pic_order_cnt[1]) + vid_dec_h264_EndFrame(priv); + + priv->codec_data.h264.delta_pic_order_cnt[1] = delta_pic_order_cnt[1]; + } + } + + if (IdrPicFlag) + FrameNumOffset = 0; + else if (prevFrameNum > frame_num) + FrameNumOffset = priv->codec_data.h264.prevFrameNumOffset + MaxFrameNum; + else + FrameNumOffset = priv->codec_data.h264.prevFrameNumOffset; + + priv->codec_data.h264.prevFrameNumOffset = FrameNumOffset; + + if (sps->num_ref_frames_in_pic_order_cnt_cycle != 0) + absFrameNum = FrameNumOffset + frame_num; + else + absFrameNum = 0; + + if (nal_ref_idc == 0 && absFrameNum > 0) + absFrameNum = absFrameNum - 1; + + if (absFrameNum > 0) { + unsigned picOrderCntCycleCnt = (absFrameNum - 1) / sps->num_ref_frames_in_pic_order_cnt_cycle; + unsigned frameNumInPicOrderCntCycle = (absFrameNum - 1) % sps->num_ref_frames_in_pic_order_cnt_cycle; + signed ExpectedDeltaPerPicOrderCntCycle = 0; + unsigned i; + + for (i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; ++i) + ExpectedDeltaPerPicOrderCntCycle += sps->offset_for_ref_frame[i]; + + expectedPicOrderCnt = picOrderCntCycleCnt * ExpectedDeltaPerPicOrderCntCycle; + for (i = 0; i <= frameNumInPicOrderCntCycle; ++i) + expectedPicOrderCnt += sps->offset_for_ref_frame[i]; + + } else + expectedPicOrderCnt = 0; + + if (nal_ref_idc == 0) + expectedPicOrderCnt += sps->offset_for_non_ref_pic; + + if (!priv->picture.h264.field_pic_flag) { + priv->picture.h264.field_order_cnt[0] = expectedPicOrderCnt + priv->codec_data.h264.delta_pic_order_cnt[0]; + priv->picture.h264.field_order_cnt[1] = priv->picture.h264.field_order_cnt[0] + + sps->offset_for_top_to_bottom_field + priv->codec_data.h264.delta_pic_order_cnt[1]; + + } else if (!priv->picture.h264.bottom_field_flag) + priv->picture.h264.field_order_cnt[0] = expectedPicOrderCnt + priv->codec_data.h264.delta_pic_order_cnt[0]; + else + priv->picture.h264.field_order_cnt[1] = expectedPicOrderCnt + sps->offset_for_top_to_bottom_field + + priv->codec_data.h264.delta_pic_order_cnt[0]; + + } else if (sps->pic_order_cnt_type == 2) { + unsigned MaxFrameNum = 1 << (sps->log2_max_frame_num_minus4 + 4); + unsigned FrameNumOffset, tempPicOrderCnt; + + if (IdrPicFlag) + FrameNumOffset = 0; + else if (prevFrameNum > frame_num) + FrameNumOffset = priv->codec_data.h264.prevFrameNumOffset + MaxFrameNum; + else + FrameNumOffset = priv->codec_data.h264.prevFrameNumOffset; + + priv->codec_data.h264.prevFrameNumOffset = FrameNumOffset; + + if (IdrPicFlag) + tempPicOrderCnt = 0; + else if (nal_ref_idc == 0) + tempPicOrderCnt = 2 * (FrameNumOffset + frame_num) - 1; + else + tempPicOrderCnt = 2 * (FrameNumOffset + frame_num); + + if (!priv->picture.h264.field_pic_flag) { + priv->picture.h264.field_order_cnt[0] = tempPicOrderCnt; + priv->picture.h264.field_order_cnt[1] = tempPicOrderCnt; + + } else if (!priv->picture.h264.bottom_field_flag) + priv->picture.h264.field_order_cnt[0] = tempPicOrderCnt; + else + priv->picture.h264.field_order_cnt[1] = tempPicOrderCnt; + } + + if (pps->redundant_pic_cnt_present_flag) + /* redundant_pic_cnt */ + vl_rbsp_ue(rbsp); + + if (slice_type == PIPE_H264_SLICE_TYPE_B) + /* direct_spatial_mv_pred_flag */ + vl_rbsp_u(rbsp, 1); + + priv->picture.h264.num_ref_idx_l0_active_minus1 = pps->num_ref_idx_l0_default_active_minus1; + priv->picture.h264.num_ref_idx_l1_active_minus1 = pps->num_ref_idx_l1_default_active_minus1; + + if (slice_type == PIPE_H264_SLICE_TYPE_P || + slice_type == PIPE_H264_SLICE_TYPE_SP || + slice_type == PIPE_H264_SLICE_TYPE_B) { + + /* num_ref_idx_active_override_flag */ + if (vl_rbsp_u(rbsp, 1)) { + priv->picture.h264.num_ref_idx_l0_active_minus1 = vl_rbsp_ue(rbsp); + + if (slice_type == PIPE_H264_SLICE_TYPE_B) + priv->picture.h264.num_ref_idx_l1_active_minus1 = vl_rbsp_ue(rbsp); + } + } + + if (nal_unit_type == 20 || nal_unit_type == 21) + ref_pic_list_mvc_modification(priv, rbsp); + else + ref_pic_list_modification(priv, rbsp, slice_type); + + if ((pps->weighted_pred_flag && (slice_type == PIPE_H264_SLICE_TYPE_P || slice_type == PIPE_H264_SLICE_TYPE_SP)) || + (pps->weighted_bipred_idc == 1 && slice_type == PIPE_H264_SLICE_TYPE_B)) + pred_weight_table(priv, rbsp, sps, slice_type); + + if (nal_ref_idc != 0) + dec_ref_pic_marking(priv, rbsp, IdrPicFlag); + + if (pps->entropy_coding_mode_flag && slice_type != PIPE_H264_SLICE_TYPE_I && slice_type != PIPE_H264_SLICE_TYPE_SI) + /* cabac_init_idc */ + vl_rbsp_ue(rbsp); + + /* slice_qp_delta */ + vl_rbsp_se(rbsp); + + if (slice_type == PIPE_H264_SLICE_TYPE_SP || slice_type == PIPE_H264_SLICE_TYPE_SI) { + if (slice_type == PIPE_H264_SLICE_TYPE_SP) + /* sp_for_switch_flag */ + vl_rbsp_u(rbsp, 1); + + /*slice_qs_delta */ + vl_rbsp_se(rbsp); + } + + if (pps->deblocking_filter_control_present_flag) { + unsigned disable_deblocking_filter_idc = vl_rbsp_ue(rbsp); + + if (disable_deblocking_filter_idc != 1) { + /* slice_alpha_c0_offset_div2 */ + vl_rbsp_se(rbsp); + + /* slice_beta_offset_div2 */ + vl_rbsp_se(rbsp); + } + } + + if (pps->num_slice_groups_minus1 > 0 && pps->slice_group_map_type >= 3 && pps->slice_group_map_type <= 5) + /* slice_group_change_cycle */ + vl_rbsp_u(rbsp, 2); +} + +#if ENABLE_ST_OMX_TIZONIA +static OMX_ERRORTYPE update_port_parameters(vid_dec_PrivateType* priv) { + OMX_VIDEO_PORTDEFINITIONTYPE * p_def = NULL; /* Output port info */ + h264d_stream_info_t * i_def = NULL; /* Info read from stream */ + OMX_ERRORTYPE err = OMX_ErrorNone; + + assert(priv); + + p_def = &(priv->out_port_def_.format.video); + i_def = &(priv->stream_info); + + /* Handle dynamic resolution change */ + if ((p_def->nFrameWidth == i_def->width) && p_def->nFrameHeight == i_def->height) + return err; + + p_def->nFrameWidth = i_def->width; + p_def->nFrameHeight = i_def->height; + p_def->nStride = i_def->width; + p_def->nSliceHeight = i_def->height; + + err = tiz_krn_SetParameter_internal(tiz_get_krn(handleOf(priv)), handleOf(priv), + OMX_IndexParamPortDefinition, &(priv->out_port_def_)); + if (err == OMX_ErrorNone) { + tiz_port_t * p_obj = tiz_krn_get_port(tiz_get_krn(handleOf(priv)), OMX_VID_DEC_AVC_INPUT_PORT_INDEX); + + /* Set desired buffer size that will be used when allocating input buffers */ + p_obj->portdef_.nBufferSize = p_def->nFrameWidth * p_def->nFrameHeight * 512 / (16*16); + + /* Get a locally copy of port def. Useful for the early return above */ + tiz_check_omx(tiz_api_GetParameter(tiz_get_krn(handleOf(priv)), handleOf(priv), + OMX_IndexParamPortDefinition, &(priv->out_port_def_))); + + tiz_srv_issue_event((OMX_PTR) priv, OMX_EventPortSettingsChanged, + OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX, + OMX_IndexParamPortDefinition, + NULL); + } + + return err; +} +#endif + +void vid_dec_h264_Decode(vid_dec_PrivateType *priv, struct vl_vlc *vlc, unsigned min_bits_left) +{ + unsigned nal_ref_idc, nal_unit_type; + + if (!vl_vlc_search_byte(vlc, vl_vlc_bits_left(vlc) - min_bits_left, 0x00)) + return; + + if (vl_vlc_peekbits(vlc, 24) != 0x000001) { + vl_vlc_eatbits(vlc, 8); + return; + } + + if (priv->slice) { + unsigned bytes = priv->bytes_left - (vl_vlc_bits_left(vlc) / 8); + ++priv->picture.h264.slice_count; + priv->codec->decode_bitstream(priv->codec, priv->target, &priv->picture.base, + 1, &priv->slice, &bytes); + priv->slice = NULL; + } + + vl_vlc_eatbits(vlc, 24); + + /* forbidden_zero_bit */ + vl_vlc_eatbits(vlc, 1); + + nal_ref_idc = vl_vlc_get_uimsbf(vlc, 2); + + if (nal_ref_idc != priv->codec_data.h264.nal_ref_idc && + (nal_ref_idc * priv->codec_data.h264.nal_ref_idc) == 0) + vid_dec_h264_EndFrame(priv); + + priv->codec_data.h264.nal_ref_idc = nal_ref_idc; + + nal_unit_type = vl_vlc_get_uimsbf(vlc, 5); + + if (nal_unit_type != 1 && nal_unit_type != 5) + vid_dec_h264_EndFrame(priv); + + if (nal_unit_type == 7) { + struct vl_rbsp rbsp; + vl_rbsp_init(&rbsp, vlc, ~0); + seq_parameter_set(priv, &rbsp); +#if ENABLE_ST_OMX_TIZONIA + update_port_parameters(priv); +#endif + + } else if (nal_unit_type == 8) { + struct vl_rbsp rbsp; + vl_rbsp_init(&rbsp, vlc, ~0); + picture_parameter_set(priv, &rbsp); + + } else if (nal_unit_type == 1 || nal_unit_type == 5) { + /* Coded slice of a non-IDR or IDR picture */ + unsigned bits = vl_vlc_valid_bits(vlc); + unsigned bytes = bits / 8 + 4; + struct vl_rbsp rbsp; + uint8_t buf[8]; + const void *ptr = buf; + unsigned i; + + buf[0] = 0x0; + buf[1] = 0x0; + buf[2] = 0x1; + buf[3] = (nal_ref_idc << 5) | nal_unit_type; + for (i = 4; i < bytes; ++i) + buf[i] = vl_vlc_peekbits(vlc, bits) >> ((bytes - i - 1) * 8); + + priv->bytes_left = (vl_vlc_bits_left(vlc) - bits) / 8; + priv->slice = vlc->data; + + vl_rbsp_init(&rbsp, vlc, 128); + slice_header(priv, &rbsp, nal_ref_idc, nal_unit_type); + + vid_dec_h264_BeginFrame(priv); + + ++priv->picture.h264.slice_count; + priv->codec->decode_bitstream(priv->codec, priv->target, &priv->picture.base, + 1, &ptr, &bytes); + } + + /* resync to byte boundary */ + vl_vlc_eatbits(vlc, vl_vlc_valid_bits(vlc) % 8); +} + +void vid_dec_FreeInputPortPrivate(OMX_BUFFERHEADERTYPE *buf) +{ + struct pipe_video_buffer *vbuf = buf->pInputPortPrivate; + if (!vbuf) + return; + + vbuf->destroy(vbuf); + buf->pInputPortPrivate = NULL; +} + +void vid_dec_FrameDecoded_common(vid_dec_PrivateType* priv, OMX_BUFFERHEADERTYPE* input, + OMX_BUFFERHEADERTYPE* output) +{ +#if ENABLE_ST_OMX_BELLAGIO + bool eos = !!(input->nFlags & OMX_BUFFERFLAG_EOS); +#else + bool eos = priv->eos_; +#endif + OMX_TICKS timestamp; + + if (!input->pInputPortPrivate) { +#if ENABLE_ST_OMX_BELLAGIO + input->pInputPortPrivate = priv->Flush(priv, ×tamp); +#else + input->pInputPortPrivate = vid_dec_h264_Flush(priv, ×tamp); +#endif + if (timestamp != OMX_VID_DEC_AVC_TIMESTAMP_INVALID) + input->nTimeStamp = timestamp; + } + + if (input->pInputPortPrivate) { + if (output->pInputPortPrivate && !priv->disable_tunnel) { + struct pipe_video_buffer *tmp, *vbuf, *new_vbuf; + + tmp = output->pOutputPortPrivate; + vbuf = input->pInputPortPrivate; + if (vbuf->interlaced) { + /* re-allocate the progressive buffer */ + struct pipe_video_buffer templat = {}; + struct u_rect src_rect, dst_rect; + +#if ENABLE_ST_OMX_BELLAGIO + omx_base_video_PortType *port; + port = (omx_base_video_PortType *) + priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; +#else + tiz_port_t *port; + port = tiz_krn_get_port(tiz_get_krn(handleOf (priv)), OMX_VID_DEC_AVC_INPUT_PORT_INDEX); +#endif + memset(&templat, 0, sizeof(templat)); +#if ENABLE_ST_OMX_BELLAGIO + templat.width = port->sPortParam.format.video.nFrameWidth; + templat.height = port->sPortParam.format.video.nFrameHeight; +#else + templat.width = port->portdef_.format.video.nFrameWidth; + templat.height = port->portdef_.format.video.nFrameHeight; +#endif + templat.buffer_format = PIPE_FORMAT_NV12; + templat.interlaced = false; + new_vbuf = priv->pipe->create_video_buffer(priv->pipe, &templat); + + /* convert the interlaced to the progressive */ + src_rect.x0 = dst_rect.x0 = 0; + src_rect.x1 = dst_rect.x1 = templat.width; + src_rect.y0 = dst_rect.y0 = 0; + src_rect.y1 = dst_rect.y1 = templat.height; + + vl_compositor_yuv_deint_full(&priv->cstate, &priv->compositor, + input->pInputPortPrivate, new_vbuf, + &src_rect, &dst_rect, VL_COMPOSITOR_WEAVE); + + /* set the progrssive buffer for next round */ + vbuf->destroy(vbuf); + input->pInputPortPrivate = new_vbuf; + } + output->pOutputPortPrivate = input->pInputPortPrivate; + input->pInputPortPrivate = tmp; + } else { + vid_dec_FillOutput(priv, input->pInputPortPrivate, output); + } + output->nFilledLen = output->nAllocLen; + output->nTimeStamp = input->nTimeStamp; + } + + if (eos && input->pInputPortPrivate) + vid_dec_FreeInputPortPrivate(input); + else + input->nFilledLen = 0; +} diff --git a/src/gallium/frontends/omx/vid_dec_h264_common.h b/src/gallium/frontends/omx/vid_dec_h264_common.h new file mode 100644 index 00000000000..abde53beef9 --- /dev/null +++ b/src/gallium/frontends/omx/vid_dec_h264_common.h @@ -0,0 +1,99 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef VID_DEC_H264_COMMON_H +#define VID_DEC_H264_COMMON_H + +#include "vid_dec_common.h" + +#define OMX_VID_DEC_AVC_DEFAULT_FRAME_WIDTH 176 +#define OMX_VID_DEC_AVC_DEFAULT_FRAME_HEIGHT 144 +#define OMX_VID_DEC_AVC_DEFAULT_FRAME_RATE 15<<16 +#define OMX_VID_DEC_AVC_ROLE "video_decoder.avc" +/* With libtizonia, port indexes must start at index 0 */ +#define OMX_VID_DEC_AVC_INPUT_PORT_INDEX 0 +#define OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX 1 +#define OMX_VID_DEC_AVC_INPUT_PORT_MIN_BUF_COUNT 8 +#define OMX_VID_DEC_AVC_OUTPUT_PORT_MIN_BUF_COUNT 4 +/* 38016 = (width * height) + ((width * height)/2) */ +#define OMX_VID_DEC_AVC_PORT_MIN_INPUT_BUF_SIZE 38016 +#define OMX_VID_DEC_AVC_PORT_MIN_OUTPUT_BUF_SIZE 345600 +#define OMX_VID_DEC_AVC_PORT_NONCONTIGUOUS OMX_FALSE +#define OMX_VID_DEC_AVC_PORT_ALIGNMENT 0 +#define OMX_VID_DEC_AVC_PORT_SUPPLIERPREF OMX_BufferSupplyInput +#define OMX_VID_DEC_AVC_TIMESTAMP_INVALID ((OMX_TICKS) -1) + +#define DPB_MAX_SIZE 5 + +struct dpb_list { + struct list_head list; + struct pipe_video_buffer *buffer; + OMX_TICKS timestamp; + int poc; +}; + +static const uint8_t Default_4x4_Intra[16] = { + 6, 13, 20, 28, 13, 20, 28, 32, + 20, 28, 32, 37, 28, 32, 37, 42 +}; + +static const uint8_t Default_4x4_Inter[16] = { + 10, 14, 20, 24, 14, 20, 24, 27, + 20, 24, 27, 30, 24, 27, 30, 34 +}; + +static const uint8_t Default_8x8_Intra[64] = { + 6, 10, 13, 16, 18, 23, 25, 27, + 10, 11, 16, 18, 23, 25, 27, 29, + 13, 16, 18, 23, 25, 27, 29, 31, + 16, 18, 23, 25, 27, 29, 31, 33, + 18, 23, 25, 27, 29, 31, 33, 36, + 23, 25, 27, 29, 31, 33, 36, 38, + 25, 27, 29, 31, 33, 36, 38, 40, + 27, 29, 31, 33, 36, 38, 40, 42 +}; + +static const uint8_t Default_8x8_Inter[64] = { + 9, 13, 15, 17, 19, 21, 22, 24, + 13, 13, 17, 19, 21, 22, 24, 25, + 15, 17, 19, 21, 22, 24, 25, 27, + 17, 19, 21, 22, 24, 25, 27, 28, + 19, 21, 22, 24, 25, 27, 28, 30, + 21, 22, 24, 25, 27, 28, 30, 32, + 22, 24, 25, 27, 28, 30, 32, 33, + 24, 25, 27, 28, 30, 32, 33, 35 +}; + +struct pipe_video_buffer *vid_dec_h264_Flush(vid_dec_PrivateType *priv, + OMX_TICKS *timestamp); +void vid_dec_h264_EndFrame(vid_dec_PrivateType *priv); +void vid_dec_h264_Decode(vid_dec_PrivateType *priv, struct vl_vlc *vlc, unsigned min_bits_left); +void vid_dec_FreeInputPortPrivate(OMX_BUFFERHEADERTYPE *buf); +void vid_dec_FrameDecoded_common(vid_dec_PrivateType*priv, OMX_BUFFERHEADERTYPE* input, + OMX_BUFFERHEADERTYPE* output); + +#endif diff --git a/src/gallium/frontends/omx/vid_enc_common.c b/src/gallium/frontends/omx/vid_enc_common.c new file mode 100644 index 00000000000..1cc0c130e5d --- /dev/null +++ b/src/gallium/frontends/omx/vid_enc_common.c @@ -0,0 +1,554 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "vid_enc_common.h" + +#include "vl/vl_video_buffer.h" +#include "tgsi/tgsi_text.h" + +void enc_ReleaseTasks(struct list_head *head) +{ + struct encode_task *i, *next; + + if (!head || !head->next) + return; + + LIST_FOR_EACH_ENTRY_SAFE(i, next, head, list) { + pipe_resource_reference(&i->bitstream, NULL); + i->buf->destroy(i->buf); + FREE(i); + } +} + +void enc_MoveTasks(struct list_head *from, struct list_head *to) +{ + to->prev->next = from->next; + from->next->prev = to->prev; + from->prev->next = to; + to->prev = from->prev; + list_inithead(from); +} + +static void enc_GetPictureParamPreset(struct pipe_h264_enc_picture_desc *picture) +{ + picture->motion_est.enc_disable_sub_mode = 0x000000fe; + picture->motion_est.enc_ime2_search_range_x = 0x00000001; + picture->motion_est.enc_ime2_search_range_y = 0x00000001; + picture->pic_ctrl.enc_constraint_set_flags = 0x00000040; +} + +enum pipe_video_profile enc_TranslateOMXProfileToPipe(unsigned omx_profile) +{ + switch (omx_profile) { + case OMX_VIDEO_AVCProfileBaseline: + return PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE; + case OMX_VIDEO_AVCProfileMain: + return PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN; + case OMX_VIDEO_AVCProfileExtended: + return PIPE_VIDEO_PROFILE_MPEG4_AVC_EXTENDED; + case OMX_VIDEO_AVCProfileHigh: + return PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH; + case OMX_VIDEO_AVCProfileHigh10: + return PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH10; + case OMX_VIDEO_AVCProfileHigh422: + return PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH422; + case OMX_VIDEO_AVCProfileHigh444: + return PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH444; + default: + return PIPE_VIDEO_PROFILE_UNKNOWN; + } +} + +unsigned enc_TranslateOMXLevelToPipe(unsigned omx_level) +{ + switch (omx_level) { + case OMX_VIDEO_AVCLevel1: + case OMX_VIDEO_AVCLevel1b: + return 10; + case OMX_VIDEO_AVCLevel11: + return 11; + case OMX_VIDEO_AVCLevel12: + return 12; + case OMX_VIDEO_AVCLevel13: + return 13; + case OMX_VIDEO_AVCLevel2: + return 20; + case OMX_VIDEO_AVCLevel21: + return 21; + case OMX_VIDEO_AVCLevel22: + return 22; + case OMX_VIDEO_AVCLevel3: + return 30; + case OMX_VIDEO_AVCLevel31: + return 31; + case OMX_VIDEO_AVCLevel32: + return 32; + case OMX_VIDEO_AVCLevel4: + return 40; + case OMX_VIDEO_AVCLevel41: + return 41; + default: + case OMX_VIDEO_AVCLevel42: + return 42; + case OMX_VIDEO_AVCLevel5: + return 50; + case OMX_VIDEO_AVCLevel51: + return 51; + } +} + +void vid_enc_BufferEncoded_common(vid_enc_PrivateType * priv, OMX_BUFFERHEADERTYPE* input, OMX_BUFFERHEADERTYPE* output) +{ + struct output_buf_private *outp = output->pOutputPortPrivate; + struct input_buf_private *inp = input->pInputPortPrivate; + struct encode_task *task; + struct pipe_box box = {}; + unsigned size; + +#if ENABLE_ST_OMX_BELLAGIO + if (!inp || list_is_empty(&inp->tasks)) { + input->nFilledLen = 0; /* mark buffer as empty */ + enc_MoveTasks(&priv->used_tasks, &inp->tasks); + return; + } +#endif + + task = LIST_ENTRY(struct encode_task, inp->tasks.next, list); + list_del(&task->list); + list_addtail(&task->list, &priv->used_tasks); + + if (!task->bitstream) + return; + + /* ------------- map result buffer ----------------- */ + + if (outp->transfer) + pipe_transfer_unmap(priv->t_pipe, outp->transfer); + + pipe_resource_reference(&outp->bitstream, task->bitstream); + pipe_resource_reference(&task->bitstream, NULL); + + box.width = outp->bitstream->width0; + box.height = outp->bitstream->height0; + box.depth = outp->bitstream->depth0; + + output->pBuffer = priv->t_pipe->transfer_map(priv->t_pipe, outp->bitstream, 0, + PIPE_TRANSFER_READ_WRITE, + &box, &outp->transfer); + + /* ------------- get size of result ----------------- */ + + priv->codec->get_feedback(priv->codec, task->feedback, &size); + + output->nOffset = 0; + output->nFilledLen = size; /* mark buffer as full */ + + /* all output buffers contain exactly one frame */ + output->nFlags = OMX_BUFFERFLAG_ENDOFFRAME; + +#if ENABLE_ST_OMX_TIZONIA + input->nFilledLen = 0; /* mark buffer as empty */ + enc_MoveTasks(&priv->used_tasks, &inp->tasks); +#endif +} + + +struct encode_task *enc_NeedTask_common(vid_enc_PrivateType * priv, OMX_VIDEO_PORTDEFINITIONTYPE *def) +{ + struct pipe_video_buffer templat = {}; + struct encode_task *task; + + if (!list_is_empty(&priv->free_tasks)) { + task = LIST_ENTRY(struct encode_task, priv->free_tasks.next, list); + list_del(&task->list); + return task; + } + + /* allocate a new one */ + task = CALLOC_STRUCT(encode_task); + if (!task) + return NULL; + + templat.buffer_format = PIPE_FORMAT_NV12; + templat.width = def->nFrameWidth; + templat.height = def->nFrameHeight; + templat.interlaced = false; + + task->buf = priv->s_pipe->create_video_buffer(priv->s_pipe, &templat); + if (!task->buf) { + FREE(task); + return NULL; + } + + return task; +} + +void enc_ScaleInput_common(vid_enc_PrivateType * priv, OMX_VIDEO_PORTDEFINITIONTYPE *def, + struct pipe_video_buffer **vbuf, unsigned *size) +{ + struct pipe_video_buffer *src_buf = *vbuf; + struct vl_compositor *compositor = &priv->compositor; + struct vl_compositor_state *s = &priv->cstate; + struct pipe_sampler_view **views; + struct pipe_surface **dst_surface; + unsigned i; + + if (!priv->scale_buffer[priv->current_scale_buffer]) + return; + + views = src_buf->get_sampler_view_planes(src_buf); + dst_surface = priv->scale_buffer[priv->current_scale_buffer]->get_surfaces + (priv->scale_buffer[priv->current_scale_buffer]); + vl_compositor_clear_layers(s); + + for (i = 0; i < VL_MAX_SURFACES; ++i) { + struct u_rect src_rect; + if (!views[i] || !dst_surface[i]) + continue; + src_rect.x0 = 0; + src_rect.y0 = 0; + src_rect.x1 = def->nFrameWidth; + src_rect.y1 = def->nFrameHeight; + if (i > 0) { + src_rect.x1 /= 2; + src_rect.y1 /= 2; + } + vl_compositor_set_rgba_layer(s, compositor, 0, views[i], &src_rect, NULL, NULL); + vl_compositor_render(s, compositor, dst_surface[i], NULL, false); + } + *size = priv->scale.xWidth * priv->scale.xHeight * 2; + *vbuf = priv->scale_buffer[priv->current_scale_buffer++]; + priv->current_scale_buffer %= OMX_VID_ENC_NUM_SCALING_BUFFERS; +} + +void enc_ControlPicture_common(vid_enc_PrivateType * priv, struct pipe_h264_enc_picture_desc *picture) +{ + struct pipe_h264_enc_rate_control *rate_ctrl = &picture->rate_ctrl; + + /* Get bitrate from port */ + switch (priv->bitrate.eControlRate) { + case OMX_Video_ControlRateVariable: + rate_ctrl->rate_ctrl_method = PIPE_H264_ENC_RATE_CONTROL_METHOD_VARIABLE; + break; + case OMX_Video_ControlRateConstant: + rate_ctrl->rate_ctrl_method = PIPE_H264_ENC_RATE_CONTROL_METHOD_CONSTANT; + break; + case OMX_Video_ControlRateVariableSkipFrames: + rate_ctrl->rate_ctrl_method = PIPE_H264_ENC_RATE_CONTROL_METHOD_VARIABLE_SKIP; + break; + case OMX_Video_ControlRateConstantSkipFrames: + rate_ctrl->rate_ctrl_method = PIPE_H264_ENC_RATE_CONTROL_METHOD_CONSTANT_SKIP; + break; + default: + rate_ctrl->rate_ctrl_method = PIPE_H264_ENC_RATE_CONTROL_METHOD_DISABLE; + break; + } + + rate_ctrl->frame_rate_den = OMX_VID_ENC_CONTROL_FRAME_RATE_DEN_DEFAULT; + rate_ctrl->frame_rate_num = ((priv->frame_rate) >> 16) * rate_ctrl->frame_rate_den; + + if (rate_ctrl->rate_ctrl_method != PIPE_H264_ENC_RATE_CONTROL_METHOD_DISABLE) { + if (priv->bitrate.nTargetBitrate < OMX_VID_ENC_BITRATE_MIN) + rate_ctrl->target_bitrate = OMX_VID_ENC_BITRATE_MIN; + else if (priv->bitrate.nTargetBitrate < OMX_VID_ENC_BITRATE_MAX) + rate_ctrl->target_bitrate = priv->bitrate.nTargetBitrate; + else + rate_ctrl->target_bitrate = OMX_VID_ENC_BITRATE_MAX; + rate_ctrl->peak_bitrate = rate_ctrl->target_bitrate; + if (rate_ctrl->target_bitrate < OMX_VID_ENC_BITRATE_MEDIAN) + rate_ctrl->vbv_buffer_size = MIN2((rate_ctrl->target_bitrate * 2.75), OMX_VID_ENC_BITRATE_MEDIAN); + else + rate_ctrl->vbv_buffer_size = rate_ctrl->target_bitrate; + + if (rate_ctrl->frame_rate_num) { + unsigned long long t = rate_ctrl->target_bitrate; + t *= rate_ctrl->frame_rate_den; + rate_ctrl->target_bits_picture = t / rate_ctrl->frame_rate_num; + } else { + rate_ctrl->target_bits_picture = rate_ctrl->target_bitrate; + } + rate_ctrl->peak_bits_picture_integer = rate_ctrl->target_bits_picture; + rate_ctrl->peak_bits_picture_fraction = 0; + } + + picture->quant_i_frames = priv->quant.nQpI; + picture->quant_p_frames = priv->quant.nQpP; + picture->quant_b_frames = priv->quant.nQpB; + + picture->frame_num = priv->frame_num; + picture->ref_idx_l0 = priv->ref_idx_l0; + picture->ref_idx_l1 = priv->ref_idx_l1; + picture->enable_vui = (picture->rate_ctrl.frame_rate_num != 0); + enc_GetPictureParamPreset(picture); +} + +static void *create_compute_state(struct pipe_context *pipe, + const char *source) +{ + struct tgsi_token tokens[1024]; + struct pipe_compute_state state = {0}; + + if (!tgsi_text_translate(source, tokens, ARRAY_SIZE(tokens))) { + assert(false); + return NULL; + } + + state.ir_type = PIPE_SHADER_IR_TGSI; + state.prog = tokens; + + return pipe->create_compute_state(pipe, &state); +} + +void enc_InitCompute_common(vid_enc_PrivateType *priv) +{ + struct pipe_context *pipe = priv->s_pipe; + struct pipe_screen *screen = pipe->screen; + + /* We need the partial last block support. */ + if (!screen->get_param(screen, PIPE_CAP_COMPUTE_GRID_INFO_LAST_BLOCK)) + return; + + static const char *copy_y = + "COMP\n" + "PROPERTY CS_FIXED_BLOCK_WIDTH 64\n" + "PROPERTY CS_FIXED_BLOCK_HEIGHT 1\n" + "PROPERTY CS_FIXED_BLOCK_DEPTH 1\n" + "DCL SV[0], THREAD_ID\n" + "DCL SV[1], BLOCK_ID\n" + "DCL IMAGE[0], 2D, PIPE_FORMAT_R8_UINT\n" + "DCL IMAGE[1], 2D, PIPE_FORMAT_R8_UINT, WR\n" + "DCL TEMP[0..1]\n" + "IMM[0] UINT32 {64, 0, 0, 0}\n" + + "UMAD TEMP[0].x, SV[1], IMM[0], SV[0]\n" + "MOV TEMP[0].y, SV[1]\n" + "LOAD TEMP[1].x, IMAGE[0], TEMP[0], 2D, PIPE_FORMAT_R8_UINT\n" + "STORE IMAGE[1].x, TEMP[0], TEMP[1], 2D, PIPE_FORMAT_R8_UINT\n" + "END\n"; + + static const char *copy_uv = + "COMP\n" + "PROPERTY CS_FIXED_BLOCK_WIDTH 64\n" + "PROPERTY CS_FIXED_BLOCK_HEIGHT 1\n" + "PROPERTY CS_FIXED_BLOCK_DEPTH 1\n" + "DCL SV[0], THREAD_ID\n" + "DCL SV[1], BLOCK_ID\n" + "DCL IMAGE[0], 2D, PIPE_FORMAT_R8_UINT\n" + "DCL IMAGE[2], 2D, PIPE_FORMAT_R8G8_UINT, WR\n" + "DCL CONST[0][0]\n" /* .x = offset of the UV portion in the y direction */ + "DCL TEMP[0..4]\n" + "IMM[0] UINT32 {64, 0, 2, 1}\n" + /* Destination R8G8 coordinates */ + "UMAD TEMP[0].x, SV[1], IMM[0], SV[0]\n" + "MOV TEMP[0].y, SV[1]\n" + /* Source R8 coordinates of U */ + "UMUL TEMP[1].x, TEMP[0], IMM[0].zzzz\n" + "UADD TEMP[1].y, TEMP[0], CONST[0].xxxx\n" + /* Source R8 coordinates of V */ + "UADD TEMP[2].x, TEMP[1], IMM[0].wwww\n" + "MOV TEMP[2].y, TEMP[1]\n" + + "LOAD TEMP[3].x, IMAGE[0], TEMP[1], 2D, PIPE_FORMAT_R8_UINT\n" + "LOAD TEMP[4].x, IMAGE[0], TEMP[2], 2D, PIPE_FORMAT_R8_UINT\n" + "MOV TEMP[3].y, TEMP[4].xxxx\n" + "STORE IMAGE[2], TEMP[0], TEMP[3], 2D, PIPE_FORMAT_R8G8_UINT\n" + "END\n"; + + priv->copy_y_shader = create_compute_state(pipe, copy_y); + priv->copy_uv_shader = create_compute_state(pipe, copy_uv); +} + +void enc_ReleaseCompute_common(vid_enc_PrivateType *priv) +{ + struct pipe_context *pipe = priv->s_pipe; + + if (priv->copy_y_shader) + pipe->delete_compute_state(pipe, priv->copy_y_shader); + if (priv->copy_uv_shader) + pipe->delete_compute_state(pipe, priv->copy_uv_shader); +} + +OMX_ERRORTYPE enc_LoadImage_common(vid_enc_PrivateType * priv, OMX_VIDEO_PORTDEFINITIONTYPE *def, + OMX_BUFFERHEADERTYPE *buf, + struct pipe_video_buffer *vbuf) +{ + struct pipe_context *pipe = priv->s_pipe; + struct pipe_box box = {}; + struct input_buf_private *inp = buf->pInputPortPrivate; + + if (!inp->resource) { + struct pipe_sampler_view **views; + void *ptr; + + views = vbuf->get_sampler_view_planes(vbuf); + if (!views) + return OMX_ErrorInsufficientResources; + + ptr = buf->pBuffer; + box.width = def->nFrameWidth; + box.height = def->nFrameHeight; + box.depth = 1; + pipe->texture_subdata(pipe, views[0]->texture, 0, + PIPE_TRANSFER_WRITE, &box, + ptr, def->nStride, 0); + ptr = ((uint8_t*)buf->pBuffer) + (def->nStride * box.height); + box.width = def->nFrameWidth / 2; + box.height = def->nFrameHeight / 2; + box.depth = 1; + pipe->texture_subdata(pipe, views[1]->texture, 0, + PIPE_TRANSFER_WRITE, &box, + ptr, def->nStride, 0); + } else { + struct vl_video_buffer *dst_buf = (struct vl_video_buffer *)vbuf; + + pipe_transfer_unmap(pipe, inp->transfer); + + /* inp->resource uses PIPE_FORMAT_I8 and the layout looks like this: + * + * def->nFrameWidth = 4, def->nFrameHeight = 4: + * |----| + * |YYYY| + * |YYYY| + * |YYYY| + * |YYYY| + * |UVUV| + * |UVUV| + * |----| + * + * The copy has 2 steps: + * - Copy Y to dst_buf->resources[0] as R8. + * - Copy UV to dst_buf->resources[1] as R8G8. + */ + if (priv->copy_y_shader && priv->copy_uv_shader) { + /* Compute path */ + /* Set shader images for both copies. */ + struct pipe_image_view image[3] = {0}; + image[0].resource = inp->resource; + image[0].shader_access = image[0].access = PIPE_IMAGE_ACCESS_READ; + image[0].format = PIPE_FORMAT_R8_UINT; + + image[1].resource = dst_buf->resources[0]; + image[1].shader_access = image[1].access = PIPE_IMAGE_ACCESS_WRITE; + image[1].format = PIPE_FORMAT_R8_UINT; + + image[2].resource = dst_buf->resources[1]; + image[2].shader_access = image[1].access = PIPE_IMAGE_ACCESS_WRITE; + image[2].format = PIPE_FORMAT_R8G8_UINT; + + pipe->set_shader_images(pipe, PIPE_SHADER_COMPUTE, 0, 3, image); + + /* Set the constant buffer. */ + uint32_t constants[4] = {def->nFrameHeight}; + struct pipe_constant_buffer cb = {}; + + cb.buffer_size = sizeof(constants); + cb.user_buffer = constants; + pipe->set_constant_buffer(pipe, PIPE_SHADER_COMPUTE, 0, &cb); + + /* Use the optimal block size for the linear image layout. */ + struct pipe_grid_info info = {}; + info.block[0] = 64; + info.block[1] = 1; + info.block[2] = 1; + info.grid[2] = 1; + + /* Copy Y */ + pipe->bind_compute_state(pipe, priv->copy_y_shader); + + info.grid[0] = DIV_ROUND_UP(def->nFrameWidth, 64); + info.grid[1] = def->nFrameHeight; + info.last_block[0] = def->nFrameWidth % 64; + pipe->launch_grid(pipe, &info); + + /* Copy UV */ + pipe->bind_compute_state(pipe, priv->copy_uv_shader); + + info.grid[0] = DIV_ROUND_UP(def->nFrameWidth / 2, 64); + info.grid[1] = def->nFrameHeight / 2; + info.last_block[0] = (def->nFrameWidth / 2) % 64; + pipe->launch_grid(pipe, &info); + + /* Make the result visible to all clients. */ + pipe->memory_barrier(pipe, PIPE_BARRIER_ALL); + + /* Unbind. */ + pipe->set_shader_images(pipe, PIPE_SHADER_COMPUTE, 0, 3, NULL); + pipe->set_constant_buffer(pipe, PIPE_SHADER_COMPUTE, 0, NULL); + pipe->bind_compute_state(pipe, NULL); + } else { + /* Graphics path */ + struct pipe_blit_info blit; + + box.width = def->nFrameWidth; + box.height = def->nFrameHeight; + box.depth = 1; + + /* Copy Y */ + pipe->resource_copy_region(pipe, + dst_buf->resources[0], + 0, 0, 0, 0, inp->resource, 0, &box); + + /* Copy U */ + memset(&blit, 0, sizeof(blit)); + blit.src.resource = inp->resource; + blit.src.format = inp->resource->format; + + blit.src.box.x = -1; + blit.src.box.y = def->nFrameHeight; + blit.src.box.width = def->nFrameWidth; + blit.src.box.height = def->nFrameHeight / 2 ; + blit.src.box.depth = 1; + + blit.dst.resource = dst_buf->resources[1]; + blit.dst.format = blit.dst.resource->format; + + blit.dst.box.width = def->nFrameWidth / 2; + blit.dst.box.height = def->nFrameHeight / 2; + blit.dst.box.depth = 1; + blit.filter = PIPE_TEX_FILTER_NEAREST; + + blit.mask = PIPE_MASK_R; + pipe->blit(pipe, &blit); + + /* Copy V */ + blit.src.box.x = 0; + blit.mask = PIPE_MASK_G; + pipe->blit(pipe, &blit); + } + + pipe->flush(pipe, NULL, 0); + + box.width = inp->resource->width0; + box.height = inp->resource->height0; + box.depth = inp->resource->depth0; + buf->pBuffer = pipe->transfer_map(pipe, inp->resource, 0, + PIPE_TRANSFER_WRITE, &box, + &inp->transfer); + } + + return OMX_ErrorNone; +} diff --git a/src/gallium/frontends/omx/vid_enc_common.h b/src/gallium/frontends/omx/vid_enc_common.h new file mode 100644 index 00000000000..8c8830dfcc6 --- /dev/null +++ b/src/gallium/frontends/omx/vid_enc_common.h @@ -0,0 +1,179 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef VID_ENC_COMMON_H +#define VID_ENC_COMMON_H + +#include "util/list.h" +#include "util/u_memory.h" + +#include "vl/vl_defines.h" +#include "vl/vl_compositor.h" +#include "vl/vl_winsys.h" + +#include + +#define OMX_VID_ENC_BITRATE_MIN 64000 +#define OMX_VID_ENC_BITRATE_MEDIAN 2000000 +#define OMX_VID_ENC_BITRATE_MAX 240000000 +#define OMX_VID_ENC_CONTROL_FRAME_RATE_DEN_DEFAULT 1001 +#define OMX_VID_ENC_QUANT_I_FRAMES_DEFAULT 0x1c +#define OMX_VID_ENC_QUANT_P_FRAMES_DEFAULT 0x1c +#define OMX_VID_ENC_QUANT_B_FRAMES_DEFAULT 0x1c +#define OMX_VID_ENC_SCALING_WIDTH_DEFAULT 0xffffffff +#define OMX_VID_ENC_SCALING_HEIGHT_DEFAULT 0xffffffff +#define OMX_VID_ENC_IDR_PERIOD_DEFAULT 1000 +#define OMX_VID_ENC_P_PERIOD_DEFAULT 3 + +#define OMX_VID_ENC_NUM_SCALING_BUFFERS 4 + +struct encode_task { + struct list_head list; + + struct pipe_video_buffer *buf; + unsigned pic_order_cnt; + struct pipe_resource *bitstream; + void *feedback; +}; + +struct input_buf_private { + struct list_head tasks; + + struct pipe_resource *resource; + struct pipe_transfer *transfer; +}; + +struct output_buf_private { + struct pipe_resource *bitstream; + struct pipe_transfer *transfer; +}; + +#if ENABLE_ST_OMX_BELLAGIO + +#include + +DERIVEDCLASS(vid_enc_PrivateType, omx_base_filter_PrivateType) +#define vid_enc_PrivateType_FIELDS omx_base_filter_PrivateType_FIELDS \ + struct vl_screen *screen; \ + struct pipe_context *s_pipe; \ + struct pipe_context *t_pipe; \ + struct pipe_video_codec *codec; \ + struct list_head free_tasks; \ + struct list_head used_tasks; \ + struct list_head b_frames; \ + struct list_head stacked_tasks; \ + OMX_U32 frame_rate; \ + OMX_U32 frame_num; \ + OMX_U32 pic_order_cnt; \ + OMX_U32 ref_idx_l0, ref_idx_l1; \ + OMX_BOOL restricted_b_frames; \ + OMX_VIDEO_PARAM_BITRATETYPE bitrate; \ + OMX_VIDEO_PARAM_QUANTIZATIONTYPE quant; \ + OMX_VIDEO_PARAM_PROFILELEVELTYPE profile_level; \ + OMX_CONFIG_INTRAREFRESHVOPTYPE force_pic_type; \ + struct vl_compositor compositor; \ + struct vl_compositor_state cstate; \ + struct pipe_video_buffer *scale_buffer[OMX_VID_ENC_NUM_SCALING_BUFFERS]; \ + OMX_CONFIG_SCALEFACTORTYPE scale; \ + OMX_U32 current_scale_buffer; \ + OMX_U32 stacked_frames_num; \ + void *copy_y_shader; \ + void *copy_uv_shader; +ENDCLASS(vid_enc_PrivateType) + +#else + +#include +#include + +typedef struct h264e_prc_class h264e_prc_class_t; +struct h264e_prc_class +{ + /* Class */ + const tiz_prc_class_t _; + /* NOTE: Class methods might be added in the future */ +}; + +typedef struct h264e_prc vid_enc_PrivateType; +struct h264e_prc +{ + /* Object */ + const tiz_prc_t _; + OMX_BUFFERHEADERTYPE *p_inhdr_; + OMX_BUFFERHEADERTYPE *p_outhdr_; + OMX_PARAM_PORTDEFINITIONTYPE in_port_def_; + OMX_PARAM_PORTDEFINITIONTYPE out_port_def_; + struct vl_screen *screen; + struct pipe_context *s_pipe; + struct pipe_context *t_pipe; + struct pipe_video_codec *codec; + struct list_head free_tasks; + struct list_head used_tasks; + struct list_head b_frames; + struct list_head stacked_tasks; + OMX_U32 frame_rate; + OMX_U32 frame_num; + OMX_U32 pic_order_cnt; + OMX_U32 ref_idx_l0, ref_idx_l1; + OMX_BOOL restricted_b_frames; + OMX_VIDEO_PARAM_BITRATETYPE bitrate; + OMX_VIDEO_PARAM_QUANTIZATIONTYPE quant; + OMX_VIDEO_PARAM_PROFILELEVELTYPE profile_level; + OMX_CONFIG_INTRAREFRESHVOPTYPE force_pic_type; + struct vl_compositor compositor; + struct vl_compositor_state cstate; + struct pipe_video_buffer *scale_buffer[OMX_VID_ENC_NUM_SCALING_BUFFERS]; + OMX_CONFIG_SCALEFACTORTYPE scale; + OMX_U32 current_scale_buffer; + OMX_U32 stacked_frames_num; + bool eos_; + bool in_port_disabled_; + bool out_port_disabled_; + void *copy_y_shader; + void *copy_uv_shader; +}; +#endif + +void enc_ReleaseTasks(struct list_head *head); +void enc_MoveTasks(struct list_head *from, struct list_head *to); +enum pipe_video_profile enc_TranslateOMXProfileToPipe(unsigned omx_profile); +unsigned enc_TranslateOMXLevelToPipe(unsigned omx_level); +void vid_enc_BufferEncoded_common(vid_enc_PrivateType * priv, OMX_BUFFERHEADERTYPE* input, + OMX_BUFFERHEADERTYPE* output); +struct encode_task *enc_NeedTask_common(vid_enc_PrivateType * priv, + OMX_VIDEO_PORTDEFINITIONTYPE *def); +void enc_ScaleInput_common(vid_enc_PrivateType * priv, + OMX_VIDEO_PORTDEFINITIONTYPE *def, + struct pipe_video_buffer **vbuf, unsigned *size); +void enc_ControlPicture_common(vid_enc_PrivateType * priv, + struct pipe_h264_enc_picture_desc *picture); +void enc_InitCompute_common(vid_enc_PrivateType *priv); +void enc_ReleaseCompute_common(vid_enc_PrivateType *priv); +OMX_ERRORTYPE enc_LoadImage_common(vid_enc_PrivateType * priv, OMX_VIDEO_PORTDEFINITIONTYPE *def, + OMX_BUFFERHEADERTYPE *buf, + struct pipe_video_buffer *vbuf); +#endif diff --git a/src/gallium/frontends/omx/vid_omx_common.c b/src/gallium/frontends/omx/vid_omx_common.c new file mode 100644 index 00000000000..63afa898ba1 --- /dev/null +++ b/src/gallium/frontends/omx/vid_omx_common.c @@ -0,0 +1,111 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include +#include +#include + +#if defined(HAVE_X11_PLATFORM) +#include +#else +#define XOpenDisplay(x) NULL +#define XCloseDisplay(x) +#define Display void +#endif + +#include "os/os_thread.h" +#include "util/u_memory.h" +#include "loader/loader.h" + +#include "vid_omx_common.h" + +static mtx_t omx_lock = _MTX_INITIALIZER_NP; +static Display *omx_display = NULL; +static struct vl_screen *omx_screen = NULL; +static unsigned omx_usecount = 0; +static const char *omx_render_node = NULL; +static int drm_fd; + +struct vl_screen *omx_get_screen(void) +{ + static bool first_time = true; + mtx_lock(&omx_lock); + + if (!omx_screen) { + if (first_time) { + omx_render_node = debug_get_option("OMX_RENDER_NODE", NULL); + first_time = false; + } + if (omx_render_node) { + drm_fd = loader_open_device(omx_render_node); + if (drm_fd < 0) + goto error; + + omx_screen = vl_drm_screen_create(drm_fd); + if (!omx_screen) { + close(drm_fd); + goto error; + } + } else { + omx_display = XOpenDisplay(NULL); + if (!omx_display) + goto error; + + omx_screen = vl_dri3_screen_create(omx_display, 0); + if (!omx_screen) + omx_screen = vl_dri2_screen_create(omx_display, 0); + if (!omx_screen) { + XCloseDisplay(omx_display); + goto error; + } + } + } + + ++omx_usecount; + + mtx_unlock(&omx_lock); + return omx_screen; + +error: + mtx_unlock(&omx_lock); + return NULL; +} + +void omx_put_screen(void) +{ + mtx_lock(&omx_lock); + if ((--omx_usecount) == 0) { + omx_screen->destroy(omx_screen); + omx_screen = NULL; + + if (omx_render_node) + close(drm_fd); + else + XCloseDisplay(omx_display); + } + mtx_unlock(&omx_lock); +} diff --git a/src/gallium/frontends/omx/vid_omx_common.h b/src/gallium/frontends/omx/vid_omx_common.h new file mode 100644 index 00000000000..e27013d1746 --- /dev/null +++ b/src/gallium/frontends/omx/vid_omx_common.h @@ -0,0 +1,36 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef VID_OMX_COMMON_H +#define VID_OMX_COMMON_H + +#include "vl/vl_winsys.h" + +struct vl_screen *omx_get_screen(void); +void omx_put_screen(void); + +#endif diff --git a/src/gallium/frontends/osmesa/Makefile.sources b/src/gallium/frontends/osmesa/Makefile.sources new file mode 100644 index 00000000000..f8008efdec5 --- /dev/null +++ b/src/gallium/frontends/osmesa/Makefile.sources @@ -0,0 +1,2 @@ +C_SOURCES := \ + osmesa.c diff --git a/src/gallium/frontends/osmesa/SConscript b/src/gallium/frontends/osmesa/SConscript new file mode 100644 index 00000000000..be67d0fe739 --- /dev/null +++ b/src/gallium/frontends/osmesa/SConscript @@ -0,0 +1,24 @@ +import os + +Import('*') + +env = env.Clone() + +env.Append(CPPPATH = [ + '#src/mapi', + '#src/mesa', + '.', +]) + +if env['platform'] == 'windows': + env.AppendUnique(CPPDEFINES = [ + 'BUILD_GL32', # declare gl* as __declspec(dllexport) in Mesa headers + 'WIN32_LEAN_AND_MEAN', # http://msdn2.microsoft.com/en-us/library/6dwk3a1z.aspx + '_GLAPI_NO_EXPORTS', # prevent _glapi_* from being declared __declspec(dllimport) + ]) + +st_osmesa = env.ConvenienceLibrary( + target ='st_osmesa', + source = env.ParseSourceList('Makefile.sources', 'C_SOURCES'), +) +Export('st_osmesa') diff --git a/src/gallium/frontends/osmesa/meson.build b/src/gallium/frontends/osmesa/meson.build new file mode 100644 index 00000000000..e5848fd9934 --- /dev/null +++ b/src/gallium/frontends/osmesa/meson.build @@ -0,0 +1,36 @@ +# Copyright © 2017-2018 Intel Corporation + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +osmesa_st_c_args = [] +if with_platform_windows + osmesa_st_c_args += ['-DBUILD_GL32', '-DWIN32_LEAN_AND_MEAN'] + if not with_shared_glapi + osmesa_st_c_args += ['-D_GLAPI_NO_EXPORTS'] + endif +endif + +libosmesa_st = static_library( + 'osmesa_st', + 'osmesa.c', + c_args : osmesa_st_c_args, + include_directories : [ + inc_include, inc_src, inc_gallium, inc_gallium_aux, inc_mapi, inc_mesa, + ], +) diff --git a/src/gallium/frontends/osmesa/osmesa.c b/src/gallium/frontends/osmesa/osmesa.c new file mode 100644 index 00000000000..8689c1113a3 --- /dev/null +++ b/src/gallium/frontends/osmesa/osmesa.c @@ -0,0 +1,1047 @@ +/* + * Copyright (c) 2013 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + + +/* + * Off-Screen rendering into client memory. + * State tracker for gallium (for softpipe and llvmpipe) + * + * Notes: + * + * If Gallium is built with LLVM support we use the llvmpipe driver. + * Otherwise we use softpipe. The GALLIUM_DRIVER environment variable + * may be set to "softpipe" or "llvmpipe" to override. + * + * With softpipe we could render directly into the user's buffer by using a + * display target resource. However, softpipe doesn't support "upside-down" + * rendering which would be needed for the OSMESA_Y_UP=TRUE case. + * + * With llvmpipe we could only render directly into the user's buffer when its + * width and height is a multiple of the tile size (64 pixels). + * + * Because of these constraints we always render into ordinary resources then + * copy the results to the user's buffer in the flush_front() function which + * is called when the app calls glFlush/Finish. + * + * In general, the OSMesa interface is pretty ugly and not a good match + * for Gallium. But we're interested in doing the best we can to preserve + * application portability. With a little work we could come up with a + * much nicer, new off-screen Gallium interface... + */ + + +#include +#include +#include "GL/osmesa.h" + +#include "glapi/glapi.h" /* for OSMesaGetProcAddress below */ + +#include "pipe/p_context.h" +#include "pipe/p_screen.h" +#include "pipe/p_state.h" + +#include "util/u_atomic.h" +#include "util/u_box.h" +#include "util/u_debug.h" +#include "util/format/u_format.h" +#include "util/u_inlines.h" +#include "util/u_memory.h" + +#include "postprocess/filters.h" +#include "postprocess/postprocess.h" + +#include "frontend/api.h" +#include "state_tracker/st_gl_api.h" + + + +extern struct pipe_screen * +osmesa_create_screen(void); + + + +struct osmesa_buffer +{ + struct st_framebuffer_iface *stfb; + struct st_visual visual; + unsigned width, height; + + struct pipe_resource *textures[ST_ATTACHMENT_COUNT]; + + void *map; + + struct osmesa_buffer *next; /**< next in linked list */ +}; + + +struct osmesa_context +{ + struct st_context_iface *stctx; + + boolean ever_used; /*< Has this context ever been current? */ + + struct osmesa_buffer *current_buffer; + + enum pipe_format depth_stencil_format, accum_format; + + GLenum format; /*< User-specified context format */ + GLenum type; /*< Buffer's data type */ + GLint user_row_length; /*< user-specified number of pixels per row */ + GLboolean y_up; /*< TRUE -> Y increases upward */ + /*< FALSE -> Y increases downward */ + + /** Which postprocessing filters are enabled. */ + unsigned pp_enabled[PP_FILTERS]; + struct pp_queue_t *pp; +}; + + +/** + * Linked list of all osmesa_buffers. + * We can re-use an osmesa_buffer from one OSMesaMakeCurrent() call to + * the next unless the color/depth/stencil/accum formats change. + * We have to do this to be compatible with the original OSMesa implementation + * because some apps call OSMesaMakeCurrent() several times during rendering + * a frame. + */ +static struct osmesa_buffer *BufferList = NULL; + + +/** + * Called from the ST manager. + */ +static int +osmesa_st_get_param(struct st_manager *smapi, enum st_manager_param param) +{ + /* no-op */ + return 0; +} + + +/** + * Create/return singleton st_api object. + */ +static struct st_api * +get_st_api(void) +{ + static struct st_api *stapi = NULL; + if (!stapi) { + stapi = st_gl_api_create(); + } + return stapi; +} + +static struct st_manager *stmgr = NULL; + +static void +create_st_manager(void) +{ + stmgr = CALLOC_STRUCT(st_manager); + if (stmgr) { + stmgr->screen = osmesa_create_screen(); + stmgr->get_param = osmesa_st_get_param; + stmgr->get_egl_image = NULL; + } +} + +/** + * Create/return a singleton st_manager object. + */ +static struct st_manager * +get_st_manager(void) +{ + static once_flag create_once_flag = ONCE_FLAG_INIT; + + call_once(&create_once_flag, create_st_manager); + + return stmgr; +} + + +/** + * Given an OSMESA_x format and a GL_y type, return the best + * matching PIPE_FORMAT_z. + * Note that we can't exactly match all user format/type combinations + * with gallium formats. If we find this to be a problem, we can + * implement more elaborate format/type conversion in the flush_front() + * function. + */ +static enum pipe_format +osmesa_choose_format(GLenum format, GLenum type) +{ + switch (format) { + case OSMESA_RGBA: + if (type == GL_UNSIGNED_BYTE) { +#if UTIL_ARCH_LITTLE_ENDIAN + return PIPE_FORMAT_R8G8B8A8_UNORM; +#else + return PIPE_FORMAT_A8B8G8R8_UNORM; +#endif + } + else if (type == GL_UNSIGNED_SHORT) { + return PIPE_FORMAT_R16G16B16A16_UNORM; + } + else if (type == GL_FLOAT) { + return PIPE_FORMAT_R32G32B32A32_FLOAT; + } + else { + return PIPE_FORMAT_NONE; + } + break; + case OSMESA_BGRA: + if (type == GL_UNSIGNED_BYTE) { +#if UTIL_ARCH_LITTLE_ENDIAN + return PIPE_FORMAT_B8G8R8A8_UNORM; +#else + return PIPE_FORMAT_A8R8G8B8_UNORM; +#endif + } + else if (type == GL_UNSIGNED_SHORT) { + return PIPE_FORMAT_R16G16B16A16_UNORM; + } + else if (type == GL_FLOAT) { + return PIPE_FORMAT_R32G32B32A32_FLOAT; + } + else { + return PIPE_FORMAT_NONE; + } + break; + case OSMESA_ARGB: + if (type == GL_UNSIGNED_BYTE) { +#if UTIL_ARCH_LITTLE_ENDIAN + return PIPE_FORMAT_A8R8G8B8_UNORM; +#else + return PIPE_FORMAT_B8G8R8A8_UNORM; +#endif + } + else if (type == GL_UNSIGNED_SHORT) { + return PIPE_FORMAT_R16G16B16A16_UNORM; + } + else if (type == GL_FLOAT) { + return PIPE_FORMAT_R32G32B32A32_FLOAT; + } + else { + return PIPE_FORMAT_NONE; + } + break; + case OSMESA_RGB: + if (type == GL_UNSIGNED_BYTE) { + return PIPE_FORMAT_R8G8B8_UNORM; + } + else if (type == GL_UNSIGNED_SHORT) { + return PIPE_FORMAT_R16G16B16_UNORM; + } + else if (type == GL_FLOAT) { + return PIPE_FORMAT_R32G32B32_FLOAT; + } + else { + return PIPE_FORMAT_NONE; + } + break; + case OSMESA_BGR: + /* No gallium format for this one */ + return PIPE_FORMAT_NONE; + case OSMESA_RGB_565: + if (type != GL_UNSIGNED_SHORT_5_6_5) + return PIPE_FORMAT_NONE; + return PIPE_FORMAT_B5G6R5_UNORM; + default: + ; /* fall-through */ + } + return PIPE_FORMAT_NONE; +} + + +/** + * Initialize an st_visual object. + */ +static void +osmesa_init_st_visual(struct st_visual *vis, + enum pipe_format color_format, + enum pipe_format ds_format, + enum pipe_format accum_format) +{ + vis->buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK; + + if (ds_format != PIPE_FORMAT_NONE) + vis->buffer_mask |= ST_ATTACHMENT_DEPTH_STENCIL_MASK; + if (accum_format != PIPE_FORMAT_NONE) + vis->buffer_mask |= ST_ATTACHMENT_ACCUM; + + vis->color_format = color_format; + vis->depth_stencil_format = ds_format; + vis->accum_format = accum_format; + vis->samples = 1; + vis->render_buffer = ST_ATTACHMENT_FRONT_LEFT; +} + + +/** + * Return the osmesa_buffer that corresponds to an st_framebuffer_iface. + */ +static inline struct osmesa_buffer * +stfbi_to_osbuffer(struct st_framebuffer_iface *stfbi) +{ + return (struct osmesa_buffer *) stfbi->st_manager_private; +} + + +/** + * Called via glFlush/glFinish. This is where we copy the contents + * of the driver's color buffer into the user-specified buffer. + */ +static bool +osmesa_st_framebuffer_flush_front(struct st_context_iface *stctx, + struct st_framebuffer_iface *stfbi, + enum st_attachment_type statt) +{ + OSMesaContext osmesa = OSMesaGetCurrentContext(); + struct osmesa_buffer *osbuffer = stfbi_to_osbuffer(stfbi); + struct pipe_context *pipe = stctx->pipe; + struct pipe_resource *res = osbuffer->textures[statt]; + struct pipe_transfer *transfer = NULL; + struct pipe_box box; + void *map; + ubyte *src, *dst; + unsigned y, bytes, bpp; + int dst_stride; + + if (osmesa->pp) { + struct pipe_resource *zsbuf = NULL; + unsigned i; + + /* Find the z/stencil buffer if there is one */ + for (i = 0; i < ARRAY_SIZE(osbuffer->textures); i++) { + struct pipe_resource *res = osbuffer->textures[i]; + if (res) { + const struct util_format_description *desc = + util_format_description(res->format); + + if (util_format_has_depth(desc)) { + zsbuf = res; + break; + } + } + } + + /* run the postprocess stage(s) */ + pp_run(osmesa->pp, res, res, zsbuf); + } + + u_box_2d(0, 0, res->width0, res->height0, &box); + + map = pipe->transfer_map(pipe, res, 0, PIPE_TRANSFER_READ, &box, + &transfer); + + /* + * Copy the color buffer from the resource to the user's buffer. + */ + bpp = util_format_get_blocksize(osbuffer->visual.color_format); + src = map; + dst = osbuffer->map; + if (osmesa->user_row_length) + dst_stride = bpp * osmesa->user_row_length; + else + dst_stride = bpp * osbuffer->width; + bytes = bpp * res->width0; + + if (osmesa->y_up) { + /* need to flip image upside down */ + dst = dst + (res->height0 - 1) * dst_stride; + dst_stride = -dst_stride; + } + + for (y = 0; y < res->height0; y++) { + memcpy(dst, src, bytes); + dst += dst_stride; + src += transfer->stride; + } + + pipe->transfer_unmap(pipe, transfer); + + return true; +} + + +/** + * Called by the st manager to validate the framebuffer (allocate + * its resources). + */ +static bool +osmesa_st_framebuffer_validate(struct st_context_iface *stctx, + struct st_framebuffer_iface *stfbi, + const enum st_attachment_type *statts, + unsigned count, + struct pipe_resource **out) +{ + struct pipe_screen *screen = get_st_manager()->screen; + enum st_attachment_type i; + struct osmesa_buffer *osbuffer = stfbi_to_osbuffer(stfbi); + struct pipe_resource templat; + + memset(&templat, 0, sizeof(templat)); + templat.target = PIPE_TEXTURE_RECT; + templat.format = 0; /* setup below */ + templat.last_level = 0; + templat.width0 = osbuffer->width; + templat.height0 = osbuffer->height; + templat.depth0 = 1; + templat.array_size = 1; + templat.usage = PIPE_USAGE_DEFAULT; + templat.bind = 0; /* setup below */ + templat.flags = 0; + + for (i = 0; i < count; i++) { + enum pipe_format format = PIPE_FORMAT_NONE; + unsigned bind = 0; + + /* + * At this time, we really only need to handle the front-left color + * attachment, since that's all we specified for the visual in + * osmesa_init_st_visual(). + */ + if (statts[i] == ST_ATTACHMENT_FRONT_LEFT) { + format = osbuffer->visual.color_format; + bind = PIPE_BIND_RENDER_TARGET; + } + else if (statts[i] == ST_ATTACHMENT_DEPTH_STENCIL) { + format = osbuffer->visual.depth_stencil_format; + bind = PIPE_BIND_DEPTH_STENCIL; + } + else if (statts[i] == ST_ATTACHMENT_ACCUM) { + format = osbuffer->visual.accum_format; + bind = PIPE_BIND_RENDER_TARGET; + } + else { + debug_warning("Unexpected attachment type in " + "osmesa_st_framebuffer_validate()"); + } + + templat.format = format; + templat.bind = bind; + pipe_resource_reference(&out[i], NULL); + out[i] = osbuffer->textures[statts[i]] = + screen->resource_create(screen, &templat); + } + + return true; +} + +static uint32_t osmesa_fb_ID = 0; + +static struct st_framebuffer_iface * +osmesa_create_st_framebuffer(void) +{ + struct st_framebuffer_iface *stfbi = CALLOC_STRUCT(st_framebuffer_iface); + if (stfbi) { + stfbi->flush_front = osmesa_st_framebuffer_flush_front; + stfbi->validate = osmesa_st_framebuffer_validate; + p_atomic_set(&stfbi->stamp, 1); + stfbi->ID = p_atomic_inc_return(&osmesa_fb_ID); + stfbi->state_manager = get_st_manager(); + } + return stfbi; +} + + +/** + * Create new buffer and add to linked list. + */ +static struct osmesa_buffer * +osmesa_create_buffer(enum pipe_format color_format, + enum pipe_format ds_format, + enum pipe_format accum_format) +{ + struct osmesa_buffer *osbuffer = CALLOC_STRUCT(osmesa_buffer); + if (osbuffer) { + osbuffer->stfb = osmesa_create_st_framebuffer(); + + osbuffer->stfb->st_manager_private = osbuffer; + osbuffer->stfb->visual = &osbuffer->visual; + + osmesa_init_st_visual(&osbuffer->visual, color_format, + ds_format, accum_format); + + /* insert into linked list */ + osbuffer->next = BufferList; + BufferList = osbuffer; + } + + return osbuffer; +} + + +/** + * Search linked list for a buffer with matching pixel formats and size. + */ +static struct osmesa_buffer * +osmesa_find_buffer(enum pipe_format color_format, + enum pipe_format ds_format, + enum pipe_format accum_format, + GLsizei width, GLsizei height) +{ + struct osmesa_buffer *b; + + /* Check if we already have a suitable buffer for the given formats */ + for (b = BufferList; b; b = b->next) { + if (b->visual.color_format == color_format && + b->visual.depth_stencil_format == ds_format && + b->visual.accum_format == accum_format && + b->width == width && + b->height == height) { + return b; + } + } + return NULL; +} + + +static void +osmesa_destroy_buffer(struct osmesa_buffer *osbuffer) +{ + struct st_api *stapi = get_st_api(); + + /* + * Notify the state manager that the associated framebuffer interface + * is no longer valid. + */ + stapi->destroy_drawable(stapi, osbuffer->stfb); + + FREE(osbuffer->stfb); + FREE(osbuffer); +} + + + +/**********************************************************************/ +/***** Public Functions *****/ +/**********************************************************************/ + + +/** + * Create an Off-Screen Mesa rendering context. The only attribute needed is + * an RGBA vs Color-Index mode flag. + * + * Input: format - Must be GL_RGBA + * sharelist - specifies another OSMesaContext with which to share + * display lists. NULL indicates no sharing. + * Return: an OSMesaContext or 0 if error + */ +GLAPI OSMesaContext GLAPIENTRY +OSMesaCreateContext(GLenum format, OSMesaContext sharelist) +{ + return OSMesaCreateContextExt(format, 24, 8, 0, sharelist); +} + + +/** + * New in Mesa 3.5 + * + * Create context and specify size of ancillary buffers. + */ +GLAPI OSMesaContext GLAPIENTRY +OSMesaCreateContextExt(GLenum format, GLint depthBits, GLint stencilBits, + GLint accumBits, OSMesaContext sharelist) +{ + int attribs[100], n = 0; + + attribs[n++] = OSMESA_FORMAT; + attribs[n++] = format; + attribs[n++] = OSMESA_DEPTH_BITS; + attribs[n++] = depthBits; + attribs[n++] = OSMESA_STENCIL_BITS; + attribs[n++] = stencilBits; + attribs[n++] = OSMESA_ACCUM_BITS; + attribs[n++] = accumBits; + attribs[n++] = 0; + + return OSMesaCreateContextAttribs(attribs, sharelist); +} + + +/** + * New in Mesa 11.2 + * + * Create context with attribute list. + */ +GLAPI OSMesaContext GLAPIENTRY +OSMesaCreateContextAttribs(const int *attribList, OSMesaContext sharelist) +{ + OSMesaContext osmesa; + struct st_context_iface *st_shared; + enum st_context_error st_error = 0; + struct st_context_attribs attribs; + struct st_api *stapi = get_st_api(); + GLenum format = GL_RGBA; + int depthBits = 0, stencilBits = 0, accumBits = 0; + int profile = OSMESA_COMPAT_PROFILE, version_major = 1, version_minor = 0; + int i; + + if (sharelist) { + st_shared = sharelist->stctx; + } + else { + st_shared = NULL; + } + + for (i = 0; attribList[i]; i += 2) { + switch (attribList[i]) { + case OSMESA_FORMAT: + format = attribList[i+1]; + switch (format) { + case OSMESA_COLOR_INDEX: + case OSMESA_RGBA: + case OSMESA_BGRA: + case OSMESA_ARGB: + case OSMESA_RGB: + case OSMESA_BGR: + case OSMESA_RGB_565: + /* legal */ + break; + default: + return NULL; + } + break; + case OSMESA_DEPTH_BITS: + depthBits = attribList[i+1]; + if (depthBits < 0) + return NULL; + break; + case OSMESA_STENCIL_BITS: + stencilBits = attribList[i+1]; + if (stencilBits < 0) + return NULL; + break; + case OSMESA_ACCUM_BITS: + accumBits = attribList[i+1]; + if (accumBits < 0) + return NULL; + break; + case OSMESA_PROFILE: + profile = attribList[i+1]; + if (profile != OSMESA_CORE_PROFILE && + profile != OSMESA_COMPAT_PROFILE) + return NULL; + break; + case OSMESA_CONTEXT_MAJOR_VERSION: + version_major = attribList[i+1]; + if (version_major < 1) + return NULL; + break; + case OSMESA_CONTEXT_MINOR_VERSION: + version_minor = attribList[i+1]; + if (version_minor < 0) + return NULL; + break; + case 0: + /* end of list */ + break; + default: + fprintf(stderr, "Bad attribute in OSMesaCreateContextAttribs()\n"); + return NULL; + } + } + + osmesa = (OSMesaContext) CALLOC_STRUCT(osmesa_context); + if (!osmesa) + return NULL; + + /* Choose depth/stencil/accum buffer formats */ + if (accumBits > 0) { + osmesa->accum_format = PIPE_FORMAT_R16G16B16A16_SNORM; + } + if (depthBits > 0 && stencilBits > 0) { + osmesa->depth_stencil_format = PIPE_FORMAT_Z24_UNORM_S8_UINT; + } + else if (stencilBits > 0) { + osmesa->depth_stencil_format = PIPE_FORMAT_S8_UINT; + } + else if (depthBits >= 24) { + osmesa->depth_stencil_format = PIPE_FORMAT_Z24X8_UNORM; + } + else if (depthBits >= 16) { + osmesa->depth_stencil_format = PIPE_FORMAT_Z16_UNORM; + } + + /* + * Create the rendering context + */ + memset(&attribs, 0, sizeof(attribs)); + attribs.profile = (profile == OSMESA_CORE_PROFILE) + ? ST_PROFILE_OPENGL_CORE : ST_PROFILE_DEFAULT; + attribs.major = version_major; + attribs.minor = version_minor; + attribs.flags = 0; /* ST_CONTEXT_FLAG_x */ + attribs.options.force_glsl_extensions_warn = FALSE; + attribs.options.disable_blend_func_extended = FALSE; + attribs.options.disable_glsl_line_continuations = FALSE; + attribs.options.force_glsl_version = 0; + + osmesa_init_st_visual(&attribs.visual, + PIPE_FORMAT_NONE, + osmesa->depth_stencil_format, + osmesa->accum_format); + + osmesa->stctx = stapi->create_context(stapi, get_st_manager(), + &attribs, &st_error, st_shared); + if (!osmesa->stctx) { + FREE(osmesa); + return NULL; + } + + osmesa->stctx->st_manager_private = osmesa; + + osmesa->format = format; + osmesa->user_row_length = 0; + osmesa->y_up = GL_TRUE; + + return osmesa; +} + + + +/** + * Destroy an Off-Screen Mesa rendering context. + * + * \param osmesa the context to destroy + */ +GLAPI void GLAPIENTRY +OSMesaDestroyContext(OSMesaContext osmesa) +{ + if (osmesa) { + pp_free(osmesa->pp); + osmesa->stctx->destroy(osmesa->stctx); + FREE(osmesa); + } +} + + +/** + * Bind an OSMesaContext to an image buffer. The image buffer is just a + * block of memory which the client provides. Its size must be at least + * as large as width*height*pixelSize. Its address should be a multiple + * of 4 if using RGBA mode. + * + * By default, image data is stored in the order of glDrawPixels: row-major + * order with the lower-left image pixel stored in the first array position + * (ie. bottom-to-top). + * + * If the context's viewport hasn't been initialized yet, it will now be + * initialized to (0,0,width,height). + * + * Input: osmesa - the rendering context + * buffer - the image buffer memory + * type - data type for pixel components + * GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT + * or GL_FLOAT. + * width, height - size of image buffer in pixels, at least 1 + * Return: GL_TRUE if success, GL_FALSE if error because of invalid osmesa, + * invalid type, invalid size, etc. + */ +GLAPI GLboolean GLAPIENTRY +OSMesaMakeCurrent(OSMesaContext osmesa, void *buffer, GLenum type, + GLsizei width, GLsizei height) +{ + struct st_api *stapi = get_st_api(); + struct osmesa_buffer *osbuffer; + enum pipe_format color_format; + + if (!osmesa && !buffer) { + stapi->make_current(stapi, NULL, NULL, NULL); + return GL_TRUE; + } + + if (!osmesa || !buffer || width < 1 || height < 1) { + return GL_FALSE; + } + + color_format = osmesa_choose_format(osmesa->format, type); + if (color_format == PIPE_FORMAT_NONE) { + fprintf(stderr, "OSMesaMakeCurrent(unsupported format/type)\n"); + return GL_FALSE; + } + + /* See if we already have a buffer that uses these pixel formats */ + osbuffer = osmesa_find_buffer(color_format, + osmesa->depth_stencil_format, + osmesa->accum_format, width, height); + if (!osbuffer) { + /* Existing buffer found, create new buffer */ + osbuffer = osmesa_create_buffer(color_format, + osmesa->depth_stencil_format, + osmesa->accum_format); + } + + osbuffer->width = width; + osbuffer->height = height; + osbuffer->map = buffer; + + /* XXX unused for now */ + (void) osmesa_destroy_buffer; + + osmesa->current_buffer = osbuffer; + osmesa->type = type; + + stapi->make_current(stapi, osmesa->stctx, osbuffer->stfb, osbuffer->stfb); + + if (!osmesa->ever_used) { + /* one-time init, just postprocessing for now */ + boolean any_pp_enabled = FALSE; + unsigned i; + + for (i = 0; i < ARRAY_SIZE(osmesa->pp_enabled); i++) { + if (osmesa->pp_enabled[i]) { + any_pp_enabled = TRUE; + break; + } + } + + if (any_pp_enabled) { + osmesa->pp = pp_init(osmesa->stctx->pipe, + osmesa->pp_enabled, + osmesa->stctx->cso_context); + + pp_init_fbos(osmesa->pp, width, height); + } + + osmesa->ever_used = TRUE; + } + + return GL_TRUE; +} + + + +GLAPI OSMesaContext GLAPIENTRY +OSMesaGetCurrentContext(void) +{ + struct st_api *stapi = get_st_api(); + struct st_context_iface *st = stapi->get_current(stapi); + return st ? (OSMesaContext) st->st_manager_private : NULL; +} + + + +GLAPI void GLAPIENTRY +OSMesaPixelStore(GLint pname, GLint value) +{ + OSMesaContext osmesa = OSMesaGetCurrentContext(); + + switch (pname) { + case OSMESA_ROW_LENGTH: + osmesa->user_row_length = value; + break; + case OSMESA_Y_UP: + osmesa->y_up = value ? GL_TRUE : GL_FALSE; + break; + default: + fprintf(stderr, "Invalid pname in OSMesaPixelStore()\n"); + return; + } +} + + +GLAPI void GLAPIENTRY +OSMesaGetIntegerv(GLint pname, GLint *value) +{ + OSMesaContext osmesa = OSMesaGetCurrentContext(); + struct osmesa_buffer *osbuffer = osmesa ? osmesa->current_buffer : NULL; + + switch (pname) { + case OSMESA_WIDTH: + *value = osbuffer ? osbuffer->width : 0; + return; + case OSMESA_HEIGHT: + *value = osbuffer ? osbuffer->height : 0; + return; + case OSMESA_FORMAT: + *value = osmesa->format; + return; + case OSMESA_TYPE: + /* current color buffer's data type */ + *value = osmesa->type; + return; + case OSMESA_ROW_LENGTH: + *value = osmesa->user_row_length; + return; + case OSMESA_Y_UP: + *value = osmesa->y_up; + return; + case OSMESA_MAX_WIDTH: + /* fall-through */ + case OSMESA_MAX_HEIGHT: + { + struct pipe_screen *screen = get_st_manager()->screen; + *value = screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_2D_SIZE); + } + return; + default: + fprintf(stderr, "Invalid pname in OSMesaGetIntegerv()\n"); + return; + } +} + + +/** + * Return information about the depth buffer associated with an OSMesa context. + * Input: c - the OSMesa context + * Output: width, height - size of buffer in pixels + * bytesPerValue - bytes per depth value (2 or 4) + * buffer - pointer to depth buffer values + * Return: GL_TRUE or GL_FALSE to indicate success or failure. + */ +GLAPI GLboolean GLAPIENTRY +OSMesaGetDepthBuffer(OSMesaContext c, GLint *width, GLint *height, + GLint *bytesPerValue, void **buffer) +{ + struct osmesa_buffer *osbuffer = c->current_buffer; + struct pipe_context *pipe = c->stctx->pipe; + struct pipe_resource *res = osbuffer->textures[ST_ATTACHMENT_DEPTH_STENCIL]; + struct pipe_transfer *transfer = NULL; + struct pipe_box box; + + /* + * Note: we can't really implement this function with gallium as + * we did for swrast. We can't just map the resource and leave it + * mapped (and there's no OSMesaUnmapDepthBuffer() function) so + * we unmap the buffer here and return a 'stale' pointer. This should + * actually be OK in most cases where the caller of this function + * immediately uses the pointer. + */ + + u_box_2d(0, 0, res->width0, res->height0, &box); + + *buffer = pipe->transfer_map(pipe, res, 0, PIPE_TRANSFER_READ, &box, + &transfer); + if (!*buffer) { + return GL_FALSE; + } + + *width = res->width0; + *height = res->height0; + *bytesPerValue = util_format_get_blocksize(res->format); + + pipe->transfer_unmap(pipe, transfer); + + return GL_TRUE; +} + + +/** + * Return the color buffer associated with an OSMesa context. + * Input: c - the OSMesa context + * Output: width, height - size of buffer in pixels + * format - the pixel format (OSMESA_FORMAT) + * buffer - pointer to color buffer values + * Return: GL_TRUE or GL_FALSE to indicate success or failure. + */ +GLAPI GLboolean GLAPIENTRY +OSMesaGetColorBuffer(OSMesaContext osmesa, GLint *width, + GLint *height, GLint *format, void **buffer) +{ + struct osmesa_buffer *osbuffer = osmesa->current_buffer; + + if (osbuffer) { + *width = osbuffer->width; + *height = osbuffer->height; + *format = osmesa->format; + *buffer = osbuffer->map; + return GL_TRUE; + } + else { + *width = 0; + *height = 0; + *format = 0; + *buffer = 0; + return GL_FALSE; + } +} + + +struct name_function +{ + const char *Name; + OSMESAproc Function; +}; + +static struct name_function functions[] = { + { "OSMesaCreateContext", (OSMESAproc) OSMesaCreateContext }, + { "OSMesaCreateContextExt", (OSMESAproc) OSMesaCreateContextExt }, + { "OSMesaCreateContextAttribs", (OSMESAproc) OSMesaCreateContextAttribs }, + { "OSMesaDestroyContext", (OSMESAproc) OSMesaDestroyContext }, + { "OSMesaMakeCurrent", (OSMESAproc) OSMesaMakeCurrent }, + { "OSMesaGetCurrentContext", (OSMESAproc) OSMesaGetCurrentContext }, + { "OSMesaPixelStore", (OSMESAproc) OSMesaPixelStore }, + { "OSMesaGetIntegerv", (OSMESAproc) OSMesaGetIntegerv }, + { "OSMesaGetDepthBuffer", (OSMESAproc) OSMesaGetDepthBuffer }, + { "OSMesaGetColorBuffer", (OSMESAproc) OSMesaGetColorBuffer }, + { "OSMesaGetProcAddress", (OSMESAproc) OSMesaGetProcAddress }, + { "OSMesaColorClamp", (OSMESAproc) OSMesaColorClamp }, + { "OSMesaPostprocess", (OSMESAproc) OSMesaPostprocess }, + { NULL, NULL } +}; + + +GLAPI OSMESAproc GLAPIENTRY +OSMesaGetProcAddress(const char *funcName) +{ + int i; + for (i = 0; functions[i].Name; i++) { + if (strcmp(functions[i].Name, funcName) == 0) + return functions[i].Function; + } + return _glapi_get_proc_address(funcName); +} + + +GLAPI void GLAPIENTRY +OSMesaColorClamp(GLboolean enable) +{ + extern void GLAPIENTRY _mesa_ClampColor(GLenum target, GLenum clamp); + + _mesa_ClampColor(GL_CLAMP_FRAGMENT_COLOR_ARB, + enable ? GL_TRUE : GL_FIXED_ONLY_ARB); +} + + +GLAPI void GLAPIENTRY +OSMesaPostprocess(OSMesaContext osmesa, const char *filter, + unsigned enable_value) +{ + if (!osmesa->ever_used) { + /* We can only enable/disable postprocess filters before a context + * is made current for the first time. + */ + unsigned i; + + for (i = 0; i < PP_FILTERS; i++) { + if (strcmp(pp_filters[i].name, filter) == 0) { + osmesa->pp_enabled[i] = enable_value; + return; + } + } + debug_warning("OSMesaPostprocess(unknown filter)\n"); + } + else { + debug_warning("Calling OSMesaPostprocess() after OSMesaMakeCurrent()\n"); + } +} diff --git a/src/gallium/frontends/va/Makefile.sources b/src/gallium/frontends/va/Makefile.sources new file mode 100644 index 00000000000..bd43100a870 --- /dev/null +++ b/src/gallium/frontends/va/Makefile.sources @@ -0,0 +1,20 @@ +C_SOURCES := \ + buffer.c \ + config.c \ + context.c \ + display.c \ + image.c \ + picture.c \ + picture_mpeg12.c \ + picture_mpeg4.c \ + picture_h264.c \ + picture_h264_enc.c \ + picture_hevc.c \ + picture_hevc_enc.c \ + picture_vc1.c \ + picture_mjpeg.c \ + picture_vp9.c \ + postproc.c \ + subpicture.c \ + surface.c \ + va_private.h diff --git a/src/gallium/frontends/va/buffer.c b/src/gallium/frontends/va/buffer.c new file mode 100644 index 00000000000..5ab90186a1a --- /dev/null +++ b/src/gallium/frontends/va/buffer.c @@ -0,0 +1,373 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian. + * Copyright 2014 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "pipe/p_screen.h" +#include "frontend/drm_driver.h" +#include "util/u_memory.h" +#include "util/u_handle_table.h" +#include "util/u_transfer.h" +#include "vl/vl_winsys.h" + +#include "va_private.h" + +VAStatus +vlVaCreateBuffer(VADriverContextP ctx, VAContextID context, VABufferType type, + unsigned int size, unsigned int num_elements, void *data, + VABufferID *buf_id) +{ + vlVaDriver *drv; + vlVaBuffer *buf; + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + buf = CALLOC(1, sizeof(vlVaBuffer)); + if (!buf) + return VA_STATUS_ERROR_ALLOCATION_FAILED; + + buf->type = type; + buf->size = size; + buf->num_elements = num_elements; + buf->data = MALLOC(size * num_elements); + + if (!buf->data) { + FREE(buf); + return VA_STATUS_ERROR_ALLOCATION_FAILED; + } + + if (data) + memcpy(buf->data, data, size * num_elements); + + drv = VL_VA_DRIVER(ctx); + mtx_lock(&drv->mutex); + *buf_id = handle_table_add(drv->htab, buf); + mtx_unlock(&drv->mutex); + + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaBufferSetNumElements(VADriverContextP ctx, VABufferID buf_id, + unsigned int num_elements) +{ + vlVaDriver *drv; + vlVaBuffer *buf; + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + drv = VL_VA_DRIVER(ctx); + mtx_lock(&drv->mutex); + buf = handle_table_get(drv->htab, buf_id); + mtx_unlock(&drv->mutex); + if (!buf) + return VA_STATUS_ERROR_INVALID_BUFFER; + + if (buf->derived_surface.resource) + return VA_STATUS_ERROR_INVALID_BUFFER; + + buf->data = REALLOC(buf->data, buf->size * buf->num_elements, + buf->size * num_elements); + buf->num_elements = num_elements; + + if (!buf->data) + return VA_STATUS_ERROR_ALLOCATION_FAILED; + + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaMapBuffer(VADriverContextP ctx, VABufferID buf_id, void **pbuff) +{ + vlVaDriver *drv; + vlVaBuffer *buf; + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + drv = VL_VA_DRIVER(ctx); + if (!drv) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + if (!pbuff) + return VA_STATUS_ERROR_INVALID_PARAMETER; + + mtx_lock(&drv->mutex); + buf = handle_table_get(drv->htab, buf_id); + if (!buf || buf->export_refcount > 0) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_INVALID_BUFFER; + } + + if (buf->derived_surface.resource) { + struct pipe_resource *resource; + struct pipe_box box = {}; + + resource = buf->derived_surface.resource; + box.width = resource->width0; + box.height = resource->height0; + box.depth = resource->depth0; + *pbuff = drv->pipe->transfer_map(drv->pipe, resource, 0, PIPE_TRANSFER_WRITE, + &box, &buf->derived_surface.transfer); + mtx_unlock(&drv->mutex); + + if (!buf->derived_surface.transfer || !*pbuff) + return VA_STATUS_ERROR_INVALID_BUFFER; + + if (buf->type == VAEncCodedBufferType) { + ((VACodedBufferSegment*)buf->data)->buf = *pbuff; + ((VACodedBufferSegment*)buf->data)->size = buf->coded_size; + ((VACodedBufferSegment*)buf->data)->next = NULL; + *pbuff = buf->data; + } + } else { + mtx_unlock(&drv->mutex); + *pbuff = buf->data; + } + + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaUnmapBuffer(VADriverContextP ctx, VABufferID buf_id) +{ + vlVaDriver *drv; + vlVaBuffer *buf; + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + drv = VL_VA_DRIVER(ctx); + if (!drv) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + mtx_lock(&drv->mutex); + buf = handle_table_get(drv->htab, buf_id); + if (!buf || buf->export_refcount > 0) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_INVALID_BUFFER; + } + + if (buf->derived_surface.resource) { + if (!buf->derived_surface.transfer) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_INVALID_BUFFER; + } + + pipe_buffer_unmap(drv->pipe, buf->derived_surface.transfer); + buf->derived_surface.transfer = NULL; + } + mtx_unlock(&drv->mutex); + + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaDestroyBuffer(VADriverContextP ctx, VABufferID buf_id) +{ + vlVaDriver *drv; + vlVaBuffer *buf; + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + drv = VL_VA_DRIVER(ctx); + mtx_lock(&drv->mutex); + buf = handle_table_get(drv->htab, buf_id); + if (!buf) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_INVALID_BUFFER; + } + + if (buf->derived_surface.resource) + pipe_resource_reference(&buf->derived_surface.resource, NULL); + + FREE(buf->data); + FREE(buf); + handle_table_remove(VL_VA_DRIVER(ctx)->htab, buf_id); + mtx_unlock(&drv->mutex); + + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaBufferInfo(VADriverContextP ctx, VABufferID buf_id, VABufferType *type, + unsigned int *size, unsigned int *num_elements) +{ + vlVaDriver *drv; + vlVaBuffer *buf; + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + drv = VL_VA_DRIVER(ctx); + mtx_lock(&drv->mutex); + buf = handle_table_get(drv->htab, buf_id); + mtx_unlock(&drv->mutex); + if (!buf) + return VA_STATUS_ERROR_INVALID_BUFFER; + + *type = buf->type; + *size = buf->size; + *num_elements = buf->num_elements; + + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaAcquireBufferHandle(VADriverContextP ctx, VABufferID buf_id, + VABufferInfo *out_buf_info) +{ + vlVaDriver *drv; + uint32_t i; + uint32_t mem_type; + vlVaBuffer *buf ; + struct pipe_screen *screen; + + /* List of supported memory types, in preferred order. */ + static const uint32_t mem_types[] = { + VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME, + 0 + }; + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + drv = VL_VA_DRIVER(ctx); + screen = VL_VA_PSCREEN(ctx); + mtx_lock(&drv->mutex); + buf = handle_table_get(VL_VA_DRIVER(ctx)->htab, buf_id); + mtx_unlock(&drv->mutex); + + if (!buf) + return VA_STATUS_ERROR_INVALID_BUFFER; + + /* Only VA surface|image like buffers are supported for now .*/ + if (buf->type != VAImageBufferType) + return VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE; + + if (!out_buf_info) + return VA_STATUS_ERROR_INVALID_PARAMETER; + + if (!out_buf_info->mem_type) + mem_type = mem_types[0]; + else { + mem_type = 0; + for (i = 0; mem_types[i] != 0; i++) { + if (out_buf_info->mem_type & mem_types[i]) { + mem_type = out_buf_info->mem_type; + break; + } + } + if (!mem_type) + return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE; + } + + if (!buf->derived_surface.resource) + return VA_STATUS_ERROR_INVALID_BUFFER; + + if (buf->export_refcount > 0) { + if (buf->export_state.mem_type != mem_type) + return VA_STATUS_ERROR_INVALID_PARAMETER; + } else { + VABufferInfo * const buf_info = &buf->export_state; + + switch (mem_type) { + case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME: { + struct winsys_handle whandle; + + mtx_lock(&drv->mutex); + drv->pipe->flush(drv->pipe, NULL, 0); + + memset(&whandle, 0, sizeof(whandle)); + whandle.type = WINSYS_HANDLE_TYPE_FD; + + if (!screen->resource_get_handle(screen, drv->pipe, + buf->derived_surface.resource, + &whandle, PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE)) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_INVALID_BUFFER; + } + + mtx_unlock(&drv->mutex); + + buf_info->handle = (intptr_t)whandle.handle; + break; + } + default: + return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE; + } + + buf_info->type = buf->type; + buf_info->mem_type = mem_type; + buf_info->mem_size = buf->num_elements * buf->size; + } + + buf->export_refcount++; + + *out_buf_info = buf->export_state; + + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaReleaseBufferHandle(VADriverContextP ctx, VABufferID buf_id) +{ + vlVaDriver *drv; + vlVaBuffer *buf; + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + drv = VL_VA_DRIVER(ctx); + mtx_lock(&drv->mutex); + buf = handle_table_get(drv->htab, buf_id); + mtx_unlock(&drv->mutex); + + if (!buf) + return VA_STATUS_ERROR_INVALID_BUFFER; + + if (buf->export_refcount == 0) + return VA_STATUS_ERROR_INVALID_BUFFER; + + if (--buf->export_refcount == 0) { + VABufferInfo * const buf_info = &buf->export_state; + + switch (buf_info->mem_type) { + case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME: + close((intptr_t)buf_info->handle); + break; + default: + return VA_STATUS_ERROR_INVALID_BUFFER; + } + + buf_info->mem_type = 0; + } + + return VA_STATUS_SUCCESS; +} diff --git a/src/gallium/frontends/va/config.c b/src/gallium/frontends/va/config.c new file mode 100644 index 00000000000..294cbcc6418 --- /dev/null +++ b/src/gallium/frontends/va/config.c @@ -0,0 +1,382 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian. + * Copyright 2014 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "pipe/p_screen.h" + +#include "util/u_video.h" +#include "util/u_memory.h" + +#include "vl/vl_winsys.h" + +#include "va_private.h" + +#include "util/u_handle_table.h" + +DEBUG_GET_ONCE_BOOL_OPTION(mpeg4, "VAAPI_MPEG4_ENABLED", false) + +VAStatus +vlVaQueryConfigProfiles(VADriverContextP ctx, VAProfile *profile_list, int *num_profiles) +{ + struct pipe_screen *pscreen; + enum pipe_video_profile p; + VAProfile vap; + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + *num_profiles = 0; + + pscreen = VL_VA_PSCREEN(ctx); + for (p = PIPE_VIDEO_PROFILE_MPEG2_SIMPLE; p <= PIPE_VIDEO_PROFILE_VP9_PROFILE2; ++p) { + if (u_reduce_video_profile(p) == PIPE_VIDEO_FORMAT_MPEG4 && !debug_get_option_mpeg4()) + continue; + + if (pscreen->get_video_param(pscreen, p, PIPE_VIDEO_ENTRYPOINT_BITSTREAM, PIPE_VIDEO_CAP_SUPPORTED)) { + vap = PipeToProfile(p); + if (vap != VAProfileNone) + profile_list[(*num_profiles)++] = vap; + } + } + + /* Support postprocessing through vl_compositor */ + profile_list[(*num_profiles)++] = VAProfileNone; + + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaQueryConfigEntrypoints(VADriverContextP ctx, VAProfile profile, + VAEntrypoint *entrypoint_list, int *num_entrypoints) +{ + struct pipe_screen *pscreen; + enum pipe_video_profile p; + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + *num_entrypoints = 0; + + if (profile == VAProfileNone) { + entrypoint_list[(*num_entrypoints)++] = VAEntrypointVideoProc; + return VA_STATUS_SUCCESS; + } + + p = ProfileToPipe(profile); + if (p == PIPE_VIDEO_PROFILE_UNKNOWN) + return VA_STATUS_ERROR_UNSUPPORTED_PROFILE; + + pscreen = VL_VA_PSCREEN(ctx); + if (pscreen->get_video_param(pscreen, p, PIPE_VIDEO_ENTRYPOINT_BITSTREAM, + PIPE_VIDEO_CAP_SUPPORTED)) + entrypoint_list[(*num_entrypoints)++] = VAEntrypointVLD; + + if (pscreen->get_video_param(pscreen, p, PIPE_VIDEO_ENTRYPOINT_ENCODE, + PIPE_VIDEO_CAP_SUPPORTED)) + entrypoint_list[(*num_entrypoints)++] = VAEntrypointEncSlice; + + if (num_entrypoints == 0) + return VA_STATUS_ERROR_UNSUPPORTED_PROFILE; + + assert(*num_entrypoints <= ctx->max_entrypoints); + + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaGetConfigAttributes(VADriverContextP ctx, VAProfile profile, VAEntrypoint entrypoint, + VAConfigAttrib *attrib_list, int num_attribs) +{ + struct pipe_screen *pscreen; + int i; + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + pscreen = VL_VA_PSCREEN(ctx); + + for (i = 0; i < num_attribs; ++i) { + unsigned int value; + if ((entrypoint == VAEntrypointVLD) && + (pscreen->get_video_param(pscreen, ProfileToPipe(profile), + PIPE_VIDEO_ENTRYPOINT_BITSTREAM, PIPE_VIDEO_CAP_SUPPORTED))) { + switch (attrib_list[i].type) { + case VAConfigAttribRTFormat: + value = VA_RT_FORMAT_YUV420 | VA_RT_FORMAT_YUV422; + if (pscreen->is_video_format_supported(pscreen, PIPE_FORMAT_P010, + ProfileToPipe(profile), + PIPE_VIDEO_ENTRYPOINT_BITSTREAM) || + pscreen->is_video_format_supported(pscreen, PIPE_FORMAT_P016, + ProfileToPipe(profile), + PIPE_VIDEO_ENTRYPOINT_BITSTREAM)) + value |= VA_RT_FORMAT_YUV420_10BPP; + break; + default: + value = VA_ATTRIB_NOT_SUPPORTED; + break; + } + } else if ((entrypoint == VAEntrypointEncSlice) && + (pscreen->get_video_param(pscreen, ProfileToPipe(profile), + PIPE_VIDEO_ENTRYPOINT_ENCODE, PIPE_VIDEO_CAP_SUPPORTED))) { + switch (attrib_list[i].type) { + case VAConfigAttribRTFormat: + value = VA_RT_FORMAT_YUV420; + if (pscreen->is_video_format_supported(pscreen, PIPE_FORMAT_P010, + ProfileToPipe(profile), + PIPE_VIDEO_ENTRYPOINT_BITSTREAM) || + pscreen->is_video_format_supported(pscreen, PIPE_FORMAT_P016, + ProfileToPipe(profile), + PIPE_VIDEO_ENTRYPOINT_BITSTREAM)) + value |= VA_RT_FORMAT_YUV420_10BPP; + break; + case VAConfigAttribRateControl: + value = VA_RC_CQP | VA_RC_CBR | VA_RC_VBR; + break; + case VAConfigAttribEncPackedHeaders: + value = 0; + break; + case VAConfigAttribEncMaxRefFrames: + value = 1; + break; + default: + value = VA_ATTRIB_NOT_SUPPORTED; + break; + } + } else if (entrypoint == VAEntrypointVideoProc) { + switch (attrib_list[i].type) { + case VAConfigAttribRTFormat: + value = (VA_RT_FORMAT_YUV420 | + VA_RT_FORMAT_YUV420_10BPP | + VA_RT_FORMAT_RGB32); + break; + default: + value = VA_ATTRIB_NOT_SUPPORTED; + break; + } + } else { + value = VA_ATTRIB_NOT_SUPPORTED; + } + attrib_list[i].value = value; + } + + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaCreateConfig(VADriverContextP ctx, VAProfile profile, VAEntrypoint entrypoint, + VAConfigAttrib *attrib_list, int num_attribs, VAConfigID *config_id) +{ + vlVaDriver *drv; + vlVaConfig *config; + struct pipe_screen *pscreen; + enum pipe_video_profile p; + unsigned int supported_rt_formats; + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + drv = VL_VA_DRIVER(ctx); + + if (!drv) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + config = CALLOC(1, sizeof(vlVaConfig)); + if (!config) + return VA_STATUS_ERROR_ALLOCATION_FAILED; + + if (profile == VAProfileNone && entrypoint == VAEntrypointVideoProc) { + config->entrypoint = PIPE_VIDEO_ENTRYPOINT_UNKNOWN; + config->profile = PIPE_VIDEO_PROFILE_UNKNOWN; + supported_rt_formats = VA_RT_FORMAT_YUV420 | + VA_RT_FORMAT_YUV420_10BPP | + VA_RT_FORMAT_RGB32; + for (int i = 0; i < num_attribs; i++) { + if (attrib_list[i].type == VAConfigAttribRTFormat) { + if (attrib_list[i].value & supported_rt_formats) { + config->rt_format = attrib_list[i].value; + } else { + FREE(config); + return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT; + } + } + } + + /* Default value if not specified in the input attributes. */ + if (!config->rt_format) + config->rt_format = supported_rt_formats; + + mtx_lock(&drv->mutex); + *config_id = handle_table_add(drv->htab, config); + mtx_unlock(&drv->mutex); + return VA_STATUS_SUCCESS; + } + + p = ProfileToPipe(profile); + if (p == PIPE_VIDEO_PROFILE_UNKNOWN) { + FREE(config); + return VA_STATUS_ERROR_UNSUPPORTED_PROFILE; + } + + pscreen = VL_VA_PSCREEN(ctx); + + switch (entrypoint) { + case VAEntrypointVLD: + if (!pscreen->get_video_param(pscreen, p, PIPE_VIDEO_ENTRYPOINT_BITSTREAM, + PIPE_VIDEO_CAP_SUPPORTED)) { + FREE(config); + return VA_STATUS_ERROR_UNSUPPORTED_PROFILE; + } + + config->entrypoint = PIPE_VIDEO_ENTRYPOINT_BITSTREAM; + break; + + case VAEntrypointEncSlice: + if (!pscreen->get_video_param(pscreen, p, PIPE_VIDEO_ENTRYPOINT_ENCODE, + PIPE_VIDEO_CAP_SUPPORTED)) { + FREE(config); + return VA_STATUS_ERROR_UNSUPPORTED_PROFILE; + } + + config->entrypoint = PIPE_VIDEO_ENTRYPOINT_ENCODE; + break; + + default: + FREE(config); + return VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT; + } + + config->profile = p; + supported_rt_formats = VA_RT_FORMAT_YUV420 | VA_RT_FORMAT_YUV422; + if (pscreen->is_video_format_supported(pscreen, PIPE_FORMAT_P010, p, + config->entrypoint) || + pscreen->is_video_format_supported(pscreen, PIPE_FORMAT_P016, p, + config->entrypoint)) + supported_rt_formats |= VA_RT_FORMAT_YUV420_10BPP; + + for (int i = 0; i rc = PIPE_H264_ENC_RATE_CONTROL_METHOD_CONSTANT; + else if (attrib_list[i].value == VA_RC_VBR) + config->rc = PIPE_H264_ENC_RATE_CONTROL_METHOD_VARIABLE; + else + config->rc = PIPE_H264_ENC_RATE_CONTROL_METHOD_DISABLE; + } + if (attrib_list[i].type == VAConfigAttribRTFormat) { + if (attrib_list[i].value & supported_rt_formats) { + config->rt_format = attrib_list[i].value; + } else { + FREE(config); + return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT; + } + } + } + + /* Default value if not specified in the input attributes. */ + if (!config->rt_format) + config->rt_format = supported_rt_formats; + + mtx_lock(&drv->mutex); + *config_id = handle_table_add(drv->htab, config); + mtx_unlock(&drv->mutex); + + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaDestroyConfig(VADriverContextP ctx, VAConfigID config_id) +{ + vlVaDriver *drv; + vlVaConfig *config; + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + drv = VL_VA_DRIVER(ctx); + + if (!drv) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + mtx_lock(&drv->mutex); + config = handle_table_get(drv->htab, config_id); + + if (!config) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_INVALID_CONFIG; + } + + FREE(config); + handle_table_remove(drv->htab, config_id); + mtx_unlock(&drv->mutex); + + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaQueryConfigAttributes(VADriverContextP ctx, VAConfigID config_id, VAProfile *profile, + VAEntrypoint *entrypoint, VAConfigAttrib *attrib_list, int *num_attribs) +{ + vlVaDriver *drv; + vlVaConfig *config; + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + drv = VL_VA_DRIVER(ctx); + + if (!drv) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + mtx_lock(&drv->mutex); + config = handle_table_get(drv->htab, config_id); + mtx_unlock(&drv->mutex); + + if (!config) + return VA_STATUS_ERROR_INVALID_CONFIG; + + *profile = PipeToProfile(config->profile); + + switch (config->entrypoint) { + case PIPE_VIDEO_ENTRYPOINT_BITSTREAM: + *entrypoint = VAEntrypointVLD; + break; + case PIPE_VIDEO_ENTRYPOINT_ENCODE: + *entrypoint = VAEntrypointEncSlice; + break; + case PIPE_VIDEO_ENTRYPOINT_UNKNOWN: + *entrypoint = VAEntrypointVideoProc; + break; + default: + return VA_STATUS_ERROR_INVALID_CONFIG; + } + + *num_attribs = 1; + attrib_list[0].type = VAConfigAttribRTFormat; + attrib_list[0].value = config->rt_format; + + return VA_STATUS_SUCCESS; +} diff --git a/src/gallium/frontends/va/context.c b/src/gallium/frontends/va/context.c new file mode 100644 index 00000000000..0c596f3f811 --- /dev/null +++ b/src/gallium/frontends/va/context.c @@ -0,0 +1,397 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian. + * Copyright 2014 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "pipe/p_screen.h" +#include "pipe/p_video_codec.h" +#include "util/u_memory.h" +#include "util/u_handle_table.h" +#include "util/u_video.h" +#include "vl/vl_deint_filter.h" +#include "vl/vl_winsys.h" + +#include "va_private.h" + +#include + +static struct VADriverVTable vtable = +{ + &vlVaTerminate, + &vlVaQueryConfigProfiles, + &vlVaQueryConfigEntrypoints, + &vlVaGetConfigAttributes, + &vlVaCreateConfig, + &vlVaDestroyConfig, + &vlVaQueryConfigAttributes, + &vlVaCreateSurfaces, + &vlVaDestroySurfaces, + &vlVaCreateContext, + &vlVaDestroyContext, + &vlVaCreateBuffer, + &vlVaBufferSetNumElements, + &vlVaMapBuffer, + &vlVaUnmapBuffer, + &vlVaDestroyBuffer, + &vlVaBeginPicture, + &vlVaRenderPicture, + &vlVaEndPicture, + &vlVaSyncSurface, + &vlVaQuerySurfaceStatus, + &vlVaQuerySurfaceError, + &vlVaPutSurface, + &vlVaQueryImageFormats, + &vlVaCreateImage, + &vlVaDeriveImage, + &vlVaDestroyImage, + &vlVaSetImagePalette, + &vlVaGetImage, + &vlVaPutImage, + &vlVaQuerySubpictureFormats, + &vlVaCreateSubpicture, + &vlVaDestroySubpicture, + &vlVaSubpictureImage, + &vlVaSetSubpictureChromakey, + &vlVaSetSubpictureGlobalAlpha, + &vlVaAssociateSubpicture, + &vlVaDeassociateSubpicture, + &vlVaQueryDisplayAttributes, + &vlVaGetDisplayAttributes, + &vlVaSetDisplayAttributes, + &vlVaBufferInfo, + &vlVaLockSurface, + &vlVaUnlockSurface, + NULL, /* DEPRECATED VaGetSurfaceAttributes */ + &vlVaCreateSurfaces2, + &vlVaQuerySurfaceAttributes, + &vlVaAcquireBufferHandle, + &vlVaReleaseBufferHandle, +#if VA_CHECK_VERSION(1, 1, 0) + NULL, /* vaCreateMFContext */ + NULL, /* vaMFAddContext */ + NULL, /* vaMFReleaseContext */ + NULL, /* vaMFSubmit */ + NULL, /* vaCreateBuffer2 */ + NULL, /* vaQueryProcessingRate */ + &vlVaExportSurfaceHandle, +#endif +}; + +static struct VADriverVTableVPP vtable_vpp = +{ + 1, + &vlVaQueryVideoProcFilters, + &vlVaQueryVideoProcFilterCaps, + &vlVaQueryVideoProcPipelineCaps +}; + +PUBLIC VAStatus +VA_DRIVER_INIT_FUNC(VADriverContextP ctx) +{ + vlVaDriver *drv; + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + drv = CALLOC(1, sizeof(vlVaDriver)); + if (!drv) + return VA_STATUS_ERROR_ALLOCATION_FAILED; + + switch (ctx->display_type) { + case VA_DISPLAY_ANDROID: + FREE(drv); + return VA_STATUS_ERROR_UNIMPLEMENTED; + case VA_DISPLAY_GLX: + case VA_DISPLAY_X11: + drv->vscreen = vl_dri3_screen_create(ctx->native_dpy, ctx->x11_screen); + if (!drv->vscreen) + drv->vscreen = vl_dri2_screen_create(ctx->native_dpy, ctx->x11_screen); + break; + case VA_DISPLAY_WAYLAND: + case VA_DISPLAY_DRM: + case VA_DISPLAY_DRM_RENDERNODES: { + const struct drm_state *drm_info = (struct drm_state *) ctx->drm_state; + + if (!drm_info || drm_info->fd < 0) { + FREE(drv); + return VA_STATUS_ERROR_INVALID_PARAMETER; + } + + drv->vscreen = vl_drm_screen_create(drm_info->fd); + break; + } + default: + FREE(drv); + return VA_STATUS_ERROR_INVALID_DISPLAY; + } + + if (!drv->vscreen) + goto error_screen; + + drv->pipe = pipe_create_multimedia_context(drv->vscreen->pscreen); + if (!drv->pipe) + goto error_pipe; + + drv->htab = handle_table_create(); + if (!drv->htab) + goto error_htab; + + if (!vl_compositor_init(&drv->compositor, drv->pipe)) + goto error_compositor; + if (!vl_compositor_init_state(&drv->cstate, drv->pipe)) + goto error_compositor_state; + + vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601, NULL, true, &drv->csc); + if (!vl_compositor_set_csc_matrix(&drv->cstate, (const vl_csc_matrix *)&drv->csc, 1.0f, 0.0f)) + goto error_csc_matrix; + (void) mtx_init(&drv->mutex, mtx_plain); + + ctx->pDriverData = (void *)drv; + ctx->version_major = 0; + ctx->version_minor = 1; + *ctx->vtable = vtable; + *ctx->vtable_vpp = vtable_vpp; + ctx->max_profiles = PIPE_VIDEO_PROFILE_MAX - PIPE_VIDEO_PROFILE_UNKNOWN - 1; + ctx->max_entrypoints = 2; + ctx->max_attributes = 1; + ctx->max_image_formats = VL_VA_MAX_IMAGE_FORMATS; + ctx->max_subpic_formats = 1; + ctx->max_display_attributes = 1; + + snprintf(drv->vendor_string, sizeof(drv->vendor_string), + "Mesa Gallium driver " PACKAGE_VERSION " for %s", + drv->vscreen->pscreen->get_name(drv->vscreen->pscreen)); + ctx->str_vendor = drv->vendor_string; + + return VA_STATUS_SUCCESS; + +error_csc_matrix: + vl_compositor_cleanup_state(&drv->cstate); + +error_compositor_state: + vl_compositor_cleanup(&drv->compositor); + +error_compositor: + handle_table_destroy(drv->htab); + +error_htab: + drv->pipe->destroy(drv->pipe); + +error_pipe: + drv->vscreen->destroy(drv->vscreen); + +error_screen: + FREE(drv); + return VA_STATUS_ERROR_ALLOCATION_FAILED; +} + +VAStatus +vlVaCreateContext(VADriverContextP ctx, VAConfigID config_id, int picture_width, + int picture_height, int flag, VASurfaceID *render_targets, + int num_render_targets, VAContextID *context_id) +{ + vlVaDriver *drv; + vlVaContext *context; + vlVaConfig *config; + int is_vpp; + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + drv = VL_VA_DRIVER(ctx); + mtx_lock(&drv->mutex); + config = handle_table_get(drv->htab, config_id); + mtx_unlock(&drv->mutex); + + is_vpp = config->profile == PIPE_VIDEO_PROFILE_UNKNOWN && !picture_width && + !picture_height && !flag && !render_targets && !num_render_targets; + + if (!(picture_width && picture_height) && !is_vpp) + return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT; + + context = CALLOC(1, sizeof(vlVaContext)); + if (!context) + return VA_STATUS_ERROR_ALLOCATION_FAILED; + + if (is_vpp) { + context->decoder = NULL; + } else { + context->templat.profile = config->profile; + context->templat.entrypoint = config->entrypoint; + context->templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; + context->templat.width = picture_width; + context->templat.height = picture_height; + context->templat.expect_chunked_decode = true; + + switch (u_reduce_video_profile(context->templat.profile)) { + case PIPE_VIDEO_FORMAT_MPEG12: + case PIPE_VIDEO_FORMAT_VC1: + case PIPE_VIDEO_FORMAT_MPEG4: + context->templat.max_references = 2; + break; + + case PIPE_VIDEO_FORMAT_MPEG4_AVC: + context->templat.max_references = 0; + if (config->entrypoint != PIPE_VIDEO_ENTRYPOINT_ENCODE) { + context->desc.h264.pps = CALLOC_STRUCT(pipe_h264_pps); + if (!context->desc.h264.pps) { + FREE(context); + return VA_STATUS_ERROR_ALLOCATION_FAILED; + } + context->desc.h264.pps->sps = CALLOC_STRUCT(pipe_h264_sps); + if (!context->desc.h264.pps->sps) { + FREE(context->desc.h264.pps); + FREE(context); + return VA_STATUS_ERROR_ALLOCATION_FAILED; + } + } + break; + + case PIPE_VIDEO_FORMAT_HEVC: + context->templat.max_references = num_render_targets; + if (config->entrypoint != PIPE_VIDEO_ENTRYPOINT_ENCODE) { + context->desc.h265.pps = CALLOC_STRUCT(pipe_h265_pps); + if (!context->desc.h265.pps) { + FREE(context); + return VA_STATUS_ERROR_ALLOCATION_FAILED; + } + context->desc.h265.pps->sps = CALLOC_STRUCT(pipe_h265_sps); + if (!context->desc.h265.pps->sps) { + FREE(context->desc.h265.pps); + FREE(context); + return VA_STATUS_ERROR_ALLOCATION_FAILED; + } + } + break; + + case PIPE_VIDEO_FORMAT_VP9: + context->templat.max_references = num_render_targets; + break; + + default: + break; + } + } + + context->desc.base.profile = config->profile; + context->desc.base.entry_point = config->entrypoint; + if (config->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) { + switch (u_reduce_video_profile(context->templat.profile)) { + case PIPE_VIDEO_FORMAT_MPEG4_AVC: + context->desc.h264enc.rate_ctrl.rate_ctrl_method = config->rc; + context->desc.h264enc.frame_idx = util_hash_table_create_ptr_keys(); + break; + case PIPE_VIDEO_FORMAT_HEVC: + context->desc.h265enc.rc.rate_ctrl_method = config->rc; + context->desc.h265enc.frame_idx = util_hash_table_create_ptr_keys(); + break; + default: + break; + } + } + + mtx_lock(&drv->mutex); + *context_id = handle_table_add(drv->htab, context); + mtx_unlock(&drv->mutex); + + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaDestroyContext(VADriverContextP ctx, VAContextID context_id) +{ + vlVaDriver *drv; + vlVaContext *context; + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + drv = VL_VA_DRIVER(ctx); + mtx_lock(&drv->mutex); + context = handle_table_get(drv->htab, context_id); + if (!context) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_INVALID_CONTEXT; + } + + if (context->decoder) { + if (context->desc.base.entry_point == PIPE_VIDEO_ENTRYPOINT_ENCODE) { + if (u_reduce_video_profile(context->decoder->profile) == + PIPE_VIDEO_FORMAT_MPEG4_AVC) { + if (context->desc.h264enc.frame_idx) + _mesa_hash_table_destroy(context->desc.h264enc.frame_idx, NULL); + } + if (u_reduce_video_profile(context->decoder->profile) == + PIPE_VIDEO_FORMAT_HEVC) { + if (context->desc.h265enc.frame_idx) + _mesa_hash_table_destroy(context->desc.h265enc.frame_idx, NULL); + } + } else { + if (u_reduce_video_profile(context->decoder->profile) == + PIPE_VIDEO_FORMAT_MPEG4_AVC) { + FREE(context->desc.h264.pps->sps); + FREE(context->desc.h264.pps); + } + if (u_reduce_video_profile(context->decoder->profile) == + PIPE_VIDEO_FORMAT_HEVC) { + FREE(context->desc.h265.pps->sps); + FREE(context->desc.h265.pps); + } + } + context->decoder->destroy(context->decoder); + } + if (context->blit_cs) + drv->pipe->delete_compute_state(drv->pipe, context->blit_cs); + if (context->deint) { + vl_deint_filter_cleanup(context->deint); + FREE(context->deint); + } + FREE(context); + handle_table_remove(drv->htab, context_id); + mtx_unlock(&drv->mutex); + + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaTerminate(VADriverContextP ctx) +{ + vlVaDriver *drv; + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + drv = ctx->pDriverData; + vl_compositor_cleanup_state(&drv->cstate); + vl_compositor_cleanup(&drv->compositor); + drv->pipe->destroy(drv->pipe); + drv->vscreen->destroy(drv->vscreen); + handle_table_destroy(drv->htab); + mtx_destroy(&drv->mutex); + FREE(drv); + + return VA_STATUS_SUCCESS; +} diff --git a/src/gallium/frontends/va/display.c b/src/gallium/frontends/va/display.c new file mode 100644 index 00000000000..3d0fe09ca61 --- /dev/null +++ b/src/gallium/frontends/va/display.c @@ -0,0 +1,61 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian. + * Copyright 2014 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "va_private.h" + +VAStatus +vlVaQueryDisplayAttributes(VADriverContextP ctx, VADisplayAttribute *attr_list, int *num_attributes) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + if (!(attr_list && num_attributes)) + return VA_STATUS_ERROR_UNKNOWN; + + *num_attributes = 0; + + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaGetDisplayAttributes(VADriverContextP ctx, VADisplayAttribute *attr_list, int num_attributes) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus +vlVaSetDisplayAttributes(VADriverContextP ctx, VADisplayAttribute *attr_list, int num_attributes) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} diff --git a/src/gallium/frontends/va/image.c b/src/gallium/frontends/va/image.c new file mode 100644 index 00000000000..3a6a7e83d14 --- /dev/null +++ b/src/gallium/frontends/va/image.c @@ -0,0 +1,628 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian. + * Copyright 2014 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "pipe/p_screen.h" + +#include "util/u_memory.h" +#include "util/u_handle_table.h" +#include "util/u_surface.h" +#include "util/u_video.h" + +#include "vl/vl_winsys.h" +#include "vl/vl_video_buffer.h" + +#include "va_private.h" + +static const VAImageFormat formats[] = +{ + {VA_FOURCC('N','V','1','2')}, + {VA_FOURCC('P','0','1','0')}, + {VA_FOURCC('P','0','1','6')}, + {VA_FOURCC('I','4','2','0')}, + {VA_FOURCC('Y','V','1','2')}, + {VA_FOURCC('Y','U','Y','V')}, + {VA_FOURCC('Y','U','Y','2')}, + {VA_FOURCC('U','Y','V','Y')}, + {.fourcc = VA_FOURCC('B','G','R','A'), .byte_order = VA_LSB_FIRST, 32, 32, + 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000}, + {.fourcc = VA_FOURCC('R','G','B','A'), .byte_order = VA_LSB_FIRST, 32, 32, + 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000}, + {.fourcc = VA_FOURCC('B','G','R','X'), .byte_order = VA_LSB_FIRST, 32, 24, + 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000}, + {.fourcc = VA_FOURCC('R','G','B','X'), .byte_order = VA_LSB_FIRST, 32, 24, + 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000} +}; + +static void +vlVaVideoSurfaceSize(vlVaSurface *p_surf, int component, + unsigned *width, unsigned *height) +{ + *width = p_surf->templat.width; + *height = p_surf->templat.height; + + vl_video_buffer_adjust_size(width, height, component, + pipe_format_to_chroma_format(p_surf->templat.buffer_format), + p_surf->templat.interlaced); +} + +VAStatus +vlVaQueryImageFormats(VADriverContextP ctx, VAImageFormat *format_list, int *num_formats) +{ + struct pipe_screen *pscreen; + enum pipe_format format; + int i; + + STATIC_ASSERT(ARRAY_SIZE(formats) == VL_VA_MAX_IMAGE_FORMATS); + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + if (!(format_list && num_formats)) + return VA_STATUS_ERROR_INVALID_PARAMETER; + + *num_formats = 0; + pscreen = VL_VA_PSCREEN(ctx); + for (i = 0; i < ARRAY_SIZE(formats); ++i) { + format = VaFourccToPipeFormat(formats[i].fourcc); + if (pscreen->is_video_format_supported(pscreen, format, + PIPE_VIDEO_PROFILE_UNKNOWN, + PIPE_VIDEO_ENTRYPOINT_BITSTREAM)) + format_list[(*num_formats)++] = formats[i]; + } + + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaCreateImage(VADriverContextP ctx, VAImageFormat *format, int width, int height, VAImage *image) +{ + VAStatus status; + vlVaDriver *drv; + VAImage *img; + int w, h; + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + if (!(format && image && width && height)) + return VA_STATUS_ERROR_INVALID_PARAMETER; + + drv = VL_VA_DRIVER(ctx); + + img = CALLOC(1, sizeof(VAImage)); + if (!img) + return VA_STATUS_ERROR_ALLOCATION_FAILED; + mtx_lock(&drv->mutex); + img->image_id = handle_table_add(drv->htab, img); + mtx_unlock(&drv->mutex); + + img->format = *format; + img->width = width; + img->height = height; + w = align(width, 2); + h = align(height, 2); + + switch (format->fourcc) { + case VA_FOURCC('N','V','1','2'): + img->num_planes = 2; + img->pitches[0] = w; + img->offsets[0] = 0; + img->pitches[1] = w; + img->offsets[1] = w * h; + img->data_size = w * h * 3 / 2; + break; + + case VA_FOURCC('P','0','1','0'): + case VA_FOURCC('P','0','1','6'): + img->num_planes = 2; + img->pitches[0] = w * 2; + img->offsets[0] = 0; + img->pitches[1] = w * 2; + img->offsets[1] = w * h * 2; + img->data_size = w * h * 3; + break; + + case VA_FOURCC('I','4','2','0'): + case VA_FOURCC('Y','V','1','2'): + img->num_planes = 3; + img->pitches[0] = w; + img->offsets[0] = 0; + img->pitches[1] = w / 2; + img->offsets[1] = w * h; + img->pitches[2] = w / 2; + img->offsets[2] = w * h * 5 / 4; + img->data_size = w * h * 3 / 2; + break; + + case VA_FOURCC('U','Y','V','Y'): + case VA_FOURCC('Y','U','Y','V'): + case VA_FOURCC('Y','U','Y','2'): + img->num_planes = 1; + img->pitches[0] = w * 2; + img->offsets[0] = 0; + img->data_size = w * h * 2; + break; + + case VA_FOURCC('B','G','R','A'): + case VA_FOURCC('R','G','B','A'): + case VA_FOURCC('B','G','R','X'): + case VA_FOURCC('R','G','B','X'): + img->num_planes = 1; + img->pitches[0] = w * 4; + img->offsets[0] = 0; + img->data_size = w * h * 4; + break; + + default: + return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT; + } + + status = vlVaCreateBuffer(ctx, 0, VAImageBufferType, + align(img->data_size, 16), + 1, NULL, &img->buf); + if (status != VA_STATUS_SUCCESS) + return status; + *image = *img; + + return status; +} + +VAStatus +vlVaDeriveImage(VADriverContextP ctx, VASurfaceID surface, VAImage *image) +{ + vlVaDriver *drv; + vlVaSurface *surf; + vlVaBuffer *img_buf; + VAImage *img; + struct pipe_screen *screen; + struct pipe_surface **surfaces; + int w; + int h; + int i; + unsigned stride = 0; + unsigned offset = 0; + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + drv = VL_VA_DRIVER(ctx); + + if (!drv) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + screen = VL_VA_PSCREEN(ctx); + + if (!screen) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + surf = handle_table_get(drv->htab, surface); + + if (!surf || !surf->buffer) + return VA_STATUS_ERROR_INVALID_SURFACE; + + if (surf->buffer->interlaced) + return VA_STATUS_ERROR_OPERATION_FAILED; + + surfaces = surf->buffer->get_surfaces(surf->buffer); + if (!surfaces || !surfaces[0]->texture) + return VA_STATUS_ERROR_ALLOCATION_FAILED; + + img = CALLOC(1, sizeof(VAImage)); + if (!img) + return VA_STATUS_ERROR_ALLOCATION_FAILED; + + img->format.fourcc = PipeFormatToVaFourcc(surf->buffer->buffer_format); + img->buf = VA_INVALID_ID; + /* Use the visible dimensions. */ + img->width = surf->templat.width; + img->height = surf->templat.height; + img->num_palette_entries = 0; + img->entry_bytes = 0; + /* Image data size is computed using internal dimensions. */ + w = align(surf->buffer->width, 2); + h = align(surf->buffer->height, 2); + + for (i = 0; i < ARRAY_SIZE(formats); ++i) { + if (img->format.fourcc == formats[i].fourcc) { + img->format = formats[i]; + break; + } + } + + mtx_lock(&drv->mutex); + if (screen->resource_get_info) { + screen->resource_get_info(screen, surfaces[0]->texture, &stride, + &offset); + if (!stride) + offset = 0; + } + + switch (img->format.fourcc) { + case VA_FOURCC('U','Y','V','Y'): + case VA_FOURCC('Y','U','Y','V'): + img->pitches[0] = stride > 0 ? stride : w * 2; + assert(img->pitches[0] >= (w * 2)); + break; + + case VA_FOURCC('B','G','R','A'): + case VA_FOURCC('R','G','B','A'): + case VA_FOURCC('B','G','R','X'): + case VA_FOURCC('R','G','B','X'): + img->pitches[0] = stride > 0 ? stride : w * 4; + assert(img->pitches[0] >= (w * 4)); + break; + + default: + /* VaDeriveImage only supports contiguous planes. But there is now a + more generic api vlVaExportSurfaceHandle. */ + FREE(img); + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_OPERATION_FAILED; + } + + img->num_planes = 1; + img->offsets[0] = offset; + img->data_size = img->pitches[0] * h; + + img_buf = CALLOC(1, sizeof(vlVaBuffer)); + if (!img_buf) { + FREE(img); + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_ALLOCATION_FAILED; + } + + img->image_id = handle_table_add(drv->htab, img); + + img_buf->type = VAImageBufferType; + img_buf->size = img->data_size; + img_buf->num_elements = 1; + + pipe_resource_reference(&img_buf->derived_surface.resource, surfaces[0]->texture); + + img->buf = handle_table_add(VL_VA_DRIVER(ctx)->htab, img_buf); + mtx_unlock(&drv->mutex); + + *image = *img; + + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaDestroyImage(VADriverContextP ctx, VAImageID image) +{ + vlVaDriver *drv; + VAImage *vaimage; + VAStatus status; + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + drv = VL_VA_DRIVER(ctx); + mtx_lock(&drv->mutex); + vaimage = handle_table_get(drv->htab, image); + if (!vaimage) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_INVALID_IMAGE; + } + + handle_table_remove(VL_VA_DRIVER(ctx)->htab, image); + mtx_unlock(&drv->mutex); + status = vlVaDestroyBuffer(ctx, vaimage->buf); + FREE(vaimage); + return status; +} + +VAStatus +vlVaSetImagePalette(VADriverContextP ctx, VAImageID image, unsigned char *palette) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus +vlVaGetImage(VADriverContextP ctx, VASurfaceID surface, int x, int y, + unsigned int width, unsigned int height, VAImageID image) +{ + vlVaDriver *drv; + vlVaSurface *surf; + vlVaBuffer *img_buf; + VAImage *vaimage; + struct pipe_sampler_view **views; + enum pipe_format format; + bool convert = false; + void *data[3]; + unsigned pitches[3], i, j; + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + drv = VL_VA_DRIVER(ctx); + + mtx_lock(&drv->mutex); + surf = handle_table_get(drv->htab, surface); + if (!surf || !surf->buffer) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_INVALID_SURFACE; + } + + vaimage = handle_table_get(drv->htab, image); + if (!vaimage) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_INVALID_IMAGE; + } + + if (x < 0 || y < 0) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_INVALID_PARAMETER; + } + + if (x + width > surf->templat.width || + y + height > surf->templat.height) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_INVALID_PARAMETER; + } + + if (width > vaimage->width || + height > vaimage->height) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_INVALID_PARAMETER; + } + + img_buf = handle_table_get(drv->htab, vaimage->buf); + if (!img_buf) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_INVALID_BUFFER; + } + + format = VaFourccToPipeFormat(vaimage->format.fourcc); + if (format == PIPE_FORMAT_NONE) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_OPERATION_FAILED; + } + + + if (format != surf->buffer->buffer_format) { + /* support NV12 to YV12 and IYUV conversion now only */ + if ((format == PIPE_FORMAT_YV12 && + surf->buffer->buffer_format == PIPE_FORMAT_NV12) || + (format == PIPE_FORMAT_IYUV && + surf->buffer->buffer_format == PIPE_FORMAT_NV12)) + convert = true; + else if (format == PIPE_FORMAT_NV12 && + (surf->buffer->buffer_format == PIPE_FORMAT_P010 || + surf->buffer->buffer_format == PIPE_FORMAT_P016)) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_OPERATION_FAILED; + } + else { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_OPERATION_FAILED; + } + } + + views = surf->buffer->get_sampler_view_planes(surf->buffer); + if (!views) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_OPERATION_FAILED; + } + + for (i = 0; i < vaimage->num_planes; i++) { + data[i] = img_buf->data + vaimage->offsets[i]; + pitches[i] = vaimage->pitches[i]; + } + if (vaimage->format.fourcc == VA_FOURCC('I','4','2','0')) { + void *tmp_d; + unsigned tmp_p; + tmp_d = data[1]; + data[1] = data[2]; + data[2] = tmp_d; + tmp_p = pitches[1]; + pitches[1] = pitches[2]; + pitches[2] = tmp_p; + } + + for (i = 0; i < vaimage->num_planes; i++) { + unsigned box_w = align(width, 2); + unsigned box_h = align(height, 2); + unsigned box_x = x & ~1; + unsigned box_y = y & ~1; + if (!views[i]) continue; + vl_video_buffer_adjust_size(&box_w, &box_h, i, + pipe_format_to_chroma_format(surf->templat.buffer_format), + surf->templat.interlaced); + vl_video_buffer_adjust_size(&box_x, &box_y, i, + pipe_format_to_chroma_format(surf->templat.buffer_format), + surf->templat.interlaced); + for (j = 0; j < views[i]->texture->array_size; ++j) { + struct pipe_box box = {box_x, box_y, j, box_w, box_h, 1}; + struct pipe_transfer *transfer; + uint8_t *map; + map = drv->pipe->transfer_map(drv->pipe, views[i]->texture, 0, + PIPE_TRANSFER_READ, &box, &transfer); + if (!map) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_OPERATION_FAILED; + } + + if (i == 1 && convert) { + u_copy_nv12_to_yv12(data, pitches, i, j, + transfer->stride, views[i]->texture->array_size, + map, box.width, box.height); + } else { + util_copy_rect(data[i] + pitches[i] * j, + views[i]->texture->format, + pitches[i] * views[i]->texture->array_size, 0, 0, + box.width, box.height, map, transfer->stride, 0, 0); + } + pipe_transfer_unmap(drv->pipe, transfer); + } + } + mtx_unlock(&drv->mutex); + + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaPutImage(VADriverContextP ctx, VASurfaceID surface, VAImageID image, + int src_x, int src_y, unsigned int src_width, unsigned int src_height, + int dest_x, int dest_y, unsigned int dest_width, unsigned int dest_height) +{ + vlVaDriver *drv; + vlVaSurface *surf; + vlVaBuffer *img_buf; + VAImage *vaimage; + struct pipe_sampler_view **views; + enum pipe_format format; + void *data[3]; + unsigned pitches[3], i, j; + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + drv = VL_VA_DRIVER(ctx); + mtx_lock(&drv->mutex); + + surf = handle_table_get(drv->htab, surface); + if (!surf || !surf->buffer) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_INVALID_SURFACE; + } + + vaimage = handle_table_get(drv->htab, image); + if (!vaimage) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_INVALID_IMAGE; + } + + img_buf = handle_table_get(drv->htab, vaimage->buf); + if (!img_buf) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_INVALID_BUFFER; + } + + if (img_buf->derived_surface.resource) { + /* Attempting to transfer derived image to surface */ + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_UNIMPLEMENTED; + } + + format = VaFourccToPipeFormat(vaimage->format.fourcc); + + if (format == PIPE_FORMAT_NONE) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_OPERATION_FAILED; + } + + if ((format != surf->buffer->buffer_format) && + ((format != PIPE_FORMAT_YV12) || (surf->buffer->buffer_format != PIPE_FORMAT_NV12)) && + ((format != PIPE_FORMAT_IYUV) || (surf->buffer->buffer_format != PIPE_FORMAT_NV12))) { + struct pipe_video_buffer *tmp_buf; + + surf->templat.buffer_format = format; + if (format == PIPE_FORMAT_YUYV || format == PIPE_FORMAT_UYVY || + format == PIPE_FORMAT_B8G8R8A8_UNORM || format == PIPE_FORMAT_B8G8R8X8_UNORM || + format == PIPE_FORMAT_R8G8B8A8_UNORM || format == PIPE_FORMAT_R8G8B8X8_UNORM) + surf->templat.interlaced = false; + tmp_buf = drv->pipe->create_video_buffer(drv->pipe, &surf->templat); + + if (!tmp_buf) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_ALLOCATION_FAILED; + } + + surf->buffer->destroy(surf->buffer); + surf->buffer = tmp_buf; + } + + views = surf->buffer->get_sampler_view_planes(surf->buffer); + if (!views) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_OPERATION_FAILED; + } + + for (i = 0; i < vaimage->num_planes; i++) { + data[i] = img_buf->data + vaimage->offsets[i]; + pitches[i] = vaimage->pitches[i]; + } + if (vaimage->format.fourcc == VA_FOURCC('I','4','2','0')) { + void *tmp_d; + unsigned tmp_p; + tmp_d = data[1]; + data[1] = data[2]; + data[2] = tmp_d; + tmp_p = pitches[1]; + pitches[1] = pitches[2]; + pitches[2] = tmp_p; + } + + for (i = 0; i < vaimage->num_planes; ++i) { + unsigned width, height; + struct pipe_resource *tex; + + if (!views[i]) continue; + tex = views[i]->texture; + + vlVaVideoSurfaceSize(surf, i, &width, &height); + for (j = 0; j < tex->array_size; ++j) { + struct pipe_box dst_box = {0, 0, j, width, height, 1}; + + if (((format == PIPE_FORMAT_YV12) || (format == PIPE_FORMAT_IYUV)) + && (surf->buffer->buffer_format == PIPE_FORMAT_NV12) + && i == 1) { + struct pipe_transfer *transfer = NULL; + uint8_t *map = NULL; + + map = drv->pipe->transfer_map(drv->pipe, + tex, + 0, + PIPE_TRANSFER_WRITE | + PIPE_TRANSFER_DISCARD_RANGE, + &dst_box, &transfer); + if (map == NULL) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_OPERATION_FAILED; + } + + u_copy_nv12_from_yv12((const void * const*) data, pitches, i, j, + transfer->stride, tex->array_size, + map, dst_box.width, dst_box.height); + pipe_transfer_unmap(drv->pipe, transfer); + } else { + drv->pipe->texture_subdata(drv->pipe, tex, 0, + PIPE_TRANSFER_WRITE, &dst_box, + data[i] + pitches[i] * j, + pitches[i] * views[i]->texture->array_size, 0); + } + } + } + mtx_unlock(&drv->mutex); + + return VA_STATUS_SUCCESS; +} diff --git a/src/gallium/frontends/va/meson.build b/src/gallium/frontends/va/meson.build new file mode 100644 index 00000000000..1929d907b9d --- /dev/null +++ b/src/gallium/frontends/va/meson.build @@ -0,0 +1,42 @@ +# Copyright © 2017-2019 Intel Corporation + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +libva_version = dep_va.version().split('.') + +libva_st = static_library( + 'va_st', + files( + 'buffer.c', 'config.c', 'context.c', 'display.c', 'image.c', 'picture.c', + 'picture_mpeg12.c', 'picture_mpeg4.c', 'picture_h264.c', 'picture_hevc.c', + 'picture_vc1.c', 'picture_mjpeg.c', 'picture_vp9.c','postproc.c', + 'subpicture.c', 'surface.c', 'picture_h264_enc.c', 'picture_hevc_enc.c', + ), + c_args : [ + c_vis_args, + '-DVA_DRIVER_INIT_FUNC=__vaDriverInit_@0@_@1@'.format( + libva_version[0], libva_version[1] + ), + ], + include_directories : [inc_include, inc_src, inc_mapi, inc_mesa, inc_gallium, inc_gallium_aux], + dependencies : [ + dep_va_headers, dep_x11_xcb, dep_xcb, dep_xcb_dri2, dep_xcb_dri3, + dep_libdrm, + ], +) diff --git a/src/gallium/frontends/va/picture.c b/src/gallium/frontends/va/picture.c new file mode 100644 index 00000000000..d292594590c --- /dev/null +++ b/src/gallium/frontends/va/picture.c @@ -0,0 +1,689 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian. + * Copyright 2014 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "pipe/p_video_codec.h" + +#include "util/u_handle_table.h" +#include "util/u_video.h" + +#include "vl/vl_vlc.h" +#include "vl/vl_winsys.h" + +#include "va_private.h" + +VAStatus +vlVaBeginPicture(VADriverContextP ctx, VAContextID context_id, VASurfaceID render_target) +{ + vlVaDriver *drv; + vlVaContext *context; + vlVaSurface *surf; + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + drv = VL_VA_DRIVER(ctx); + if (!drv) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + mtx_lock(&drv->mutex); + context = handle_table_get(drv->htab, context_id); + if (!context) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_INVALID_CONTEXT; + } + + if (u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_MPEG12) { + context->desc.mpeg12.intra_matrix = NULL; + context->desc.mpeg12.non_intra_matrix = NULL; + } + + surf = handle_table_get(drv->htab, render_target); + mtx_unlock(&drv->mutex); + if (!surf || !surf->buffer) + return VA_STATUS_ERROR_INVALID_SURFACE; + + context->target_id = render_target; + surf->ctx = context_id; + context->target = surf->buffer; + context->mjpeg.sampling_factor = 0; + + if (!context->decoder) { + + /* VPP */ + if (context->templat.profile == PIPE_VIDEO_PROFILE_UNKNOWN && + context->target->buffer_format != PIPE_FORMAT_B8G8R8A8_UNORM && + context->target->buffer_format != PIPE_FORMAT_R8G8B8A8_UNORM && + context->target->buffer_format != PIPE_FORMAT_B8G8R8X8_UNORM && + context->target->buffer_format != PIPE_FORMAT_R8G8B8X8_UNORM && + context->target->buffer_format != PIPE_FORMAT_NV12 && + context->target->buffer_format != PIPE_FORMAT_P010 && + context->target->buffer_format != PIPE_FORMAT_P016) + return VA_STATUS_ERROR_UNIMPLEMENTED; + + return VA_STATUS_SUCCESS; + } + + if (context->decoder->entrypoint != PIPE_VIDEO_ENTRYPOINT_ENCODE) + context->needs_begin_frame = true; + + return VA_STATUS_SUCCESS; +} + +void +vlVaGetReferenceFrame(vlVaDriver *drv, VASurfaceID surface_id, + struct pipe_video_buffer **ref_frame) +{ + vlVaSurface *surf = handle_table_get(drv->htab, surface_id); + if (surf) + *ref_frame = surf->buffer; + else + *ref_frame = NULL; +} + +static VAStatus +handlePictureParameterBuffer(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) +{ + VAStatus vaStatus = VA_STATUS_SUCCESS; + + switch (u_reduce_video_profile(context->templat.profile)) { + case PIPE_VIDEO_FORMAT_MPEG12: + vlVaHandlePictureParameterBufferMPEG12(drv, context, buf); + break; + + case PIPE_VIDEO_FORMAT_MPEG4_AVC: + vlVaHandlePictureParameterBufferH264(drv, context, buf); + break; + + case PIPE_VIDEO_FORMAT_VC1: + vlVaHandlePictureParameterBufferVC1(drv, context, buf); + break; + + case PIPE_VIDEO_FORMAT_MPEG4: + vlVaHandlePictureParameterBufferMPEG4(drv, context, buf); + break; + + case PIPE_VIDEO_FORMAT_HEVC: + vlVaHandlePictureParameterBufferHEVC(drv, context, buf); + break; + + case PIPE_VIDEO_FORMAT_JPEG: + vlVaHandlePictureParameterBufferMJPEG(drv, context, buf); + break; + + case PIPE_VIDEO_FORMAT_VP9: + vlVaHandlePictureParameterBufferVP9(drv, context, buf); + break; + + default: + break; + } + + /* Create the decoder once max_references is known. */ + if (!context->decoder) { + enum pipe_video_format format = + u_reduce_video_profile(context->templat.profile); + + if (!context->target) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + if (context->templat.max_references == 0 && + format != PIPE_VIDEO_FORMAT_JPEG) + return VA_STATUS_ERROR_INVALID_BUFFER; + + if (format == PIPE_VIDEO_FORMAT_MPEG4_AVC) + context->templat.level = u_get_h264_level(context->templat.width, + context->templat.height, &context->templat.max_references); + + context->decoder = drv->pipe->create_video_codec(drv->pipe, + &context->templat); + + if (!context->decoder) + return VA_STATUS_ERROR_ALLOCATION_FAILED; + + context->needs_begin_frame = true; + } + + return vaStatus; +} + +static void +handleIQMatrixBuffer(vlVaContext *context, vlVaBuffer *buf) +{ + switch (u_reduce_video_profile(context->templat.profile)) { + case PIPE_VIDEO_FORMAT_MPEG12: + vlVaHandleIQMatrixBufferMPEG12(context, buf); + break; + + case PIPE_VIDEO_FORMAT_MPEG4_AVC: + vlVaHandleIQMatrixBufferH264(context, buf); + break; + + case PIPE_VIDEO_FORMAT_MPEG4: + vlVaHandleIQMatrixBufferMPEG4(context, buf); + break; + + case PIPE_VIDEO_FORMAT_HEVC: + vlVaHandleIQMatrixBufferHEVC(context, buf); + break; + + case PIPE_VIDEO_FORMAT_JPEG: + vlVaHandleIQMatrixBufferMJPEG(context, buf); + break; + + default: + break; + } +} + +static void +handleSliceParameterBuffer(vlVaContext *context, vlVaBuffer *buf) +{ + switch (u_reduce_video_profile(context->templat.profile)) { + case PIPE_VIDEO_FORMAT_MPEG12: + vlVaHandleSliceParameterBufferMPEG12(context, buf); + break; + + case PIPE_VIDEO_FORMAT_VC1: + vlVaHandleSliceParameterBufferVC1(context, buf); + break; + + case PIPE_VIDEO_FORMAT_MPEG4_AVC: + vlVaHandleSliceParameterBufferH264(context, buf); + break; + + case PIPE_VIDEO_FORMAT_MPEG4: + vlVaHandleSliceParameterBufferMPEG4(context, buf); + break; + + case PIPE_VIDEO_FORMAT_HEVC: + vlVaHandleSliceParameterBufferHEVC(context, buf); + break; + + case PIPE_VIDEO_FORMAT_JPEG: + vlVaHandleSliceParameterBufferMJPEG(context, buf); + break; + + case PIPE_VIDEO_FORMAT_VP9: + vlVaHandleSliceParameterBufferVP9(context, buf); + break; + + default: + break; + } +} + +static unsigned int +bufHasStartcode(vlVaBuffer *buf, unsigned int code, unsigned int bits) +{ + struct vl_vlc vlc = {0}; + int i; + + /* search the first 64 bytes for a startcode */ + vl_vlc_init(&vlc, 1, (const void * const*)&buf->data, &buf->size); + for (i = 0; i < 64 && vl_vlc_bits_left(&vlc) >= bits; ++i) { + if (vl_vlc_peekbits(&vlc, bits) == code) + return 1; + vl_vlc_eatbits(&vlc, 8); + vl_vlc_fillbits(&vlc); + } + + return 0; +} + +static void +handleVASliceDataBufferType(vlVaContext *context, vlVaBuffer *buf) +{ + enum pipe_video_format format; + unsigned num_buffers = 0; + void * const *buffers[3]; + unsigned sizes[3]; + static const uint8_t start_code_h264[] = { 0x00, 0x00, 0x01 }; + static const uint8_t start_code_h265[] = { 0x00, 0x00, 0x01 }; + static const uint8_t start_code_vc1[] = { 0x00, 0x00, 0x01, 0x0d }; + static const uint8_t eoi_jpeg[] = { 0xff, 0xd9 }; + + format = u_reduce_video_profile(context->templat.profile); + switch (format) { + case PIPE_VIDEO_FORMAT_MPEG4_AVC: + if (bufHasStartcode(buf, 0x000001, 24)) + break; + + buffers[num_buffers] = (void *const)&start_code_h264; + sizes[num_buffers++] = sizeof(start_code_h264); + break; + case PIPE_VIDEO_FORMAT_HEVC: + if (bufHasStartcode(buf, 0x000001, 24)) + break; + + buffers[num_buffers] = (void *const)&start_code_h265; + sizes[num_buffers++] = sizeof(start_code_h265); + break; + case PIPE_VIDEO_FORMAT_VC1: + if (bufHasStartcode(buf, 0x0000010d, 32) || + bufHasStartcode(buf, 0x0000010c, 32) || + bufHasStartcode(buf, 0x0000010b, 32)) + break; + + if (context->decoder->profile == PIPE_VIDEO_PROFILE_VC1_ADVANCED) { + buffers[num_buffers] = (void *const)&start_code_vc1; + sizes[num_buffers++] = sizeof(start_code_vc1); + } + break; + case PIPE_VIDEO_FORMAT_MPEG4: + if (bufHasStartcode(buf, 0x000001, 24)) + break; + + vlVaDecoderFixMPEG4Startcode(context); + buffers[num_buffers] = (void *)context->mpeg4.start_code; + sizes[num_buffers++] = context->mpeg4.start_code_size; + break; + case PIPE_VIDEO_FORMAT_JPEG: + vlVaGetJpegSliceHeader(context); + buffers[num_buffers] = (void *)context->mjpeg.slice_header; + sizes[num_buffers++] = context->mjpeg.slice_header_size; + break; + case PIPE_VIDEO_FORMAT_VP9: + vlVaDecoderVP9BitstreamHeader(context, buf); + break; + default: + break; + } + + buffers[num_buffers] = buf->data; + sizes[num_buffers] = buf->size; + ++num_buffers; + + if (format == PIPE_VIDEO_FORMAT_JPEG) { + buffers[num_buffers] = (void *const)&eoi_jpeg; + sizes[num_buffers++] = sizeof(eoi_jpeg); + } + + if (context->needs_begin_frame) { + context->decoder->begin_frame(context->decoder, context->target, + &context->desc.base); + context->needs_begin_frame = false; + } + context->decoder->decode_bitstream(context->decoder, context->target, &context->desc.base, + num_buffers, (const void * const*)buffers, sizes); +} + +static VAStatus +handleVAEncMiscParameterTypeRateControl(vlVaContext *context, VAEncMiscParameterBuffer *misc) +{ + VAStatus status = VA_STATUS_SUCCESS; + + switch (u_reduce_video_profile(context->templat.profile)) { + case PIPE_VIDEO_FORMAT_MPEG4_AVC: + status = vlVaHandleVAEncMiscParameterTypeRateControlH264(context, misc); + break; + + case PIPE_VIDEO_FORMAT_HEVC: + status = vlVaHandleVAEncMiscParameterTypeRateControlHEVC(context, misc); + break; + + default: + break; + } + + return status; +} + +static VAStatus +handleVAEncMiscParameterTypeFrameRate(vlVaContext *context, VAEncMiscParameterBuffer *misc) +{ + VAStatus status = VA_STATUS_SUCCESS; + + switch (u_reduce_video_profile(context->templat.profile)) { + case PIPE_VIDEO_FORMAT_MPEG4_AVC: + status = vlVaHandleVAEncMiscParameterTypeFrameRateH264(context, misc); + break; + + case PIPE_VIDEO_FORMAT_HEVC: + status = vlVaHandleVAEncMiscParameterTypeFrameRateHEVC(context, misc); + break; + + default: + break; + } + + return status; +} + +static VAStatus +handleVAEncSequenceParameterBufferType(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) +{ + VAStatus status = VA_STATUS_SUCCESS; + + switch (u_reduce_video_profile(context->templat.profile)) { + case PIPE_VIDEO_FORMAT_MPEG4_AVC: + status = vlVaHandleVAEncSequenceParameterBufferTypeH264(drv, context, buf); + break; + + case PIPE_VIDEO_FORMAT_HEVC: + status = vlVaHandleVAEncSequenceParameterBufferTypeHEVC(drv, context, buf); + break; + + default: + break; + } + + return status; +} + +static VAStatus +handleVAEncMiscParameterBufferType(vlVaContext *context, vlVaBuffer *buf) +{ + VAStatus vaStatus = VA_STATUS_SUCCESS; + VAEncMiscParameterBuffer *misc; + misc = buf->data; + + switch (misc->type) { + case VAEncMiscParameterTypeRateControl: + vaStatus = handleVAEncMiscParameterTypeRateControl(context, misc); + break; + + case VAEncMiscParameterTypeFrameRate: + vaStatus = handleVAEncMiscParameterTypeFrameRate(context, misc); + break; + + default: + break; + } + + return vaStatus; +} + +static VAStatus +handleVAEncPictureParameterBufferType(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) +{ + VAStatus status = VA_STATUS_SUCCESS; + + switch (u_reduce_video_profile(context->templat.profile)) { + case PIPE_VIDEO_FORMAT_MPEG4_AVC: + status = vlVaHandleVAEncPictureParameterBufferTypeH264(drv, context, buf); + break; + + case PIPE_VIDEO_FORMAT_HEVC: + status = vlVaHandleVAEncPictureParameterBufferTypeHEVC(drv, context, buf); + break; + + default: + break; + } + + return status; +} + +static VAStatus +handleVAEncSliceParameterBufferType(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) +{ + VAStatus status = VA_STATUS_SUCCESS; + + switch (u_reduce_video_profile(context->templat.profile)) { + case PIPE_VIDEO_FORMAT_MPEG4_AVC: + status = vlVaHandleVAEncSliceParameterBufferTypeH264(drv, context, buf); + break; + + case PIPE_VIDEO_FORMAT_HEVC: + status = vlVaHandleVAEncSliceParameterBufferTypeHEVC(drv, context, buf); + break; + + default: + break; + } + + return status; +} + +VAStatus +vlVaRenderPicture(VADriverContextP ctx, VAContextID context_id, VABufferID *buffers, int num_buffers) +{ + vlVaDriver *drv; + vlVaContext *context; + VAStatus vaStatus = VA_STATUS_SUCCESS; + + unsigned i; + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + drv = VL_VA_DRIVER(ctx); + if (!drv) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + mtx_lock(&drv->mutex); + context = handle_table_get(drv->htab, context_id); + if (!context) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_INVALID_CONTEXT; + } + + for (i = 0; i < num_buffers; ++i) { + vlVaBuffer *buf = handle_table_get(drv->htab, buffers[i]); + if (!buf) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_INVALID_BUFFER; + } + + switch (buf->type) { + case VAPictureParameterBufferType: + vaStatus = handlePictureParameterBuffer(drv, context, buf); + break; + + case VAIQMatrixBufferType: + handleIQMatrixBuffer(context, buf); + break; + + case VASliceParameterBufferType: + handleSliceParameterBuffer(context, buf); + break; + + case VASliceDataBufferType: + handleVASliceDataBufferType(context, buf); + break; + case VAProcPipelineParameterBufferType: + vaStatus = vlVaHandleVAProcPipelineParameterBufferType(drv, context, buf); + break; + + case VAEncSequenceParameterBufferType: + vaStatus = handleVAEncSequenceParameterBufferType(drv, context, buf); + break; + + case VAEncMiscParameterBufferType: + vaStatus = handleVAEncMiscParameterBufferType(context, buf); + break; + + case VAEncPictureParameterBufferType: + vaStatus = handleVAEncPictureParameterBufferType(drv, context, buf); + break; + + case VAEncSliceParameterBufferType: + vaStatus = handleVAEncSliceParameterBufferType(drv, context, buf); + break; + + case VAHuffmanTableBufferType: + vlVaHandleHuffmanTableBufferType(context, buf); + break; + + default: + break; + } + } + mtx_unlock(&drv->mutex); + + return vaStatus; +} + +VAStatus +vlVaEndPicture(VADriverContextP ctx, VAContextID context_id) +{ + vlVaDriver *drv; + vlVaContext *context; + vlVaBuffer *coded_buf; + vlVaSurface *surf; + void *feedback; + struct pipe_screen *screen; + bool supported; + bool realloc = false; + enum pipe_format format; + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + drv = VL_VA_DRIVER(ctx); + if (!drv) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + mtx_lock(&drv->mutex); + context = handle_table_get(drv->htab, context_id); + mtx_unlock(&drv->mutex); + if (!context) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + if (!context->decoder) { + if (context->templat.profile != PIPE_VIDEO_PROFILE_UNKNOWN) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + /* VPP */ + return VA_STATUS_SUCCESS; + } + + mtx_lock(&drv->mutex); + surf = handle_table_get(drv->htab, context->target_id); + context->mpeg4.frame_num++; + + screen = context->decoder->context->screen; + supported = screen->get_video_param(screen, context->decoder->profile, + context->decoder->entrypoint, + surf->buffer->interlaced ? + PIPE_VIDEO_CAP_SUPPORTS_INTERLACED : + PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE); + + if (!supported) { + surf->templat.interlaced = screen->get_video_param(screen, + context->decoder->profile, + context->decoder->entrypoint, + PIPE_VIDEO_CAP_PREFERS_INTERLACED); + realloc = true; + } + + format = screen->get_video_param(screen, context->decoder->profile, + PIPE_VIDEO_ENTRYPOINT_BITSTREAM, + PIPE_VIDEO_CAP_PREFERED_FORMAT); + + if (surf->buffer->buffer_format != format && + surf->buffer->buffer_format == PIPE_FORMAT_NV12) { + /* check originally as NV12 only */ + surf->templat.buffer_format = format; + realloc = true; + } + + if (u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_JPEG && + surf->buffer->buffer_format == PIPE_FORMAT_NV12) { + if (context->mjpeg.sampling_factor == 0x211111 || + context->mjpeg.sampling_factor == 0x221212) { + surf->templat.buffer_format = PIPE_FORMAT_YUYV; + realloc = true; + } else if (context->mjpeg.sampling_factor != 0x221111) { + /* Not NV12 either */ + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_INVALID_SURFACE; + } + } + + if (realloc) { + struct pipe_video_buffer *old_buf = surf->buffer; + + if (vlVaHandleSurfaceAllocate(drv, surf, &surf->templat) != VA_STATUS_SUCCESS) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_ALLOCATION_FAILED; + } + + if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) { + if (old_buf->interlaced) { + struct u_rect src_rect, dst_rect; + + dst_rect.x0 = src_rect.x0 = 0; + dst_rect.y0 = src_rect.y0 = 0; + dst_rect.x1 = src_rect.x1 = surf->templat.width; + dst_rect.y1 = src_rect.y1 = surf->templat.height; + vl_compositor_yuv_deint_full(&drv->cstate, &drv->compositor, + old_buf, surf->buffer, + &src_rect, &dst_rect, VL_COMPOSITOR_WEAVE); + } else { + /* Can't convert from progressive to interlaced yet */ + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_INVALID_SURFACE; + } + } + + old_buf->destroy(old_buf); + context->target = surf->buffer; + } + + if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) { + coded_buf = context->coded_buf; + if (u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_MPEG4_AVC) { + getEncParamPresetH264(context); + context->desc.h264enc.frame_num_cnt++; + } else if (u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_HEVC) + getEncParamPresetH265(context); + context->decoder->begin_frame(context->decoder, context->target, &context->desc.base); + context->decoder->encode_bitstream(context->decoder, context->target, + coded_buf->derived_surface.resource, &feedback); + surf->feedback = feedback; + surf->coded_buf = coded_buf; + } + + context->decoder->end_frame(context->decoder, context->target, &context->desc.base); + if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE && + u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_MPEG4_AVC) { + int idr_period = context->desc.h264enc.gop_size / context->gop_coeff; + int p_remain_in_idr = idr_period - context->desc.h264enc.frame_num; + surf->frame_num_cnt = context->desc.h264enc.frame_num_cnt; + surf->force_flushed = false; + if (context->first_single_submitted) { + context->decoder->flush(context->decoder); + context->first_single_submitted = false; + surf->force_flushed = true; + } + if (p_remain_in_idr == 1) { + if ((context->desc.h264enc.frame_num_cnt % 2) != 0) { + context->decoder->flush(context->decoder); + context->first_single_submitted = true; + } + else + context->first_single_submitted = false; + surf->force_flushed = true; + } + } else if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE && + u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_HEVC) + context->desc.h265enc.frame_num++; + mtx_unlock(&drv->mutex); + return VA_STATUS_SUCCESS; +} diff --git a/src/gallium/frontends/va/picture_h264.c b/src/gallium/frontends/va/picture_h264.c new file mode 100644 index 00000000000..883a94a2b52 --- /dev/null +++ b/src/gallium/frontends/va/picture_h264.c @@ -0,0 +1,171 @@ + /************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian. + * Copyright 2014 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "util/u_video.h" +#include "va_private.h" + +static void resetReferencePictureDesc(struct pipe_h264_picture_desc *h264, + unsigned int i) +{ + h264->ref[i] = NULL; + h264->frame_num_list[i] = 0; + h264->is_long_term[i] = 0; + h264->top_is_reference[i] = 0; + h264->bottom_is_reference[i] = 0; + h264->field_order_cnt_list[i][0] = 0; + h264->field_order_cnt_list[i][1] = 0; +} + +void vlVaHandlePictureParameterBufferH264(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) +{ + VAPictureParameterBufferH264 *h264 = buf->data; + unsigned int top_or_bottom_field; + unsigned i; + + assert(buf->size >= sizeof(VAPictureParameterBufferH264) && buf->num_elements == 1); + context->desc.h264.slice_count = 0; + /*CurrPic*/ + context->desc.h264.field_order_cnt[0] = h264->CurrPic.TopFieldOrderCnt; + context->desc.h264.field_order_cnt[1] = h264->CurrPic.BottomFieldOrderCnt; + /*ReferenceFrames[16]*/ + /*picture_width_in_mbs_minus1*/ + /*picture_height_in_mbs_minus1*/ + /*bit_depth_luma_minus8*/ + /*bit_depth_chroma_minus8*/ + context->desc.h264.num_ref_frames = h264->num_ref_frames; + /*chroma_format_idc*/ + /*residual_colour_transform_flag*/ + /*gaps_in_frame_num_value_allowed_flag*/ + context->desc.h264.pps->sps->frame_mbs_only_flag = + h264->seq_fields.bits.frame_mbs_only_flag; + context->desc.h264.pps->sps->mb_adaptive_frame_field_flag = + h264->seq_fields.bits.mb_adaptive_frame_field_flag; + context->desc.h264.pps->sps->direct_8x8_inference_flag = + h264->seq_fields.bits.direct_8x8_inference_flag; + /*MinLumaBiPredSize8x8*/ + context->desc.h264.pps->sps->log2_max_frame_num_minus4 = + h264->seq_fields.bits.log2_max_frame_num_minus4; + context->desc.h264.pps->sps->pic_order_cnt_type = + h264->seq_fields.bits.pic_order_cnt_type; + context->desc.h264.pps->sps->log2_max_pic_order_cnt_lsb_minus4 = + h264->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4; + context->desc.h264.pps->sps->delta_pic_order_always_zero_flag = + h264->seq_fields.bits.delta_pic_order_always_zero_flag; + /*num_slice_groups_minus1*/ + /*slice_group_map_type*/ + /*slice_group_change_rate_minus1*/ + context->desc.h264.pps->pic_init_qp_minus26 = + h264->pic_init_qp_minus26; + /*pic_init_qs_minus26*/ + context->desc.h264.pps->chroma_qp_index_offset = + h264->chroma_qp_index_offset; + context->desc.h264.pps->second_chroma_qp_index_offset = + h264->second_chroma_qp_index_offset; + context->desc.h264.pps->entropy_coding_mode_flag = + h264->pic_fields.bits.entropy_coding_mode_flag; + context->desc.h264.pps->weighted_pred_flag = + h264->pic_fields.bits.weighted_pred_flag; + context->desc.h264.pps->weighted_bipred_idc = + h264->pic_fields.bits.weighted_bipred_idc; + context->desc.h264.pps->transform_8x8_mode_flag = + h264->pic_fields.bits.transform_8x8_mode_flag; + context->desc.h264.field_pic_flag = + h264->pic_fields.bits.field_pic_flag; + context->desc.h264.pps->constrained_intra_pred_flag = + h264->pic_fields.bits.constrained_intra_pred_flag; + context->desc.h264.pps->bottom_field_pic_order_in_frame_present_flag = + h264->pic_fields.bits.pic_order_present_flag; + context->desc.h264.pps->deblocking_filter_control_present_flag = + h264->pic_fields.bits.deblocking_filter_control_present_flag; + context->desc.h264.pps->redundant_pic_cnt_present_flag = + h264->pic_fields.bits.redundant_pic_cnt_present_flag; + /*reference_pic_flag*/ + context->desc.h264.frame_num = h264->frame_num; + context->desc.h264.is_reference = h264->pic_fields.bits.reference_pic_flag; + context->desc.h264.bottom_field_flag = + h264->pic_fields.bits.field_pic_flag && + (h264->CurrPic.flags & VA_PICTURE_H264_BOTTOM_FIELD) != 0; + + if (!context->decoder && context->desc.h264.num_ref_frames > 0) + context->templat.max_references = MIN2(context->desc.h264.num_ref_frames, 16); + + for (i = 0; i < context->templat.max_references; ++i) { + if ((h264->ReferenceFrames[i].flags & VA_PICTURE_H264_INVALID) || + (h264->ReferenceFrames[i].picture_id == VA_INVALID_SURFACE)) { + resetReferencePictureDesc(&context->desc.h264, i); + break; + } + + vlVaGetReferenceFrame(drv, h264->ReferenceFrames[i].picture_id, &context->desc.h264.ref[i]); + context->desc.h264.frame_num_list[i] = h264->ReferenceFrames[i].frame_idx; + + top_or_bottom_field = h264->ReferenceFrames[i].flags & + (VA_PICTURE_H264_TOP_FIELD | VA_PICTURE_H264_BOTTOM_FIELD); + context->desc.h264.is_long_term[i] = (h264->ReferenceFrames[i].flags & + (VA_PICTURE_H264_SHORT_TERM_REFERENCE | + VA_PICTURE_H264_LONG_TERM_REFERENCE)) != + VA_PICTURE_H264_SHORT_TERM_REFERENCE; + context->desc.h264.top_is_reference[i] = + !context->desc.h264.is_long_term[i] || + !!(h264->ReferenceFrames[i].flags & VA_PICTURE_H264_TOP_FIELD); + context->desc.h264.bottom_is_reference[i] = + !context->desc.h264.is_long_term[i] || + !!(h264->ReferenceFrames[i].flags & VA_PICTURE_H264_BOTTOM_FIELD); + context->desc.h264.field_order_cnt_list[i][0] = + top_or_bottom_field != VA_PICTURE_H264_BOTTOM_FIELD ? + h264->ReferenceFrames[i].TopFieldOrderCnt: INT_MAX; + context->desc.h264.field_order_cnt_list[i][1] = + top_or_bottom_field != VA_PICTURE_H264_TOP_FIELD ? + h264->ReferenceFrames[i].BottomFieldOrderCnt: INT_MAX; + } + + /* Make sure remaining elements are clean */ + for (; i < 16; ++i) + resetReferencePictureDesc(&context->desc.h264, i); +} + +void vlVaHandleIQMatrixBufferH264(vlVaContext *context, vlVaBuffer *buf) +{ + VAIQMatrixBufferH264 *h264 = buf->data; + + assert(buf->size >= sizeof(VAIQMatrixBufferH264) && buf->num_elements == 1); + memcpy(&context->desc.h264.pps->ScalingList4x4, h264->ScalingList4x4, 6 * 16); + memcpy(&context->desc.h264.pps->ScalingList8x8, h264->ScalingList8x8, 2 * 64); +} + +void vlVaHandleSliceParameterBufferH264(vlVaContext *context, vlVaBuffer *buf) +{ + VASliceParameterBufferH264 *h264 = buf->data; + + assert(buf->size >= sizeof(VASliceParameterBufferH264) && buf->num_elements == 1); + context->desc.h264.slice_count += buf->num_elements; + context->desc.h264.num_ref_idx_l0_active_minus1 = + h264->num_ref_idx_l0_active_minus1; + context->desc.h264.num_ref_idx_l1_active_minus1 = + h264->num_ref_idx_l1_active_minus1; +} diff --git a/src/gallium/frontends/va/picture_h264_enc.c b/src/gallium/frontends/va/picture_h264_enc.c new file mode 100644 index 00000000000..8ee27d2cb29 --- /dev/null +++ b/src/gallium/frontends/va/picture_h264_enc.c @@ -0,0 +1,210 @@ +/************************************************************************** + * + * Copyright 2018 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "util/u_handle_table.h" +#include "util/u_video.h" +#include "va_private.h" + +VAStatus +vlVaHandleVAEncPictureParameterBufferTypeH264(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) +{ + VAEncPictureParameterBufferH264 *h264; + vlVaBuffer *coded_buf; + + h264 = buf->data; + context->desc.h264enc.frame_num = h264->frame_num; + context->desc.h264enc.not_referenced = false; + context->desc.h264enc.pic_order_cnt = h264->CurrPic.TopFieldOrderCnt; + if (context->desc.h264enc.gop_cnt == 0) + context->desc.h264enc.i_remain = context->gop_coeff; + else if (context->desc.h264enc.frame_num == 1) + context->desc.h264enc.i_remain--; + + context->desc.h264enc.p_remain = context->desc.h264enc.gop_size - context->desc.h264enc.gop_cnt - context->desc.h264enc.i_remain; + + coded_buf = handle_table_get(drv->htab, h264->coded_buf); + if (!coded_buf->derived_surface.resource) + coded_buf->derived_surface.resource = pipe_buffer_create(drv->pipe->screen, PIPE_BIND_VERTEX_BUFFER, + PIPE_USAGE_STREAM, coded_buf->size); + context->coded_buf = coded_buf; + + _mesa_hash_table_insert(context->desc.h264enc.frame_idx, + UINT_TO_PTR(h264->CurrPic.picture_id), + UINT_TO_PTR(h264->frame_num)); + + if (h264->pic_fields.bits.idr_pic_flag == 1) + context->desc.h264enc.picture_type = PIPE_H264_ENC_PICTURE_TYPE_IDR; + else + context->desc.h264enc.picture_type = PIPE_H264_ENC_PICTURE_TYPE_P; + + context->desc.h264enc.quant_i_frames = h264->pic_init_qp; + context->desc.h264enc.quant_b_frames = h264->pic_init_qp; + context->desc.h264enc.quant_p_frames = h264->pic_init_qp; + context->desc.h264enc.gop_cnt++; + if (context->desc.h264enc.gop_cnt == context->desc.h264enc.gop_size) + context->desc.h264enc.gop_cnt = 0; + + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaHandleVAEncSliceParameterBufferTypeH264(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) +{ + VAEncSliceParameterBufferH264 *h264; + + h264 = buf->data; + context->desc.h264enc.ref_idx_l0 = VA_INVALID_ID; + context->desc.h264enc.ref_idx_l1 = VA_INVALID_ID; + + for (int i = 0; i < 32; i++) { + if (h264->RefPicList0[i].picture_id != VA_INVALID_ID) { + if (context->desc.h264enc.ref_idx_l0 == VA_INVALID_ID) + context->desc.h264enc.ref_idx_l0 = PTR_TO_UINT(util_hash_table_get(context->desc.h264enc.frame_idx, + UINT_TO_PTR(h264->RefPicList0[i].picture_id))); + } + if (h264->RefPicList1[i].picture_id != VA_INVALID_ID && h264->slice_type == 1) { + if (context->desc.h264enc.ref_idx_l1 == VA_INVALID_ID) + context->desc.h264enc.ref_idx_l1 = PTR_TO_UINT(util_hash_table_get(context->desc.h264enc.frame_idx, + UINT_TO_PTR(h264->RefPicList1[i].picture_id))); + } + } + + if (h264->slice_type == 1) + context->desc.h264enc.picture_type = PIPE_H264_ENC_PICTURE_TYPE_B; + else if (h264->slice_type == 0) + context->desc.h264enc.picture_type = PIPE_H264_ENC_PICTURE_TYPE_P; + else if (h264->slice_type == 2) { + if (context->desc.h264enc.picture_type == PIPE_H264_ENC_PICTURE_TYPE_IDR) + context->desc.h264enc.idr_pic_id++; + else + context->desc.h264enc.picture_type = PIPE_H264_ENC_PICTURE_TYPE_I; + } else + context->desc.h264enc.picture_type = PIPE_H264_ENC_PICTURE_TYPE_SKIP; + + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaHandleVAEncSequenceParameterBufferTypeH264(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) +{ + VAEncSequenceParameterBufferH264 *h264 = (VAEncSequenceParameterBufferH264 *)buf->data; + if (!context->decoder) { + context->templat.max_references = h264->max_num_ref_frames; + context->templat.level = h264->level_idc; + context->decoder = drv->pipe->create_video_codec(drv->pipe, &context->templat); + if (!context->decoder) + return VA_STATUS_ERROR_ALLOCATION_FAILED; + } + + context->gop_coeff = ((1024 + h264->intra_idr_period - 1) / h264->intra_idr_period + 1) / 2 * 2; + if (context->gop_coeff > VL_VA_ENC_GOP_COEFF) + context->gop_coeff = VL_VA_ENC_GOP_COEFF; + context->desc.h264enc.gop_size = h264->intra_idr_period * context->gop_coeff; + context->desc.h264enc.rate_ctrl.frame_rate_num = h264->time_scale / 2; + context->desc.h264enc.rate_ctrl.frame_rate_den = h264->num_units_in_tick; + context->desc.h264enc.pic_order_cnt_type = h264->seq_fields.bits.pic_order_cnt_type; + + if (h264->frame_cropping_flag) { + context->desc.h264enc.pic_ctrl.enc_frame_cropping_flag = h264->frame_cropping_flag; + context->desc.h264enc.pic_ctrl.enc_frame_crop_left_offset = h264->frame_crop_left_offset; + context->desc.h264enc.pic_ctrl.enc_frame_crop_right_offset = h264->frame_crop_right_offset; + context->desc.h264enc.pic_ctrl.enc_frame_crop_top_offset = h264->frame_crop_top_offset; + context->desc.h264enc.pic_ctrl.enc_frame_crop_bottom_offset = h264->frame_crop_bottom_offset; + } + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaHandleVAEncMiscParameterTypeRateControlH264(vlVaContext *context, VAEncMiscParameterBuffer *misc) +{ + VAEncMiscParameterRateControl *rc = (VAEncMiscParameterRateControl *)misc->data; + if (context->desc.h264enc.rate_ctrl.rate_ctrl_method == + PIPE_H264_ENC_RATE_CONTROL_METHOD_CONSTANT) + context->desc.h264enc.rate_ctrl.target_bitrate = rc->bits_per_second; + else + context->desc.h264enc.rate_ctrl.target_bitrate = rc->bits_per_second * (rc->target_percentage / 100.0); + context->desc.h264enc.rate_ctrl.peak_bitrate = rc->bits_per_second; + if (context->desc.h264enc.rate_ctrl.target_bitrate < 2000000) + context->desc.h264enc.rate_ctrl.vbv_buffer_size = MIN2((context->desc.h264enc.rate_ctrl.target_bitrate * 2.75), 2000000); + else + context->desc.h264enc.rate_ctrl.vbv_buffer_size = context->desc.h264enc.rate_ctrl.target_bitrate; + + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaHandleVAEncMiscParameterTypeFrameRateH264(vlVaContext *context, VAEncMiscParameterBuffer *misc) +{ + VAEncMiscParameterFrameRate *fr = (VAEncMiscParameterFrameRate *)misc->data; + if (fr->framerate & 0xffff0000) { + context->desc.h264enc.rate_ctrl.frame_rate_num = fr->framerate & 0xffff; + context->desc.h264enc.rate_ctrl.frame_rate_den = fr->framerate >> 16 & 0xffff; + } else { + context->desc.h264enc.rate_ctrl.frame_rate_num = fr->framerate; + context->desc.h264enc.rate_ctrl.frame_rate_den = 1; + } + return VA_STATUS_SUCCESS; +} + +void getEncParamPresetH264(vlVaContext *context) +{ + //motion estimation preset + context->desc.h264enc.motion_est.motion_est_quarter_pixel = 0x00000001; + context->desc.h264enc.motion_est.lsmvert = 0x00000002; + context->desc.h264enc.motion_est.enc_disable_sub_mode = 0x00000078; + context->desc.h264enc.motion_est.enc_en_ime_overw_dis_subm = 0x00000001; + context->desc.h264enc.motion_est.enc_ime_overw_dis_subm_no = 0x00000001; + context->desc.h264enc.motion_est.enc_ime2_search_range_x = 0x00000004; + context->desc.h264enc.motion_est.enc_ime2_search_range_y = 0x00000004; + + //pic control preset + context->desc.h264enc.pic_ctrl.enc_cabac_enable = 0x00000001; + context->desc.h264enc.pic_ctrl.enc_constraint_set_flags = 0x00000040; + + //rate control + context->desc.h264enc.rate_ctrl.vbv_buffer_size = 20000000; + context->desc.h264enc.rate_ctrl.vbv_buf_lv = 48; + context->desc.h264enc.rate_ctrl.fill_data_enable = 1; + context->desc.h264enc.rate_ctrl.enforce_hrd = 1; + context->desc.h264enc.enable_vui = false; + if (context->desc.h264enc.rate_ctrl.frame_rate_num == 0 || + context->desc.h264enc.rate_ctrl.frame_rate_den == 0) { + context->desc.h264enc.rate_ctrl.frame_rate_num = 30; + context->desc.h264enc.rate_ctrl.frame_rate_den = 1; + } + context->desc.h264enc.rate_ctrl.target_bits_picture = + context->desc.h264enc.rate_ctrl.target_bitrate * + ((float)context->desc.h264enc.rate_ctrl.frame_rate_den / + context->desc.h264enc.rate_ctrl.frame_rate_num); + context->desc.h264enc.rate_ctrl.peak_bits_picture_integer = + context->desc.h264enc.rate_ctrl.peak_bitrate * + ((float)context->desc.h264enc.rate_ctrl.frame_rate_den / + context->desc.h264enc.rate_ctrl.frame_rate_num); + + context->desc.h264enc.rate_ctrl.peak_bits_picture_fraction = 0; + context->desc.h264enc.ref_pic_mode = 0x00000201; +} diff --git a/src/gallium/frontends/va/picture_hevc.c b/src/gallium/frontends/va/picture_hevc.c new file mode 100644 index 00000000000..e879259ae1f --- /dev/null +++ b/src/gallium/frontends/va/picture_hevc.c @@ -0,0 +1,221 @@ +/************************************************************************** + * + * Copyright 2014 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "vl/vl_zscan.h" +#include "va_private.h" + +void vlVaHandlePictureParameterBufferHEVC(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) +{ + VAPictureParameterBufferHEVC *hevc = buf->data; + unsigned i; + + assert(buf->size >= sizeof(VAPictureParameterBufferHEVC) && buf->num_elements == 1); + context->desc.h265.pps->sps->chroma_format_idc = hevc->pic_fields.bits.chroma_format_idc; + context->desc.h265.pps->sps->separate_colour_plane_flag = + hevc->pic_fields.bits.separate_colour_plane_flag; + context->desc.h265.pps->sps->pic_width_in_luma_samples = hevc->pic_width_in_luma_samples; + context->desc.h265.pps->sps->pic_height_in_luma_samples = hevc->pic_height_in_luma_samples; + context->desc.h265.pps->sps->bit_depth_luma_minus8 = hevc->bit_depth_luma_minus8; + context->desc.h265.pps->sps->bit_depth_chroma_minus8 = hevc->bit_depth_chroma_minus8; + context->desc.h265.pps->sps->log2_max_pic_order_cnt_lsb_minus4 = + hevc->log2_max_pic_order_cnt_lsb_minus4; + context->desc.h265.pps->sps->sps_max_dec_pic_buffering_minus1 = + hevc->sps_max_dec_pic_buffering_minus1; + context->desc.h265.pps->sps->log2_min_luma_coding_block_size_minus3 = + hevc->log2_min_luma_coding_block_size_minus3; + context->desc.h265.pps->sps->log2_diff_max_min_luma_coding_block_size = + hevc->log2_diff_max_min_luma_coding_block_size; + context->desc.h265.pps->sps->log2_min_transform_block_size_minus2 = + hevc->log2_min_transform_block_size_minus2; + context->desc.h265.pps->sps->log2_diff_max_min_transform_block_size = + hevc->log2_diff_max_min_transform_block_size; + context->desc.h265.pps->sps->max_transform_hierarchy_depth_inter = + hevc->max_transform_hierarchy_depth_inter; + context->desc.h265.pps->sps->max_transform_hierarchy_depth_intra = + hevc->max_transform_hierarchy_depth_intra; + context->desc.h265.pps->sps->scaling_list_enabled_flag = + hevc->pic_fields.bits.scaling_list_enabled_flag; + context->desc.h265.pps->sps->amp_enabled_flag = hevc->pic_fields.bits.amp_enabled_flag; + context->desc.h265.pps->sps->sample_adaptive_offset_enabled_flag = + hevc->slice_parsing_fields.bits.sample_adaptive_offset_enabled_flag; + context->desc.h265.pps->sps->pcm_enabled_flag = hevc->pic_fields.bits.pcm_enabled_flag; + if (hevc->pic_fields.bits.pcm_enabled_flag == 1) { + context->desc.h265.pps->sps->pcm_sample_bit_depth_luma_minus1 = + hevc->pcm_sample_bit_depth_luma_minus1; + context->desc.h265.pps->sps->pcm_sample_bit_depth_chroma_minus1 = + hevc->pcm_sample_bit_depth_chroma_minus1; + context->desc.h265.pps->sps->log2_min_pcm_luma_coding_block_size_minus3 = + hevc->log2_min_pcm_luma_coding_block_size_minus3; + context->desc.h265.pps->sps->log2_diff_max_min_pcm_luma_coding_block_size = + hevc->log2_diff_max_min_pcm_luma_coding_block_size; + context->desc.h265.pps->sps->pcm_loop_filter_disabled_flag = + hevc->pic_fields.bits.pcm_loop_filter_disabled_flag; + } + context->desc.h265.pps->sps->num_short_term_ref_pic_sets = hevc->num_short_term_ref_pic_sets; + context->desc.h265.pps->sps->long_term_ref_pics_present_flag = + hevc->slice_parsing_fields.bits.long_term_ref_pics_present_flag; + context->desc.h265.pps->sps->num_long_term_ref_pics_sps = hevc->num_long_term_ref_pic_sps; + context->desc.h265.pps->sps->sps_temporal_mvp_enabled_flag = + hevc->slice_parsing_fields.bits.sps_temporal_mvp_enabled_flag; + context->desc.h265.pps->sps->strong_intra_smoothing_enabled_flag = + hevc->pic_fields.bits.strong_intra_smoothing_enabled_flag; + + context->desc.h265.pps->dependent_slice_segments_enabled_flag = + hevc->slice_parsing_fields.bits.dependent_slice_segments_enabled_flag; + context->desc.h265.pps->output_flag_present_flag = + hevc->slice_parsing_fields.bits.output_flag_present_flag; + context->desc.h265.pps->num_extra_slice_header_bits = hevc->num_extra_slice_header_bits; + context->desc.h265.pps->sign_data_hiding_enabled_flag = + hevc->pic_fields.bits.sign_data_hiding_enabled_flag; + context->desc.h265.pps->cabac_init_present_flag = + hevc->slice_parsing_fields.bits.cabac_init_present_flag; + context->desc.h265.pps->num_ref_idx_l0_default_active_minus1 = + hevc->num_ref_idx_l0_default_active_minus1; + context->desc.h265.pps->num_ref_idx_l1_default_active_minus1 = + hevc->num_ref_idx_l1_default_active_minus1; + context->desc.h265.pps->init_qp_minus26 = hevc->init_qp_minus26; + context->desc.h265.pps->constrained_intra_pred_flag = + hevc->pic_fields.bits.constrained_intra_pred_flag; + context->desc.h265.pps->transform_skip_enabled_flag = + hevc->pic_fields.bits.transform_skip_enabled_flag; + context->desc.h265.pps->cu_qp_delta_enabled_flag = + hevc->pic_fields.bits.cu_qp_delta_enabled_flag; + context->desc.h265.pps->diff_cu_qp_delta_depth = hevc->diff_cu_qp_delta_depth; + context->desc.h265.pps->pps_cb_qp_offset = hevc->pps_cb_qp_offset; + context->desc.h265.pps->pps_cr_qp_offset = hevc->pps_cr_qp_offset; + context->desc.h265.pps->pps_slice_chroma_qp_offsets_present_flag = + hevc->slice_parsing_fields.bits.pps_slice_chroma_qp_offsets_present_flag; + context->desc.h265.pps->weighted_pred_flag = hevc->pic_fields.bits.weighted_pred_flag; + context->desc.h265.pps->weighted_bipred_flag = hevc->pic_fields.bits.weighted_bipred_flag; + context->desc.h265.pps->transquant_bypass_enabled_flag = + hevc->pic_fields.bits.transquant_bypass_enabled_flag; + context->desc.h265.pps->tiles_enabled_flag = hevc->pic_fields.bits.tiles_enabled_flag; + context->desc.h265.pps->entropy_coding_sync_enabled_flag = + hevc->pic_fields.bits.entropy_coding_sync_enabled_flag; + if (hevc->pic_fields.bits.tiles_enabled_flag == 1) { + context->desc.h265.pps->num_tile_columns_minus1 = hevc->num_tile_columns_minus1; + context->desc.h265.pps->num_tile_rows_minus1 = hevc->num_tile_rows_minus1; + for (i = 0 ; i < 19 ; i++) + context->desc.h265.pps->column_width_minus1[i] = hevc->column_width_minus1[i]; + for (i = 0 ; i < 21 ; i++) + context->desc.h265.pps->row_height_minus1[i] = hevc->row_height_minus1[i]; + context->desc.h265.pps->loop_filter_across_tiles_enabled_flag = + hevc->pic_fields.bits.loop_filter_across_tiles_enabled_flag; + } + context->desc.h265.pps->pps_loop_filter_across_slices_enabled_flag = + hevc->pic_fields.bits.pps_loop_filter_across_slices_enabled_flag; + context->desc.h265.pps->deblocking_filter_override_enabled_flag = + hevc->slice_parsing_fields.bits.deblocking_filter_override_enabled_flag; + context->desc.h265.pps->pps_deblocking_filter_disabled_flag = + hevc->slice_parsing_fields.bits.pps_disable_deblocking_filter_flag; + context->desc.h265.pps->pps_beta_offset_div2 = hevc->pps_beta_offset_div2; + context->desc.h265.pps->pps_tc_offset_div2 = hevc->pps_tc_offset_div2; + context->desc.h265.pps->lists_modification_present_flag = + hevc->slice_parsing_fields.bits.lists_modification_present_flag; + context->desc.h265.pps->log2_parallel_merge_level_minus2 = + hevc->log2_parallel_merge_level_minus2; + context->desc.h265.pps->slice_segment_header_extension_present_flag = + hevc->slice_parsing_fields.bits.slice_segment_header_extension_present_flag; + + context->desc.h265.IDRPicFlag = hevc->slice_parsing_fields.bits.IdrPicFlag; + context->desc.h265.RAPPicFlag = hevc->slice_parsing_fields.bits.RapPicFlag; + + context->desc.h265.CurrPicOrderCntVal = hevc->CurrPic.pic_order_cnt; + + for (i = 0 ; i < 8 ; i++) { + context->desc.h265.RefPicSetStCurrBefore[i] = 0xFF; + context->desc.h265.RefPicSetStCurrAfter[i] = 0xFF; + context->desc.h265.RefPicSetLtCurr[i] = 0xFF; + } + context->desc.h265.NumPocStCurrBefore = 0; + context->desc.h265.NumPocStCurrAfter = 0; + context->desc.h265.NumPocLtCurr = 0; + unsigned int iBefore = 0; + unsigned int iAfter = 0; + unsigned int iCurr = 0; + for (i = 0 ; i < 15 ; i++) { + context->desc.h265.PicOrderCntVal[i] = hevc->ReferenceFrames[i].pic_order_cnt; + + vlVaGetReferenceFrame(drv, hevc->ReferenceFrames[i].picture_id, &context->desc.h265.ref[i]); + + if ((hevc->ReferenceFrames[i].flags & VA_PICTURE_HEVC_RPS_ST_CURR_BEFORE) && (iBefore < 8)) { + context->desc.h265.RefPicSetStCurrBefore[iBefore++] = i; + context->desc.h265.NumPocStCurrBefore++; + } + if ((hevc->ReferenceFrames[i].flags & VA_PICTURE_HEVC_RPS_ST_CURR_AFTER) && (iAfter < 8)) { + context->desc.h265.RefPicSetStCurrAfter[iAfter++] = i; + context->desc.h265.NumPocStCurrAfter++; + } + if ((hevc->ReferenceFrames[i].flags & VA_PICTURE_HEVC_RPS_LT_CURR) && (iCurr < 8)) { + context->desc.h265.RefPicSetLtCurr[iCurr++] = i; + context->desc.h265.NumPocLtCurr++; + } + } +} + +void vlVaHandleIQMatrixBufferHEVC(vlVaContext *context, vlVaBuffer *buf) +{ + VAIQMatrixBufferHEVC *h265 = buf->data; + int i, j; + + assert(buf->size >= sizeof(VAIQMatrixBufferHEVC) && buf->num_elements == 1); + + for (i = 0; i < 6; i++) { + for (j = 0; j < 16; j++) + context->desc.h265.pps->sps->ScalingList4x4[i][j] = + h265->ScalingList4x4[i][vl_zscan_h265_up_right_diagonal_16[j]]; + + for (j = 0; j < 64; j++) { + context->desc.h265.pps->sps->ScalingList8x8[i][j] = + h265->ScalingList8x8[i][vl_zscan_h265_up_right_diagonal[j]]; + context->desc.h265.pps->sps->ScalingList16x16[i][j] = + h265->ScalingList16x16[i][vl_zscan_h265_up_right_diagonal[j]]; + + if (i < 2) + context->desc.h265.pps->sps->ScalingList32x32[i][j] = + h265->ScalingList32x32[i][vl_zscan_h265_up_right_diagonal[j]]; + } + + context->desc.h265.pps->sps->ScalingListDCCoeff16x16[i] = + h265->ScalingListDC16x16[i]; + if (i < 2) + context->desc.h265.pps->sps->ScalingListDCCoeff32x32[i] = + h265->ScalingListDC32x32[i]; + } +} + +void vlVaHandleSliceParameterBufferHEVC(vlVaContext *context, vlVaBuffer *buf) +{ + VASliceParameterBufferHEVC *h265 = buf->data; + + assert(buf->size >= sizeof(VASliceParameterBufferHEVC) && buf->num_elements == 1); + for (int i = 0 ; i < 2 ; i++) { + for (int j = 0 ; j < 15 ; j++) + context->desc.h265.RefPicList[i][j] = h265->RefPicList[i][j]; + } + context->desc.h265.UseRefPicList = true; +} diff --git a/src/gallium/frontends/va/picture_hevc_enc.c b/src/gallium/frontends/va/picture_hevc_enc.c new file mode 100644 index 00000000000..510597753ce --- /dev/null +++ b/src/gallium/frontends/va/picture_hevc_enc.c @@ -0,0 +1,213 @@ +/************************************************************************** + * + * Copyright 2018 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "util/u_handle_table.h" +#include "util/u_video.h" +#include "va_private.h" + +VAStatus +vlVaHandleVAEncPictureParameterBufferTypeHEVC(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) +{ + VAEncPictureParameterBufferHEVC *h265; + vlVaBuffer *coded_buf; + int i; + + h265 = buf->data; + context->desc.h265enc.decoded_curr_pic = h265->decoded_curr_pic.picture_id; + + for (i = 0; i < 15; i++) + context->desc.h265enc.reference_frames[i] = h265->reference_frames[i].picture_id; + + context->desc.h265enc.pic_order_cnt = h265->decoded_curr_pic.pic_order_cnt; + coded_buf = handle_table_get(drv->htab, h265->coded_buf); + + if (!coded_buf->derived_surface.resource) + coded_buf->derived_surface.resource = pipe_buffer_create(drv->pipe->screen, PIPE_BIND_VERTEX_BUFFER, + PIPE_USAGE_STREAM, coded_buf->size); + + context->coded_buf = coded_buf; + context->desc.h265enc.pic.log2_parallel_merge_level_minus2 = h265->log2_parallel_merge_level_minus2; + context->desc.h265enc.pic.nal_unit_type = h265->nal_unit_type; + context->desc.h265enc.rc.quant_i_frames = h265->pic_init_qp; + + switch(h265->pic_fields.bits.coding_type) { + case 1: + if (h265->pic_fields.bits.idr_pic_flag) + context->desc.h265enc.picture_type = PIPE_H265_ENC_PICTURE_TYPE_IDR; + else + context->desc.h265enc.picture_type = PIPE_H265_ENC_PICTURE_TYPE_I; + break; + case 2: + context->desc.h265enc.picture_type = PIPE_H265_ENC_PICTURE_TYPE_P; + break; + case 3: + case 4: + case 5: + return VA_STATUS_ERROR_UNIMPLEMENTED; //no b frame support + break; + } + + context->desc.h265enc.pic.constrained_intra_pred_flag = h265->pic_fields.bits.constrained_intra_pred_flag; + + _mesa_hash_table_insert(context->desc.h265enc.frame_idx, + UINT_TO_PTR(h265->decoded_curr_pic.picture_id), + UINT_TO_PTR(context->desc.h265enc.frame_num)); + + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaHandleVAEncSliceParameterBufferTypeHEVC(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) +{ + VAEncSliceParameterBufferHEVC *h265; + + h265 = buf->data; + context->desc.h265enc.ref_idx_l0 = VA_INVALID_ID; + context->desc.h265enc.ref_idx_l1 = VA_INVALID_ID; + + for (int i = 0; i < 15; i++) { + if (h265->ref_pic_list0[i].picture_id != VA_INVALID_ID) { + if (context->desc.h265enc.ref_idx_l0 == VA_INVALID_ID) + context->desc.h265enc.ref_idx_l0 = PTR_TO_UINT(util_hash_table_get(context->desc.h265enc.frame_idx, + UINT_TO_PTR(h265->ref_pic_list0[i].picture_id))); + } + if (h265->ref_pic_list1[i].picture_id != VA_INVALID_ID && h265->slice_type == 1) { + if (context->desc.h265enc.ref_idx_l1 == VA_INVALID_ID) + context->desc.h265enc.ref_idx_l1 = PTR_TO_UINT(util_hash_table_get(context->desc.h265enc.frame_idx, + UINT_TO_PTR(h265->ref_pic_list1[i].picture_id))); + } + } + + context->desc.h265enc.slice.max_num_merge_cand = h265->max_num_merge_cand; + context->desc.h265enc.slice.slice_cb_qp_offset = h265->slice_cb_qp_offset; + context->desc.h265enc.slice.slice_cr_qp_offset = h265->slice_cr_qp_offset; + context->desc.h265enc.slice.slice_beta_offset_div2 = h265->slice_beta_offset_div2; + context->desc.h265enc.slice.slice_tc_offset_div2 = h265->slice_tc_offset_div2; + context->desc.h265enc.slice.cabac_init_flag = h265->slice_fields.bits.cabac_init_flag; + context->desc.h265enc.slice.slice_deblocking_filter_disabled_flag = h265->slice_fields.bits.slice_deblocking_filter_disabled_flag; + context->desc.h265enc.slice.slice_loop_filter_across_slices_enabled_flag = h265->slice_fields.bits.slice_loop_filter_across_slices_enabled_flag; + + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaHandleVAEncSequenceParameterBufferTypeHEVC(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) +{ + VAEncSequenceParameterBufferHEVC *h265 = (VAEncSequenceParameterBufferHEVC *)buf->data; + + if (!context->decoder) { + context->templat.level = h265->general_level_idc; + context->decoder = drv->pipe->create_video_codec(drv->pipe, &context->templat); + + if (!context->decoder) + return VA_STATUS_ERROR_ALLOCATION_FAILED; + } + + context->desc.h265enc.seq.general_profile_idc = h265->general_profile_idc; + context->desc.h265enc.seq.general_level_idc = h265->general_level_idc; + context->desc.h265enc.seq.general_tier_flag = h265->general_tier_flag; + context->desc.h265enc.seq.intra_period = h265->intra_period; + context->desc.h265enc.seq.pic_width_in_luma_samples = h265->pic_width_in_luma_samples; + context->desc.h265enc.seq.pic_height_in_luma_samples = h265->pic_height_in_luma_samples; + context->desc.h265enc.seq.chroma_format_idc = h265->seq_fields.bits.chroma_format_idc; + context->desc.h265enc.seq.bit_depth_luma_minus8 = h265->seq_fields.bits.bit_depth_luma_minus8; + context->desc.h265enc.seq.bit_depth_chroma_minus8 = h265->seq_fields.bits.bit_depth_chroma_minus8; + context->desc.h265enc.seq.strong_intra_smoothing_enabled_flag = h265->seq_fields.bits.strong_intra_smoothing_enabled_flag; + context->desc.h265enc.seq.amp_enabled_flag = h265->seq_fields.bits.amp_enabled_flag; + context->desc.h265enc.seq.sample_adaptive_offset_enabled_flag = h265->seq_fields.bits.sample_adaptive_offset_enabled_flag; + context->desc.h265enc.seq.pcm_enabled_flag = h265->seq_fields.bits.pcm_enabled_flag; + context->desc.h265enc.seq.sps_temporal_mvp_enabled_flag = h265->seq_fields.bits.sps_temporal_mvp_enabled_flag; + context->desc.h265enc.seq.log2_min_luma_coding_block_size_minus3 = h265->log2_min_luma_coding_block_size_minus3; + context->desc.h265enc.seq.log2_diff_max_min_luma_coding_block_size = h265->log2_diff_max_min_luma_coding_block_size; + context->desc.h265enc.seq.log2_min_transform_block_size_minus2 = h265->log2_min_transform_block_size_minus2; + context->desc.h265enc.seq.log2_diff_max_min_transform_block_size = h265->log2_diff_max_min_transform_block_size; + context->desc.h265enc.seq.max_transform_hierarchy_depth_inter = h265->max_transform_hierarchy_depth_inter; + context->desc.h265enc.seq.max_transform_hierarchy_depth_intra = h265->max_transform_hierarchy_depth_intra; + context->desc.h265enc.rc.frame_rate_num = h265->vui_time_scale; + context->desc.h265enc.rc.frame_rate_den = h265->vui_num_units_in_tick; + + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaHandleVAEncMiscParameterTypeRateControlHEVC(vlVaContext *context, VAEncMiscParameterBuffer *misc) +{ + VAEncMiscParameterRateControl *rc = (VAEncMiscParameterRateControl *)misc->data; + + if (context->desc.h265enc.rc.rate_ctrl_method == + PIPE_H265_ENC_RATE_CONTROL_METHOD_CONSTANT) + context->desc.h265enc.rc.target_bitrate = rc->bits_per_second; + else + context->desc.h265enc.rc.target_bitrate = rc->bits_per_second * (rc->target_percentage / 100.0); + context->desc.h265enc.rc.peak_bitrate = rc->bits_per_second; + if (context->desc.h265enc.rc.target_bitrate < 2000000) + context->desc.h265enc.rc.vbv_buffer_size = MIN2((context->desc.h265enc.rc.target_bitrate * 2.75), 2000000); + else + context->desc.h265enc.rc.vbv_buffer_size = context->desc.h265enc.rc.target_bitrate; + + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaHandleVAEncMiscParameterTypeFrameRateHEVC(vlVaContext *context, VAEncMiscParameterBuffer *misc) +{ + VAEncMiscParameterFrameRate *fr = (VAEncMiscParameterFrameRate *)misc->data; + + if (fr->framerate & 0xffff0000) { + context->desc.h265enc.rc.frame_rate_num = fr->framerate & 0xffff; + context->desc.h265enc.rc.frame_rate_den = fr->framerate >> 16 & 0xffff; + } else { + context->desc.h265enc.rc.frame_rate_num = fr->framerate; + context->desc.h265enc.rc.frame_rate_den = 1; + } + + return VA_STATUS_SUCCESS; +} + +void getEncParamPresetH265(vlVaContext *context) +{ + //rate control + context->desc.h265enc.rc.vbv_buffer_size = 20000000; + context->desc.h265enc.rc.vbv_buf_lv = 48; + context->desc.h265enc.rc.fill_data_enable = 1; + context->desc.h265enc.rc.enforce_hrd = 1; + if (context->desc.h265enc.rc.frame_rate_num == 0 || + context->desc.h265enc.rc.frame_rate_den == 0) { + context->desc.h265enc.rc.frame_rate_num = 30; + context->desc.h265enc.rc.frame_rate_den = 1; + } + context->desc.h265enc.rc.target_bits_picture = + context->desc.h265enc.rc.target_bitrate * + ((float)context->desc.h265enc.rc.frame_rate_den / + context->desc.h265enc.rc.frame_rate_num); + context->desc.h265enc.rc.peak_bits_picture_integer = + context->desc.h265enc.rc.peak_bitrate * + ((float)context->desc.h265enc.rc.frame_rate_den / + context->desc.h265enc.rc.frame_rate_num); + + context->desc.h265enc.rc.peak_bits_picture_fraction = 0; +} diff --git a/src/gallium/frontends/va/picture_mjpeg.c b/src/gallium/frontends/va/picture_mjpeg.c new file mode 100644 index 00000000000..defb0b546de --- /dev/null +++ b/src/gallium/frontends/va/picture_mjpeg.c @@ -0,0 +1,258 @@ +/************************************************************************** + * + * Copyright 2017 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "va_private.h" + +void vlVaHandlePictureParameterBufferMJPEG(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) +{ + VAPictureParameterBufferJPEGBaseline *mjpeg = buf->data; + unsigned sf; + int i; + + assert(buf->size >= sizeof(VAPictureParameterBufferJPEGBaseline) && buf->num_elements == 1); + + context->desc.mjpeg.picture_parameter.picture_width = mjpeg->picture_width; + context->desc.mjpeg.picture_parameter.picture_height = mjpeg->picture_height; + + for (i = 0; i < mjpeg->num_components; ++i) { + context->desc.mjpeg.picture_parameter.components[i].component_id = + mjpeg->components[i].component_id; + context->desc.mjpeg.picture_parameter.components[i].h_sampling_factor = + mjpeg->components[i].h_sampling_factor; + context->desc.mjpeg.picture_parameter.components[i].v_sampling_factor = + mjpeg->components[i].v_sampling_factor; + context->desc.mjpeg.picture_parameter.components[i].quantiser_table_selector = + mjpeg->components[i].quantiser_table_selector; + + sf = mjpeg->components[i].h_sampling_factor << 4 | mjpeg->components[i].v_sampling_factor; + context->mjpeg.sampling_factor <<= 8; + context->mjpeg.sampling_factor |= sf; + } + + context->desc.mjpeg.picture_parameter.num_components = mjpeg->num_components; +} + +void vlVaHandleIQMatrixBufferMJPEG(vlVaContext *context, vlVaBuffer *buf) +{ + VAIQMatrixBufferJPEGBaseline *mjpeg = buf->data; + + assert(buf->size >= sizeof(VAIQMatrixBufferJPEGBaseline) && buf->num_elements == 1); + + memcpy(&context->desc.mjpeg.quantization_table.load_quantiser_table, mjpeg->load_quantiser_table, 4); + memcpy(&context->desc.mjpeg.quantization_table.quantiser_table, mjpeg->quantiser_table, 4 * 64); +} + +void vlVaHandleHuffmanTableBufferType(vlVaContext *context, vlVaBuffer *buf) +{ + VAHuffmanTableBufferJPEGBaseline *mjpeg = buf->data; + int i; + + assert(buf->size >= sizeof(VASliceParameterBufferJPEGBaseline) && buf->num_elements == 1); + + for (i = 0; i < 2; ++i) { + context->desc.mjpeg.huffman_table.load_huffman_table[i] = mjpeg->load_huffman_table[i]; + + memcpy(&context->desc.mjpeg.huffman_table.table[i].num_dc_codes, + mjpeg->huffman_table[i].num_dc_codes, 16); + memcpy(&context->desc.mjpeg.huffman_table.table[i].dc_values, + mjpeg->huffman_table[i].dc_values, 12); + memcpy(&context->desc.mjpeg.huffman_table.table[i].num_ac_codes, + mjpeg->huffman_table[i].num_ac_codes, 16); + memcpy(&context->desc.mjpeg.huffman_table.table[i].ac_values, + mjpeg->huffman_table[i].ac_values, 162); + memcpy(&context->desc.mjpeg.huffman_table.table[i].pad, mjpeg->huffman_table[i].pad, 2); + } +} + +void vlVaHandleSliceParameterBufferMJPEG(vlVaContext *context, vlVaBuffer *buf) +{ + VASliceParameterBufferJPEGBaseline *mjpeg = buf->data; + int i; + + assert(buf->size >= sizeof(VASliceParameterBufferJPEGBaseline) && buf->num_elements == 1); + + context->desc.mjpeg.slice_parameter.slice_data_size = mjpeg->slice_data_size; + context->desc.mjpeg.slice_parameter.slice_data_offset = mjpeg->slice_data_offset; + context->desc.mjpeg.slice_parameter.slice_data_flag = mjpeg->slice_data_flag; + context->desc.mjpeg.slice_parameter.slice_horizontal_position = mjpeg->slice_horizontal_position; + context->desc.mjpeg.slice_parameter.slice_vertical_position = mjpeg->slice_vertical_position; + + for (i = 0; i < mjpeg->num_components; ++i) { + context->desc.mjpeg.slice_parameter.components[i].component_selector = + mjpeg->components[i].component_selector; + context->desc.mjpeg.slice_parameter.components[i].dc_table_selector = + mjpeg->components[i].dc_table_selector; + context->desc.mjpeg.slice_parameter.components[i].ac_table_selector = + mjpeg->components[i].ac_table_selector; + } + + context->desc.mjpeg.slice_parameter.num_components = mjpeg->num_components; + context->desc.mjpeg.slice_parameter.restart_interval = mjpeg->restart_interval; + context->desc.mjpeg.slice_parameter.num_mcus = mjpeg->num_mcus; +} + +void vlVaGetJpegSliceHeader(vlVaContext *context) +{ + int size = 0, saved_size, len_pos, i; + uint16_t *bs; + uint8_t *p = context->mjpeg.slice_header; + + /* SOI */ + p[size++] = 0xff; + p[size++] = 0xd8; + + /* DQT */ + p[size++] = 0xff; + p[size++] = 0xdb; + + len_pos = size++; + size++; + + for (i = 0; i < 4; ++i) { + if (context->desc.mjpeg.quantization_table.load_quantiser_table[i] == 0) + continue; + + p[size++] = i; + memcpy((p + size), &context->desc.mjpeg.quantization_table.quantiser_table[i], 64); + size += 64; + } + + bs = (uint16_t*)&p[len_pos]; + *bs = util_bswap16(size - 4); + + saved_size = size; + + /* DHT */ + p[size++] = 0xff; + p[size++] = 0xc4; + + len_pos = size++; + size++; + + for (i = 0; i < 2; ++i) { + int num = 0, j; + + if (context->desc.mjpeg.huffman_table.load_huffman_table[i] == 0) + continue; + + p[size++] = 0x00 | i; + memcpy((p + size), &context->desc.mjpeg.huffman_table.table[i].num_dc_codes, 16); + size += 16; + for (j = 0; j < 16; ++j) + num += context->desc.mjpeg.huffman_table.table[i].num_dc_codes[j]; + assert(num <= 12); + memcpy((p + size), &context->desc.mjpeg.huffman_table.table[i].dc_values, num); + size += num; + } + + for (i = 0; i < 2; ++i) { + int num = 0, j; + + if (context->desc.mjpeg.huffman_table.load_huffman_table[i] == 0) + continue; + + p[size++] = 0x10 | i; + memcpy((p + size), &context->desc.mjpeg.huffman_table.table[i].num_ac_codes, 16); + size += 16; + for (j = 0; j < 16; ++j) + num += context->desc.mjpeg.huffman_table.table[i].num_ac_codes[j]; + assert(num <= 162); + memcpy((p + size), &context->desc.mjpeg.huffman_table.table[i].ac_values, num); + size += num; + } + + bs = (uint16_t*)&p[len_pos]; + *bs = util_bswap16(size - saved_size - 2); + + saved_size = size; + + /* DRI */ + if (context->desc.mjpeg.slice_parameter.restart_interval) { + p[size++] = 0xff; + p[size++] = 0xdd; + p[size++] = 0x00; + p[size++] = 0x04; + bs = (uint16_t*)&p[size++]; + *bs = util_bswap16(context->desc.mjpeg.slice_parameter.restart_interval); + saved_size = ++size; + } + + /* SOF */ + p[size++] = 0xff; + p[size++] = 0xc0; + + len_pos = size++; + size++; + + p[size++] = 0x08; + + bs = (uint16_t*)&p[size++]; + *bs = util_bswap16(context->desc.mjpeg.picture_parameter.picture_height); + size++; + + bs = (uint16_t*)&p[size++]; + *bs = util_bswap16(context->desc.mjpeg.picture_parameter.picture_width); + size++; + + p[size++] = context->desc.mjpeg.picture_parameter.num_components; + + for (i = 0; i < context->desc.mjpeg.picture_parameter.num_components; ++i) { + p[size++] = context->desc.mjpeg.picture_parameter.components[i].component_id; + p[size++] = context->desc.mjpeg.picture_parameter.components[i].h_sampling_factor << 4 | + context->desc.mjpeg.picture_parameter.components[i].v_sampling_factor; + p[size++] = context->desc.mjpeg.picture_parameter.components[i].quantiser_table_selector; + } + + bs = (uint16_t*)&p[len_pos]; + *bs = util_bswap16(size - saved_size - 2); + + saved_size = size; + + /* SOS */ + p[size++] = 0xff; + p[size++] = 0xda; + + len_pos = size++; + size++; + + p[size++] = context->desc.mjpeg.slice_parameter.num_components; + + for (i = 0; i < context->desc.mjpeg.slice_parameter.num_components; ++i) { + p[size++] = context->desc.mjpeg.slice_parameter.components[i].component_selector; + p[size++] = context->desc.mjpeg.slice_parameter.components[i].dc_table_selector << 4 | + context->desc.mjpeg.slice_parameter.components[i].ac_table_selector; + } + + p[size++] = 0x00; + p[size++] = 0x3f; + p[size++] = 0x00; + + bs = (uint16_t*)&p[len_pos]; + *bs = util_bswap16(size - saved_size - 2); + + context->mjpeg.slice_header_size = size; +} diff --git a/src/gallium/frontends/va/picture_mpeg12.c b/src/gallium/frontends/va/picture_mpeg12.c new file mode 100644 index 00000000000..daf95f7403c --- /dev/null +++ b/src/gallium/frontends/va/picture_mpeg12.c @@ -0,0 +1,112 @@ +/************************************************************************** + * + * Copyright 2014 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "va_private.h" + +const int reverse_inverse_zscan[] = +{ + /* Reverse inverse z scan pattern */ + 0, 2, 3, 9, 10, 20, 21, 35, + 1, 4, 8, 11, 19, 22, 34, 36, + 5, 7, 12, 18, 23, 33, 37, 48, + 6, 13, 17, 24, 32, 38, 47, 49, + 14, 16, 25, 31, 39, 46, 50, 57, + 15, 26, 30, 40, 45, 51, 56, 58, + 27, 29, 41, 44, 52, 55, 59, 62, + 28, 42, 43, 53, 54, 60, 61, 63, +}; + +void vlVaHandlePictureParameterBufferMPEG12(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) +{ + VAPictureParameterBufferMPEG2 *mpeg2 = buf->data; + + assert(buf->size >= sizeof(VAPictureParameterBufferMPEG2) && buf->num_elements == 1); + context->desc.mpeg12.num_slices = 0; + /*horizontal_size;*/ + /*vertical_size;*/ + vlVaGetReferenceFrame(drv, mpeg2->forward_reference_picture, &context->desc.mpeg12.ref[0]); + vlVaGetReferenceFrame(drv, mpeg2->backward_reference_picture, &context->desc.mpeg12.ref[1]); + context->desc.mpeg12.picture_coding_type = mpeg2->picture_coding_type; + context->desc.mpeg12.f_code[0][0] = ((mpeg2->f_code >> 12) & 0xf) - 1; + context->desc.mpeg12.f_code[0][1] = ((mpeg2->f_code >> 8) & 0xf) - 1; + context->desc.mpeg12.f_code[1][0] = ((mpeg2->f_code >> 4) & 0xf) - 1; + context->desc.mpeg12.f_code[1][1] = (mpeg2->f_code & 0xf) - 1; + context->desc.mpeg12.intra_dc_precision = + mpeg2->picture_coding_extension.bits.intra_dc_precision; + context->desc.mpeg12.picture_structure = + mpeg2->picture_coding_extension.bits.picture_structure; + context->desc.mpeg12.top_field_first = + mpeg2->picture_coding_extension.bits.top_field_first; + context->desc.mpeg12.frame_pred_frame_dct = + mpeg2->picture_coding_extension.bits.frame_pred_frame_dct; + context->desc.mpeg12.concealment_motion_vectors = + mpeg2->picture_coding_extension.bits.concealment_motion_vectors; + context->desc.mpeg12.q_scale_type = + mpeg2->picture_coding_extension.bits.q_scale_type; + context->desc.mpeg12.intra_vlc_format = + mpeg2->picture_coding_extension.bits.intra_vlc_format; + context->desc.mpeg12.alternate_scan = + mpeg2->picture_coding_extension.bits.alternate_scan; + /*repeat_first_field*/ + /*progressive_frame*/ + /*is_first_field*/ +} + +void vlVaHandleIQMatrixBufferMPEG12(vlVaContext *context, vlVaBuffer *buf) +{ + VAIQMatrixBufferMPEG2 *mpeg2 = buf->data; + static uint8_t temp_intra_matrix[64]; + static uint8_t temp_nonintra_matrix[64]; + + assert(buf->size >= sizeof(VAIQMatrixBufferMPEG2) && buf->num_elements == 1); + if (mpeg2->load_intra_quantiser_matrix) { + /* The quantiser matrix that VAAPI provides has been applied + with inverse z-scan. However, what we expect in MPEG2 + picture description is the original order. Therefore, + we need to reverse it back to its original order. + */ + for (int i = 0; i < 64; i++) + temp_intra_matrix[i] = + mpeg2->intra_quantiser_matrix[reverse_inverse_zscan[i]]; + context->desc.mpeg12.intra_matrix = temp_intra_matrix; + } else + context->desc.mpeg12.intra_matrix = NULL; + + if (mpeg2->load_non_intra_quantiser_matrix) { + for (int i = 0; i < 64; i++) + temp_nonintra_matrix[i] = + mpeg2->non_intra_quantiser_matrix[reverse_inverse_zscan[i]]; + context->desc.mpeg12.non_intra_matrix = temp_nonintra_matrix; + } else + context->desc.mpeg12.non_intra_matrix = NULL; +} + +void vlVaHandleSliceParameterBufferMPEG12(vlVaContext *context, vlVaBuffer *buf) +{ + assert(buf->size >= sizeof(VASliceParameterBufferMPEG2)); + context->desc.mpeg12.num_slices += buf->num_elements; +} diff --git a/src/gallium/frontends/va/picture_mpeg4.c b/src/gallium/frontends/va/picture_mpeg4.c new file mode 100644 index 00000000000..82659ef7b20 --- /dev/null +++ b/src/gallium/frontends/va/picture_mpeg4.c @@ -0,0 +1,209 @@ +/************************************************************************** + * + * Copyright 2014 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "va_private.h" + +void vlVaHandlePictureParameterBufferMPEG4(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) +{ + static const uint8_t default_intra_quant_matrix[64] = { 0 }; + static const uint8_t default_non_intra_quant_matrix[64] = { 0 }; + + VAPictureParameterBufferMPEG4 *mpeg4 = buf->data; + unsigned i; + + assert(buf->size >= sizeof(VAPictureParameterBufferMPEG4) && buf->num_elements == 1); + + context->mpeg4.pps = *mpeg4; + + /* vop_width */ + /* vop_height */ + /* forward_reference_picture */ + /* backward_reference_picture */ + context->desc.mpeg4.short_video_header = + mpeg4->vol_fields.bits.short_video_header; + /* chroma_format */ + context->desc.mpeg4.interlaced = mpeg4->vol_fields.bits.interlaced; + /* obmc_disable */ + /* sprite_enable */ + /* sprite_warping_accuracy */ + context->desc.mpeg4.quant_type = mpeg4->vol_fields.bits.quant_type; + context->desc.mpeg4.quarter_sample = mpeg4->vol_fields.bits.quarter_sample; + /* data_partitioned */ + /* reversible_vlc */ + context->desc.mpeg4.resync_marker_disable = + mpeg4->vol_fields.bits.resync_marker_disable; + /* no_of_sprite_warping_points */ + /* sprite_trajectory_du */ + /* sprite_trajectory_dv */ + /* quant_precision */ + context->desc.mpeg4.vop_coding_type = mpeg4->vop_fields.bits.vop_coding_type; + /* backward_reference_vop_coding_type */ + /* vop_rounding_type */ + /* intra_dc_vlc_thr */ + context->desc.mpeg4.top_field_first = + mpeg4->vop_fields.bits.top_field_first; + context->desc.mpeg4.alternate_vertical_scan_flag = + mpeg4->vop_fields.bits.alternate_vertical_scan_flag; + context->desc.mpeg4.vop_fcode_forward = mpeg4->vop_fcode_forward; + context->desc.mpeg4.vop_fcode_backward = mpeg4->vop_fcode_backward; + context->desc.mpeg4.vop_time_increment_resolution = + mpeg4->vop_time_increment_resolution; + /* num_gobs_in_vop */ + /* num_macroblocks_in_gob */ + context->desc.mpeg4.trb[0] = mpeg4->TRB; + context->desc.mpeg4.trb[1] = mpeg4->TRB; + context->desc.mpeg4.trd[0] = mpeg4->TRD; + context->desc.mpeg4.trd[1] = mpeg4->TRD; + + /* default [non-]intra quant matrix because mpv does not set these + matrices */ + if (!context->desc.mpeg4.intra_matrix) + context->desc.mpeg4.intra_matrix = default_intra_quant_matrix; + if (!context->desc.mpeg4.non_intra_matrix) + context->desc.mpeg4.non_intra_matrix = default_non_intra_quant_matrix; + + vlVaGetReferenceFrame(drv, mpeg4->forward_reference_picture, &context->desc.mpeg4.ref[0]); + vlVaGetReferenceFrame(drv, mpeg4->backward_reference_picture, &context->desc.mpeg4.ref[1]); + + context->mpeg4.vti_bits = 0; + for (i = context->desc.mpeg4.vop_time_increment_resolution; i > 0; i /= 2) + ++context->mpeg4.vti_bits; +} + +void vlVaHandleIQMatrixBufferMPEG4(vlVaContext *context, vlVaBuffer *buf) +{ + VAIQMatrixBufferMPEG4 *mpeg4 = buf->data; + + assert(buf->size >= sizeof(VAIQMatrixBufferMPEG4) && buf->num_elements == 1); + if (mpeg4->load_intra_quant_mat) + context->desc.mpeg4.intra_matrix = mpeg4->intra_quant_mat; + else + context->desc.mpeg4.intra_matrix = NULL; + + if (mpeg4->load_non_intra_quant_mat) + context->desc.mpeg4.non_intra_matrix = mpeg4->non_intra_quant_mat; + else + context->desc.mpeg4.non_intra_matrix = NULL; +} + +void vlVaHandleSliceParameterBufferMPEG4(vlVaContext *context, vlVaBuffer *buf) +{ + VASliceParameterBufferMPEG4 *mpeg4 = buf->data; + + assert(buf->size >= sizeof(VASliceParameterBufferMPEG4) && buf->num_elements == 1); + context->mpeg4.quant_scale = mpeg4->quant_scale; +} + +struct bit_stream +{ + uint8_t *data; + unsigned int length; /* bits */ + unsigned int pos; /* bits */ +}; + +static inline void +write_bit(struct bit_stream *writer, unsigned int bit) +{ + assert(writer->length > (writer)->pos); + writer->data[writer->pos>>3] |= ((bit & 1)<<(7 - (writer->pos & 7))); + writer->pos++; +} + +static inline void +write_bits(struct bit_stream *writer, unsigned int bits, unsigned int len) +{ + int i; + assert(len <= sizeof(bits)*8); + for (i = len - 1; i >= 0; i--) + write_bit(writer, bits>>i); +} + +void vlVaDecoderFixMPEG4Startcode(vlVaContext *context) +{ + uint8_t vop[] = { 0x00, 0x00, 0x01, 0xb6, 0x00, 0x00, 0x00, 0x00, 0x00 }; + struct bit_stream bs_vop = {vop, sizeof(vop)*8, 32}; + unsigned int vop_time_inc; + int mod_time; + unsigned int vop_size; + unsigned int vop_coding_type = context->desc.mpeg4.vop_coding_type; + + context->mpeg4.start_code_size = 0; + memset(context->mpeg4.start_code, 0, sizeof(context->mpeg4.start_code)); + if (vop_coding_type+1 == PIPE_MPEG12_PICTURE_CODING_TYPE_I) { + unsigned int vop_time = context->mpeg4.frame_num/ + context->desc.mpeg4.vop_time_increment_resolution; + unsigned int vop_hour = vop_time / 3600; + unsigned int vop_minute = (vop_time / 60) % 60; + unsigned int vop_second = vop_time % 60; + uint8_t group_of_vop[] = { 0x00, 0x00, 0x01, 0xb3, 0x00, 0x00, 0x00 }; + struct bit_stream bs_gvop = {group_of_vop, sizeof(group_of_vop)*8, 32}; + + write_bits(&bs_gvop, vop_hour, 5); + write_bits(&bs_gvop, vop_minute, 6); + write_bit(&bs_gvop, 1); /* marker_bit */ + write_bits(&bs_gvop, vop_second, 6); + write_bit(&bs_gvop, 0); /* closed_gov */ /* TODO replace magic */ + write_bit(&bs_gvop, 0); /* broken_link */ + write_bit(&bs_gvop, 0); /* padding */ + write_bits(&bs_gvop, 7, 3); /* padding */ + + memcpy(context->mpeg4.start_code, group_of_vop, sizeof(group_of_vop)); + context->mpeg4.start_code_size += sizeof(group_of_vop); + } + + write_bits(&bs_vop, vop_coding_type, 2); + mod_time = context->mpeg4.frame_num % + context->desc.mpeg4.vop_time_increment_resolution == 0 && + vop_coding_type+1 != PIPE_MPEG12_PICTURE_CODING_TYPE_I; + while (mod_time--) + write_bit(&bs_vop, 1); /* modulo_time_base */ + write_bit(&bs_vop, 0); /* modulo_time_base */ + + write_bit(&bs_vop, 1); /* marker_bit */ + vop_time_inc = context->mpeg4.frame_num % + context->desc.mpeg4.vop_time_increment_resolution; + write_bits(&bs_vop, vop_time_inc, context->mpeg4.vti_bits); + write_bit(&bs_vop, 1); /* marker_bit */ + write_bit(&bs_vop, 1); /* vop_coded */ + if (vop_coding_type+1 == PIPE_MPEG12_PICTURE_CODING_TYPE_P) + write_bit(&bs_vop, context->mpeg4.pps.vop_fields.bits.vop_rounding_type); + write_bits(&bs_vop, context->mpeg4.pps.vop_fields.bits.intra_dc_vlc_thr, 3); + if (context->mpeg4.pps.vol_fields.bits.interlaced) { + write_bit(&bs_vop, context->mpeg4.pps.vop_fields.bits.top_field_first); + write_bit(&bs_vop, context->mpeg4.pps.vop_fields.bits.alternate_vertical_scan_flag); + } + + write_bits(&bs_vop, context->mpeg4.quant_scale, context->mpeg4.pps.quant_precision); + if (vop_coding_type+1 != PIPE_MPEG12_PICTURE_CODING_TYPE_I) + write_bits(&bs_vop, context->desc.mpeg4.vop_fcode_forward, 3); + if (vop_coding_type+1 == PIPE_MPEG12_PICTURE_CODING_TYPE_B) + write_bits(&bs_vop, context->desc.mpeg4.vop_fcode_backward, 3); + + vop_size = bs_vop.pos/8; + memcpy(context->mpeg4.start_code + context->mpeg4.start_code_size, vop, vop_size); + context->mpeg4.start_code_size += vop_size; +} diff --git a/src/gallium/frontends/va/picture_vc1.c b/src/gallium/frontends/va/picture_vc1.c new file mode 100644 index 00000000000..6ad1571ca96 --- /dev/null +++ b/src/gallium/frontends/va/picture_vc1.c @@ -0,0 +1,74 @@ +/************************************************************************** + * + * Copyright 2014 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "va_private.h" + +void vlVaHandlePictureParameterBufferVC1(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) +{ + VAPictureParameterBufferVC1 * vc1 = buf->data; + + assert(buf->size >= sizeof(VAPictureParameterBufferVC1) && buf->num_elements == 1); + context->desc.vc1.slice_count = 0; + vlVaGetReferenceFrame(drv, vc1->forward_reference_picture, &context->desc.vc1.ref[0]); + vlVaGetReferenceFrame(drv, vc1->backward_reference_picture, &context->desc.vc1.ref[1]); + context->desc.vc1.picture_type = vc1->picture_fields.bits.picture_type; + context->desc.vc1.frame_coding_mode = vc1->picture_fields.bits.frame_coding_mode; + context->desc.vc1.postprocflag = vc1->post_processing != 0; + context->desc.vc1.pulldown = vc1->sequence_fields.bits.pulldown; + context->desc.vc1.interlace = vc1->sequence_fields.bits.interlace; + context->desc.vc1.tfcntrflag = vc1->sequence_fields.bits.tfcntrflag; + context->desc.vc1.finterpflag = vc1->sequence_fields.bits.finterpflag; + context->desc.vc1.psf = vc1->sequence_fields.bits.psf; + context->desc.vc1.dquant = vc1->pic_quantizer_fields.bits.dquant; + context->desc.vc1.panscan_flag = vc1->entrypoint_fields.bits.panscan_flag; + context->desc.vc1.refdist_flag = + vc1->reference_fields.bits.reference_distance_flag; + context->desc.vc1.quantizer = vc1->pic_quantizer_fields.bits.quantizer; + context->desc.vc1.extended_mv = vc1->mv_fields.bits.extended_mv_flag; + context->desc.vc1.extended_dmv = vc1->mv_fields.bits.extended_dmv_flag; + context->desc.vc1.overlap = vc1->sequence_fields.bits.overlap; + context->desc.vc1.vstransform = + vc1->transform_fields.bits.variable_sized_transform_flag; + context->desc.vc1.loopfilter = vc1->entrypoint_fields.bits.loopfilter; + context->desc.vc1.fastuvmc = vc1->fast_uvmc_flag; + context->desc.vc1.range_mapy_flag = vc1->range_mapping_fields.bits.luma_flag; + context->desc.vc1.range_mapy = vc1->range_mapping_fields.bits.luma; + context->desc.vc1.range_mapuv_flag = vc1->range_mapping_fields.bits.chroma_flag; + context->desc.vc1.range_mapuv = vc1->range_mapping_fields.bits.chroma; + context->desc.vc1.multires = vc1->sequence_fields.bits.multires; + context->desc.vc1.syncmarker = vc1->sequence_fields.bits.syncmarker; + context->desc.vc1.rangered = vc1->sequence_fields.bits.rangered; + context->desc.vc1.maxbframes = vc1->sequence_fields.bits.max_b_frames; + context->desc.vc1.deblockEnable = vc1->post_processing != 0; + context->desc.vc1.pquant = vc1->pic_quantizer_fields.bits.pic_quantizer_scale; +} + +void vlVaHandleSliceParameterBufferVC1(vlVaContext *context, vlVaBuffer *buf) +{ + assert(buf->size >= sizeof(VASliceParameterBufferVC1) && buf->num_elements == 1); + context->desc.vc1.slice_count += buf->num_elements; +} diff --git a/src/gallium/frontends/va/picture_vp9.c b/src/gallium/frontends/va/picture_vp9.c new file mode 100644 index 00000000000..b5aca9a513c --- /dev/null +++ b/src/gallium/frontends/va/picture_vp9.c @@ -0,0 +1,353 @@ +/************************************************************************** + * + * Copyright 2018 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "vl/vl_vlc.h" +#include "va_private.h" + +#define NUM_VP9_REFS 8 + +void vlVaHandlePictureParameterBufferVP9(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) +{ + VADecPictureParameterBufferVP9 *vp9 = buf->data; + int i; + + assert(buf->size >= sizeof(VADecPictureParameterBufferVP9) && buf->num_elements == 1); + + context->desc.vp9.picture_parameter.frame_width = vp9->frame_width; + context->desc.vp9.picture_parameter.frame_height = vp9->frame_height; + + context->desc.vp9.picture_parameter.pic_fields.subsampling_x = vp9->pic_fields.bits.subsampling_x; + context->desc.vp9.picture_parameter.pic_fields.subsampling_y = vp9->pic_fields.bits.subsampling_y; + context->desc.vp9.picture_parameter.pic_fields.frame_type = vp9->pic_fields.bits.frame_type; + context->desc.vp9.picture_parameter.pic_fields.show_frame = vp9->pic_fields.bits.show_frame; + context->desc.vp9.picture_parameter.pic_fields.error_resilient_mode = vp9->pic_fields.bits.error_resilient_mode; + context->desc.vp9.picture_parameter.pic_fields.intra_only = vp9->pic_fields.bits.intra_only; + context->desc.vp9.picture_parameter.pic_fields.allow_high_precision_mv = vp9->pic_fields.bits.allow_high_precision_mv; + context->desc.vp9.picture_parameter.pic_fields.mcomp_filter_type = vp9->pic_fields.bits.mcomp_filter_type; + context->desc.vp9.picture_parameter.pic_fields.frame_parallel_decoding_mode = vp9->pic_fields.bits.frame_parallel_decoding_mode; + context->desc.vp9.picture_parameter.pic_fields.reset_frame_context = vp9->pic_fields.bits.reset_frame_context; + context->desc.vp9.picture_parameter.pic_fields.refresh_frame_context = vp9->pic_fields.bits.refresh_frame_context; + context->desc.vp9.picture_parameter.pic_fields.frame_context_idx = vp9->pic_fields.bits.frame_context_idx; + context->desc.vp9.picture_parameter.pic_fields.segmentation_enabled = vp9->pic_fields.bits.segmentation_enabled; + context->desc.vp9.picture_parameter.pic_fields.segmentation_temporal_update = vp9->pic_fields.bits.segmentation_temporal_update; + context->desc.vp9.picture_parameter.pic_fields.segmentation_update_map = vp9->pic_fields.bits.segmentation_update_map; + context->desc.vp9.picture_parameter.pic_fields.last_ref_frame = vp9->pic_fields.bits.last_ref_frame; + context->desc.vp9.picture_parameter.pic_fields.last_ref_frame_sign_bias = vp9->pic_fields.bits.last_ref_frame_sign_bias; + context->desc.vp9.picture_parameter.pic_fields.golden_ref_frame = vp9->pic_fields.bits.golden_ref_frame; + context->desc.vp9.picture_parameter.pic_fields.golden_ref_frame_sign_bias = vp9->pic_fields.bits.golden_ref_frame_sign_bias; + context->desc.vp9.picture_parameter.pic_fields.alt_ref_frame = vp9->pic_fields.bits.alt_ref_frame; + context->desc.vp9.picture_parameter.pic_fields.alt_ref_frame_sign_bias = vp9->pic_fields.bits.alt_ref_frame_sign_bias; + context->desc.vp9.picture_parameter.pic_fields.lossless_flag = vp9->pic_fields.bits.lossless_flag; + + context->desc.vp9.picture_parameter.filter_level = vp9->filter_level; + context->desc.vp9.picture_parameter.sharpness_level = vp9->sharpness_level; + + context->desc.vp9.picture_parameter.log2_tile_rows = vp9->log2_tile_rows; + context->desc.vp9.picture_parameter.log2_tile_columns = vp9->log2_tile_columns; + + context->desc.vp9.picture_parameter.frame_header_length_in_bytes = vp9->frame_header_length_in_bytes; + context->desc.vp9.picture_parameter.first_partition_size = vp9->first_partition_size; + + for (i = 0; i < 7; ++i) + context->desc.vp9.picture_parameter.mb_segment_tree_probs[i] = vp9->mb_segment_tree_probs[i]; + for (i = 0; i < 3; ++i) + context->desc.vp9.picture_parameter.segment_pred_probs[i] = vp9->segment_pred_probs[i]; + + context->desc.vp9.picture_parameter.profile = vp9->profile; + + context->desc.vp9.picture_parameter.bit_depth = vp9->bit_depth; + + for (i = 0 ; i < NUM_VP9_REFS ; i++) + vlVaGetReferenceFrame(drv, vp9->reference_frames[i], &context->desc.vp9.ref[i]); + + if (!context->decoder && !context->templat.max_references) + context->templat.max_references = NUM_VP9_REFS; +} + +void vlVaHandleSliceParameterBufferVP9(vlVaContext *context, vlVaBuffer *buf) +{ + VASliceParameterBufferVP9 *vp9 = buf->data; + int i; + + assert(buf->size >= sizeof(VASliceParameterBufferVP9) && buf->num_elements == 1); + + context->desc.vp9.slice_parameter.slice_data_size = vp9->slice_data_size; + context->desc.vp9.slice_parameter.slice_data_offset = vp9->slice_data_offset; + context->desc.vp9.slice_parameter.slice_data_flag = vp9->slice_data_flag; + + for (i = 0; i < 8; ++i) { + context->desc.vp9.slice_parameter.seg_param[i].segment_flags.segment_reference_enabled = + vp9->seg_param[i].segment_flags.fields.segment_reference_enabled; + context->desc.vp9.slice_parameter.seg_param[i].segment_flags.segment_reference = + vp9->seg_param[i].segment_flags.fields.segment_reference; + context->desc.vp9.slice_parameter.seg_param[i].segment_flags.segment_reference_skipped = + vp9->seg_param[i].segment_flags.fields.segment_reference_skipped; + + memcpy(context->desc.vp9.slice_parameter.seg_param[i].filter_level, vp9->seg_param[i].filter_level, 4 * 2); + + context->desc.vp9.slice_parameter.seg_param[i].luma_ac_quant_scale = vp9->seg_param[i].luma_ac_quant_scale; + context->desc.vp9.slice_parameter.seg_param[i].luma_dc_quant_scale = vp9->seg_param[i].luma_dc_quant_scale; + context->desc.vp9.slice_parameter.seg_param[i].chroma_ac_quant_scale = vp9->seg_param[i].chroma_ac_quant_scale; + context->desc.vp9.slice_parameter.seg_param[i].chroma_dc_quant_scale = vp9->seg_param[i].chroma_dc_quant_scale; + } +} + +static unsigned vp9_u(struct vl_vlc *vlc, unsigned n) +{ + unsigned valid = vl_vlc_valid_bits(vlc); + + if (n == 0) + return 0; + + if (valid < 32) + vl_vlc_fillbits(vlc); + + return vl_vlc_get_uimsbf(vlc, n); +} + +static signed vp9_s(struct vl_vlc *vlc, unsigned n) +{ + unsigned v; + bool s; + + v = vp9_u(vlc, n); + s = vp9_u(vlc, 1); + + return s ? -v : v; +} + +static void bitdepth_colorspace_sampling(struct vl_vlc *vlc, unsigned profile) +{ + unsigned cs; + + if (profile == 2) + /* bit_depth */ + vp9_u(vlc, 1); + + cs = vp9_u(vlc, 3); + if (cs != 7) + /* yuv_range_flag */ + vp9_u(vlc, 1); +} + +static void frame_size(struct vl_vlc *vlc) +{ + /* width_minus_one */ + vp9_u(vlc, 16); + /* height_minus_one */ + vp9_u(vlc, 16); + + /* has_scaling */ + if (vp9_u(vlc, 1)) { + /* render_width_minus_one */ + vp9_u(vlc, 16); + /* render_height_minus_one */ + vp9_u(vlc, 16); + } +} + +void vlVaDecoderVP9BitstreamHeader(vlVaContext *context, vlVaBuffer *buf) +{ + struct vl_vlc vlc; + unsigned profile; + bool frame_type, show_frame, error_resilient_mode; + bool mode_ref_delta_enabled, mode_ref_delta_update = false; + int i; + + vl_vlc_init(&vlc, 1, (const void * const*)&buf->data, + (const unsigned *)&context->desc.vp9.picture_parameter.frame_header_length_in_bytes); + + /* frame_marker */ + if (vp9_u(&vlc, 2) != 0x2) + return; + + profile = vp9_u(&vlc, 1) | vp9_u(&vlc, 1) << 1; + + if (profile == 3) + profile += vp9_u(&vlc, 1); + + if (profile != 0 && profile != 2) + return; + + /* show_existing_frame */ + if (vp9_u(&vlc, 1)) + return; + + frame_type = vp9_u(&vlc, 1); + show_frame = vp9_u(&vlc, 1); + error_resilient_mode = vp9_u(&vlc, 1); + + if (frame_type == 0) { + /* sync_code */ + if (vp9_u(&vlc, 24) != 0x498342) + return; + + bitdepth_colorspace_sampling(&vlc, profile); + frame_size(&vlc); + } else { + bool intra_only, size_in_refs = false; + + intra_only = show_frame ? 0 : vp9_u(&vlc, 1); + if (!error_resilient_mode) + /* reset_frame_context */ + vp9_u(&vlc, 2); + + if (intra_only) { + /* sync_code */ + if (vp9_u(&vlc, 24) != 0x498342) + return; + + bitdepth_colorspace_sampling(&vlc, profile); + /* refresh_frame_flags */ + vp9_u(&vlc, 8); + frame_size(&vlc); + } else { + /* refresh_frame_flags */ + vp9_u(&vlc, 8); + + for (i = 0; i < 3; ++i) { + /* frame refs */ + vp9_u(&vlc, 3); + vp9_u(&vlc, 1); + } + + for (i = 0; i < 3; ++i) { + size_in_refs = vp9_u(&vlc, 1); + if (size_in_refs) + break; + } + + if (!size_in_refs) { + /* width/height_minus_one */ + vp9_u(&vlc, 16); + vp9_u(&vlc, 16); + } + + if (vp9_u(&vlc, 1)) { + /* render_width/height_minus_one */ + vp9_u(&vlc, 16); + vp9_u(&vlc, 16); + } + + /* high_precision_mv */ + vp9_u(&vlc, 1); + /* filter_switchable */ + if (!vp9_u(&vlc, 1)) + /* filter_index */ + vp9_u(&vlc, 2); + } + } + if (!error_resilient_mode) { + /* refresh_frame_context */ + vp9_u(&vlc, 1); + /* frame_parallel_decoding_mode */ + vp9_u(&vlc, 1); + } + /* frame_context_index */ + vp9_u(&vlc, 2); + + /* loop filter */ + + /* filter_level */ + vp9_u(&vlc, 6); + /* sharpness_level */ + vp9_u(&vlc, 3); + + mode_ref_delta_enabled = vp9_u(&vlc, 1); + if (mode_ref_delta_enabled) { + mode_ref_delta_update = vp9_u(&vlc, 1); + if (mode_ref_delta_update) { + for (i = 0; i < 4; ++i) { + /* update_ref_delta */ + if (vp9_u(&vlc, 1)) + /* ref_deltas */ + vp9_s(&vlc, 6); + } + for (i = 0; i < 2; ++i) { + /* update_mode_delta */ + if (vp9_u(&vlc, 1)) + /* mode_deltas */ + vp9_s(&vlc, 6); + } + } + } + context->desc.vp9.picture_parameter.mode_ref_delta_enabled = mode_ref_delta_enabled; + context->desc.vp9.picture_parameter.mode_ref_delta_update = mode_ref_delta_update; + + /* quantization */ + + context->desc.vp9.picture_parameter.base_qindex = vp9_u(&vlc, 8); + context->desc.vp9.picture_parameter.y_dc_delta_q = vp9_u(&vlc, 1) ? vp9_s(&vlc, 4) : 0; + context->desc.vp9.picture_parameter.uv_ac_delta_q = vp9_u(&vlc, 1) ? vp9_s(&vlc, 4) : 0; + context->desc.vp9.picture_parameter.uv_dc_delta_q = vp9_u(&vlc, 1) ? vp9_s(&vlc, 4) : 0; + + /* segmentation */ + + /* enabled */ + if (!vp9_u(&vlc, 1)) + return; + + /* update_map */ + if (vp9_u(&vlc, 1)) { + for (i = 0; i < 7; ++i) { + /* tree_probs_set */ + if (vp9_u(&vlc, 1)) { + /* tree_probs */ + vp9_u(&vlc, 8); + } + } + + /* temporal_update */ + if (vp9_u(&vlc, 1)) { + for (i = 0; i < 3; ++i) { + /* pred_probs_set */ + if (vp9_u(&vlc, 1)) + /* pred_probs */ + vp9_u(&vlc, 8); + } + } + } + + /* update_data */ + if (vp9_u(&vlc, 1)) { + /* abs_delta */ + vp9_u(&vlc, 1); + for (i = 0; i < 8; ++i) { + /* Use alternate quantizer */ + if ((context->desc.vp9.slice_parameter.seg_param[i].alt_quant_enabled = vp9_u(&vlc, 1))) + context->desc.vp9.slice_parameter.seg_param[i].alt_quant = vp9_s(&vlc, 8); + /* Use alternate loop filter value */ + if ((context->desc.vp9.slice_parameter.seg_param[i].alt_lf_enabled = vp9_u(&vlc, 1))) + context->desc.vp9.slice_parameter.seg_param[i].alt_lf = vp9_s(&vlc, 6); + /* Optional Segment reference frame */ + if (vp9_u(&vlc, 1)) + vp9_u(&vlc, 2); + /* Optional Segment skip mode */ + vp9_u(&vlc, 1); + } + } +} diff --git a/src/gallium/frontends/va/postproc.c b/src/gallium/frontends/va/postproc.c new file mode 100644 index 00000000000..18458832844 --- /dev/null +++ b/src/gallium/frontends/va/postproc.c @@ -0,0 +1,362 @@ +/************************************************************************** + * + * Copyright 2015 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "util/u_handle_table.h" +#include "util/u_memory.h" +#include "util/u_compute.h" + +#include "vl/vl_defines.h" +#include "vl/vl_video_buffer.h" +#include "vl/vl_deint_filter.h" + +#include "va_private.h" + +static const VARectangle * +vlVaRegionDefault(const VARectangle *region, vlVaSurface *surf, + VARectangle *def) +{ + if (region) + return region; + + def->x = 0; + def->y = 0; + def->width = surf->templat.width; + def->height = surf->templat.height; + + return def; +} + +static VAStatus +vlVaPostProcCompositor(vlVaDriver *drv, vlVaContext *context, + const VARectangle *src_region, + const VARectangle *dst_region, + struct pipe_video_buffer *src, + struct pipe_video_buffer *dst, + enum vl_compositor_deinterlace deinterlace) +{ + struct pipe_surface **surfaces; + struct u_rect src_rect; + struct u_rect dst_rect; + + surfaces = dst->get_surfaces(dst); + if (!surfaces || !surfaces[0]) + return VA_STATUS_ERROR_INVALID_SURFACE; + + src_rect.x0 = src_region->x; + src_rect.y0 = src_region->y; + src_rect.x1 = src_region->x + src_region->width; + src_rect.y1 = src_region->y + src_region->height; + + dst_rect.x0 = dst_region->x; + dst_rect.y0 = dst_region->y; + dst_rect.x1 = dst_region->x + dst_region->width; + dst_rect.y1 = dst_region->y + dst_region->height; + + vl_compositor_clear_layers(&drv->cstate); + vl_compositor_set_buffer_layer(&drv->cstate, &drv->compositor, 0, src, + &src_rect, NULL, deinterlace); + vl_compositor_set_layer_dst_area(&drv->cstate, 0, &dst_rect); + vl_compositor_render(&drv->cstate, &drv->compositor, surfaces[0], NULL, false); + + drv->pipe->flush(drv->pipe, NULL, 0); + return VA_STATUS_SUCCESS; +} + +static void vlVaGetBox(struct pipe_video_buffer *buf, unsigned idx, + struct pipe_box *box, const VARectangle *region) +{ + unsigned plane = buf->interlaced ? idx / 2: idx; + unsigned x, y, width, height; + + x = abs(region->x); + y = abs(region->y); + width = region->width; + height = region->height; + + vl_video_buffer_adjust_size(&x, &y, plane, + pipe_format_to_chroma_format(buf->buffer_format), + buf->interlaced); + vl_video_buffer_adjust_size(&width, &height, plane, + pipe_format_to_chroma_format(buf->buffer_format), + buf->interlaced); + + box->x = region->x < 0 ? -x : x; + box->y = region->y < 0 ? -y : y; + box->width = width; + box->height = height; +} + +static VAStatus vlVaPostProcBlit(vlVaDriver *drv, vlVaContext *context, + const VARectangle *src_region, + const VARectangle *dst_region, + struct pipe_video_buffer *src, + struct pipe_video_buffer *dst, + enum vl_compositor_deinterlace deinterlace) +{ + struct pipe_surface **src_surfaces; + struct pipe_surface **dst_surfaces; + struct u_rect src_rect; + struct u_rect dst_rect; + bool scale = false; + bool grab = false; + unsigned i; + + if ((src->buffer_format == PIPE_FORMAT_B8G8R8A8_UNORM || + src->buffer_format == PIPE_FORMAT_B8G8R8X8_UNORM) && + !src->interlaced) + grab = true; + + if ((src->width != dst->width || src->height != dst->height) && + (src->interlaced && dst->interlaced)) + scale = true; + + src_surfaces = src->get_surfaces(src); + if (!src_surfaces || !src_surfaces[0]) + return VA_STATUS_ERROR_INVALID_SURFACE; + + if (scale || (src->interlaced != dst->interlaced && dst->interlaced)) { + vlVaSurface *surf; + + surf = handle_table_get(drv->htab, context->target_id); + surf->templat.interlaced = false; + dst->destroy(dst); + + if (vlVaHandleSurfaceAllocate(drv, surf, &surf->templat) != VA_STATUS_SUCCESS) + return VA_STATUS_ERROR_ALLOCATION_FAILED; + + dst = context->target = surf->buffer; + } + + dst_surfaces = dst->get_surfaces(dst); + if (!dst_surfaces || !dst_surfaces[0]) + return VA_STATUS_ERROR_INVALID_SURFACE; + + src_rect.x0 = src_region->x; + src_rect.y0 = src_region->y; + src_rect.x1 = src_region->x + src_region->width; + src_rect.y1 = src_region->y + src_region->height; + + dst_rect.x0 = dst_region->x; + dst_rect.y0 = dst_region->y; + dst_rect.x1 = dst_region->x + dst_region->width; + dst_rect.y1 = dst_region->y + dst_region->height; + + if (grab) { + vl_compositor_convert_rgb_to_yuv(&drv->cstate, &drv->compositor, 0, + ((struct vl_video_buffer *)src)->resources[0], + dst, &src_rect, &dst_rect); + + return VA_STATUS_SUCCESS; + } + + if (src->interlaced != dst->interlaced) { + vl_compositor_yuv_deint_full(&drv->cstate, &drv->compositor, + src, dst, &src_rect, &dst_rect, + deinterlace); + + return VA_STATUS_SUCCESS; + } + + for (i = 0; i < VL_MAX_SURFACES; ++i) { + struct pipe_surface *from = src_surfaces[i]; + struct pipe_blit_info blit; + + if (src->interlaced) { + /* Not 100% accurate, but close enough */ + switch (deinterlace) { + case VL_COMPOSITOR_BOB_TOP: + from = src_surfaces[i & ~1]; + break; + case VL_COMPOSITOR_BOB_BOTTOM: + from = src_surfaces[(i & ~1) + 1]; + break; + default: + break; + } + } + + if (!from || !dst_surfaces[i]) + continue; + + memset(&blit, 0, sizeof(blit)); + blit.src.resource = from->texture; + blit.src.format = from->format; + blit.src.level = 0; + blit.src.box.z = from->u.tex.first_layer; + blit.src.box.depth = 1; + vlVaGetBox(src, i, &blit.src.box, src_region); + + blit.dst.resource = dst_surfaces[i]->texture; + blit.dst.format = dst_surfaces[i]->format; + blit.dst.level = 0; + blit.dst.box.z = dst_surfaces[i]->u.tex.first_layer; + blit.dst.box.depth = 1; + vlVaGetBox(dst, i, &blit.dst.box, dst_region); + + blit.mask = PIPE_MASK_RGBA; + blit.filter = PIPE_TEX_MIPFILTER_LINEAR; + + if (drv->pipe->screen->get_param(drv->pipe->screen, + PIPE_CAP_PREFER_COMPUTE_FOR_MULTIMEDIA)) + util_compute_blit(drv->pipe, &blit, &context->blit_cs); + else + drv->pipe->blit(drv->pipe, &blit); + } + + // TODO: figure out why this is necessary for DMA-buf sharing + drv->pipe->flush(drv->pipe, NULL, 0); + + return VA_STATUS_SUCCESS; +} + +static struct pipe_video_buffer * +vlVaApplyDeint(vlVaDriver *drv, vlVaContext *context, + VAProcPipelineParameterBuffer *param, + struct pipe_video_buffer *current, + unsigned field) +{ + vlVaSurface *prevprev, *prev, *next; + + if (param->num_forward_references < 2 || + param->num_backward_references < 1) + return current; + + prevprev = handle_table_get(drv->htab, param->forward_references[1]); + prev = handle_table_get(drv->htab, param->forward_references[0]); + next = handle_table_get(drv->htab, param->backward_references[0]); + + if (!prevprev || !prev || !next) + return current; + + if (context->deint && (context->deint->video_width != current->width || + context->deint->video_height != current->height)) { + vl_deint_filter_cleanup(context->deint); + FREE(context->deint); + context->deint = NULL; + } + + if (!context->deint) { + context->deint = MALLOC(sizeof(struct vl_deint_filter)); + if (!vl_deint_filter_init(context->deint, drv->pipe, current->width, + current->height, false, false)) { + FREE(context->deint); + context->deint = NULL; + return current; + } + } + + if (!vl_deint_filter_check_buffers(context->deint, prevprev->buffer, + prev->buffer, current, next->buffer)) + return current; + + vl_deint_filter_render(context->deint, prevprev->buffer, prev->buffer, + current, next->buffer, field); + return context->deint->video_buffer; +} + +VAStatus +vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) +{ + enum vl_compositor_deinterlace deinterlace = VL_COMPOSITOR_WEAVE; + VARectangle def_src_region, def_dst_region; + const VARectangle *src_region, *dst_region; + VAProcPipelineParameterBuffer *param; + struct pipe_video_buffer *src; + vlVaSurface *src_surface, *dst_surface; + unsigned i; + + if (!drv || !context) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + if (!buf || !buf->data) + return VA_STATUS_ERROR_INVALID_BUFFER; + + if (!context->target) + return VA_STATUS_ERROR_INVALID_SURFACE; + + param = buf->data; + + src_surface = handle_table_get(drv->htab, param->surface); + dst_surface = handle_table_get(drv->htab, context->target_id); + + if (!src_surface || !src_surface->buffer) + return VA_STATUS_ERROR_INVALID_SURFACE; + + src = src_surface->buffer; + + for (i = 0; i < param->num_filters; i++) { + vlVaBuffer *buf = handle_table_get(drv->htab, param->filters[i]); + VAProcFilterParameterBufferBase *filter; + + if (!buf || buf->type != VAProcFilterParameterBufferType) + return VA_STATUS_ERROR_INVALID_BUFFER; + + filter = buf->data; + switch (filter->type) { + case VAProcFilterDeinterlacing: { + VAProcFilterParameterBufferDeinterlacing *deint = buf->data; + switch (deint->algorithm) { + case VAProcDeinterlacingBob: + if (deint->flags & VA_DEINTERLACING_BOTTOM_FIELD) + deinterlace = VL_COMPOSITOR_BOB_BOTTOM; + else + deinterlace = VL_COMPOSITOR_BOB_TOP; + break; + + case VAProcDeinterlacingWeave: + deinterlace = VL_COMPOSITOR_WEAVE; + break; + + case VAProcDeinterlacingMotionAdaptive: + src = vlVaApplyDeint(drv, context, param, src, + !!(deint->flags & VA_DEINTERLACING_BOTTOM_FIELD)); + break; + + default: + return VA_STATUS_ERROR_UNIMPLEMENTED; + } + + break; + } + + default: + return VA_STATUS_ERROR_UNIMPLEMENTED; + } + } + + src_region = vlVaRegionDefault(param->surface_region, src_surface, &def_src_region); + dst_region = vlVaRegionDefault(param->output_region, dst_surface, &def_dst_region); + + if (context->target->buffer_format != PIPE_FORMAT_NV12 && + context->target->buffer_format != PIPE_FORMAT_P010 && + context->target->buffer_format != PIPE_FORMAT_P016) + return vlVaPostProcCompositor(drv, context, src_region, dst_region, + src, context->target, deinterlace); + else + return vlVaPostProcBlit(drv, context, src_region, dst_region, + src, context->target, deinterlace); +} diff --git a/src/gallium/frontends/va/subpicture.c b/src/gallium/frontends/va/subpicture.c new file mode 100644 index 00000000000..b213e9abb7d --- /dev/null +++ b/src/gallium/frontends/va/subpicture.c @@ -0,0 +1,290 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian. + * Copyright 2014 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "util/u_memory.h" +#include "util/u_handle_table.h" +#include "util/u_sampler.h" + +#include "va_private.h" + +static VAImageFormat subpic_formats[] = { + { + .fourcc = VA_FOURCC_BGRA, + .byte_order = VA_LSB_FIRST, + .bits_per_pixel = 32, + .depth = 32, + .red_mask = 0x00ff0000ul, + .green_mask = 0x0000ff00ul, + .blue_mask = 0x000000fful, + .alpha_mask = 0xff000000ul, + }, +}; + +VAStatus +vlVaQuerySubpictureFormats(VADriverContextP ctx, VAImageFormat *format_list, + unsigned int *flags, unsigned int *num_formats) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + if (!(format_list && flags && num_formats)) + return VA_STATUS_ERROR_UNKNOWN; + + *num_formats = sizeof(subpic_formats)/sizeof(VAImageFormat); + memcpy(format_list, subpic_formats, sizeof(subpic_formats)); + + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaCreateSubpicture(VADriverContextP ctx, VAImageID image, + VASubpictureID *subpicture) +{ + vlVaDriver *drv; + vlVaSubpicture *sub; + VAImage *img; + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + drv = VL_VA_DRIVER(ctx); + mtx_lock(&drv->mutex); + img = handle_table_get(drv->htab, image); + if (!img) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_INVALID_IMAGE; + } + + sub = CALLOC(1, sizeof(*sub)); + if (!sub) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_ALLOCATION_FAILED; + } + + sub->image = img; + *subpicture = handle_table_add(VL_VA_DRIVER(ctx)->htab, sub); + mtx_unlock(&drv->mutex); + + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaDestroySubpicture(VADriverContextP ctx, VASubpictureID subpicture) +{ + vlVaDriver *drv; + vlVaSubpicture *sub; + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + drv = VL_VA_DRIVER(ctx); + mtx_lock(&drv->mutex); + + sub = handle_table_get(drv->htab, subpicture); + if (!sub) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_INVALID_SUBPICTURE; + } + + FREE(sub); + handle_table_remove(drv->htab, subpicture); + mtx_unlock(&drv->mutex); + + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaSubpictureImage(VADriverContextP ctx, VASubpictureID subpicture, VAImageID image) +{ + vlVaDriver *drv; + vlVaSubpicture *sub; + VAImage *img; + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + drv = VL_VA_DRIVER(ctx); + mtx_lock(&drv->mutex); + + img = handle_table_get(drv->htab, image); + if (!img) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_INVALID_IMAGE; + } + + sub = handle_table_get(drv->htab, subpicture); + mtx_unlock(&drv->mutex); + if (!sub) + return VA_STATUS_ERROR_INVALID_SUBPICTURE; + + sub->image = img; + + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaSetSubpictureChromakey(VADriverContextP ctx, VASubpictureID subpicture, + unsigned int chromakey_min, unsigned int chromakey_max, unsigned int chromakey_mask) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus +vlVaSetSubpictureGlobalAlpha(VADriverContextP ctx, VASubpictureID subpicture, float global_alpha) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus +vlVaAssociateSubpicture(VADriverContextP ctx, VASubpictureID subpicture, + VASurfaceID *target_surfaces, int num_surfaces, + short src_x, short src_y, unsigned short src_width, + unsigned short src_height, short dest_x, short dest_y, + unsigned short dest_width, unsigned short dest_height, + unsigned int flags) +{ + vlVaSubpicture *sub; + struct pipe_resource tex_temp, *tex; + struct pipe_sampler_view sampler_templ; + vlVaDriver *drv; + vlVaSurface *surf; + int i; + struct u_rect src_rect = {src_x, src_x + src_width, src_y, src_y + src_height}; + struct u_rect dst_rect = {dest_x, dest_x + dest_width, dest_y, dest_y + dest_height}; + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + drv = VL_VA_DRIVER(ctx); + mtx_lock(&drv->mutex); + + sub = handle_table_get(drv->htab, subpicture); + if (!sub) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_INVALID_SUBPICTURE; + } + + for (i = 0; i < num_surfaces; i++) { + surf = handle_table_get(drv->htab, target_surfaces[i]); + if (!surf) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_INVALID_SURFACE; + } + } + + sub->src_rect = src_rect; + sub->dst_rect = dst_rect; + + memset(&tex_temp, 0, sizeof(tex_temp)); + tex_temp.target = PIPE_TEXTURE_2D; + tex_temp.format = PIPE_FORMAT_B8G8R8A8_UNORM; + tex_temp.last_level = 0; + tex_temp.width0 = src_width; + tex_temp.height0 = src_height; + tex_temp.depth0 = 1; + tex_temp.array_size = 1; + tex_temp.usage = PIPE_USAGE_DYNAMIC; + tex_temp.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; + tex_temp.flags = 0; + if (!drv->pipe->screen->is_format_supported( + drv->pipe->screen, tex_temp.format, tex_temp.target, + tex_temp.nr_samples, tex_temp.nr_storage_samples, tex_temp.bind)) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_ALLOCATION_FAILED; + } + + tex = drv->pipe->screen->resource_create(drv->pipe->screen, &tex_temp); + + memset(&sampler_templ, 0, sizeof(sampler_templ)); + u_sampler_view_default_template(&sampler_templ, tex, tex->format); + sub->sampler = drv->pipe->create_sampler_view(drv->pipe, tex, &sampler_templ); + pipe_resource_reference(&tex, NULL); + if (!sub->sampler) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_ALLOCATION_FAILED; + } + + for (i = 0; i < num_surfaces; i++) { + surf = handle_table_get(drv->htab, target_surfaces[i]); + util_dynarray_append(&surf->subpics, vlVaSubpicture *, sub); + } + mtx_unlock(&drv->mutex); + + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaDeassociateSubpicture(VADriverContextP ctx, VASubpictureID subpicture, + VASurfaceID *target_surfaces, int num_surfaces) +{ + int i; + int j; + vlVaSurface *surf; + vlVaSubpicture *sub, **array; + vlVaDriver *drv; + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + drv = VL_VA_DRIVER(ctx); + mtx_lock(&drv->mutex); + + sub = handle_table_get(drv->htab, subpicture); + if (!sub) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_INVALID_SUBPICTURE; + } + + for (i = 0; i < num_surfaces; i++) { + surf = handle_table_get(drv->htab, target_surfaces[i]); + if (!surf) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_INVALID_SURFACE; + } + + array = surf->subpics.data; + if (!array) + continue; + + for (j = 0; j < surf->subpics.size/sizeof(vlVaSubpicture *); j++) { + if (array[j] == sub) + array[j] = NULL; + } + + while (surf->subpics.size && util_dynarray_top(&surf->subpics, vlVaSubpicture *) == NULL) + (void)util_dynarray_pop(&surf->subpics, vlVaSubpicture *); + } + pipe_sampler_view_reference(&sub->sampler,NULL); + mtx_unlock(&drv->mutex); + + return VA_STATUS_SUCCESS; +} diff --git a/src/gallium/frontends/va/surface.c b/src/gallium/frontends/va/surface.c new file mode 100644 index 00000000000..964d316bc46 --- /dev/null +++ b/src/gallium/frontends/va/surface.c @@ -0,0 +1,1110 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian. + * Copyright 2014 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "pipe/p_screen.h" +#include "pipe/p_video_codec.h" + +#include "frontend/drm_driver.h" + +#include "util/u_memory.h" +#include "util/u_handle_table.h" +#include "util/u_rect.h" +#include "util/u_sampler.h" +#include "util/u_surface.h" +#include "util/u_video.h" + +#include "vl/vl_compositor.h" +#include "vl/vl_video_buffer.h" +#include "vl/vl_winsys.h" + +#include "va_private.h" + +#include +#include "drm-uapi/drm_fourcc.h" + +static const enum pipe_format vpp_surface_formats[] = { + PIPE_FORMAT_B8G8R8A8_UNORM, PIPE_FORMAT_R8G8B8A8_UNORM, + PIPE_FORMAT_B8G8R8X8_UNORM, PIPE_FORMAT_R8G8B8X8_UNORM +}; + +VAStatus +vlVaCreateSurfaces(VADriverContextP ctx, int width, int height, int format, + int num_surfaces, VASurfaceID *surfaces) +{ + return vlVaCreateSurfaces2(ctx, format, width, height, surfaces, num_surfaces, + NULL, 0); +} + +VAStatus +vlVaDestroySurfaces(VADriverContextP ctx, VASurfaceID *surface_list, int num_surfaces) +{ + vlVaDriver *drv; + int i; + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + drv = VL_VA_DRIVER(ctx); + mtx_lock(&drv->mutex); + for (i = 0; i < num_surfaces; ++i) { + vlVaSurface *surf = handle_table_get(drv->htab, surface_list[i]); + if (!surf) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_INVALID_SURFACE; + } + if (surf->buffer) + surf->buffer->destroy(surf->buffer); + util_dynarray_fini(&surf->subpics); + FREE(surf); + handle_table_remove(drv->htab, surface_list[i]); + } + mtx_unlock(&drv->mutex); + + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaSyncSurface(VADriverContextP ctx, VASurfaceID render_target) +{ + vlVaDriver *drv; + vlVaContext *context; + vlVaSurface *surf; + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + drv = VL_VA_DRIVER(ctx); + if (!drv) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + mtx_lock(&drv->mutex); + surf = handle_table_get(drv->htab, render_target); + + if (!surf || !surf->buffer) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_INVALID_SURFACE; + } + + if (!surf->feedback) { + // No outstanding operation: nothing to do. + mtx_unlock(&drv->mutex); + return VA_STATUS_SUCCESS; + } + + context = handle_table_get(drv->htab, surf->ctx); + if (!context) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_INVALID_CONTEXT; + } + + if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) { + if (u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_MPEG4_AVC) { + int frame_diff; + if (context->desc.h264enc.frame_num_cnt >= surf->frame_num_cnt) + frame_diff = context->desc.h264enc.frame_num_cnt - surf->frame_num_cnt; + else + frame_diff = 0xFFFFFFFF - surf->frame_num_cnt + 1 + context->desc.h264enc.frame_num_cnt; + if ((frame_diff == 0) && + (surf->force_flushed == false) && + (context->desc.h264enc.frame_num_cnt % 2 != 0)) { + context->decoder->flush(context->decoder); + context->first_single_submitted = true; + } + } + context->decoder->get_feedback(context->decoder, surf->feedback, &(surf->coded_buf->coded_size)); + surf->feedback = NULL; + } + mtx_unlock(&drv->mutex); + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaQuerySurfaceStatus(VADriverContextP ctx, VASurfaceID render_target, VASurfaceStatus *status) +{ + vlVaDriver *drv; + vlVaSurface *surf; + vlVaContext *context; + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + drv = VL_VA_DRIVER(ctx); + if (!drv) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + mtx_lock(&drv->mutex); + + surf = handle_table_get(drv->htab, render_target); + if (!surf || !surf->buffer) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_INVALID_SURFACE; + } + + context = handle_table_get(drv->htab, surf->ctx); + if (!context) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_INVALID_CONTEXT; + } + + if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) { + if(surf->feedback == NULL) + *status=VASurfaceReady; + else + *status=VASurfaceRendering; + } + + mtx_unlock(&drv->mutex); + + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaQuerySurfaceError(VADriverContextP ctx, VASurfaceID render_target, VAStatus error_status, void **error_info) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +static void +upload_sampler(struct pipe_context *pipe, struct pipe_sampler_view *dst, + const struct pipe_box *dst_box, const void *src, unsigned src_stride, + unsigned src_x, unsigned src_y) +{ + struct pipe_transfer *transfer; + void *map; + + map = pipe->transfer_map(pipe, dst->texture, 0, PIPE_TRANSFER_WRITE, + dst_box, &transfer); + if (!map) + return; + + util_copy_rect(map, dst->texture->format, transfer->stride, 0, 0, + dst_box->width, dst_box->height, + src, src_stride, src_x, src_y); + + pipe->transfer_unmap(pipe, transfer); +} + +static VAStatus +vlVaPutSubpictures(vlVaSurface *surf, vlVaDriver *drv, + struct pipe_surface *surf_draw, struct u_rect *dirty_area, + struct u_rect *src_rect, struct u_rect *dst_rect) +{ + vlVaSubpicture *sub; + int i; + + if (!(surf->subpics.data || surf->subpics.size)) + return VA_STATUS_SUCCESS; + + for (i = 0; i < surf->subpics.size/sizeof(vlVaSubpicture *); i++) { + struct pipe_blend_state blend; + void *blend_state; + vlVaBuffer *buf; + struct pipe_box box; + struct u_rect *s, *d, sr, dr, c; + int sw, sh, dw, dh; + + sub = ((vlVaSubpicture **)surf->subpics.data)[i]; + if (!sub) + continue; + + buf = handle_table_get(drv->htab, sub->image->buf); + if (!buf) + return VA_STATUS_ERROR_INVALID_IMAGE; + + box.x = 0; + box.y = 0; + box.z = 0; + box.width = sub->dst_rect.x1 - sub->dst_rect.x0; + box.height = sub->dst_rect.y1 - sub->dst_rect.y0; + box.depth = 1; + + s = &sub->src_rect; + d = &sub->dst_rect; + sw = s->x1 - s->x0; + sh = s->y1 - s->y0; + dw = d->x1 - d->x0; + dh = d->y1 - d->y0; + c.x0 = MAX2(d->x0, s->x0); + c.y0 = MAX2(d->y0, s->y0); + c.x1 = MIN2(d->x0 + dw, src_rect->x1); + c.y1 = MIN2(d->y0 + dh, src_rect->y1); + sr.x0 = s->x0 + (c.x0 - d->x0)*(sw/(float)dw); + sr.y0 = s->y0 + (c.y0 - d->y0)*(sh/(float)dh); + sr.x1 = s->x0 + (c.x1 - d->x0)*(sw/(float)dw); + sr.y1 = s->y0 + (c.y1 - d->y0)*(sh/(float)dh); + + s = src_rect; + d = dst_rect; + sw = s->x1 - s->x0; + sh = s->y1 - s->y0; + dw = d->x1 - d->x0; + dh = d->y1 - d->y0; + dr.x0 = d->x0 + c.x0*(dw/(float)sw); + dr.y0 = d->y0 + c.y0*(dh/(float)sh); + dr.x1 = d->x0 + c.x1*(dw/(float)sw); + dr.y1 = d->y0 + c.y1*(dh/(float)sh); + + memset(&blend, 0, sizeof(blend)); + blend.independent_blend_enable = 0; + blend.rt[0].blend_enable = 1; + blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA; + blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA; + blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ZERO; + blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend.rt[0].rgb_func = PIPE_BLEND_ADD; + blend.rt[0].alpha_func = PIPE_BLEND_ADD; + blend.rt[0].colormask = PIPE_MASK_RGBA; + blend.logicop_enable = 0; + blend.logicop_func = PIPE_LOGICOP_CLEAR; + blend.dither = 0; + blend_state = drv->pipe->create_blend_state(drv->pipe, &blend); + + vl_compositor_clear_layers(&drv->cstate); + vl_compositor_set_layer_blend(&drv->cstate, 0, blend_state, false); + upload_sampler(drv->pipe, sub->sampler, &box, buf->data, + sub->image->pitches[0], 0, 0); + vl_compositor_set_rgba_layer(&drv->cstate, &drv->compositor, 0, sub->sampler, + &sr, NULL, NULL); + vl_compositor_set_layer_dst_area(&drv->cstate, 0, &dr); + vl_compositor_render(&drv->cstate, &drv->compositor, surf_draw, dirty_area, false); + drv->pipe->delete_blend_state(drv->pipe, blend_state); + } + + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaPutSurface(VADriverContextP ctx, VASurfaceID surface_id, void* draw, short srcx, short srcy, + unsigned short srcw, unsigned short srch, short destx, short desty, + unsigned short destw, unsigned short desth, VARectangle *cliprects, + unsigned int number_cliprects, unsigned int flags) +{ + vlVaDriver *drv; + vlVaSurface *surf; + struct pipe_screen *screen; + struct pipe_resource *tex; + struct pipe_surface surf_templ, *surf_draw; + struct vl_screen *vscreen; + struct u_rect src_rect, *dirty_area; + struct u_rect dst_rect = {destx, destx + destw, desty, desty + desth}; + enum pipe_format format; + VAStatus status; + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + drv = VL_VA_DRIVER(ctx); + mtx_lock(&drv->mutex); + surf = handle_table_get(drv->htab, surface_id); + if (!surf) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_INVALID_SURFACE; + } + + screen = drv->pipe->screen; + vscreen = drv->vscreen; + + tex = vscreen->texture_from_drawable(vscreen, draw); + if (!tex) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_INVALID_DISPLAY; + } + + dirty_area = vscreen->get_dirty_area(vscreen); + + memset(&surf_templ, 0, sizeof(surf_templ)); + surf_templ.format = tex->format; + surf_draw = drv->pipe->create_surface(drv->pipe, tex, &surf_templ); + if (!surf_draw) { + pipe_resource_reference(&tex, NULL); + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_INVALID_DISPLAY; + } + + src_rect.x0 = srcx; + src_rect.y0 = srcy; + src_rect.x1 = srcw + srcx; + src_rect.y1 = srch + srcy; + + format = surf->buffer->buffer_format; + + vl_compositor_clear_layers(&drv->cstate); + + if (format == PIPE_FORMAT_B8G8R8A8_UNORM || format == PIPE_FORMAT_B8G8R8X8_UNORM || + format == PIPE_FORMAT_R8G8B8A8_UNORM || format == PIPE_FORMAT_R8G8B8X8_UNORM) { + struct pipe_sampler_view **views; + + views = surf->buffer->get_sampler_view_planes(surf->buffer); + vl_compositor_set_rgba_layer(&drv->cstate, &drv->compositor, 0, views[0], &src_rect, NULL, NULL); + } else + vl_compositor_set_buffer_layer(&drv->cstate, &drv->compositor, 0, surf->buffer, &src_rect, NULL, VL_COMPOSITOR_WEAVE); + + vl_compositor_set_layer_dst_area(&drv->cstate, 0, &dst_rect); + vl_compositor_render(&drv->cstate, &drv->compositor, surf_draw, dirty_area, true); + + status = vlVaPutSubpictures(surf, drv, surf_draw, dirty_area, &src_rect, &dst_rect); + if (status) { + mtx_unlock(&drv->mutex); + return status; + } + + /* flush before calling flush_frontbuffer so that rendering is flushed + * to back buffer so the texture can be copied in flush_frontbuffer + */ + drv->pipe->flush(drv->pipe, NULL, 0); + + screen->flush_frontbuffer(screen, tex, 0, 0, + vscreen->get_private(vscreen), NULL); + + + pipe_resource_reference(&tex, NULL); + pipe_surface_reference(&surf_draw, NULL); + mtx_unlock(&drv->mutex); + + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaLockSurface(VADriverContextP ctx, VASurfaceID surface, unsigned int *fourcc, + unsigned int *luma_stride, unsigned int *chroma_u_stride, unsigned int *chroma_v_stride, + unsigned int *luma_offset, unsigned int *chroma_u_offset, unsigned int *chroma_v_offset, + unsigned int *buffer_name, void **buffer) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus +vlVaUnlockSurface(VADriverContextP ctx, VASurfaceID surface) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus +vlVaQuerySurfaceAttributes(VADriverContextP ctx, VAConfigID config_id, + VASurfaceAttrib *attrib_list, unsigned int *num_attribs) +{ + vlVaDriver *drv; + vlVaConfig *config; + VASurfaceAttrib *attribs; + struct pipe_screen *pscreen; + int i, j; + + STATIC_ASSERT(ARRAY_SIZE(vpp_surface_formats) <= VL_VA_MAX_IMAGE_FORMATS); + + if (config_id == VA_INVALID_ID) + return VA_STATUS_ERROR_INVALID_CONFIG; + + if (!attrib_list && !num_attribs) + return VA_STATUS_ERROR_INVALID_PARAMETER; + + if (!attrib_list) { + *num_attribs = VL_VA_MAX_IMAGE_FORMATS + VASurfaceAttribCount; + return VA_STATUS_SUCCESS; + } + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + drv = VL_VA_DRIVER(ctx); + + if (!drv) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + mtx_lock(&drv->mutex); + config = handle_table_get(drv->htab, config_id); + mtx_unlock(&drv->mutex); + + if (!config) + return VA_STATUS_ERROR_INVALID_CONFIG; + + pscreen = VL_VA_PSCREEN(ctx); + + if (!pscreen) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + attribs = CALLOC(VL_VA_MAX_IMAGE_FORMATS + VASurfaceAttribCount, + sizeof(VASurfaceAttrib)); + + if (!attribs) + return VA_STATUS_ERROR_ALLOCATION_FAILED; + + i = 0; + + /* vlVaCreateConfig returns PIPE_VIDEO_PROFILE_UNKNOWN + * only for VAEntrypointVideoProc. */ + if (config->profile == PIPE_VIDEO_PROFILE_UNKNOWN) { + if (config->rt_format & VA_RT_FORMAT_RGB32) { + for (j = 0; j < ARRAY_SIZE(vpp_surface_formats); ++j) { + attribs[i].type = VASurfaceAttribPixelFormat; + attribs[i].value.type = VAGenericValueTypeInteger; + attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE; + attribs[i].value.value.i = PipeFormatToVaFourcc(vpp_surface_formats[j]); + i++; + } + } + } + if (config->rt_format & VA_RT_FORMAT_YUV420) { + attribs[i].type = VASurfaceAttribPixelFormat; + attribs[i].value.type = VAGenericValueTypeInteger; + attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE; + attribs[i].value.value.i = VA_FOURCC_NV12; + i++; + } + if (config->rt_format & VA_RT_FORMAT_YUV420_10BPP) { + attribs[i].type = VASurfaceAttribPixelFormat; + attribs[i].value.type = VAGenericValueTypeInteger; + attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE; + attribs[i].value.value.i = VA_FOURCC_P010; + i++; + attribs[i].type = VASurfaceAttribPixelFormat; + attribs[i].value.type = VAGenericValueTypeInteger; + attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE; + attribs[i].value.value.i = VA_FOURCC_P016; + i++; + } + + attribs[i].type = VASurfaceAttribMemoryType; + attribs[i].value.type = VAGenericValueTypeInteger; + attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE; + attribs[i].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_VA | + VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME; + i++; + + attribs[i].type = VASurfaceAttribExternalBufferDescriptor; + attribs[i].value.type = VAGenericValueTypePointer; + attribs[i].flags = VA_SURFACE_ATTRIB_SETTABLE; + attribs[i].value.value.p = NULL; /* ignore */ + i++; + + if (config->entrypoint != PIPE_VIDEO_ENTRYPOINT_UNKNOWN) { + attribs[i].type = VASurfaceAttribMaxWidth; + attribs[i].value.type = VAGenericValueTypeInteger; + attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE; + attribs[i].value.value.i = + pscreen->get_video_param(pscreen, + config->profile, config->entrypoint, + PIPE_VIDEO_CAP_MAX_WIDTH); + i++; + + attribs[i].type = VASurfaceAttribMaxHeight; + attribs[i].value.type = VAGenericValueTypeInteger; + attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE; + attribs[i].value.value.i = + pscreen->get_video_param(pscreen, + config->profile, config->entrypoint, + PIPE_VIDEO_CAP_MAX_HEIGHT); + i++; + } else { + attribs[i].type = VASurfaceAttribMaxWidth; + attribs[i].value.type = VAGenericValueTypeInteger; + attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE; + attribs[i].value.value.i = vl_video_buffer_max_size(pscreen); + i++; + + attribs[i].type = VASurfaceAttribMaxHeight; + attribs[i].value.type = VAGenericValueTypeInteger; + attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE; + attribs[i].value.value.i = vl_video_buffer_max_size(pscreen); + i++; + } + + if (i > *num_attribs) { + *num_attribs = i; + FREE(attribs); + return VA_STATUS_ERROR_MAX_NUM_EXCEEDED; + } + + *num_attribs = i; + memcpy(attrib_list, attribs, i * sizeof(VASurfaceAttrib)); + FREE(attribs); + + return VA_STATUS_SUCCESS; +} + +static VAStatus +surface_from_external_memory(VADriverContextP ctx, vlVaSurface *surface, + VASurfaceAttribExternalBuffers *memory_attribute, + unsigned index, struct pipe_video_buffer *templat) +{ + vlVaDriver *drv; + struct pipe_screen *pscreen; + struct pipe_resource res_templ; + struct winsys_handle whandle; + struct pipe_resource *resources[VL_NUM_COMPONENTS]; + enum pipe_format resource_formats[VL_NUM_COMPONENTS]; + VAStatus result; + int i; + + pscreen = VL_VA_PSCREEN(ctx); + drv = VL_VA_DRIVER(ctx); + + if (!memory_attribute || !memory_attribute->buffers || + index > memory_attribute->num_buffers) + return VA_STATUS_ERROR_INVALID_PARAMETER; + + if (surface->templat.width != memory_attribute->width || + surface->templat.height != memory_attribute->height || + memory_attribute->num_planes < 1) + return VA_STATUS_ERROR_INVALID_PARAMETER; + + if (memory_attribute->num_planes > VL_NUM_COMPONENTS) + return VA_STATUS_ERROR_INVALID_PARAMETER; + + vl_get_video_buffer_formats(pscreen, templat->buffer_format, resource_formats); + + memset(&res_templ, 0, sizeof(res_templ)); + res_templ.target = PIPE_TEXTURE_2D; + res_templ.last_level = 0; + res_templ.depth0 = 1; + res_templ.array_size = 1; + res_templ.width0 = memory_attribute->width; + res_templ.height0 = memory_attribute->height; + res_templ.bind = PIPE_BIND_SAMPLER_VIEW; + res_templ.usage = PIPE_USAGE_DEFAULT; + + memset(&whandle, 0, sizeof(struct winsys_handle)); + whandle.type = WINSYS_HANDLE_TYPE_FD; + whandle.handle = memory_attribute->buffers[index]; + + // Create a resource for each plane. + memset(resources, 0, sizeof resources); + for (i = 0; i < memory_attribute->num_planes; i++) { + res_templ.format = resource_formats[i]; + if (res_templ.format == PIPE_FORMAT_NONE) { + result = VA_STATUS_ERROR_INVALID_PARAMETER; + goto fail; + } + + whandle.stride = memory_attribute->pitches[i]; + whandle.offset = memory_attribute->offsets[i]; + resources[i] = pscreen->resource_from_handle(pscreen, &res_templ, &whandle, + PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE); + if (!resources[i]) { + result = VA_STATUS_ERROR_ALLOCATION_FAILED; + goto fail; + } + } + + surface->buffer = vl_video_buffer_create_ex2(drv->pipe, templat, resources); + if (!surface->buffer) { + result = VA_STATUS_ERROR_ALLOCATION_FAILED; + goto fail; + } + return VA_STATUS_SUCCESS; + +fail: + for (i = 0; i < VL_NUM_COMPONENTS; i++) + pipe_resource_reference(&resources[i], NULL); + return result; +} + +VAStatus +vlVaHandleSurfaceAllocate(vlVaDriver *drv, vlVaSurface *surface, + struct pipe_video_buffer *templat) +{ + struct pipe_surface **surfaces; + unsigned i; + + surface->buffer = drv->pipe->create_video_buffer(drv->pipe, templat); + if (!surface->buffer) + return VA_STATUS_ERROR_ALLOCATION_FAILED; + + surfaces = surface->buffer->get_surfaces(surface->buffer); + for (i = 0; i < VL_MAX_SURFACES; ++i) { + union pipe_color_union c = {}; + + if (!surfaces[i]) + continue; + + if (i > !!surface->buffer->interlaced) + c.f[0] = c.f[1] = c.f[2] = c.f[3] = 0.5f; + + drv->pipe->clear_render_target(drv->pipe, surfaces[i], &c, 0, 0, + surfaces[i]->width, surfaces[i]->height, + false); + } + drv->pipe->flush(drv->pipe, NULL, 0); + + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaCreateSurfaces2(VADriverContextP ctx, unsigned int format, + unsigned int width, unsigned int height, + VASurfaceID *surfaces, unsigned int num_surfaces, + VASurfaceAttrib *attrib_list, unsigned int num_attribs) +{ + vlVaDriver *drv; + VASurfaceAttribExternalBuffers *memory_attribute; + struct pipe_video_buffer templat; + struct pipe_screen *pscreen; + int i; + int memory_type; + int expected_fourcc; + VAStatus vaStatus; + vlVaSurface *surf; + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + if (!(width && height)) + return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT; + + drv = VL_VA_DRIVER(ctx); + + if (!drv) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + pscreen = VL_VA_PSCREEN(ctx); + + if (!pscreen) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + /* Default. */ + memory_attribute = NULL; + memory_type = VA_SURFACE_ATTRIB_MEM_TYPE_VA; + expected_fourcc = 0; + + for (i = 0; i < num_attribs && attrib_list; i++) { + if ((attrib_list[i].type == VASurfaceAttribPixelFormat) && + (attrib_list[i].flags & VA_SURFACE_ATTRIB_SETTABLE)) { + if (attrib_list[i].value.type != VAGenericValueTypeInteger) + return VA_STATUS_ERROR_INVALID_PARAMETER; + expected_fourcc = attrib_list[i].value.value.i; + } + + if ((attrib_list[i].type == VASurfaceAttribMemoryType) && + (attrib_list[i].flags & VA_SURFACE_ATTRIB_SETTABLE)) { + + if (attrib_list[i].value.type != VAGenericValueTypeInteger) + return VA_STATUS_ERROR_INVALID_PARAMETER; + + switch (attrib_list[i].value.value.i) { + case VA_SURFACE_ATTRIB_MEM_TYPE_VA: + case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME: + memory_type = attrib_list[i].value.value.i; + break; + default: + return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE; + } + } + + if ((attrib_list[i].type == VASurfaceAttribExternalBufferDescriptor) && + (attrib_list[i].flags == VA_SURFACE_ATTRIB_SETTABLE)) { + if (attrib_list[i].value.type != VAGenericValueTypePointer) + return VA_STATUS_ERROR_INVALID_PARAMETER; + memory_attribute = (VASurfaceAttribExternalBuffers *)attrib_list[i].value.value.p; + } + } + + if (VA_RT_FORMAT_YUV420 != format && + VA_RT_FORMAT_YUV422 != format && + VA_RT_FORMAT_YUV444 != format && + VA_RT_FORMAT_YUV420_10BPP != format && + VA_RT_FORMAT_RGB32 != format) { + return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT; + } + + switch (memory_type) { + case VA_SURFACE_ATTRIB_MEM_TYPE_VA: + break; + case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME: + if (!memory_attribute) + return VA_STATUS_ERROR_INVALID_PARAMETER; + + expected_fourcc = memory_attribute->pixel_format; + break; + default: + assert(0); + } + + memset(&templat, 0, sizeof(templat)); + + templat.buffer_format = pscreen->get_video_param( + pscreen, + PIPE_VIDEO_PROFILE_UNKNOWN, + PIPE_VIDEO_ENTRYPOINT_BITSTREAM, + PIPE_VIDEO_CAP_PREFERED_FORMAT + ); + templat.interlaced = pscreen->get_video_param( + pscreen, + PIPE_VIDEO_PROFILE_UNKNOWN, + PIPE_VIDEO_ENTRYPOINT_BITSTREAM, + PIPE_VIDEO_CAP_PREFERS_INTERLACED + ); + + if (expected_fourcc) { + enum pipe_format expected_format = VaFourccToPipeFormat(expected_fourcc); + + if (expected_format != templat.buffer_format || memory_attribute) + templat.interlaced = 0; + + templat.buffer_format = expected_format; + } + + templat.width = width; + templat.height = height; + + memset(surfaces, VA_INVALID_ID, num_surfaces * sizeof(VASurfaceID)); + + mtx_lock(&drv->mutex); + for (i = 0; i < num_surfaces; i++) { + surf = CALLOC(1, sizeof(vlVaSurface)); + if (!surf) { + vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; + goto no_res; + } + + surf->templat = templat; + + switch (memory_type) { + case VA_SURFACE_ATTRIB_MEM_TYPE_VA: + /* The application will clear the TILING flag when the surface is + * intended to be exported as dmabuf. Adding shared flag because not + * null memory_attribute means VASurfaceAttribExternalBuffers is used. + */ + if (memory_attribute && + !(memory_attribute->flags & VA_SURFACE_EXTBUF_DESC_ENABLE_TILING)) + templat.bind = PIPE_BIND_LINEAR | PIPE_BIND_SHARED; + + vaStatus = vlVaHandleSurfaceAllocate(drv, surf, &templat); + if (vaStatus != VA_STATUS_SUCCESS) + goto free_surf; + break; + + case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME: + vaStatus = surface_from_external_memory(ctx, surf, memory_attribute, i, &templat); + if (vaStatus != VA_STATUS_SUCCESS) + goto free_surf; + break; + + default: + assert(0); + } + + util_dynarray_init(&surf->subpics, NULL); + surfaces[i] = handle_table_add(drv->htab, surf); + if (!surfaces[i]) { + vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; + goto destroy_surf; + } + } + mtx_unlock(&drv->mutex); + + return VA_STATUS_SUCCESS; + +destroy_surf: + surf->buffer->destroy(surf->buffer); + +free_surf: + FREE(surf); + +no_res: + mtx_unlock(&drv->mutex); + if (i) + vlVaDestroySurfaces(ctx, surfaces, i); + + return vaStatus; +} + +VAStatus +vlVaQueryVideoProcFilters(VADriverContextP ctx, VAContextID context, + VAProcFilterType *filters, unsigned int *num_filters) +{ + unsigned int num = 0; + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + if (!num_filters || !filters) + return VA_STATUS_ERROR_INVALID_PARAMETER; + + filters[num++] = VAProcFilterDeinterlacing; + + *num_filters = num; + + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaQueryVideoProcFilterCaps(VADriverContextP ctx, VAContextID context, + VAProcFilterType type, void *filter_caps, + unsigned int *num_filter_caps) +{ + unsigned int i; + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + if (!filter_caps || !num_filter_caps) + return VA_STATUS_ERROR_INVALID_PARAMETER; + + i = 0; + + switch (type) { + case VAProcFilterNone: + break; + case VAProcFilterDeinterlacing: { + VAProcFilterCapDeinterlacing *deint = filter_caps; + + if (*num_filter_caps < 3) { + *num_filter_caps = 3; + return VA_STATUS_ERROR_MAX_NUM_EXCEEDED; + } + + deint[i++].type = VAProcDeinterlacingBob; + deint[i++].type = VAProcDeinterlacingWeave; + deint[i++].type = VAProcDeinterlacingMotionAdaptive; + break; + } + + case VAProcFilterNoiseReduction: + case VAProcFilterSharpening: + case VAProcFilterColorBalance: + case VAProcFilterSkinToneEnhancement: + return VA_STATUS_ERROR_UNIMPLEMENTED; + default: + assert(0); + } + + *num_filter_caps = i; + + return VA_STATUS_SUCCESS; +} + +static VAProcColorStandardType vpp_input_color_standards[] = { + VAProcColorStandardBT601 +}; + +static VAProcColorStandardType vpp_output_color_standards[] = { + VAProcColorStandardBT601 +}; + +VAStatus +vlVaQueryVideoProcPipelineCaps(VADriverContextP ctx, VAContextID context, + VABufferID *filters, unsigned int num_filters, + VAProcPipelineCaps *pipeline_cap) +{ + unsigned int i = 0; + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + if (!pipeline_cap) + return VA_STATUS_ERROR_INVALID_PARAMETER; + + if (num_filters && !filters) + return VA_STATUS_ERROR_INVALID_PARAMETER; + + pipeline_cap->pipeline_flags = 0; + pipeline_cap->filter_flags = 0; + pipeline_cap->num_forward_references = 0; + pipeline_cap->num_backward_references = 0; + pipeline_cap->num_input_color_standards = ARRAY_SIZE(vpp_input_color_standards); + pipeline_cap->input_color_standards = vpp_input_color_standards; + pipeline_cap->num_output_color_standards = ARRAY_SIZE(vpp_output_color_standards); + pipeline_cap->output_color_standards = vpp_output_color_standards; + + for (i = 0; i < num_filters; i++) { + vlVaBuffer *buf = handle_table_get(VL_VA_DRIVER(ctx)->htab, filters[i]); + VAProcFilterParameterBufferBase *filter; + + if (!buf || buf->type != VAProcFilterParameterBufferType) + return VA_STATUS_ERROR_INVALID_BUFFER; + + filter = buf->data; + switch (filter->type) { + case VAProcFilterDeinterlacing: { + VAProcFilterParameterBufferDeinterlacing *deint = buf->data; + if (deint->algorithm == VAProcDeinterlacingMotionAdaptive) { + pipeline_cap->num_forward_references = 2; + pipeline_cap->num_backward_references = 1; + } + break; + } + default: + return VA_STATUS_ERROR_UNIMPLEMENTED; + } + } + + return VA_STATUS_SUCCESS; +} + +#if VA_CHECK_VERSION(1, 1, 0) +VAStatus +vlVaExportSurfaceHandle(VADriverContextP ctx, + VASurfaceID surface_id, + uint32_t mem_type, + uint32_t flags, + void *descriptor) +{ + vlVaDriver *drv; + vlVaSurface *surf; + struct pipe_surface **surfaces; + struct pipe_screen *screen; + VAStatus ret; + unsigned int usage; + int i, p; + + VADRMPRIMESurfaceDescriptor *desc = descriptor; + + if (mem_type != VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2) + return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE; + if (flags & VA_EXPORT_SURFACE_COMPOSED_LAYERS) + return VA_STATUS_ERROR_INVALID_SURFACE; + + drv = VL_VA_DRIVER(ctx); + screen = VL_VA_PSCREEN(ctx); + mtx_lock(&drv->mutex); + + surf = handle_table_get(drv->htab, surface_id); + if (!surf || !surf->buffer) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_INVALID_SURFACE; + } + + if (surf->buffer->interlaced) { + struct pipe_video_buffer *interlaced = surf->buffer; + struct u_rect src_rect, dst_rect; + + surf->templat.interlaced = false; + + ret = vlVaHandleSurfaceAllocate(drv, surf, &surf->templat); + if (ret != VA_STATUS_SUCCESS) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_ALLOCATION_FAILED; + } + + src_rect.x0 = dst_rect.x0 = 0; + src_rect.y0 = dst_rect.y0 = 0; + src_rect.x1 = dst_rect.x1 = surf->templat.width; + src_rect.y1 = dst_rect.y1 = surf->templat.height; + + vl_compositor_yuv_deint_full(&drv->cstate, &drv->compositor, + interlaced, surf->buffer, + &src_rect, &dst_rect, + VL_COMPOSITOR_WEAVE); + + interlaced->destroy(interlaced); + } + + surfaces = surf->buffer->get_surfaces(surf->buffer); + + usage = 0; + if (flags & VA_EXPORT_SURFACE_WRITE_ONLY) + usage |= PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE; + + desc->fourcc = PipeFormatToVaFourcc(surf->buffer->buffer_format); + desc->width = surf->buffer->width; + desc->height = surf->buffer->height; + + for (p = 0; p < VL_MAX_SURFACES; p++) { + struct winsys_handle whandle; + struct pipe_resource *resource; + uint32_t drm_format; + + if (!surfaces[p]) + break; + + resource = surfaces[p]->texture; + + switch (resource->format) { + case PIPE_FORMAT_R8_UNORM: + drm_format = DRM_FORMAT_R8; + break; + case PIPE_FORMAT_R8G8_UNORM: + drm_format = DRM_FORMAT_GR88; + break; + case PIPE_FORMAT_R16_UNORM: + drm_format = DRM_FORMAT_R16; + break; + case PIPE_FORMAT_R16G16_UNORM: + drm_format = DRM_FORMAT_GR1616; + break; + case PIPE_FORMAT_B8G8R8A8_UNORM: + drm_format = DRM_FORMAT_ARGB8888; + break; + case PIPE_FORMAT_R8G8B8A8_UNORM: + drm_format = DRM_FORMAT_ABGR8888; + break; + case PIPE_FORMAT_B8G8R8X8_UNORM: + drm_format = DRM_FORMAT_XRGB8888; + break; + case PIPE_FORMAT_R8G8B8X8_UNORM: + drm_format = DRM_FORMAT_XBGR8888; + break; + default: + ret = VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE; + goto fail; + } + + memset(&whandle, 0, sizeof(whandle)); + whandle.type = WINSYS_HANDLE_TYPE_FD; + + if (!screen->resource_get_handle(screen, drv->pipe, resource, + &whandle, usage)) { + ret = VA_STATUS_ERROR_INVALID_SURFACE; + goto fail; + } + + desc->objects[p].fd = (int)whandle.handle; + desc->objects[p].size = 0; + desc->objects[p].drm_format_modifier = whandle.modifier; + + desc->layers[p].drm_format = drm_format; + desc->layers[p].num_planes = 1; + desc->layers[p].object_index[0] = p; + desc->layers[p].offset[0] = whandle.offset; + desc->layers[p].pitch[0] = whandle.stride; + } + + desc->num_objects = p; + desc->num_layers = p; + + mtx_unlock(&drv->mutex); + + return VA_STATUS_SUCCESS; + +fail: + for (i = 0; i < p; i++) + close(desc->objects[i].fd); + + mtx_unlock(&drv->mutex); + + return ret; +} +#endif diff --git a/src/gallium/frontends/va/va_private.h b/src/gallium/frontends/va/va_private.h new file mode 100644 index 00000000000..e3a9790103b --- /dev/null +++ b/src/gallium/frontends/va/va_private.h @@ -0,0 +1,462 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian. + * Copyright 2014 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef VA_PRIVATE_H +#define VA_PRIVATE_H + +#include + +#include +#include +#include +#include + +#include "pipe/p_video_enums.h" +#include "pipe/p_video_codec.h" +#include "pipe/p_video_state.h" + +#include "vl/vl_compositor.h" +#include "vl/vl_csc.h" + +#include "util/u_dynarray.h" +#include "os/os_thread.h" + +#define VL_VA_DRIVER(ctx) ((vlVaDriver *)ctx->pDriverData) +#define VL_VA_PSCREEN(ctx) (VL_VA_DRIVER(ctx)->vscreen->pscreen) + +#define VL_VA_MAX_IMAGE_FORMATS 12 +#define VL_VA_ENC_GOP_COEFF 16 + +#define UINT_TO_PTR(x) ((void*)(uintptr_t)(x)) +#define PTR_TO_UINT(x) ((unsigned)((intptr_t)(x))) + +#define SOI 2 +#define DQT (4 + 4 * 65) +#define DHT (4 + 2 * 29 + 2 * 179) +#define DRI 6 +#define SOF (10 + 255 * 3) +#define SOS (8 + 4 * 2) +#define MAX_MJPEG_SLICE_HEADER_SIZE (SOI + DQT + DHT + DRI + SOF + SOS) + +static inline enum pipe_video_chroma_format +ChromaToPipe(int format) +{ + switch (format) { + case VA_RT_FORMAT_YUV420: + case VA_RT_FORMAT_YUV420_10BPP: + return PIPE_VIDEO_CHROMA_FORMAT_420; + case VA_RT_FORMAT_YUV422: + return PIPE_VIDEO_CHROMA_FORMAT_422; + case VA_RT_FORMAT_YUV444: + return PIPE_VIDEO_CHROMA_FORMAT_444; + default: + return PIPE_VIDEO_CHROMA_FORMAT_NONE; + } +} + +static inline enum pipe_format +VaFourccToPipeFormat(unsigned format) +{ + switch(format) { + case VA_FOURCC('N','V','1','2'): + return PIPE_FORMAT_NV12; + case VA_FOURCC('P','0','1','0'): + return PIPE_FORMAT_P010; + case VA_FOURCC('P','0','1','6'): + return PIPE_FORMAT_P016; + case VA_FOURCC('I','4','2','0'): + return PIPE_FORMAT_IYUV; + case VA_FOURCC('Y','V','1','2'): + return PIPE_FORMAT_YV12; + case VA_FOURCC('Y','U','Y','V'): + case VA_FOURCC('Y','U','Y','2'): + return PIPE_FORMAT_YUYV; + case VA_FOURCC('U','Y','V','Y'): + return PIPE_FORMAT_UYVY; + case VA_FOURCC('B','G','R','A'): + return PIPE_FORMAT_B8G8R8A8_UNORM; + case VA_FOURCC('R','G','B','A'): + return PIPE_FORMAT_R8G8B8A8_UNORM; + case VA_FOURCC('B','G','R','X'): + return PIPE_FORMAT_B8G8R8X8_UNORM; + case VA_FOURCC('R','G','B','X'): + return PIPE_FORMAT_R8G8B8X8_UNORM; + default: + assert(0); + return PIPE_FORMAT_NONE; + } +} + +static inline unsigned +PipeFormatToVaFourcc(enum pipe_format p_format) +{ + switch (p_format) { + case PIPE_FORMAT_NV12: + return VA_FOURCC('N','V','1','2'); + case PIPE_FORMAT_P010: + return VA_FOURCC('P','0','1','0'); + case PIPE_FORMAT_P016: + return VA_FOURCC('P','0','1','6'); + case PIPE_FORMAT_IYUV: + return VA_FOURCC('I','4','2','0'); + case PIPE_FORMAT_YV12: + return VA_FOURCC('Y','V','1','2'); + case PIPE_FORMAT_UYVY: + return VA_FOURCC('U','Y','V','Y'); + case PIPE_FORMAT_YUYV: + return VA_FOURCC('Y','U','Y','V'); + case PIPE_FORMAT_B8G8R8A8_UNORM: + return VA_FOURCC('B','G','R','A'); + case PIPE_FORMAT_R8G8B8A8_UNORM: + return VA_FOURCC('R','G','B','A'); + case PIPE_FORMAT_B8G8R8X8_UNORM: + return VA_FOURCC('B','G','R','X'); + case PIPE_FORMAT_R8G8B8X8_UNORM: + return VA_FOURCC('R','G','B','X'); + default: + assert(0); + return -1; + } +} + +static inline VAProfile +PipeToProfile(enum pipe_video_profile profile) +{ + switch (profile) { + case PIPE_VIDEO_PROFILE_MPEG2_SIMPLE: + return VAProfileMPEG2Simple; + case PIPE_VIDEO_PROFILE_MPEG2_MAIN: + return VAProfileMPEG2Main; + case PIPE_VIDEO_PROFILE_MPEG4_SIMPLE: + return VAProfileMPEG4Simple; + case PIPE_VIDEO_PROFILE_MPEG4_ADVANCED_SIMPLE: + return VAProfileMPEG4AdvancedSimple; + case PIPE_VIDEO_PROFILE_VC1_SIMPLE: + return VAProfileVC1Simple; + case PIPE_VIDEO_PROFILE_VC1_MAIN: + return VAProfileVC1Main; + case PIPE_VIDEO_PROFILE_VC1_ADVANCED: + return VAProfileVC1Advanced; + case PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE: + return VAProfileH264ConstrainedBaseline; + case PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN: + return VAProfileH264Main; + case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH: + return VAProfileH264High; + case PIPE_VIDEO_PROFILE_HEVC_MAIN: + return VAProfileHEVCMain; + case PIPE_VIDEO_PROFILE_HEVC_MAIN_10: + return VAProfileHEVCMain10; + case PIPE_VIDEO_PROFILE_JPEG_BASELINE: + return VAProfileJPEGBaseline; + case PIPE_VIDEO_PROFILE_VP9_PROFILE0: + return VAProfileVP9Profile0; + case PIPE_VIDEO_PROFILE_VP9_PROFILE2: + return VAProfileVP9Profile2; + case PIPE_VIDEO_PROFILE_MPEG4_AVC_EXTENDED: + case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH10: + case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH422: + case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH444: + case PIPE_VIDEO_PROFILE_MPEG4_AVC_CONSTRAINED_BASELINE: + case PIPE_VIDEO_PROFILE_HEVC_MAIN_12: + case PIPE_VIDEO_PROFILE_HEVC_MAIN_STILL: + case PIPE_VIDEO_PROFILE_HEVC_MAIN_444: + case PIPE_VIDEO_PROFILE_UNKNOWN: + return VAProfileNone; + default: + assert(0); + return -1; + } +} + +static inline enum pipe_video_profile +ProfileToPipe(VAProfile profile) +{ + switch (profile) { + case VAProfileMPEG2Simple: + return PIPE_VIDEO_PROFILE_MPEG2_SIMPLE; + case VAProfileMPEG2Main: + return PIPE_VIDEO_PROFILE_MPEG2_MAIN; + case VAProfileMPEG4Simple: + return PIPE_VIDEO_PROFILE_MPEG4_SIMPLE; + case VAProfileMPEG4AdvancedSimple: + return PIPE_VIDEO_PROFILE_MPEG4_ADVANCED_SIMPLE; + case VAProfileVC1Simple: + return PIPE_VIDEO_PROFILE_VC1_SIMPLE; + case VAProfileVC1Main: + return PIPE_VIDEO_PROFILE_VC1_MAIN; + case VAProfileVC1Advanced: + return PIPE_VIDEO_PROFILE_VC1_ADVANCED; + case VAProfileH264ConstrainedBaseline: + return PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE; + case VAProfileH264Main: + return PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN; + case VAProfileH264High: + return PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH; + case VAProfileHEVCMain: + return PIPE_VIDEO_PROFILE_HEVC_MAIN; + case VAProfileHEVCMain10: + return PIPE_VIDEO_PROFILE_HEVC_MAIN_10; + case VAProfileJPEGBaseline: + return PIPE_VIDEO_PROFILE_JPEG_BASELINE; + case VAProfileVP9Profile0: + return PIPE_VIDEO_PROFILE_VP9_PROFILE0; + case VAProfileVP9Profile2: + return PIPE_VIDEO_PROFILE_VP9_PROFILE2; + case VAProfileNone: + return PIPE_VIDEO_PROFILE_UNKNOWN; + default: + return PIPE_VIDEO_PROFILE_UNKNOWN; + } +} + +typedef struct { + struct vl_screen *vscreen; + struct pipe_context *pipe; + struct handle_table *htab; + struct vl_compositor compositor; + struct vl_compositor_state cstate; + vl_csc_matrix csc; + mtx_t mutex; + char vendor_string[256]; +} vlVaDriver; + +typedef struct { + VAImage *image; + + struct u_rect src_rect; + struct u_rect dst_rect; + + struct pipe_sampler_view *sampler; +} vlVaSubpicture; + +typedef struct { + VABufferType type; + unsigned int size; + unsigned int num_elements; + void *data; + struct { + struct pipe_resource *resource; + struct pipe_transfer *transfer; + } derived_surface; + unsigned int export_refcount; + VABufferInfo export_state; + unsigned int coded_size; +} vlVaBuffer; + +typedef struct { + struct pipe_video_codec templat, *decoder; + struct pipe_video_buffer *target; + union { + struct pipe_picture_desc base; + struct pipe_mpeg12_picture_desc mpeg12; + struct pipe_mpeg4_picture_desc mpeg4; + struct pipe_vc1_picture_desc vc1; + struct pipe_h264_picture_desc h264; + struct pipe_h265_picture_desc h265; + struct pipe_mjpeg_picture_desc mjpeg; + struct pipe_vp9_picture_desc vp9; + struct pipe_h264_enc_picture_desc h264enc; + struct pipe_h265_enc_picture_desc h265enc; + } desc; + + struct { + unsigned long long int frame_num; + unsigned int start_code_size; + unsigned int vti_bits; + unsigned int quant_scale; + VAPictureParameterBufferMPEG4 pps; + uint8_t start_code[32]; + } mpeg4; + + struct { + unsigned sampling_factor; + uint8_t slice_header[MAX_MJPEG_SLICE_HEADER_SIZE]; + unsigned int slice_header_size; + } mjpeg; + + struct vl_deint_filter *deint; + vlVaBuffer *coded_buf; + int target_id; + bool first_single_submitted; + int gop_coeff; + bool needs_begin_frame; + void *blit_cs; +} vlVaContext; + +typedef struct { + enum pipe_video_profile profile; + enum pipe_video_entrypoint entrypoint; + enum pipe_h264_enc_rate_control_method rc; + unsigned int rt_format; +} vlVaConfig; + +typedef struct { + struct pipe_video_buffer templat, *buffer; + struct util_dynarray subpics; /* vlVaSubpicture */ + VAContextID ctx; + vlVaBuffer *coded_buf; + void *feedback; + unsigned int frame_num_cnt; + bool force_flushed; +} vlVaSurface; + +// Public functions: +VAStatus VA_DRIVER_INIT_FUNC(VADriverContextP ctx); + +// vtable functions: +VAStatus vlVaTerminate(VADriverContextP ctx); +VAStatus vlVaQueryConfigProfiles(VADriverContextP ctx, VAProfile *profile_list,int *num_profiles); +VAStatus vlVaQueryConfigEntrypoints(VADriverContextP ctx, VAProfile profile, + VAEntrypoint *entrypoint_list, int *num_entrypoints); +VAStatus vlVaGetConfigAttributes(VADriverContextP ctx, VAProfile profile, VAEntrypoint entrypoint, + VAConfigAttrib *attrib_list, int num_attribs); +VAStatus vlVaCreateConfig(VADriverContextP ctx, VAProfile profile, VAEntrypoint entrypoint, + VAConfigAttrib *attrib_list, int num_attribs, VAConfigID *config_id); +VAStatus vlVaDestroyConfig(VADriverContextP ctx, VAConfigID config_id); +VAStatus vlVaQueryConfigAttributes(VADriverContextP ctx, VAConfigID config_id, VAProfile *profile, + VAEntrypoint *entrypoint, VAConfigAttrib *attrib_list, int *num_attribs); +VAStatus vlVaCreateSurfaces(VADriverContextP ctx, int width, int height, int format, + int num_surfaces, VASurfaceID *surfaces); +VAStatus vlVaDestroySurfaces(VADriverContextP ctx, VASurfaceID *surface_list, int num_surfaces); +VAStatus vlVaCreateContext(VADriverContextP ctx, VAConfigID config_id, int picture_width, int picture_height, + int flag, VASurfaceID *render_targets, int num_render_targets, VAContextID *context); +VAStatus vlVaDestroyContext(VADriverContextP ctx, VAContextID context); +VAStatus vlVaCreateBuffer(VADriverContextP ctx, VAContextID context, VABufferType type, unsigned int size, + unsigned int num_elements, void *data, VABufferID *buf_id); +VAStatus vlVaBufferSetNumElements(VADriverContextP ctx, VABufferID buf_id, unsigned int num_elements); +VAStatus vlVaMapBuffer(VADriverContextP ctx, VABufferID buf_id, void **pbuf); +VAStatus vlVaUnmapBuffer(VADriverContextP ctx, VABufferID buf_id); +VAStatus vlVaDestroyBuffer(VADriverContextP ctx, VABufferID buffer_id); +VAStatus vlVaBeginPicture(VADriverContextP ctx, VAContextID context, VASurfaceID render_target); +VAStatus vlVaRenderPicture(VADriverContextP ctx, VAContextID context, VABufferID *buffers, int num_buffers); +VAStatus vlVaEndPicture(VADriverContextP ctx, VAContextID context); +VAStatus vlVaSyncSurface(VADriverContextP ctx, VASurfaceID render_target); +VAStatus vlVaQuerySurfaceStatus(VADriverContextP ctx, VASurfaceID render_target, VASurfaceStatus *status); +VAStatus vlVaQuerySurfaceError(VADriverContextP ctx, VASurfaceID render_target, + VAStatus error_status, void **error_info); +VAStatus vlVaPutSurface(VADriverContextP ctx, VASurfaceID surface, void* draw, short srcx, short srcy, + unsigned short srcw, unsigned short srch, short destx, short desty, unsigned short destw, + unsigned short desth, VARectangle *cliprects, unsigned int number_cliprects, + unsigned int flags); +VAStatus vlVaQueryImageFormats(VADriverContextP ctx, VAImageFormat *format_list, int *num_formats); +VAStatus vlVaQuerySubpictureFormats(VADriverContextP ctx, VAImageFormat *format_list, + unsigned int *flags, unsigned int *num_formats); +VAStatus vlVaCreateImage(VADriverContextP ctx, VAImageFormat *format, int width, int height, VAImage *image); +VAStatus vlVaDeriveImage(VADriverContextP ctx, VASurfaceID surface, VAImage *image); +VAStatus vlVaDestroyImage(VADriverContextP ctx, VAImageID image); +VAStatus vlVaSetImagePalette(VADriverContextP ctx, VAImageID image, unsigned char *palette); +VAStatus vlVaGetImage(VADriverContextP ctx, VASurfaceID surface, int x, int y, + unsigned int width, unsigned int height, VAImageID image); +VAStatus vlVaPutImage(VADriverContextP ctx, VASurfaceID surface, VAImageID image, int src_x, int src_y, + unsigned int src_width, unsigned int src_height, int dest_x, int dest_y, + unsigned int dest_width, unsigned int dest_height); +VAStatus vlVaQuerySubpictureFormats(VADriverContextP ctx, VAImageFormat *format_list, + unsigned int *flags, unsigned int *num_formats); +VAStatus vlVaCreateSubpicture(VADriverContextP ctx, VAImageID image, VASubpictureID *subpicture); +VAStatus vlVaDestroySubpicture(VADriverContextP ctx, VASubpictureID subpicture); +VAStatus vlVaSubpictureImage(VADriverContextP ctx, VASubpictureID subpicture, VAImageID image); +VAStatus vlVaSetSubpictureChromakey(VADriverContextP ctx, VASubpictureID subpicture, + unsigned int chromakey_min, unsigned int chromakey_max, + unsigned int chromakey_mask); +VAStatus vlVaSetSubpictureGlobalAlpha(VADriverContextP ctx, VASubpictureID subpicture, float global_alpha); +VAStatus vlVaAssociateSubpicture(VADriverContextP ctx, VASubpictureID subpicture, VASurfaceID *target_surfaces, + int num_surfaces, short src_x, short src_y, + unsigned short src_width, unsigned short src_height, + short dest_x, short dest_y, unsigned short dest_width, unsigned short dest_height, + unsigned int flags); +VAStatus vlVaDeassociateSubpicture(VADriverContextP ctx, VASubpictureID subpicture, + VASurfaceID *target_surfaces, int num_surfaces); +VAStatus vlVaQueryDisplayAttributes(VADriverContextP ctx, VADisplayAttribute *attr_list, int *num_attributes); +VAStatus vlVaGetDisplayAttributes(VADriverContextP ctx, VADisplayAttribute *attr_list, int num_attributes); +VAStatus vlVaSetDisplayAttributes(VADriverContextP ctx, VADisplayAttribute *attr_list, int num_attributes); +VAStatus vlVaBufferInfo(VADriverContextP ctx, VABufferID buf_id, VABufferType *type, + unsigned int *size, unsigned int *num_elements); +VAStatus vlVaLockSurface(VADriverContextP ctx, VASurfaceID surface, unsigned int *fourcc, + unsigned int *luma_stride, unsigned int *chroma_u_stride, unsigned int *chroma_v_stride, + unsigned int *luma_offset, unsigned int *chroma_u_offset, unsigned int *chroma_v_offset, + unsigned int *buffer_name, void **buffer); +VAStatus vlVaUnlockSurface(VADriverContextP ctx, VASurfaceID surface); +VAStatus vlVaCreateSurfaces2(VADriverContextP ctx, unsigned int format, unsigned int width, unsigned int height, + VASurfaceID *surfaces, unsigned int num_surfaces, VASurfaceAttrib *attrib_list, + unsigned int num_attribs); +VAStatus vlVaQuerySurfaceAttributes(VADriverContextP ctx, VAConfigID config, VASurfaceAttrib *attrib_list, + unsigned int *num_attribs); + +VAStatus vlVaAcquireBufferHandle(VADriverContextP ctx, VABufferID buf_id, VABufferInfo *out_buf_info); +VAStatus vlVaReleaseBufferHandle(VADriverContextP ctx, VABufferID buf_id); +VAStatus vlVaExportSurfaceHandle(VADriverContextP ctx, VASurfaceID surface_id, uint32_t mem_type, uint32_t flags, void *descriptor); + +VAStatus vlVaQueryVideoProcFilters(VADriverContextP ctx, VAContextID context, VAProcFilterType *filters, + unsigned int *num_filters); +VAStatus vlVaQueryVideoProcFilterCaps(VADriverContextP ctx, VAContextID context, VAProcFilterType type, + void *filter_caps, unsigned int *num_filter_caps); +VAStatus vlVaQueryVideoProcPipelineCaps(VADriverContextP ctx, VAContextID context, VABufferID *filters, + unsigned int num_filters, VAProcPipelineCaps *pipeline_cap); + +// internal functions +VAStatus vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf); +VAStatus vlVaHandleSurfaceAllocate(vlVaDriver *drv, vlVaSurface *surface, struct pipe_video_buffer *templat); +void vlVaGetReferenceFrame(vlVaDriver *drv, VASurfaceID surface_id, struct pipe_video_buffer **ref_frame); +void vlVaHandlePictureParameterBufferMPEG12(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf); +void vlVaHandleIQMatrixBufferMPEG12(vlVaContext *context, vlVaBuffer *buf); +void vlVaHandleSliceParameterBufferMPEG12(vlVaContext *context, vlVaBuffer *buf); +void vlVaHandlePictureParameterBufferH264(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf); +void vlVaHandleIQMatrixBufferH264(vlVaContext *context, vlVaBuffer *buf); +void vlVaHandleSliceParameterBufferH264(vlVaContext *context, vlVaBuffer *buf); +void vlVaHandlePictureParameterBufferVC1(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf); +void vlVaHandleSliceParameterBufferVC1(vlVaContext *context, vlVaBuffer *buf); +void vlVaHandlePictureParameterBufferMPEG4(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf); +void vlVaHandleIQMatrixBufferMPEG4(vlVaContext *context, vlVaBuffer *buf); +void vlVaHandleSliceParameterBufferMPEG4(vlVaContext *context, vlVaBuffer *buf); +void vlVaDecoderFixMPEG4Startcode(vlVaContext *context); +void vlVaGetJpegSliceHeader(vlVaContext *context); +void vlVaHandlePictureParameterBufferHEVC(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf); +void vlVaHandleIQMatrixBufferHEVC(vlVaContext *context, vlVaBuffer *buf); +void vlVaHandleSliceParameterBufferHEVC(vlVaContext *context, vlVaBuffer *buf); +void vlVaHandlePictureParameterBufferMJPEG(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf); +void vlVaHandleIQMatrixBufferMJPEG(vlVaContext *context, vlVaBuffer *buf); +void vlVaHandleHuffmanTableBufferType(vlVaContext *context, vlVaBuffer *buf); +void vlVaHandleSliceParameterBufferMJPEG(vlVaContext *context, vlVaBuffer *buf); +void vlVaHandlePictureParameterBufferVP9(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf); +void vlVaHandleSliceParameterBufferVP9(vlVaContext *context, vlVaBuffer *buf); +void vlVaDecoderVP9BitstreamHeader(vlVaContext *context, vlVaBuffer *buf); +void getEncParamPresetH264(vlVaContext *context); +void getEncParamPresetH265(vlVaContext *context); +VAStatus vlVaHandleVAEncPictureParameterBufferTypeH264(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf); +VAStatus vlVaHandleVAEncSliceParameterBufferTypeH264(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf); +VAStatus vlVaHandleVAEncSequenceParameterBufferTypeH264(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf); +VAStatus vlVaHandleVAEncMiscParameterTypeRateControlH264(vlVaContext *context, VAEncMiscParameterBuffer *buf); +VAStatus vlVaHandleVAEncMiscParameterTypeFrameRateH264(vlVaContext *context, VAEncMiscParameterBuffer *buf); +VAStatus vlVaHandleVAEncPictureParameterBufferTypeHEVC(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf); +VAStatus vlVaHandleVAEncSliceParameterBufferTypeHEVC(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf); +VAStatus vlVaHandleVAEncSequenceParameterBufferTypeHEVC(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf); +VAStatus vlVaHandleVAEncMiscParameterTypeRateControlHEVC(vlVaContext *context, VAEncMiscParameterBuffer *buf); +VAStatus vlVaHandleVAEncMiscParameterTypeFrameRateHEVC(vlVaContext *context, VAEncMiscParameterBuffer *buf); + +#endif //VA_PRIVATE_H diff --git a/src/gallium/frontends/vdpau/Makefile.sources b/src/gallium/frontends/vdpau/Makefile.sources new file mode 100644 index 00000000000..dfe0bcd043f --- /dev/null +++ b/src/gallium/frontends/vdpau/Makefile.sources @@ -0,0 +1,13 @@ +C_SOURCES := \ + bitmap.c \ + decode.c \ + device.c \ + ftab.c \ + htab.c \ + mixer.c \ + output.c \ + preemption.c \ + presentation.c \ + query.c \ + surface.c \ + vdpau_private.h diff --git a/src/gallium/frontends/vdpau/bitmap.c b/src/gallium/frontends/vdpau/bitmap.c new file mode 100644 index 00000000000..643be75e618 --- /dev/null +++ b/src/gallium/frontends/vdpau/bitmap.c @@ -0,0 +1,209 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include + +#include "util/u_memory.h" +#include "util/u_sampler.h" + +#include "vdpau_private.h" + +/** + * Create a VdpBitmapSurface. + */ +VdpStatus +vlVdpBitmapSurfaceCreate(VdpDevice device, + VdpRGBAFormat rgba_format, + uint32_t width, uint32_t height, + VdpBool frequently_accessed, + VdpBitmapSurface *surface) +{ + struct pipe_context *pipe; + struct pipe_resource res_tmpl, *res; + struct pipe_sampler_view sv_templ; + VdpStatus ret; + + vlVdpBitmapSurface *vlsurface = NULL; + + if (!(width && height)) + return VDP_STATUS_INVALID_SIZE; + + vlVdpDevice *dev = vlGetDataHTAB(device); + if (!dev) + return VDP_STATUS_INVALID_HANDLE; + + pipe = dev->context; + if (!pipe) + return VDP_STATUS_INVALID_HANDLE; + + if (!surface) + return VDP_STATUS_INVALID_POINTER; + + vlsurface = CALLOC(1, sizeof(vlVdpBitmapSurface)); + if (!vlsurface) + return VDP_STATUS_RESOURCES; + + DeviceReference(&vlsurface->device, dev); + + memset(&res_tmpl, 0, sizeof(res_tmpl)); + res_tmpl.target = PIPE_TEXTURE_2D; + res_tmpl.format = VdpFormatRGBAToPipe(rgba_format); + res_tmpl.width0 = width; + res_tmpl.height0 = height; + res_tmpl.depth0 = 1; + res_tmpl.array_size = 1; + res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; + res_tmpl.usage = frequently_accessed ? PIPE_USAGE_DYNAMIC : PIPE_USAGE_DEFAULT; + + mtx_lock(&dev->mutex); + + if (!CheckSurfaceParams(pipe->screen, &res_tmpl)) { + ret = VDP_STATUS_RESOURCES; + goto err_unlock; + } + + res = pipe->screen->resource_create(pipe->screen, &res_tmpl); + if (!res) { + ret = VDP_STATUS_RESOURCES; + goto err_unlock; + } + + vlVdpDefaultSamplerViewTemplate(&sv_templ, res); + vlsurface->sampler_view = pipe->create_sampler_view(pipe, res, &sv_templ); + + pipe_resource_reference(&res, NULL); + + if (!vlsurface->sampler_view) { + ret = VDP_STATUS_RESOURCES; + goto err_unlock; + } + + mtx_unlock(&dev->mutex); + + *surface = vlAddDataHTAB(vlsurface); + if (*surface == 0) { + mtx_lock(&dev->mutex); + ret = VDP_STATUS_ERROR; + goto err_sampler; + } + + return VDP_STATUS_OK; + +err_sampler: + pipe_sampler_view_reference(&vlsurface->sampler_view, NULL); +err_unlock: + mtx_unlock(&dev->mutex); + DeviceReference(&vlsurface->device, NULL); + FREE(vlsurface); + return ret; +} + +/** + * Destroy a VdpBitmapSurface. + */ +VdpStatus +vlVdpBitmapSurfaceDestroy(VdpBitmapSurface surface) +{ + vlVdpBitmapSurface *vlsurface; + + vlsurface = vlGetDataHTAB(surface); + if (!vlsurface) + return VDP_STATUS_INVALID_HANDLE; + + mtx_lock(&vlsurface->device->mutex); + pipe_sampler_view_reference(&vlsurface->sampler_view, NULL); + mtx_unlock(&vlsurface->device->mutex); + + vlRemoveDataHTAB(surface); + DeviceReference(&vlsurface->device, NULL); + FREE(vlsurface); + + return VDP_STATUS_OK; +} + +/** + * Retrieve the parameters used to create a VdpBitmapSurface. + */ +VdpStatus +vlVdpBitmapSurfaceGetParameters(VdpBitmapSurface surface, + VdpRGBAFormat *rgba_format, + uint32_t *width, uint32_t *height, + VdpBool *frequently_accessed) +{ + vlVdpBitmapSurface *vlsurface; + struct pipe_resource *res; + + vlsurface = vlGetDataHTAB(surface); + if (!vlsurface) + return VDP_STATUS_INVALID_HANDLE; + + if (!(rgba_format && width && height && frequently_accessed)) + return VDP_STATUS_INVALID_POINTER; + + res = vlsurface->sampler_view->texture; + *rgba_format = PipeToFormatRGBA(res->format); + *width = res->width0; + *height = res->height0; + *frequently_accessed = res->usage == PIPE_USAGE_DYNAMIC; + + return VDP_STATUS_OK; +} + +/** + * Copy image data from application memory in the surface's native format to + * a VdpBitmapSurface. + */ +VdpStatus +vlVdpBitmapSurfacePutBitsNative(VdpBitmapSurface surface, + void const *const *source_data, + uint32_t const *source_pitches, + VdpRect const *destination_rect) +{ + vlVdpBitmapSurface *vlsurface; + struct pipe_box dst_box; + struct pipe_context *pipe; + + vlsurface = vlGetDataHTAB(surface); + if (!vlsurface) + return VDP_STATUS_INVALID_HANDLE; + + if (!(source_data && source_pitches)) + return VDP_STATUS_INVALID_POINTER; + + pipe = vlsurface->device->context; + + mtx_lock(&vlsurface->device->mutex); + + dst_box = RectToPipeBox(destination_rect, vlsurface->sampler_view->texture); + pipe->texture_subdata(pipe, vlsurface->sampler_view->texture, 0, + PIPE_TRANSFER_WRITE, &dst_box, *source_data, + *source_pitches, 0); + + mtx_unlock(&vlsurface->device->mutex); + + return VDP_STATUS_OK; +} diff --git a/src/gallium/frontends/vdpau/decode.c b/src/gallium/frontends/vdpau/decode.c new file mode 100644 index 00000000000..8d3c58714a8 --- /dev/null +++ b/src/gallium/frontends/vdpau/decode.c @@ -0,0 +1,684 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "util/u_memory.h" +#include "util/u_math.h" +#include "util/u_debug.h" +#include "util/u_video.h" + +#include "vl/vl_vlc.h" + +#include "vdpau_private.h" + +/** + * Create a VdpDecoder. + */ +VdpStatus +vlVdpDecoderCreate(VdpDevice device, + VdpDecoderProfile profile, + uint32_t width, uint32_t height, + uint32_t max_references, + VdpDecoder *decoder) +{ + struct pipe_video_codec templat = {}; + struct pipe_context *pipe; + struct pipe_screen *screen; + vlVdpDevice *dev; + vlVdpDecoder *vldecoder; + VdpStatus ret; + bool supported; + uint32_t maxwidth, maxheight; + + if (!decoder) + return VDP_STATUS_INVALID_POINTER; + *decoder = 0; + + if (!(width && height)) + return VDP_STATUS_INVALID_VALUE; + + templat.profile = ProfileToPipe(profile); + if (templat.profile == PIPE_VIDEO_PROFILE_UNKNOWN) + return VDP_STATUS_INVALID_DECODER_PROFILE; + + dev = vlGetDataHTAB(device); + if (!dev) + return VDP_STATUS_INVALID_HANDLE; + + pipe = dev->context; + screen = dev->vscreen->pscreen; + + mtx_lock(&dev->mutex); + + supported = screen->get_video_param + ( + screen, + templat.profile, + PIPE_VIDEO_ENTRYPOINT_BITSTREAM, + PIPE_VIDEO_CAP_SUPPORTED + ); + if (!supported) { + mtx_unlock(&dev->mutex); + return VDP_STATUS_INVALID_DECODER_PROFILE; + } + + maxwidth = screen->get_video_param + ( + screen, + templat.profile, + PIPE_VIDEO_ENTRYPOINT_BITSTREAM, + PIPE_VIDEO_CAP_MAX_WIDTH + ); + maxheight = screen->get_video_param + ( + screen, + templat.profile, + PIPE_VIDEO_ENTRYPOINT_BITSTREAM, + PIPE_VIDEO_CAP_MAX_HEIGHT + ); + if (width > maxwidth || height > maxheight) { + mtx_unlock(&dev->mutex); + return VDP_STATUS_INVALID_SIZE; + } + + vldecoder = CALLOC(1,sizeof(vlVdpDecoder)); + if (!vldecoder) { + mtx_unlock(&dev->mutex); + return VDP_STATUS_RESOURCES; + } + + DeviceReference(&vldecoder->device, dev); + + templat.entrypoint = PIPE_VIDEO_ENTRYPOINT_BITSTREAM; + templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; + templat.width = width; + templat.height = height; + templat.max_references = max_references; + + if (u_reduce_video_profile(templat.profile) == + PIPE_VIDEO_FORMAT_MPEG4_AVC) + templat.level = u_get_h264_level(templat.width, templat.height, + &templat.max_references); + + vldecoder->decoder = pipe->create_video_codec(pipe, &templat); + + if (!vldecoder->decoder) { + ret = VDP_STATUS_ERROR; + goto error_decoder; + } + + *decoder = vlAddDataHTAB(vldecoder); + if (*decoder == 0) { + ret = VDP_STATUS_ERROR; + goto error_handle; + } + + (void) mtx_init(&vldecoder->mutex, mtx_plain); + mtx_unlock(&dev->mutex); + + return VDP_STATUS_OK; + +error_handle: + vldecoder->decoder->destroy(vldecoder->decoder); + +error_decoder: + mtx_unlock(&dev->mutex); + DeviceReference(&vldecoder->device, NULL); + FREE(vldecoder); + return ret; +} + +/** + * Destroy a VdpDecoder. + */ +VdpStatus +vlVdpDecoderDestroy(VdpDecoder decoder) +{ + vlVdpDecoder *vldecoder; + + vldecoder = (vlVdpDecoder *)vlGetDataHTAB(decoder); + if (!vldecoder) + return VDP_STATUS_INVALID_HANDLE; + + mtx_lock(&vldecoder->mutex); + vldecoder->decoder->destroy(vldecoder->decoder); + mtx_unlock(&vldecoder->mutex); + mtx_destroy(&vldecoder->mutex); + + vlRemoveDataHTAB(decoder); + DeviceReference(&vldecoder->device, NULL); + FREE(vldecoder); + + return VDP_STATUS_OK; +} + +/** + * Retrieve the parameters used to create a VdpDecoder. + */ +VdpStatus +vlVdpDecoderGetParameters(VdpDecoder decoder, + VdpDecoderProfile *profile, + uint32_t *width, + uint32_t *height) +{ + vlVdpDecoder *vldecoder; + + vldecoder = (vlVdpDecoder *)vlGetDataHTAB(decoder); + if (!vldecoder) + return VDP_STATUS_INVALID_HANDLE; + + *profile = PipeToProfile(vldecoder->decoder->profile); + *width = vldecoder->decoder->width; + *height = vldecoder->decoder->height; + + return VDP_STATUS_OK; +} + +static VdpStatus +vlVdpGetReferenceFrame(VdpVideoSurface handle, struct pipe_video_buffer **ref_frame) +{ + vlVdpSurface *surface; + + /* if surfaces equals VDP_STATUS_INVALID_HANDLE, they are not used */ + if (handle == VDP_INVALID_HANDLE) { + *ref_frame = NULL; + return VDP_STATUS_OK; + } + + surface = vlGetDataHTAB(handle); + if (!surface) + return VDP_STATUS_INVALID_HANDLE; + + *ref_frame = surface->video_buffer; + if (!*ref_frame) + return VDP_STATUS_INVALID_HANDLE; + + return VDP_STATUS_OK; +} + +/** + * Decode a mpeg 1/2 video. + */ +static VdpStatus +vlVdpDecoderRenderMpeg12(struct pipe_mpeg12_picture_desc *picture, + VdpPictureInfoMPEG1Or2 *picture_info) +{ + VdpStatus r; + + VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Decoding MPEG12\n"); + + r = vlVdpGetReferenceFrame(picture_info->forward_reference, &picture->ref[0]); + if (r != VDP_STATUS_OK) + return r; + + r = vlVdpGetReferenceFrame(picture_info->backward_reference, &picture->ref[1]); + if (r != VDP_STATUS_OK) + return r; + + picture->picture_coding_type = picture_info->picture_coding_type; + picture->picture_structure = picture_info->picture_structure; + picture->frame_pred_frame_dct = picture_info->frame_pred_frame_dct; + picture->q_scale_type = picture_info->q_scale_type; + picture->alternate_scan = picture_info->alternate_scan; + picture->intra_vlc_format = picture_info->intra_vlc_format; + picture->concealment_motion_vectors = picture_info->concealment_motion_vectors; + picture->intra_dc_precision = picture_info->intra_dc_precision; + picture->f_code[0][0] = picture_info->f_code[0][0] - 1; + picture->f_code[0][1] = picture_info->f_code[0][1] - 1; + picture->f_code[1][0] = picture_info->f_code[1][0] - 1; + picture->f_code[1][1] = picture_info->f_code[1][1] - 1; + picture->num_slices = picture_info->slice_count; + picture->top_field_first = picture_info->top_field_first; + picture->full_pel_forward_vector = picture_info->full_pel_forward_vector; + picture->full_pel_backward_vector = picture_info->full_pel_backward_vector; + picture->intra_matrix = picture_info->intra_quantizer_matrix; + picture->non_intra_matrix = picture_info->non_intra_quantizer_matrix; + + return VDP_STATUS_OK; +} + +/** + * Decode a mpeg 4 video. + */ +static VdpStatus +vlVdpDecoderRenderMpeg4(struct pipe_mpeg4_picture_desc *picture, + VdpPictureInfoMPEG4Part2 *picture_info) +{ + VdpStatus r; + unsigned i; + + VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Decoding MPEG4\n"); + + r = vlVdpGetReferenceFrame(picture_info->forward_reference, &picture->ref[0]); + if (r != VDP_STATUS_OK) + return r; + + r = vlVdpGetReferenceFrame(picture_info->backward_reference, &picture->ref[1]); + if (r != VDP_STATUS_OK) + return r; + + for (i = 0; i < 2; ++i) { + picture->trd[i] = picture_info->trd[i]; + picture->trb[i] = picture_info->trb[i]; + } + picture->vop_time_increment_resolution = picture_info->vop_time_increment_resolution; + picture->vop_coding_type = picture_info->vop_coding_type; + picture->vop_fcode_forward = picture_info->vop_fcode_forward; + picture->vop_fcode_backward = picture_info->vop_fcode_backward; + picture->resync_marker_disable = picture_info->resync_marker_disable; + picture->interlaced = picture_info->interlaced; + picture->quant_type = picture_info->quant_type; + picture->quarter_sample = picture_info->quarter_sample; + picture->short_video_header = picture_info->short_video_header; + picture->rounding_control = picture_info->rounding_control; + picture->alternate_vertical_scan_flag = picture_info->alternate_vertical_scan_flag; + picture->top_field_first = picture_info->top_field_first; + picture->intra_matrix = picture_info->intra_quantizer_matrix; + picture->non_intra_matrix = picture_info->non_intra_quantizer_matrix; + + return VDP_STATUS_OK; +} + +static VdpStatus +vlVdpDecoderRenderVC1(struct pipe_vc1_picture_desc *picture, + VdpPictureInfoVC1 *picture_info) +{ + VdpStatus r; + + VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Decoding VC-1\n"); + + r = vlVdpGetReferenceFrame(picture_info->forward_reference, &picture->ref[0]); + if (r != VDP_STATUS_OK) + return r; + + r = vlVdpGetReferenceFrame(picture_info->backward_reference, &picture->ref[1]); + if (r != VDP_STATUS_OK) + return r; + + picture->slice_count = picture_info->slice_count; + picture->picture_type = picture_info->picture_type; + picture->frame_coding_mode = picture_info->frame_coding_mode; + picture->postprocflag = picture_info->postprocflag; + picture->pulldown = picture_info->pulldown; + picture->interlace = picture_info->interlace; + picture->tfcntrflag = picture_info->tfcntrflag; + picture->finterpflag = picture_info->finterpflag; + picture->psf = picture_info->psf; + picture->dquant = picture_info->dquant; + picture->panscan_flag = picture_info->panscan_flag; + picture->refdist_flag = picture_info->refdist_flag; + picture->quantizer = picture_info->quantizer; + picture->extended_mv = picture_info->extended_mv; + picture->extended_dmv = picture_info->extended_dmv; + picture->overlap = picture_info->overlap; + picture->vstransform = picture_info->vstransform; + picture->loopfilter = picture_info->loopfilter; + picture->fastuvmc = picture_info->fastuvmc; + picture->range_mapy_flag = picture_info->range_mapy_flag; + picture->range_mapy = picture_info->range_mapy; + picture->range_mapuv_flag = picture_info->range_mapuv_flag; + picture->range_mapuv = picture_info->range_mapuv; + picture->multires = picture_info->multires; + picture->syncmarker = picture_info->syncmarker; + picture->rangered = picture_info->rangered; + picture->maxbframes = picture_info->maxbframes; + picture->deblockEnable = picture_info->deblockEnable; + picture->pquant = picture_info->pquant; + + return VDP_STATUS_OK; +} + +static VdpStatus +vlVdpDecoderRenderH264(struct pipe_h264_picture_desc *picture, + VdpPictureInfoH264 *picture_info) +{ + unsigned i; + + VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Decoding H264\n"); + + picture->pps->sps->mb_adaptive_frame_field_flag = picture_info->mb_adaptive_frame_field_flag; + picture->pps->sps->frame_mbs_only_flag = picture_info->frame_mbs_only_flag; + picture->pps->sps->log2_max_frame_num_minus4 = picture_info->log2_max_frame_num_minus4; + picture->pps->sps->pic_order_cnt_type = picture_info->pic_order_cnt_type; + picture->pps->sps->log2_max_pic_order_cnt_lsb_minus4 = picture_info->log2_max_pic_order_cnt_lsb_minus4; + picture->pps->sps->delta_pic_order_always_zero_flag = picture_info->delta_pic_order_always_zero_flag; + picture->pps->sps->direct_8x8_inference_flag = picture_info->direct_8x8_inference_flag; + + picture->pps->transform_8x8_mode_flag = picture_info->transform_8x8_mode_flag; + picture->pps->chroma_qp_index_offset = picture_info->chroma_qp_index_offset; + picture->pps->second_chroma_qp_index_offset = picture_info->second_chroma_qp_index_offset; + picture->pps->pic_init_qp_minus26 = picture_info->pic_init_qp_minus26; + picture->pps->entropy_coding_mode_flag = picture_info->entropy_coding_mode_flag; + picture->pps->deblocking_filter_control_present_flag = picture_info->deblocking_filter_control_present_flag; + picture->pps->redundant_pic_cnt_present_flag = picture_info->redundant_pic_cnt_present_flag; + picture->pps->constrained_intra_pred_flag = picture_info->constrained_intra_pred_flag; + picture->pps->weighted_pred_flag = picture_info->weighted_pred_flag; + picture->pps->weighted_bipred_idc = picture_info->weighted_bipred_idc; + picture->pps->bottom_field_pic_order_in_frame_present_flag = picture_info->pic_order_present_flag; + memcpy(picture->pps->ScalingList4x4, picture_info->scaling_lists_4x4, 6*16); + memcpy(picture->pps->ScalingList8x8, picture_info->scaling_lists_8x8, 2*64); + + picture->slice_count = picture_info->slice_count; + picture->field_order_cnt[0] = picture_info->field_order_cnt[0]; + picture->field_order_cnt[1] = picture_info->field_order_cnt[1]; + picture->is_reference = picture_info->is_reference; + picture->frame_num = picture_info->frame_num; + picture->field_pic_flag = picture_info->field_pic_flag; + picture->bottom_field_flag = picture_info->bottom_field_flag; + picture->num_ref_frames = picture_info->num_ref_frames; + + picture->num_ref_idx_l0_active_minus1 = picture_info->num_ref_idx_l0_active_minus1; + picture->num_ref_idx_l1_active_minus1 = picture_info->num_ref_idx_l1_active_minus1; + + for (i = 0; i < 16; ++i) { + VdpStatus ret = vlVdpGetReferenceFrame + ( + picture_info->referenceFrames[i].surface, + &picture->ref[i] + ); + if (ret != VDP_STATUS_OK) + return ret; + + picture->is_long_term[i] = picture_info->referenceFrames[i].is_long_term; + picture->top_is_reference[i] = picture_info->referenceFrames[i].top_is_reference; + picture->bottom_is_reference[i] = picture_info->referenceFrames[i].bottom_is_reference; + picture->field_order_cnt_list[i][0] = picture_info->referenceFrames[i].field_order_cnt[0]; + picture->field_order_cnt_list[i][1] = picture_info->referenceFrames[i].field_order_cnt[1]; + picture->frame_num_list[i] = picture_info->referenceFrames[i].frame_idx; + } + + return VDP_STATUS_OK; +} + +static VdpStatus +vlVdpDecoderRenderH265(struct pipe_h265_picture_desc *picture, + VdpPictureInfoHEVC *picture_info) +{ + unsigned i; + + picture->pps->sps->chroma_format_idc = picture_info->chroma_format_idc; + picture->pps->sps->separate_colour_plane_flag = picture_info->separate_colour_plane_flag; + picture->pps->sps->pic_width_in_luma_samples = picture_info->pic_width_in_luma_samples; + picture->pps->sps->pic_height_in_luma_samples = picture_info->pic_height_in_luma_samples; + picture->pps->sps->bit_depth_luma_minus8 = picture_info->bit_depth_luma_minus8; + picture->pps->sps->bit_depth_chroma_minus8 = picture_info->bit_depth_chroma_minus8; + picture->pps->sps->log2_max_pic_order_cnt_lsb_minus4 = picture_info->log2_max_pic_order_cnt_lsb_minus4; + picture->pps->sps->sps_max_dec_pic_buffering_minus1 = picture_info->sps_max_dec_pic_buffering_minus1; + picture->pps->sps->log2_min_luma_coding_block_size_minus3 = picture_info->log2_min_luma_coding_block_size_minus3; + picture->pps->sps->log2_diff_max_min_luma_coding_block_size = picture_info->log2_diff_max_min_luma_coding_block_size; + picture->pps->sps->log2_min_transform_block_size_minus2 = picture_info->log2_min_transform_block_size_minus2; + picture->pps->sps->log2_diff_max_min_transform_block_size = picture_info->log2_diff_max_min_transform_block_size; + picture->pps->sps->max_transform_hierarchy_depth_inter = picture_info->max_transform_hierarchy_depth_inter; + picture->pps->sps->max_transform_hierarchy_depth_intra = picture_info->max_transform_hierarchy_depth_intra; + picture->pps->sps->scaling_list_enabled_flag = picture_info->scaling_list_enabled_flag; + memcpy(picture->pps->sps->ScalingList4x4, picture_info->ScalingList4x4, 6*16); + memcpy(picture->pps->sps->ScalingList8x8, picture_info->ScalingList8x8, 6*64); + memcpy(picture->pps->sps->ScalingList16x16, picture_info->ScalingList16x16, 6*64); + memcpy(picture->pps->sps->ScalingList32x32, picture_info->ScalingList32x32, 2*64); + memcpy(picture->pps->sps->ScalingListDCCoeff16x16, picture_info->ScalingListDCCoeff16x16, 6); + memcpy(picture->pps->sps->ScalingListDCCoeff32x32, picture_info->ScalingListDCCoeff32x32, 2); + picture->pps->sps->amp_enabled_flag = picture_info->amp_enabled_flag; + picture->pps->sps->sample_adaptive_offset_enabled_flag = picture_info->sample_adaptive_offset_enabled_flag; + picture->pps->sps->pcm_enabled_flag = picture_info->pcm_enabled_flag; + picture->pps->sps->pcm_sample_bit_depth_luma_minus1 = picture_info->pcm_sample_bit_depth_luma_minus1; + picture->pps->sps->pcm_sample_bit_depth_chroma_minus1 = picture_info->pcm_sample_bit_depth_chroma_minus1; + picture->pps->sps->log2_min_pcm_luma_coding_block_size_minus3 = picture_info->log2_min_pcm_luma_coding_block_size_minus3; + picture->pps->sps->log2_diff_max_min_pcm_luma_coding_block_size = picture_info->log2_diff_max_min_pcm_luma_coding_block_size; + picture->pps->sps->pcm_loop_filter_disabled_flag = picture_info->pcm_loop_filter_disabled_flag; + picture->pps->sps->num_short_term_ref_pic_sets = picture_info->num_short_term_ref_pic_sets; + picture->pps->sps->long_term_ref_pics_present_flag = picture_info->long_term_ref_pics_present_flag; + picture->pps->sps->num_long_term_ref_pics_sps = picture_info->num_long_term_ref_pics_sps; + picture->pps->sps->sps_temporal_mvp_enabled_flag = picture_info->sps_temporal_mvp_enabled_flag; + picture->pps->sps->strong_intra_smoothing_enabled_flag = picture_info->strong_intra_smoothing_enabled_flag; + + picture->pps->dependent_slice_segments_enabled_flag = picture_info->dependent_slice_segments_enabled_flag; + picture->pps->output_flag_present_flag = picture_info->output_flag_present_flag; + picture->pps->num_extra_slice_header_bits = picture_info->num_extra_slice_header_bits; + picture->pps->sign_data_hiding_enabled_flag = picture_info->sign_data_hiding_enabled_flag; + picture->pps->cabac_init_present_flag = picture_info->cabac_init_present_flag; + picture->pps->num_ref_idx_l0_default_active_minus1 = picture_info->num_ref_idx_l0_default_active_minus1; + picture->pps->num_ref_idx_l1_default_active_minus1 = picture_info->num_ref_idx_l1_default_active_minus1; + picture->pps->init_qp_minus26 = picture_info->init_qp_minus26; + picture->pps->constrained_intra_pred_flag = picture_info->constrained_intra_pred_flag; + picture->pps->transform_skip_enabled_flag = picture_info->transform_skip_enabled_flag; + picture->pps->cu_qp_delta_enabled_flag = picture_info->cu_qp_delta_enabled_flag; + picture->pps->diff_cu_qp_delta_depth = picture_info->diff_cu_qp_delta_depth; + picture->pps->pps_cb_qp_offset = picture_info->pps_cb_qp_offset; + picture->pps->pps_cr_qp_offset = picture_info->pps_cr_qp_offset; + picture->pps->pps_slice_chroma_qp_offsets_present_flag = picture_info->pps_slice_chroma_qp_offsets_present_flag; + picture->pps->weighted_pred_flag = picture_info->weighted_pred_flag; + picture->pps->weighted_bipred_flag = picture_info->weighted_bipred_flag; + picture->pps->transquant_bypass_enabled_flag = picture_info->transquant_bypass_enabled_flag; + picture->pps->tiles_enabled_flag = picture_info->tiles_enabled_flag; + picture->pps->entropy_coding_sync_enabled_flag = picture_info->entropy_coding_sync_enabled_flag; + picture->pps->num_tile_columns_minus1 = picture_info->num_tile_columns_minus1; + picture->pps->num_tile_rows_minus1 = picture_info->num_tile_rows_minus1; + picture->pps->uniform_spacing_flag = picture_info->uniform_spacing_flag; + memcpy(picture->pps->column_width_minus1, picture_info->column_width_minus1, 20 * 2); + memcpy(picture->pps->row_height_minus1, picture_info->row_height_minus1, 22 * 2); + picture->pps->loop_filter_across_tiles_enabled_flag = picture_info->loop_filter_across_tiles_enabled_flag; + picture->pps->pps_loop_filter_across_slices_enabled_flag = picture_info->pps_loop_filter_across_slices_enabled_flag; + picture->pps->deblocking_filter_control_present_flag = picture_info->deblocking_filter_control_present_flag; + picture->pps->deblocking_filter_override_enabled_flag = picture_info->deblocking_filter_override_enabled_flag; + picture->pps->pps_deblocking_filter_disabled_flag = picture_info->pps_deblocking_filter_disabled_flag; + picture->pps->pps_beta_offset_div2 = picture_info->pps_beta_offset_div2; + picture->pps->pps_tc_offset_div2 = picture_info->pps_tc_offset_div2; + picture->pps->lists_modification_present_flag = picture_info->lists_modification_present_flag; + picture->pps->log2_parallel_merge_level_minus2 = picture_info->log2_parallel_merge_level_minus2; + picture->pps->slice_segment_header_extension_present_flag = picture_info->slice_segment_header_extension_present_flag; + + picture->IDRPicFlag = picture_info->IDRPicFlag; + picture->RAPPicFlag = picture_info->RAPPicFlag; + picture->CurrRpsIdx = picture_info->CurrRpsIdx; + picture->NumPocTotalCurr = picture_info->NumPocTotalCurr; + picture->NumDeltaPocsOfRefRpsIdx = picture_info->NumDeltaPocsOfRefRpsIdx; + picture->NumShortTermPictureSliceHeaderBits = picture_info->NumShortTermPictureSliceHeaderBits; + picture->NumLongTermPictureSliceHeaderBits = picture_info->NumLongTermPictureSliceHeaderBits; + picture->CurrPicOrderCntVal = picture_info->CurrPicOrderCntVal; + + for (i = 0; i < 16; ++i) { + VdpStatus ret = vlVdpGetReferenceFrame + ( + picture_info->RefPics[i], + &picture->ref[i] + ); + if (ret != VDP_STATUS_OK) + return ret; + + picture->PicOrderCntVal[i] = picture_info->PicOrderCntVal[i]; + picture->IsLongTerm[i] = picture_info->IsLongTerm[i]; + } + + picture->NumPocStCurrBefore = picture_info->NumPocStCurrBefore; + picture->NumPocStCurrAfter = picture_info->NumPocStCurrAfter; + picture->NumPocLtCurr = picture_info->NumPocLtCurr; + memcpy(picture->RefPicSetStCurrBefore, picture_info->RefPicSetStCurrBefore, 8); + memcpy(picture->RefPicSetStCurrAfter, picture_info->RefPicSetStCurrAfter, 8); + memcpy(picture->RefPicSetLtCurr, picture_info->RefPicSetLtCurr, 8); + picture->UseRefPicList = false; + + return VDP_STATUS_OK; +} + +static void +vlVdpDecoderFixVC1Startcode(uint32_t *num_buffers, const void *buffers[], unsigned sizes[]) +{ + static const uint8_t vc1_startcode[] = { 0x00, 0x00, 0x01, 0x0D }; + struct vl_vlc vlc = {}; + unsigned i; + + /* search the first 64 bytes for a startcode */ + vl_vlc_init(&vlc, *num_buffers, buffers, sizes); + while (vl_vlc_search_byte(&vlc, 64*8, 0x00) && vl_vlc_bits_left(&vlc) >= 32) { + uint32_t value = vl_vlc_peekbits(&vlc, 32); + if (value == 0x0000010D || + value == 0x0000010C || + value == 0x0000010B) + return; + vl_vlc_eatbits(&vlc, 8); + } + + /* none found, ok add one manually */ + VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Manually adding VC-1 startcode\n"); + for (i = *num_buffers; i > 0; --i) { + buffers[i] = buffers[i - 1]; + sizes[i] = sizes[i - 1]; + } + ++(*num_buffers); + buffers[0] = vc1_startcode; + sizes[0] = 4; +} + +/** + * Decode a compressed field/frame and render the result into a VdpVideoSurface. + */ +VdpStatus +vlVdpDecoderRender(VdpDecoder decoder, + VdpVideoSurface target, + VdpPictureInfo const *picture_info, + uint32_t bitstream_buffer_count, + VdpBitstreamBuffer const *bitstream_buffers) +{ + const void * buffers[bitstream_buffer_count + 1]; + unsigned sizes[bitstream_buffer_count + 1]; + vlVdpDecoder *vldecoder; + vlVdpSurface *vlsurf; + VdpStatus ret; + struct pipe_screen *screen; + struct pipe_video_codec *dec; + bool buffer_support[2]; + unsigned i; + struct pipe_h264_sps sps_h264 = {}; + struct pipe_h264_pps pps_h264 = { &sps_h264 }; + struct pipe_h265_sps sps_h265 = {}; + struct pipe_h265_pps pps_h265 = { &sps_h265 }; + union { + struct pipe_picture_desc base; + struct pipe_mpeg12_picture_desc mpeg12; + struct pipe_mpeg4_picture_desc mpeg4; + struct pipe_vc1_picture_desc vc1; + struct pipe_h264_picture_desc h264; + struct pipe_h265_picture_desc h265; + } desc; + + if (!(picture_info && bitstream_buffers)) + return VDP_STATUS_INVALID_POINTER; + + vldecoder = (vlVdpDecoder *)vlGetDataHTAB(decoder); + if (!vldecoder) + return VDP_STATUS_INVALID_HANDLE; + dec = vldecoder->decoder; + screen = dec->context->screen; + + vlsurf = (vlVdpSurface *)vlGetDataHTAB(target); + if (!vlsurf) + return VDP_STATUS_INVALID_HANDLE; + + if (vlsurf->device != vldecoder->device) + return VDP_STATUS_HANDLE_DEVICE_MISMATCH; + + if (vlsurf->video_buffer != NULL && + pipe_format_to_chroma_format(vlsurf->video_buffer->buffer_format) != dec->chroma_format) + // TODO: Recreate decoder with correct chroma + return VDP_STATUS_INVALID_CHROMA_TYPE; + + buffer_support[0] = screen->get_video_param(screen, dec->profile, PIPE_VIDEO_ENTRYPOINT_BITSTREAM, + PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE); + buffer_support[1] = screen->get_video_param(screen, dec->profile, PIPE_VIDEO_ENTRYPOINT_BITSTREAM, + PIPE_VIDEO_CAP_SUPPORTS_INTERLACED); + + if (vlsurf->video_buffer == NULL || + !screen->is_video_format_supported(screen, vlsurf->video_buffer->buffer_format, + dec->profile, PIPE_VIDEO_ENTRYPOINT_BITSTREAM) || + !buffer_support[vlsurf->video_buffer->interlaced]) { + + mtx_lock(&vlsurf->device->mutex); + + /* destroy the old one */ + if (vlsurf->video_buffer) + vlsurf->video_buffer->destroy(vlsurf->video_buffer); + + /* set the buffer format to the prefered one */ + vlsurf->templat.buffer_format = screen->get_video_param(screen, dec->profile, PIPE_VIDEO_ENTRYPOINT_BITSTREAM, + PIPE_VIDEO_CAP_PREFERED_FORMAT); + + /* also set interlacing to decoders preferences */ + vlsurf->templat.interlaced = screen->get_video_param(screen, dec->profile, PIPE_VIDEO_ENTRYPOINT_BITSTREAM, + PIPE_VIDEO_CAP_PREFERS_INTERLACED); + + /* and recreate the video buffer */ + vlsurf->video_buffer = dec->context->create_video_buffer(dec->context, &vlsurf->templat); + + /* still no luck? get me out of here... */ + if (!vlsurf->video_buffer) { + mtx_unlock(&vlsurf->device->mutex); + return VDP_STATUS_NO_IMPLEMENTATION; + } + vlVdpVideoSurfaceClear(vlsurf); + mtx_unlock(&vlsurf->device->mutex); + } + + for (i = 0; i < bitstream_buffer_count; ++i) { + buffers[i] = bitstream_buffers[i].bitstream; + sizes[i] = bitstream_buffers[i].bitstream_bytes; + } + + memset(&desc, 0, sizeof(desc)); + desc.base.profile = dec->profile; + switch (u_reduce_video_profile(dec->profile)) { + case PIPE_VIDEO_FORMAT_MPEG12: + ret = vlVdpDecoderRenderMpeg12(&desc.mpeg12, (VdpPictureInfoMPEG1Or2 *)picture_info); + break; + case PIPE_VIDEO_FORMAT_MPEG4: + ret = vlVdpDecoderRenderMpeg4(&desc.mpeg4, (VdpPictureInfoMPEG4Part2 *)picture_info); + break; + case PIPE_VIDEO_FORMAT_VC1: + if (dec->profile == PIPE_VIDEO_PROFILE_VC1_ADVANCED) + vlVdpDecoderFixVC1Startcode(&bitstream_buffer_count, buffers, sizes); + ret = vlVdpDecoderRenderVC1(&desc.vc1, (VdpPictureInfoVC1 *)picture_info); + break; + case PIPE_VIDEO_FORMAT_MPEG4_AVC: + desc.h264.pps = &pps_h264; + ret = vlVdpDecoderRenderH264(&desc.h264, (VdpPictureInfoH264 *)picture_info); + break; + case PIPE_VIDEO_FORMAT_HEVC: + desc.h265.pps = &pps_h265; + ret = vlVdpDecoderRenderH265(&desc.h265, (VdpPictureInfoHEVC *)picture_info); + break; + default: + return VDP_STATUS_INVALID_DECODER_PROFILE; + } + + if (ret != VDP_STATUS_OK) + return ret; + + mtx_lock(&vldecoder->mutex); + dec->begin_frame(dec, vlsurf->video_buffer, &desc.base); + dec->decode_bitstream(dec, vlsurf->video_buffer, &desc.base, bitstream_buffer_count, buffers, sizes); + dec->end_frame(dec, vlsurf->video_buffer, &desc.base); + mtx_unlock(&vldecoder->mutex); + return ret; +} diff --git a/src/gallium/frontends/vdpau/device.c b/src/gallium/frontends/vdpau/device.c new file mode 100644 index 00000000000..5df30ea3c08 --- /dev/null +++ b/src/gallium/frontends/vdpau/device.c @@ -0,0 +1,327 @@ +/************************************************************************** + * + * Copyright 2010 Younes Manton og Thomas Balling Sørensen. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "pipe/p_compiler.h" + +#include "util/u_memory.h" +#include "util/u_debug.h" +#include "util/format/u_format.h" +#include "util/u_sampler.h" + +#include "vdpau_private.h" + +/** + * Create a VdpDevice object for use with X11. + */ +PUBLIC VdpStatus +vdp_imp_device_create_x11(Display *display, int screen, VdpDevice *device, + VdpGetProcAddress **get_proc_address) +{ + struct pipe_screen *pscreen; + struct pipe_resource *res, res_tmpl; + struct pipe_sampler_view sv_tmpl; + vlVdpDevice *dev = NULL; + VdpStatus ret; + + if (!(display && device && get_proc_address)) + return VDP_STATUS_INVALID_POINTER; + + if (!vlCreateHTAB()) { + ret = VDP_STATUS_RESOURCES; + goto no_htab; + } + + dev = CALLOC(1, sizeof(vlVdpDevice)); + if (!dev) { + ret = VDP_STATUS_RESOURCES; + goto no_dev; + } + + pipe_reference_init(&dev->reference, 1); + + dev->vscreen = vl_dri3_screen_create(display, screen); + if (!dev->vscreen) + dev->vscreen = vl_dri2_screen_create(display, screen); + if (!dev->vscreen) { + ret = VDP_STATUS_RESOURCES; + goto no_vscreen; + } + + pscreen = dev->vscreen->pscreen; + dev->context = pipe_create_multimedia_context(pscreen); + if (!dev->context) { + ret = VDP_STATUS_RESOURCES; + goto no_context; + } + + if (!pscreen->get_param(pscreen, PIPE_CAP_NPOT_TEXTURES)) { + ret = VDP_STATUS_NO_IMPLEMENTATION; + goto no_context; + } + + memset(&res_tmpl, 0, sizeof(res_tmpl)); + + res_tmpl.target = PIPE_TEXTURE_2D; + res_tmpl.format = PIPE_FORMAT_R8G8B8A8_UNORM; + res_tmpl.width0 = 1; + res_tmpl.height0 = 1; + res_tmpl.depth0 = 1; + res_tmpl.array_size = 1; + res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW; + res_tmpl.usage = PIPE_USAGE_DEFAULT; + + if (!CheckSurfaceParams(pscreen, &res_tmpl)) { + ret = VDP_STATUS_NO_IMPLEMENTATION; + goto no_resource; + } + + res = pscreen->resource_create(pscreen, &res_tmpl); + if (!res) { + ret = VDP_STATUS_RESOURCES; + goto no_resource; + } + + memset(&sv_tmpl, 0, sizeof(sv_tmpl)); + u_sampler_view_default_template(&sv_tmpl, res, res->format); + + sv_tmpl.swizzle_r = PIPE_SWIZZLE_1; + sv_tmpl.swizzle_g = PIPE_SWIZZLE_1; + sv_tmpl.swizzle_b = PIPE_SWIZZLE_1; + sv_tmpl.swizzle_a = PIPE_SWIZZLE_1; + + dev->dummy_sv = dev->context->create_sampler_view(dev->context, res, &sv_tmpl); + pipe_resource_reference(&res, NULL); + if (!dev->dummy_sv) { + ret = VDP_STATUS_RESOURCES; + goto no_resource; + } + + *device = vlAddDataHTAB(dev); + if (*device == 0) { + ret = VDP_STATUS_ERROR; + goto no_handle; + } + + if (!vl_compositor_init(&dev->compositor, dev->context)) { + ret = VDP_STATUS_ERROR; + goto no_compositor; + } + + (void) mtx_init(&dev->mutex, mtx_plain); + + *get_proc_address = &vlVdpGetProcAddress; + + return VDP_STATUS_OK; + +no_compositor: + vlRemoveDataHTAB(*device); +no_handle: + pipe_sampler_view_reference(&dev->dummy_sv, NULL); +no_resource: + dev->context->destroy(dev->context); +no_context: + dev->vscreen->destroy(dev->vscreen); +no_vscreen: + FREE(dev); +no_dev: + vlDestroyHTAB(); +no_htab: + return ret; +} + +/** + * Create a VdpPresentationQueueTarget for use with X11. + */ +VdpStatus +vlVdpPresentationQueueTargetCreateX11(VdpDevice device, Drawable drawable, + VdpPresentationQueueTarget *target) +{ + vlVdpPresentationQueueTarget *pqt; + VdpStatus ret; + + if (!drawable) + return VDP_STATUS_INVALID_HANDLE; + + vlVdpDevice *dev = vlGetDataHTAB(device); + if (!dev) + return VDP_STATUS_INVALID_HANDLE; + + pqt = CALLOC(1, sizeof(vlVdpPresentationQueue)); + if (!pqt) + return VDP_STATUS_RESOURCES; + + DeviceReference(&pqt->device, dev); + pqt->drawable = drawable; + + *target = vlAddDataHTAB(pqt); + if (*target == 0) { + ret = VDP_STATUS_ERROR; + goto no_handle; + } + + return VDP_STATUS_OK; + +no_handle: + FREE(pqt); + return ret; +} + +/** + * Destroy a VdpPresentationQueueTarget. + */ +VdpStatus +vlVdpPresentationQueueTargetDestroy(VdpPresentationQueueTarget presentation_queue_target) +{ + vlVdpPresentationQueueTarget *pqt; + + pqt = vlGetDataHTAB(presentation_queue_target); + if (!pqt) + return VDP_STATUS_INVALID_HANDLE; + + vlRemoveDataHTAB(presentation_queue_target); + DeviceReference(&pqt->device, NULL); + FREE(pqt); + + return VDP_STATUS_OK; +} + +/** + * Destroy a VdpDevice. + */ +VdpStatus +vlVdpDeviceDestroy(VdpDevice device) +{ + vlVdpDevice *dev = vlGetDataHTAB(device); + if (!dev) + return VDP_STATUS_INVALID_HANDLE; + + vlRemoveDataHTAB(device); + DeviceReference(&dev, NULL); + + return VDP_STATUS_OK; +} + +/** + * Free a VdpDevice. + */ +void +vlVdpDeviceFree(vlVdpDevice *dev) +{ + mtx_destroy(&dev->mutex); + vl_compositor_cleanup(&dev->compositor); + pipe_sampler_view_reference(&dev->dummy_sv, NULL); + dev->context->destroy(dev->context); + dev->vscreen->destroy(dev->vscreen); + FREE(dev); + vlDestroyHTAB(); +} + +/** + * Retrieve a VDPAU function pointer. + */ +VdpStatus +vlVdpGetProcAddress(VdpDevice device, VdpFuncId function_id, void **function_pointer) +{ + vlVdpDevice *dev = vlGetDataHTAB(device); + if (!dev) + return VDP_STATUS_INVALID_HANDLE; + + if (!function_pointer) + return VDP_STATUS_INVALID_POINTER; + + if (!vlGetFuncFTAB(function_id, function_pointer)) + return VDP_STATUS_INVALID_FUNC_ID; + + VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Got proc address %p for id %d\n", *function_pointer, function_id); + + return VDP_STATUS_OK; +} + +#define _ERROR_TYPE(TYPE,STRING) case TYPE: return STRING; + +/** + * Retrieve a string describing an error code. + */ +char const * +vlVdpGetErrorString (VdpStatus status) +{ + switch (status) { + _ERROR_TYPE(VDP_STATUS_OK,"The operation completed successfully; no error."); + _ERROR_TYPE(VDP_STATUS_NO_IMPLEMENTATION,"No backend implementation could be loaded."); + _ERROR_TYPE(VDP_STATUS_DISPLAY_PREEMPTED,"The display was preempted, or a fatal error occurred. The application must re-initialize VDPAU."); + _ERROR_TYPE(VDP_STATUS_INVALID_HANDLE,"An invalid handle value was provided. Either the handle does not exist at all, or refers to an object of an incorrect type."); + _ERROR_TYPE(VDP_STATUS_INVALID_POINTER,"An invalid pointer was provided. Typically, this means that a NULL pointer was provided for an 'output' parameter."); + _ERROR_TYPE(VDP_STATUS_INVALID_CHROMA_TYPE,"An invalid/unsupported VdpChromaType value was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_Y_CB_CR_FORMAT,"An invalid/unsupported VdpYCbCrFormat value was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_RGBA_FORMAT,"An invalid/unsupported VdpRGBAFormat value was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_INDEXED_FORMAT,"An invalid/unsupported VdpIndexedFormat value was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_COLOR_STANDARD,"An invalid/unsupported VdpColorStandard value was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_COLOR_TABLE_FORMAT,"An invalid/unsupported VdpColorTableFormat value was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_BLEND_FACTOR,"An invalid/unsupported VdpOutputSurfaceRenderBlendFactor value was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_BLEND_EQUATION,"An invalid/unsupported VdpOutputSurfaceRenderBlendEquation value was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_FLAG,"An invalid/unsupported flag value/combination was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_DECODER_PROFILE,"An invalid/unsupported VdpDecoderProfile value was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_VIDEO_MIXER_FEATURE,"An invalid/unsupported VdpVideoMixerFeature value was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_VIDEO_MIXER_PARAMETER,"An invalid/unsupported VdpVideoMixerParameter value was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_VIDEO_MIXER_ATTRIBUTE,"An invalid/unsupported VdpVideoMixerAttribute value was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_VIDEO_MIXER_PICTURE_STRUCTURE,"An invalid/unsupported VdpVideoMixerPictureStructure value was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_FUNC_ID,"An invalid/unsupported VdpFuncId value was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_SIZE,"The size of a supplied object does not match the object it is being used with.\ + For example, a VdpVideoMixer is configured to process VdpVideoSurface objects of a specific size.\ + If presented with a VdpVideoSurface of a different size, this error will be raised."); + _ERROR_TYPE(VDP_STATUS_INVALID_VALUE,"An invalid/unsupported value was supplied.\ + This is a catch-all error code for values of type other than those with a specific error code."); + _ERROR_TYPE(VDP_STATUS_INVALID_STRUCT_VERSION,"An invalid/unsupported structure version was specified in a versioned structure. \ + This implies that the implementation is older than the header file the application was built against."); + _ERROR_TYPE(VDP_STATUS_RESOURCES,"The system does not have enough resources to complete the requested operation at this time."); + _ERROR_TYPE(VDP_STATUS_HANDLE_DEVICE_MISMATCH,"The set of handles supplied are not all related to the same VdpDevice.When performing operations \ + that operate on multiple surfaces, such as VdpOutputSurfaceRenderOutputSurface or VdpVideoMixerRender, \ + all supplied surfaces must have been created within the context of the same VdpDevice object. \ + This error is raised if they were not."); + _ERROR_TYPE(VDP_STATUS_ERROR,"A catch-all error, used when no other error code applies."); + default: return "Unknown Error"; + } +} + +void +vlVdpDefaultSamplerViewTemplate(struct pipe_sampler_view *templ, struct pipe_resource *res) +{ + const struct util_format_description *desc; + + memset(templ, 0, sizeof(*templ)); + u_sampler_view_default_template(templ, res, res->format); + + desc = util_format_description(res->format); + if (desc->swizzle[0] == PIPE_SWIZZLE_0) + templ->swizzle_r = PIPE_SWIZZLE_1; + if (desc->swizzle[1] == PIPE_SWIZZLE_0) + templ->swizzle_g = PIPE_SWIZZLE_1; + if (desc->swizzle[2] == PIPE_SWIZZLE_0) + templ->swizzle_b = PIPE_SWIZZLE_1; + if (desc->swizzle[3] == PIPE_SWIZZLE_0) + templ->swizzle_a = PIPE_SWIZZLE_1; +} diff --git a/src/gallium/frontends/vdpau/ftab.c b/src/gallium/frontends/vdpau/ftab.c new file mode 100644 index 00000000000..31786229bc5 --- /dev/null +++ b/src/gallium/frontends/vdpau/ftab.c @@ -0,0 +1,139 @@ +/************************************************************************** + * + * Copyright 2010 Younes Manton & Thomas Balling Sørensen. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include + +#include "util/u_memory.h" + +#include "vdpau_private.h" + +static void* ftab[67] = +{ + &vlVdpGetErrorString, /* VDP_FUNC_ID_GET_ERROR_STRING */ + &vlVdpGetProcAddress, /* VDP_FUNC_ID_GET_PROC_ADDRESS */ + &vlVdpGetApiVersion, /* VDP_FUNC_ID_GET_API_VERSION */ + NULL, /* DUMMY */ + &vlVdpGetInformationString, /* VDP_FUNC_ID_GET_INFORMATION_STRING */ + &vlVdpDeviceDestroy, /* VDP_FUNC_ID_DEVICE_DESTROY */ + &vlVdpGenerateCSCMatrix, /* VDP_FUNC_ID_GENERATE_CSC_MATRIX */ + &vlVdpVideoSurfaceQueryCapabilities, /* VDP_FUNC_ID_VIDEO_SURFACE_QUERY_CAPABILITIES */ + &vlVdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities, /* VDP_FUNC_ID_VIDEO_SURFACE_QUERY_GET_PUT_BITS_Y_CB_CR_CAPABILITIES */ + &vlVdpVideoSurfaceCreate, /* VDP_FUNC_ID_VIDEO_SURFACE_CREATE */ + &vlVdpVideoSurfaceDestroy, /* VDP_FUNC_ID_VIDEO_SURFACE_DESTROY */ + &vlVdpVideoSurfaceGetParameters, /* VDP_FUNC_ID_VIDEO_SURFACE_GET_PARAMETERS */ + &vlVdpVideoSurfaceGetBitsYCbCr, /* VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR */ + &vlVdpVideoSurfacePutBitsYCbCr, /* VDP_FUNC_ID_VIDEO_SURFACE_PUT_BITS_Y_CB_CR */ + &vlVdpOutputSurfaceQueryCapabilities, /* VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_CAPABILITIES */ + &vlVdpOutputSurfaceQueryGetPutBitsNativeCapabilities, /* VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_GET_PUT_BITS_NATIVE_CAPABILITIES */ + &vlVdpOutputSurfaceQueryPutBitsIndexedCapabilities, /* VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_PUT_BITS_INDEXED_CAPABILITIES */ + &vlVdpOutputSurfaceQueryPutBitsYCbCrCapabilities, /* VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_PUT_BITS_Y_CB_CR_CAPABILITIES */ + &vlVdpOutputSurfaceCreate, /* VDP_FUNC_ID_OUTPUT_SURFACE_CREATE */ + &vlVdpOutputSurfaceDestroy, /* VDP_FUNC_ID_OUTPUT_SURFACE_DESTROY */ + &vlVdpOutputSurfaceGetParameters, /* VDP_FUNC_ID_OUTPUT_SURFACE_GET_PARAMETERS */ + &vlVdpOutputSurfaceGetBitsNative, /* VDP_FUNC_ID_OUTPUT_SURFACE_GET_BITS_NATIVE */ + &vlVdpOutputSurfacePutBitsNative, /* VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_NATIVE */ + &vlVdpOutputSurfacePutBitsIndexed, /* VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_INDEXED */ + &vlVdpOutputSurfacePutBitsYCbCr, /* VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_Y_CB_CR */ + &vlVdpBitmapSurfaceQueryCapabilities, /* VDP_FUNC_ID_BITMAP_SURFACE_QUERY_CAPABILITIES */ + &vlVdpBitmapSurfaceCreate, /* VDP_FUNC_ID_BITMAP_SURFACE_CREATE */ + &vlVdpBitmapSurfaceDestroy, /* VDP_FUNC_ID_BITMAP_SURFACE_DESTROY */ + &vlVdpBitmapSurfaceGetParameters, /* VDP_FUNC_ID_BITMAP_SURFACE_GET_PARAMETERS */ + &vlVdpBitmapSurfacePutBitsNative, /* VDP_FUNC_ID_BITMAP_SURFACE_PUT_BITS_NATIVE */ + NULL, /* DUMMY */ + NULL, /* DUMMY */ + NULL, /* DUMMY */ + &vlVdpOutputSurfaceRenderOutputSurface, /* VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_OUTPUT_SURFACE */ + &vlVdpOutputSurfaceRenderBitmapSurface, /* VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_BITMAP_SURFACE */ + NULL, /* VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_VIDEO_SURFACE_LUMA */ + &vlVdpDecoderQueryCapabilities, /* VDP_FUNC_ID_DECODER_QUERY_CAPABILITIES */ + &vlVdpDecoderCreate, /* VDP_FUNC_ID_DECODER_CREATE */ + &vlVdpDecoderDestroy, /* VDP_FUNC_ID_DECODER_DESTROY */ + &vlVdpDecoderGetParameters, /* VDP_FUNC_ID_DECODER_GET_PARAMETERS */ + &vlVdpDecoderRender, /* VDP_FUNC_ID_DECODER_RENDER */ + &vlVdpVideoMixerQueryFeatureSupport, /* VDP_FUNC_ID_VIDEO_MIXER_QUERY_FEATURE_SUPPORT */ + &vlVdpVideoMixerQueryParameterSupport, /* VDP_FUNC_ID_VIDEO_MIXER_QUERY_PARAMETER_SUPPORT */ + &vlVdpVideoMixerQueryAttributeSupport, /* VDP_FUNC_ID_VIDEO_MIXER_QUERY_ATTRIBUTE_SUPPORT */ + &vlVdpVideoMixerQueryParameterValueRange, /* VDP_FUNC_ID_VIDEO_MIXER_QUERY_PARAMETER_VALUE_RANGE */ + &vlVdpVideoMixerQueryAttributeValueRange, /* VDP_FUNC_ID_VIDEO_MIXER_QUERY_ATTRIBUTE_VALUE_RANGE */ + &vlVdpVideoMixerCreate, /* VDP_FUNC_ID_VIDEO_MIXER_CREATE */ + &vlVdpVideoMixerSetFeatureEnables, /* VDP_FUNC_ID_VIDEO_MIXER_SET_FEATURE_ENABLES */ + &vlVdpVideoMixerSetAttributeValues, /* VDP_FUNC_ID_VIDEO_MIXER_SET_ATTRIBUTE_VALUES */ + &vlVdpVideoMixerGetFeatureSupport, /* VDP_FUNC_ID_VIDEO_MIXER_GET_FEATURE_SUPPORT */ + &vlVdpVideoMixerGetFeatureEnables, /* VDP_FUNC_ID_VIDEO_MIXER_GET_FEATURE_ENABLES */ + &vlVdpVideoMixerGetParameterValues, /* VDP_FUNC_ID_VIDEO_MIXER_GET_PARAMETER_VALUES */ + &vlVdpVideoMixerGetAttributeValues, /* VDP_FUNC_ID_VIDEO_MIXER_GET_ATTRIBUTE_VALUES */ + &vlVdpVideoMixerDestroy, /* VDP_FUNC_ID_VIDEO_MIXER_DESTROY */ + &vlVdpVideoMixerRender, /* VDP_FUNC_ID_VIDEO_MIXER_RENDER */ + &vlVdpPresentationQueueTargetDestroy, /* VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_DESTROY */ + &vlVdpPresentationQueueCreate, /* VDP_FUNC_ID_PRESENTATION_QUEUE_CREATE */ + &vlVdpPresentationQueueDestroy, /* VDP_FUNC_ID_PRESENTATION_QUEUE_DESTROY */ + &vlVdpPresentationQueueSetBackgroundColor, /* VDP_FUNC_ID_PRESENTATION_QUEUE_SET_BACKGROUND_COLOR */ + &vlVdpPresentationQueueGetBackgroundColor, /* VDP_FUNC_ID_PRESENTATION_QUEUE_GET_BACKGROUND_COLOR */ + NULL, /* DUMMY */ + NULL, /* DUMMY */ + &vlVdpPresentationQueueGetTime, /* VDP_FUNC_ID_PRESENTATION_QUEUE_GET_TIME */ + &vlVdpPresentationQueueDisplay, /* VDP_FUNC_ID_PRESENTATION_QUEUE_DISPLAY */ + &vlVdpPresentationQueueBlockUntilSurfaceIdle, /* VDP_FUNC_ID_PRESENTATION_QUEUE_BLOCK_UNTIL_SURFACE_IDLE */ + &vlVdpPresentationQueueQuerySurfaceStatus, /* VDP_FUNC_ID_PRESENTATION_QUEUE_QUERY_SURFACE_STATUS */ + &vlVdpPreemptionCallbackRegister /* VDP_FUNC_ID_PREEMPTION_CALLBACK_REGISTER */ +}; + +static void* ftab_winsys[1] = +{ + &vlVdpPresentationQueueTargetCreateX11 /* VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_CREATE_X11 */ +}; + +static void* ftab_driver[4] = +{ + &vlVdpVideoSurfaceGallium, /* VDP_FUNC_ID_SURFACE_GALLIUM */ + &vlVdpOutputSurfaceGallium, /* VDP_FUNC_ID_OUTPUT_SURFACE_GALLIUM */ + &vlVdpVideoSurfaceDMABuf, /* VDP_FUNC_ID_VIDEO_SURFACE_DMA_BUF */ + &vlVdpOutputSurfaceDMABuf /* VDP_FUNC_ID_OUTPUT_SURFACE_DMA_BUF */ +}; + +boolean vlGetFuncFTAB(VdpFuncId function_id, void **func) +{ + assert(func); + *func = NULL; + + if (function_id < VDP_FUNC_ID_BASE_WINSYS) { + if (function_id < ARRAY_SIZE(ftab)) + *func = ftab[function_id]; + + } else if (function_id < VDP_FUNC_ID_BASE_DRIVER) { + function_id -= VDP_FUNC_ID_BASE_WINSYS; + if (function_id < ARRAY_SIZE(ftab_winsys)) + *func = ftab_winsys[function_id]; + + } else { + function_id -= VDP_FUNC_ID_BASE_DRIVER; + if (function_id < ARRAY_SIZE(ftab_driver)) + *func = ftab_driver[function_id]; + } + + return *func != NULL; +} diff --git a/src/gallium/frontends/vdpau/htab.c b/src/gallium/frontends/vdpau/htab.c new file mode 100644 index 00000000000..f596b2d571f --- /dev/null +++ b/src/gallium/frontends/vdpau/htab.c @@ -0,0 +1,89 @@ +/************************************************************************** + * + * Copyright 2010 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "util/u_handle_table.h" +#include "os/os_thread.h" +#include "vdpau_private.h" + +static struct handle_table *htab = NULL; +static mtx_t htab_lock = _MTX_INITIALIZER_NP; + +boolean vlCreateHTAB(void) +{ + boolean ret; + + /* Make sure handle table handles match VDPAU handles. */ + assert(sizeof(unsigned) <= sizeof(vlHandle)); + mtx_lock(&htab_lock); + if (!htab) + htab = handle_table_create(); + ret = htab != NULL; + mtx_unlock(&htab_lock); + return ret; +} + +void vlDestroyHTAB(void) +{ + mtx_lock(&htab_lock); + if (htab && !handle_table_get_first_handle(htab)) { + handle_table_destroy(htab); + htab = NULL; + } + mtx_unlock(&htab_lock); +} + +vlHandle vlAddDataHTAB(void *data) +{ + vlHandle handle = 0; + + assert(data); + mtx_lock(&htab_lock); + if (htab) + handle = handle_table_add(htab, data); + mtx_unlock(&htab_lock); + return handle; +} + +void* vlGetDataHTAB(vlHandle handle) +{ + void *data = NULL; + + assert(handle); + mtx_lock(&htab_lock); + if (htab) + data = handle_table_get(htab, handle); + mtx_unlock(&htab_lock); + return data; +} + +void vlRemoveDataHTAB(vlHandle handle) +{ + mtx_lock(&htab_lock); + if (htab) + handle_table_remove(htab, handle); + mtx_unlock(&htab_lock); +} diff --git a/src/gallium/frontends/vdpau/meson.build b/src/gallium/frontends/vdpau/meson.build new file mode 100644 index 00000000000..28c4e9cab76 --- /dev/null +++ b/src/gallium/frontends/vdpau/meson.build @@ -0,0 +1,39 @@ +# Copyright © 2017, 2019 Intel Corproration + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +VDPAU_MAJOR = 1 +VDPAU_MINOR = 0 + +libvdpau_st = static_library( + 'vdpau_st', + files( + 'bitmap.c', 'decode.c', 'device.c', 'ftab.c', 'htab.c', 'mixer.c', + 'output.c', 'preemption.c', 'presentation.c', 'query.c', 'surface.c', + ), + c_args : [ + c_vis_args, + '-DVER_MAJOR=@0@'.format(VDPAU_MAJOR), + '-DVER_MINOR=@0@'.format(VDPAU_MINOR), + ], + include_directories : [ + inc_include, inc_src, inc_util, inc_gallium, inc_gallium_aux, + ], + dependencies : [dep_vdpau, dep_xcb, dep_x11_xcb, dep_xcb_dri2, dep_libdrm], +) diff --git a/src/gallium/frontends/vdpau/mixer.c b/src/gallium/frontends/vdpau/mixer.c new file mode 100644 index 00000000000..2e2bd20ef39 --- /dev/null +++ b/src/gallium/frontends/vdpau/mixer.c @@ -0,0 +1,1028 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include + +#include "util/u_memory.h" +#include "util/u_debug.h" + +#include "vl/vl_csc.h" + +#include "vdpau_private.h" + +/** + * Create a VdpVideoMixer. + */ +VdpStatus +vlVdpVideoMixerCreate(VdpDevice device, + uint32_t feature_count, + VdpVideoMixerFeature const *features, + uint32_t parameter_count, + VdpVideoMixerParameter const *parameters, + void const *const *parameter_values, + VdpVideoMixer *mixer) +{ + vlVdpVideoMixer *vmixer = NULL; + VdpStatus ret; + struct pipe_screen *screen; + unsigned max_size, i; + + vlVdpDevice *dev = vlGetDataHTAB(device); + if (!dev) + return VDP_STATUS_INVALID_HANDLE; + screen = dev->vscreen->pscreen; + + vmixer = CALLOC(1, sizeof(vlVdpVideoMixer)); + if (!vmixer) + return VDP_STATUS_RESOURCES; + + DeviceReference(&vmixer->device, dev); + + mtx_lock(&dev->mutex); + + if (!vl_compositor_init_state(&vmixer->cstate, dev->context)) { + ret = VDP_STATUS_ERROR; + goto no_compositor_state; + } + + vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601, NULL, true, &vmixer->csc); + if (!debug_get_bool_option("G3DVL_NO_CSC", FALSE)) { + if (!vl_compositor_set_csc_matrix(&vmixer->cstate, (const vl_csc_matrix *)&vmixer->csc, 1.0f, 0.0f)) { + ret = VDP_STATUS_ERROR; + goto err_csc_matrix; + } + } + + *mixer = vlAddDataHTAB(vmixer); + if (*mixer == 0) { + ret = VDP_STATUS_ERROR; + goto no_handle; + } + + ret = VDP_STATUS_INVALID_VIDEO_MIXER_FEATURE; + for (i = 0; i < feature_count; ++i) { + switch (features[i]) { + /* they are valid, but we doesn't support them */ + case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL: + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2: + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3: + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4: + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L5: + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L6: + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L7: + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L8: + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L9: + case VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE: + break; + + case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL: + vmixer->deint.supported = true; + break; + + case VDP_VIDEO_MIXER_FEATURE_SHARPNESS: + vmixer->sharpness.supported = true; + break; + + case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION: + vmixer->noise_reduction.supported = true; + break; + + case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY: + vmixer->luma_key.supported = true; + break; + + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1: + vmixer->bicubic.supported = true; + break; + default: goto no_params; + } + } + + vmixer->chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; + ret = VDP_STATUS_INVALID_VIDEO_MIXER_PARAMETER; + for (i = 0; i < parameter_count; ++i) { + switch (parameters[i]) { + case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH: + vmixer->video_width = *(uint32_t*)parameter_values[i]; + break; + case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT: + vmixer->video_height = *(uint32_t*)parameter_values[i]; + break; + case VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE: + vmixer->chroma_format = ChromaToPipe(*(VdpChromaType*)parameter_values[i]); + break; + case VDP_VIDEO_MIXER_PARAMETER_LAYERS: + vmixer->max_layers = *(uint32_t*)parameter_values[i]; + break; + default: goto no_params; + } + } + ret = VDP_STATUS_INVALID_VALUE; + if (vmixer->max_layers > 4) { + VDPAU_MSG(VDPAU_WARN, "[VDPAU] Max layers > 4 not supported\n", vmixer->max_layers); + goto no_params; + } + + max_size = screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_2D_SIZE); + if (vmixer->video_width < 48 || vmixer->video_width > max_size) { + VDPAU_MSG(VDPAU_WARN, "[VDPAU] 48 < %u < %u not valid for width\n", + vmixer->video_width, max_size); + goto no_params; + } + if (vmixer->video_height < 48 || vmixer->video_height > max_size) { + VDPAU_MSG(VDPAU_WARN, "[VDPAU] 48 < %u < %u not valid for height\n", + vmixer->video_height, max_size); + goto no_params; + } + vmixer->luma_key.luma_min = 1.0f; + vmixer->luma_key.luma_max = 0.0f; + mtx_unlock(&dev->mutex); + + return VDP_STATUS_OK; + +no_params: + vlRemoveDataHTAB(*mixer); + +no_handle: +err_csc_matrix: + vl_compositor_cleanup_state(&vmixer->cstate); +no_compositor_state: + mtx_unlock(&dev->mutex); + DeviceReference(&vmixer->device, NULL); + FREE(vmixer); + return ret; +} + +/** + * Destroy a VdpVideoMixer. + */ +VdpStatus +vlVdpVideoMixerDestroy(VdpVideoMixer mixer) +{ + vlVdpVideoMixer *vmixer; + + vmixer = vlGetDataHTAB(mixer); + if (!vmixer) + return VDP_STATUS_INVALID_HANDLE; + + mtx_lock(&vmixer->device->mutex); + + vlRemoveDataHTAB(mixer); + + vl_compositor_cleanup_state(&vmixer->cstate); + + if (vmixer->deint.filter) { + vl_deint_filter_cleanup(vmixer->deint.filter); + FREE(vmixer->deint.filter); + } + + if (vmixer->noise_reduction.filter) { + vl_median_filter_cleanup(vmixer->noise_reduction.filter); + FREE(vmixer->noise_reduction.filter); + } + + if (vmixer->sharpness.filter) { + vl_matrix_filter_cleanup(vmixer->sharpness.filter); + FREE(vmixer->sharpness.filter); + } + + if (vmixer->bicubic.filter) { + vl_bicubic_filter_cleanup(vmixer->bicubic.filter); + FREE(vmixer->bicubic.filter); + } + mtx_unlock(&vmixer->device->mutex); + DeviceReference(&vmixer->device, NULL); + + FREE(vmixer); + + return VDP_STATUS_OK; +} + +/** + * Perform a video post-processing and compositing operation. + */ +VdpStatus vlVdpVideoMixerRender(VdpVideoMixer mixer, + VdpOutputSurface background_surface, + VdpRect const *background_source_rect, + VdpVideoMixerPictureStructure current_picture_structure, + uint32_t video_surface_past_count, + VdpVideoSurface const *video_surface_past, + VdpVideoSurface video_surface_current, + uint32_t video_surface_future_count, + VdpVideoSurface const *video_surface_future, + VdpRect const *video_source_rect, + VdpOutputSurface destination_surface, + VdpRect const *destination_rect, + VdpRect const *destination_video_rect, + uint32_t layer_count, + VdpLayer const *layers) +{ + enum vl_compositor_deinterlace deinterlace; + struct u_rect rect, clip, *prect, dirty_area; + unsigned i, layer = 0; + struct pipe_video_buffer *video_buffer; + struct pipe_sampler_view *sampler_view, sv_templ; + struct pipe_surface *surface, surf_templ; + struct pipe_context *pipe = NULL; + struct pipe_resource res_tmpl, *res; + + vlVdpVideoMixer *vmixer; + vlVdpSurface *surf; + vlVdpOutputSurface *dst, *bg = NULL; + + struct vl_compositor *compositor; + + vmixer = vlGetDataHTAB(mixer); + if (!vmixer) + return VDP_STATUS_INVALID_HANDLE; + + compositor = &vmixer->device->compositor; + + surf = vlGetDataHTAB(video_surface_current); + if (!surf) + return VDP_STATUS_INVALID_HANDLE; + video_buffer = surf->video_buffer; + + if (surf->device != vmixer->device) + return VDP_STATUS_HANDLE_DEVICE_MISMATCH; + + if (vmixer->video_width > video_buffer->width || + vmixer->video_height > video_buffer->height || + vmixer->chroma_format != pipe_format_to_chroma_format(video_buffer->buffer_format)) + return VDP_STATUS_INVALID_SIZE; + + if (layer_count > vmixer->max_layers) + return VDP_STATUS_INVALID_VALUE; + + dst = vlGetDataHTAB(destination_surface); + if (!dst) + return VDP_STATUS_INVALID_HANDLE; + + if (background_surface != VDP_INVALID_HANDLE) { + bg = vlGetDataHTAB(background_surface); + if (!bg) + return VDP_STATUS_INVALID_HANDLE; + } + + mtx_lock(&vmixer->device->mutex); + + vl_compositor_clear_layers(&vmixer->cstate); + + if (bg) + vl_compositor_set_rgba_layer(&vmixer->cstate, compositor, layer++, bg->sampler_view, + RectToPipe(background_source_rect, &rect), NULL, NULL); + + switch (current_picture_structure) { + case VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD: + deinterlace = VL_COMPOSITOR_BOB_TOP; + break; + + case VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD: + deinterlace = VL_COMPOSITOR_BOB_BOTTOM; + break; + + case VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME: + deinterlace = VL_COMPOSITOR_WEAVE; + break; + + default: + mtx_unlock(&vmixer->device->mutex); + return VDP_STATUS_INVALID_VIDEO_MIXER_PICTURE_STRUCTURE; + } + + if (deinterlace != VL_COMPOSITOR_WEAVE && vmixer->deint.enabled && + video_surface_past_count > 1 && video_surface_future_count > 0) { + vlVdpSurface *prevprev = vlGetDataHTAB(video_surface_past[1]); + vlVdpSurface *prev = vlGetDataHTAB(video_surface_past[0]); + vlVdpSurface *next = vlGetDataHTAB(video_surface_future[0]); + if (prevprev && prev && next && + vl_deint_filter_check_buffers(vmixer->deint.filter, + prevprev->video_buffer, prev->video_buffer, surf->video_buffer, next->video_buffer)) { + vl_deint_filter_render(vmixer->deint.filter, prevprev->video_buffer, + prev->video_buffer, surf->video_buffer, + next->video_buffer, + deinterlace == VL_COMPOSITOR_BOB_BOTTOM); + deinterlace = VL_COMPOSITOR_WEAVE; + video_buffer = vmixer->deint.filter->video_buffer; + } + } + + prect = RectToPipe(video_source_rect, &rect); + if (!prect) { + rect.x0 = 0; + rect.y0 = 0; + rect.x1 = surf->templat.width; + rect.y1 = surf->templat.height; + prect = ▭ + } + vl_compositor_set_buffer_layer(&vmixer->cstate, compositor, layer, video_buffer, prect, NULL, deinterlace); + + if (vmixer->bicubic.filter || vmixer->sharpness.filter || vmixer->noise_reduction.filter) { + pipe = vmixer->device->context; + memset(&res_tmpl, 0, sizeof(res_tmpl)); + + res_tmpl.target = PIPE_TEXTURE_2D; + res_tmpl.format = dst->sampler_view->format; + res_tmpl.depth0 = 1; + res_tmpl.array_size = 1; + res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; + res_tmpl.usage = PIPE_USAGE_DEFAULT; + + if (!vmixer->bicubic.filter) { + res_tmpl.width0 = dst->surface->width; + res_tmpl.height0 = dst->surface->height; + } else { + res_tmpl.width0 = surf->templat.width; + res_tmpl.height0 = surf->templat.height; + } + + res = pipe->screen->resource_create(pipe->screen, &res_tmpl); + + vlVdpDefaultSamplerViewTemplate(&sv_templ, res); + sampler_view = pipe->create_sampler_view(pipe, res, &sv_templ); + + memset(&surf_templ, 0, sizeof(surf_templ)); + surf_templ.format = res->format; + surface = pipe->create_surface(pipe, res, &surf_templ); + + vl_compositor_reset_dirty_area(&dirty_area); + pipe_resource_reference(&res, NULL); + } else { + surface = dst->surface; + sampler_view = dst->sampler_view; + dirty_area = dst->dirty_area; + } + + if (!vmixer->bicubic.filter) { + vl_compositor_set_layer_dst_area(&vmixer->cstate, layer++, RectToPipe(destination_video_rect, &rect)); + vl_compositor_set_dst_clip(&vmixer->cstate, RectToPipe(destination_rect, &clip)); + } + + for (i = 0; i < layer_count; ++i) { + vlVdpOutputSurface *src = vlGetDataHTAB(layers->source_surface); + if (!src) { + mtx_unlock(&vmixer->device->mutex); + return VDP_STATUS_INVALID_HANDLE; + } + + assert(layers->struct_version == VDP_LAYER_VERSION); + + vl_compositor_set_rgba_layer(&vmixer->cstate, compositor, layer, src->sampler_view, + RectToPipe(layers->source_rect, &rect), NULL, NULL); + vl_compositor_set_layer_dst_area(&vmixer->cstate, layer++, RectToPipe(layers->destination_rect, &rect)); + + ++layers; + } + + vl_compositor_render(&vmixer->cstate, compositor, surface, &dirty_area, true); + + if (vmixer->noise_reduction.filter) { + if (!vmixer->sharpness.filter && !vmixer->bicubic.filter) { + vl_median_filter_render(vmixer->noise_reduction.filter, + sampler_view, dst->surface); + } else { + res = pipe->screen->resource_create(pipe->screen, &res_tmpl); + struct pipe_sampler_view *sampler_view_temp = pipe->create_sampler_view(pipe, res, &sv_templ); + struct pipe_surface *surface_temp = pipe->create_surface(pipe, res, &surf_templ); + pipe_resource_reference(&res, NULL); + + vl_median_filter_render(vmixer->noise_reduction.filter, + sampler_view, surface_temp); + + pipe_sampler_view_reference(&sampler_view, NULL); + pipe_surface_reference(&surface, NULL); + + sampler_view = sampler_view_temp; + surface = surface_temp; + } + } + + if (vmixer->sharpness.filter) { + if (!vmixer->bicubic.filter) { + vl_matrix_filter_render(vmixer->sharpness.filter, + sampler_view, dst->surface); + } else { + res = pipe->screen->resource_create(pipe->screen, &res_tmpl); + struct pipe_sampler_view *sampler_view_temp = pipe->create_sampler_view(pipe, res, &sv_templ); + struct pipe_surface *surface_temp = pipe->create_surface(pipe, res, &surf_templ); + pipe_resource_reference(&res, NULL); + + vl_matrix_filter_render(vmixer->sharpness.filter, + sampler_view, surface_temp); + + pipe_sampler_view_reference(&sampler_view, NULL); + pipe_surface_reference(&surface, NULL); + + sampler_view = sampler_view_temp; + surface = surface_temp; + } + } + + if (vmixer->bicubic.filter) + vl_bicubic_filter_render(vmixer->bicubic.filter, + sampler_view, dst->surface, + RectToPipe(destination_video_rect, &rect), + RectToPipe(destination_rect, &clip)); + + if(surface != dst->surface) { + pipe_sampler_view_reference(&sampler_view, NULL); + pipe_surface_reference(&surface, NULL); + } + mtx_unlock(&vmixer->device->mutex); + + return VDP_STATUS_OK; +} + +static void +vlVdpVideoMixerUpdateDeinterlaceFilter(vlVdpVideoMixer *vmixer) +{ + struct pipe_context *pipe = vmixer->device->context; + assert(vmixer); + + /* remove existing filter */ + if (vmixer->deint.filter) { + vl_deint_filter_cleanup(vmixer->deint.filter); + FREE(vmixer->deint.filter); + vmixer->deint.filter = NULL; + } + + /* create a new filter if requested */ + if (vmixer->deint.enabled && vmixer->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420) { + vmixer->deint.filter = MALLOC(sizeof(struct vl_deint_filter)); + vmixer->deint.enabled = vl_deint_filter_init(vmixer->deint.filter, pipe, + vmixer->video_width, vmixer->video_height, + vmixer->skip_chroma_deint, vmixer->deint.spatial); + if (!vmixer->deint.enabled) { + FREE(vmixer->deint.filter); + } + } +} + +/** + * Update the noise reduction setting + */ +static void +vlVdpVideoMixerUpdateNoiseReductionFilter(vlVdpVideoMixer *vmixer) +{ + assert(vmixer); + + /* if present remove the old filter first */ + if (vmixer->noise_reduction.filter) { + vl_median_filter_cleanup(vmixer->noise_reduction.filter); + FREE(vmixer->noise_reduction.filter); + vmixer->noise_reduction.filter = NULL; + } + + /* and create a new filter as needed */ + if (vmixer->noise_reduction. enabled && vmixer->noise_reduction.level > 0) { + vmixer->noise_reduction.filter = MALLOC(sizeof(struct vl_median_filter)); + vl_median_filter_init(vmixer->noise_reduction.filter, vmixer->device->context, + vmixer->video_width, vmixer->video_height, + vmixer->noise_reduction.level + 1, + VL_MEDIAN_FILTER_CROSS); + } +} + +static void +vlVdpVideoMixerUpdateSharpnessFilter(vlVdpVideoMixer *vmixer) +{ + assert(vmixer); + + /* if present remove the old filter first */ + if (vmixer->sharpness.filter) { + vl_matrix_filter_cleanup(vmixer->sharpness.filter); + FREE(vmixer->sharpness.filter); + vmixer->sharpness.filter = NULL; + } + + /* and create a new filter as needed */ + if (vmixer->sharpness.enabled && vmixer->sharpness.value != 0.0f) { + float matrix[9]; + unsigned i; + + if (vmixer->sharpness.value > 0.0f) { + matrix[0] = -1.0f; matrix[1] = -1.0f; matrix[2] = -1.0f; + matrix[3] = -1.0f; matrix[4] = 8.0f; matrix[5] = -1.0f; + matrix[6] = -1.0f; matrix[7] = -1.0f; matrix[8] = -1.0f; + + for (i = 0; i < 9; ++i) + matrix[i] *= vmixer->sharpness.value; + + matrix[4] += 1.0f; + + } else { + matrix[0] = 1.0f; matrix[1] = 2.0f; matrix[2] = 1.0f; + matrix[3] = 2.0f; matrix[4] = 4.0f; matrix[5] = 2.0f; + matrix[6] = 1.0f; matrix[7] = 2.0f; matrix[8] = 1.0f; + + for (i = 0; i < 9; ++i) + matrix[i] *= fabsf(vmixer->sharpness.value) / 16.0f; + + matrix[4] += 1.0f - fabsf(vmixer->sharpness.value); + } + + vmixer->sharpness.filter = MALLOC(sizeof(struct vl_matrix_filter)); + vl_matrix_filter_init(vmixer->sharpness.filter, vmixer->device->context, + vmixer->video_width, vmixer->video_height, + 3, 3, matrix); + } +} + +/** + * Update the bicubic filter + */ +static void +vlVdpVideoMixerUpdateBicubicFilter(vlVdpVideoMixer *vmixer) +{ + assert(vmixer); + + /* if present remove the old filter first */ + if (vmixer->bicubic.filter) { + vl_bicubic_filter_cleanup(vmixer->bicubic.filter); + FREE(vmixer->bicubic.filter); + vmixer->bicubic.filter = NULL; + } + /* and create a new filter as needed */ + if (vmixer->bicubic.enabled) { + vmixer->bicubic.filter = MALLOC(sizeof(struct vl_bicubic_filter)); + vl_bicubic_filter_init(vmixer->bicubic.filter, vmixer->device->context, + vmixer->video_width, vmixer->video_height); + } +} + +/** + * Retrieve whether features were requested at creation time. + */ +VdpStatus +vlVdpVideoMixerGetFeatureSupport(VdpVideoMixer mixer, + uint32_t feature_count, + VdpVideoMixerFeature const *features, + VdpBool *feature_supports) +{ + vlVdpVideoMixer *vmixer; + unsigned i; + + if (!(features && feature_supports)) + return VDP_STATUS_INVALID_POINTER; + + vmixer = vlGetDataHTAB(mixer); + if (!vmixer) + return VDP_STATUS_INVALID_HANDLE; + + for (i = 0; i < feature_count; ++i) { + switch (features[i]) { + /* they are valid, but we doesn't support them */ + case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL: + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2: + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3: + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4: + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L5: + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L6: + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L7: + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L8: + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L9: + case VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE: + feature_supports[i] = false; + break; + + case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL: + feature_supports[i] = vmixer->deint.supported; + break; + + case VDP_VIDEO_MIXER_FEATURE_SHARPNESS: + feature_supports[i] = vmixer->sharpness.supported; + break; + + case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION: + feature_supports[i] = vmixer->noise_reduction.supported; + break; + + case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY: + feature_supports[i] = vmixer->luma_key.supported; + break; + + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1: + feature_supports[i] = vmixer->bicubic.supported; + break; + + default: + return VDP_STATUS_INVALID_VIDEO_MIXER_FEATURE; + } + } + + return VDP_STATUS_OK; +} + +/** + * Enable or disable features. + */ +VdpStatus +vlVdpVideoMixerSetFeatureEnables(VdpVideoMixer mixer, + uint32_t feature_count, + VdpVideoMixerFeature const *features, + VdpBool const *feature_enables) +{ + vlVdpVideoMixer *vmixer; + unsigned i; + + if (!(features && feature_enables)) + return VDP_STATUS_INVALID_POINTER; + + vmixer = vlGetDataHTAB(mixer); + if (!vmixer) + return VDP_STATUS_INVALID_HANDLE; + + mtx_lock(&vmixer->device->mutex); + for (i = 0; i < feature_count; ++i) { + switch (features[i]) { + /* they are valid, but we doesn't support them */ + case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL: + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2: + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3: + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4: + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L5: + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L6: + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L7: + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L8: + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L9: + case VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE: + break; + + case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL: + vmixer->deint.enabled = feature_enables[i]; + vlVdpVideoMixerUpdateDeinterlaceFilter(vmixer); + break; + + case VDP_VIDEO_MIXER_FEATURE_SHARPNESS: + vmixer->sharpness.enabled = feature_enables[i]; + vlVdpVideoMixerUpdateSharpnessFilter(vmixer); + break; + + case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION: + vmixer->noise_reduction.enabled = feature_enables[i]; + vlVdpVideoMixerUpdateNoiseReductionFilter(vmixer); + break; + + case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY: + vmixer->luma_key.enabled = feature_enables[i]; + if (!debug_get_bool_option("G3DVL_NO_CSC", FALSE)) + if (!vl_compositor_set_csc_matrix(&vmixer->cstate, (const vl_csc_matrix *)&vmixer->csc, + vmixer->luma_key.luma_min, vmixer->luma_key.luma_max)) { + mtx_unlock(&vmixer->device->mutex); + return VDP_STATUS_ERROR; + } + break; + + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1: + vmixer->bicubic.enabled = feature_enables[i]; + vlVdpVideoMixerUpdateBicubicFilter(vmixer); + break; + + default: + mtx_unlock(&vmixer->device->mutex); + return VDP_STATUS_INVALID_VIDEO_MIXER_FEATURE; + } + } + mtx_unlock(&vmixer->device->mutex); + + return VDP_STATUS_OK; +} + +/** + * Retrieve whether features are enabled. + */ +VdpStatus +vlVdpVideoMixerGetFeatureEnables(VdpVideoMixer mixer, + uint32_t feature_count, + VdpVideoMixerFeature const *features, + VdpBool *feature_enables) +{ + vlVdpVideoMixer *vmixer; + unsigned i; + + if (!(features && feature_enables)) + return VDP_STATUS_INVALID_POINTER; + + vmixer = vlGetDataHTAB(mixer); + if (!vmixer) + return VDP_STATUS_INVALID_HANDLE; + + for (i = 0; i < feature_count; ++i) { + switch (features[i]) { + /* they are valid, but we doesn't support them */ + case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL: + case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL: + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2: + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3: + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4: + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L5: + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L6: + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L7: + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L8: + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L9: + case VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE: + break; + + case VDP_VIDEO_MIXER_FEATURE_SHARPNESS: + feature_enables[i] = vmixer->sharpness.enabled; + break; + + case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION: + feature_enables[i] = vmixer->noise_reduction.enabled; + break; + + case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY: + feature_enables[i] = vmixer->luma_key.enabled; + break; + + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1: + feature_enables[i] = vmixer->bicubic.enabled; + break; + + default: + return VDP_STATUS_INVALID_VIDEO_MIXER_FEATURE; + } + } + + return VDP_STATUS_OK; +} + +/** + * Set attribute values. + */ +VdpStatus +vlVdpVideoMixerSetAttributeValues(VdpVideoMixer mixer, + uint32_t attribute_count, + VdpVideoMixerAttribute const *attributes, + void const *const *attribute_values) +{ + const VdpColor *background_color; + union pipe_color_union color; + const float *vdp_csc; + float val; + unsigned i; + VdpStatus ret; + + if (!(attributes && attribute_values)) + return VDP_STATUS_INVALID_POINTER; + + vlVdpVideoMixer *vmixer = vlGetDataHTAB(mixer); + if (!vmixer) + return VDP_STATUS_INVALID_HANDLE; + + mtx_lock(&vmixer->device->mutex); + for (i = 0; i < attribute_count; ++i) { + switch (attributes[i]) { + case VDP_VIDEO_MIXER_ATTRIBUTE_BACKGROUND_COLOR: + background_color = attribute_values[i]; + color.f[0] = background_color->red; + color.f[1] = background_color->green; + color.f[2] = background_color->blue; + color.f[3] = background_color->alpha; + vl_compositor_set_clear_color(&vmixer->cstate, &color); + break; + case VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX: + vdp_csc = attribute_values[i]; + vmixer->custom_csc = !!vdp_csc; + if (!vdp_csc) + vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601, NULL, 1, &vmixer->csc); + else + memcpy(vmixer->csc, vdp_csc, sizeof(vl_csc_matrix)); + if (!debug_get_bool_option("G3DVL_NO_CSC", FALSE)) + if (!vl_compositor_set_csc_matrix(&vmixer->cstate, (const vl_csc_matrix *)&vmixer->csc, + vmixer->luma_key.luma_min, vmixer->luma_key.luma_max)) { + ret = VDP_STATUS_ERROR; + goto fail; + } + break; + + case VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL: + + val = *(float*)attribute_values[i]; + if (val < 0.0f || val > 1.0f) { + ret = VDP_STATUS_INVALID_VALUE; + goto fail; + } + + vmixer->noise_reduction.level = val * 10; + vlVdpVideoMixerUpdateNoiseReductionFilter(vmixer); + break; + + case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MIN_LUMA: + val = *(float*)attribute_values[i]; + if (val < 0.0f || val > 1.0f) { + ret = VDP_STATUS_INVALID_VALUE; + goto fail; + } + vmixer->luma_key.luma_min = val; + if (!debug_get_bool_option("G3DVL_NO_CSC", FALSE)) + if (!vl_compositor_set_csc_matrix(&vmixer->cstate, (const vl_csc_matrix *)&vmixer->csc, + vmixer->luma_key.luma_min, vmixer->luma_key.luma_max)) { + ret = VDP_STATUS_ERROR; + goto fail; + } + break; + + case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MAX_LUMA: + val = *(float*)attribute_values[i]; + if (val < 0.0f || val > 1.0f) { + ret = VDP_STATUS_INVALID_VALUE; + goto fail; + } + vmixer->luma_key.luma_max = val; + if (!debug_get_bool_option("G3DVL_NO_CSC", FALSE)) + if (!vl_compositor_set_csc_matrix(&vmixer->cstate, (const vl_csc_matrix *)&vmixer->csc, + vmixer->luma_key.luma_min, vmixer->luma_key.luma_max)) { + ret = VDP_STATUS_ERROR; + goto fail; + } + break; + + case VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL: + + val = *(float*)attribute_values[i]; + if (val < -1.0f || val > 1.0f) { + ret = VDP_STATUS_INVALID_VALUE; + goto fail; + } + + vmixer->sharpness.value = val; + vlVdpVideoMixerUpdateSharpnessFilter(vmixer); + break; + + case VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE: + if (*(uint8_t*)attribute_values[i] > 1) { + ret = VDP_STATUS_INVALID_VALUE; + goto fail; + } + vmixer->skip_chroma_deint = *(uint8_t*)attribute_values[i]; + vlVdpVideoMixerUpdateDeinterlaceFilter(vmixer); + break; + default: + ret = VDP_STATUS_INVALID_VIDEO_MIXER_ATTRIBUTE; + goto fail; + } + } + mtx_unlock(&vmixer->device->mutex); + + return VDP_STATUS_OK; +fail: + mtx_unlock(&vmixer->device->mutex); + return ret; +} + +/** + * Retrieve parameter values given at creation time. + */ +VdpStatus +vlVdpVideoMixerGetParameterValues(VdpVideoMixer mixer, + uint32_t parameter_count, + VdpVideoMixerParameter const *parameters, + void *const *parameter_values) +{ + vlVdpVideoMixer *vmixer = vlGetDataHTAB(mixer); + unsigned i; + if (!vmixer) + return VDP_STATUS_INVALID_HANDLE; + + if (!parameter_count) + return VDP_STATUS_OK; + if (!(parameters && parameter_values)) + return VDP_STATUS_INVALID_POINTER; + for (i = 0; i < parameter_count; ++i) { + switch (parameters[i]) { + case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH: + *(uint32_t*)parameter_values[i] = vmixer->video_width; + break; + case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT: + *(uint32_t*)parameter_values[i] = vmixer->video_height; + break; + case VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE: + *(VdpChromaType*)parameter_values[i] = PipeToChroma(vmixer->chroma_format); + break; + case VDP_VIDEO_MIXER_PARAMETER_LAYERS: + *(uint32_t*)parameter_values[i] = vmixer->max_layers; + break; + default: + return VDP_STATUS_INVALID_VIDEO_MIXER_PARAMETER; + } + } + return VDP_STATUS_OK; +} + +/** + * Retrieve current attribute values. + */ +VdpStatus +vlVdpVideoMixerGetAttributeValues(VdpVideoMixer mixer, + uint32_t attribute_count, + VdpVideoMixerAttribute const *attributes, + void *const *attribute_values) +{ + unsigned i; + VdpCSCMatrix **vdp_csc; + + if (!(attributes && attribute_values)) + return VDP_STATUS_INVALID_POINTER; + + vlVdpVideoMixer *vmixer = vlGetDataHTAB(mixer); + if (!vmixer) + return VDP_STATUS_INVALID_HANDLE; + + mtx_lock(&vmixer->device->mutex); + for (i = 0; i < attribute_count; ++i) { + switch (attributes[i]) { + case VDP_VIDEO_MIXER_ATTRIBUTE_BACKGROUND_COLOR: + vl_compositor_get_clear_color(&vmixer->cstate, attribute_values[i]); + break; + case VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX: + vdp_csc = attribute_values[i]; + if (!vmixer->custom_csc) { + *vdp_csc = NULL; + break; + } + memcpy(*vdp_csc, vmixer->csc, sizeof(float)*12); + break; + + case VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL: + *(float*)attribute_values[i] = (float)vmixer->noise_reduction.level / 10.0f; + break; + + case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MIN_LUMA: + *(float*)attribute_values[i] = vmixer->luma_key.luma_min; + break; + case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MAX_LUMA: + *(float*)attribute_values[i] = vmixer->luma_key.luma_max; + break; + case VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL: + *(float*)attribute_values[i] = vmixer->sharpness.value; + break; + case VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE: + *(uint8_t*)attribute_values[i] = vmixer->skip_chroma_deint; + break; + default: + mtx_unlock(&vmixer->device->mutex); + return VDP_STATUS_INVALID_VIDEO_MIXER_ATTRIBUTE; + } + } + mtx_unlock(&vmixer->device->mutex); + return VDP_STATUS_OK; +} + +/** + * Generate a color space conversion matrix. + */ +VdpStatus +vlVdpGenerateCSCMatrix(VdpProcamp *procamp, + VdpColorStandard standard, + VdpCSCMatrix *csc_matrix) +{ + enum VL_CSC_COLOR_STANDARD vl_std; + struct vl_procamp camp; + + if (!csc_matrix) + return VDP_STATUS_INVALID_POINTER; + + switch (standard) { + case VDP_COLOR_STANDARD_ITUR_BT_601: vl_std = VL_CSC_COLOR_STANDARD_BT_601; break; + case VDP_COLOR_STANDARD_ITUR_BT_709: vl_std = VL_CSC_COLOR_STANDARD_BT_709; break; + case VDP_COLOR_STANDARD_SMPTE_240M: vl_std = VL_CSC_COLOR_STANDARD_SMPTE_240M; break; + default: return VDP_STATUS_INVALID_COLOR_STANDARD; + } + + if (procamp) { + if (procamp->struct_version > VDP_PROCAMP_VERSION) + return VDP_STATUS_INVALID_STRUCT_VERSION; + camp.brightness = procamp->brightness; + camp.contrast = procamp->contrast; + camp.saturation = procamp->saturation; + camp.hue = procamp->hue; + } + + vl_csc_get_matrix(vl_std, procamp ? &camp : NULL, true, csc_matrix); + return VDP_STATUS_OK; +} diff --git a/src/gallium/frontends/vdpau/output.c b/src/gallium/frontends/vdpau/output.c new file mode 100644 index 00000000000..75a9f016e90 --- /dev/null +++ b/src/gallium/frontends/vdpau/output.c @@ -0,0 +1,828 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen. + * Copyright 2011 Christian König. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include + +#include "util/u_debug.h" +#include "util/u_memory.h" +#include "util/u_sampler.h" +#include "util/format/u_format.h" +#include "util/u_surface.h" + +#include "vl/vl_csc.h" + +#include "frontend/drm_driver.h" + +#include "vdpau_private.h" + +/** + * Create a VdpOutputSurface. + */ +VdpStatus +vlVdpOutputSurfaceCreate(VdpDevice device, + VdpRGBAFormat rgba_format, + uint32_t width, uint32_t height, + VdpOutputSurface *surface) +{ + struct pipe_context *pipe; + struct pipe_resource res_tmpl, *res; + struct pipe_sampler_view sv_templ; + struct pipe_surface surf_templ; + + vlVdpOutputSurface *vlsurface = NULL; + + if (!(width && height)) + return VDP_STATUS_INVALID_SIZE; + + vlVdpDevice *dev = vlGetDataHTAB(device); + if (!dev) + return VDP_STATUS_INVALID_HANDLE; + + pipe = dev->context; + if (!pipe) + return VDP_STATUS_INVALID_HANDLE; + + vlsurface = CALLOC(1, sizeof(vlVdpOutputSurface)); + if (!vlsurface) + return VDP_STATUS_RESOURCES; + + DeviceReference(&vlsurface->device, dev); + + memset(&res_tmpl, 0, sizeof(res_tmpl)); + + /* + * The output won't look correctly when this buffer is send to X, + * if the VDPAU RGB component order doesn't match the X11 one so + * we only allow the X11 format + */ + vlsurface->send_to_X = dev->vscreen->color_depth == 24 && + rgba_format == VDP_RGBA_FORMAT_B8G8R8A8; + + res_tmpl.target = PIPE_TEXTURE_2D; + res_tmpl.format = VdpFormatRGBAToPipe(rgba_format); + res_tmpl.width0 = width; + res_tmpl.height0 = height; + res_tmpl.depth0 = 1; + res_tmpl.array_size = 1; + res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET | + PIPE_BIND_SHARED | PIPE_BIND_SCANOUT; + res_tmpl.usage = PIPE_USAGE_DEFAULT; + + mtx_lock(&dev->mutex); + + if (!CheckSurfaceParams(pipe->screen, &res_tmpl)) + goto err_unlock; + + res = pipe->screen->resource_create(pipe->screen, &res_tmpl); + if (!res) + goto err_unlock; + + vlVdpDefaultSamplerViewTemplate(&sv_templ, res); + vlsurface->sampler_view = pipe->create_sampler_view(pipe, res, &sv_templ); + if (!vlsurface->sampler_view) + goto err_resource; + + memset(&surf_templ, 0, sizeof(surf_templ)); + surf_templ.format = res->format; + vlsurface->surface = pipe->create_surface(pipe, res, &surf_templ); + if (!vlsurface->surface) + goto err_resource; + + *surface = vlAddDataHTAB(vlsurface); + if (*surface == 0) + goto err_resource; + + pipe_resource_reference(&res, NULL); + + if (!vl_compositor_init_state(&vlsurface->cstate, pipe)) + goto err_resource; + + vl_compositor_reset_dirty_area(&vlsurface->dirty_area); + mtx_unlock(&dev->mutex); + + return VDP_STATUS_OK; + +err_resource: + pipe_sampler_view_reference(&vlsurface->sampler_view, NULL); + pipe_surface_reference(&vlsurface->surface, NULL); + pipe_resource_reference(&res, NULL); +err_unlock: + mtx_unlock(&dev->mutex); + DeviceReference(&vlsurface->device, NULL); + FREE(vlsurface); + return VDP_STATUS_ERROR; +} + +/** + * Destroy a VdpOutputSurface. + */ +VdpStatus +vlVdpOutputSurfaceDestroy(VdpOutputSurface surface) +{ + vlVdpOutputSurface *vlsurface; + struct pipe_context *pipe; + + vlsurface = vlGetDataHTAB(surface); + if (!vlsurface) + return VDP_STATUS_INVALID_HANDLE; + + pipe = vlsurface->device->context; + + mtx_lock(&vlsurface->device->mutex); + + pipe_surface_reference(&vlsurface->surface, NULL); + pipe_sampler_view_reference(&vlsurface->sampler_view, NULL); + pipe->screen->fence_reference(pipe->screen, &vlsurface->fence, NULL); + vl_compositor_cleanup_state(&vlsurface->cstate); + mtx_unlock(&vlsurface->device->mutex); + + vlRemoveDataHTAB(surface); + DeviceReference(&vlsurface->device, NULL); + FREE(vlsurface); + + return VDP_STATUS_OK; +} + +/** + * Retrieve the parameters used to create a VdpOutputSurface. + */ +VdpStatus +vlVdpOutputSurfaceGetParameters(VdpOutputSurface surface, + VdpRGBAFormat *rgba_format, + uint32_t *width, uint32_t *height) +{ + vlVdpOutputSurface *vlsurface; + + vlsurface = vlGetDataHTAB(surface); + if (!vlsurface) + return VDP_STATUS_INVALID_HANDLE; + + *rgba_format = PipeToFormatRGBA(vlsurface->sampler_view->texture->format); + *width = vlsurface->sampler_view->texture->width0; + *height = vlsurface->sampler_view->texture->height0; + + return VDP_STATUS_OK; +} + +/** + * Copy image data from a VdpOutputSurface to application memory in the + * surface's native format. + */ +VdpStatus +vlVdpOutputSurfaceGetBitsNative(VdpOutputSurface surface, + VdpRect const *source_rect, + void *const *destination_data, + uint32_t const *destination_pitches) +{ + vlVdpOutputSurface *vlsurface; + struct pipe_context *pipe; + struct pipe_resource *res; + struct pipe_box box; + struct pipe_transfer *transfer; + uint8_t *map; + + vlsurface = vlGetDataHTAB(surface); + if (!vlsurface) + return VDP_STATUS_INVALID_HANDLE; + + pipe = vlsurface->device->context; + if (!pipe) + return VDP_STATUS_INVALID_HANDLE; + + if (!destination_data || !destination_pitches) + return VDP_STATUS_INVALID_POINTER; + + mtx_lock(&vlsurface->device->mutex); + + res = vlsurface->sampler_view->texture; + box = RectToPipeBox(source_rect, res); + map = pipe->transfer_map(pipe, res, 0, PIPE_TRANSFER_READ, &box, &transfer); + if (!map) { + mtx_unlock(&vlsurface->device->mutex); + return VDP_STATUS_RESOURCES; + } + + util_copy_rect(*destination_data, res->format, *destination_pitches, 0, 0, + box.width, box.height, map, transfer->stride, 0, 0); + + pipe_transfer_unmap(pipe, transfer); + mtx_unlock(&vlsurface->device->mutex); + + return VDP_STATUS_OK; +} + +/** + * Copy image data from application memory in the surface's native format to + * a VdpOutputSurface. + */ +VdpStatus +vlVdpOutputSurfacePutBitsNative(VdpOutputSurface surface, + void const *const *source_data, + uint32_t const *source_pitches, + VdpRect const *destination_rect) +{ + vlVdpOutputSurface *vlsurface; + struct pipe_box dst_box; + struct pipe_context *pipe; + + vlsurface = vlGetDataHTAB(surface); + if (!vlsurface) + return VDP_STATUS_INVALID_HANDLE; + + pipe = vlsurface->device->context; + if (!pipe) + return VDP_STATUS_INVALID_HANDLE; + + if (!source_data || !source_pitches) + return VDP_STATUS_INVALID_POINTER; + + mtx_lock(&vlsurface->device->mutex); + + dst_box = RectToPipeBox(destination_rect, vlsurface->sampler_view->texture); + + /* Check for a no-op. (application bug?) */ + if (!dst_box.width || !dst_box.height) { + mtx_unlock(&vlsurface->device->mutex); + return VDP_STATUS_OK; + } + + pipe->texture_subdata(pipe, vlsurface->sampler_view->texture, 0, + PIPE_TRANSFER_WRITE, &dst_box, *source_data, + *source_pitches, 0); + mtx_unlock(&vlsurface->device->mutex); + + return VDP_STATUS_OK; +} + +/** + * Copy image data from application memory in a specific indexed format to + * a VdpOutputSurface. + */ +VdpStatus +vlVdpOutputSurfacePutBitsIndexed(VdpOutputSurface surface, + VdpIndexedFormat source_indexed_format, + void const *const *source_data, + uint32_t const *source_pitch, + VdpRect const *destination_rect, + VdpColorTableFormat color_table_format, + void const *color_table) +{ + vlVdpOutputSurface *vlsurface; + struct pipe_context *context; + struct vl_compositor *compositor; + struct vl_compositor_state *cstate; + + enum pipe_format index_format; + enum pipe_format colortbl_format; + + struct pipe_resource *res, res_tmpl; + struct pipe_sampler_view sv_tmpl; + struct pipe_sampler_view *sv_idx = NULL, *sv_tbl = NULL; + + struct pipe_box box; + struct u_rect dst_rect; + + vlsurface = vlGetDataHTAB(surface); + if (!vlsurface) + return VDP_STATUS_INVALID_HANDLE; + + context = vlsurface->device->context; + compositor = &vlsurface->device->compositor; + cstate = &vlsurface->cstate; + + index_format = FormatIndexedToPipe(source_indexed_format); + if (index_format == PIPE_FORMAT_NONE) + return VDP_STATUS_INVALID_INDEXED_FORMAT; + + if (!source_data || !source_pitch) + return VDP_STATUS_INVALID_POINTER; + + colortbl_format = FormatColorTableToPipe(color_table_format); + if (colortbl_format == PIPE_FORMAT_NONE) + return VDP_STATUS_INVALID_COLOR_TABLE_FORMAT; + + if (!color_table) + return VDP_STATUS_INVALID_POINTER; + + memset(&res_tmpl, 0, sizeof(res_tmpl)); + res_tmpl.target = PIPE_TEXTURE_2D; + res_tmpl.format = index_format; + + if (destination_rect) { + res_tmpl.width0 = abs(destination_rect->x0-destination_rect->x1); + res_tmpl.height0 = abs(destination_rect->y0-destination_rect->y1); + } else { + res_tmpl.width0 = vlsurface->surface->texture->width0; + res_tmpl.height0 = vlsurface->surface->texture->height0; + } + res_tmpl.depth0 = 1; + res_tmpl.array_size = 1; + res_tmpl.usage = PIPE_USAGE_STAGING; + res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW; + + mtx_lock(&vlsurface->device->mutex); + + if (!CheckSurfaceParams(context->screen, &res_tmpl)) + goto error_resource; + + res = context->screen->resource_create(context->screen, &res_tmpl); + if (!res) + goto error_resource; + + box.x = box.y = box.z = 0; + box.width = res->width0; + box.height = res->height0; + box.depth = res->depth0; + + context->texture_subdata(context, res, 0, PIPE_TRANSFER_WRITE, &box, + source_data[0], source_pitch[0], + source_pitch[0] * res->height0); + + memset(&sv_tmpl, 0, sizeof(sv_tmpl)); + u_sampler_view_default_template(&sv_tmpl, res, res->format); + + sv_idx = context->create_sampler_view(context, res, &sv_tmpl); + pipe_resource_reference(&res, NULL); + + if (!sv_idx) + goto error_resource; + + memset(&res_tmpl, 0, sizeof(res_tmpl)); + res_tmpl.target = PIPE_TEXTURE_1D; + res_tmpl.format = colortbl_format; + res_tmpl.width0 = 1 << util_format_get_component_bits( + index_format, UTIL_FORMAT_COLORSPACE_RGB, 0); + res_tmpl.height0 = 1; + res_tmpl.depth0 = 1; + res_tmpl.array_size = 1; + res_tmpl.usage = PIPE_USAGE_STAGING; + res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW; + + res = context->screen->resource_create(context->screen, &res_tmpl); + if (!res) + goto error_resource; + + box.x = box.y = box.z = 0; + box.width = res->width0; + box.height = res->height0; + box.depth = res->depth0; + + context->texture_subdata(context, res, 0, PIPE_TRANSFER_WRITE, &box, color_table, + util_format_get_stride(colortbl_format, res->width0), 0); + + memset(&sv_tmpl, 0, sizeof(sv_tmpl)); + u_sampler_view_default_template(&sv_tmpl, res, res->format); + + sv_tbl = context->create_sampler_view(context, res, &sv_tmpl); + pipe_resource_reference(&res, NULL); + + if (!sv_tbl) + goto error_resource; + + vl_compositor_clear_layers(cstate); + vl_compositor_set_palette_layer(cstate, compositor, 0, sv_idx, sv_tbl, NULL, NULL, false); + vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect)); + vl_compositor_render(cstate, compositor, vlsurface->surface, &vlsurface->dirty_area, false); + + pipe_sampler_view_reference(&sv_idx, NULL); + pipe_sampler_view_reference(&sv_tbl, NULL); + mtx_unlock(&vlsurface->device->mutex); + + return VDP_STATUS_OK; + +error_resource: + pipe_sampler_view_reference(&sv_idx, NULL); + pipe_sampler_view_reference(&sv_tbl, NULL); + mtx_unlock(&vlsurface->device->mutex); + return VDP_STATUS_RESOURCES; +} + +/** + * Copy image data from application memory in a specific YCbCr format to + * a VdpOutputSurface. + */ +VdpStatus +vlVdpOutputSurfacePutBitsYCbCr(VdpOutputSurface surface, + VdpYCbCrFormat source_ycbcr_format, + void const *const *source_data, + uint32_t const *source_pitches, + VdpRect const *destination_rect, + VdpCSCMatrix const *csc_matrix) +{ + vlVdpOutputSurface *vlsurface; + struct vl_compositor *compositor; + struct vl_compositor_state *cstate; + + struct pipe_context *pipe; + enum pipe_format format; + struct pipe_video_buffer vtmpl, *vbuffer; + struct u_rect dst_rect; + struct pipe_sampler_view **sampler_views; + + unsigned i; + + vlsurface = vlGetDataHTAB(surface); + if (!vlsurface) + return VDP_STATUS_INVALID_HANDLE; + + + pipe = vlsurface->device->context; + compositor = &vlsurface->device->compositor; + cstate = &vlsurface->cstate; + + format = FormatYCBCRToPipe(source_ycbcr_format); + if (format == PIPE_FORMAT_NONE) + return VDP_STATUS_INVALID_Y_CB_CR_FORMAT; + + if (!source_data || !source_pitches) + return VDP_STATUS_INVALID_POINTER; + + mtx_lock(&vlsurface->device->mutex); + memset(&vtmpl, 0, sizeof(vtmpl)); + vtmpl.buffer_format = format; + + if (destination_rect) { + vtmpl.width = abs(destination_rect->x0-destination_rect->x1); + vtmpl.height = abs(destination_rect->y0-destination_rect->y1); + } else { + vtmpl.width = vlsurface->surface->texture->width0; + vtmpl.height = vlsurface->surface->texture->height0; + } + + vbuffer = pipe->create_video_buffer(pipe, &vtmpl); + if (!vbuffer) { + mtx_unlock(&vlsurface->device->mutex); + return VDP_STATUS_RESOURCES; + } + + sampler_views = vbuffer->get_sampler_view_planes(vbuffer); + if (!sampler_views) { + vbuffer->destroy(vbuffer); + mtx_unlock(&vlsurface->device->mutex); + return VDP_STATUS_RESOURCES; + } + + for (i = 0; i < 3; ++i) { + struct pipe_sampler_view *sv = sampler_views[i]; + if (!sv) continue; + + struct pipe_box dst_box = { + 0, 0, 0, + sv->texture->width0, sv->texture->height0, 1 + }; + + pipe->texture_subdata(pipe, sv->texture, 0, PIPE_TRANSFER_WRITE, &dst_box, + source_data[i], source_pitches[i], 0); + } + + if (!csc_matrix) { + vl_csc_matrix csc; + vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601, NULL, 1, &csc); + if (!vl_compositor_set_csc_matrix(cstate, (const vl_csc_matrix*)&csc, 1.0f, 0.0f)) + goto err_csc_matrix; + } else { + if (!vl_compositor_set_csc_matrix(cstate, csc_matrix, 1.0f, 0.0f)) + goto err_csc_matrix; + } + + vl_compositor_clear_layers(cstate); + vl_compositor_set_buffer_layer(cstate, compositor, 0, vbuffer, NULL, NULL, VL_COMPOSITOR_WEAVE); + vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect)); + vl_compositor_render(cstate, compositor, vlsurface->surface, &vlsurface->dirty_area, false); + + vbuffer->destroy(vbuffer); + mtx_unlock(&vlsurface->device->mutex); + + return VDP_STATUS_OK; +err_csc_matrix: + vbuffer->destroy(vbuffer); + mtx_unlock(&vlsurface->device->mutex); + return VDP_STATUS_ERROR; +} + +static unsigned +BlendFactorToPipe(VdpOutputSurfaceRenderBlendFactor factor) +{ + switch (factor) { + case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ZERO: + return PIPE_BLENDFACTOR_ZERO; + case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE: + return PIPE_BLENDFACTOR_ONE; + case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_COLOR: + return PIPE_BLENDFACTOR_SRC_COLOR; + case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_COLOR: + return PIPE_BLENDFACTOR_INV_SRC_COLOR; + case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA: + return PIPE_BLENDFACTOR_SRC_ALPHA; + case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA: + return PIPE_BLENDFACTOR_INV_SRC_ALPHA; + case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_DST_ALPHA: + return PIPE_BLENDFACTOR_DST_ALPHA; + case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_DST_ALPHA: + return PIPE_BLENDFACTOR_INV_DST_ALPHA; + case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_DST_COLOR: + return PIPE_BLENDFACTOR_DST_COLOR; + case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_DST_COLOR: + return PIPE_BLENDFACTOR_INV_DST_COLOR; + case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA_SATURATE: + return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE; + case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_CONSTANT_COLOR: + return PIPE_BLENDFACTOR_CONST_COLOR; + case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR: + return PIPE_BLENDFACTOR_INV_CONST_COLOR; + case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_CONSTANT_ALPHA: + return PIPE_BLENDFACTOR_CONST_ALPHA; + case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA: + return PIPE_BLENDFACTOR_INV_CONST_ALPHA; + default: + assert(0); + return PIPE_BLENDFACTOR_ONE; + } +} + +static unsigned +BlendEquationToPipe(VdpOutputSurfaceRenderBlendEquation equation) +{ + switch (equation) { + case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_SUBTRACT: + return PIPE_BLEND_SUBTRACT; + case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_REVERSE_SUBTRACT: + return PIPE_BLEND_REVERSE_SUBTRACT; + case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD: + return PIPE_BLEND_ADD; + case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_MIN: + return PIPE_BLEND_MIN; + case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_MAX: + return PIPE_BLEND_MAX; + default: + assert(0); + return PIPE_BLEND_ADD; + } +} + +static void * +BlenderToPipe(struct pipe_context *context, + VdpOutputSurfaceRenderBlendState const *blend_state) +{ + struct pipe_blend_state blend; + + memset(&blend, 0, sizeof blend); + blend.independent_blend_enable = 0; + + if (blend_state) { + blend.rt[0].blend_enable = 1; + blend.rt[0].rgb_src_factor = BlendFactorToPipe(blend_state->blend_factor_source_color); + blend.rt[0].rgb_dst_factor = BlendFactorToPipe(blend_state->blend_factor_destination_color); + blend.rt[0].alpha_src_factor = BlendFactorToPipe(blend_state->blend_factor_source_alpha); + blend.rt[0].alpha_dst_factor = BlendFactorToPipe(blend_state->blend_factor_destination_alpha); + blend.rt[0].rgb_func = BlendEquationToPipe(blend_state->blend_equation_color); + blend.rt[0].alpha_func = BlendEquationToPipe(blend_state->blend_equation_alpha); + } else { + blend.rt[0].blend_enable = 0; + } + + blend.logicop_enable = 0; + blend.logicop_func = PIPE_LOGICOP_CLEAR; + blend.rt[0].colormask = PIPE_MASK_RGBA; + blend.dither = 0; + + return context->create_blend_state(context, &blend); +} + +static struct vertex4f * +ColorsToPipe(VdpColor const *colors, uint32_t flags, struct vertex4f result[4]) +{ + unsigned i; + struct vertex4f *dst = result; + + if (!colors) + return NULL; + + for (i = 0; i < 4; ++i) { + dst->x = colors->red; + dst->y = colors->green; + dst->z = colors->blue; + dst->w = colors->alpha; + + ++dst; + if (flags & VDP_OUTPUT_SURFACE_RENDER_COLOR_PER_VERTEX) + ++colors; + } + return result; +} + +/** + * Composite a sub-rectangle of a VdpOutputSurface into a sub-rectangle of + * another VdpOutputSurface; Output Surface object VdpOutputSurface. + */ +VdpStatus +vlVdpOutputSurfaceRenderOutputSurface(VdpOutputSurface destination_surface, + VdpRect const *destination_rect, + VdpOutputSurface source_surface, + VdpRect const *source_rect, + VdpColor const *colors, + VdpOutputSurfaceRenderBlendState const *blend_state, + uint32_t flags) +{ + vlVdpOutputSurface *dst_vlsurface; + + struct pipe_context *context; + struct pipe_sampler_view *src_sv; + struct vl_compositor *compositor; + struct vl_compositor_state *cstate; + + struct u_rect src_rect, dst_rect; + + struct vertex4f vlcolors[4]; + void *blend; + + dst_vlsurface = vlGetDataHTAB(destination_surface); + if (!dst_vlsurface) + return VDP_STATUS_INVALID_HANDLE; + + if (source_surface == VDP_INVALID_HANDLE) { + src_sv = dst_vlsurface->device->dummy_sv; + + } else { + vlVdpOutputSurface *src_vlsurface = vlGetDataHTAB(source_surface); + if (!src_vlsurface) + return VDP_STATUS_INVALID_HANDLE; + + if (dst_vlsurface->device != src_vlsurface->device) + return VDP_STATUS_HANDLE_DEVICE_MISMATCH; + + src_sv = src_vlsurface->sampler_view; + } + + mtx_lock(&dst_vlsurface->device->mutex); + + context = dst_vlsurface->device->context; + compositor = &dst_vlsurface->device->compositor; + cstate = &dst_vlsurface->cstate; + + blend = BlenderToPipe(context, blend_state); + + vl_compositor_clear_layers(cstate); + vl_compositor_set_layer_blend(cstate, 0, blend, false); + vl_compositor_set_rgba_layer(cstate, compositor, 0, src_sv, + RectToPipe(source_rect, &src_rect), NULL, + ColorsToPipe(colors, flags, vlcolors)); + STATIC_ASSERT(VL_COMPOSITOR_ROTATE_0 == VDP_OUTPUT_SURFACE_RENDER_ROTATE_0); + STATIC_ASSERT(VL_COMPOSITOR_ROTATE_90 == VDP_OUTPUT_SURFACE_RENDER_ROTATE_90); + STATIC_ASSERT(VL_COMPOSITOR_ROTATE_180 == VDP_OUTPUT_SURFACE_RENDER_ROTATE_180); + STATIC_ASSERT(VL_COMPOSITOR_ROTATE_270 == VDP_OUTPUT_SURFACE_RENDER_ROTATE_270); + vl_compositor_set_layer_rotation(cstate, 0, flags & 3); + vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect)); + vl_compositor_render(cstate, compositor, dst_vlsurface->surface, &dst_vlsurface->dirty_area, false); + + context->delete_blend_state(context, blend); + mtx_unlock(&dst_vlsurface->device->mutex); + + return VDP_STATUS_OK; +} + +/** + * Composite a sub-rectangle of a VdpBitmapSurface into a sub-rectangle of + * a VdpOutputSurface; Output Surface object VdpOutputSurface. + */ +VdpStatus +vlVdpOutputSurfaceRenderBitmapSurface(VdpOutputSurface destination_surface, + VdpRect const *destination_rect, + VdpBitmapSurface source_surface, + VdpRect const *source_rect, + VdpColor const *colors, + VdpOutputSurfaceRenderBlendState const *blend_state, + uint32_t flags) +{ + vlVdpOutputSurface *dst_vlsurface; + + struct pipe_context *context; + struct pipe_sampler_view *src_sv; + struct vl_compositor *compositor; + struct vl_compositor_state *cstate; + + struct u_rect src_rect, dst_rect; + + struct vertex4f vlcolors[4]; + void *blend; + + dst_vlsurface = vlGetDataHTAB(destination_surface); + if (!dst_vlsurface) + return VDP_STATUS_INVALID_HANDLE; + + if (source_surface == VDP_INVALID_HANDLE) { + src_sv = dst_vlsurface->device->dummy_sv; + + } else { + vlVdpBitmapSurface *src_vlsurface = vlGetDataHTAB(source_surface); + if (!src_vlsurface) + return VDP_STATUS_INVALID_HANDLE; + + if (dst_vlsurface->device != src_vlsurface->device) + return VDP_STATUS_HANDLE_DEVICE_MISMATCH; + + src_sv = src_vlsurface->sampler_view; + } + + context = dst_vlsurface->device->context; + compositor = &dst_vlsurface->device->compositor; + cstate = &dst_vlsurface->cstate; + + mtx_lock(&dst_vlsurface->device->mutex); + + blend = BlenderToPipe(context, blend_state); + + vl_compositor_clear_layers(cstate); + vl_compositor_set_layer_blend(cstate, 0, blend, false); + vl_compositor_set_rgba_layer(cstate, compositor, 0, src_sv, + RectToPipe(source_rect, &src_rect), NULL, + ColorsToPipe(colors, flags, vlcolors)); + vl_compositor_set_layer_rotation(cstate, 0, flags & 3); + vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect)); + vl_compositor_render(cstate, compositor, dst_vlsurface->surface, &dst_vlsurface->dirty_area, false); + + context->delete_blend_state(context, blend); + mtx_unlock(&dst_vlsurface->device->mutex); + + return VDP_STATUS_OK; +} + +struct pipe_resource *vlVdpOutputSurfaceGallium(VdpOutputSurface surface) +{ + vlVdpOutputSurface *vlsurface; + + vlsurface = vlGetDataHTAB(surface); + if (!vlsurface || !vlsurface->surface) + return NULL; + + mtx_lock(&vlsurface->device->mutex); + vlsurface->device->context->flush(vlsurface->device->context, NULL, 0); + mtx_unlock(&vlsurface->device->mutex); + + return vlsurface->surface->texture; +} + +VdpStatus vlVdpOutputSurfaceDMABuf(VdpOutputSurface surface, + struct VdpSurfaceDMABufDesc *result) +{ + vlVdpOutputSurface *vlsurface; + struct pipe_screen *pscreen; + struct winsys_handle whandle; + + memset(result, 0, sizeof(*result)); + result->handle = -1; + + vlsurface = vlGetDataHTAB(surface); + if (!vlsurface || !vlsurface->surface) + return VDP_STATUS_INVALID_HANDLE; + + mtx_lock(&vlsurface->device->mutex); + vlsurface->device->context->flush(vlsurface->device->context, NULL, 0); + + memset(&whandle, 0, sizeof(struct winsys_handle)); + whandle.type = WINSYS_HANDLE_TYPE_FD; + + pscreen = vlsurface->surface->texture->screen; + if (!pscreen->resource_get_handle(pscreen, vlsurface->device->context, + vlsurface->surface->texture, &whandle, + PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE)) { + mtx_unlock(&vlsurface->device->mutex); + return VDP_STATUS_NO_IMPLEMENTATION; + } + + mtx_unlock(&vlsurface->device->mutex); + + result->handle = whandle.handle; + result->width = vlsurface->surface->width; + result->height = vlsurface->surface->height; + result->offset = whandle.offset; + result->stride = whandle.stride; + result->format = PipeToFormatRGBA(vlsurface->surface->format); + + return VDP_STATUS_OK; +} diff --git a/src/gallium/frontends/vdpau/preemption.c b/src/gallium/frontends/vdpau/preemption.c new file mode 100644 index 00000000000..6d376acd339 --- /dev/null +++ b/src/gallium/frontends/vdpau/preemption.c @@ -0,0 +1,48 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include +#include "vdpau_private.h" + +/** + * A callback to notify the client application that a device's display has + * been preempted. + */ +void vlVdpPreemptionCallback(VdpDevice device, void *context) +{ + /* TODO: Implement preemption */ +} + +/** + * Configure the display preemption callback. + */ +VdpStatus vlVdpPreemptionCallbackRegister(VdpDevice device, + VdpPreemptionCallback callback, + void *context) +{ + return VDP_STATUS_OK; +} diff --git a/src/gallium/frontends/vdpau/presentation.c b/src/gallium/frontends/vdpau/presentation.c new file mode 100644 index 00000000000..54f15ff34b1 --- /dev/null +++ b/src/gallium/frontends/vdpau/presentation.c @@ -0,0 +1,384 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include +#include + +#include "util/u_debug.h" +#include "util/u_memory.h" + +#include "vdpau_private.h" + +/** + * Create a VdpPresentationQueue. + */ +VdpStatus +vlVdpPresentationQueueCreate(VdpDevice device, + VdpPresentationQueueTarget presentation_queue_target, + VdpPresentationQueue *presentation_queue) +{ + vlVdpPresentationQueue *pq = NULL; + VdpStatus ret; + + if (!presentation_queue) + return VDP_STATUS_INVALID_POINTER; + + vlVdpDevice *dev = vlGetDataHTAB(device); + if (!dev) + return VDP_STATUS_INVALID_HANDLE; + + vlVdpPresentationQueueTarget *pqt = vlGetDataHTAB(presentation_queue_target); + if (!pqt) + return VDP_STATUS_INVALID_HANDLE; + + if (dev != pqt->device) + return VDP_STATUS_HANDLE_DEVICE_MISMATCH; + + pq = CALLOC(1, sizeof(vlVdpPresentationQueue)); + if (!pq) + return VDP_STATUS_RESOURCES; + + DeviceReference(&pq->device, dev); + pq->drawable = pqt->drawable; + + mtx_lock(&dev->mutex); + if (!vl_compositor_init_state(&pq->cstate, dev->context)) { + mtx_unlock(&dev->mutex); + ret = VDP_STATUS_ERROR; + goto no_compositor; + } + mtx_unlock(&dev->mutex); + + *presentation_queue = vlAddDataHTAB(pq); + if (*presentation_queue == 0) { + ret = VDP_STATUS_ERROR; + goto no_handle; + } + + return VDP_STATUS_OK; + +no_handle: +no_compositor: + DeviceReference(&pq->device, NULL); + FREE(pq); + return ret; +} + +/** + * Destroy a VdpPresentationQueue. + */ +VdpStatus +vlVdpPresentationQueueDestroy(VdpPresentationQueue presentation_queue) +{ + vlVdpPresentationQueue *pq; + + pq = vlGetDataHTAB(presentation_queue); + if (!pq) + return VDP_STATUS_INVALID_HANDLE; + + mtx_lock(&pq->device->mutex); + vl_compositor_cleanup_state(&pq->cstate); + mtx_unlock(&pq->device->mutex); + + vlRemoveDataHTAB(presentation_queue); + DeviceReference(&pq->device, NULL); + FREE(pq); + + return VDP_STATUS_OK; +} + +/** + * Configure the background color setting. + */ +VdpStatus +vlVdpPresentationQueueSetBackgroundColor(VdpPresentationQueue presentation_queue, + VdpColor *const background_color) +{ + vlVdpPresentationQueue *pq; + union pipe_color_union color; + + if (!background_color) + return VDP_STATUS_INVALID_POINTER; + + pq = vlGetDataHTAB(presentation_queue); + if (!pq) + return VDP_STATUS_INVALID_HANDLE; + + color.f[0] = background_color->red; + color.f[1] = background_color->green; + color.f[2] = background_color->blue; + color.f[3] = background_color->alpha; + + mtx_lock(&pq->device->mutex); + vl_compositor_set_clear_color(&pq->cstate, &color); + mtx_unlock(&pq->device->mutex); + + return VDP_STATUS_OK; +} + +/** + * Retrieve the current background color setting. + */ +VdpStatus +vlVdpPresentationQueueGetBackgroundColor(VdpPresentationQueue presentation_queue, + VdpColor *const background_color) +{ + vlVdpPresentationQueue *pq; + union pipe_color_union color; + + if (!background_color) + return VDP_STATUS_INVALID_POINTER; + + pq = vlGetDataHTAB(presentation_queue); + if (!pq) + return VDP_STATUS_INVALID_HANDLE; + + mtx_lock(&pq->device->mutex); + vl_compositor_get_clear_color(&pq->cstate, &color); + mtx_unlock(&pq->device->mutex); + + background_color->red = color.f[0]; + background_color->green = color.f[1]; + background_color->blue = color.f[2]; + background_color->alpha = color.f[3]; + + return VDP_STATUS_OK; +} + +/** + * Retrieve the presentation queue's "current" time. + */ +VdpStatus +vlVdpPresentationQueueGetTime(VdpPresentationQueue presentation_queue, + VdpTime *current_time) +{ + vlVdpPresentationQueue *pq; + + if (!current_time) + return VDP_STATUS_INVALID_POINTER; + + pq = vlGetDataHTAB(presentation_queue); + if (!pq) + return VDP_STATUS_INVALID_HANDLE; + + mtx_lock(&pq->device->mutex); + *current_time = pq->device->vscreen->get_timestamp(pq->device->vscreen, + (void *)pq->drawable); + mtx_unlock(&pq->device->mutex); + + return VDP_STATUS_OK; +} + +/** + * Enter a surface into the presentation queue. + */ +VdpStatus +vlVdpPresentationQueueDisplay(VdpPresentationQueue presentation_queue, + VdpOutputSurface surface, + uint32_t clip_width, + uint32_t clip_height, + VdpTime earliest_presentation_time) +{ + static int dump_window = -1; + + vlVdpPresentationQueue *pq; + vlVdpOutputSurface *surf; + + struct pipe_context *pipe; + struct pipe_resource *tex; + struct pipe_surface surf_templ, *surf_draw = NULL; + struct u_rect src_rect, dst_clip, *dirty_area; + + struct vl_compositor *compositor; + struct vl_compositor_state *cstate; + struct vl_screen *vscreen; + + pq = vlGetDataHTAB(presentation_queue); + if (!pq) + return VDP_STATUS_INVALID_HANDLE; + + surf = vlGetDataHTAB(surface); + if (!surf) + return VDP_STATUS_INVALID_HANDLE; + + pipe = pq->device->context; + compositor = &pq->device->compositor; + cstate = &pq->cstate; + vscreen = pq->device->vscreen; + + mtx_lock(&pq->device->mutex); + if (vscreen->set_back_texture_from_output && surf->send_to_X) + vscreen->set_back_texture_from_output(vscreen, surf->surface->texture, clip_width, clip_height); + tex = vscreen->texture_from_drawable(vscreen, (void *)pq->drawable); + if (!tex) { + mtx_unlock(&pq->device->mutex); + return VDP_STATUS_INVALID_HANDLE; + } + + if (!vscreen->set_back_texture_from_output || !surf->send_to_X) { + dirty_area = vscreen->get_dirty_area(vscreen); + + memset(&surf_templ, 0, sizeof(surf_templ)); + surf_templ.format = tex->format; + surf_draw = pipe->create_surface(pipe, tex, &surf_templ); + + dst_clip.x0 = 0; + dst_clip.y0 = 0; + dst_clip.x1 = clip_width ? clip_width : surf_draw->width; + dst_clip.y1 = clip_height ? clip_height : surf_draw->height; + + src_rect.x0 = 0; + src_rect.y0 = 0; + src_rect.x1 = surf_draw->width; + src_rect.y1 = surf_draw->height; + + vl_compositor_clear_layers(cstate); + vl_compositor_set_rgba_layer(cstate, compositor, 0, surf->sampler_view, &src_rect, NULL, NULL); + vl_compositor_set_dst_clip(cstate, &dst_clip); + vl_compositor_render(cstate, compositor, surf_draw, dirty_area, true); + } + + vscreen->set_next_timestamp(vscreen, earliest_presentation_time); + + // flush before calling flush_frontbuffer so that rendering is flushed + // to back buffer so the texture can be copied in flush_frontbuffer + pipe->screen->fence_reference(pipe->screen, &surf->fence, NULL); + pipe->flush(pipe, &surf->fence, 0); + pipe->screen->flush_frontbuffer(pipe->screen, tex, 0, 0, + vscreen->get_private(vscreen), NULL); + + pq->last_surf = surf; + + if (dump_window == -1) { + dump_window = debug_get_num_option("VDPAU_DUMP", 0); + } + + if (dump_window) { + static unsigned int framenum = 0; + char cmd[256]; + + if (framenum) { + sprintf(cmd, "xwd -id %d -silent -out vdpau_frame_%08d.xwd", (int)pq->drawable, framenum); + if (system(cmd) != 0) + VDPAU_MSG(VDPAU_ERR, "[VDPAU] Dumping surface %d failed.\n", surface); + } + framenum++; + } + + if (!vscreen->set_back_texture_from_output || !surf->send_to_X) { + pipe_resource_reference(&tex, NULL); + pipe_surface_reference(&surf_draw, NULL); + } + mtx_unlock(&pq->device->mutex); + + return VDP_STATUS_OK; +} + +/** + * Wait for a surface to finish being displayed. + */ +VdpStatus +vlVdpPresentationQueueBlockUntilSurfaceIdle(VdpPresentationQueue presentation_queue, + VdpOutputSurface surface, + VdpTime *first_presentation_time) +{ + vlVdpPresentationQueue *pq; + vlVdpOutputSurface *surf; + struct pipe_screen *screen; + + if (!first_presentation_time) + return VDP_STATUS_INVALID_POINTER; + + pq = vlGetDataHTAB(presentation_queue); + if (!pq) + return VDP_STATUS_INVALID_HANDLE; + + surf = vlGetDataHTAB(surface); + if (!surf) + return VDP_STATUS_INVALID_HANDLE; + + mtx_lock(&pq->device->mutex); + if (surf->fence) { + screen = pq->device->vscreen->pscreen; + screen->fence_finish(screen, NULL, surf->fence, PIPE_TIMEOUT_INFINITE); + screen->fence_reference(screen, &surf->fence, NULL); + } + mtx_unlock(&pq->device->mutex); + + return vlVdpPresentationQueueGetTime(presentation_queue, first_presentation_time); +} + +/** + * Poll the current queue status of a surface. + */ +VdpStatus +vlVdpPresentationQueueQuerySurfaceStatus(VdpPresentationQueue presentation_queue, + VdpOutputSurface surface, + VdpPresentationQueueStatus *status, + VdpTime *first_presentation_time) +{ + vlVdpPresentationQueue *pq; + vlVdpOutputSurface *surf; + struct pipe_screen *screen; + + if (!(status && first_presentation_time)) + return VDP_STATUS_INVALID_POINTER; + + pq = vlGetDataHTAB(presentation_queue); + if (!pq) + return VDP_STATUS_INVALID_HANDLE; + + surf = vlGetDataHTAB(surface); + if (!surf) + return VDP_STATUS_INVALID_HANDLE; + + *first_presentation_time = 0; + + if (!surf->fence) { + if (pq->last_surf == surf) + *status = VDP_PRESENTATION_QUEUE_STATUS_VISIBLE; + else + *status = VDP_PRESENTATION_QUEUE_STATUS_IDLE; + } else { + mtx_lock(&pq->device->mutex); + screen = pq->device->vscreen->pscreen; + if (screen->fence_finish(screen, NULL, surf->fence, 0)) { + screen->fence_reference(screen, &surf->fence, NULL); + *status = VDP_PRESENTATION_QUEUE_STATUS_VISIBLE; + mtx_unlock(&pq->device->mutex); + + // We actually need to query the timestamp of the last VSYNC event from the hardware + vlVdpPresentationQueueGetTime(presentation_queue, first_presentation_time); + *first_presentation_time += 1; + } else { + *status = VDP_PRESENTATION_QUEUE_STATUS_QUEUED; + mtx_unlock(&pq->device->mutex); + } + } + + return VDP_STATUS_OK; +} diff --git a/src/gallium/frontends/vdpau/query.c b/src/gallium/frontends/vdpau/query.c new file mode 100644 index 00000000000..701d9f220c4 --- /dev/null +++ b/src/gallium/frontends/vdpau/query.c @@ -0,0 +1,622 @@ +/************************************************************************** + * + * Copyright 2010 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include +#include + +#include "vdpau_private.h" +#include "pipe/p_screen.h" +#include "pipe/p_defines.h" +#include "util/u_debug.h" + +/** + * Retrieve the VDPAU version implemented by the backend. + */ +VdpStatus +vlVdpGetApiVersion(uint32_t *api_version) +{ + if (!api_version) + return VDP_STATUS_INVALID_POINTER; + + *api_version = 1; + return VDP_STATUS_OK; +} + +/** + * Retrieve an implementation-specific string description of the implementation. + * This typically includes detailed version information. + */ +VdpStatus +vlVdpGetInformationString(char const **information_string) +{ + if (!information_string) + return VDP_STATUS_INVALID_POINTER; + + *information_string = INFORMATION_STRING; + return VDP_STATUS_OK; +} + +/** + * Query the implementation's VdpVideoSurface capabilities. + */ +VdpStatus +vlVdpVideoSurfaceQueryCapabilities(VdpDevice device, VdpChromaType surface_chroma_type, + VdpBool *is_supported, uint32_t *max_width, uint32_t *max_height) +{ + vlVdpDevice *dev; + struct pipe_screen *pscreen; + uint32_t max_2d_texture_size; + + if (!(is_supported && max_width && max_height)) + return VDP_STATUS_INVALID_POINTER; + + dev = vlGetDataHTAB(device); + if (!dev) + return VDP_STATUS_INVALID_HANDLE; + + pscreen = dev->vscreen->pscreen; + if (!pscreen) + return VDP_STATUS_RESOURCES; + + mtx_lock(&dev->mutex); + + /* XXX: Current limits */ + *is_supported = true; + max_2d_texture_size = pscreen->get_param(pscreen, PIPE_CAP_MAX_TEXTURE_2D_SIZE); + mtx_unlock(&dev->mutex); + if (!max_2d_texture_size) + return VDP_STATUS_RESOURCES; + + *max_width = *max_height = max_2d_texture_size; + + return VDP_STATUS_OK; +} + +/** + * Query the implementation's VdpVideoSurface GetBits/PutBits capabilities. + */ +VdpStatus +vlVdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities(VdpDevice device, VdpChromaType surface_chroma_type, + VdpYCbCrFormat bits_ycbcr_format, + VdpBool *is_supported) +{ + vlVdpDevice *dev; + struct pipe_screen *pscreen; + + if (!is_supported) + return VDP_STATUS_INVALID_POINTER; + + dev = vlGetDataHTAB(device); + if (!dev) + return VDP_STATUS_INVALID_HANDLE; + + pscreen = dev->vscreen->pscreen; + if (!pscreen) + return VDP_STATUS_RESOURCES; + + mtx_lock(&dev->mutex); + + switch(bits_ycbcr_format) { + case VDP_YCBCR_FORMAT_NV12: + *is_supported = surface_chroma_type == VDP_CHROMA_TYPE_420; + break; + + case VDP_YCBCR_FORMAT_YV12: + *is_supported = surface_chroma_type == VDP_CHROMA_TYPE_420; + + /* We can convert YV12 to NV12 on the fly! */ + if (*is_supported && + pscreen->is_video_format_supported(pscreen, + PIPE_FORMAT_NV12, + PIPE_VIDEO_PROFILE_UNKNOWN, + PIPE_VIDEO_ENTRYPOINT_BITSTREAM)) { + mtx_unlock(&dev->mutex); + return VDP_STATUS_OK; + } + break; + + case VDP_YCBCR_FORMAT_UYVY: + case VDP_YCBCR_FORMAT_YUYV: + *is_supported = surface_chroma_type == VDP_CHROMA_TYPE_422; + break; + + case VDP_YCBCR_FORMAT_Y8U8V8A8: + case VDP_YCBCR_FORMAT_V8U8Y8A8: + *is_supported = surface_chroma_type == VDP_CHROMA_TYPE_444; + break; + + default: + *is_supported = false; + break; + } + + if (*is_supported && + !pscreen->is_video_format_supported(pscreen, + FormatYCBCRToPipe(bits_ycbcr_format), + PIPE_VIDEO_PROFILE_UNKNOWN, + PIPE_VIDEO_ENTRYPOINT_BITSTREAM)) { + *is_supported = false; + } + mtx_unlock(&dev->mutex); + + return VDP_STATUS_OK; +} + +/** + * Query the implementation's VdpDecoder capabilities. + */ +VdpStatus +vlVdpDecoderQueryCapabilities(VdpDevice device, VdpDecoderProfile profile, + VdpBool *is_supported, uint32_t *max_level, uint32_t *max_macroblocks, + uint32_t *max_width, uint32_t *max_height) +{ + vlVdpDevice *dev; + struct pipe_screen *pscreen; + enum pipe_video_profile p_profile; + + if (!(is_supported && max_level && max_macroblocks && max_width && max_height)) + return VDP_STATUS_INVALID_POINTER; + + dev = vlGetDataHTAB(device); + if (!dev) + return VDP_STATUS_INVALID_HANDLE; + + pscreen = dev->vscreen->pscreen; + if (!pscreen) + return VDP_STATUS_RESOURCES; + + p_profile = ProfileToPipe(profile); + if (p_profile == PIPE_VIDEO_PROFILE_UNKNOWN) { + *is_supported = false; + return VDP_STATUS_OK; + } + + mtx_lock(&dev->mutex); + *is_supported = pscreen->get_video_param(pscreen, p_profile, PIPE_VIDEO_ENTRYPOINT_BITSTREAM, + PIPE_VIDEO_CAP_SUPPORTED); + if (*is_supported) { + *max_width = pscreen->get_video_param(pscreen, p_profile, PIPE_VIDEO_ENTRYPOINT_BITSTREAM, + PIPE_VIDEO_CAP_MAX_WIDTH); + *max_height = pscreen->get_video_param(pscreen, p_profile, PIPE_VIDEO_ENTRYPOINT_BITSTREAM, + PIPE_VIDEO_CAP_MAX_HEIGHT); + *max_level = pscreen->get_video_param(pscreen, p_profile, PIPE_VIDEO_ENTRYPOINT_BITSTREAM, + PIPE_VIDEO_CAP_MAX_LEVEL); + *max_macroblocks = (*max_width/16)*(*max_height/16); + } else { + *max_width = 0; + *max_height = 0; + *max_level = 0; + *max_macroblocks = 0; + } + mtx_unlock(&dev->mutex); + + return VDP_STATUS_OK; +} + +/** + * Query the implementation's VdpOutputSurface capabilities. + */ +VdpStatus +vlVdpOutputSurfaceQueryCapabilities(VdpDevice device, VdpRGBAFormat surface_rgba_format, + VdpBool *is_supported, uint32_t *max_width, uint32_t *max_height) +{ + vlVdpDevice *dev; + struct pipe_screen *pscreen; + enum pipe_format format; + + dev = vlGetDataHTAB(device); + if (!dev) + return VDP_STATUS_INVALID_HANDLE; + + pscreen = dev->vscreen->pscreen; + if (!pscreen) + return VDP_STATUS_RESOURCES; + + format = VdpFormatRGBAToPipe(surface_rgba_format); + if (format == PIPE_FORMAT_NONE || format == PIPE_FORMAT_A8_UNORM) + return VDP_STATUS_INVALID_RGBA_FORMAT; + + if (!(is_supported && max_width && max_height)) + return VDP_STATUS_INVALID_POINTER; + + mtx_lock(&dev->mutex); + *is_supported = pscreen->is_format_supported + ( + pscreen, format, PIPE_TEXTURE_2D, 1, 1, + PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET + ); + if (*is_supported) { + uint32_t max_2d_texture_size = pscreen->get_param( + pscreen, PIPE_CAP_MAX_TEXTURE_2D_SIZE); + + if (!max_2d_texture_size) { + mtx_unlock(&dev->mutex); + return VDP_STATUS_ERROR; + } + + *max_width = *max_height = max_2d_texture_size; + } else { + *max_width = 0; + *max_height = 0; + } + mtx_unlock(&dev->mutex); + + return VDP_STATUS_OK; +} + +/** + * Query the implementation's capability to perform a PutBits operation using + * application data matching the surface's format. + */ +VdpStatus +vlVdpOutputSurfaceQueryGetPutBitsNativeCapabilities(VdpDevice device, VdpRGBAFormat surface_rgba_format, + VdpBool *is_supported) +{ + vlVdpDevice *dev; + struct pipe_screen *pscreen; + enum pipe_format format; + + dev = vlGetDataHTAB(device); + if (!dev) + return VDP_STATUS_INVALID_HANDLE; + + pscreen = dev->vscreen->pscreen; + if (!pscreen) + return VDP_STATUS_ERROR; + + format = VdpFormatRGBAToPipe(surface_rgba_format); + if (format == PIPE_FORMAT_NONE || format == PIPE_FORMAT_A8_UNORM) + return VDP_STATUS_INVALID_RGBA_FORMAT; + + if (!is_supported) + return VDP_STATUS_INVALID_POINTER; + + mtx_lock(&dev->mutex); + *is_supported = pscreen->is_format_supported + ( + pscreen, format, PIPE_TEXTURE_2D, 1, 1, + PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET + ); + mtx_unlock(&dev->mutex); + + return VDP_STATUS_OK; +} + +/** + * Query the implementation's capability to perform a PutBits operation using + * application data in a specific indexed format. + */ +VdpStatus +vlVdpOutputSurfaceQueryPutBitsIndexedCapabilities(VdpDevice device, + VdpRGBAFormat surface_rgba_format, + VdpIndexedFormat bits_indexed_format, + VdpColorTableFormat color_table_format, + VdpBool *is_supported) +{ + vlVdpDevice *dev; + struct pipe_screen *pscreen; + enum pipe_format rgba_format, index_format, colortbl_format; + + dev = vlGetDataHTAB(device); + if (!dev) + return VDP_STATUS_INVALID_HANDLE; + + pscreen = dev->vscreen->pscreen; + if (!pscreen) + return VDP_STATUS_ERROR; + + rgba_format = VdpFormatRGBAToPipe(surface_rgba_format); + if (rgba_format == PIPE_FORMAT_NONE || rgba_format == PIPE_FORMAT_A8_UNORM) + return VDP_STATUS_INVALID_RGBA_FORMAT; + + index_format = FormatIndexedToPipe(bits_indexed_format); + if (index_format == PIPE_FORMAT_NONE) + return VDP_STATUS_INVALID_INDEXED_FORMAT; + + colortbl_format = FormatColorTableToPipe(color_table_format); + if (colortbl_format == PIPE_FORMAT_NONE) + return VDP_STATUS_INVALID_COLOR_TABLE_FORMAT; + + if (!is_supported) + return VDP_STATUS_INVALID_POINTER; + + mtx_lock(&dev->mutex); + *is_supported = pscreen->is_format_supported + ( + pscreen, rgba_format, PIPE_TEXTURE_2D, 1, 1, + PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET + ); + + *is_supported &= pscreen->is_format_supported + ( + pscreen, index_format, PIPE_TEXTURE_2D, 1, 1, + PIPE_BIND_SAMPLER_VIEW + ); + + *is_supported &= pscreen->is_format_supported + ( + pscreen, colortbl_format, PIPE_TEXTURE_1D, 1, 1, + PIPE_BIND_SAMPLER_VIEW + ); + mtx_unlock(&dev->mutex); + + return VDP_STATUS_OK; +} + +/** + * Query the implementation's capability to perform a PutBits operation using + * application data in a specific YCbCr/YUB format. + */ +VdpStatus +vlVdpOutputSurfaceQueryPutBitsYCbCrCapabilities(VdpDevice device, VdpRGBAFormat surface_rgba_format, + VdpYCbCrFormat bits_ycbcr_format, + VdpBool *is_supported) +{ + vlVdpDevice *dev; + struct pipe_screen *pscreen; + enum pipe_format rgba_format, ycbcr_format; + + dev = vlGetDataHTAB(device); + if (!dev) + return VDP_STATUS_INVALID_HANDLE; + + pscreen = dev->vscreen->pscreen; + if (!pscreen) + return VDP_STATUS_ERROR; + + rgba_format = VdpFormatRGBAToPipe(surface_rgba_format); + if (rgba_format == PIPE_FORMAT_NONE || rgba_format == PIPE_FORMAT_A8_UNORM) + return VDP_STATUS_INVALID_RGBA_FORMAT; + + ycbcr_format = FormatYCBCRToPipe(bits_ycbcr_format); + if (ycbcr_format == PIPE_FORMAT_NONE) + return VDP_STATUS_INVALID_INDEXED_FORMAT; + + if (!is_supported) + return VDP_STATUS_INVALID_POINTER; + + mtx_lock(&dev->mutex); + *is_supported = pscreen->is_format_supported + ( + pscreen, rgba_format, PIPE_TEXTURE_2D, 1, 1, + PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET + ); + + *is_supported &= pscreen->is_video_format_supported + ( + pscreen, ycbcr_format, + PIPE_VIDEO_PROFILE_UNKNOWN, + PIPE_VIDEO_ENTRYPOINT_BITSTREAM + ); + mtx_unlock(&dev->mutex); + + return VDP_STATUS_OK; +} + +/** + * Query the implementation's VdpBitmapSurface capabilities. + */ +VdpStatus +vlVdpBitmapSurfaceQueryCapabilities(VdpDevice device, VdpRGBAFormat surface_rgba_format, + VdpBool *is_supported, uint32_t *max_width, uint32_t *max_height) +{ + vlVdpDevice *dev; + struct pipe_screen *pscreen; + enum pipe_format format; + + dev = vlGetDataHTAB(device); + if (!dev) + return VDP_STATUS_INVALID_HANDLE; + + pscreen = dev->vscreen->pscreen; + if (!pscreen) + return VDP_STATUS_RESOURCES; + + format = VdpFormatRGBAToPipe(surface_rgba_format); + if (format == PIPE_FORMAT_NONE) + return VDP_STATUS_INVALID_RGBA_FORMAT; + + if (!(is_supported && max_width && max_height)) + return VDP_STATUS_INVALID_POINTER; + + mtx_lock(&dev->mutex); + *is_supported = pscreen->is_format_supported + ( + pscreen, format, PIPE_TEXTURE_2D, 1, 1, + PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET + ); + if (*is_supported) { + uint32_t max_2d_texture_size = pscreen->get_param( + pscreen, PIPE_CAP_MAX_TEXTURE_2D_SIZE); + + if (!max_2d_texture_size) { + mtx_unlock(&dev->mutex); + return VDP_STATUS_ERROR; + } + + *max_width = *max_height = max_2d_texture_size; + } else { + *max_width = 0; + *max_height = 0; + } + mtx_unlock(&dev->mutex); + + return VDP_STATUS_OK; +} + +/** + * Query the implementation's support for a specific feature. + */ +VdpStatus +vlVdpVideoMixerQueryFeatureSupport(VdpDevice device, VdpVideoMixerFeature feature, + VdpBool *is_supported) +{ + if (!is_supported) + return VDP_STATUS_INVALID_POINTER; + + switch (feature) { + case VDP_VIDEO_MIXER_FEATURE_SHARPNESS: + case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION: + case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL: + case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY: + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1: + *is_supported = VDP_TRUE; + break; + default: + *is_supported = VDP_FALSE; + break; + } + return VDP_STATUS_OK; +} + +/** + * Query the implementation's support for a specific parameter. + */ +VdpStatus +vlVdpVideoMixerQueryParameterSupport(VdpDevice device, VdpVideoMixerParameter parameter, + VdpBool *is_supported) +{ + if (!is_supported) + return VDP_STATUS_INVALID_POINTER; + + switch (parameter) { + case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH: + case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT: + case VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE: + case VDP_VIDEO_MIXER_PARAMETER_LAYERS: + *is_supported = VDP_TRUE; + break; + default: + *is_supported = VDP_FALSE; + break; + } + return VDP_STATUS_OK; +} + +/** + * Query the implementation's supported for a specific parameter. + */ +VdpStatus +vlVdpVideoMixerQueryParameterValueRange(VdpDevice device, VdpVideoMixerParameter parameter, + void *min_value, void *max_value) +{ + vlVdpDevice *dev = vlGetDataHTAB(device); + struct pipe_screen *screen; + + if (!dev) + return VDP_STATUS_INVALID_HANDLE; + if (!(min_value && max_value)) + return VDP_STATUS_INVALID_POINTER; + + mtx_lock(&dev->mutex); + screen = dev->vscreen->pscreen; + switch (parameter) { + case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH: + *(uint32_t*)min_value = 48; + *(uint32_t*)max_value = screen->get_video_param(screen, PIPE_VIDEO_PROFILE_UNKNOWN, + PIPE_VIDEO_ENTRYPOINT_BITSTREAM, + PIPE_VIDEO_CAP_MAX_WIDTH); + break; + case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT: + *(uint32_t*)min_value = 48; + *(uint32_t*)max_value = screen->get_video_param(screen, PIPE_VIDEO_PROFILE_UNKNOWN, + PIPE_VIDEO_ENTRYPOINT_BITSTREAM, + PIPE_VIDEO_CAP_MAX_HEIGHT); + break; + + case VDP_VIDEO_MIXER_PARAMETER_LAYERS: + *(uint32_t*)min_value = 0; + *(uint32_t*)max_value = 4; + break; + + case VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE: + default: + mtx_unlock(&dev->mutex); + return VDP_STATUS_INVALID_VIDEO_MIXER_PARAMETER; + } + mtx_unlock(&dev->mutex); + return VDP_STATUS_OK; +} + +/** + * Query the implementation's support for a specific attribute. + */ +VdpStatus +vlVdpVideoMixerQueryAttributeSupport(VdpDevice device, VdpVideoMixerAttribute attribute, + VdpBool *is_supported) +{ + if (!is_supported) + return VDP_STATUS_INVALID_POINTER; + + switch (attribute) { + case VDP_VIDEO_MIXER_ATTRIBUTE_BACKGROUND_COLOR: + case VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX: + case VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL: + case VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL: + case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MIN_LUMA: + case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MAX_LUMA: + case VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE: + *is_supported = VDP_TRUE; + break; + default: + *is_supported = VDP_FALSE; + } + return VDP_STATUS_OK; +} + +/** + * Query the implementation's supported for a specific attribute. + */ +VdpStatus +vlVdpVideoMixerQueryAttributeValueRange(VdpDevice device, VdpVideoMixerAttribute attribute, + void *min_value, void *max_value) +{ + if (!(min_value && max_value)) + return VDP_STATUS_INVALID_POINTER; + + switch (attribute) { + case VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL: + case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MIN_LUMA: + case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MAX_LUMA: + *(float*)min_value = 0.0f; + *(float*)max_value = 1.0f; + break; + case VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL: + *(float*)min_value = -1.0f; + *(float*)max_value = 1.0f; + break; + case VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE: + *(uint8_t*)min_value = 0; + *(uint8_t*)max_value = 1; + break; + case VDP_VIDEO_MIXER_ATTRIBUTE_BACKGROUND_COLOR: + case VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX: + default: + return VDP_STATUS_INVALID_VIDEO_MIXER_ATTRIBUTE; + } + return VDP_STATUS_OK; +} diff --git a/src/gallium/frontends/vdpau/surface.c b/src/gallium/frontends/vdpau/surface.c new file mode 100644 index 00000000000..bce4400b0ee --- /dev/null +++ b/src/gallium/frontends/vdpau/surface.c @@ -0,0 +1,554 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen. + * Copyright 2011 Christian König. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include + +#include "pipe/p_state.h" + +#include "util/u_memory.h" +#include "util/u_debug.h" +#include "util/u_rect.h" +#include "util/u_surface.h" +#include "util/u_video.h" +#include "vl/vl_defines.h" + +#include "frontend/drm_driver.h" + +#include "vdpau_private.h" + +enum getbits_conversion { + CONVERSION_NONE, + CONVERSION_NV12_TO_YV12, + CONVERSION_YV12_TO_NV12, + CONVERSION_SWAP_YUYV_UYVY, +}; + +/** + * Create a VdpVideoSurface. + */ +VdpStatus +vlVdpVideoSurfaceCreate(VdpDevice device, VdpChromaType chroma_type, + uint32_t width, uint32_t height, + VdpVideoSurface *surface) +{ + struct pipe_context *pipe; + vlVdpSurface *p_surf; + VdpStatus ret; + + if (!(width && height)) { + ret = VDP_STATUS_INVALID_SIZE; + goto inv_size; + } + + p_surf = CALLOC(1, sizeof(vlVdpSurface)); + if (!p_surf) { + ret = VDP_STATUS_RESOURCES; + goto no_res; + } + + vlVdpDevice *dev = vlGetDataHTAB(device); + if (!dev) { + ret = VDP_STATUS_INVALID_HANDLE; + goto inv_device; + } + + DeviceReference(&p_surf->device, dev); + pipe = dev->context; + + mtx_lock(&dev->mutex); + memset(&p_surf->templat, 0, sizeof(p_surf->templat)); + /* TODO: buffer_format should be selected to match chroma_type */ + p_surf->templat.buffer_format = pipe->screen->get_video_param + ( + pipe->screen, + PIPE_VIDEO_PROFILE_UNKNOWN, + PIPE_VIDEO_ENTRYPOINT_BITSTREAM, + PIPE_VIDEO_CAP_PREFERED_FORMAT + ); + p_surf->templat.width = width; + p_surf->templat.height = height; + p_surf->templat.interlaced = pipe->screen->get_video_param + ( + pipe->screen, + PIPE_VIDEO_PROFILE_UNKNOWN, + PIPE_VIDEO_ENTRYPOINT_BITSTREAM, + PIPE_VIDEO_CAP_PREFERS_INTERLACED + ); + if (p_surf->templat.buffer_format != PIPE_FORMAT_NONE) + p_surf->video_buffer = pipe->create_video_buffer(pipe, &p_surf->templat); + + /* do not mandate early allocation of a video buffer */ + vlVdpVideoSurfaceClear(p_surf); + mtx_unlock(&dev->mutex); + + *surface = vlAddDataHTAB(p_surf); + if (*surface == 0) { + ret = VDP_STATUS_ERROR; + goto no_handle; + } + + return VDP_STATUS_OK; + +no_handle: + p_surf->video_buffer->destroy(p_surf->video_buffer); + +inv_device: + DeviceReference(&p_surf->device, NULL); + FREE(p_surf); + +no_res: +inv_size: + return ret; +} + +/** + * Destroy a VdpVideoSurface. + */ +VdpStatus +vlVdpVideoSurfaceDestroy(VdpVideoSurface surface) +{ + vlVdpSurface *p_surf; + + p_surf = (vlVdpSurface *)vlGetDataHTAB((vlHandle)surface); + if (!p_surf) + return VDP_STATUS_INVALID_HANDLE; + + mtx_lock(&p_surf->device->mutex); + if (p_surf->video_buffer) + p_surf->video_buffer->destroy(p_surf->video_buffer); + mtx_unlock(&p_surf->device->mutex); + + vlRemoveDataHTAB(surface); + DeviceReference(&p_surf->device, NULL); + FREE(p_surf); + + return VDP_STATUS_OK; +} + +/** + * Retrieve the parameters used to create a VdpVideoSurface. + */ +VdpStatus +vlVdpVideoSurfaceGetParameters(VdpVideoSurface surface, + VdpChromaType *chroma_type, + uint32_t *width, uint32_t *height) +{ + if (!(width && height && chroma_type)) + return VDP_STATUS_INVALID_POINTER; + + vlVdpSurface *p_surf = vlGetDataHTAB(surface); + if (!p_surf) + return VDP_STATUS_INVALID_HANDLE; + + if (p_surf->video_buffer) { + *width = p_surf->video_buffer->width; + *height = p_surf->video_buffer->height; + *chroma_type = PipeToChroma(pipe_format_to_chroma_format(p_surf->video_buffer->buffer_format)); + } else { + *width = p_surf->templat.width; + *height = p_surf->templat.height; + *chroma_type = PipeToChroma(pipe_format_to_chroma_format(p_surf->templat.buffer_format)); + } + + return VDP_STATUS_OK; +} + +static void +vlVdpVideoSurfaceSize(vlVdpSurface *p_surf, int component, + unsigned *width, unsigned *height) +{ + *width = p_surf->templat.width; + *height = p_surf->templat.height; + + vl_video_buffer_adjust_size(width, height, component, + pipe_format_to_chroma_format(p_surf->templat.buffer_format), + p_surf->templat.interlaced); +} + +/** + * Copy image data from a VdpVideoSurface to application memory in a specified + * YCbCr format. + */ +VdpStatus +vlVdpVideoSurfaceGetBitsYCbCr(VdpVideoSurface surface, + VdpYCbCrFormat destination_ycbcr_format, + void *const *destination_data, + uint32_t const *destination_pitches) +{ + vlVdpSurface *vlsurface; + struct pipe_context *pipe; + enum pipe_format format, buffer_format; + struct pipe_sampler_view **sampler_views; + enum getbits_conversion conversion = CONVERSION_NONE; + unsigned i, j; + + vlsurface = vlGetDataHTAB(surface); + if (!vlsurface) + return VDP_STATUS_INVALID_HANDLE; + + pipe = vlsurface->device->context; + if (!pipe) + return VDP_STATUS_INVALID_HANDLE; + + if (!destination_data || !destination_pitches) + return VDP_STATUS_INVALID_POINTER; + + format = FormatYCBCRToPipe(destination_ycbcr_format); + if (format == PIPE_FORMAT_NONE) + return VDP_STATUS_INVALID_Y_CB_CR_FORMAT; + + if (vlsurface->video_buffer == NULL) + return VDP_STATUS_INVALID_VALUE; + + buffer_format = vlsurface->video_buffer->buffer_format; + if (format != buffer_format) { + if (format == PIPE_FORMAT_YV12 && buffer_format == PIPE_FORMAT_NV12) + conversion = CONVERSION_NV12_TO_YV12; + else if (format == PIPE_FORMAT_NV12 && buffer_format == PIPE_FORMAT_YV12) + conversion = CONVERSION_YV12_TO_NV12; + else if ((format == PIPE_FORMAT_YUYV && buffer_format == PIPE_FORMAT_UYVY) || + (format == PIPE_FORMAT_UYVY && buffer_format == PIPE_FORMAT_YUYV)) + conversion = CONVERSION_SWAP_YUYV_UYVY; + else + return VDP_STATUS_NO_IMPLEMENTATION; + } + + mtx_lock(&vlsurface->device->mutex); + sampler_views = vlsurface->video_buffer->get_sampler_view_planes(vlsurface->video_buffer); + if (!sampler_views) { + mtx_unlock(&vlsurface->device->mutex); + return VDP_STATUS_RESOURCES; + } + + for (i = 0; i < 3; ++i) { + unsigned width, height; + struct pipe_sampler_view *sv = sampler_views[i]; + if (!sv) continue; + + vlVdpVideoSurfaceSize(vlsurface, i, &width, &height); + + for (j = 0; j < sv->texture->array_size; ++j) { + struct pipe_box box = { + 0, 0, j, + width, height, 1 + }; + struct pipe_transfer *transfer; + uint8_t *map; + + map = pipe->transfer_map(pipe, sv->texture, 0, + PIPE_TRANSFER_READ, &box, &transfer); + if (!map) { + mtx_unlock(&vlsurface->device->mutex); + return VDP_STATUS_RESOURCES; + } + + if (conversion == CONVERSION_NV12_TO_YV12 && i == 1) { + u_copy_nv12_to_yv12(destination_data, destination_pitches, + i, j, transfer->stride, sv->texture->array_size, + map, box.width, box.height); + } else if (conversion == CONVERSION_YV12_TO_NV12 && i > 0) { + u_copy_yv12_to_nv12(destination_data, destination_pitches, + i, j, transfer->stride, sv->texture->array_size, + map, box.width, box.height); + } else if (conversion == CONVERSION_SWAP_YUYV_UYVY) { + u_copy_swap422_packed(destination_data, destination_pitches, + i, j, transfer->stride, sv->texture->array_size, + map, box.width, box.height); + } else { + util_copy_rect(destination_data[i] + destination_pitches[i] * j, sv->texture->format, + destination_pitches[i] * sv->texture->array_size, 0, 0, + box.width, box.height, map, transfer->stride, 0, 0); + } + + pipe_transfer_unmap(pipe, transfer); + } + } + mtx_unlock(&vlsurface->device->mutex); + + return VDP_STATUS_OK; +} + +/** + * Copy image data from application memory in a specific YCbCr format to + * a VdpVideoSurface. + */ +VdpStatus +vlVdpVideoSurfacePutBitsYCbCr(VdpVideoSurface surface, + VdpYCbCrFormat source_ycbcr_format, + void const *const *source_data, + uint32_t const *source_pitches) +{ + enum pipe_format pformat = FormatYCBCRToPipe(source_ycbcr_format); + enum getbits_conversion conversion = CONVERSION_NONE; + struct pipe_context *pipe; + struct pipe_sampler_view **sampler_views; + unsigned i, j; + unsigned usage = PIPE_TRANSFER_WRITE; + + vlVdpSurface *p_surf = vlGetDataHTAB(surface); + if (!p_surf) + return VDP_STATUS_INVALID_HANDLE; + + pipe = p_surf->device->context; + if (!pipe) + return VDP_STATUS_INVALID_HANDLE; + + if (!source_data || !source_pitches) + return VDP_STATUS_INVALID_POINTER; + + mtx_lock(&p_surf->device->mutex); + + if (p_surf->video_buffer == NULL || + ((pformat != p_surf->video_buffer->buffer_format))) { + enum pipe_format nformat = pformat; + struct pipe_screen *screen = pipe->screen; + + /* Determine the most suitable format for the new surface */ + if (!screen->is_video_format_supported(screen, nformat, + PIPE_VIDEO_PROFILE_UNKNOWN, + PIPE_VIDEO_ENTRYPOINT_BITSTREAM)) { + nformat = screen->get_video_param(screen, + PIPE_VIDEO_PROFILE_UNKNOWN, + PIPE_VIDEO_ENTRYPOINT_BITSTREAM, + PIPE_VIDEO_CAP_PREFERED_FORMAT); + if (nformat == PIPE_FORMAT_NONE) { + mtx_unlock(&p_surf->device->mutex); + return VDP_STATUS_NO_IMPLEMENTATION; + } + } + + if (p_surf->video_buffer == NULL || + nformat != p_surf->video_buffer->buffer_format) { + /* destroy the old one */ + if (p_surf->video_buffer) + p_surf->video_buffer->destroy(p_surf->video_buffer); + + /* adjust the template parameters */ + p_surf->templat.buffer_format = nformat; + if (nformat == PIPE_FORMAT_YUYV || nformat == PIPE_FORMAT_UYVY) + p_surf->templat.interlaced = false; + + /* and try to create the video buffer with the new format */ + p_surf->video_buffer = pipe->create_video_buffer(pipe, &p_surf->templat); + + /* stil no luck? ok forget it we don't support it */ + if (!p_surf->video_buffer) { + mtx_unlock(&p_surf->device->mutex); + return VDP_STATUS_NO_IMPLEMENTATION; + } + vlVdpVideoSurfaceClear(p_surf); + } + } + + if (pformat != p_surf->video_buffer->buffer_format) { + if (pformat == PIPE_FORMAT_YV12 && + p_surf->video_buffer->buffer_format == PIPE_FORMAT_NV12) + conversion = CONVERSION_YV12_TO_NV12; + else { + mtx_unlock(&p_surf->device->mutex); + return VDP_STATUS_NO_IMPLEMENTATION; + } + } + + sampler_views = p_surf->video_buffer->get_sampler_view_planes(p_surf->video_buffer); + if (!sampler_views) { + mtx_unlock(&p_surf->device->mutex); + return VDP_STATUS_RESOURCES; + } + + for (i = 0; i < 3; ++i) { + unsigned width, height; + struct pipe_sampler_view *sv = sampler_views[i]; + struct pipe_resource *tex; + if (!sv || !source_pitches[i]) continue; + + tex = sv->texture; + vlVdpVideoSurfaceSize(p_surf, i, &width, &height); + + for (j = 0; j < tex->array_size; ++j) { + struct pipe_box dst_box = { + 0, 0, j, + width, height, 1 + }; + + if (conversion == CONVERSION_YV12_TO_NV12 && i == 1) { + struct pipe_transfer *transfer; + uint8_t *map; + + map = pipe->transfer_map(pipe, tex, 0, usage, + &dst_box, &transfer); + if (!map) { + mtx_unlock(&p_surf->device->mutex); + return VDP_STATUS_RESOURCES; + } + + u_copy_nv12_from_yv12(source_data, source_pitches, + i, j, transfer->stride, tex->array_size, + map, dst_box.width, dst_box.height); + + pipe_transfer_unmap(pipe, transfer); + } else { + pipe->texture_subdata(pipe, tex, 0, + PIPE_TRANSFER_WRITE, &dst_box, + source_data[i] + source_pitches[i] * j, + source_pitches[i] * tex->array_size, + 0); + } + /* + * This surface has already been synced + * by the first map. + */ + usage |= PIPE_TRANSFER_UNSYNCHRONIZED; + } + } + mtx_unlock(&p_surf->device->mutex); + + return VDP_STATUS_OK; +} + +/** + * Helper function to initially clear the VideoSurface after (re-)creation + */ +void +vlVdpVideoSurfaceClear(vlVdpSurface *vlsurf) +{ + struct pipe_context *pipe = vlsurf->device->context; + struct pipe_surface **surfaces; + unsigned i; + + if (!vlsurf->video_buffer) + return; + + surfaces = vlsurf->video_buffer->get_surfaces(vlsurf->video_buffer); + for (i = 0; i < VL_MAX_SURFACES; ++i) { + union pipe_color_union c = {}; + + if (!surfaces[i]) + continue; + + if (i > !!vlsurf->templat.interlaced) + c.f[0] = c.f[1] = c.f[2] = c.f[3] = 0.5f; + + pipe->clear_render_target(pipe, surfaces[i], &c, 0, 0, + surfaces[i]->width, surfaces[i]->height, false); + } + pipe->flush(pipe, NULL, 0); +} + +/** + * Interop to mesa state tracker + */ +struct pipe_video_buffer *vlVdpVideoSurfaceGallium(VdpVideoSurface surface) +{ + vlVdpSurface *p_surf = vlGetDataHTAB(surface); + if (!p_surf) + return NULL; + + mtx_lock(&p_surf->device->mutex); + if (p_surf->video_buffer == NULL) { + struct pipe_context *pipe = p_surf->device->context; + + /* try to create a video buffer if we don't already have one */ + p_surf->video_buffer = pipe->create_video_buffer(pipe, &p_surf->templat); + } + mtx_unlock(&p_surf->device->mutex); + + return p_surf->video_buffer; +} + +VdpStatus vlVdpVideoSurfaceDMABuf(VdpVideoSurface surface, + VdpVideoSurfacePlane plane, + struct VdpSurfaceDMABufDesc *result) +{ + vlVdpSurface *p_surf = vlGetDataHTAB(surface); + + struct pipe_screen *pscreen; + struct winsys_handle whandle; + + struct pipe_surface *surf; + + if (!p_surf) + return VDP_STATUS_INVALID_HANDLE; + + if (plane > 3) + return VDP_STATUS_INVALID_VALUE; + + if (!result) + return VDP_STATUS_INVALID_POINTER; + + memset(result, 0, sizeof(*result)); + result->handle = -1; + + mtx_lock(&p_surf->device->mutex); + if (p_surf->video_buffer == NULL) { + struct pipe_context *pipe = p_surf->device->context; + + /* try to create a video buffer if we don't already have one */ + p_surf->video_buffer = pipe->create_video_buffer(pipe, &p_surf->templat); + } + + /* Check if surface match interop requirements */ + if (p_surf->video_buffer == NULL || !p_surf->video_buffer->interlaced || + p_surf->video_buffer->buffer_format != PIPE_FORMAT_NV12) { + mtx_unlock(&p_surf->device->mutex); + return VDP_STATUS_NO_IMPLEMENTATION; + } + + surf = p_surf->video_buffer->get_surfaces(p_surf->video_buffer)[plane]; + if (!surf) { + mtx_unlock(&p_surf->device->mutex); + return VDP_STATUS_RESOURCES; + } + + memset(&whandle, 0, sizeof(struct winsys_handle)); + whandle.type = WINSYS_HANDLE_TYPE_FD; + whandle.layer = surf->u.tex.first_layer; + + pscreen = surf->texture->screen; + if (!pscreen->resource_get_handle(pscreen, p_surf->device->context, + surf->texture, &whandle, + PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE)) { + mtx_unlock(&p_surf->device->mutex); + return VDP_STATUS_NO_IMPLEMENTATION; + } + + mtx_unlock(&p_surf->device->mutex); + + result->handle = whandle.handle; + result->width = surf->width; + result->height = surf->height; + result->offset = whandle.offset; + result->stride = whandle.stride; + + if (surf->format == PIPE_FORMAT_R8_UNORM) + result->format = VDP_RGBA_FORMAT_R8; + else + result->format = VDP_RGBA_FORMAT_R8G8; + + return VDP_STATUS_OK; +} diff --git a/src/gallium/frontends/vdpau/vdpau_private.h b/src/gallium/frontends/vdpau/vdpau_private.h new file mode 100644 index 00000000000..1f46f31a549 --- /dev/null +++ b/src/gallium/frontends/vdpau/vdpau_private.h @@ -0,0 +1,586 @@ +/************************************************************************** + * + * Copyright 2010 Younes Manton & Thomas Balling Sørensen. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef VDPAU_PRIVATE_H +#define VDPAU_PRIVATE_H + +#include + +#include +#include + +#include "pipe/p_compiler.h" +#include "pipe/p_video_codec.h" + +#include "frontend/vdpau_interop.h" +#include "frontend/vdpau_dmabuf.h" +#include "frontend/vdpau_funcs.h" + +#include "util/u_debug.h" +#include "util/u_rect.h" +#include "os/os_thread.h" + +#include "vl/vl_video_buffer.h" +#include "vl/vl_bicubic_filter.h" +#include "vl/vl_compositor.h" +#include "vl/vl_csc.h" +#include "vl/vl_deint_filter.h" +#include "vl/vl_matrix_filter.h" +#include "vl/vl_median_filter.h" +#include "vl/vl_winsys.h" + +/* Full VDPAU API documentation available at : + * ftp://download.nvidia.com/XFree86/vdpau/doxygen/html/index.html */ + +#define INFORMATION G3DVL VDPAU Driver Shared Library version VER_MAJOR.VER_MINOR +#define QUOTEME(x) #x +#define TOSTRING(x) QUOTEME(x) +#define INFORMATION_STRING TOSTRING(INFORMATION) + +static inline enum pipe_video_chroma_format +ChromaToPipe(VdpChromaType vdpau_type) +{ + switch (vdpau_type) { + case VDP_CHROMA_TYPE_420: + return PIPE_VIDEO_CHROMA_FORMAT_420; + case VDP_CHROMA_TYPE_422: + return PIPE_VIDEO_CHROMA_FORMAT_422; + case VDP_CHROMA_TYPE_444: + return PIPE_VIDEO_CHROMA_FORMAT_444; + default: + assert(0); + } + + return -1; +} + +static inline VdpChromaType +PipeToChroma(enum pipe_video_chroma_format pipe_type) +{ + switch (pipe_type) { + case PIPE_VIDEO_CHROMA_FORMAT_420: + return VDP_CHROMA_TYPE_420; + case PIPE_VIDEO_CHROMA_FORMAT_422: + return VDP_CHROMA_TYPE_422; + case PIPE_VIDEO_CHROMA_FORMAT_444: + return VDP_CHROMA_TYPE_444; + default: + assert(0); + } + + return -1; +} + +static inline enum pipe_video_chroma_format +FormatYCBCRToPipeChroma(VdpYCbCrFormat vdpau_format) +{ + switch (vdpau_format) { + case VDP_YCBCR_FORMAT_NV12: + return PIPE_VIDEO_CHROMA_FORMAT_420; + case VDP_YCBCR_FORMAT_YV12: + return PIPE_VIDEO_CHROMA_FORMAT_420; + case VDP_YCBCR_FORMAT_UYVY: + return PIPE_VIDEO_CHROMA_FORMAT_422; + case VDP_YCBCR_FORMAT_YUYV: + return PIPE_VIDEO_CHROMA_FORMAT_422; + case VDP_YCBCR_FORMAT_Y8U8V8A8: + return PIPE_VIDEO_CHROMA_FORMAT_444; + case VDP_YCBCR_FORMAT_V8U8Y8A8: + return PIPE_VIDEO_CHROMA_FORMAT_444; + default: + assert(0); + } + + return PIPE_FORMAT_NONE; +} + +static inline enum pipe_format +FormatYCBCRToPipe(VdpYCbCrFormat vdpau_format) +{ + switch (vdpau_format) { + case VDP_YCBCR_FORMAT_NV12: + return PIPE_FORMAT_NV12; + case VDP_YCBCR_FORMAT_YV12: + return PIPE_FORMAT_YV12; + case VDP_YCBCR_FORMAT_UYVY: + return PIPE_FORMAT_UYVY; + case VDP_YCBCR_FORMAT_YUYV: + return PIPE_FORMAT_YUYV; + case VDP_YCBCR_FORMAT_Y8U8V8A8: + return PIPE_FORMAT_R8G8B8A8_UNORM; + case VDP_YCBCR_FORMAT_V8U8Y8A8: + return PIPE_FORMAT_B8G8R8A8_UNORM; +#ifdef VDP_YCBCR_FORMAT_P010 + case VDP_YCBCR_FORMAT_P010: + return PIPE_FORMAT_P010; +#endif +#ifdef VDP_YCBCR_FORMAT_P016 + case VDP_YCBCR_FORMAT_P016: + return PIPE_FORMAT_P016; +#endif + default: + /* NOTE: Can't be "unreachable", as it's quite reachable. */ + assert(!"unexpected VdpYCbCrFormat"); + /* fallthrough */ +#ifdef VDP_YCBCR_FORMAT_Y_UV_444 + case VDP_YCBCR_FORMAT_Y_UV_444: +#endif +#ifdef VDP_YCBCR_FORMAT_Y_U_V_444 + case VDP_YCBCR_FORMAT_Y_U_V_444: +#endif +#ifdef VDP_YCBCR_FORMAT_Y_U_V_444_16 + case VDP_YCBCR_FORMAT_Y_U_V_444_16: +#endif + return PIPE_FORMAT_NONE; + } + +} + +static inline VdpYCbCrFormat +PipeToFormatYCBCR(enum pipe_format p_format) +{ + switch (p_format) { + case PIPE_FORMAT_NV12: + return VDP_YCBCR_FORMAT_NV12; + case PIPE_FORMAT_YV12: + return VDP_YCBCR_FORMAT_YV12; + case PIPE_FORMAT_UYVY: + return VDP_YCBCR_FORMAT_UYVY; + case PIPE_FORMAT_YUYV: + return VDP_YCBCR_FORMAT_YUYV; + case PIPE_FORMAT_R8G8B8A8_UNORM: + return VDP_YCBCR_FORMAT_Y8U8V8A8; + case PIPE_FORMAT_B8G8R8A8_UNORM: + return VDP_YCBCR_FORMAT_V8U8Y8A8; + default: + assert(0); + } + + return -1; +} + +static inline VdpRGBAFormat +PipeToFormatRGBA(enum pipe_format p_format) +{ + switch (p_format) { + case PIPE_FORMAT_A8_UNORM: + return VDP_RGBA_FORMAT_A8; + case PIPE_FORMAT_B10G10R10A2_UNORM: + return VDP_RGBA_FORMAT_B10G10R10A2; + case PIPE_FORMAT_B8G8R8A8_UNORM: + return VDP_RGBA_FORMAT_B8G8R8A8; + case PIPE_FORMAT_R10G10B10A2_UNORM: + return VDP_RGBA_FORMAT_R10G10B10A2; + case PIPE_FORMAT_R8G8B8A8_UNORM: + return VDP_RGBA_FORMAT_R8G8B8A8; + default: + assert(0); + } + + return -1; +} + +static inline enum pipe_format +FormatIndexedToPipe(VdpRGBAFormat vdpau_format) +{ + switch (vdpau_format) { + case VDP_INDEXED_FORMAT_A4I4: + return PIPE_FORMAT_R4A4_UNORM; + case VDP_INDEXED_FORMAT_I4A4: + return PIPE_FORMAT_A4R4_UNORM; + case VDP_INDEXED_FORMAT_A8I8: + return PIPE_FORMAT_A8R8_UNORM; + case VDP_INDEXED_FORMAT_I8A8: + return PIPE_FORMAT_R8A8_UNORM; + default: + assert(0); + } + + return PIPE_FORMAT_NONE; +} + +static inline enum pipe_format +FormatColorTableToPipe(VdpColorTableFormat vdpau_format) +{ + switch(vdpau_format) { + case VDP_COLOR_TABLE_FORMAT_B8G8R8X8: + return PIPE_FORMAT_B8G8R8X8_UNORM; + default: + assert(0); + } + + return PIPE_FORMAT_NONE; +} + +static inline enum pipe_video_profile +ProfileToPipe(VdpDecoderProfile vdpau_profile) +{ + switch (vdpau_profile) { + case VDP_DECODER_PROFILE_MPEG1: + return PIPE_VIDEO_PROFILE_MPEG1; + case VDP_DECODER_PROFILE_MPEG2_SIMPLE: + return PIPE_VIDEO_PROFILE_MPEG2_SIMPLE; + case VDP_DECODER_PROFILE_MPEG2_MAIN: + return PIPE_VIDEO_PROFILE_MPEG2_MAIN; + case VDP_DECODER_PROFILE_H264_BASELINE: + return PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE; + case VDP_DECODER_PROFILE_H264_CONSTRAINED_BASELINE: + return PIPE_VIDEO_PROFILE_MPEG4_AVC_CONSTRAINED_BASELINE; + case VDP_DECODER_PROFILE_H264_MAIN: + return PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN; + case VDP_DECODER_PROFILE_H264_HIGH: + return PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH; + case VDP_DECODER_PROFILE_MPEG4_PART2_SP: + return PIPE_VIDEO_PROFILE_MPEG4_SIMPLE; + case VDP_DECODER_PROFILE_MPEG4_PART2_ASP: + return PIPE_VIDEO_PROFILE_MPEG4_ADVANCED_SIMPLE; + case VDP_DECODER_PROFILE_VC1_SIMPLE: + return PIPE_VIDEO_PROFILE_VC1_SIMPLE; + case VDP_DECODER_PROFILE_VC1_MAIN: + return PIPE_VIDEO_PROFILE_VC1_MAIN; + case VDP_DECODER_PROFILE_VC1_ADVANCED: + return PIPE_VIDEO_PROFILE_VC1_ADVANCED; + case VDP_DECODER_PROFILE_HEVC_MAIN: + return PIPE_VIDEO_PROFILE_HEVC_MAIN; + case VDP_DECODER_PROFILE_HEVC_MAIN_10: + return PIPE_VIDEO_PROFILE_HEVC_MAIN_10; + case VDP_DECODER_PROFILE_HEVC_MAIN_STILL: + return PIPE_VIDEO_PROFILE_HEVC_MAIN_STILL; + case VDP_DECODER_PROFILE_HEVC_MAIN_12: + return PIPE_VIDEO_PROFILE_HEVC_MAIN_12; + case VDP_DECODER_PROFILE_HEVC_MAIN_444: + return PIPE_VIDEO_PROFILE_HEVC_MAIN_444; + default: + return PIPE_VIDEO_PROFILE_UNKNOWN; + } +} + +static inline VdpDecoderProfile +PipeToProfile(enum pipe_video_profile p_profile) +{ + switch (p_profile) { + case PIPE_VIDEO_PROFILE_MPEG1: + return VDP_DECODER_PROFILE_MPEG1; + case PIPE_VIDEO_PROFILE_MPEG2_SIMPLE: + return VDP_DECODER_PROFILE_MPEG2_SIMPLE; + case PIPE_VIDEO_PROFILE_MPEG2_MAIN: + return VDP_DECODER_PROFILE_MPEG2_MAIN; + case PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE: + return VDP_DECODER_PROFILE_H264_BASELINE; + case PIPE_VIDEO_PROFILE_MPEG4_AVC_CONSTRAINED_BASELINE: + return VDP_DECODER_PROFILE_H264_CONSTRAINED_BASELINE; + case PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN: + return VDP_DECODER_PROFILE_H264_MAIN; + case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH: + return VDP_DECODER_PROFILE_H264_HIGH; + case PIPE_VIDEO_PROFILE_MPEG4_SIMPLE: + return VDP_DECODER_PROFILE_MPEG4_PART2_SP; + case PIPE_VIDEO_PROFILE_MPEG4_ADVANCED_SIMPLE: + return VDP_DECODER_PROFILE_MPEG4_PART2_ASP; + case PIPE_VIDEO_PROFILE_VC1_SIMPLE: + return VDP_DECODER_PROFILE_VC1_SIMPLE; + case PIPE_VIDEO_PROFILE_VC1_MAIN: + return VDP_DECODER_PROFILE_VC1_MAIN; + case PIPE_VIDEO_PROFILE_VC1_ADVANCED: + return VDP_DECODER_PROFILE_VC1_ADVANCED; + case PIPE_VIDEO_PROFILE_HEVC_MAIN: + return VDP_DECODER_PROFILE_HEVC_MAIN; + case PIPE_VIDEO_PROFILE_HEVC_MAIN_10: + return VDP_DECODER_PROFILE_HEVC_MAIN_10; + case PIPE_VIDEO_PROFILE_HEVC_MAIN_STILL: + return VDP_DECODER_PROFILE_HEVC_MAIN_STILL; + case PIPE_VIDEO_PROFILE_HEVC_MAIN_12: + return VDP_DECODER_PROFILE_HEVC_MAIN_12; + case PIPE_VIDEO_PROFILE_HEVC_MAIN_444: + return VDP_DECODER_PROFILE_HEVC_MAIN_444; + default: + assert(0); + return -1; + } +} + +static inline struct u_rect * +RectToPipe(const VdpRect *src, struct u_rect *dst) +{ + if (src) { + dst->x0 = src->x0; + dst->y0 = src->y0; + dst->x1 = src->x1; + dst->y1 = src->y1; + return dst; + } + return NULL; +} + +static inline struct pipe_box +RectToPipeBox(const VdpRect *rect, struct pipe_resource *res) +{ + struct pipe_box box; + + box.x = 0; + box.y = 0; + box.z = 0; + box.width = res->width0; + box.height = res->height0; + box.depth = 1; + + if (rect) { + box.x = MIN2(rect->x0, rect->x1); + box.y = MIN2(rect->y0, rect->y1); + box.width = abs(rect->x1 - rect->x0); + box.height = abs(rect->y1 - rect->y0); + } + + return box; +} + +static inline bool +CheckSurfaceParams(struct pipe_screen *screen, + const struct pipe_resource *templ) +{ + return screen->is_format_supported(screen, templ->format, templ->target, + templ->nr_samples, + templ->nr_storage_samples, templ->bind); +} + +typedef struct +{ + struct pipe_reference reference; + struct vl_screen *vscreen; + struct pipe_context *context; + struct vl_compositor compositor; + struct pipe_sampler_view *dummy_sv; + mtx_t mutex; +} vlVdpDevice; + +typedef struct +{ + vlVdpDevice *device; + struct vl_compositor_state cstate; + + struct { + bool supported, enabled; + float luma_min, luma_max; + } luma_key; + + struct { + bool supported, enabled, spatial; + struct vl_deint_filter *filter; + } deint; + + struct { + bool supported, enabled; + struct vl_bicubic_filter *filter; + } bicubic; + + struct { + bool supported, enabled; + unsigned level; + struct vl_median_filter *filter; + } noise_reduction; + + struct { + bool supported, enabled; + float value; + struct vl_matrix_filter *filter; + } sharpness; + + unsigned video_width, video_height; + enum pipe_video_chroma_format chroma_format; + unsigned max_layers, skip_chroma_deint; + + bool custom_csc; + vl_csc_matrix csc; +} vlVdpVideoMixer; + +typedef struct +{ + vlVdpDevice *device; + struct pipe_video_buffer templat, *video_buffer; +} vlVdpSurface; + +typedef struct +{ + vlVdpDevice *device; + struct pipe_sampler_view *sampler_view; +} vlVdpBitmapSurface; + +typedef uint64_t vlVdpTime; + +typedef struct +{ + vlVdpDevice *device; + struct pipe_surface *surface; + struct pipe_sampler_view *sampler_view; + struct pipe_fence_handle *fence; + struct vl_compositor_state cstate; + struct u_rect dirty_area; + bool send_to_X; +} vlVdpOutputSurface; + +typedef struct +{ + vlVdpDevice *device; + Drawable drawable; +} vlVdpPresentationQueueTarget; + +typedef struct +{ + vlVdpDevice *device; + Drawable drawable; + struct vl_compositor_state cstate; + vlVdpOutputSurface *last_surf; +} vlVdpPresentationQueue; + +typedef struct +{ + vlVdpDevice *device; + mtx_t mutex; + struct pipe_video_codec *decoder; +} vlVdpDecoder; + +typedef uint32_t vlHandle; + +boolean vlCreateHTAB(void); +void vlDestroyHTAB(void); +vlHandle vlAddDataHTAB(void *data); +void* vlGetDataHTAB(vlHandle handle); +void vlRemoveDataHTAB(vlHandle handle); + +boolean vlGetFuncFTAB(VdpFuncId function_id, void **func); + +/* Public functions */ +VdpDeviceCreateX11 vdp_imp_device_create_x11; + +void vlVdpDefaultSamplerViewTemplate(struct pipe_sampler_view *templ, struct pipe_resource *res); + +/* Internal function pointers */ +VdpGetErrorString vlVdpGetErrorString; +VdpDeviceDestroy vlVdpDeviceDestroy; +void vlVdpDeviceFree(vlVdpDevice *dev); +VdpGetProcAddress vlVdpGetProcAddress; +VdpGetApiVersion vlVdpGetApiVersion; +VdpGetInformationString vlVdpGetInformationString; +VdpVideoSurfaceQueryCapabilities vlVdpVideoSurfaceQueryCapabilities; +VdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities vlVdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities; +VdpDecoderQueryCapabilities vlVdpDecoderQueryCapabilities; +VdpOutputSurfaceQueryCapabilities vlVdpOutputSurfaceQueryCapabilities; +VdpOutputSurfaceQueryGetPutBitsNativeCapabilities vlVdpOutputSurfaceQueryGetPutBitsNativeCapabilities; +VdpOutputSurfaceQueryPutBitsIndexedCapabilities vlVdpOutputSurfaceQueryPutBitsIndexedCapabilities; +VdpOutputSurfaceQueryPutBitsYCbCrCapabilities vlVdpOutputSurfaceQueryPutBitsYCbCrCapabilities; +VdpBitmapSurfaceQueryCapabilities vlVdpBitmapSurfaceQueryCapabilities; +VdpVideoMixerQueryFeatureSupport vlVdpVideoMixerQueryFeatureSupport; +VdpVideoMixerQueryParameterSupport vlVdpVideoMixerQueryParameterSupport; +VdpVideoMixerQueryParameterValueRange vlVdpVideoMixerQueryParameterValueRange; +VdpVideoMixerQueryAttributeSupport vlVdpVideoMixerQueryAttributeSupport; +VdpVideoMixerQueryAttributeValueRange vlVdpVideoMixerQueryAttributeValueRange; +VdpVideoSurfaceCreate vlVdpVideoSurfaceCreate; +VdpVideoSurfaceDestroy vlVdpVideoSurfaceDestroy; +VdpVideoSurfaceGetParameters vlVdpVideoSurfaceGetParameters; +VdpVideoSurfaceGetBitsYCbCr vlVdpVideoSurfaceGetBitsYCbCr; +VdpVideoSurfacePutBitsYCbCr vlVdpVideoSurfacePutBitsYCbCr; +void vlVdpVideoSurfaceClear(vlVdpSurface *vlsurf); +VdpDecoderCreate vlVdpDecoderCreate; +VdpDecoderDestroy vlVdpDecoderDestroy; +VdpDecoderGetParameters vlVdpDecoderGetParameters; +VdpDecoderRender vlVdpDecoderRender; +VdpOutputSurfaceCreate vlVdpOutputSurfaceCreate; +VdpOutputSurfaceDestroy vlVdpOutputSurfaceDestroy; +VdpOutputSurfaceGetParameters vlVdpOutputSurfaceGetParameters; +VdpOutputSurfaceGetBitsNative vlVdpOutputSurfaceGetBitsNative; +VdpOutputSurfacePutBitsNative vlVdpOutputSurfacePutBitsNative; +VdpOutputSurfacePutBitsIndexed vlVdpOutputSurfacePutBitsIndexed; +VdpOutputSurfacePutBitsYCbCr vlVdpOutputSurfacePutBitsYCbCr; +VdpOutputSurfaceRenderOutputSurface vlVdpOutputSurfaceRenderOutputSurface; +VdpOutputSurfaceRenderBitmapSurface vlVdpOutputSurfaceRenderBitmapSurface; +VdpBitmapSurfaceCreate vlVdpBitmapSurfaceCreate; +VdpBitmapSurfaceDestroy vlVdpBitmapSurfaceDestroy; +VdpBitmapSurfaceGetParameters vlVdpBitmapSurfaceGetParameters; +VdpBitmapSurfacePutBitsNative vlVdpBitmapSurfacePutBitsNative; +VdpPresentationQueueTargetDestroy vlVdpPresentationQueueTargetDestroy; +VdpPresentationQueueCreate vlVdpPresentationQueueCreate; +VdpPresentationQueueDestroy vlVdpPresentationQueueDestroy; +VdpPresentationQueueSetBackgroundColor vlVdpPresentationQueueSetBackgroundColor; +VdpPresentationQueueGetBackgroundColor vlVdpPresentationQueueGetBackgroundColor; +VdpPresentationQueueGetTime vlVdpPresentationQueueGetTime; +VdpPresentationQueueDisplay vlVdpPresentationQueueDisplay; +VdpPresentationQueueBlockUntilSurfaceIdle vlVdpPresentationQueueBlockUntilSurfaceIdle; +VdpPresentationQueueQuerySurfaceStatus vlVdpPresentationQueueQuerySurfaceStatus; +VdpPreemptionCallback vlVdpPreemptionCallback; +VdpPreemptionCallbackRegister vlVdpPreemptionCallbackRegister; +VdpVideoMixerSetFeatureEnables vlVdpVideoMixerSetFeatureEnables; +VdpVideoMixerCreate vlVdpVideoMixerCreate; +VdpVideoMixerRender vlVdpVideoMixerRender; +VdpVideoMixerSetAttributeValues vlVdpVideoMixerSetAttributeValues; +VdpVideoMixerGetFeatureSupport vlVdpVideoMixerGetFeatureSupport; +VdpVideoMixerGetFeatureEnables vlVdpVideoMixerGetFeatureEnables; +VdpVideoMixerGetParameterValues vlVdpVideoMixerGetParameterValues; +VdpVideoMixerGetAttributeValues vlVdpVideoMixerGetAttributeValues; +VdpVideoMixerDestroy vlVdpVideoMixerDestroy; +VdpGenerateCSCMatrix vlVdpGenerateCSCMatrix; +/* Winsys specific internal function pointers */ +VdpPresentationQueueTargetCreateX11 vlVdpPresentationQueueTargetCreateX11; + + +/* interop to mesa state tracker */ +VdpVideoSurfaceGallium vlVdpVideoSurfaceGallium; +VdpOutputSurfaceGallium vlVdpOutputSurfaceGallium; +VdpVideoSurfaceDMABuf vlVdpVideoSurfaceDMABuf; +VdpOutputSurfaceDMABuf vlVdpOutputSurfaceDMABuf; + +#define VDPAU_OUT 0 +#define VDPAU_ERR 1 +#define VDPAU_WARN 2 +#define VDPAU_TRACE 3 + +static inline void VDPAU_MSG(unsigned int level, const char *fmt, ...) +{ + static int debug_level = -1; + + if (debug_level == -1) { + debug_level = MAX2(debug_get_num_option("VDPAU_DEBUG", 0), 0); + } + + if (level <= debug_level) { + va_list ap; + va_start(ap, fmt); + _debug_vprintf(fmt, ap); + va_end(ap); + } +} + +static inline void +DeviceReference(vlVdpDevice **ptr, vlVdpDevice *dev) +{ + vlVdpDevice *old_dev = *ptr; + + if (pipe_reference(&(*ptr)->reference, &dev->reference)) + vlVdpDeviceFree(old_dev); + *ptr = dev; +} + +#endif /* VDPAU_PRIVATE_H */ diff --git a/src/gallium/frontends/wgl/Makefile.sources b/src/gallium/frontends/wgl/Makefile.sources new file mode 100644 index 00000000000..2630b445d54 --- /dev/null +++ b/src/gallium/frontends/wgl/Makefile.sources @@ -0,0 +1,17 @@ +C_SOURCES := \ + stw_context.c \ + stw_device.c \ + stw_ext_context.c \ + stw_ext_extensionsstring.c \ + stw_ext_pbuffer.c \ + stw_ext_pixelformat.c \ + stw_ext_rendertexture.c \ + stw_ext_swapinterval.c \ + stw_framebuffer.c \ + stw_getprocaddress.c \ + stw_nopfuncs.c \ + stw_nopfuncs.h \ + stw_pixelformat.c \ + stw_st.c \ + stw_tls.c \ + stw_wgl.c diff --git a/src/gallium/frontends/wgl/SConscript b/src/gallium/frontends/wgl/SConscript new file mode 100644 index 00000000000..bbf5ebd9764 --- /dev/null +++ b/src/gallium/frontends/wgl/SConscript @@ -0,0 +1,24 @@ +import os + +Import('*') + +env = env.Clone() + +env.Append(CPPPATH = [ + '#src/mapi', + '#src/mesa', + '.', +]) + +env.AppendUnique(CPPDEFINES = [ + '_GDI32_', # prevent wgl* being declared __declspec(dllimport) + 'BUILD_GL32', # declare gl* as __declspec(dllexport) in Mesa headers + 'WIN32_LEAN_AND_MEAN', # http://msdn2.microsoft.com/en-us/library/6dwk3a1z.aspx + '_GLAPI_NO_EXPORTS', # prevent _glapi_* from being declared __declspec(dllimport) +]) + +wgl = env.ConvenienceLibrary( + target ='wgl', + source = env.ParseSourceList('Makefile.sources', 'C_SOURCES'), +) +Export('wgl') diff --git a/src/gallium/frontends/wgl/gldrv.h b/src/gallium/frontends/wgl/gldrv.h new file mode 100644 index 00000000000..829422c96a8 --- /dev/null +++ b/src/gallium/frontends/wgl/gldrv.h @@ -0,0 +1,589 @@ +/* + * Copyright © Microsoft Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef _GLDRV_ +#define _GLDRV_ + +#include + +// Number of entries expected for various versions of OpenGL +#define OPENGL_VERSION_100_ENTRIES 306 +#define OPENGL_VERSION_110_ENTRIES 336 + +typedef struct _GLDISPATCHTABLE { + void (APIENTRY *glNewList )( GLuint list, GLenum mode ); + void (APIENTRY *glEndList )( void ); + void (APIENTRY *glCallList )( GLuint list ); + void (APIENTRY *glCallLists )( GLsizei n, GLenum type, const GLvoid *lists ); + void (APIENTRY *glDeleteLists )( GLuint list, GLsizei range ); + GLuint (APIENTRY *glGenLists )( GLsizei range ); + void (APIENTRY *glListBase )( GLuint base ); + void (APIENTRY *glBegin )( GLenum mode ); + void (APIENTRY *glBitmap )( GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap ); + void (APIENTRY *glColor3b )( GLbyte red, GLbyte green, GLbyte blue ); + void (APIENTRY *glColor3bv )( const GLbyte *v ); + void (APIENTRY *glColor3d )( GLdouble red, GLdouble green, GLdouble blue ); + void (APIENTRY *glColor3dv )( const GLdouble *v ); + void (APIENTRY *glColor3f )( GLfloat red, GLfloat green, GLfloat blue ); + void (APIENTRY *glColor3fv )( const GLfloat *v ); + void (APIENTRY *glColor3i )( GLint red, GLint green, GLint blue ); + void (APIENTRY *glColor3iv )( const GLint *v ); + void (APIENTRY *glColor3s )( GLshort red, GLshort green, GLshort blue ); + void (APIENTRY *glColor3sv )( const GLshort *v ); + void (APIENTRY *glColor3ub )( GLubyte red, GLubyte green, GLubyte blue ); + void (APIENTRY *glColor3ubv )( const GLubyte *v ); + void (APIENTRY *glColor3ui )( GLuint red, GLuint green, GLuint blue ); + void (APIENTRY *glColor3uiv )( const GLuint *v ); + void (APIENTRY *glColor3us )( GLushort red, GLushort green, GLushort blue ); + void (APIENTRY *glColor3usv )( const GLushort *v ); + void (APIENTRY *glColor4b )( GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha ); + void (APIENTRY *glColor4bv )( const GLbyte *v ); + void (APIENTRY *glColor4d )( GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha ); + void (APIENTRY *glColor4dv )( const GLdouble *v ); + void (APIENTRY *glColor4f )( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha ); + void (APIENTRY *glColor4fv )( const GLfloat *v ); + void (APIENTRY *glColor4i )( GLint red, GLint green, GLint blue, GLint alpha ); + void (APIENTRY *glColor4iv )( const GLint *v ); + void (APIENTRY *glColor4s )( GLshort red, GLshort green, GLshort blue, GLshort alpha ); + void (APIENTRY *glColor4sv )( const GLshort *v ); + void (APIENTRY *glColor4ub )( GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha ); + void (APIENTRY *glColor4ubv )( const GLubyte *v ); + void (APIENTRY *glColor4ui )( GLuint red, GLuint green, GLuint blue, GLuint alpha ); + void (APIENTRY *glColor4uiv )( const GLuint *v ); + void (APIENTRY *glColor4us )( GLushort red, GLushort green, GLushort blue, GLushort alpha ); + void (APIENTRY *glColor4usv )( const GLushort *v ); + void (APIENTRY *glEdgeFlag )( GLboolean flag ); + void (APIENTRY *glEdgeFlagv )( const GLboolean *flag ); + void (APIENTRY *glEnd )( void ); + void (APIENTRY *glIndexd )( GLdouble c ); + void (APIENTRY *glIndexdv )( const GLdouble *c ); + void (APIENTRY *glIndexf )( GLfloat c ); + void (APIENTRY *glIndexfv )( const GLfloat *c ); + void (APIENTRY *glIndexi )( GLint c ); + void (APIENTRY *glIndexiv )( const GLint *c ); + void (APIENTRY *glIndexs )( GLshort c ); + void (APIENTRY *glIndexsv )( const GLshort *c ); + void (APIENTRY *glNormal3b )( GLbyte nx, GLbyte ny, GLbyte nz ); + void (APIENTRY *glNormal3bv )( const GLbyte *v ); + void (APIENTRY *glNormal3d )( GLdouble nx, GLdouble ny, GLdouble nz ); + void (APIENTRY *glNormal3dv )( const GLdouble *v ); + void (APIENTRY *glNormal3f )( GLfloat nx, GLfloat ny, GLfloat nz ); + void (APIENTRY *glNormal3fv )( const GLfloat *v ); + void (APIENTRY *glNormal3i )( GLint nx, GLint ny, GLint nz ); + void (APIENTRY *glNormal3iv )( const GLint *v ); + void (APIENTRY *glNormal3s )( GLshort nx, GLshort ny, GLshort nz ); + void (APIENTRY *glNormal3sv )( const GLshort *v ); + void (APIENTRY *glRasterPos2d )( GLdouble x, GLdouble y ); + void (APIENTRY *glRasterPos2dv )( const GLdouble *v ); + void (APIENTRY *glRasterPos2f )( GLfloat x, GLfloat y ); + void (APIENTRY *glRasterPos2fv )( const GLfloat *v ); + void (APIENTRY *glRasterPos2i )( GLint x, GLint y ); + void (APIENTRY *glRasterPos2iv )( const GLint *v ); + void (APIENTRY *glRasterPos2s )( GLshort x, GLshort y ); + void (APIENTRY *glRasterPos2sv )( const GLshort *v ); + void (APIENTRY *glRasterPos3d )( GLdouble x, GLdouble y, GLdouble z ); + void (APIENTRY *glRasterPos3dv )( const GLdouble *v ); + void (APIENTRY *glRasterPos3f )( GLfloat x, GLfloat y, GLfloat z ); + void (APIENTRY *glRasterPos3fv )( const GLfloat *v ); + void (APIENTRY *glRasterPos3i )( GLint x, GLint y, GLint z ); + void (APIENTRY *glRasterPos3iv )( const GLint *v ); + void (APIENTRY *glRasterPos3s )( GLshort x, GLshort y, GLshort z ); + void (APIENTRY *glRasterPos3sv )( const GLshort *v ); + void (APIENTRY *glRasterPos4d )( GLdouble x, GLdouble y, GLdouble z, GLdouble w ); + void (APIENTRY *glRasterPos4dv )( const GLdouble *v ); + void (APIENTRY *glRasterPos4f )( GLfloat x, GLfloat y, GLfloat z, GLfloat w ); + void (APIENTRY *glRasterPos4fv )( const GLfloat *v ); + void (APIENTRY *glRasterPos4i )( GLint x, GLint y, GLint z, GLint w ); + void (APIENTRY *glRasterPos4iv )( const GLint *v ); + void (APIENTRY *glRasterPos4s )( GLshort x, GLshort y, GLshort z, GLshort w ); + void (APIENTRY *glRasterPos4sv )( const GLshort *v ); + void (APIENTRY *glRectd )( GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2 ); + void (APIENTRY *glRectdv )( const GLdouble *v1, const GLdouble *v2 ); + void (APIENTRY *glRectf )( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 ); + void (APIENTRY *glRectfv )( const GLfloat *v1, const GLfloat *v2 ); + void (APIENTRY *glRecti )( GLint x1, GLint y1, GLint x2, GLint y2 ); + void (APIENTRY *glRectiv )( const GLint *v1, const GLint *v2 ); + void (APIENTRY *glRects )( GLshort x1, GLshort y1, GLshort x2, GLshort y2 ); + void (APIENTRY *glRectsv )( const GLshort *v1, const GLshort *v2 ); + void (APIENTRY *glTexCoord1d )( GLdouble s ); + void (APIENTRY *glTexCoord1dv )( const GLdouble *v ); + void (APIENTRY *glTexCoord1f )( GLfloat s ); + void (APIENTRY *glTexCoord1fv )( const GLfloat *v ); + void (APIENTRY *glTexCoord1i )( GLint s ); + void (APIENTRY *glTexCoord1iv )( const GLint *v ); + void (APIENTRY *glTexCoord1s )( GLshort s ); + void (APIENTRY *glTexCoord1sv )( const GLshort *v ); + void (APIENTRY *glTexCoord2d )( GLdouble s, GLdouble t ); + void (APIENTRY *glTexCoord2dv )( const GLdouble *v ); + void (APIENTRY *glTexCoord2f )( GLfloat s, GLfloat t ); + void (APIENTRY *glTexCoord2fv )( const GLfloat *v ); + void (APIENTRY *glTexCoord2i )( GLint s, GLint t ); + void (APIENTRY *glTexCoord2iv )( const GLint *v ); + void (APIENTRY *glTexCoord2s )( GLshort s, GLshort t ); + void (APIENTRY *glTexCoord2sv )( const GLshort *v ); + void (APIENTRY *glTexCoord3d )( GLdouble s, GLdouble t, GLdouble r ); + void (APIENTRY *glTexCoord3dv )( const GLdouble *v ); + void (APIENTRY *glTexCoord3f )( GLfloat s, GLfloat t, GLfloat r ); + void (APIENTRY *glTexCoord3fv )( const GLfloat *v ); + void (APIENTRY *glTexCoord3i )( GLint s, GLint t, GLint r ); + void (APIENTRY *glTexCoord3iv )( const GLint *v ); + void (APIENTRY *glTexCoord3s )( GLshort s, GLshort t, GLshort r ); + void (APIENTRY *glTexCoord3sv )( const GLshort *v ); + void (APIENTRY *glTexCoord4d )( GLdouble s, GLdouble t, GLdouble r, GLdouble q ); + void (APIENTRY *glTexCoord4dv )( const GLdouble *v ); + void (APIENTRY *glTexCoord4f )( GLfloat s, GLfloat t, GLfloat r, GLfloat q ); + void (APIENTRY *glTexCoord4fv )( const GLfloat *v ); + void (APIENTRY *glTexCoord4i )( GLint s, GLint t, GLint r, GLint q ); + void (APIENTRY *glTexCoord4iv )( const GLint *v ); + void (APIENTRY *glTexCoord4s )( GLshort s, GLshort t, GLshort r, GLshort q ); + void (APIENTRY *glTexCoord4sv )( const GLshort *v ); + void (APIENTRY *glVertex2d )( GLdouble x, GLdouble y ); + void (APIENTRY *glVertex2dv )( const GLdouble *v ); + void (APIENTRY *glVertex2f )( GLfloat x, GLfloat y ); + void (APIENTRY *glVertex2fv )( const GLfloat *v ); + void (APIENTRY *glVertex2i )( GLint x, GLint y ); + void (APIENTRY *glVertex2iv )( const GLint *v ); + void (APIENTRY *glVertex2s )( GLshort x, GLshort y ); + void (APIENTRY *glVertex2sv )( const GLshort *v ); + void (APIENTRY *glVertex3d )( GLdouble x, GLdouble y, GLdouble z ); + void (APIENTRY *glVertex3dv )( const GLdouble *v ); + void (APIENTRY *glVertex3f )( GLfloat x, GLfloat y, GLfloat z ); + void (APIENTRY *glVertex3fv )( const GLfloat *v ); + void (APIENTRY *glVertex3i )( GLint x, GLint y, GLint z ); + void (APIENTRY *glVertex3iv )( const GLint *v ); + void (APIENTRY *glVertex3s )( GLshort x, GLshort y, GLshort z ); + void (APIENTRY *glVertex3sv )( const GLshort *v ); + void (APIENTRY *glVertex4d )( GLdouble x, GLdouble y, GLdouble z, GLdouble w ); + void (APIENTRY *glVertex4dv )( const GLdouble *v ); + void (APIENTRY *glVertex4f )( GLfloat x, GLfloat y, GLfloat z, GLfloat w ); + void (APIENTRY *glVertex4fv )( const GLfloat *v ); + void (APIENTRY *glVertex4i )( GLint x, GLint y, GLint z, GLint w ); + void (APIENTRY *glVertex4iv )( const GLint *v ); + void (APIENTRY *glVertex4s )( GLshort x, GLshort y, GLshort z, GLshort w ); + void (APIENTRY *glVertex4sv )( const GLshort *v ); + void (APIENTRY *glClipPlane )( GLenum plane, const GLdouble *equation ); + void (APIENTRY *glColorMaterial )( GLenum face, GLenum mode ); + void (APIENTRY *glCullFace )( GLenum mode ); + void (APIENTRY *glFogf )( GLenum pname, GLfloat param ); + void (APIENTRY *glFogfv )( GLenum pname, const GLfloat *params ); + void (APIENTRY *glFogi )( GLenum pname, GLint param ); + void (APIENTRY *glFogiv )( GLenum pname, const GLint *params ); + void (APIENTRY *glFrontFace )( GLenum mode ); + void (APIENTRY *glHint )( GLenum target, GLenum mode ); + void (APIENTRY *glLightf )( GLenum light, GLenum pname, GLfloat param ); + void (APIENTRY *glLightfv )( GLenum light, GLenum pname, const GLfloat *params ); + void (APIENTRY *glLighti )( GLenum light, GLenum pname, GLint param ); + void (APIENTRY *glLightiv )( GLenum light, GLenum pname, const GLint *params ); + void (APIENTRY *glLightModelf )( GLenum pname, GLfloat param ); + void (APIENTRY *glLightModelfv )( GLenum pname, const GLfloat *params ); + void (APIENTRY *glLightModeli )( GLenum pname, GLint param ); + void (APIENTRY *glLightModeliv )( GLenum pname, const GLint *params ); + void (APIENTRY *glLineStipple )( GLint factor, GLushort pattern ); + void (APIENTRY *glLineWidth )( GLfloat width ); + void (APIENTRY *glMaterialf )( GLenum face, GLenum pname, GLfloat param ); + void (APIENTRY *glMaterialfv )( GLenum face, GLenum pname, const GLfloat *params ); + void (APIENTRY *glMateriali )( GLenum face, GLenum pname, GLint param ); + void (APIENTRY *glMaterialiv )( GLenum face, GLenum pname, const GLint *params ); + void (APIENTRY *glPointSize )( GLfloat size ); + void (APIENTRY *glPolygonMode )( GLenum face, GLenum mode ); + void (APIENTRY *glPolygonStipple )( const GLubyte *mask ); + void (APIENTRY *glScissor )( GLint x, GLint y, GLsizei width, GLsizei height ); + void (APIENTRY *glShadeModel )( GLenum mode ); + void (APIENTRY *glTexParameterf )( GLenum target, GLenum pname, GLfloat param ); + void (APIENTRY *glTexParameterfv )( GLenum target, GLenum pname, const GLfloat *params ); + void (APIENTRY *glTexParameteri )( GLenum target, GLenum pname, GLint param ); + void (APIENTRY *glTexParameteriv )( GLenum target, GLenum pname, const GLint *params ); + void (APIENTRY *glTexImage1D )( GLenum target, GLint level, GLint components, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels ); + void (APIENTRY *glTexImage2D )( GLenum target, GLint level, GLint components, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels ); + void (APIENTRY *glTexEnvf )( GLenum target, GLenum pname, GLfloat param ); + void (APIENTRY *glTexEnvfv )( GLenum target, GLenum pname, const GLfloat *params ); + void (APIENTRY *glTexEnvi )( GLenum target, GLenum pname, GLint param ); + void (APIENTRY *glTexEnviv )( GLenum target, GLenum pname, const GLint *params ); + void (APIENTRY *glTexGend )( GLenum coord, GLenum pname, GLdouble param ); + void (APIENTRY *glTexGendv )( GLenum coord, GLenum pname, const GLdouble *params ); + void (APIENTRY *glTexGenf )( GLenum coord, GLenum pname, GLfloat param ); + void (APIENTRY *glTexGenfv )( GLenum coord, GLenum pname, const GLfloat *params ); + void (APIENTRY *glTexGeni )( GLenum coord, GLenum pname, GLint param ); + void (APIENTRY *glTexGeniv )( GLenum coord, GLenum pname, const GLint *params ); + void (APIENTRY *glFeedbackBuffer )( GLsizei size, GLenum type, GLfloat *buffer ); + void (APIENTRY *glSelectBuffer )( GLsizei size, GLuint *buffer ); + GLint (APIENTRY *glRenderMode )( GLenum mode ); + void (APIENTRY *glInitNames )( void ); + void (APIENTRY *glLoadName )( GLuint name ); + void (APIENTRY *glPassThrough )( GLfloat token ); + void (APIENTRY *glPopName )( void ); + void (APIENTRY *glPushName )( GLuint name ); + void (APIENTRY *glDrawBuffer )( GLenum mode ); + void (APIENTRY *glClear )( GLbitfield mask ); + void (APIENTRY *glClearAccum )( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha ); + void (APIENTRY *glClearIndex )( GLfloat c ); + void (APIENTRY *glClearColor )( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha ); + void (APIENTRY *glClearStencil )( GLint s ); + void (APIENTRY *glClearDepth )( GLclampd depth ); + void (APIENTRY *glStencilMask )( GLuint mask ); + void (APIENTRY *glColorMask )( GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha ); + void (APIENTRY *glDepthMask )( GLboolean flag ); + void (APIENTRY *glIndexMask )( GLuint mask ); + void (APIENTRY *glAccum )( GLenum op, GLfloat value ); + void (APIENTRY *glDisable )( GLenum cap ); + void (APIENTRY *glEnable )( GLenum cap ); + void (APIENTRY *glFinish )( void ); + void (APIENTRY *glFlush )( void ); + void (APIENTRY *glPopAttrib )( void ); + void (APIENTRY *glPushAttrib )( GLbitfield mask ); + void (APIENTRY *glMap1d )( GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points ); + void (APIENTRY *glMap1f )( GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points ); + void (APIENTRY *glMap2d )( GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points ); + void (APIENTRY *glMap2f )( GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points ); + void (APIENTRY *glMapGrid1d )( GLint un, GLdouble u1, GLdouble u2 ); + void (APIENTRY *glMapGrid1f )( GLint un, GLfloat u1, GLfloat u2 ); + void (APIENTRY *glMapGrid2d )( GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2 ); + void (APIENTRY *glMapGrid2f )( GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2 ); + void (APIENTRY *glEvalCoord1d )( GLdouble u ); + void (APIENTRY *glEvalCoord1dv )( const GLdouble *u ); + void (APIENTRY *glEvalCoord1f )( GLfloat u ); + void (APIENTRY *glEvalCoord1fv )( const GLfloat *u ); + void (APIENTRY *glEvalCoord2d )( GLdouble u, GLdouble v ); + void (APIENTRY *glEvalCoord2dv )( const GLdouble *u ); + void (APIENTRY *glEvalCoord2f )( GLfloat u, GLfloat v ); + void (APIENTRY *glEvalCoord2fv )( const GLfloat *u ); + void (APIENTRY *glEvalMesh1 )( GLenum mode, GLint i1, GLint i2 ); + void (APIENTRY *glEvalPoint1 )( GLint i ); + void (APIENTRY *glEvalMesh2 )( GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2 ); + void (APIENTRY *glEvalPoint2 )( GLint i, GLint j ); + void (APIENTRY *glAlphaFunc )( GLenum func, GLclampf ref ); + void (APIENTRY *glBlendFunc )( GLenum sfactor, GLenum dfactor ); + void (APIENTRY *glLogicOp )( GLenum opcode ); + void (APIENTRY *glStencilFunc )( GLenum func, GLint ref, GLuint mask ); + void (APIENTRY *glStencilOp )( GLenum fail, GLenum zfail, GLenum zpass ); + void (APIENTRY *glDepthFunc )( GLenum func ); + void (APIENTRY *glPixelZoom )( GLfloat xfactor, GLfloat yfactor ); + void (APIENTRY *glPixelTransferf )( GLenum pname, GLfloat param ); + void (APIENTRY *glPixelTransferi )( GLenum pname, GLint param ); + void (APIENTRY *glPixelStoref )( GLenum pname, GLfloat param ); + void (APIENTRY *glPixelStorei )( GLenum pname, GLint param ); + void (APIENTRY *glPixelMapfv )( GLenum map, GLint mapsize, const GLfloat *values ); + void (APIENTRY *glPixelMapuiv )( GLenum map, GLint mapsize, const GLuint *values ); + void (APIENTRY *glPixelMapusv )( GLenum map, GLint mapsize, const GLushort *values ); + void (APIENTRY *glReadBuffer )( GLenum mode ); + void (APIENTRY *glCopyPixels )( GLint x, GLint y, GLsizei width, GLsizei height, GLenum type ); + void (APIENTRY *glReadPixels )( GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels ); + void (APIENTRY *glDrawPixels )( GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels ); + void (APIENTRY *glGetBooleanv )( GLenum pname, GLboolean *params ); + void (APIENTRY *glGetClipPlane )( GLenum plane, GLdouble *equation ); + void (APIENTRY *glGetDoublev )( GLenum pname, GLdouble *params ); + GLenum (APIENTRY *glGetError )( void ); + void (APIENTRY *glGetFloatv )( GLenum pname, GLfloat *params ); + void (APIENTRY *glGetIntegerv )( GLenum pname, GLint *params ); + void (APIENTRY *glGetLightfv )( GLenum light, GLenum pname, GLfloat *params ); + void (APIENTRY *glGetLightiv )( GLenum light, GLenum pname, GLint *params ); + void (APIENTRY *glGetMapdv )( GLenum target, GLenum query, GLdouble *v ); + void (APIENTRY *glGetMapfv )( GLenum target, GLenum query, GLfloat *v ); + void (APIENTRY *glGetMapiv )( GLenum target, GLenum query, GLint *v ); + void (APIENTRY *glGetMaterialfv )( GLenum face, GLenum pname, GLfloat *params ); + void (APIENTRY *glGetMaterialiv )( GLenum face, GLenum pname, GLint *params ); + void (APIENTRY *glGetPixelMapfv )( GLenum map, GLfloat *values ); + void (APIENTRY *glGetPixelMapuiv )( GLenum map, GLuint *values ); + void (APIENTRY *glGetPixelMapusv )( GLenum map, GLushort *values ); + void (APIENTRY *glGetPolygonStipple )( GLubyte *mask ); + const GLubyte * (APIENTRY *glGetString )( GLenum name ); + void (APIENTRY *glGetTexEnvfv )( GLenum target, GLenum pname, GLfloat *params ); + void (APIENTRY *glGetTexEnviv )( GLenum target, GLenum pname, GLint *params ); + void (APIENTRY *glGetTexGendv )( GLenum coord, GLenum pname, GLdouble *params ); + void (APIENTRY *glGetTexGenfv )( GLenum coord, GLenum pname, GLfloat *params ); + void (APIENTRY *glGetTexGeniv )( GLenum coord, GLenum pname, GLint *params ); + void (APIENTRY *glGetTexImage )( GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels ); + void (APIENTRY *glGetTexParameterfv )( GLenum target, GLenum pname, GLfloat *params ); + void (APIENTRY *glGetTexParameteriv )( GLenum target, GLenum pname, GLint *params ); + void (APIENTRY *glGetTexLevelParameterfv )( GLenum target, GLint level, GLenum pname, GLfloat *params ); + void (APIENTRY *glGetTexLevelParameteriv )( GLenum target, GLint level, GLenum pname, GLint *params ); + GLboolean (APIENTRY *glIsEnabled )( GLenum cap ); + GLboolean (APIENTRY *glIsList )( GLuint list ); + void (APIENTRY *glDepthRange )( GLclampd zNear, GLclampd zFar ); + void (APIENTRY *glFrustum )( GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar ); + void (APIENTRY *glLoadIdentity )( void ); + void (APIENTRY *glLoadMatrixf )( const GLfloat *m ); + void (APIENTRY *glLoadMatrixd )( const GLdouble *m ); + void (APIENTRY *glMatrixMode )( GLenum mode ); + void (APIENTRY *glMultMatrixf )( const GLfloat *m ); + void (APIENTRY *glMultMatrixd )( const GLdouble *m ); + void (APIENTRY *glOrtho )( GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar ); + void (APIENTRY *glPopMatrix )( void ); + void (APIENTRY *glPushMatrix )( void ); + void (APIENTRY *glRotated )( GLdouble angle, GLdouble x, GLdouble y, GLdouble z ); + void (APIENTRY *glRotatef )( GLfloat angle, GLfloat x, GLfloat y, GLfloat z ); + void (APIENTRY *glScaled )( GLdouble x, GLdouble y, GLdouble z ); + void (APIENTRY *glScalef )( GLfloat x, GLfloat y, GLfloat z ); + void (APIENTRY *glTranslated )( GLdouble x, GLdouble y, GLdouble z ); + void (APIENTRY *glTranslatef )( GLfloat x, GLfloat y, GLfloat z ); + void (APIENTRY *glViewport )( GLint x, GLint y, GLsizei width, GLsizei height ); + // OpenGL version 1.0 entries end here + + // OpenGL version 1.1 entries begin here + void (APIENTRY *glArrayElement )(GLint i); + void (APIENTRY *glBindTexture )(GLenum target, GLuint texture); + void (APIENTRY *glColorPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); + void (APIENTRY *glDisableClientState )(GLenum array); + void (APIENTRY *glDrawArrays )(GLenum mode, GLint first, GLsizei count); + void (APIENTRY *glDrawElements )(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); + void (APIENTRY *glEdgeFlagPointer )(GLsizei stride, const GLvoid *pointer); + void (APIENTRY *glEnableClientState )(GLenum array); + void (APIENTRY *glIndexPointer )(GLenum type, GLsizei stride, const GLvoid *pointer); + void (APIENTRY *glIndexub )(GLubyte c); + void (APIENTRY *glIndexubv )(const GLubyte *c); + void (APIENTRY *glInterleavedArrays )(GLenum format, GLsizei stride, const GLvoid *pointer); + void (APIENTRY *glNormalPointer )(GLenum type, GLsizei stride, const GLvoid *pointer); + void (APIENTRY *glPolygonOffset )(GLfloat factor, GLfloat units); + void (APIENTRY *glTexCoordPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); + void (APIENTRY *glVertexPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); + GLboolean (APIENTRY *glAreTexturesResident )(GLsizei n, const GLuint *textures, GLboolean *residences); + void (APIENTRY *glCopyTexImage1D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border); + void (APIENTRY *glCopyTexImage2D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); + void (APIENTRY *glCopyTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); + void (APIENTRY *glCopyTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); + void (APIENTRY *glDeleteTextures )(GLsizei n, const GLuint *textures); + void (APIENTRY *glGenTextures )(GLsizei n, GLuint *textures); + void (APIENTRY *glGetPointerv )(GLenum pname, GLvoid* *params); + GLboolean (APIENTRY *glIsTexture )(GLuint texture); + void (APIENTRY *glPrioritizeTextures )(GLsizei n, const GLuint *textures, const GLclampf *priorities); + void (APIENTRY *glTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); + void (APIENTRY *glTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); + void (APIENTRY *glPopClientAttrib )(void); + void (APIENTRY *glPushClientAttrib )(GLbitfield mask); +} GLDISPATCHTABLE, *PGLDISPATCHTABLE; + +// OpenGL Client/Driver Procedure Table. + +typedef struct _GLCLTPROCTABLE { + _In_range_(0,OPENGL_VERSION_110_ENTRIES) int cEntries; // Number of function entries in table + GLDISPATCHTABLE glDispatchTable; // OpenGL function dispatch table +} GLCLTPROCTABLE, *PGLCLTPROCTABLE; + +// Driver GLRC handle. + +typedef ULONG DHGLRC; + +// SetProcTable function prototype for DrvSetContext. + +typedef VOID (APIENTRY *PFN_SETPROCTABLE)(PGLCLTPROCTABLE); + +// DrvSetCallbackProcs prototypes +typedef VOID (APIENTRY *PFN_SETCURRENTVALUE)(VOID *pv); +typedef VOID *(APIENTRY *PFN_GETCURRENTVALUE)(VOID); +typedef DHGLRC (APIENTRY *PFN_GETDHGLRC)(HGLRC hrc); +#if WINVER >= 0x600 +typedef struct _PRESENTBUFFERSCB { + IN UINT nVersion; + IN UINT syncType; // See PRESCB_SYNCTYPE_NONE and PRESCB_SYNCTYPE_VSYNC + IN LUID luidAdapter; + IN LPVOID pPrivData; + IN RECT updateRect; // Update rectangle in the coordinate system of the window, whose HDC is passed to PFN_PRESENTBUFFERS +} PRESENTBUFFERSCB, *LPPRESENTBUFFERSCB; +typedef BOOL (APIENTRY *PFN_PRESENTBUFFERS)(HDC hdc, LPPRESENTBUFFERSCB pprsbcbData); +#endif +#if WINVER >= 0xA00 +typedef VOID (APIENTRY *PFN_GETADAPTERLUID)(HDC hdc, OUT LUID* pLuid); +typedef struct _CHECKFULLSCREENSUPPORTCB { + IN UINT nVersion; + IN LUID luidAdapter; + IN UINT hDevice; + IN HMONITOR hMonitor; + OUT UINT VidPnSourceId; +} CHECKFULLSCREENSUPPORTCB, *LPCHECKFULLSCREENSUPPORTCB; +typedef BOOL (APIENTRY *PFN_CHECKFULLSCREENSUPPORT)(HDC hdc, LPCHECKFULLSCREENSUPPORTCB pArgs); +typedef struct _PRESENTTOREDIRECTIONSURFACECB { + IN UINT nVersion; + IN UINT hContext; + IN UINT hSource; + IN UINT hDestination; + IN HANDLE hSharedHandle; + IN UINT64 updateId; + IN RECT updateRect; + IN UINT broadcastContextCount; + IN UINT broadcastContext[64]; + IN UINT broadcastSrcAllocation[64]; + IN UINT broadcastDstAllocation[64]; + IN UINT cbPrivateDriverDataSize; + IN VOID *pPrivateDriverData; +} PRESENTTOREDIRECTIONSURFACECB, *LPPRESENTTOREDIRECTIONSURFACECB; +typedef BOOL (APIENTRY *PFN_PRESENTTOREDIRECTIONSURFACE)(HDC hdc, LPPRESENTTOREDIRECTIONSURFACECB pArgs); +typedef struct _SUBMITPRESENTTOREDIRECTIONSURFACECB { + IN UINT nVersion; + IN HANDLE hSharedHandle; + IN UINT64 updateId; + IN RECT updateRect; + IN UINT broadcastHwQueueCount; + + _Field_size_(broadcastHwQueueCount) + IN UINT *broadcastHwQueue; + + _Field_size_(broadcastHwQueueCount) + IN UINT *broadcastSrcAllocation; + + _Field_size_opt_(broadcastHwQueueCount) + IN UINT *broadcastDstAllocation; + + IN UINT cbPrivateDriverDataSize; + IN VOID *pPrivateDriverData; +} SUBMITPRESENTTOREDIRECTIONSURFACECB, *LPSUBMITPRESENTTOREDIRECTIONSURFACECB; +typedef BOOL (APIENTRY *PFN_SUBMITPRESENTTOREDIRECTIONSURFACE)(HDC hdc, LPSUBMITPRESENTTOREDIRECTIONSURFACECB pArgs); +#endif + +// Note: Structure not referenced directly, simply present to document the expected order/count of +// callbacks received through DrvSetCallbackProcs. +struct WGLCALLBACKS +{ + PFN_SETCURRENTVALUE pfnSetCurrentValue; + PFN_GETCURRENTVALUE pfnGetCurrentValue; + PFN_GETDHGLRC pfnGetDhglrc; + PROC pfnUnused; +#if WINVER >= 0x600 + PFN_PRESENTBUFFERS pfnPresentBuffers; +#endif +#if WINVER >= 0xA00 + PFN_GETADAPTERLUID pfnGetAdapterLuid; + PFN_CHECKFULLSCREENSUPPORT pfnCheckFullscreenSupport; + PFN_PRESENTTOREDIRECTIONSURFACE pfnPresentToRedirectionSurface; + PFN_SUBMITPRESENTTOREDIRECTIONSURFACE pfnSubmitPresentToRedirectionSurface; +#endif +}; + +// Driver context function prototypes. + +BOOL APIENTRY DrvCopyContext(DHGLRC, DHGLRC, UINT); +DHGLRC APIENTRY DrvCreateContext(HDC); +DHGLRC APIENTRY DrvCreateLayerContext(HDC, int); +BOOL APIENTRY DrvDeleteContext(DHGLRC); +PGLCLTPROCTABLE APIENTRY DrvSetContext(HDC,DHGLRC,PFN_SETPROCTABLE); +BOOL APIENTRY DrvReleaseContext(DHGLRC); +BOOL APIENTRY DrvValidateVersion(ULONG); +BOOL APIENTRY DrvShareLists(DHGLRC, DHGLRC); +PROC APIENTRY DrvGetProcAddress(LPCSTR); +VOID APIENTRY DrvSetCallbackProcs(INT, PROC *); // See WGLCALLBACKS for expected order/count per OS. +BOOL APIENTRY DrvDescribeLayerPlane(HDC, INT, INT, UINT, + LPLAYERPLANEDESCRIPTOR); +INT APIENTRY DrvSetLayerPaletteEntries(HDC, INT, INT, INT, + CONST COLORREF *); +INT APIENTRY DrvGetLayerPaletteEntries(HDC, INT, INT, INT, + COLORREF *); +BOOL APIENTRY DrvRealizeLayerPalette(HDC, INT, BOOL); +BOOL APIENTRY DrvSwapLayerBuffers(HDC, UINT); + +#if WINVER >= 0x500 + +typedef struct IDirectDrawSurface *LPDIRECTDRAWSURFACE; +typedef struct _DDSURFACEDESC *LPDDSURFACEDESC; + +DHGLRC APIENTRY DrvCreateDirectDrawContext(HDC, LPDIRECTDRAWSURFACE, + int); +int APIENTRY DrvEnumTextureFormats(int, LPDDSURFACEDESC); +BOOL APIENTRY DrvBindDirectDrawTexture(LPDIRECTDRAWSURFACE); +DWORD APIENTRY DrvSwapMultipleBuffers(UINT cBuffers, + CONST WGLSWAP *pgswap); + +LONG APIENTRY DrvDescribePixelFormat(HDC, INT, ULONG, PIXELFORMATDESCRIPTOR*); +BOOL APIENTRY DrvSetPixelFormat(HDC, LONG); +BOOL APIENTRY DrvSwapBuffers(HDC); + +#endif // WINVER >= 0x500 + +#if WINVER >= 0x600 +typedef struct _PRESENTBUFFERS { + IN HANDLE hSurface; + IN LUID luidAdapter; + IN ULONGLONG ullPresentToken; + IN LPVOID pPrivData; +} PRESENTBUFFERS, *LPPRESENTBUFFERS; +typedef BOOL (APIENTRY *PFN_PRESENTBUFFERS)(HDC hdc, LPPRESENTBUFFERSCB pprsbcbData); + +#define PRESCB_SYNCTYPE_NONE 0 +#define PRESCB_SYNCTYPE_VSYNC 1 + +BOOL APIENTRY DrvPresentBuffers(HDC hdc, LPPRESENTBUFFERS pprsbData); + +#endif + +// Input structure for OPENGL_CMD ExtEscape. + +typedef struct _WNDOBJ WNDOBJ; +typedef struct _XLATEOBJ XLATEOBJ; + +typedef struct _OPENGLCMD +{ + ULONG ulSubEsc; + FLONG fl; + WNDOBJ *pwo; + XLATEOBJ *pxo; +} OPENGLCMD, *POPENGLCMD; + +#if WINVER >= 0x500 + +#define OPENGLCMD_MAXMULTI WGL_SWAPMULTIPLE_MAX + +typedef struct _OPENGLCMDMULTI +{ + ULONG ulSubEsc; + FLONG fl; + ULONG cMulti; + XLATEOBJ *pxo; +} OPENGLCMDMULTI, *POPENGLCMDMULTI; + +#endif // WINVER >= 0x500 + +// Flags for OPENGL_CMD ExtEscape. + +#define OGLCMD_NEEDWNDOBJ 0x01 +#define OGLCMD_NEEDXLATEOBJ 0x02 + +#if WINVER >= 0x500 +#define OGLCMD_MULTIWNDOBJ 0x04 +#endif // WINVER >= 0x500 + +// OPENGL_GETINFO ExtEscape sub-escape numbers. They are defined by Microsoft. + +#define OPENGL_GETINFO_DRVNAME 0 + +// Input structure for OPENGL_GETINFO ExtEscape. + +typedef struct _OPENGLGETINFO +{ + ULONG ulSubEsc; +} OPENGLGETINFO, *POPENGLGETINFO; + +// Input structure for OPENGL_GETINFO_DRVNAME ExtEscape. + +typedef struct _GLDRVNAME +{ + OPENGLGETINFO oglget; +} GLDRVNAME, *PGLDRVNAME; + +// Output structure for OPENGL_GETINFO_DRVNAME ExtEscape. + +typedef struct _GLDRVNAMERET +{ + ULONG ulVersion; // must be 1 for this version + ULONG ulDriverVersion; // driver specific version number + WCHAR awch[MAX_PATH+1]; +} GLDRVNAMERET, *PGLDRVNAMERET; + +#endif /* _GLDRV_ */ diff --git a/src/gallium/frontends/wgl/meson.build b/src/gallium/frontends/wgl/meson.build new file mode 100644 index 00000000000..ce6e9883e00 --- /dev/null +++ b/src/gallium/frontends/wgl/meson.build @@ -0,0 +1,57 @@ +# Copyright © 2018 Intel Corporation + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +inc_wgl = include_directories('.') +_c_args_wgl = [] +if not with_shared_glapi + # prevent _glapi_* from being declared __declspec(dllimport) + _c_args_wgl += '-D_GLAPI_NO_EXPORTS' +endif + +libwgl = static_library( + 'wgl', + files( + 'stw_context.c', + 'stw_device.c', + 'stw_ext_context.c', + 'stw_ext_extensionsstring.c', + 'stw_ext_pbuffer.c', + 'stw_ext_pixelformat.c', + 'stw_ext_rendertexture.c', + 'stw_ext_swapinterval.c', + 'stw_framebuffer.c', + 'stw_getprocaddress.c', + 'stw_nopfuncs.c', + 'stw_nopfuncs.h', + 'stw_pixelformat.c', + 'stw_st.c', + 'stw_tls.c', + 'stw_wgl.c', + ), + c_args : [ + '-D_GDI32_', # prevent wgl* being declared __declspec(dllimport) + '-DBUILD_GL32', # declare gl* as __declspec(dllexport) in Mesa headers + '-DWIN32_LEAN_AND_MEAN', # http://msdn2.microsoft.com/en-us/library/6dwk3a1z.aspx + _c_args_wgl + ], + include_directories : [ + inc_include, inc_src, inc_gallium, inc_gallium_aux, inc_mapi, inc_mesa, + ], +) diff --git a/src/gallium/frontends/wgl/opengl32.def b/src/gallium/frontends/wgl/opengl32.def new file mode 100644 index 00000000000..c35c23b55e1 --- /dev/null +++ b/src/gallium/frontends/wgl/opengl32.def @@ -0,0 +1,388 @@ +EXPORTS +; GlmfBeginGlsBlock +; GlmfCloseMetaFile +; GlmfEndGlsBlock +; GlmfEndPlayback +; GlmfInitPlayback +; GlmfPlayGlsRecord + glAccum + glAlphaFunc + glAreTexturesResident + glArrayElement + glBegin + glBindTexture + glBitmap + glBlendFunc + glCallList + glCallLists + glClear + glClearAccum + glClearColor + glClearDepth + glClearIndex + glClearStencil + glClipPlane + glColor3b + glColor3bv + glColor3d + glColor3dv + glColor3f + glColor3fv + glColor3i + glColor3iv + glColor3s + glColor3sv + glColor3ub + glColor3ubv + glColor3ui + glColor3uiv + glColor3us + glColor3usv + glColor4b + glColor4bv + glColor4d + glColor4dv + glColor4f + glColor4fv + glColor4i + glColor4iv + glColor4s + glColor4sv + glColor4ub + glColor4ubv + glColor4ui + glColor4uiv + glColor4us + glColor4usv + glColorMask + glColorMaterial + glColorPointer + glCopyPixels + glCopyTexImage1D + glCopyTexImage2D + glCopyTexSubImage1D + glCopyTexSubImage2D + glCullFace +; glDebugEntry + glDeleteLists + glDeleteTextures + glDepthFunc + glDepthMask + glDepthRange + glDisable + glDisableClientState + glDrawArrays + glDrawBuffer + glDrawElements + glDrawPixels + glEdgeFlag + glEdgeFlagPointer + glEdgeFlagv + glEnable + glEnableClientState + glEnd + glEndList + glEvalCoord1d + glEvalCoord1dv + glEvalCoord1f + glEvalCoord1fv + glEvalCoord2d + glEvalCoord2dv + glEvalCoord2f + glEvalCoord2fv + glEvalMesh1 + glEvalMesh2 + glEvalPoint1 + glEvalPoint2 + glFeedbackBuffer + glFinish + glFlush + glFogf + glFogfv + glFogi + glFogiv + glFrontFace + glFrustum + glGenLists + glGenTextures + glGetBooleanv + glGetClipPlane + glGetDoublev + glGetError + glGetFloatv + glGetIntegerv + glGetLightfv + glGetLightiv + glGetMapdv + glGetMapfv + glGetMapiv + glGetMaterialfv + glGetMaterialiv + glGetPixelMapfv + glGetPixelMapuiv + glGetPixelMapusv + glGetPointerv + glGetPolygonStipple + glGetString + glGetTexEnvfv + glGetTexEnviv + glGetTexGendv + glGetTexGenfv + glGetTexGeniv + glGetTexImage + glGetTexLevelParameterfv + glGetTexLevelParameteriv + glGetTexParameterfv + glGetTexParameteriv + glHint + glIndexMask + glIndexPointer + glIndexd + glIndexdv + glIndexf + glIndexfv + glIndexi + glIndexiv + glIndexs + glIndexsv + glIndexub + glIndexubv + glInitNames + glInterleavedArrays + glIsEnabled + glIsList + glIsTexture + glLightModelf + glLightModelfv + glLightModeli + glLightModeliv + glLightf + glLightfv + glLighti + glLightiv + glLineStipple + glLineWidth + glListBase + glLoadIdentity + glLoadMatrixd + glLoadMatrixf + glLoadName + glLogicOp + glMap1d + glMap1f + glMap2d + glMap2f + glMapGrid1d + glMapGrid1f + glMapGrid2d + glMapGrid2f + glMaterialf + glMaterialfv + glMateriali + glMaterialiv + glMatrixMode + glMultMatrixd + glMultMatrixf + glNewList + glNormal3b + glNormal3bv + glNormal3d + glNormal3dv + glNormal3f + glNormal3fv + glNormal3i + glNormal3iv + glNormal3s + glNormal3sv + glNormalPointer + glOrtho + glPassThrough + glPixelMapfv + glPixelMapuiv + glPixelMapusv + glPixelStoref + glPixelStorei + glPixelTransferf + glPixelTransferi + glPixelZoom + glPointSize + glPolygonMode + glPolygonOffset + glPolygonStipple + glPopAttrib + glPopClientAttrib + glPopMatrix + glPopName + glPrioritizeTextures + glPushAttrib + glPushClientAttrib + glPushMatrix + glPushName + glRasterPos2d + glRasterPos2dv + glRasterPos2f + glRasterPos2fv + glRasterPos2i + glRasterPos2iv + glRasterPos2s + glRasterPos2sv + glRasterPos3d + glRasterPos3dv + glRasterPos3f + glRasterPos3fv + glRasterPos3i + glRasterPos3iv + glRasterPos3s + glRasterPos3sv + glRasterPos4d + glRasterPos4dv + glRasterPos4f + glRasterPos4fv + glRasterPos4i + glRasterPos4iv + glRasterPos4s + glRasterPos4sv + glReadBuffer + glReadPixels + glRectd + glRectdv + glRectf + glRectfv + glRecti + glRectiv + glRects + glRectsv + glRenderMode + glRotated + glRotatef + glScaled + glScalef + glScissor + glSelectBuffer + glShadeModel + glStencilFunc + glStencilMask + glStencilOp + glTexCoord1d + glTexCoord1dv + glTexCoord1f + glTexCoord1fv + glTexCoord1i + glTexCoord1iv + glTexCoord1s + glTexCoord1sv + glTexCoord2d + glTexCoord2dv + glTexCoord2f + glTexCoord2fv + glTexCoord2i + glTexCoord2iv + glTexCoord2s + glTexCoord2sv + glTexCoord3d + glTexCoord3dv + glTexCoord3f + glTexCoord3fv + glTexCoord3i + glTexCoord3iv + glTexCoord3s + glTexCoord3sv + glTexCoord4d + glTexCoord4dv + glTexCoord4f + glTexCoord4fv + glTexCoord4i + glTexCoord4iv + glTexCoord4s + glTexCoord4sv + glTexCoordPointer + glTexEnvf + glTexEnvfv + glTexEnvi + glTexEnviv + glTexGend + glTexGendv + glTexGenf + glTexGenfv + glTexGeni + glTexGeniv + glTexImage1D + glTexImage2D + glTexParameterf + glTexParameterfv + glTexParameteri + glTexParameteriv + glTexSubImage1D + glTexSubImage2D + glTranslated + glTranslatef + glVertex2d + glVertex2dv + glVertex2f + glVertex2fv + glVertex2i + glVertex2iv + glVertex2s + glVertex2sv + glVertex3d + glVertex3dv + glVertex3f + glVertex3fv + glVertex3i + glVertex3iv + glVertex3s + glVertex3sv + glVertex4d + glVertex4dv + glVertex4f + glVertex4fv + glVertex4i + glVertex4iv + glVertex4s + glVertex4sv + glVertexPointer + glViewport + wglChoosePixelFormat + wglCopyContext + wglCreateContext + wglCreateLayerContext + wglDeleteContext + wglDescribeLayerPlane + wglDescribePixelFormat + wglGetCurrentContext + wglGetCurrentDC +; wglGetDefaultProcAddress + wglGetLayerPaletteEntries + wglGetPixelFormat + wglGetProcAddress + wglMakeCurrent + wglRealizeLayerPalette + wglSetLayerPaletteEntries + wglSetPixelFormat + wglShareLists + wglSwapBuffers + wglSwapLayerBuffers + wglSwapMultipleBuffers + wglUseFontBitmapsA + wglUseFontBitmapsW + wglUseFontOutlinesA + wglUseFontOutlinesW + DrvCopyContext + DrvCreateContext + DrvCreateLayerContext + DrvDeleteContext + DrvDescribeLayerPlane + DrvDescribePixelFormat + DrvGetLayerPaletteEntries + DrvGetProcAddress + DrvPresentBuffers + DrvRealizeLayerPalette + DrvReleaseContext + DrvSetCallbackProcs + DrvSetContext + DrvSetLayerPaletteEntries + DrvSetPixelFormat + DrvShareLists + DrvSwapBuffers + DrvSwapLayerBuffers + DrvValidateVersion diff --git a/src/gallium/frontends/wgl/opengl32.mingw.def b/src/gallium/frontends/wgl/opengl32.mingw.def new file mode 100644 index 00000000000..0bceee06979 --- /dev/null +++ b/src/gallium/frontends/wgl/opengl32.mingw.def @@ -0,0 +1,388 @@ +EXPORTS +; GlmfBeginGlsBlock = GlmfBeginGlsBlock@4 +; GlmfCloseMetaFile = GlmfCloseMetaFile@4 +; GlmfEndGlsBlock = GlmfEndGlsBlock@4 +; GlmfEndPlayback = GlmfEndPlayback@4 +; GlmfInitPlayback = GlmfInitPlayback@12 +; GlmfPlayGlsRecord = GlmfPlayGlsRecord@16 + glAccum = glAccum@8 + glAlphaFunc = glAlphaFunc@8 + glAreTexturesResident = glAreTexturesResident@12 + glArrayElement = glArrayElement@4 + glBegin = glBegin@4 + glBindTexture = glBindTexture@8 + glBitmap = glBitmap@28 + glBlendFunc = glBlendFunc@8 + glCallList = glCallList@4 + glCallLists = glCallLists@12 + glClear = glClear@4 + glClearAccum = glClearAccum@16 + glClearColor = glClearColor@16 + glClearDepth = glClearDepth@8 + glClearIndex = glClearIndex@4 + glClearStencil = glClearStencil@4 + glClipPlane = glClipPlane@8 + glColor3b = glColor3b@12 + glColor3bv = glColor3bv@4 + glColor3d = glColor3d@24 + glColor3dv = glColor3dv@4 + glColor3f = glColor3f@12 + glColor3fv = glColor3fv@4 + glColor3i = glColor3i@12 + glColor3iv = glColor3iv@4 + glColor3s = glColor3s@12 + glColor3sv = glColor3sv@4 + glColor3ub = glColor3ub@12 + glColor3ubv = glColor3ubv@4 + glColor3ui = glColor3ui@12 + glColor3uiv = glColor3uiv@4 + glColor3us = glColor3us@12 + glColor3usv = glColor3usv@4 + glColor4b = glColor4b@16 + glColor4bv = glColor4bv@4 + glColor4d = glColor4d@32 + glColor4dv = glColor4dv@4 + glColor4f = glColor4f@16 + glColor4fv = glColor4fv@4 + glColor4i = glColor4i@16 + glColor4iv = glColor4iv@4 + glColor4s = glColor4s@16 + glColor4sv = glColor4sv@4 + glColor4ub = glColor4ub@16 + glColor4ubv = glColor4ubv@4 + glColor4ui = glColor4ui@16 + glColor4uiv = glColor4uiv@4 + glColor4us = glColor4us@16 + glColor4usv = glColor4usv@4 + glColorMask = glColorMask@16 + glColorMaterial = glColorMaterial@8 + glColorPointer = glColorPointer@16 + glCopyPixels = glCopyPixels@20 + glCopyTexImage1D = glCopyTexImage1D@28 + glCopyTexImage2D = glCopyTexImage2D@32 + glCopyTexSubImage1D = glCopyTexSubImage1D@24 + glCopyTexSubImage2D = glCopyTexSubImage2D@32 + glCullFace = glCullFace@4 +; glDebugEntry = glDebugEntry@8 + glDeleteLists = glDeleteLists@8 + glDeleteTextures = glDeleteTextures@8 + glDepthFunc = glDepthFunc@4 + glDepthMask = glDepthMask@4 + glDepthRange = glDepthRange@16 + glDisable = glDisable@4 + glDisableClientState = glDisableClientState@4 + glDrawArrays = glDrawArrays@12 + glDrawBuffer = glDrawBuffer@4 + glDrawElements = glDrawElements@16 + glDrawPixels = glDrawPixels@20 + glEdgeFlag = glEdgeFlag@4 + glEdgeFlagPointer = glEdgeFlagPointer@8 + glEdgeFlagv = glEdgeFlagv@4 + glEnable = glEnable@4 + glEnableClientState = glEnableClientState@4 + glEnd = glEnd@0 + glEndList = glEndList@0 + glEvalCoord1d = glEvalCoord1d@8 + glEvalCoord1dv = glEvalCoord1dv@4 + glEvalCoord1f = glEvalCoord1f@4 + glEvalCoord1fv = glEvalCoord1fv@4 + glEvalCoord2d = glEvalCoord2d@16 + glEvalCoord2dv = glEvalCoord2dv@4 + glEvalCoord2f = glEvalCoord2f@8 + glEvalCoord2fv = glEvalCoord2fv@4 + glEvalMesh1 = glEvalMesh1@12 + glEvalMesh2 = glEvalMesh2@20 + glEvalPoint1 = glEvalPoint1@4 + glEvalPoint2 = glEvalPoint2@8 + glFeedbackBuffer = glFeedbackBuffer@12 + glFinish = glFinish@0 + glFlush = glFlush@0 + glFogf = glFogf@8 + glFogfv = glFogfv@8 + glFogi = glFogi@8 + glFogiv = glFogiv@8 + glFrontFace = glFrontFace@4 + glFrustum = glFrustum@48 + glGenLists = glGenLists@4 + glGenTextures = glGenTextures@8 + glGetBooleanv = glGetBooleanv@8 + glGetClipPlane = glGetClipPlane@8 + glGetDoublev = glGetDoublev@8 + glGetError = glGetError@0 + glGetFloatv = glGetFloatv@8 + glGetIntegerv = glGetIntegerv@8 + glGetLightfv = glGetLightfv@12 + glGetLightiv = glGetLightiv@12 + glGetMapdv = glGetMapdv@12 + glGetMapfv = glGetMapfv@12 + glGetMapiv = glGetMapiv@12 + glGetMaterialfv = glGetMaterialfv@12 + glGetMaterialiv = glGetMaterialiv@12 + glGetPixelMapfv = glGetPixelMapfv@8 + glGetPixelMapuiv = glGetPixelMapuiv@8 + glGetPixelMapusv = glGetPixelMapusv@8 + glGetPointerv = glGetPointerv@8 + glGetPolygonStipple = glGetPolygonStipple@4 + glGetString = glGetString@4 + glGetTexEnvfv = glGetTexEnvfv@12 + glGetTexEnviv = glGetTexEnviv@12 + glGetTexGendv = glGetTexGendv@12 + glGetTexGenfv = glGetTexGenfv@12 + glGetTexGeniv = glGetTexGeniv@12 + glGetTexImage = glGetTexImage@20 + glGetTexLevelParameterfv = glGetTexLevelParameterfv@16 + glGetTexLevelParameteriv = glGetTexLevelParameteriv@16 + glGetTexParameterfv = glGetTexParameterfv@12 + glGetTexParameteriv = glGetTexParameteriv@12 + glHint = glHint@8 + glIndexMask = glIndexMask@4 + glIndexPointer = glIndexPointer@12 + glIndexd = glIndexd@8 + glIndexdv = glIndexdv@4 + glIndexf = glIndexf@4 + glIndexfv = glIndexfv@4 + glIndexi = glIndexi@4 + glIndexiv = glIndexiv@4 + glIndexs = glIndexs@4 + glIndexsv = glIndexsv@4 + glIndexub = glIndexub@4 + glIndexubv = glIndexubv@4 + glInitNames = glInitNames@0 + glInterleavedArrays = glInterleavedArrays@12 + glIsEnabled = glIsEnabled@4 + glIsList = glIsList@4 + glIsTexture = glIsTexture@4 + glLightModelf = glLightModelf@8 + glLightModelfv = glLightModelfv@8 + glLightModeli = glLightModeli@8 + glLightModeliv = glLightModeliv@8 + glLightf = glLightf@12 + glLightfv = glLightfv@12 + glLighti = glLighti@12 + glLightiv = glLightiv@12 + glLineStipple = glLineStipple@8 + glLineWidth = glLineWidth@4 + glListBase = glListBase@4 + glLoadIdentity = glLoadIdentity@0 + glLoadMatrixd = glLoadMatrixd@4 + glLoadMatrixf = glLoadMatrixf@4 + glLoadName = glLoadName@4 + glLogicOp = glLogicOp@4 + glMap1d = glMap1d@32 + glMap1f = glMap1f@24 + glMap2d = glMap2d@56 + glMap2f = glMap2f@40 + glMapGrid1d = glMapGrid1d@20 + glMapGrid1f = glMapGrid1f@12 + glMapGrid2d = glMapGrid2d@40 + glMapGrid2f = glMapGrid2f@24 + glMaterialf = glMaterialf@12 + glMaterialfv = glMaterialfv@12 + glMateriali = glMateriali@12 + glMaterialiv = glMaterialiv@12 + glMatrixMode = glMatrixMode@4 + glMultMatrixd = glMultMatrixd@4 + glMultMatrixf = glMultMatrixf@4 + glNewList = glNewList@8 + glNormal3b = glNormal3b@12 + glNormal3bv = glNormal3bv@4 + glNormal3d = glNormal3d@24 + glNormal3dv = glNormal3dv@4 + glNormal3f = glNormal3f@12 + glNormal3fv = glNormal3fv@4 + glNormal3i = glNormal3i@12 + glNormal3iv = glNormal3iv@4 + glNormal3s = glNormal3s@12 + glNormal3sv = glNormal3sv@4 + glNormalPointer = glNormalPointer@12 + glOrtho = glOrtho@48 + glPassThrough = glPassThrough@4 + glPixelMapfv = glPixelMapfv@12 + glPixelMapuiv = glPixelMapuiv@12 + glPixelMapusv = glPixelMapusv@12 + glPixelStoref = glPixelStoref@8 + glPixelStorei = glPixelStorei@8 + glPixelTransferf = glPixelTransferf@8 + glPixelTransferi = glPixelTransferi@8 + glPixelZoom = glPixelZoom@8 + glPointSize = glPointSize@4 + glPolygonMode = glPolygonMode@8 + glPolygonOffset = glPolygonOffset@8 + glPolygonStipple = glPolygonStipple@4 + glPopAttrib = glPopAttrib@0 + glPopClientAttrib = glPopClientAttrib@0 + glPopMatrix = glPopMatrix@0 + glPopName = glPopName@0 + glPrioritizeTextures = glPrioritizeTextures@12 + glPushAttrib = glPushAttrib@4 + glPushClientAttrib = glPushClientAttrib@4 + glPushMatrix = glPushMatrix@0 + glPushName = glPushName@4 + glRasterPos2d = glRasterPos2d@16 + glRasterPos2dv = glRasterPos2dv@4 + glRasterPos2f = glRasterPos2f@8 + glRasterPos2fv = glRasterPos2fv@4 + glRasterPos2i = glRasterPos2i@8 + glRasterPos2iv = glRasterPos2iv@4 + glRasterPos2s = glRasterPos2s@8 + glRasterPos2sv = glRasterPos2sv@4 + glRasterPos3d = glRasterPos3d@24 + glRasterPos3dv = glRasterPos3dv@4 + glRasterPos3f = glRasterPos3f@12 + glRasterPos3fv = glRasterPos3fv@4 + glRasterPos3i = glRasterPos3i@12 + glRasterPos3iv = glRasterPos3iv@4 + glRasterPos3s = glRasterPos3s@12 + glRasterPos3sv = glRasterPos3sv@4 + glRasterPos4d = glRasterPos4d@32 + glRasterPos4dv = glRasterPos4dv@4 + glRasterPos4f = glRasterPos4f@16 + glRasterPos4fv = glRasterPos4fv@4 + glRasterPos4i = glRasterPos4i@16 + glRasterPos4iv = glRasterPos4iv@4 + glRasterPos4s = glRasterPos4s@16 + glRasterPos4sv = glRasterPos4sv@4 + glReadBuffer = glReadBuffer@4 + glReadPixels = glReadPixels@28 + glRectd = glRectd@32 + glRectdv = glRectdv@8 + glRectf = glRectf@16 + glRectfv = glRectfv@8 + glRecti = glRecti@16 + glRectiv = glRectiv@8 + glRects = glRects@16 + glRectsv = glRectsv@8 + glRenderMode = glRenderMode@4 + glRotated = glRotated@32 + glRotatef = glRotatef@16 + glScaled = glScaled@24 + glScalef = glScalef@12 + glScissor = glScissor@16 + glSelectBuffer = glSelectBuffer@8 + glShadeModel = glShadeModel@4 + glStencilFunc = glStencilFunc@12 + glStencilMask = glStencilMask@4 + glStencilOp = glStencilOp@12 + glTexCoord1d = glTexCoord1d@8 + glTexCoord1dv = glTexCoord1dv@4 + glTexCoord1f = glTexCoord1f@4 + glTexCoord1fv = glTexCoord1fv@4 + glTexCoord1i = glTexCoord1i@4 + glTexCoord1iv = glTexCoord1iv@4 + glTexCoord1s = glTexCoord1s@4 + glTexCoord1sv = glTexCoord1sv@4 + glTexCoord2d = glTexCoord2d@16 + glTexCoord2dv = glTexCoord2dv@4 + glTexCoord2f = glTexCoord2f@8 + glTexCoord2fv = glTexCoord2fv@4 + glTexCoord2i = glTexCoord2i@8 + glTexCoord2iv = glTexCoord2iv@4 + glTexCoord2s = glTexCoord2s@8 + glTexCoord2sv = glTexCoord2sv@4 + glTexCoord3d = glTexCoord3d@24 + glTexCoord3dv = glTexCoord3dv@4 + glTexCoord3f = glTexCoord3f@12 + glTexCoord3fv = glTexCoord3fv@4 + glTexCoord3i = glTexCoord3i@12 + glTexCoord3iv = glTexCoord3iv@4 + glTexCoord3s = glTexCoord3s@12 + glTexCoord3sv = glTexCoord3sv@4 + glTexCoord4d = glTexCoord4d@32 + glTexCoord4dv = glTexCoord4dv@4 + glTexCoord4f = glTexCoord4f@16 + glTexCoord4fv = glTexCoord4fv@4 + glTexCoord4i = glTexCoord4i@16 + glTexCoord4iv = glTexCoord4iv@4 + glTexCoord4s = glTexCoord4s@16 + glTexCoord4sv = glTexCoord4sv@4 + glTexCoordPointer = glTexCoordPointer@16 + glTexEnvf = glTexEnvf@12 + glTexEnvfv = glTexEnvfv@12 + glTexEnvi = glTexEnvi@12 + glTexEnviv = glTexEnviv@12 + glTexGend = glTexGend@16 + glTexGendv = glTexGendv@12 + glTexGenf = glTexGenf@12 + glTexGenfv = glTexGenfv@12 + glTexGeni = glTexGeni@12 + glTexGeniv = glTexGeniv@12 + glTexImage1D = glTexImage1D@32 + glTexImage2D = glTexImage2D@36 + glTexParameterf = glTexParameterf@12 + glTexParameterfv = glTexParameterfv@12 + glTexParameteri = glTexParameteri@12 + glTexParameteriv = glTexParameteriv@12 + glTexSubImage1D = glTexSubImage1D@28 + glTexSubImage2D = glTexSubImage2D@36 + glTranslated = glTranslated@24 + glTranslatef = glTranslatef@12 + glVertex2d = glVertex2d@16 + glVertex2dv = glVertex2dv@4 + glVertex2f = glVertex2f@8 + glVertex2fv = glVertex2fv@4 + glVertex2i = glVertex2i@8 + glVertex2iv = glVertex2iv@4 + glVertex2s = glVertex2s@8 + glVertex2sv = glVertex2sv@4 + glVertex3d = glVertex3d@24 + glVertex3dv = glVertex3dv@4 + glVertex3f = glVertex3f@12 + glVertex3fv = glVertex3fv@4 + glVertex3i = glVertex3i@12 + glVertex3iv = glVertex3iv@4 + glVertex3s = glVertex3s@12 + glVertex3sv = glVertex3sv@4 + glVertex4d = glVertex4d@32 + glVertex4dv = glVertex4dv@4 + glVertex4f = glVertex4f@16 + glVertex4fv = glVertex4fv@4 + glVertex4i = glVertex4i@16 + glVertex4iv = glVertex4iv@4 + glVertex4s = glVertex4s@16 + glVertex4sv = glVertex4sv@4 + glVertexPointer = glVertexPointer@16 + glViewport = glViewport@16 + wglChoosePixelFormat = wglChoosePixelFormat@8 + wglCopyContext = wglCopyContext@12 + wglCreateContext = wglCreateContext@4 + wglCreateLayerContext = wglCreateLayerContext@8 + wglDeleteContext = wglDeleteContext@4 + wglDescribeLayerPlane = wglDescribeLayerPlane@20 + wglDescribePixelFormat = wglDescribePixelFormat@16 + wglGetCurrentContext = wglGetCurrentContext@0 + wglGetCurrentDC = wglGetCurrentDC@0 +; wglGetDefaultProcAddress = wglGetDefaultProcAddress@4 + wglGetLayerPaletteEntries = wglGetLayerPaletteEntries@20 + wglGetPixelFormat = wglGetPixelFormat@4 + wglGetProcAddress = wglGetProcAddress@4 + wglMakeCurrent = wglMakeCurrent@8 + wglRealizeLayerPalette = wglRealizeLayerPalette@12 + wglSetLayerPaletteEntries = wglSetLayerPaletteEntries@20 + wglSetPixelFormat = wglSetPixelFormat@12 + wglShareLists = wglShareLists@8 + wglSwapBuffers = wglSwapBuffers@4 + wglSwapLayerBuffers = wglSwapLayerBuffers@8 + wglSwapMultipleBuffers = wglSwapMultipleBuffers@8 + wglUseFontBitmapsA = wglUseFontBitmapsA@16 + wglUseFontBitmapsW = wglUseFontBitmapsW@16 + wglUseFontOutlinesA = wglUseFontOutlinesA@32 + wglUseFontOutlinesW = wglUseFontOutlinesW@32 + DrvCopyContext = DrvCopyContext@12 + DrvCreateContext = DrvCreateContext@4 + DrvCreateLayerContext = DrvCreateLayerContext@8 + DrvDeleteContext = DrvDeleteContext@4 + DrvDescribeLayerPlane = DrvDescribeLayerPlane@20 + DrvDescribePixelFormat = DrvDescribePixelFormat@16 + DrvGetLayerPaletteEntries = DrvGetLayerPaletteEntries@20 + DrvGetProcAddress = DrvGetProcAddress@4 + DrvPresentBuffers = DrvPresentBuffers@8 + DrvRealizeLayerPalette = DrvRealizeLayerPalette@12 + DrvReleaseContext = DrvReleaseContext@4 + DrvSetCallbackProcs = DrvSetCallbackProcs@8 + DrvSetContext = DrvSetContext@12 + DrvSetLayerPaletteEntries = DrvSetLayerPaletteEntries@20 + DrvSetPixelFormat = DrvSetPixelFormat@8 + DrvShareLists = DrvShareLists@8 + DrvSwapBuffers = DrvSwapBuffers@4 + DrvSwapLayerBuffers = DrvSwapLayerBuffers@8 + DrvValidateVersion = DrvValidateVersion@4 diff --git a/src/gallium/frontends/wgl/stw_context.c b/src/gallium/frontends/wgl/stw_context.c new file mode 100644 index 00000000000..57dd85c382d --- /dev/null +++ b/src/gallium/frontends/wgl/stw_context.c @@ -0,0 +1,954 @@ +/************************************************************************** + * + * Copyright 2008 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include + +#define WGL_WGLEXT_PROTOTYPES + +#include +#include + +#include "pipe/p_compiler.h" +#include "pipe/p_context.h" +#include "pipe/p_state.h" +#include "util/u_memory.h" +#include "util/u_atomic.h" +#include "frontend/api.h" +#include "hud/hud_context.h" + +#include "gldrv.h" +#include "stw_device.h" +#include "stw_winsys.h" +#include "stw_framebuffer.h" +#include "stw_pixelformat.h" +#include "stw_context.h" +#include "stw_tls.h" + + +struct stw_context * +stw_current_context(void) +{ + struct st_context_iface *st; + + st = (stw_dev) ? stw_dev->stapi->get_current(stw_dev->stapi) : NULL; + + return (struct stw_context *) ((st) ? st->st_manager_private : NULL); +} + + +BOOL APIENTRY +DrvCopyContext(DHGLRC dhrcSource, DHGLRC dhrcDest, UINT fuMask) +{ + struct stw_context *src; + struct stw_context *dst; + BOOL ret = FALSE; + + if (!stw_dev) + return FALSE; + + stw_lock_contexts(stw_dev); + + src = stw_lookup_context_locked( dhrcSource ); + dst = stw_lookup_context_locked( dhrcDest ); + + if (src && dst) { + /* FIXME */ + assert(0); + (void) src; + (void) dst; + (void) fuMask; + } + + stw_unlock_contexts(stw_dev); + + return ret; +} + + +BOOL APIENTRY +DrvShareLists(DHGLRC dhglrc1, DHGLRC dhglrc2) +{ + struct stw_context *ctx1; + struct stw_context *ctx2; + BOOL ret = FALSE; + + if (!stw_dev) + return FALSE; + + stw_lock_contexts(stw_dev); + + ctx1 = stw_lookup_context_locked( dhglrc1 ); + ctx2 = stw_lookup_context_locked( dhglrc2 ); + + if (ctx1 && ctx2 && ctx2->st->share) { + ret = ctx2->st->share(ctx2->st, ctx1->st); + ctx1->shared = TRUE; + ctx2->shared = TRUE; + } + + stw_unlock_contexts(stw_dev); + + return ret; +} + + +DHGLRC APIENTRY +DrvCreateContext(HDC hdc) +{ + return DrvCreateLayerContext( hdc, 0 ); +} + + +DHGLRC APIENTRY +DrvCreateLayerContext(HDC hdc, INT iLayerPlane) +{ + return stw_create_context_attribs(hdc, iLayerPlane, 0, 1, 0, 0, + WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, + 0); +} + + +/** + * Return the stw pixel format that most closely matches the pixel format + * on HDC. + * Used to get a pixel format when SetPixelFormat() hasn't been called before. + */ +static int +get_matching_pixel_format(HDC hdc) +{ + int iPixelFormat = GetPixelFormat(hdc); + PIXELFORMATDESCRIPTOR pfd; + + if (!iPixelFormat) + return 0; + if (!DescribePixelFormat(hdc, iPixelFormat, sizeof(pfd), &pfd)) + return 0; + return stw_pixelformat_choose(hdc, &pfd); +} + + +/** + * Called via DrvCreateContext(), DrvCreateLayerContext() and + * wglCreateContextAttribsARB() to actually create a rendering context. + * \param handle the desired DHGLRC handle to use for the context, or zero + * if a new handle should be allocated. + * \return the handle for the new context or zero if there was a problem. + */ +DHGLRC +stw_create_context_attribs(HDC hdc, INT iLayerPlane, DHGLRC hShareContext, + int majorVersion, int minorVersion, + int contextFlags, int profileMask, + DHGLRC handle) +{ + int iPixelFormat; + struct stw_framebuffer *fb; + const struct stw_pixelformat_info *pfi; + struct st_context_attribs attribs; + struct stw_context *ctx = NULL; + struct stw_context *shareCtx = NULL; + enum st_context_error ctx_err = 0; + + if (!stw_dev) + return 0; + + if (iLayerPlane != 0) + return 0; + + /* + * GDI only knows about displayable pixel formats, so determine the pixel + * format from the framebuffer. + * + * This also allows to use a OpenGL DLL / ICD without installing. + */ + fb = stw_framebuffer_from_hdc( hdc ); + if (fb) { + iPixelFormat = fb->iPixelFormat; + stw_framebuffer_unlock(fb); + } else { + /* Applications should call SetPixelFormat before creating a context, + * but not all do, and the opengl32 runtime seems to use a default + * pixel format in some cases, so use that. + */ + iPixelFormat = get_matching_pixel_format(hdc); + if (!iPixelFormat) + return 0; + } + + pfi = stw_pixelformat_get_info( iPixelFormat ); + + if (hShareContext != 0) { + stw_lock_contexts(stw_dev); + shareCtx = stw_lookup_context_locked( hShareContext ); + shareCtx->shared = TRUE; + stw_unlock_contexts(stw_dev); + } + + ctx = CALLOC_STRUCT( stw_context ); + if (ctx == NULL) + goto no_ctx; + + ctx->hDrawDC = hdc; + ctx->hReadDC = hdc; + ctx->iPixelFormat = iPixelFormat; + ctx->shared = shareCtx != NULL; + + memset(&attribs, 0, sizeof(attribs)); + attribs.visual = pfi->stvis; + attribs.major = majorVersion; + attribs.minor = minorVersion; + if (contextFlags & WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB) + attribs.flags |= ST_CONTEXT_FLAG_FORWARD_COMPATIBLE; + if (contextFlags & WGL_CONTEXT_DEBUG_BIT_ARB) + attribs.flags |= ST_CONTEXT_FLAG_DEBUG; + + switch (profileMask) { + case WGL_CONTEXT_CORE_PROFILE_BIT_ARB: + /* There are no profiles before OpenGL 3.2. The + * WGL_ARB_create_context_profile spec says: + * + * "If the requested OpenGL version is less than 3.2, + * WGL_CONTEXT_PROFILE_MASK_ARB is ignored and the functionality + * of the context is determined solely by the requested version." + */ + if (majorVersion > 3 || (majorVersion == 3 && minorVersion >= 2)) { + attribs.profile = ST_PROFILE_OPENGL_CORE; + break; + } + /* fall-through */ + case WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB: + /* + * The spec also says: + * + * "If version 3.1 is requested, the context returned may implement + * any of the following versions: + * + * * Version 3.1. The GL_ARB_compatibility extension may or may not + * be implemented, as determined by the implementation. + * * The core profile of version 3.2 or greater." + * + * But Mesa doesn't support GL_ARB_compatibility, while most prevalent + * Windows OpenGL implementations do, and unfortunately many Windows + * applications don't check whether they receive or not a context with + * GL_ARB_compatibility, so returning a core profile here does more harm + * than good. + */ + attribs.profile = ST_PROFILE_DEFAULT; + break; + case WGL_CONTEXT_ES_PROFILE_BIT_EXT: + if (majorVersion >= 2) { + attribs.profile = ST_PROFILE_OPENGL_ES2; + } else { + attribs.profile = ST_PROFILE_OPENGL_ES1; + } + break; + default: + assert(0); + goto no_st_ctx; + } + + ctx->st = stw_dev->stapi->create_context(stw_dev->stapi, + stw_dev->smapi, &attribs, &ctx_err, shareCtx ? shareCtx->st : NULL); + if (ctx->st == NULL) + goto no_st_ctx; + + ctx->st->st_manager_private = (void *) ctx; + + if (ctx->st->cso_context) { + ctx->hud = hud_create(ctx->st->cso_context, NULL); + } + + stw_lock_contexts(stw_dev); + if (handle) { + /* We're replacing the context data for this handle. See the + * wglCreateContextAttribsARB() function. + */ + struct stw_context *old_ctx = + stw_lookup_context_locked((unsigned) handle); + if (old_ctx) { + /* free the old context data associated with this handle */ + if (old_ctx->hud) { + hud_destroy(old_ctx->hud, NULL); + } + ctx->st->destroy(old_ctx->st); + FREE(old_ctx); + } + + /* replace table entry */ + handle_table_set(stw_dev->ctx_table, (unsigned) handle, ctx); + } + else { + /* create new table entry */ + handle = (DHGLRC) handle_table_add(stw_dev->ctx_table, ctx); + } + + ctx->dhglrc = handle; + + stw_unlock_contexts(stw_dev); + + if (!ctx->dhglrc) + goto no_hglrc; + + return ctx->dhglrc; + +no_hglrc: + if (ctx->hud) { + hud_destroy(ctx->hud, NULL); + } + ctx->st->destroy(ctx->st); +no_st_ctx: + FREE(ctx); +no_ctx: + return 0; +} + + +BOOL APIENTRY +DrvDeleteContext(DHGLRC dhglrc) +{ + struct stw_context *ctx ; + BOOL ret = FALSE; + + if (!stw_dev) + return FALSE; + + stw_lock_contexts(stw_dev); + ctx = stw_lookup_context_locked(dhglrc); + handle_table_remove(stw_dev->ctx_table, dhglrc); + stw_unlock_contexts(stw_dev); + + if (ctx) { + struct stw_context *curctx = stw_current_context(); + + /* Unbind current if deleting current context. */ + if (curctx == ctx) + stw_dev->stapi->make_current(stw_dev->stapi, NULL, NULL, NULL); + + if (ctx->hud) { + hud_destroy(ctx->hud, NULL); + } + + ctx->st->destroy(ctx->st); + FREE(ctx); + + ret = TRUE; + } + + return ret; +} + + +BOOL APIENTRY +DrvReleaseContext(DHGLRC dhglrc) +{ + struct stw_context *ctx; + + if (!stw_dev) + return FALSE; + + stw_lock_contexts(stw_dev); + ctx = stw_lookup_context_locked( dhglrc ); + stw_unlock_contexts(stw_dev); + + if (!ctx) + return FALSE; + + /* The expectation is that ctx is the same context which is + * current for this thread. We should check that and return False + * if not the case. + */ + if (ctx != stw_current_context()) + return FALSE; + + if (stw_make_current( NULL, NULL, 0 ) == FALSE) + return FALSE; + + return TRUE; +} + + +DHGLRC +stw_get_current_context( void ) +{ + struct stw_context *ctx; + + ctx = stw_current_context(); + if (!ctx) + return 0; + + return ctx->dhglrc; +} + + +HDC +stw_get_current_dc( void ) +{ + struct stw_context *ctx; + + ctx = stw_current_context(); + if (!ctx) + return NULL; + + return ctx->hDrawDC; +} + +HDC +stw_get_current_read_dc( void ) +{ + struct stw_context *ctx; + + ctx = stw_current_context(); + if (!ctx) + return NULL; + + return ctx->hReadDC; +} + +BOOL +stw_make_current(HDC hDrawDC, HDC hReadDC, DHGLRC dhglrc) +{ + struct stw_context *old_ctx = NULL; + struct stw_context *ctx = NULL; + BOOL ret = FALSE; + + if (!stw_dev) + return FALSE; + + old_ctx = stw_current_context(); + if (old_ctx != NULL) { + if (old_ctx->dhglrc == dhglrc) { + if (old_ctx->hDrawDC == hDrawDC && old_ctx->hReadDC == hReadDC) { + /* Return if already current. */ + return TRUE; + } + } else { + if (old_ctx->shared) { + struct pipe_fence_handle *fence = NULL; + old_ctx->st->flush(old_ctx->st, + ST_FLUSH_FRONT | ST_FLUSH_WAIT, &fence, + NULL, NULL); + } + else { + old_ctx->st->flush(old_ctx->st, ST_FLUSH_FRONT, NULL, NULL, NULL); + } + } + } + + if (dhglrc) { + struct stw_framebuffer *fb = NULL; + struct stw_framebuffer *fbRead = NULL; + stw_lock_contexts(stw_dev); + ctx = stw_lookup_context_locked( dhglrc ); + stw_unlock_contexts(stw_dev); + if (!ctx) { + goto fail; + } + + /* This call locks fb's mutex */ + fb = stw_framebuffer_from_hdc( hDrawDC ); + if (fb) { + stw_framebuffer_update(fb); + } + else { + /* Applications should call SetPixelFormat before creating a context, + * but not all do, and the opengl32 runtime seems to use a default + * pixel format in some cases, so we must create a framebuffer for + * those here. + */ + int iPixelFormat = get_matching_pixel_format(hDrawDC); + if (iPixelFormat) + fb = stw_framebuffer_create( hDrawDC, iPixelFormat ); + if (!fb) + goto fail; + } + + if (fb->iPixelFormat != ctx->iPixelFormat) { + stw_framebuffer_unlock(fb); + SetLastError(ERROR_INVALID_PIXEL_FORMAT); + goto fail; + } + + /* Bind the new framebuffer */ + ctx->hDrawDC = hDrawDC; + ctx->hReadDC = hReadDC; + + struct stw_framebuffer *old_fb = ctx->current_framebuffer; + if (old_fb != fb) { + stw_framebuffer_reference_locked(fb); + ctx->current_framebuffer = fb; + } + stw_framebuffer_unlock(fb); + + if (hReadDC) { + if (hReadDC == hDrawDC) { + fbRead = fb; + } + else { + fbRead = stw_framebuffer_from_hdc( hReadDC ); + + if (fbRead) { + stw_framebuffer_update(fbRead); + } + else { + /* Applications should call SetPixelFormat before creating a + * context, but not all do, and the opengl32 runtime seems to + * use a default pixel format in some cases, so we must create + * a framebuffer for those here. + */ + int iPixelFormat = GetPixelFormat(hReadDC); + if (iPixelFormat) + fbRead = stw_framebuffer_create( hReadDC, iPixelFormat ); + if (!fbRead) + goto fail; + } + + if (fbRead->iPixelFormat != ctx->iPixelFormat) { + stw_framebuffer_unlock(fbRead); + SetLastError(ERROR_INVALID_PIXEL_FORMAT); + goto fail; + } + stw_framebuffer_unlock(fbRead); + } + ret = stw_dev->stapi->make_current(stw_dev->stapi, ctx->st, + fb->stfb, fbRead->stfb); + } + else { + /* Note: when we call this function we will wind up in the + * stw_st_framebuffer_validate_locked() function which will incur + * a recursive fb->mutex lock. + */ + ret = stw_dev->stapi->make_current(stw_dev->stapi, ctx->st, + fb->stfb, fb->stfb); + } + + if (old_fb && old_fb != fb) { + stw_lock_framebuffers(stw_dev); + stw_framebuffer_lock(old_fb); + stw_framebuffer_release_locked(old_fb); + stw_unlock_framebuffers(stw_dev); + } + +fail: + if (fb) { + /* fb must be unlocked at this point. */ + assert(!stw_own_mutex(&fb->mutex)); + } + + /* On failure, make the thread's current rendering context not current + * before returning. + */ + if (!ret) { + stw_make_current(NULL, NULL, 0); + } + } else { + ret = stw_dev->stapi->make_current(stw_dev->stapi, NULL, NULL, NULL); + } + + /* Unreference the previous framebuffer if any. It must be done after + * make_current, as it can be referenced inside. + */ + if (old_ctx && old_ctx != ctx) { + struct stw_framebuffer *old_fb = old_ctx->current_framebuffer; + if (old_fb) { + old_ctx->current_framebuffer = NULL; + stw_lock_framebuffers(stw_dev); + stw_framebuffer_lock(old_fb); + stw_framebuffer_release_locked(old_fb); + stw_unlock_framebuffers(stw_dev); + } + } + + return ret; +} + + +/** + * Notify the current context that the framebuffer has become invalid. + */ +void +stw_notify_current_locked( struct stw_framebuffer *fb ) +{ + p_atomic_inc(&fb->stfb->stamp); +} + + +/** + * Although WGL allows different dispatch entrypoints per context + */ +static const GLCLTPROCTABLE cpt = +{ + OPENGL_VERSION_110_ENTRIES, + { + &glNewList, + &glEndList, + &glCallList, + &glCallLists, + &glDeleteLists, + &glGenLists, + &glListBase, + &glBegin, + &glBitmap, + &glColor3b, + &glColor3bv, + &glColor3d, + &glColor3dv, + &glColor3f, + &glColor3fv, + &glColor3i, + &glColor3iv, + &glColor3s, + &glColor3sv, + &glColor3ub, + &glColor3ubv, + &glColor3ui, + &glColor3uiv, + &glColor3us, + &glColor3usv, + &glColor4b, + &glColor4bv, + &glColor4d, + &glColor4dv, + &glColor4f, + &glColor4fv, + &glColor4i, + &glColor4iv, + &glColor4s, + &glColor4sv, + &glColor4ub, + &glColor4ubv, + &glColor4ui, + &glColor4uiv, + &glColor4us, + &glColor4usv, + &glEdgeFlag, + &glEdgeFlagv, + &glEnd, + &glIndexd, + &glIndexdv, + &glIndexf, + &glIndexfv, + &glIndexi, + &glIndexiv, + &glIndexs, + &glIndexsv, + &glNormal3b, + &glNormal3bv, + &glNormal3d, + &glNormal3dv, + &glNormal3f, + &glNormal3fv, + &glNormal3i, + &glNormal3iv, + &glNormal3s, + &glNormal3sv, + &glRasterPos2d, + &glRasterPos2dv, + &glRasterPos2f, + &glRasterPos2fv, + &glRasterPos2i, + &glRasterPos2iv, + &glRasterPos2s, + &glRasterPos2sv, + &glRasterPos3d, + &glRasterPos3dv, + &glRasterPos3f, + &glRasterPos3fv, + &glRasterPos3i, + &glRasterPos3iv, + &glRasterPos3s, + &glRasterPos3sv, + &glRasterPos4d, + &glRasterPos4dv, + &glRasterPos4f, + &glRasterPos4fv, + &glRasterPos4i, + &glRasterPos4iv, + &glRasterPos4s, + &glRasterPos4sv, + &glRectd, + &glRectdv, + &glRectf, + &glRectfv, + &glRecti, + &glRectiv, + &glRects, + &glRectsv, + &glTexCoord1d, + &glTexCoord1dv, + &glTexCoord1f, + &glTexCoord1fv, + &glTexCoord1i, + &glTexCoord1iv, + &glTexCoord1s, + &glTexCoord1sv, + &glTexCoord2d, + &glTexCoord2dv, + &glTexCoord2f, + &glTexCoord2fv, + &glTexCoord2i, + &glTexCoord2iv, + &glTexCoord2s, + &glTexCoord2sv, + &glTexCoord3d, + &glTexCoord3dv, + &glTexCoord3f, + &glTexCoord3fv, + &glTexCoord3i, + &glTexCoord3iv, + &glTexCoord3s, + &glTexCoord3sv, + &glTexCoord4d, + &glTexCoord4dv, + &glTexCoord4f, + &glTexCoord4fv, + &glTexCoord4i, + &glTexCoord4iv, + &glTexCoord4s, + &glTexCoord4sv, + &glVertex2d, + &glVertex2dv, + &glVertex2f, + &glVertex2fv, + &glVertex2i, + &glVertex2iv, + &glVertex2s, + &glVertex2sv, + &glVertex3d, + &glVertex3dv, + &glVertex3f, + &glVertex3fv, + &glVertex3i, + &glVertex3iv, + &glVertex3s, + &glVertex3sv, + &glVertex4d, + &glVertex4dv, + &glVertex4f, + &glVertex4fv, + &glVertex4i, + &glVertex4iv, + &glVertex4s, + &glVertex4sv, + &glClipPlane, + &glColorMaterial, + &glCullFace, + &glFogf, + &glFogfv, + &glFogi, + &glFogiv, + &glFrontFace, + &glHint, + &glLightf, + &glLightfv, + &glLighti, + &glLightiv, + &glLightModelf, + &glLightModelfv, + &glLightModeli, + &glLightModeliv, + &glLineStipple, + &glLineWidth, + &glMaterialf, + &glMaterialfv, + &glMateriali, + &glMaterialiv, + &glPointSize, + &glPolygonMode, + &glPolygonStipple, + &glScissor, + &glShadeModel, + &glTexParameterf, + &glTexParameterfv, + &glTexParameteri, + &glTexParameteriv, + &glTexImage1D, + &glTexImage2D, + &glTexEnvf, + &glTexEnvfv, + &glTexEnvi, + &glTexEnviv, + &glTexGend, + &glTexGendv, + &glTexGenf, + &glTexGenfv, + &glTexGeni, + &glTexGeniv, + &glFeedbackBuffer, + &glSelectBuffer, + &glRenderMode, + &glInitNames, + &glLoadName, + &glPassThrough, + &glPopName, + &glPushName, + &glDrawBuffer, + &glClear, + &glClearAccum, + &glClearIndex, + &glClearColor, + &glClearStencil, + &glClearDepth, + &glStencilMask, + &glColorMask, + &glDepthMask, + &glIndexMask, + &glAccum, + &glDisable, + &glEnable, + &glFinish, + &glFlush, + &glPopAttrib, + &glPushAttrib, + &glMap1d, + &glMap1f, + &glMap2d, + &glMap2f, + &glMapGrid1d, + &glMapGrid1f, + &glMapGrid2d, + &glMapGrid2f, + &glEvalCoord1d, + &glEvalCoord1dv, + &glEvalCoord1f, + &glEvalCoord1fv, + &glEvalCoord2d, + &glEvalCoord2dv, + &glEvalCoord2f, + &glEvalCoord2fv, + &glEvalMesh1, + &glEvalPoint1, + &glEvalMesh2, + &glEvalPoint2, + &glAlphaFunc, + &glBlendFunc, + &glLogicOp, + &glStencilFunc, + &glStencilOp, + &glDepthFunc, + &glPixelZoom, + &glPixelTransferf, + &glPixelTransferi, + &glPixelStoref, + &glPixelStorei, + &glPixelMapfv, + &glPixelMapuiv, + &glPixelMapusv, + &glReadBuffer, + &glCopyPixels, + &glReadPixels, + &glDrawPixels, + &glGetBooleanv, + &glGetClipPlane, + &glGetDoublev, + &glGetError, + &glGetFloatv, + &glGetIntegerv, + &glGetLightfv, + &glGetLightiv, + &glGetMapdv, + &glGetMapfv, + &glGetMapiv, + &glGetMaterialfv, + &glGetMaterialiv, + &glGetPixelMapfv, + &glGetPixelMapuiv, + &glGetPixelMapusv, + &glGetPolygonStipple, + &glGetString, + &glGetTexEnvfv, + &glGetTexEnviv, + &glGetTexGendv, + &glGetTexGenfv, + &glGetTexGeniv, + &glGetTexImage, + &glGetTexParameterfv, + &glGetTexParameteriv, + &glGetTexLevelParameterfv, + &glGetTexLevelParameteriv, + &glIsEnabled, + &glIsList, + &glDepthRange, + &glFrustum, + &glLoadIdentity, + &glLoadMatrixf, + &glLoadMatrixd, + &glMatrixMode, + &glMultMatrixf, + &glMultMatrixd, + &glOrtho, + &glPopMatrix, + &glPushMatrix, + &glRotated, + &glRotatef, + &glScaled, + &glScalef, + &glTranslated, + &glTranslatef, + &glViewport, + &glArrayElement, + &glBindTexture, + &glColorPointer, + &glDisableClientState, + &glDrawArrays, + &glDrawElements, + &glEdgeFlagPointer, + &glEnableClientState, + &glIndexPointer, + &glIndexub, + &glIndexubv, + &glInterleavedArrays, + &glNormalPointer, + &glPolygonOffset, + &glTexCoordPointer, + &glVertexPointer, + &glAreTexturesResident, + &glCopyTexImage1D, + &glCopyTexImage2D, + &glCopyTexSubImage1D, + &glCopyTexSubImage2D, + &glDeleteTextures, + &glGenTextures, + &glGetPointerv, + &glIsTexture, + &glPrioritizeTextures, + &glTexSubImage1D, + &glTexSubImage2D, + &glPopClientAttrib, + &glPushClientAttrib + } +}; + + +PGLCLTPROCTABLE APIENTRY +DrvSetContext(HDC hdc, DHGLRC dhglrc, PFN_SETPROCTABLE pfnSetProcTable) +{ + PGLCLTPROCTABLE r = (PGLCLTPROCTABLE)&cpt; + + if (!stw_make_current(hdc, hdc, dhglrc)) + r = NULL; + + return r; +} diff --git a/src/gallium/frontends/wgl/stw_context.h b/src/gallium/frontends/wgl/stw_context.h new file mode 100644 index 00000000000..b630fc307df --- /dev/null +++ b/src/gallium/frontends/wgl/stw_context.h @@ -0,0 +1,69 @@ +/************************************************************************** + * + * Copyright 2008 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef STW_CONTEXT_H +#define STW_CONTEXT_H + +#include + +struct hud_context; +struct stw_framebuffer; +struct st_context_iface; + +struct stw_context +{ + struct st_context_iface *st; + DHGLRC dhglrc; + int iPixelFormat; + HDC hDrawDC; + HDC hReadDC; + BOOL shared; + + struct stw_framebuffer *current_framebuffer; + + struct hud_context *hud; +}; + +DHGLRC stw_create_context_attribs(HDC hdc, INT iLayerPlane, + DHGLRC hShareContext, + int majorVersion, int minorVersion, + int contextFlags, int profileMask, + DHGLRC handle); + +DHGLRC stw_get_current_context( void ); + +struct stw_context *stw_current_context(void); + +HDC stw_get_current_dc( void ); + +HDC stw_get_current_read_dc( void ); + +BOOL stw_make_current( HDC hDrawDC, HDC hReadDC, DHGLRC dhglrc ); + +void stw_notify_current_locked( struct stw_framebuffer *fb ); + +#endif /* STW_CONTEXT_H */ diff --git a/src/gallium/frontends/wgl/stw_device.c b/src/gallium/frontends/wgl/stw_device.c new file mode 100644 index 00000000000..f5064da9f29 --- /dev/null +++ b/src/gallium/frontends/wgl/stw_device.c @@ -0,0 +1,263 @@ +/************************************************************************** + * + * Copyright 2008 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include + +#include "glapi/glapi.h" +#include "util/u_debug.h" +#include "util/u_math.h" +#include "util/u_memory.h" +#include "pipe/p_screen.h" + +#include "stw_device.h" +#include "stw_winsys.h" +#include "stw_pixelformat.h" +#include "gldrv.h" +#include "stw_tls.h" +#include "stw_framebuffer.h" +#include "stw_st.h" + + +struct stw_device *stw_dev = NULL; + +static int +stw_get_param(struct st_manager *smapi, + enum st_manager_param param) +{ + switch (param) { + case ST_MANAGER_BROKEN_INVALIDATE: + /* + * Force framebuffer validation on glViewport. + * + * Certain applications, like Rhinoceros 4, uses glReadPixels + * exclusively (never uses SwapBuffers), so framebuffers never get + * resized unless we check on glViewport. + */ + return 1; + default: + return 0; + } +} + + +/** Get the refresh rate for the monitor, in Hz */ +static int +get_refresh_rate(void) +{ + DEVMODE devModes; + + if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &devModes)) { + /* clamp the value, just in case we get garbage */ + return CLAMP(devModes.dmDisplayFrequency, 30, 120); + } + else { + /* reasonable default */ + return 60; + } +} + +static bool +init_screen(const struct stw_winsys *stw_winsys) +{ + struct pipe_screen *screen = stw_winsys->create_screen(); + if (!screen) + return false; + + if (stw_winsys->get_adapter_luid) + stw_winsys->get_adapter_luid(screen, &stw_dev->AdapterLuid); + + stw_dev->smapi->screen = screen; + stw_dev->screen = screen; + + stw_dev->max_2d_length = screen->get_param(screen, + PIPE_CAP_MAX_TEXTURE_2D_SIZE); + return true; +} + +boolean +stw_init(const struct stw_winsys *stw_winsys) +{ + static struct stw_device stw_dev_storage; + + debug_disable_error_message_boxes(); + + assert(!stw_dev); + + stw_tls_init(); + + stw_dev = &stw_dev_storage; + memset(stw_dev, 0, sizeof(*stw_dev)); + + stw_dev->stw_winsys = stw_winsys; + + stw_dev->stapi = stw_st_create_api(); + stw_dev->smapi = CALLOC_STRUCT(st_manager); + if (!stw_dev->stapi || !stw_dev->smapi) + goto error1; + + stw_dev->smapi->get_param = stw_get_param; + + InitializeCriticalSection(&stw_dev->screen_mutex); + InitializeCriticalSection(&stw_dev->ctx_mutex); + InitializeCriticalSection(&stw_dev->fb_mutex); + + stw_dev->ctx_table = handle_table_create(); + if (!stw_dev->ctx_table) { + goto error1; + } + + /* env var override for WGL_EXT_swap_control, useful for testing/debugging */ + const char *s = os_get_option("WGL_SWAP_INTERVAL"); + if (s) { + stw_dev->swap_interval = atoi(s); + } + stw_dev->refresh_rate = get_refresh_rate(); + + stw_dev->initialized = true; + + return TRUE; + +error1: + FREE(stw_dev->smapi); + if (stw_dev->stapi) + stw_dev->stapi->destroy(stw_dev->stapi); + + stw_dev = NULL; + return FALSE; +} + +boolean +stw_init_screen() +{ + EnterCriticalSection(&stw_dev->screen_mutex); + + if (!stw_dev->screen_initialized) { + stw_dev->screen_initialized = true; + if (!init_screen(stw_dev->stw_winsys)) { + LeaveCriticalSection(&stw_dev->screen_mutex); + return false; + } + stw_pixelformat_init(); + } + + LeaveCriticalSection(&stw_dev->screen_mutex); + return stw_dev->screen != NULL; +} + +boolean +stw_init_thread(void) +{ + return stw_tls_init_thread(); +} + + +void +stw_cleanup_thread(void) +{ + stw_tls_cleanup_thread(); +} + + +void +stw_cleanup(void) +{ + DHGLRC dhglrc; + + debug_printf("%s\n", __FUNCTION__); + + if (!stw_dev) + return; + + /* + * Abort cleanup if there are still active contexts. In some situations + * this DLL may be unloaded before the DLL that is using GL contexts is. + */ + stw_lock_contexts(stw_dev); + dhglrc = handle_table_get_first_handle(stw_dev->ctx_table); + stw_unlock_contexts(stw_dev); + if (dhglrc) { + debug_printf("%s: contexts still active -- cleanup aborted\n", __FUNCTION__); + stw_dev = NULL; + return; + } + + handle_table_destroy(stw_dev->ctx_table); + + stw_framebuffer_cleanup(); + + DeleteCriticalSection(&stw_dev->fb_mutex); + DeleteCriticalSection(&stw_dev->ctx_mutex); + DeleteCriticalSection(&stw_dev->screen_mutex); + + if (stw_dev->smapi->destroy) + stw_dev->smapi->destroy(stw_dev->smapi); + + FREE(stw_dev->smapi); + stw_dev->stapi->destroy(stw_dev->stapi); + + stw_dev->screen->destroy(stw_dev->screen); + + /* glapi is statically linked: we can call the local destroy function. */ +#ifdef _GLAPI_NO_EXPORTS + _glapi_destroy_multithread(); +#endif + + stw_tls_cleanup(); + + stw_dev = NULL; +} + + +void APIENTRY +DrvSetCallbackProcs(INT nProcs, PROC *pProcs) +{ + size_t size; + + if (stw_dev == NULL) + return; + + size = MIN2(nProcs * sizeof *pProcs, sizeof stw_dev->callbacks); + memcpy(&stw_dev->callbacks, pProcs, size); + + return; +} + + +BOOL APIENTRY +DrvValidateVersion(ULONG ulVersion) +{ + /* ulVersion is the version reported by the KMD: + * - via D3DKMTQueryAdapterInfo(KMTQAITYPE_UMOPENGLINFO) on WDDM, + * - or ExtEscape on XPDM and can be used to ensure the KMD and OpenGL ICD + * versions match. + * + * We should get the expected version number from the winsys, but for now + * ignore it. + */ + (void)ulVersion; + return TRUE; +} diff --git a/src/gallium/frontends/wgl/stw_device.h b/src/gallium/frontends/wgl/stw_device.h new file mode 100644 index 00000000000..a2cd6c7487c --- /dev/null +++ b/src/gallium/frontends/wgl/stw_device.h @@ -0,0 +1,133 @@ +/************************************************************************** + * + * Copyright 2008 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef STW_DEVICE_H_ +#define STW_DEVICE_H_ + + +#include "pipe/p_compiler.h" +#include "util/u_handle_table.h" +#include +#include "gldrv.h" +#include "stw_pixelformat.h" + + +#define STW_MAX_PIXELFORMATS 256 + + +struct pipe_screen; +struct st_api; +struct st_manager; +struct stw_framebuffer; + +struct stw_device +{ + const struct stw_winsys *stw_winsys; + + CRITICAL_SECTION screen_mutex; + bool screen_initialized; + struct pipe_screen *screen; + + /* Cache some PIPE_CAP_* */ + unsigned max_2d_length; + + struct st_api *stapi; + struct st_manager *smapi; + + LUID AdapterLuid; + + struct stw_pixelformat_info pixelformats[STW_MAX_PIXELFORMATS]; + unsigned pixelformat_count; + unsigned pixelformat_extended_count; + + struct WGLCALLBACKS callbacks; + + CRITICAL_SECTION ctx_mutex; + struct handle_table *ctx_table; + + /* TODO: use an atomic counter to track the number of locked + * stw_framebuffer objects. Assert that the counter is zero when + * trying to lock this mutex. + */ + CRITICAL_SECTION fb_mutex; + struct stw_framebuffer *fb_head; + +#ifdef DEBUG + unsigned long memdbg_no; +#endif + + /** WGL_EXT_swap_control */ + int refresh_rate; + int swap_interval; + + bool initialized; +}; + + +extern struct stw_device *stw_dev; + +boolean +stw_init_screen(void); + +static inline struct stw_context * +stw_lookup_context_locked( DHGLRC dhglrc ) +{ + if (dhglrc == 0 || stw_dev == NULL) + return NULL; + return (struct stw_context *) handle_table_get(stw_dev->ctx_table, dhglrc); +} + + +static inline void +stw_lock_contexts(struct stw_device *stw_dev) +{ + EnterCriticalSection(&stw_dev->ctx_mutex); +} + + +static inline void +stw_unlock_contexts(struct stw_device *stw_dev) +{ + LeaveCriticalSection(&stw_dev->ctx_mutex); +} + + +static inline void +stw_lock_framebuffers(struct stw_device *stw_dev) +{ + EnterCriticalSection(&stw_dev->fb_mutex); +} + + +static inline void +stw_unlock_framebuffers(struct stw_device *stw_dev) +{ + LeaveCriticalSection(&stw_dev->fb_mutex); +} + + +#endif /* STW_DEVICE_H_ */ diff --git a/src/gallium/frontends/wgl/stw_ext_context.c b/src/gallium/frontends/wgl/stw_ext_context.c new file mode 100644 index 00000000000..4171987f89c --- /dev/null +++ b/src/gallium/frontends/wgl/stw_ext_context.c @@ -0,0 +1,212 @@ +/* + * Mesa 3-D graphics library + * + * Copyright (C) 2011 Morgan Armand + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include + +#define WGL_WGLEXT_PROTOTYPES + +#include +#include + +#include "gldrv.h" +#include "stw_context.h" +#include "stw_device.h" +#include "stw_ext_context.h" + +#include "util/u_debug.h" + + +wglCreateContext_t wglCreateContext_func = 0; +wglDeleteContext_t wglDeleteContext_func = 0; + + +/** + * The implementation of this function is tricky. The OPENGL32.DLL library + * remaps the context IDs returned by our stw_create_context_attribs() + * function to different values returned to the caller of wglCreateContext(). + * That is, DHGLRC (driver) handles are not equivalent to HGLRC (public) + * handles. + * + * So we need to generate a new HGLRC ID here. We do that by calling + * the regular wglCreateContext() function. Then, we replace the newly- + * created stw_context with a new stw_context that reflects the arguments + * to this function. + */ +HGLRC WINAPI +wglCreateContextAttribsARB(HDC hDC, HGLRC hShareContext, const int *attribList) +{ + HGLRC context; + + int majorVersion = 1, minorVersion = 0, layerPlane = 0; + int contextFlags = 0x0; + int profileMask = WGL_CONTEXT_CORE_PROFILE_BIT_ARB; + int i; + BOOL done = FALSE; + const int contextFlagsAll = (WGL_CONTEXT_DEBUG_BIT_ARB | + WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB); + + /* parse attrib_list */ + if (attribList) { + for (i = 0; !done && attribList[i]; i++) { + switch (attribList[i]) { + case WGL_CONTEXT_MAJOR_VERSION_ARB: + majorVersion = attribList[++i]; + break; + case WGL_CONTEXT_MINOR_VERSION_ARB: + minorVersion = attribList[++i]; + break; + case WGL_CONTEXT_LAYER_PLANE_ARB: + layerPlane = attribList[++i]; + break; + case WGL_CONTEXT_FLAGS_ARB: + contextFlags = attribList[++i]; + break; + case WGL_CONTEXT_PROFILE_MASK_ARB: + profileMask = attribList[++i]; + break; + case 0: + /* end of list */ + done = TRUE; + break; + default: + /* bad attribute */ + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + } + } + + /* check contextFlags */ + if (contextFlags & ~contextFlagsAll) { + SetLastError(ERROR_INVALID_PARAMETER); + return NULL; + } + + /* check profileMask */ + if (profileMask != WGL_CONTEXT_CORE_PROFILE_BIT_ARB && + profileMask != WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB && + profileMask != WGL_CONTEXT_ES_PROFILE_BIT_EXT) { + SetLastError(ERROR_INVALID_PROFILE_ARB); + return NULL; + } + + /* check version (generate ERROR_INVALID_VERSION_ARB if bad) */ + if (majorVersion <= 0 || + minorVersion < 0 || + (profileMask != WGL_CONTEXT_ES_PROFILE_BIT_EXT && + ((majorVersion == 1 && minorVersion > 5) || + (majorVersion == 2 && minorVersion > 1) || + (majorVersion == 3 && minorVersion > 3) || + (majorVersion == 4 && minorVersion > 5) || + majorVersion > 4)) || + (profileMask == WGL_CONTEXT_ES_PROFILE_BIT_EXT && + ((majorVersion == 1 && minorVersion > 1) || + (majorVersion == 2 && minorVersion > 0) || + (majorVersion == 3 && minorVersion > 1) || + majorVersion > 3))) { + SetLastError(ERROR_INVALID_VERSION_ARB); + return NULL; + } + + if ((contextFlags & WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB) && + majorVersion < 3) { + SetLastError(ERROR_INVALID_VERSION_ARB); + return 0; + } + + /* Get pointer to OPENGL32.DLL's wglCreate/DeleteContext() functions */ + if (!wglCreateContext_func || !wglDeleteContext_func) { + /* Get the OPENGL32.DLL library */ + HMODULE opengl_lib = GetModuleHandleA("opengl32.dll"); + if (!opengl_lib) { + _debug_printf("wgl: GetModuleHandleA(\"opengl32.dll\") failed\n"); + return 0; + } + + /* Get pointer to wglCreateContext() function */ + wglCreateContext_func = (wglCreateContext_t) + GetProcAddress(opengl_lib, "wglCreateContext"); + if (!wglCreateContext_func) { + _debug_printf("wgl: failed to get wglCreateContext()\n"); + return 0; + } + + /* Get pointer to wglDeleteContext() function */ + wglDeleteContext_func = (wglDeleteContext_t) + GetProcAddress(opengl_lib, "wglDeleteContext"); + if (!wglDeleteContext_func) { + _debug_printf("wgl: failed to get wglDeleteContext()\n"); + return 0; + } + } + + /* Call wglCreateContext to get a valid context ID */ + context = wglCreateContext_func(hDC); + + if (context) { + /* Now replace the context we just created with a new one that reflects + * the attributes passed to this function. + */ + DHGLRC dhglrc, c, share_dhglrc = 0; + + /* Convert public HGLRC to driver DHGLRC */ + if (stw_dev && stw_dev->callbacks.pfnGetDhglrc) { + dhglrc = stw_dev->callbacks.pfnGetDhglrc(context); + if (hShareContext) + share_dhglrc = stw_dev->callbacks.pfnGetDhglrc(hShareContext); + } + else { + /* not using ICD */ + dhglrc = (DHGLRC)(INT_PTR)context; + share_dhglrc = (DHGLRC)(INT_PTR)hShareContext; + } + + c = stw_create_context_attribs(hDC, layerPlane, share_dhglrc, + majorVersion, minorVersion, + contextFlags, profileMask, + dhglrc); + if (!c) { + wglDeleteContext_func(context); + context = 0; + } + } + + return context; +} + + +/** Defined by WGL_ARB_make_current_read */ +BOOL APIENTRY +wglMakeContextCurrentARB(HDC hDrawDC, HDC hReadDC, HGLRC hglrc) +{ + DHGLRC dhglrc = 0; + + if (stw_dev && stw_dev->callbacks.pfnGetDhglrc) { + /* Convert HGLRC to DHGLRC */ + dhglrc = stw_dev->callbacks.pfnGetDhglrc(hglrc); + } + + return stw_make_current(hDrawDC, hReadDC, dhglrc); +} diff --git a/src/gallium/frontends/wgl/stw_ext_context.h b/src/gallium/frontends/wgl/stw_ext_context.h new file mode 100644 index 00000000000..d0337490436 --- /dev/null +++ b/src/gallium/frontends/wgl/stw_ext_context.h @@ -0,0 +1,38 @@ +/* + * Mesa 3-D graphics library + * + * Copyright (C) 2011 Morgan Armand + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef STW_EXT_CONTEXT_H +#define STW_EXT_CONTEXT_H + +#include +#include + + +typedef HGLRC (WINAPI *wglCreateContext_t)(HDC hdc); +typedef BOOL (WINAPI *wglDeleteContext_t)(HGLRC hglrc); + +extern wglCreateContext_t wglCreateContext_func; +extern wglDeleteContext_t wglDeleteContext_func; + +#endif /* STW_EXT_CONTEXT_H */ diff --git a/src/gallium/frontends/wgl/stw_ext_extensionsstring.c b/src/gallium/frontends/wgl/stw_ext_extensionsstring.c new file mode 100644 index 00000000000..904ac151490 --- /dev/null +++ b/src/gallium/frontends/wgl/stw_ext_extensionsstring.c @@ -0,0 +1,68 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * Copyright 2008 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include + +#define WGL_WGLEXT_PROTOTYPES + +#include +#include + + +static const char *stw_extension_string = + "WGL_ARB_create_context " + "WGL_ARB_create_context_profile " + "WGL_ARB_extensions_string " + "WGL_ARB_make_current_read " + "WGL_ARB_multisample " + "WGL_ARB_pbuffer " + "WGL_ARB_pixel_format " + "WGL_ARB_render_texture " + "WGL_EXT_create_context_es_profile " + "WGL_EXT_create_context_es2_profile " + "WGL_EXT_extensions_string " + "WGL_EXT_swap_control"; + + +WINGDIAPI const char * APIENTRY +wglGetExtensionsStringARB( + HDC hdc ) +{ + if (!hdc) { + return NULL; + } + + return stw_extension_string; +} + + +WINGDIAPI const char * APIENTRY +wglGetExtensionsStringEXT( void ) +{ + return stw_extension_string; +} diff --git a/src/gallium/frontends/wgl/stw_ext_pbuffer.c b/src/gallium/frontends/wgl/stw_ext_pbuffer.c new file mode 100644 index 00000000000..02ccb76e277 --- /dev/null +++ b/src/gallium/frontends/wgl/stw_ext_pbuffer.c @@ -0,0 +1,377 @@ +/************************************************************************** + * + * Copyright 2010 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include + +#define WGL_WGLEXT_PROTOTYPES + +#include +#include + +#include "pipe/p_defines.h" +#include "pipe/p_screen.h" + +#include "util/u_debug.h" + +#include "stw_device.h" +#include "stw_pixelformat.h" +#include "stw_framebuffer.h" + + +#define LARGE_WINDOW_SIZE 60000 + + +static LRESULT CALLBACK +WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + MINMAXINFO *pMMI; + switch (uMsg) { + case WM_GETMINMAXINFO: + // Allow to create a window bigger than the desktop + pMMI = (MINMAXINFO *)lParam; + pMMI->ptMaxSize.x = LARGE_WINDOW_SIZE; + pMMI->ptMaxSize.y = LARGE_WINDOW_SIZE; + pMMI->ptMaxTrackSize.x = LARGE_WINDOW_SIZE; + pMMI->ptMaxTrackSize.y = LARGE_WINDOW_SIZE; + break; + default: + break; + } + + return DefWindowProc(hWnd, uMsg, wParam, lParam); +} + + +HPBUFFERARB WINAPI +wglCreatePbufferARB(HDC hCurrentDC, + int iPixelFormat, + int iWidth, + int iHeight, + const int *piAttribList) +{ + static boolean first = TRUE; + const int *piAttrib; + int useLargest = 0; + const struct stw_pixelformat_info *info; + struct stw_framebuffer *fb; + DWORD dwExStyle; + DWORD dwStyle; + RECT rect; + HWND hWnd; + HDC hDC; + int iDisplayablePixelFormat; + PIXELFORMATDESCRIPTOR pfd; + BOOL bRet; + int textureFormat = WGL_NO_TEXTURE_ARB; + int textureTarget = WGL_NO_TEXTURE_ARB; + BOOL textureMipmap = FALSE; + + info = stw_pixelformat_get_info(iPixelFormat - 1); + if (!info) { + SetLastError(ERROR_INVALID_PIXEL_FORMAT); + return 0; + } + + if (iWidth <= 0 || iHeight <= 0) { + SetLastError(ERROR_INVALID_DATA); + return 0; + } + + if (piAttribList) { + for (piAttrib = piAttribList; *piAttrib; piAttrib++) { + switch (*piAttrib) { + case WGL_PBUFFER_LARGEST_ARB: + piAttrib++; + useLargest = *piAttrib; + break; + case WGL_TEXTURE_FORMAT_ARB: + /* WGL_ARB_render_texture */ + piAttrib++; + textureFormat = *piAttrib; + if (textureFormat != WGL_TEXTURE_RGB_ARB && + textureFormat != WGL_TEXTURE_RGBA_ARB && + textureFormat != WGL_NO_TEXTURE_ARB) { + SetLastError(ERROR_INVALID_DATA); + return 0; + } + break; + case WGL_TEXTURE_TARGET_ARB: + /* WGL_ARB_render_texture */ + piAttrib++; + textureTarget = *piAttrib; + if (textureTarget != WGL_TEXTURE_CUBE_MAP_ARB && + textureTarget != WGL_TEXTURE_1D_ARB && + textureTarget != WGL_TEXTURE_2D_ARB && + textureTarget != WGL_NO_TEXTURE_ARB) { + SetLastError(ERROR_INVALID_DATA); + return 0; + } + break; + case WGL_MIPMAP_TEXTURE_ARB: + /* WGL_ARB_render_texture */ + piAttrib++; + textureMipmap = !!*piAttrib; + break; + default: + SetLastError(ERROR_INVALID_DATA); + debug_printf("wgl: Unsupported attribute 0x%x in %s\n", + *piAttrib, __func__); + return 0; + } + } + } + + if (iWidth > stw_dev->max_2d_length) { + if (useLargest) { + iWidth = stw_dev->max_2d_length; + } else { + SetLastError(ERROR_NO_SYSTEM_RESOURCES); + return 0; + } + } + + if (iHeight > stw_dev->max_2d_length) { + if (useLargest) { + iHeight = stw_dev->max_2d_length; + } else { + SetLastError(ERROR_NO_SYSTEM_RESOURCES); + return 0; + } + } + + /* + * Implement pbuffers through invisible windows + */ + + if (first) { + WNDCLASS wc; + memset(&wc, 0, sizeof wc); + wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); + wc.lpfnWndProc = WndProc; + wc.lpszClassName = "wglpbuffer"; + wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW; + RegisterClass(&wc); + first = FALSE; + } + + dwExStyle = 0; + dwStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN; + + if (0) { + /* + * Don't hide the window -- useful for debugging what the application is + * drawing + */ + + dwStyle |= WS_VISIBLE | WS_OVERLAPPEDWINDOW; + } else { + dwStyle |= WS_POPUPWINDOW; + } + + rect.left = 0; + rect.top = 0; + rect.right = rect.left + iWidth; + rect.bottom = rect.top + iHeight; + + /* + * The CreateWindowEx parameters are the total (outside) dimensions of the + * window, which can vary with Windows version and user settings. Use + * AdjustWindowRect to get the required total area for the given client area. + * + * AdjustWindowRectEx does not accept WS_OVERLAPPED style (which is defined + * as 0), which means we need to use some other style instead, e.g., + * WS_OVERLAPPEDWINDOW or WS_POPUPWINDOW as above. + */ + + AdjustWindowRectEx(&rect, dwStyle, FALSE, dwExStyle); + + hWnd = CreateWindowEx(dwExStyle, + "wglpbuffer", /* wc.lpszClassName */ + NULL, + dwStyle, + CW_USEDEFAULT, /* x */ + CW_USEDEFAULT, /* y */ + rect.right - rect.left, /* width */ + rect.bottom - rect.top, /* height */ + NULL, + NULL, + NULL, + NULL); + if (!hWnd) { + return 0; + } + +#ifdef DEBUG + /* + * Verify the client area size matches the specified size. + */ + + GetClientRect(hWnd, &rect); + assert(rect.left == 0); + assert(rect.top == 0); + assert(rect.right - rect.left == iWidth); + assert(rect.bottom - rect.top == iHeight); +#endif + + hDC = GetDC(hWnd); + if (!hDC) { + return 0; + } + + /* + * We can't pass non-displayable pixel formats to GDI, which is why we + * create the framebuffer object before calling SetPixelFormat(). + */ + fb = stw_framebuffer_create(hDC, iPixelFormat); + if (!fb) { + SetLastError(ERROR_NO_SYSTEM_RESOURCES); + return NULL; + } + + fb->bPbuffer = TRUE; + + /* WGL_ARB_render_texture fields */ + fb->textureTarget = textureTarget; + fb->textureFormat = textureFormat; + fb->textureMipmap = textureMipmap; + + iDisplayablePixelFormat = fb->iDisplayablePixelFormat; + + stw_framebuffer_unlock(fb); + + /* + * We need to set a displayable pixel format on the hidden window DC + * so that wglCreateContext and wglMakeCurrent are not overruled by GDI. + */ + bRet = SetPixelFormat(hDC, iDisplayablePixelFormat, &pfd); + assert(bRet); + + return (HPBUFFERARB)fb; +} + + +HDC WINAPI +wglGetPbufferDCARB(HPBUFFERARB hPbuffer) +{ + struct stw_framebuffer *fb; + HDC hDC; + + if (!hPbuffer) { + SetLastError(ERROR_INVALID_HANDLE); + return NULL; + } + + fb = stw_framebuffer_from_HPBUFFERARB(hPbuffer); + + hDC = GetDC(fb->hWnd); + + return hDC; +} + + +int WINAPI +wglReleasePbufferDCARB(HPBUFFERARB hPbuffer, + HDC hDC) +{ + struct stw_framebuffer *fb; + + if (!hPbuffer) { + SetLastError(ERROR_INVALID_HANDLE); + return 0; + } + + fb = stw_framebuffer_from_HPBUFFERARB(hPbuffer); + + return ReleaseDC(fb->hWnd, hDC); +} + + +BOOL WINAPI +wglDestroyPbufferARB(HPBUFFERARB hPbuffer) +{ + struct stw_framebuffer *fb; + + if (!hPbuffer) { + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + fb = stw_framebuffer_from_HPBUFFERARB(hPbuffer); + + /* This will destroy all our data */ + return DestroyWindow(fb->hWnd); +} + + +BOOL WINAPI +wglQueryPbufferARB(HPBUFFERARB hPbuffer, + int iAttribute, + int *piValue) +{ + struct stw_framebuffer *fb; + + if (!hPbuffer) { + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + fb = stw_framebuffer_from_HPBUFFERARB(hPbuffer); + + switch (iAttribute) { + case WGL_PBUFFER_WIDTH_ARB: + *piValue = fb->width; + return TRUE; + case WGL_PBUFFER_HEIGHT_ARB: + *piValue = fb->height; + return TRUE; + case WGL_PBUFFER_LOST_ARB: + /* We assume that no content is ever lost due to display mode change */ + *piValue = FALSE; + return TRUE; + /* WGL_ARB_render_texture */ + case WGL_TEXTURE_TARGET_ARB: + *piValue = fb->textureTarget; + return TRUE; + case WGL_TEXTURE_FORMAT_ARB: + *piValue = fb->textureFormat; + return TRUE; + case WGL_MIPMAP_TEXTURE_ARB: + *piValue = fb->textureMipmap; + return TRUE; + case WGL_MIPMAP_LEVEL_ARB: + *piValue = fb->textureLevel; + return TRUE; + case WGL_CUBE_MAP_FACE_ARB: + *piValue = fb->textureFace + WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB; + return TRUE; + default: + SetLastError(ERROR_INVALID_DATA); + return FALSE; + } +} diff --git a/src/gallium/frontends/wgl/stw_ext_pixelformat.c b/src/gallium/frontends/wgl/stw_ext_pixelformat.c new file mode 100644 index 00000000000..8fc6da1df2e --- /dev/null +++ b/src/gallium/frontends/wgl/stw_ext_pixelformat.c @@ -0,0 +1,518 @@ +/************************************************************************** + * + * Copyright 2008 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/** + * @file + * + * WGL_ARB_pixel_format extension implementation. + * + * @sa http://www.opengl.org/registry/specs/ARB/wgl_pixel_format.txt + */ + + +#include + +#define WGL_WGLEXT_PROTOTYPES + +#include +#include + +#include "pipe/p_compiler.h" +#include "util/format/u_format.h" +#include "util/u_memory.h" +#include "stw_device.h" +#include "stw_pixelformat.h" + + +static boolean +stw_query_attrib(int iPixelFormat, int iLayerPlane, int attrib, int *pvalue) +{ + uint count; + const struct stw_pixelformat_info *pfi; + + count = stw_pixelformat_get_extended_count(); + + if (attrib == WGL_NUMBER_PIXEL_FORMATS_ARB) { + *pvalue = (int) count; + return TRUE; + } + + pfi = stw_pixelformat_get_info(iPixelFormat); + if (!pfi) { + return FALSE; + } + + switch (attrib) { + case WGL_DRAW_TO_WINDOW_ARB: + *pvalue = pfi->pfd.dwFlags & PFD_DRAW_TO_WINDOW ? TRUE : FALSE; + return TRUE; + + case WGL_DRAW_TO_BITMAP_ARB: + *pvalue = pfi->pfd.dwFlags & PFD_DRAW_TO_BITMAP ? TRUE : FALSE; + return TRUE; + + case WGL_NEED_PALETTE_ARB: + *pvalue = pfi->pfd.dwFlags & PFD_NEED_PALETTE ? TRUE : FALSE; + return TRUE; + + case WGL_NEED_SYSTEM_PALETTE_ARB: + *pvalue = pfi->pfd.dwFlags & PFD_NEED_SYSTEM_PALETTE ? TRUE : FALSE; + return TRUE; + + case WGL_SWAP_METHOD_ARB: + if (pfi->pfd.dwFlags & PFD_SWAP_COPY) + *pvalue = WGL_SWAP_COPY_ARB; + else if (pfi->pfd.dwFlags & PFD_SWAP_EXCHANGE) + *pvalue = WGL_SWAP_EXCHANGE_EXT; + else + *pvalue = WGL_SWAP_UNDEFINED_ARB; + return TRUE; + + case WGL_SWAP_LAYER_BUFFERS_ARB: + *pvalue = FALSE; + return TRUE; + + case WGL_NUMBER_OVERLAYS_ARB: + *pvalue = 0; + return TRUE; + + case WGL_NUMBER_UNDERLAYS_ARB: + *pvalue = 0; + return TRUE; + + case WGL_BIND_TO_TEXTURE_RGB_ARB: + /* WGL_ARB_render_texture */ + *pvalue = pfi->bindToTextureRGB; + return TRUE; + + case WGL_BIND_TO_TEXTURE_RGBA_ARB: + /* WGL_ARB_render_texture */ + *pvalue = pfi->bindToTextureRGBA; + return TRUE; + } + + if (iLayerPlane != 0) + return FALSE; + + switch (attrib) { + case WGL_ACCELERATION_ARB: + *pvalue = WGL_FULL_ACCELERATION_ARB; + break; + + case WGL_TRANSPARENT_ARB: + *pvalue = FALSE; + break; + + case WGL_TRANSPARENT_RED_VALUE_ARB: + case WGL_TRANSPARENT_GREEN_VALUE_ARB: + case WGL_TRANSPARENT_BLUE_VALUE_ARB: + case WGL_TRANSPARENT_ALPHA_VALUE_ARB: + case WGL_TRANSPARENT_INDEX_VALUE_ARB: + break; + + case WGL_SHARE_DEPTH_ARB: + case WGL_SHARE_STENCIL_ARB: + case WGL_SHARE_ACCUM_ARB: + *pvalue = TRUE; + break; + + case WGL_SUPPORT_GDI_ARB: + *pvalue = pfi->pfd.dwFlags & PFD_SUPPORT_GDI ? TRUE : FALSE; + break; + + case WGL_SUPPORT_OPENGL_ARB: + *pvalue = pfi->pfd.dwFlags & PFD_SUPPORT_OPENGL ? TRUE : FALSE; + break; + + case WGL_DOUBLE_BUFFER_ARB: + *pvalue = pfi->pfd.dwFlags & PFD_DOUBLEBUFFER ? TRUE : FALSE; + break; + + case WGL_STEREO_ARB: + *pvalue = pfi->pfd.dwFlags & PFD_STEREO ? TRUE : FALSE; + break; + + case WGL_PIXEL_TYPE_ARB: + switch (pfi->pfd.iPixelType) { + case PFD_TYPE_RGBA: + if (util_format_is_float(pfi->stvis.color_format)) { + *pvalue = WGL_TYPE_RGBA_FLOAT_ARB; + } + else { + *pvalue = WGL_TYPE_RGBA_ARB; + } + break; + case PFD_TYPE_COLORINDEX: + *pvalue = WGL_TYPE_COLORINDEX_ARB; + break; + default: + return FALSE; + } + break; + + case WGL_COLOR_BITS_ARB: + *pvalue = pfi->pfd.cColorBits; + break; + + case WGL_RED_BITS_ARB: + *pvalue = pfi->pfd.cRedBits; + break; + + case WGL_RED_SHIFT_ARB: + *pvalue = pfi->pfd.cRedShift; + break; + + case WGL_GREEN_BITS_ARB: + *pvalue = pfi->pfd.cGreenBits; + break; + + case WGL_GREEN_SHIFT_ARB: + *pvalue = pfi->pfd.cGreenShift; + break; + + case WGL_BLUE_BITS_ARB: + *pvalue = pfi->pfd.cBlueBits; + break; + + case WGL_BLUE_SHIFT_ARB: + *pvalue = pfi->pfd.cBlueShift; + break; + + case WGL_ALPHA_BITS_ARB: + *pvalue = pfi->pfd.cAlphaBits; + break; + + case WGL_ALPHA_SHIFT_ARB: + *pvalue = pfi->pfd.cAlphaShift; + break; + + case WGL_ACCUM_BITS_ARB: + *pvalue = pfi->pfd.cAccumBits; + break; + + case WGL_ACCUM_RED_BITS_ARB: + *pvalue = pfi->pfd.cAccumRedBits; + break; + + case WGL_ACCUM_GREEN_BITS_ARB: + *pvalue = pfi->pfd.cAccumGreenBits; + break; + + case WGL_ACCUM_BLUE_BITS_ARB: + *pvalue = pfi->pfd.cAccumBlueBits; + break; + + case WGL_ACCUM_ALPHA_BITS_ARB: + *pvalue = pfi->pfd.cAccumAlphaBits; + break; + + case WGL_DEPTH_BITS_ARB: + *pvalue = pfi->pfd.cDepthBits; + break; + + case WGL_STENCIL_BITS_ARB: + *pvalue = pfi->pfd.cStencilBits; + break; + + case WGL_AUX_BUFFERS_ARB: + *pvalue = pfi->pfd.cAuxBuffers; + break; + + case WGL_SAMPLE_BUFFERS_ARB: + *pvalue = (pfi->stvis.samples > 1); + break; + + case WGL_SAMPLES_ARB: + *pvalue = pfi->stvis.samples; + break; + + + /* WGL_ARB_pbuffer */ + + case WGL_MAX_PBUFFER_WIDTH_ARB: + case WGL_MAX_PBUFFER_HEIGHT_ARB: + *pvalue = stw_dev->max_2d_length; + break; + + case WGL_MAX_PBUFFER_PIXELS_ARB: + *pvalue = stw_dev->max_2d_length * stw_dev->max_2d_length; + break; + + case WGL_DRAW_TO_PBUFFER_ARB: + *pvalue = 1; + break; + + + default: + return FALSE; + } + + return TRUE; +} + +struct attrib_match_info +{ + int attribute; + int weight; + BOOL exact; +}; + +static const struct attrib_match_info attrib_match[] = { + /* WGL_ARB_pixel_format */ + { WGL_DRAW_TO_WINDOW_ARB, 0, TRUE }, + { WGL_DRAW_TO_BITMAP_ARB, 0, TRUE }, + { WGL_ACCELERATION_ARB, 0, TRUE }, + { WGL_NEED_PALETTE_ARB, 0, TRUE }, + { WGL_NEED_SYSTEM_PALETTE_ARB, 0, TRUE }, + { WGL_SWAP_LAYER_BUFFERS_ARB, 0, TRUE }, + { WGL_SWAP_METHOD_ARB, 0, TRUE }, + { WGL_NUMBER_OVERLAYS_ARB, 4, FALSE }, + { WGL_NUMBER_UNDERLAYS_ARB, 4, FALSE }, + /*{ WGL_SHARE_DEPTH_ARB, 0, TRUE },*/ /* no overlays -- ignore */ + /*{ WGL_SHARE_STENCIL_ARB, 0, TRUE },*/ /* no overlays -- ignore */ + /*{ WGL_SHARE_ACCUM_ARB, 0, TRUE },*/ /* no overlays -- ignore */ + { WGL_SUPPORT_GDI_ARB, 0, TRUE }, + { WGL_SUPPORT_OPENGL_ARB, 0, TRUE }, + { WGL_DOUBLE_BUFFER_ARB, 0, TRUE }, + { WGL_STEREO_ARB, 0, TRUE }, + { WGL_PIXEL_TYPE_ARB, 0, TRUE }, + { WGL_COLOR_BITS_ARB, 1, FALSE }, + { WGL_RED_BITS_ARB, 1, FALSE }, + { WGL_GREEN_BITS_ARB, 1, FALSE }, + { WGL_BLUE_BITS_ARB, 1, FALSE }, + { WGL_ALPHA_BITS_ARB, 1, FALSE }, + { WGL_ACCUM_BITS_ARB, 1, FALSE }, + { WGL_ACCUM_RED_BITS_ARB, 1, FALSE }, + { WGL_ACCUM_GREEN_BITS_ARB, 1, FALSE }, + { WGL_ACCUM_BLUE_BITS_ARB, 1, FALSE }, + { WGL_ACCUM_ALPHA_BITS_ARB, 1, FALSE }, + { WGL_DEPTH_BITS_ARB, 1, FALSE }, + { WGL_STENCIL_BITS_ARB, 1, FALSE }, + { WGL_AUX_BUFFERS_ARB, 2, FALSE }, + + /* WGL_ARB_multisample */ + { WGL_SAMPLE_BUFFERS_ARB, 2, FALSE }, + { WGL_SAMPLES_ARB, 2, FALSE }, + + /* WGL_ARB_render_texture */ + { WGL_BIND_TO_TEXTURE_RGB_ARB, 0, FALSE }, + { WGL_BIND_TO_TEXTURE_RGBA_ARB, 0, FALSE }, +}; + +struct stw_pixelformat_score +{ + int points; + uint index; +}; + + +static BOOL +score_pixelformats(struct stw_pixelformat_score *scores, + uint count, + int attribute, + int expected_value) +{ + uint i; + const struct attrib_match_info *ami = NULL; + uint index; + + /* Find out if a given attribute should be considered for score calculation. + */ + for (i = 0; i < ARRAY_SIZE(attrib_match); i++) { + if (attrib_match[i].attribute == attribute) { + ami = &attrib_match[i]; + break; + } + } + if (ami == NULL) + return TRUE; + + /* Iterate all pixelformats, query the requested attribute and calculate + * score points. + */ + for (index = 0; index < count; index++) { + int actual_value; + + if (!stw_query_attrib(index + 1, 0, attribute, &actual_value)) + return FALSE; + + if (ami->exact) { + /* For an exact match criteria, if the actual and expected values + * differ, the score is set to 0 points, effectively removing the + * pixelformat from a list of matching pixelformats. + */ + if (actual_value != expected_value) + scores[index].points = 0; + } + else { + /* For a minimum match criteria, if the actual value is smaller than + * the expected value, the pixelformat is rejected (score set to + * 0). However, if the actual value is bigger, the pixelformat is + * given a penalty to favour pixelformats that more closely match the + * expected values. + */ + if (actual_value < expected_value) + scores[index].points = 0; + else if (actual_value > expected_value) + scores[index].points -= (actual_value - expected_value) + * ami->weight; + } + } + + return TRUE; +} + + +WINGDIAPI BOOL APIENTRY +wglChoosePixelFormatARB(HDC hdc, const int *piAttribIList, + const FLOAT *pfAttribFList, UINT nMaxFormats, + int *piFormats, UINT *nNumFormats) +{ + uint count; + struct stw_pixelformat_score *scores; + uint i; + + *nNumFormats = 0; + + /* Allocate and initialize pixelformat score table -- better matches + * have higher scores. Start with a high score and take out penalty + * points for a mismatch when the match does not have to be exact. + * Set a score to 0 if there is a mismatch for an exact match criteria. + */ + count = stw_pixelformat_get_extended_count(); + scores = (struct stw_pixelformat_score *) + MALLOC(count * sizeof(struct stw_pixelformat_score)); + if (scores == NULL) + return FALSE; + for (i = 0; i < count; i++) { + scores[i].points = 0x7fffffff; + scores[i].index = i; + } + + /* Given the attribute list calculate a score for each pixelformat. + */ + if (piAttribIList != NULL) { + while (*piAttribIList != 0) { + if (!score_pixelformats(scores, count, piAttribIList[0], + piAttribIList[1])) { + FREE(scores); + return FALSE; + } + piAttribIList += 2; + } + } + if (pfAttribFList != NULL) { + while (*pfAttribFList != 0) { + if (!score_pixelformats(scores, count, (int) pfAttribFList[0], + (int) pfAttribFList[1])) { + FREE(scores); + return FALSE; + } + pfAttribFList += 2; + } + } + + /* Bubble-sort the resulting scores. Pixelformats with higher scores go + * first. TODO: Find out if there are any patent issues with it. + */ + if (count > 1) { + uint n = count; + boolean swapped; + + do { + swapped = FALSE; + for (i = 1; i < n; i++) { + if (scores[i - 1].points < scores[i].points) { + struct stw_pixelformat_score score = scores[i - 1]; + + scores[i - 1] = scores[i]; + scores[i] = score; + swapped = TRUE; + } + } + n--; + } + while (swapped); + } + + /* Return a list of pixelformats that are the best match. + * Reject pixelformats with non-positive scores. + */ + for (i = 0; i < count; i++) { + if (scores[i].points > 0) { + piFormats[*nNumFormats] = scores[i].index + 1; + (*nNumFormats)++; + if (*nNumFormats >= nMaxFormats) { + break; + } + } + } + + FREE(scores); + return TRUE; +} + + +WINGDIAPI BOOL APIENTRY +wglGetPixelFormatAttribfvARB(HDC hdc, int iPixelFormat, int iLayerPlane, + UINT nAttributes, const int *piAttributes, + FLOAT *pfValues) +{ + UINT i; + + (void) hdc; + + for (i = 0; i < nAttributes; i++) { + int value = 0; + + if (!stw_query_attrib(iPixelFormat, iLayerPlane, + piAttributes[i], &value)) + return FALSE; + pfValues[i] = (FLOAT) value; + } + + return TRUE; +} + + +WINGDIAPI BOOL APIENTRY +wglGetPixelFormatAttribivARB(HDC hdc, int iPixelFormat, int iLayerPlane, + UINT nAttributes, const int *piAttributes, + int *piValues) +{ + UINT i; + + (void) hdc; + + for (i = 0; i < nAttributes; i++) { + if (!stw_query_attrib(iPixelFormat, iLayerPlane, + piAttributes[i], &piValues[i])) + return FALSE; + } + + return TRUE; +} diff --git a/src/gallium/frontends/wgl/stw_ext_rendertexture.c b/src/gallium/frontends/wgl/stw_ext_rendertexture.c new file mode 100644 index 00000000000..48b2b1f61a4 --- /dev/null +++ b/src/gallium/frontends/wgl/stw_ext_rendertexture.c @@ -0,0 +1,264 @@ +/************************************************************************** + * Copyright 2015 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include + +#define WGL_WGLEXT_PROTOTYPES + +#include +#include + +#include "state_tracker/st_copytex.h" + +#include "pipe/p_defines.h" +#include "pipe/p_screen.h" +#include "pipe/p_state.h" + +#include "gldrv.h" +#include "stw_context.h" +#include "stw_device.h" +#include "stw_pixelformat.h" +#include "stw_framebuffer.h" +#include "stw_st.h" + + +/** Translate a WGL buffer name to a GLenum */ +static GLenum +translate_ibuffer(int iBuffer) +{ + switch (iBuffer) { + case WGL_FRONT_LEFT_ARB: + return GL_FRONT_LEFT; + case WGL_BACK_LEFT_ARB: + return GL_BACK_LEFT; + case WGL_FRONT_RIGHT_ARB: + return GL_FRONT_RIGHT; + case WGL_BACK_RIGHT_ARB: + return GL_BACK_RIGHT; + case WGL_AUX0_ARB: + return GL_AUX0; + default: + return GL_NONE; + } +} + + +/** Translate a WGL texture target type to a GLenum */ +static GLenum +translate_target(unsigned textureTarget) +{ + switch (textureTarget) { + case WGL_TEXTURE_1D_ARB: + return GL_TEXTURE_1D; + case WGL_TEXTURE_2D_ARB: + return GL_TEXTURE_2D; + case WGL_TEXTURE_CUBE_MAP_ARB: + return GL_TEXTURE_CUBE_MAP; + case WGL_NO_TEXTURE_ARB: + default: + return GL_NONE; + } +} + + +/** Translate a WGL texture format to a GLenum */ +static GLenum +translate_texture_format(unsigned wgl_format) +{ + switch (wgl_format) { + case WGL_TEXTURE_RGB_ARB: + return GL_RGB; + case WGL_TEXTURE_RGBA_ARB: + return GL_RGBA; + case WGL_NO_TEXTURE_ARB: + default: + return GL_NONE; + } +} + + +BOOL WINAPI +wglBindTexImageARB(HPBUFFERARB hPbuffer, int iBuffer) +{ + HDC prevDrawable = stw_get_current_dc(); + HDC prevReadable = stw_get_current_read_dc(); + HDC dc; + struct stw_context *curctx = stw_current_context(); + struct stw_framebuffer *fb; + GLenum texFormat, srcBuffer, target; + boolean retVal; + int pixelFormatSave; + + /* + * Implementation notes: + * Ideally, we'd implement this function with the + * st_context_iface::teximage() function which replaces a specific + * texture image with a different resource (the pbuffer). + * The main problem however, is the pbuffer image is upside down relative + * to the texture image. + * Window system drawing surfaces (windows & pbuffers) are "top to bottom" + * while OpenGL texture images are "bottom to top". One possible solution + * to this is to invert rendering to pbuffers (as we do for renderbuffers) + * but that could lead to other issues (and would require extensive + * testing). + * + * The simple alternative is to use a copy-based approach which copies the + * pbuffer image into the texture via glCopyTex[Sub]Image. That's what + * we do here. + */ + + if (!curctx) { + debug_printf("No rendering context in wglBindTexImageARB()\n"); + SetLastError(ERROR_INVALID_OPERATION); + return FALSE; + } + + fb = stw_framebuffer_from_HPBUFFERARB(hPbuffer); + if (!fb) { + debug_printf("Invalid pbuffer handle in wglBindTexImageARB()\n"); + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + srcBuffer = translate_ibuffer(iBuffer); + if (srcBuffer == GL_NONE) { + debug_printf("Invalid buffer 0x%x in wglBindTexImageARB()\n", iBuffer); + SetLastError(ERROR_INVALID_DATA); + return FALSE; + } + + target = translate_target(fb->textureTarget); + if (target == GL_NONE) { + debug_printf("no texture target in wglBindTexImageARB()\n"); + return FALSE; + } + + texFormat = translate_texture_format(fb->textureFormat); + if (texFormat == GL_NONE) { + debug_printf("no texture format in wglBindTexImageARB()\n"); + return FALSE; + } + + /* + * Bind the pbuffer surface so we can read/copy from it. + * + * Before we can call stw_make_current() we have to temporarily + * change the pbuffer's pixel format to match the context to avoid + * an error condition. After the stw_make_current() we restore the + * buffer's pixel format. + */ + pixelFormatSave = fb->iPixelFormat; + fb->iPixelFormat = curctx->iPixelFormat; + dc = wglGetPbufferDCARB(hPbuffer); + retVal = stw_make_current(dc, dc, curctx->dhglrc); + fb->iPixelFormat = pixelFormatSave; + if (!retVal) { + debug_printf("stw_make_current(#1) failed in wglBindTexImageARB()\n"); + wglReleasePbufferDCARB(hPbuffer, dc); + return FALSE; + } + + st_copy_framebuffer_to_texture(srcBuffer, fb->width, fb->height, + target, fb->textureLevel, + fb->textureFace, texFormat); + + /* rebind previous drawing surface */ + retVal = stw_make_current(prevDrawable, prevReadable, curctx->dhglrc); + if (!retVal) { + debug_printf("stw_make_current(#2) failed in wglBindTexImageARB()\n"); + } + + wglReleasePbufferDCARB(hPbuffer, dc); + + return retVal; +} + + +BOOL WINAPI +wglReleaseTexImageARB(HPBUFFERARB hPbuffer, int iBuffer) +{ + struct stw_framebuffer *fb = stw_framebuffer_from_HPBUFFERARB(hPbuffer); + GLenum srcBuffer; + + /* nothing to do here, but we do error checking anyway */ + + if (!fb) { + debug_printf("Invalid pbuffer handle in wglReleaseTexImageARB()\n"); + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + srcBuffer = translate_ibuffer(iBuffer); + if (srcBuffer == GL_NONE) { + debug_printf("Invalid buffer 0x%x in wglReleaseTexImageARB()\n", iBuffer); + SetLastError(ERROR_INVALID_DATA); + return FALSE; + } + + return TRUE; +} + + +BOOL WINAPI +wglSetPbufferAttribARB(HPBUFFERARB hPbuffer, const int *piAttribList) +{ + struct stw_framebuffer *fb = stw_framebuffer_from_HPBUFFERARB(hPbuffer); + int face, i; + + if (!fb) { + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + for (i = 0; piAttribList[i]; i += 2) { + switch (piAttribList[i]) { + case WGL_MIPMAP_LEVEL_ARB: + fb->textureLevel = piAttribList[i+1]; + break; + case WGL_CUBE_MAP_FACE_ARB: + face = piAttribList[i+1]; + if (face >= WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && + face <= WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { + fb->textureFace = face - WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB; + } + else { + debug_printf("Invalid cube face 0x%x in " + "wglSetPbufferAttribARB()\n", + piAttribList[i]); + SetLastError(ERROR_INVALID_DATA); + return FALSE; + } + break; + default: + debug_printf("Invalid attribute 0x%x in wglSetPbufferAttribARB()\n", + piAttribList[i]); + SetLastError(ERROR_INVALID_DATA); + return FALSE; + } + } + + return TRUE; +} diff --git a/src/gallium/frontends/wgl/stw_ext_swapinterval.c b/src/gallium/frontends/wgl/stw_ext_swapinterval.c new file mode 100644 index 00000000000..3b913e7db93 --- /dev/null +++ b/src/gallium/frontends/wgl/stw_ext_swapinterval.c @@ -0,0 +1,62 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * Copyright 2008 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include + +#define WGL_WGLEXT_PROTOTYPES + +#include +#include +#include "util/u_debug.h" +#include "stw_device.h" + + +/** + * Note that our implementation of swap intervals is a bit of a hack. + * We implement it based on querying the time and Sleep()'ing. We don't + * sync to the vblank. + */ +WINGDIAPI BOOL APIENTRY +wglSwapIntervalEXT(int interval) +{ + if (interval < 0) { + SetLastError(ERROR_INVALID_DATA); + return FALSE; + } + if (stw_dev && !os_get_option("WGL_SWAP_INTERVAL")) { + stw_dev->swap_interval = interval; + } + return TRUE; +} + + +WINGDIAPI int APIENTRY +wglGetSwapIntervalEXT(void) +{ + return stw_dev ? stw_dev->swap_interval : 0; +} diff --git a/src/gallium/frontends/wgl/stw_framebuffer.c b/src/gallium/frontends/wgl/stw_framebuffer.c new file mode 100644 index 00000000000..1456f2e7caf --- /dev/null +++ b/src/gallium/frontends/wgl/stw_framebuffer.c @@ -0,0 +1,670 @@ +/************************************************************************** + * + * Copyright 2008-2009 Vmware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include + +#include "pipe/p_screen.h" +#include "util/u_memory.h" +#include "hud/hud_context.h" +#include "util/os_time.h" +#include "frontend/api.h" + +#include +#include "gldrv.h" +#include "stw_framebuffer.h" +#include "stw_device.h" +#include "stw_winsys.h" +#include "stw_tls.h" +#include "stw_context.h" +#include "stw_st.h" + + +/** + * Search the framebuffer with the matching HWND while holding the + * stw_dev::fb_mutex global lock. + * If a stw_framebuffer is found, lock it and return the pointer. + * Else, return NULL. + */ +static struct stw_framebuffer * +stw_framebuffer_from_hwnd_locked(HWND hwnd) +{ + struct stw_framebuffer *fb; + + for (fb = stw_dev->fb_head; fb != NULL; fb = fb->next) + if (fb->hWnd == hwnd) { + stw_framebuffer_lock(fb); + assert(fb->mutex.RecursionCount == 1); + return fb; + } + + return NULL; +} + + +/** + * Decrement the reference count on the given stw_framebuffer object. + * If the reference count hits zero, destroy the object. + * + * Note: Both stw_dev::fb_mutex and stw_framebuffer::mutex must already be + * locked. After this function completes, the fb's mutex will be unlocked. + */ +void +stw_framebuffer_release_locked(struct stw_framebuffer *fb) +{ + struct stw_framebuffer **link; + + assert(fb); + assert(stw_own_mutex(&fb->mutex)); + assert(stw_own_mutex(&stw_dev->fb_mutex)); + + /* check the reference count */ + fb->refcnt--; + if (fb->refcnt) { + stw_framebuffer_unlock(fb); + return; + } + + /* remove this stw_framebuffer from the device's linked list */ + link = &stw_dev->fb_head; + while (*link != fb) + link = &(*link)->next; + assert(*link); + *link = fb->next; + fb->next = NULL; + + if (fb->shared_surface) + stw_dev->stw_winsys->shared_surface_close(stw_dev->screen, + fb->shared_surface); + + stw_st_destroy_framebuffer_locked(fb->stfb); + + stw_framebuffer_unlock(fb); + + DeleteCriticalSection(&fb->mutex); + + FREE( fb ); +} + + +/** + * Query the size of the given framebuffer's on-screen window and update + * the stw_framebuffer's width/height. + */ +static void +stw_framebuffer_get_size(struct stw_framebuffer *fb) +{ + LONG width, height; + RECT client_rect; + RECT window_rect; + POINT client_pos; + + /* + * Sanity checking. + */ + assert(fb->hWnd); + assert(fb->width && fb->height); + assert(fb->client_rect.right == fb->client_rect.left + fb->width); + assert(fb->client_rect.bottom == fb->client_rect.top + fb->height); + + /* + * Get the client area size. + */ + if (!GetClientRect(fb->hWnd, &client_rect)) { + return; + } + + assert(client_rect.left == 0); + assert(client_rect.top == 0); + width = client_rect.right - client_rect.left; + height = client_rect.bottom - client_rect.top; + + fb->minimized = width == 0 || height == 0; + + if (width <= 0 || height <= 0) { + /* + * When the window is minimized GetClientRect will return zeros. Simply + * preserve the current window size, until the window is restored or + * maximized again. + */ + return; + } + + if (width != fb->width || height != fb->height) { + fb->must_resize = TRUE; + fb->width = width; + fb->height = height; + } + + client_pos.x = 0; + client_pos.y = 0; + if (ClientToScreen(fb->hWnd, &client_pos) && + GetWindowRect(fb->hWnd, &window_rect)) { + fb->client_rect.left = client_pos.x - window_rect.left; + fb->client_rect.top = client_pos.y - window_rect.top; + } + + fb->client_rect.right = fb->client_rect.left + fb->width; + fb->client_rect.bottom = fb->client_rect.top + fb->height; + +#if 0 + debug_printf("\n"); + debug_printf("%s: hwnd = %p\n", __FUNCTION__, fb->hWnd); + debug_printf("%s: client_position = (%li, %li)\n", + __FUNCTION__, client_pos.x, client_pos.y); + debug_printf("%s: window_rect = (%li, %li) - (%li, %li)\n", + __FUNCTION__, + window_rect.left, window_rect.top, + window_rect.right, window_rect.bottom); + debug_printf("%s: client_rect = (%li, %li) - (%li, %li)\n", + __FUNCTION__, + fb->client_rect.left, fb->client_rect.top, + fb->client_rect.right, fb->client_rect.bottom); +#endif +} + + +/** + * @sa http://msdn.microsoft.com/en-us/library/ms644975(VS.85).aspx + * @sa http://msdn.microsoft.com/en-us/library/ms644960(VS.85).aspx + */ +LRESULT CALLBACK +stw_call_window_proc(int nCode, WPARAM wParam, LPARAM lParam) +{ + struct stw_tls_data *tls_data; + PCWPSTRUCT pParams = (PCWPSTRUCT)lParam; + struct stw_framebuffer *fb; + + tls_data = stw_tls_get_data(); + if (!tls_data) + return 0; + + if (nCode < 0 || !stw_dev) + return CallNextHookEx(tls_data->hCallWndProcHook, nCode, wParam, lParam); + + /* We check that the stw_dev object is initialized before we try to do + * anything with it. Otherwise, in multi-threaded programs there's a + * chance of executing this code before the stw_dev object is fully + * initialized. + */ + if (stw_dev && stw_dev->initialized) { + if (pParams->message == WM_WINDOWPOSCHANGED) { + /* We handle WM_WINDOWPOSCHANGED instead of WM_SIZE because according + * to http://blogs.msdn.com/oldnewthing/archive/2008/01/15/7113860.aspx + * WM_SIZE is generated from WM_WINDOWPOSCHANGED by DefWindowProc so it + * can be masked out by the application. + */ + LPWINDOWPOS lpWindowPos = (LPWINDOWPOS)pParams->lParam; + if ((lpWindowPos->flags & SWP_SHOWWINDOW) || + !(lpWindowPos->flags & SWP_NOMOVE) || + !(lpWindowPos->flags & SWP_NOSIZE)) { + fb = stw_framebuffer_from_hwnd( pParams->hwnd ); + if (fb) { + /* Size in WINDOWPOS includes the window frame, so get the size + * of the client area via GetClientRect. + */ + stw_framebuffer_get_size(fb); + stw_framebuffer_unlock(fb); + } + } + } + else if (pParams->message == WM_DESTROY) { + stw_lock_framebuffers(stw_dev); + fb = stw_framebuffer_from_hwnd_locked( pParams->hwnd ); + if (fb) + stw_framebuffer_release_locked(fb); + stw_unlock_framebuffers(stw_dev); + } + } + + return CallNextHookEx(tls_data->hCallWndProcHook, nCode, wParam, lParam); +} + + +/** + * Create a new stw_framebuffer object which corresponds to the given + * HDC/window. If successful, we return the new stw_framebuffer object + * with its mutex locked. + */ +struct stw_framebuffer * +stw_framebuffer_create(HDC hdc, int iPixelFormat) +{ + HWND hWnd; + struct stw_framebuffer *fb; + const struct stw_pixelformat_info *pfi; + + /* We only support drawing to a window. */ + hWnd = WindowFromDC( hdc ); + if (!hWnd) + return NULL; + + fb = CALLOC_STRUCT( stw_framebuffer ); + if (fb == NULL) + return NULL; + + fb->hWnd = hWnd; + fb->iPixelFormat = iPixelFormat; + + /* + * We often need a displayable pixel format to make GDI happy. Set it + * here (always 1, i.e., out first pixel format) where appropriate. + */ + fb->iDisplayablePixelFormat = iPixelFormat <= stw_dev->pixelformat_count + ? iPixelFormat : 1; + + fb->pfi = pfi = stw_pixelformat_get_info( iPixelFormat ); + fb->stfb = stw_st_create_framebuffer( fb ); + if (!fb->stfb) { + FREE( fb ); + return NULL; + } + + fb->refcnt = 1; + + /* + * Windows can be sometimes have zero width and or height, but we ensure + * a non-zero framebuffer size at all times. + */ + + fb->must_resize = TRUE; + fb->width = 1; + fb->height = 1; + fb->client_rect.left = 0; + fb->client_rect.top = 0; + fb->client_rect.right = fb->client_rect.left + fb->width; + fb->client_rect.bottom = fb->client_rect.top + fb->height; + + stw_framebuffer_get_size(fb); + + InitializeCriticalSection(&fb->mutex); + + /* This is the only case where we lock the stw_framebuffer::mutex before + * stw_dev::fb_mutex, since no other thread can know about this framebuffer + * and we must prevent any other thread from destroying it before we return. + */ + stw_framebuffer_lock(fb); + + stw_lock_framebuffers(stw_dev); + fb->next = stw_dev->fb_head; + stw_dev->fb_head = fb; + stw_unlock_framebuffers(stw_dev); + + return fb; +} + + +/** + * Update the framebuffer's size if necessary. + */ +void +stw_framebuffer_update(struct stw_framebuffer *fb) +{ + assert(fb->stfb); + assert(fb->height); + assert(fb->width); + + /* XXX: It would be nice to avoid checking the size again -- in theory + * stw_call_window_proc would have cought the resize and stored the right + * size already, but unfortunately threads created before the DllMain is + * called don't get a DLL_THREAD_ATTACH notification, and there is no way + * to know of their existing without using the not very portable PSAPI. + */ + stw_framebuffer_get_size(fb); +} + + +/** + * Try to free all stw_framebuffer objects associated with the device. + */ +void +stw_framebuffer_cleanup(void) +{ + struct stw_framebuffer *fb; + struct stw_framebuffer *next; + + if (!stw_dev) + return; + + stw_lock_framebuffers(stw_dev); + + fb = stw_dev->fb_head; + while (fb) { + next = fb->next; + + stw_framebuffer_lock(fb); + stw_framebuffer_release_locked(fb); + + fb = next; + } + stw_dev->fb_head = NULL; + + stw_unlock_framebuffers(stw_dev); +} + + +/** + * Given an hdc, return the corresponding stw_framebuffer. + * The returned stw_framebuffer will have its mutex locked. + */ +static struct stw_framebuffer * +stw_framebuffer_from_hdc_locked(HDC hdc) +{ + HWND hwnd; + + hwnd = WindowFromDC(hdc); + if (!hwnd) { + return NULL; + } + + return stw_framebuffer_from_hwnd_locked(hwnd); +} + + +/** + * Given an HDC, return the corresponding stw_framebuffer. + * The returned stw_framebuffer will have its mutex locked. + */ +struct stw_framebuffer * +stw_framebuffer_from_hdc(HDC hdc) +{ + struct stw_framebuffer *fb; + + if (!stw_dev) + return NULL; + + stw_lock_framebuffers(stw_dev); + fb = stw_framebuffer_from_hdc_locked(hdc); + stw_unlock_framebuffers(stw_dev); + + return fb; +} + + +/** + * Given an HWND, return the corresponding stw_framebuffer. + * The returned stw_framebuffer will have its mutex locked. + */ +struct stw_framebuffer * +stw_framebuffer_from_hwnd(HWND hwnd) +{ + struct stw_framebuffer *fb; + + stw_lock_framebuffers(stw_dev); + fb = stw_framebuffer_from_hwnd_locked(hwnd); + stw_unlock_framebuffers(stw_dev); + + return fb; +} + + +BOOL APIENTRY +DrvSetPixelFormat(HDC hdc, LONG iPixelFormat) +{ + uint count; + uint index; + struct stw_framebuffer *fb; + + if (!stw_dev) + return FALSE; + + index = (uint) iPixelFormat - 1; + count = stw_pixelformat_get_count(); + if (index >= count) + return FALSE; + + fb = stw_framebuffer_from_hdc_locked(hdc); + if (fb) { + /* + * SetPixelFormat must be called only once. However ignore + * pbuffers, for which the framebuffer object is created first. + */ + boolean bPbuffer = fb->bPbuffer; + + stw_framebuffer_unlock( fb ); + + return bPbuffer; + } + + fb = stw_framebuffer_create(hdc, iPixelFormat); + if (!fb) { + return FALSE; + } + + stw_framebuffer_unlock( fb ); + + /* Some applications mistakenly use the undocumented wglSetPixelFormat + * function instead of SetPixelFormat, so we call SetPixelFormat here to + * avoid opengl32.dll's wglCreateContext to fail */ + if (GetPixelFormat(hdc) == 0) { + BOOL bRet = SetPixelFormat(hdc, iPixelFormat, NULL); + if (!bRet) { + debug_printf("SetPixelFormat failed\n"); + } + } + + return TRUE; +} + + +int +stw_pixelformat_get(HDC hdc) +{ + int iPixelFormat = 0; + struct stw_framebuffer *fb; + + fb = stw_framebuffer_from_hdc(hdc); + if (fb) { + iPixelFormat = fb->iPixelFormat; + stw_framebuffer_unlock(fb); + } + + return iPixelFormat; +} + + +BOOL APIENTRY +DrvPresentBuffers(HDC hdc, LPPRESENTBUFFERS data) +{ + struct stw_framebuffer *fb; + struct pipe_screen *screen; + struct pipe_resource *res; + + if (!stw_dev) + return FALSE; + + fb = stw_framebuffer_from_hdc( hdc ); + if (fb == NULL) + return FALSE; + + screen = stw_dev->screen; + + res = (struct pipe_resource *)data->pPrivData; + + if (data->hSurface != fb->hSharedSurface) { + if (fb->shared_surface) { + stw_dev->stw_winsys->shared_surface_close(screen, fb->shared_surface); + fb->shared_surface = NULL; + } + + fb->hSharedSurface = data->hSurface; + + if (data->hSurface && + stw_dev->stw_winsys->shared_surface_open) { + fb->shared_surface = + stw_dev->stw_winsys->shared_surface_open(screen, + fb->hSharedSurface); + } + } + + if (!fb->minimized) { + if (fb->shared_surface) { + stw_dev->stw_winsys->compose(screen, + res, + fb->shared_surface, + &fb->client_rect, + data->ullPresentToken); + } + else { + stw_dev->stw_winsys->present( screen, res, hdc ); + } + } + + stw_framebuffer_update(fb); + stw_notify_current_locked(fb); + + stw_framebuffer_unlock(fb); + + return TRUE; +} + + +/** + * Queue a composition. + * + * The stw_framebuffer object must have its mutex locked. The mutex will + * be unlocked here before returning. + */ +BOOL +stw_framebuffer_present_locked(HDC hdc, + struct stw_framebuffer *fb, + struct pipe_resource *res) +{ + if (stw_dev->callbacks.pfnPresentBuffers && + stw_dev->stw_winsys->compose) { + PRESENTBUFFERSCB data; + + memset(&data, 0, sizeof data); + data.nVersion = 2; + data.syncType = PRESCB_SYNCTYPE_NONE; + data.luidAdapter = stw_dev->AdapterLuid; + data.updateRect = fb->client_rect; + data.pPrivData = (void *)res; + + stw_notify_current_locked(fb); + stw_framebuffer_unlock(fb); + + return stw_dev->callbacks.pfnPresentBuffers(hdc, &data); + } + else { + struct pipe_screen *screen = stw_dev->screen; + + stw_dev->stw_winsys->present( screen, res, hdc ); + + stw_framebuffer_update(fb); + stw_notify_current_locked(fb); + stw_framebuffer_unlock(fb); + + return TRUE; + } +} + + +/** + * This is called just before issuing the buffer swap/present. + * We query the current time and determine if we should sleep before + * issuing the swap/present. + * This is a bit of a hack and is certainly not very accurate but it + * basically works. + * This is for the WGL_ARB_swap_interval extension. + */ +static void +wait_swap_interval(struct stw_framebuffer *fb) +{ + /* Note: all time variables here are in units of microseconds */ + int64_t cur_time = os_time_get_nano() / 1000; + + if (fb->prev_swap_time != 0) { + /* Compute time since previous swap */ + int64_t delta = cur_time - fb->prev_swap_time; + int64_t min_swap_period = + 1.0e6 / stw_dev->refresh_rate * stw_dev->swap_interval; + + /* If time since last swap is less than wait period, wait. + * Note that it's possible for the delta to be negative because of + * rollover. See https://bugs.freedesktop.org/show_bug.cgi?id=102241 + */ + if ((delta >= 0) && (delta < min_swap_period)) { + float fudge = 1.75f; /* emperical fudge factor */ + int64_t wait = (min_swap_period - delta) * fudge; + os_time_sleep(wait); + } + } + + fb->prev_swap_time = cur_time; +} + + +BOOL APIENTRY +DrvSwapBuffers(HDC hdc) +{ + struct stw_context *ctx; + struct stw_framebuffer *fb; + + if (!stw_dev) + return FALSE; + + fb = stw_framebuffer_from_hdc( hdc ); + if (fb == NULL) + return FALSE; + + if (!(fb->pfi->pfd.dwFlags & PFD_DOUBLEBUFFER)) { + stw_framebuffer_unlock(fb); + return TRUE; + } + + ctx = stw_current_context(); + if (ctx) { + if (ctx->hud) { + /* Display the HUD */ + struct pipe_resource *back = + stw_get_framebuffer_resource(fb->stfb, ST_ATTACHMENT_BACK_LEFT); + if (back) { + hud_run(ctx->hud, NULL, back); + } + } + + if (ctx->current_framebuffer == fb) { + /* flush current context */ + ctx->st->flush(ctx->st, ST_FLUSH_END_OF_FRAME, NULL, NULL, NULL); + } + } + + if (stw_dev->swap_interval != 0) { + wait_swap_interval(fb); + } + + return stw_st_swap_framebuffer_locked(hdc, ctx->st, fb->stfb); +} + + +BOOL APIENTRY +DrvSwapLayerBuffers(HDC hdc, UINT fuPlanes) +{ + if (fuPlanes & WGL_SWAP_MAIN_PLANE) + return DrvSwapBuffers(hdc); + + return FALSE; +} diff --git a/src/gallium/frontends/wgl/stw_framebuffer.h b/src/gallium/frontends/wgl/stw_framebuffer.h new file mode 100644 index 00000000000..d44c3a6634a --- /dev/null +++ b/src/gallium/frontends/wgl/stw_framebuffer.h @@ -0,0 +1,227 @@ +/************************************************************************** + * + * Copyright 2008 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef STW_FRAMEBUFFER_H +#define STW_FRAMEBUFFER_H + +#include + +#include +#include + +#include "util/u_debug.h" +#include "stw_st.h" + + +struct pipe_resource; +struct st_framebuffer_iface; +struct stw_pixelformat_info; + +/** + * Windows framebuffer. + */ +struct stw_framebuffer +{ + /** + * This mutex has two purposes: + * - protect the access to the mutable data members below + * - prevent the framebuffer from being deleted while being accessed. + * + * Note: if both this mutex and the stw_device::fb_mutex need to be locked, + * the stw_device::fb_mutex needs to be locked first. + */ + CRITICAL_SECTION mutex; + + /* + * Immutable members. + * + * Note that even access to immutable members implies acquiring the mutex + * above, to prevent the framebuffer from being destroyed. + */ + + HWND hWnd; + + int iPixelFormat; + const struct stw_pixelformat_info *pfi; + + /* A pixel format that can be used by GDI */ + int iDisplayablePixelFormat; + boolean bPbuffer; + + struct st_framebuffer_iface *stfb; + + /* + * Mutable members. + */ + + unsigned refcnt; + + + /* FIXME: Make this work for multiple contexts bound to the same framebuffer */ + boolean must_resize; + + boolean minimized; /**< Is the window currently minimized? */ + + unsigned width; + unsigned height; + + /** WGL_ARB_render_texture - set at Pbuffer creation time */ + unsigned textureFormat; /**< WGL_NO_TEXTURE or WGL_TEXTURE_RGB[A]_ARB */ + unsigned textureTarget; /**< WGL_NO_TEXTURE or WGL_TEXTURE_1D/2D/ + CUBE_MAP_ARB */ + boolean textureMipmap; /**< TRUE/FALSE */ + /** WGL_ARB_render_texture - set with wglSetPbufferAttribARB() */ + unsigned textureLevel; + unsigned textureFace; /**< [0..6] */ + + /** + * Client area rectangle, relative to the window upper-left corner. + * + * @sa GLCBPRESENTBUFFERSDATA::rect. + */ + RECT client_rect; + + HANDLE hSharedSurface; + struct stw_shared_surface *shared_surface; + + /* For WGL_EXT_swap_control */ + int64_t prev_swap_time; + + /** + * This is protected by stw_device::fb_mutex, not the mutex above. + * + * Deletions must be done by first acquiring stw_device::fb_mutex, and then + * acquiring the stw_framebuffer::mutex of the framebuffer to be deleted. + * This ensures that nobody else is reading/writing to the. + * + * It is not necessary to acquire the mutex above to navigate the linked list + * given that deletions are done with stw_device::fb_mutex held, so no other + * thread can delete. + */ + struct stw_framebuffer *next; +}; + + +/** + * Create a new framebuffer object which will correspond to the given HDC. + * + * This function will acquire stw_framebuffer::mutex. stw_framebuffer_unlock + * must be called when done + */ +struct stw_framebuffer * +stw_framebuffer_create(HDC hdc, int iPixelFormat); + + +/** + * Increase fb reference count. The referenced framebuffer should be locked. + * + * It's not necessary to hold stw_dev::fb_mutex global lock. + */ +static inline void +stw_framebuffer_reference_locked(struct stw_framebuffer *fb) +{ + if (fb) { + assert(stw_own_mutex(&fb->mutex)); + fb->refcnt++; + } +} + + +void +stw_framebuffer_release_locked(struct stw_framebuffer *fb); + +/** + * Search a framebuffer with a matching HWND. + * + * This function will acquire stw_framebuffer::mutex. stw_framebuffer_unlock + * must be called when done + */ +struct stw_framebuffer * +stw_framebuffer_from_hwnd(HWND hwnd); + +/** + * Search a framebuffer with a matching HDC. + * + * This function will acquire stw_framebuffer::mutex. stw_framebuffer_unlock + * must be called when done + */ +struct stw_framebuffer * +stw_framebuffer_from_hdc(HDC hdc); + +BOOL +stw_framebuffer_present_locked(HDC hdc, + struct stw_framebuffer *fb, + struct pipe_resource *res); + +void +stw_framebuffer_update(struct stw_framebuffer *fb); + + +static inline void +stw_framebuffer_lock(struct stw_framebuffer *fb) +{ + assert(fb); + EnterCriticalSection(&fb->mutex); +} + + +/** + * Release stw_framebuffer::mutex lock. This framebuffer must not be accessed + * after calling this function, as it may have been deleted by another thread + * in the meanwhile. + */ +static inline void +stw_framebuffer_unlock(struct stw_framebuffer *fb) +{ + assert(fb); + assert(stw_own_mutex(&fb->mutex)); + LeaveCriticalSection(&fb->mutex); +} + + +/** + * Cleanup any existing framebuffers when exiting application. + */ +void +stw_framebuffer_cleanup(void); + + +static inline struct stw_st_framebuffer * +stw_st_framebuffer(struct st_framebuffer_iface *stfb) +{ + return (struct stw_st_framebuffer *) stfb; +} + + +static inline struct stw_framebuffer * +stw_framebuffer_from_HPBUFFERARB(HPBUFFERARB hPbuffer) +{ + return (struct stw_framebuffer *) hPbuffer; +} + + +#endif /* STW_FRAMEBUFFER_H */ diff --git a/src/gallium/frontends/wgl/stw_getprocaddress.c b/src/gallium/frontends/wgl/stw_getprocaddress.c new file mode 100644 index 00000000000..f062cd38aed --- /dev/null +++ b/src/gallium/frontends/wgl/stw_getprocaddress.c @@ -0,0 +1,122 @@ +/************************************************************************** + * + * Copyright 2008 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include + +#define WGL_WGLEXT_PROTOTYPES + +#include +#include + +#include "glapi/glapi.h" +#include "stw_device.h" +#include "gldrv.h" +#include "stw_nopfuncs.h" + +#include "util/u_debug.h" + +struct stw_extension_entry +{ + const char *name; + PROC proc; +}; + +#define STW_EXTENSION_ENTRY(P) { #P, (PROC) P } + +static const struct stw_extension_entry stw_extension_entries[] = { + + /* WGL_ARB_extensions_string */ + STW_EXTENSION_ENTRY( wglGetExtensionsStringARB ), + + /* WGL_ARB_pbuffer */ + STW_EXTENSION_ENTRY( wglCreatePbufferARB ), + STW_EXTENSION_ENTRY( wglGetPbufferDCARB ), + STW_EXTENSION_ENTRY( wglReleasePbufferDCARB ), + STW_EXTENSION_ENTRY( wglDestroyPbufferARB ), + STW_EXTENSION_ENTRY( wglQueryPbufferARB ), + + /* WGL_ARB_pixel_format */ + STW_EXTENSION_ENTRY( wglChoosePixelFormatARB ), + STW_EXTENSION_ENTRY( wglGetPixelFormatAttribfvARB ), + STW_EXTENSION_ENTRY( wglGetPixelFormatAttribivARB ), + + /* WGL_EXT_extensions_string */ + STW_EXTENSION_ENTRY( wglGetExtensionsStringEXT ), + + /* WGL_EXT_swap_control */ + STW_EXTENSION_ENTRY( wglGetSwapIntervalEXT ), + STW_EXTENSION_ENTRY( wglSwapIntervalEXT ), + + /* WGL_ARB_create_context */ + STW_EXTENSION_ENTRY( wglCreateContextAttribsARB ), + + /* WGL_ARB_render_texture */ + STW_EXTENSION_ENTRY( wglBindTexImageARB ), + STW_EXTENSION_ENTRY( wglReleaseTexImageARB ), + STW_EXTENSION_ENTRY( wglSetPbufferAttribARB ), + + /* WGL_ARB_make_current_read */ + STW_EXTENSION_ENTRY( wglMakeContextCurrentARB ), + STW_EXTENSION_ENTRY( wglGetCurrentReadDCARB ), + { NULL, NULL } +}; + +PROC APIENTRY +DrvGetProcAddress( + LPCSTR lpszProc ) +{ + const struct stw_extension_entry *entry; + PROC p; + + if (!stw_dev) + return NULL; + + if (lpszProc[0] == 'w' && lpszProc[1] == 'g' && lpszProc[2] == 'l') + for (entry = stw_extension_entries; entry->name; entry++) + if (strcmp( lpszProc, entry->name ) == 0) + return entry->proc; + + if (lpszProc[0] == 'g' && lpszProc[1] == 'l') { + p = (PROC) _glapi_get_proc_address(lpszProc); + if (p) + return p; + } + + /* If we get here, we'd normally just return NULL, but since some apps + * (like Viewperf12) crash when they try to use the null pointer, try + * returning a pointer to a no-op function instead. + */ + p = stw_get_nop_function(lpszProc); + if (p) { + debug_printf("wglGetProcAddress(\"%s\") returning no-op function\n", + lpszProc); + return p; + } + + debug_printf("wglGetProcAddress(\"%s\") returning NULL\n", lpszProc); + return NULL; +} diff --git a/src/gallium/frontends/wgl/stw_nopfuncs.c b/src/gallium/frontends/wgl/stw_nopfuncs.c new file mode 100644 index 00000000000..d69c0134f37 --- /dev/null +++ b/src/gallium/frontends/wgl/stw_nopfuncs.c @@ -0,0 +1,464 @@ +/************************************************************************** + * + * Copyright 2015 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/** + * No-op GL API functions. + * + * Some OpenGL apps (like Viewperf12) call wglGetProcAddress() to get + * a pointer to an extension function, get a NULL pointer, but don't bother + * to check for NULL before jumping through the pointer. This causes a + * crash. + * + * As a work-around we provide some no-op functions here to avoid those + * crashes. + */ + +#include +#include "stw_nopfuncs.h" +#include "util/u_debug.h" + + +static void +warning(const char *name) +{ + /* use name+4 to skip "nop_" prefix */ + _debug_printf("Application calling unsupported %s function\n", name+4); +} + +static void APIENTRY +nop_glBindMultiTextureEXT(GLenum texunit, GLenum target, GLuint texture) +{ + warning(__func__); +} + +static void APIENTRY +nop_glColor3hNV(GLhalfNV red, GLhalfNV green, GLhalfNV blue) +{ + warning(__func__); +} + +static void APIENTRY +nop_glColor3hvNV(const GLhalfNV *v) +{ + warning(__func__); +} + +static void APIENTRY +nop_glColor4hNV(GLhalfNV red, GLhalfNV green, GLhalfNV blue, GLhalfNV alpha) +{ + warning(__func__); +} + +static void APIENTRY +nop_glColor4hvNV(const GLhalfNV *v) +{ + warning(__func__); +} + +static void APIENTRY +nop_glDisableClientStateIndexedEXT(GLenum array, GLuint index) +{ + warning(__func__); +} + +static void APIENTRY +nop_glEnableClientStateIndexedEXT(GLenum array, GLuint index) +{ + warning(__func__); +} + +static void APIENTRY +nop_glFogCoordhNV(GLhalfNV fog) +{ + warning(__func__); +} + +static void APIENTRY +nop_glFogCoordhvNV(const GLhalfNV *fog) +{ + warning(__func__); +} + +static void APIENTRY +nop_glGetNamedBufferParameterivEXT(GLuint buffer, GLenum pname, GLint *params) +{ + warning(__func__); +} + +static void APIENTRY +nop_glGetNamedBufferSubDataEXT(GLuint buffer, GLintptr offset, GLsizeiptr size, void *data) +{ + warning(__func__); +} + +static void *APIENTRY +nop_glMapNamedBufferEXT(GLuint buffer, GLenum access) +{ + warning(__func__); + return NULL; +} + +static void APIENTRY +nop_glMatrixLoadfEXT(GLenum mode, const GLfloat *m) +{ + warning(__func__); +} + +static void APIENTRY +nop_glMatrixLoadIdentityEXT(GLenum mode) +{ + warning(__func__); +} + +static void APIENTRY +nop_glMultiTexCoord1hNV(GLenum target, GLhalfNV s) +{ + warning(__func__); +} + +static void APIENTRY +nop_glMultiTexCoord1hvNV(GLenum target, const GLhalfNV *v) +{ + warning(__func__); +} + +static void APIENTRY +nop_glMultiTexCoord2hNV(GLenum target, GLhalfNV s, GLhalfNV t) +{ + warning(__func__); +} + +static void APIENTRY +nop_glMultiTexCoord2hvNV(GLenum target, const GLhalfNV *v) +{ + warning(__func__); +} + +static void APIENTRY +nop_glMultiTexCoord3hNV(GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r) +{ + warning(__func__); +} + +static void APIENTRY +nop_glMultiTexCoord3hvNV(GLenum target, const GLhalfNV *v) +{ + warning(__func__); +} + +static void APIENTRY +nop_glMultiTexCoord4hNV(GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q) +{ + warning(__func__); +} + +static void APIENTRY +nop_glMultiTexCoord4hvNV(GLenum target, const GLhalfNV *v) +{ + warning(__func__); +} + +static void APIENTRY +nop_glMultiTexCoordPointerEXT(GLenum texunit, GLint size, GLenum type, GLsizei stride, const void *pointer) +{ + warning(__func__); +} + +static void APIENTRY +nop_glMultiTexEnvfEXT(GLenum texunit, GLenum target, GLenum pname, GLfloat param) +{ + warning(__func__); +} + +static void APIENTRY +nop_glMultiTexEnvfvEXT(GLenum texunit, GLenum target, GLenum pname, const GLfloat *params) +{ + warning(__func__); +} + +static void APIENTRY +nop_glMultiTexEnviEXT(GLenum texunit, GLenum target, GLenum pname, GLint param) +{ + warning(__func__); +} + +static void APIENTRY +nop_glMultiTexGenfvEXT(GLenum texunit, GLenum coord, GLenum pname, const GLfloat *params) +{ + warning(__func__); +} + +static void APIENTRY +nop_glMultiTexGeniEXT(GLenum texunit, GLenum coord, GLenum pname, GLint param) +{ + warning(__func__); +} + +static void APIENTRY +nop_glNamedBufferDataEXT(GLuint buffer, GLsizeiptr size, const void *data, GLenum usage) +{ + warning(__func__); +} + +static void APIENTRY +nop_glNamedBufferSubDataEXT(GLuint buffer, GLintptr offset, GLsizeiptr size, const void *data) +{ + warning(__func__); +} + +static void APIENTRY +nop_glNamedProgramLocalParameter4fvEXT(GLuint program, GLenum target, GLuint index, const GLfloat *params) +{ + warning(__func__); +} + +static void APIENTRY +nop_glNamedProgramLocalParameters4fvEXT(GLuint program, GLenum target, GLuint index, GLsizei count, const GLfloat *params) +{ + warning(__func__); +} + +static void APIENTRY +nop_glNormal3hNV(GLhalfNV nx, GLhalfNV ny, GLhalfNV nz) +{ + warning(__func__); +} + +static void APIENTRY +nop_glNormal3hvNV(const GLhalfNV *v) +{ + warning(__func__); +} + +static void APIENTRY +nop_glPatchParameterfv(GLenum pname, const GLfloat *values) +{ + warning(__func__); +} + +static void APIENTRY +nop_glPatchParameteri(GLenum pname, GLint value) +{ + warning(__func__); +} + +static void APIENTRY +nop_glSecondaryColor3hNV(GLhalfNV red, GLhalfNV green, GLhalfNV blue) +{ + warning(__func__); +} + +static void APIENTRY +nop_glSecondaryColor3hvNV(const GLhalfNV *v) +{ + warning(__func__); +} + +static void APIENTRY +nop_glTexCoord1hNV(GLhalfNV s) +{ + warning(__func__); +} + +static void APIENTRY +nop_glTexCoord1hvNV(const GLhalfNV *v) +{ + warning(__func__); +} + +static void APIENTRY +nop_glTexCoord2hNV(GLhalfNV s, GLhalfNV t) +{ + warning(__func__); +} + +static void APIENTRY +nop_glTexCoord2hvNV(const GLhalfNV *v) +{ + warning(__func__); +} + +static void APIENTRY +nop_glTexCoord3hNV(GLhalfNV s, GLhalfNV t, GLhalfNV r) +{ + warning(__func__); +} + +static void APIENTRY +nop_glTexCoord3hvNV(const GLhalfNV *v) +{ + warning(__func__); +} + +static void APIENTRY +nop_glTexCoord4hNV(GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q) +{ + warning(__func__); +} + +static void APIENTRY +nop_glTexCoord4hvNV(const GLhalfNV *v) +{ + warning(__func__); +} + +static void APIENTRY +nop_glTextureParameterfEXT(GLuint texture, GLenum target, GLenum pname, GLfloat param) +{ + warning(__func__); +} + +static void APIENTRY +nop_glTextureParameterfvEXT(GLuint texture, GLenum target, GLenum pname, const GLfloat *params) +{ + warning(__func__); +} + +static void APIENTRY +nop_glTextureParameteriEXT(GLuint texture, GLenum target, GLenum pname, GLint param) +{ + warning(__func__); +} + +static GLboolean APIENTRY +nop_glUnmapNamedBufferEXT(GLuint buffer) +{ + warning(__func__); + return GL_FALSE; +} + +static void APIENTRY +nop_glVertex2hNV(GLhalfNV x, GLhalfNV y) +{ + warning(__func__); +} + +static void APIENTRY +nop_glVertex2hvNV(const GLhalfNV *v) +{ + warning(__func__); +} + +static void APIENTRY +nop_glVertex3hNV(GLhalfNV x, GLhalfNV y, GLhalfNV z) +{ + warning(__func__); +} + +static void APIENTRY +nop_glVertex3hvNV(const GLhalfNV *v) +{ + warning(__func__); +} + +static void APIENTRY +nop_glVertex4hNV(GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w) +{ + warning(__func__); +} + +static void APIENTRY +nop_glVertex4hvNV(const GLhalfNV *v) +{ + warning(__func__); +} + + +PROC +stw_get_nop_function(const char *name) +{ + struct { + const char *name; + PROC p; + } table[] = { + { "glBindMultiTextureEXT", (PROC) nop_glBindMultiTextureEXT }, + { "glColor3hNV", (PROC) nop_glColor3hNV }, + { "glColor3hvNV", (PROC) nop_glColor3hvNV }, + { "glColor4hNV", (PROC) nop_glColor4hNV }, + { "glColor4hvNV", (PROC) nop_glColor4hvNV }, + { "glDisableClientStateIndexedEXT", (PROC) nop_glDisableClientStateIndexedEXT }, + { "glEnableClientStateIndexedEXT", (PROC) nop_glEnableClientStateIndexedEXT }, + { "glFogCoordhNV", (PROC) nop_glFogCoordhNV }, + { "glFogCoordhvNV", (PROC) nop_glFogCoordhvNV }, + { "glGetNamedBufferParameterivEXT", (PROC) nop_glGetNamedBufferParameterivEXT }, + { "glGetNamedBufferSubDataEXT", (PROC) nop_glGetNamedBufferSubDataEXT }, + { "glMapNamedBufferEXT", (PROC) nop_glMapNamedBufferEXT }, + { "glMatrixLoadfEXT", (PROC) nop_glMatrixLoadfEXT }, + { "glMatrixLoadIdentityEXT", (PROC) nop_glMatrixLoadIdentityEXT }, + { "glMultiTexCoord1hNV", (PROC) nop_glMultiTexCoord1hNV }, + { "glMultiTexCoord1hvNV", (PROC) nop_glMultiTexCoord1hvNV }, + { "glMultiTexCoord2hNV", (PROC) nop_glMultiTexCoord2hNV }, + { "glMultiTexCoord2hvNV", (PROC) nop_glMultiTexCoord2hvNV }, + { "glMultiTexCoord3hNV", (PROC) nop_glMultiTexCoord3hNV }, + { "glMultiTexCoord3hvNV", (PROC) nop_glMultiTexCoord3hvNV }, + { "glMultiTexCoord4hNV", (PROC) nop_glMultiTexCoord4hNV }, + { "glMultiTexCoord4hvNV", (PROC) nop_glMultiTexCoord4hvNV }, + { "glMultiTexCoordPointerEXT", (PROC) nop_glMultiTexCoordPointerEXT }, + { "glMultiTexEnvfEXT", (PROC) nop_glMultiTexEnvfEXT }, + { "glMultiTexEnvfvEXT", (PROC) nop_glMultiTexEnvfvEXT }, + { "glMultiTexEnviEXT", (PROC) nop_glMultiTexEnviEXT }, + { "glMultiTexGenfvEXT", (PROC) nop_glMultiTexGenfvEXT }, + { "glMultiTexGeniEXT", (PROC) nop_glMultiTexGeniEXT }, + { "glNamedBufferDataEXT", (PROC) nop_glNamedBufferDataEXT }, + { "glNamedBufferSubDataEXT", (PROC) nop_glNamedBufferSubDataEXT }, + { "glNamedProgramLocalParameter4fvEXT", (PROC) nop_glNamedProgramLocalParameter4fvEXT }, + { "glNamedProgramLocalParameters4fvEXT", (PROC) nop_glNamedProgramLocalParameters4fvEXT }, + { "glNormal3hNV", (PROC) nop_glNormal3hNV }, + { "glNormal3hvNV", (PROC) nop_glNormal3hvNV }, + { "glPatchParameterfv", (PROC) nop_glPatchParameterfv }, + { "glPatchParameteri", (PROC) nop_glPatchParameteri }, + { "glSecondaryColor3hNV", (PROC) nop_glSecondaryColor3hNV }, + { "glSecondaryColor3hvNV", (PROC) nop_glSecondaryColor3hvNV }, + { "glTexCoord1hNV", (PROC) nop_glTexCoord1hNV }, + { "glTexCoord1hvNV", (PROC) nop_glTexCoord1hvNV }, + { "glTexCoord2hNV", (PROC) nop_glTexCoord2hNV }, + { "glTexCoord2hvNV", (PROC) nop_glTexCoord2hvNV }, + { "glTexCoord3hNV", (PROC) nop_glTexCoord3hNV }, + { "glTexCoord3hvNV", (PROC) nop_glTexCoord3hvNV }, + { "glTexCoord4hNV", (PROC) nop_glTexCoord4hNV }, + { "glTexCoord4hvNV", (PROC) nop_glTexCoord4hvNV }, + { "glTextureParameterfEXT", (PROC) nop_glTextureParameterfEXT }, + { "glTextureParameterfvEXT", (PROC) nop_glTextureParameterfvEXT }, + { "glTextureParameteriEXT", (PROC) nop_glTextureParameteriEXT }, + { "glUnmapNamedBufferEXT", (PROC) nop_glUnmapNamedBufferEXT }, + { "glVertex2hNV", (PROC) nop_glVertex2hNV }, + { "glVertex2hvNV", (PROC) nop_glVertex2hvNV }, + { "glVertex3hNV", (PROC) nop_glVertex3hNV }, + { "glVertex3hvNV", (PROC) nop_glVertex3hvNV }, + { "glVertex4hNV", (PROC) nop_glVertex4hNV }, + { "glVertex4hvNV", (PROC) nop_glVertex4hvNV }, + { NULL, NULL } + }; + + int i; + + for (i = 0; table[i].name; i++) { + if (strcmp(table[i].name, name) == 0) + return table[i].p; + } + return NULL; +} diff --git a/src/gallium/frontends/wgl/stw_nopfuncs.h b/src/gallium/frontends/wgl/stw_nopfuncs.h new file mode 100644 index 00000000000..f00d420accf --- /dev/null +++ b/src/gallium/frontends/wgl/stw_nopfuncs.h @@ -0,0 +1,11 @@ + + +#ifndef STW_NOPFUNCS_H +#define STW_NOPFUNCS_H + + +PROC +stw_get_nop_function(const char *name); + + +#endif /* STW_NOPFUNCS_H */ diff --git a/src/gallium/frontends/wgl/stw_pixelformat.c b/src/gallium/frontends/wgl/stw_pixelformat.c new file mode 100644 index 00000000000..8696300f3e0 --- /dev/null +++ b/src/gallium/frontends/wgl/stw_pixelformat.c @@ -0,0 +1,487 @@ +/************************************************************************** + * + * Copyright 2008 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "pipe/p_format.h" +#include "pipe/p_defines.h" +#include "pipe/p_screen.h" + +#include "util/format/u_format.h" +#include "util/u_debug.h" +#include "util/u_memory.h" + +#include +#include "gldrv.h" +#include "stw_device.h" +#include "stw_pixelformat.h" +#include "stw_tls.h" + + +struct stw_pf_color_info +{ + enum pipe_format format; + struct { + unsigned char red; + unsigned char green; + unsigned char blue; + unsigned char alpha; + } bits; + struct { + unsigned char red; + unsigned char green; + unsigned char blue; + unsigned char alpha; + } shift; +}; + +struct stw_pf_depth_info +{ + enum pipe_format format; + struct { + unsigned char depth; + unsigned char stencil; + } bits; +}; + + +/* NOTE: order matters, since in otherwise equal circumstances the first + * format listed will get chosen */ + +static const struct stw_pf_color_info +stw_pf_color[] = { + /* no-alpha */ + { PIPE_FORMAT_B8G8R8X8_UNORM, { 8, 8, 8, 0}, {16, 8, 0, 0} }, + { PIPE_FORMAT_X8R8G8B8_UNORM, { 8, 8, 8, 0}, { 8, 16, 24, 0} }, + /* alpha */ + { PIPE_FORMAT_B8G8R8A8_UNORM, { 8, 8, 8, 8}, {16, 8, 0, 24} }, + { PIPE_FORMAT_A8R8G8B8_UNORM, { 8, 8, 8, 8}, { 8, 16, 24, 0} }, + /* shallow bit depths */ + { PIPE_FORMAT_B5G6R5_UNORM, { 5, 6, 5, 0}, {11, 5, 0, 0} }, +#if 0 + { PIPE_FORMAT_R10G10B10A2_UNORM, {10, 10, 10, 2}, { 0, 10, 20, 30} }, +#endif + { PIPE_FORMAT_B5G5R5A1_UNORM, { 5, 5, 5, 1}, {10, 5, 0, 15} }, + { PIPE_FORMAT_B4G4R4A4_UNORM, { 4, 4, 4, 4}, {16, 4, 0, 12} } +}; + +static const struct stw_pf_color_info +stw_pf_color_extended[] = { + { PIPE_FORMAT_R32G32B32A32_FLOAT, {32, 32, 32, 32}, {0, 32, 64, 96} } +}; + +static const struct stw_pf_depth_info +stw_pf_depth_stencil[] = { + /* pure depth */ + { PIPE_FORMAT_Z32_UNORM, {32, 0} }, + { PIPE_FORMAT_X8Z24_UNORM, {24, 0} }, + { PIPE_FORMAT_Z24X8_UNORM, {24, 0} }, + { PIPE_FORMAT_Z16_UNORM, {16, 0} }, + /* combined depth-stencil */ + { PIPE_FORMAT_Z24_UNORM_S8_UINT, {24, 8} }, + { PIPE_FORMAT_S8_UINT_Z24_UNORM, {24, 8} } +}; + + +static const boolean +stw_pf_doublebuffer[] = { + FALSE, + TRUE, +}; + + +const unsigned +stw_pf_multisample[] = { + 0, + 4, + 8, + 16 +}; + + +static void +stw_pixelformat_add(struct stw_device *stw_dev, + boolean extended, + const struct stw_pf_color_info *color, + const struct stw_pf_depth_info *depth, + unsigned accum, + boolean doublebuffer, + unsigned samples) +{ + struct stw_pixelformat_info *pfi; + + assert(stw_dev->pixelformat_extended_count < STW_MAX_PIXELFORMATS); + if (stw_dev->pixelformat_extended_count >= STW_MAX_PIXELFORMATS) + return; + + assert(util_format_get_component_bits(color->format, UTIL_FORMAT_COLORSPACE_RGB, 0) == color->bits.red); + assert(util_format_get_component_bits(color->format, UTIL_FORMAT_COLORSPACE_RGB, 1) == color->bits.green); + assert(util_format_get_component_bits(color->format, UTIL_FORMAT_COLORSPACE_RGB, 2) == color->bits.blue); + assert(util_format_get_component_bits(color->format, UTIL_FORMAT_COLORSPACE_RGB, 3) == color->bits.alpha); + assert(util_format_get_component_bits(depth->format, UTIL_FORMAT_COLORSPACE_ZS, 0) == depth->bits.depth); + assert(util_format_get_component_bits(depth->format, UTIL_FORMAT_COLORSPACE_ZS, 1) == depth->bits.stencil); + + pfi = &stw_dev->pixelformats[stw_dev->pixelformat_extended_count]; + + memset(pfi, 0, sizeof *pfi); + + pfi->pfd.nSize = sizeof pfi->pfd; + pfi->pfd.nVersion = 1; + + pfi->pfd.dwFlags = PFD_SUPPORT_OPENGL; + + /* TODO: also support non-native pixel formats */ + if (!extended) { + pfi->pfd.dwFlags |= PFD_DRAW_TO_WINDOW; + } + + /* See http://www.opengl.org/pipeline/article/vol003_7/ */ + pfi->pfd.dwFlags |= PFD_SUPPORT_COMPOSITION; + + if (doublebuffer) + pfi->pfd.dwFlags |= PFD_DOUBLEBUFFER | PFD_SWAP_EXCHANGE; + + pfi->pfd.iPixelType = PFD_TYPE_RGBA; + + pfi->pfd.cColorBits = + color->bits.red + color->bits.green + color->bits.blue + color->bits.alpha; + pfi->pfd.cRedBits = color->bits.red; + pfi->pfd.cRedShift = color->shift.red; + pfi->pfd.cGreenBits = color->bits.green; + pfi->pfd.cGreenShift = color->shift.green; + pfi->pfd.cBlueBits = color->bits.blue; + pfi->pfd.cBlueShift = color->shift.blue; + pfi->pfd.cAlphaBits = color->bits.alpha; + pfi->pfd.cAlphaShift = color->shift.alpha; + pfi->pfd.cAccumBits = 4*accum; + pfi->pfd.cAccumRedBits = accum; + pfi->pfd.cAccumGreenBits = accum; + pfi->pfd.cAccumBlueBits = accum; + pfi->pfd.cAccumAlphaBits = accum; + pfi->pfd.cDepthBits = depth->bits.depth; + pfi->pfd.cStencilBits = depth->bits.stencil; + pfi->pfd.cAuxBuffers = 0; + pfi->pfd.iLayerType = 0; + pfi->pfd.bReserved = 0; + pfi->pfd.dwLayerMask = 0; + pfi->pfd.dwVisibleMask = 0; + pfi->pfd.dwDamageMask = 0; + + /* + * since state trackers can allocate depth/stencil/accum buffers, we provide + * only color buffers here + */ + pfi->stvis.buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK; + if (doublebuffer) + pfi->stvis.buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK; + + pfi->stvis.color_format = color->format; + pfi->stvis.depth_stencil_format = depth->format; + + pfi->stvis.accum_format = (accum) ? + PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE; + + pfi->stvis.samples = samples; + pfi->stvis.render_buffer = ST_ATTACHMENT_INVALID; + + /* WGL_ARB_render_texture */ + if (color->bits.alpha) + pfi->bindToTextureRGBA = TRUE; + + pfi->bindToTextureRGB = TRUE; + + ++stw_dev->pixelformat_extended_count; + + if (!extended) { + ++stw_dev->pixelformat_count; + assert(stw_dev->pixelformat_count == stw_dev->pixelformat_extended_count); + } +} + + +/** + * Add the depth/stencil/accum/ms variants for a list of color formats. + */ +static unsigned +add_color_format_variants(const struct stw_pf_color_info *color_formats, + unsigned num_color_formats, boolean extended) +{ + struct pipe_screen *screen = stw_dev->screen; + unsigned cfmt, ms, db, ds, acc; + unsigned bind_flags = PIPE_BIND_RENDER_TARGET; + unsigned num_added = 0; + int force_samples = 0; + + /* Since GLUT for Windows doesn't support MSAA we have an env var + * to force all pixel formats to have a particular number of samples. + */ + { + const char *samples= getenv("SVGA_FORCE_MSAA"); + if (samples) + force_samples = atoi(samples); + } + + if (!extended) { + bind_flags |= PIPE_BIND_DISPLAY_TARGET; + } + + for (ms = 0; ms < ARRAY_SIZE(stw_pf_multisample); ms++) { + unsigned samples = stw_pf_multisample[ms]; + + if (force_samples && samples != force_samples) + continue; + + for (cfmt = 0; cfmt < num_color_formats; cfmt++) { + if (!screen->is_format_supported(screen, color_formats[cfmt].format, + PIPE_TEXTURE_2D, samples, samples, + bind_flags)) { + continue; + } + + for (db = 0; db < ARRAY_SIZE(stw_pf_doublebuffer); db++) { + unsigned doublebuffer = stw_pf_doublebuffer[db]; + + for (ds = 0; ds < ARRAY_SIZE(stw_pf_depth_stencil); ds++) { + const struct stw_pf_depth_info *depth = &stw_pf_depth_stencil[ds]; + + if (!screen->is_format_supported(screen, depth->format, + PIPE_TEXTURE_2D, samples, + samples, + PIPE_BIND_DEPTH_STENCIL)) { + continue; + } + + for (acc = 0; acc < 2; acc++) { + stw_pixelformat_add(stw_dev, extended, &color_formats[cfmt], + depth, + acc * 16, doublebuffer, samples); + num_added++; + } + } + } + } + } + + return num_added; +} + + +void +stw_pixelformat_init(void) +{ + unsigned num_formats; + + assert(!stw_dev->pixelformat_count); + assert(!stw_dev->pixelformat_extended_count); + + /* normal, displayable formats */ + num_formats = add_color_format_variants(stw_pf_color, + ARRAY_SIZE(stw_pf_color), FALSE); + assert(num_formats > 0); + + /* extended, pbuffer-only formats */ + add_color_format_variants(stw_pf_color_extended, + ARRAY_SIZE(stw_pf_color_extended), TRUE); + + assert(stw_dev->pixelformat_count <= stw_dev->pixelformat_extended_count); + assert(stw_dev->pixelformat_extended_count <= STW_MAX_PIXELFORMATS); +} + + +uint +stw_pixelformat_get_count(void) +{ + if (!stw_init_screen()) + return 0; + + return stw_dev->pixelformat_count; +} + + +uint +stw_pixelformat_get_extended_count(void) +{ + if (!stw_init_screen()) + return 0; + + return stw_dev->pixelformat_extended_count; +} + + +const struct stw_pixelformat_info * +stw_pixelformat_get_info(int iPixelFormat) +{ + unsigned index; + + if (iPixelFormat <= 0) { + return NULL; + } + + index = iPixelFormat - 1; + if (index >= stw_dev->pixelformat_extended_count) { + return NULL; + } + + return &stw_dev->pixelformats[index]; +} + + +LONG APIENTRY +DrvDescribePixelFormat(HDC hdc, INT iPixelFormat, ULONG cjpfd, + PIXELFORMATDESCRIPTOR *ppfd) +{ + uint count; + const struct stw_pixelformat_info *pfi; + + (void) hdc; + + if (!stw_dev) + return 0; + + count = stw_pixelformat_get_count(); + + if (ppfd == NULL) + return count; + + if (cjpfd != sizeof(PIXELFORMATDESCRIPTOR)) + return 0; + + pfi = stw_pixelformat_get_info(iPixelFormat); + if (!pfi) { + return 0; + } + + memcpy(ppfd, &pfi->pfd, sizeof(PIXELFORMATDESCRIPTOR)); + + return count; +} + + +BOOL APIENTRY +DrvDescribeLayerPlane(HDC hdc, INT iPixelFormat, INT iLayerPlane, + UINT nBytes, LPLAYERPLANEDESCRIPTOR plpd) +{ + assert(0); + return FALSE; +} + + +int APIENTRY +DrvGetLayerPaletteEntries(HDC hdc, INT iLayerPlane, INT iStart, + INT cEntries, COLORREF *pcr) +{ + assert(0); + return 0; +} + + +int APIENTRY +DrvSetLayerPaletteEntries(HDC hdc, INT iLayerPlane, INT iStart, + INT cEntries, CONST COLORREF *pcr) +{ + assert(0); + return 0; +} + + +BOOL APIENTRY +DrvRealizeLayerPalette(HDC hdc, INT iLayerPlane, BOOL bRealize) +{ + assert(0); + return FALSE; +} + + +/* Only used by the wgl code, but have it here to avoid exporting the + * pixelformat.h functionality. + */ +int +stw_pixelformat_choose(HDC hdc, CONST PIXELFORMATDESCRIPTOR *ppfd) +{ + uint count; + uint index; + uint bestindex; + uint bestdelta; + + (void) hdc; + + count = stw_pixelformat_get_extended_count(); + bestindex = 0; + bestdelta = ~0U; + + for (index = 1; index <= count; index++) { + uint delta = 0; + const struct stw_pixelformat_info *pfi = stw_pixelformat_get_info(index); + + if (!(ppfd->dwFlags & PFD_DOUBLEBUFFER_DONTCARE) && + !!(ppfd->dwFlags & PFD_DOUBLEBUFFER) != + !!(pfi->pfd.dwFlags & PFD_DOUBLEBUFFER)) + continue; + + /* Selection logic: + * - Enabling a feature (depth, stencil...) is given highest priority. + * - Giving as many bits as requested is given medium priority. + * - Giving no more bits than requested is given lowest priority. + */ + + /* FIXME: Take in account individual channel bits */ + if (ppfd->cColorBits && !pfi->pfd.cColorBits) + delta += 10000; + else if (ppfd->cColorBits > pfi->pfd.cColorBits) + delta += 100; + else if (ppfd->cColorBits < pfi->pfd.cColorBits) + delta++; + + if (ppfd->cDepthBits && !pfi->pfd.cDepthBits) + delta += 10000; + else if (ppfd->cDepthBits > pfi->pfd.cDepthBits) + delta += 200; + else if (ppfd->cDepthBits < pfi->pfd.cDepthBits) + delta += 2; + + if (ppfd->cStencilBits && !pfi->pfd.cStencilBits) + delta += 10000; + else if (ppfd->cStencilBits > pfi->pfd.cStencilBits) + delta += 400; + else if (ppfd->cStencilBits < pfi->pfd.cStencilBits) + delta++; + + if (ppfd->cAlphaBits && !pfi->pfd.cAlphaBits) + delta += 10000; + else if (ppfd->cAlphaBits > pfi->pfd.cAlphaBits) + delta += 100; + else if (ppfd->cAlphaBits < pfi->pfd.cAlphaBits) + delta++; + + if (delta < bestdelta) { + bestindex = index; + bestdelta = delta; + if (bestdelta == 0) + break; + } + } + + return bestindex; +} diff --git a/src/gallium/frontends/wgl/stw_pixelformat.h b/src/gallium/frontends/wgl/stw_pixelformat.h new file mode 100644 index 00000000000..e3ab1ee7514 --- /dev/null +++ b/src/gallium/frontends/wgl/stw_pixelformat.h @@ -0,0 +1,71 @@ +/************************************************************************** + * + * Copyright 2008 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef STW_PIXELFORMAT_H +#define STW_PIXELFORMAT_H + +#include + +#ifndef PFD_SUPPORT_COMPOSITION +#define PFD_SUPPORT_COMPOSITION 0x00008000 +#endif + +#include "pipe/p_compiler.h" +#include "pipe/p_format.h" +#include "frontend/api.h" + +struct stw_pixelformat_info +{ + PIXELFORMATDESCRIPTOR pfd; + + struct st_visual stvis; + + /** WGL_ARB_render_texture */ + boolean bindToTextureRGB; + boolean bindToTextureRGBA; +}; + +void +stw_pixelformat_init( void ); + +uint +stw_pixelformat_get_count( void ); + +uint +stw_pixelformat_get_extended_count( void ); + +const struct stw_pixelformat_info * +stw_pixelformat_get_info( int iPixelFormat ); + +int +stw_pixelformat_choose( HDC hdc, + CONST PIXELFORMATDESCRIPTOR *ppfd ); + +int +stw_pixelformat_get(HDC hdc); + +#endif /* STW_PIXELFORMAT_H */ diff --git a/src/gallium/frontends/wgl/stw_st.c b/src/gallium/frontends/wgl/stw_st.c new file mode 100644 index 00000000000..e173c816c7c --- /dev/null +++ b/src/gallium/frontends/wgl/stw_st.c @@ -0,0 +1,394 @@ +/* + * Mesa 3-D graphics library + * + * Copyright (C) 2010 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu + */ + +#include "util/u_memory.h" +#include "util/u_inlines.h" +#include "util/u_atomic.h" +#include "state_tracker/st_gl_api.h" /* for st_gl_api_create */ + +#include "stw_st.h" +#include "stw_device.h" +#include "stw_framebuffer.h" +#include "stw_pixelformat.h" + +struct stw_st_framebuffer { + struct st_framebuffer_iface base; + + struct stw_framebuffer *fb; + struct st_visual stvis; + + struct pipe_resource *textures[ST_ATTACHMENT_COUNT]; + struct pipe_resource *msaa_textures[ST_ATTACHMENT_COUNT]; + unsigned texture_width, texture_height; + unsigned texture_mask; +}; + +static uint32_t stwfb_ID = 0; + +/** + * Is the given mutex held by the calling thread? + */ +bool +stw_own_mutex(const CRITICAL_SECTION *cs) +{ + // We can't compare OwningThread with our thread handle/id (see + // http://stackoverflow.com/a/12675635 ) but we can compare with the + // OwningThread member of a critical section we know we own. + CRITICAL_SECTION dummy; + InitializeCriticalSection(&dummy); + EnterCriticalSection(&dummy); + if (0) + _debug_printf("%p %p\n", cs->OwningThread, dummy.OwningThread); + bool ret = cs->OwningThread == dummy.OwningThread; + LeaveCriticalSection(&dummy); + DeleteCriticalSection(&dummy); + return ret; +} + + +/** + * Remove outdated textures and create the requested ones. + */ +static void +stw_st_framebuffer_validate_locked(struct st_framebuffer_iface *stfb, + unsigned width, unsigned height, + unsigned mask) +{ + struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb); + struct pipe_resource templ; + unsigned i; + + /* remove outdated textures */ + if (stwfb->texture_width != width || stwfb->texture_height != height) { + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { + pipe_resource_reference(&stwfb->msaa_textures[i], NULL); + pipe_resource_reference(&stwfb->textures[i], NULL); + } + } + + memset(&templ, 0, sizeof(templ)); + templ.target = PIPE_TEXTURE_2D; + templ.width0 = width; + templ.height0 = height; + templ.depth0 = 1; + templ.array_size = 1; + templ.last_level = 0; + + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { + enum pipe_format format; + unsigned bind; + + /* the texture already exists or not requested */ + if (stwfb->textures[i] || !(mask & (1 << i))) { + /* remember the texture */ + if (stwfb->textures[i]) + mask |= (1 << i); + continue; + } + + switch (i) { + case ST_ATTACHMENT_FRONT_LEFT: + case ST_ATTACHMENT_BACK_LEFT: + format = stwfb->stvis.color_format; + bind = PIPE_BIND_DISPLAY_TARGET | + PIPE_BIND_SAMPLER_VIEW | + PIPE_BIND_RENDER_TARGET; + break; + case ST_ATTACHMENT_DEPTH_STENCIL: + format = stwfb->stvis.depth_stencil_format; + bind = PIPE_BIND_DEPTH_STENCIL; + break; + default: + format = PIPE_FORMAT_NONE; + break; + } + + if (format != PIPE_FORMAT_NONE) { + templ.format = format; + + if (bind != PIPE_BIND_DEPTH_STENCIL && stwfb->stvis.samples > 1) { + templ.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; + templ.nr_samples = templ.nr_storage_samples = + stwfb->stvis.samples; + + stwfb->msaa_textures[i] = + stw_dev->screen->resource_create(stw_dev->screen, &templ); + } + + templ.bind = bind; + templ.nr_samples = templ.nr_storage_samples = 1; + stwfb->textures[i] = + stw_dev->screen->resource_create(stw_dev->screen, &templ); + } + } + + stwfb->texture_width = width; + stwfb->texture_height = height; + stwfb->texture_mask = mask; +} + +static bool +stw_st_framebuffer_validate(struct st_context_iface *stctx, + struct st_framebuffer_iface *stfb, + const enum st_attachment_type *statts, + unsigned count, + struct pipe_resource **out) +{ + struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb); + unsigned statt_mask, i; + + statt_mask = 0x0; + for (i = 0; i < count; i++) + statt_mask |= 1 << statts[i]; + + stw_framebuffer_lock(stwfb->fb); + + if (stwfb->fb->must_resize || (statt_mask & ~stwfb->texture_mask)) { + stw_st_framebuffer_validate_locked(&stwfb->base, + stwfb->fb->width, stwfb->fb->height, statt_mask); + stwfb->fb->must_resize = FALSE; + } + + struct pipe_resource **textures = + stwfb->stvis.samples > 1 ? stwfb->msaa_textures + : stwfb->textures; + + for (i = 0; i < count; i++) + pipe_resource_reference(&out[i], textures[statts[i]]); + + stw_framebuffer_unlock(stwfb->fb); + + return true; +} + +static void +stw_pipe_blit(struct pipe_context *pipe, + struct pipe_resource *dst, + struct pipe_resource *src) +{ + struct pipe_blit_info blit; + + /* From the GL spec, version 4.2, section 4.1.11 (Additional Multisample + * Fragment Operations): + * + * If a framebuffer object is not bound, after all operations have + * been completed on the multisample buffer, the sample values for + * each color in the multisample buffer are combined to produce a + * single color value, and that value is written into the + * corresponding color buffers selected by DrawBuffer or + * DrawBuffers. An implementation may defer the writing of the color + * buffers until a later time, but the state of the framebuffer must + * behave as if the color buffers were updated as each fragment was + * processed. The method of combination is not specified. If the + * framebuffer contains sRGB values, then it is recommended that the + * an average of sample values is computed in a linearized space, as + * for blending (see section 4.1.7). + * + * In other words, to do a resolve operation in a linear space, we have + * to set sRGB formats if the original resources were sRGB, so don't use + * util_format_linear. + */ + + memset(&blit, 0, sizeof(blit)); + blit.dst.resource = dst; + blit.dst.box.width = dst->width0; + blit.dst.box.height = dst->height0; + blit.dst.box.depth = 1; + blit.dst.format = dst->format; + blit.src.resource = src; + blit.src.box.width = src->width0; + blit.src.box.height = src->height0; + blit.src.box.depth = 1; + blit.src.format = src->format; + blit.mask = PIPE_MASK_RGBA; + blit.filter = PIPE_TEX_FILTER_NEAREST; + + pipe->blit(pipe, &blit); +} + +/** + * Present an attachment of the framebuffer. + */ +static bool +stw_st_framebuffer_present_locked(HDC hdc, + struct st_context_iface *stctx, + struct st_framebuffer_iface *stfb, + enum st_attachment_type statt) +{ + struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb); + struct pipe_resource *resource; + + assert(stw_own_mutex(&stwfb->fb->mutex)); + + if (stwfb->stvis.samples > 1) { + stw_pipe_blit(stctx->pipe, + stwfb->textures[statt], + stwfb->msaa_textures[statt]); + } + + resource = stwfb->textures[statt]; + if (resource) { + stw_framebuffer_present_locked(hdc, stwfb->fb, resource); + } + else { + stw_framebuffer_unlock(stwfb->fb); + } + + assert(!stw_own_mutex(&stwfb->fb->mutex)); + + return true; +} + +static bool +stw_st_framebuffer_flush_front(struct st_context_iface *stctx, + struct st_framebuffer_iface *stfb, + enum st_attachment_type statt) +{ + struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb); + bool ret; + HDC hDC; + + stw_framebuffer_lock(stwfb->fb); + + /* We must not cache HDCs anywhere, as they can be invalidated by the + * application, or screen resolution changes. */ + + hDC = GetDC(stwfb->fb->hWnd); + + ret = stw_st_framebuffer_present_locked(hDC, stctx, &stwfb->base, statt); + + ReleaseDC(stwfb->fb->hWnd, hDC); + + return ret; +} + +/** + * Create a framebuffer interface. + */ +struct st_framebuffer_iface * +stw_st_create_framebuffer(struct stw_framebuffer *fb) +{ + struct stw_st_framebuffer *stwfb; + + stwfb = CALLOC_STRUCT(stw_st_framebuffer); + if (!stwfb) + return NULL; + + stwfb->fb = fb; + stwfb->stvis = fb->pfi->stvis; + stwfb->base.ID = p_atomic_inc_return(&stwfb_ID); + stwfb->base.state_manager = stw_dev->smapi; + + stwfb->base.visual = &stwfb->stvis; + p_atomic_set(&stwfb->base.stamp, 1); + stwfb->base.flush_front = stw_st_framebuffer_flush_front; + stwfb->base.validate = stw_st_framebuffer_validate; + + return &stwfb->base; +} + +/** + * Destroy a framebuffer interface. + */ +void +stw_st_destroy_framebuffer_locked(struct st_framebuffer_iface *stfb) +{ + struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb); + int i; + + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { + pipe_resource_reference(&stwfb->msaa_textures[i], NULL); + pipe_resource_reference(&stwfb->textures[i], NULL); + } + + /* Notify the st manager that the framebuffer interface is no + * longer valid. + */ + stw_dev->stapi->destroy_drawable(stw_dev->stapi, &stwfb->base); + + FREE(stwfb); +} + +/** + * Swap the buffers of the given framebuffer. + */ +bool +stw_st_swap_framebuffer_locked(HDC hdc, struct st_context_iface *stctx, + struct st_framebuffer_iface *stfb) +{ + struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb); + unsigned front = ST_ATTACHMENT_FRONT_LEFT, back = ST_ATTACHMENT_BACK_LEFT; + struct pipe_resource *ptex; + unsigned mask; + + /* swap the textures */ + ptex = stwfb->textures[front]; + stwfb->textures[front] = stwfb->textures[back]; + stwfb->textures[back] = ptex; + + /* swap msaa_textures */ + ptex = stwfb->msaa_textures[front]; + stwfb->msaa_textures[front] = stwfb->msaa_textures[back]; + stwfb->msaa_textures[back] = ptex; + + /* convert to mask */ + front = 1 << front; + back = 1 << back; + + /* swap the bits in mask */ + mask = stwfb->texture_mask & ~(front | back); + if (stwfb->texture_mask & front) + mask |= back; + if (stwfb->texture_mask & back) + mask |= front; + stwfb->texture_mask = mask; + + front = ST_ATTACHMENT_FRONT_LEFT; + return stw_st_framebuffer_present_locked(hdc, stctx, &stwfb->base, front); +} + + +/** + * Return the pipe_resource that correspond to given buffer. + */ +struct pipe_resource * +stw_get_framebuffer_resource(struct st_framebuffer_iface *stfb, + enum st_attachment_type att) +{ + struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb); + return stwfb->textures[att]; +} + + +/** + * Create an st_api of the state tracker. + */ +struct st_api * +stw_st_create_api(void) +{ + return st_gl_api_create(); +} diff --git a/src/gallium/frontends/wgl/stw_st.h b/src/gallium/frontends/wgl/stw_st.h new file mode 100644 index 00000000000..91b8fffc2ce --- /dev/null +++ b/src/gallium/frontends/wgl/stw_st.h @@ -0,0 +1,57 @@ +/* + * Mesa 3-D graphics library + * + * Copyright (C) 2010 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu + */ + +#ifndef STW_ST_H +#define STW_ST_H + +#include + +#include "frontend/api.h" + +struct stw_framebuffer; + +bool +stw_own_mutex(const CRITICAL_SECTION *cs); + +struct st_api * +stw_st_create_api(void); + +struct st_framebuffer_iface * +stw_st_create_framebuffer(struct stw_framebuffer *fb); + +void +stw_st_destroy_framebuffer_locked(struct st_framebuffer_iface *stfb); + +bool +stw_st_swap_framebuffer_locked(HDC hdc, struct st_context_iface *stctx, + struct st_framebuffer_iface *stfb); + +struct pipe_resource * +stw_get_framebuffer_resource(struct st_framebuffer_iface *stfb, + enum st_attachment_type att); + +#endif /* STW_ST_H */ diff --git a/src/gallium/frontends/wgl/stw_tls.c b/src/gallium/frontends/wgl/stw_tls.c new file mode 100644 index 00000000000..9b7d60c6d8c --- /dev/null +++ b/src/gallium/frontends/wgl/stw_tls.c @@ -0,0 +1,305 @@ +/************************************************************************** + * + * Copyright 2009-2013 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include +#include + +#include "pipe/p_compiler.h" +#include "util/u_debug.h" +#include "stw_tls.h" + +static DWORD tlsIndex = TLS_OUT_OF_INDEXES; + + +/** + * Static mutex to protect the access to g_pendingTlsData global and + * stw_tls_data::next member. + */ +static CRITICAL_SECTION g_mutex = { + (PCRITICAL_SECTION_DEBUG)-1, -1, 0, 0, 0, 0 +}; + +/** + * There is no way to invoke TlsSetValue for a different thread, so we + * temporarily put the thread data for non-current threads here. + */ +static struct stw_tls_data *g_pendingTlsData = NULL; + + +static struct stw_tls_data * +stw_tls_data_create(DWORD dwThreadId); + +static struct stw_tls_data * +stw_tls_lookup_pending_data(DWORD dwThreadId); + + +boolean +stw_tls_init(void) +{ + tlsIndex = TlsAlloc(); + if (tlsIndex == TLS_OUT_OF_INDEXES) { + return FALSE; + } + + /* + * DllMain is called with DLL_THREAD_ATTACH only for threads created after + * the DLL is loaded by the process. So enumerate and add our hook to all + * previously existing threads. + * + * XXX: Except for the current thread since it there is an explicit + * stw_tls_init_thread() call for it later on. + */ + if (1) { + DWORD dwCurrentProcessId = GetCurrentProcessId(); + DWORD dwCurrentThreadId = GetCurrentThreadId(); + HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, dwCurrentProcessId); + if (hSnapshot != INVALID_HANDLE_VALUE) { + THREADENTRY32 te; + te.dwSize = sizeof te; + if (Thread32First(hSnapshot, &te)) { + do { + if (te.dwSize >= FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) + + sizeof te.th32OwnerProcessID) { + if (te.th32OwnerProcessID == dwCurrentProcessId) { + if (te.th32ThreadID != dwCurrentThreadId) { + struct stw_tls_data *data; + data = stw_tls_data_create(te.th32ThreadID); + if (data) { + EnterCriticalSection(&g_mutex); + data->next = g_pendingTlsData; + g_pendingTlsData = data; + LeaveCriticalSection(&g_mutex); + } + } + } + } + te.dwSize = sizeof te; + } while (Thread32Next(hSnapshot, &te)); + } + CloseHandle(hSnapshot); + } + } + + return TRUE; +} + + +/** + * Install windows hook for a given thread (not necessarily the current one). + */ +static struct stw_tls_data * +stw_tls_data_create(DWORD dwThreadId) +{ + struct stw_tls_data *data; + + if (0) { + debug_printf("%s(0x%04lx)\n", __FUNCTION__, dwThreadId); + } + + data = calloc(1, sizeof *data); + if (!data) { + goto no_data; + } + + data->dwThreadId = dwThreadId; + + data->hCallWndProcHook = SetWindowsHookEx(WH_CALLWNDPROC, + stw_call_window_proc, + NULL, + dwThreadId); + if (data->hCallWndProcHook == NULL) { + goto no_hook; + } + + return data; + +no_hook: + free(data); +no_data: + return NULL; +} + +/** + * Destroy the per-thread data/hook. + * + * It is important to remove all hooks when unloading our DLL, otherwise our + * hook function might be called after it is no longer there. + */ +static void +stw_tls_data_destroy(struct stw_tls_data *data) +{ + assert(data); + if (!data) { + return; + } + + if (0) { + debug_printf("%s(0x%04lx)\n", __FUNCTION__, data->dwThreadId); + } + + if (data->hCallWndProcHook) { + UnhookWindowsHookEx(data->hCallWndProcHook); + data->hCallWndProcHook = NULL; + } + + free(data); +} + +boolean +stw_tls_init_thread(void) +{ + struct stw_tls_data *data; + + if (tlsIndex == TLS_OUT_OF_INDEXES) { + return FALSE; + } + + data = stw_tls_data_create(GetCurrentThreadId()); + if (!data) { + return FALSE; + } + + TlsSetValue(tlsIndex, data); + + return TRUE; +} + +void +stw_tls_cleanup_thread(void) +{ + struct stw_tls_data *data; + + if (tlsIndex == TLS_OUT_OF_INDEXES) { + return; + } + + data = (struct stw_tls_data *) TlsGetValue(tlsIndex); + if (data) { + TlsSetValue(tlsIndex, NULL); + } else { + /* See if there this thread's data in on the pending list */ + data = stw_tls_lookup_pending_data(GetCurrentThreadId()); + } + + if (data) { + stw_tls_data_destroy(data); + } +} + +void +stw_tls_cleanup(void) +{ + if (tlsIndex != TLS_OUT_OF_INDEXES) { + /* + * Destroy all items in g_pendingTlsData linked list. + */ + EnterCriticalSection(&g_mutex); + while (g_pendingTlsData) { + struct stw_tls_data * data = g_pendingTlsData; + g_pendingTlsData = data->next; + stw_tls_data_destroy(data); + } + LeaveCriticalSection(&g_mutex); + + TlsFree(tlsIndex); + tlsIndex = TLS_OUT_OF_INDEXES; + } +} + +/* + * Search for the current thread in the g_pendingTlsData linked list. + * + * It will remove and return the node on success, or return NULL on failure. + */ +static struct stw_tls_data * +stw_tls_lookup_pending_data(DWORD dwThreadId) +{ + struct stw_tls_data ** p_data; + struct stw_tls_data *data = NULL; + + EnterCriticalSection(&g_mutex); + for (p_data = &g_pendingTlsData; *p_data; p_data = &(*p_data)->next) { + if ((*p_data)->dwThreadId == dwThreadId) { + data = *p_data; + + /* + * Unlink the node. + */ + *p_data = data->next; + data->next = NULL; + + break; + } + } + LeaveCriticalSection(&g_mutex); + + return data; +} + +struct stw_tls_data * +stw_tls_get_data(void) +{ + struct stw_tls_data *data; + + if (tlsIndex == TLS_OUT_OF_INDEXES) { + return NULL; + } + + data = (struct stw_tls_data *) TlsGetValue(tlsIndex); + if (!data) { + DWORD dwCurrentThreadId = GetCurrentThreadId(); + + /* + * Search for the current thread in the g_pendingTlsData linked list. + */ + data = stw_tls_lookup_pending_data(dwCurrentThreadId); + + if (!data) { + /* + * This should be impossible now. + */ + assert(!"Failed to find thread data for thread id"); + + /* + * DllMain is called with DLL_THREAD_ATTACH only by threads created + * after the DLL is loaded by the process + */ + data = stw_tls_data_create(dwCurrentThreadId); + if (!data) { + return NULL; + } + } + + TlsSetValue(tlsIndex, data); + } + + assert(data); + assert(data->dwThreadId = GetCurrentThreadId()); + assert(data->next == NULL); + + return data; +} diff --git a/src/gallium/frontends/wgl/stw_tls.h b/src/gallium/frontends/wgl/stw_tls.h new file mode 100644 index 00000000000..07cfe3168d9 --- /dev/null +++ b/src/gallium/frontends/wgl/stw_tls.h @@ -0,0 +1,63 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef STW_TLS_H +#define STW_TLS_H + +#include + +struct stw_tls_data +{ + DWORD dwThreadId; + + HHOOK hCallWndProcHook; + + struct stw_tls_data *next; +}; + +boolean +stw_tls_init(void); + +boolean +stw_tls_init_thread(void); + +void +stw_tls_cleanup_thread(void); + +void +stw_tls_cleanup(void); + +struct stw_tls_data * +stw_tls_get_data(void); + +LRESULT CALLBACK +stw_call_window_proc( + int nCode, + WPARAM wParam, + LPARAM lParam ); + +#endif /* STW_TLS_H */ diff --git a/src/gallium/frontends/wgl/stw_wgl.c b/src/gallium/frontends/wgl/stw_wgl.c new file mode 100644 index 00000000000..9103c750ea9 --- /dev/null +++ b/src/gallium/frontends/wgl/stw_wgl.c @@ -0,0 +1,400 @@ +/************************************************************************** + * + * Copyright 2008 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/** + * @file + * + * Fake WGL API implementation. + * + * These functions implement the WGL API, on top of the ICD DDI, so that the + * resulting DLL can be used as a drop-in replacement for the system's + * opengl32.dll. + * + * These functions never get called for ICD drivers, which use exclusively the + * ICD DDI, i.e., the Drv* entrypoints. + */ + +#include +#include + +#include "util/u_debug.h" +#include "gldrv.h" +#include "stw_context.h" +#include "stw_pixelformat.h" +#include "stw_wgl.h" +#include "stw_ext_context.h" + + +static void +overrideOpenGL32EntryPoints(void); + +WINGDIAPI BOOL APIENTRY +wglCopyContext( + HGLRC hglrcSrc, + HGLRC hglrcDst, + UINT mask ) +{ + return DrvCopyContext( (DHGLRC)(UINT_PTR)hglrcSrc, + (DHGLRC)(UINT_PTR)hglrcDst, + mask ); +} + +WINGDIAPI HGLRC APIENTRY +wglCreateContext( + HDC hdc ) +{ + overrideOpenGL32EntryPoints(); + return (HGLRC)(UINT_PTR)DrvCreateContext(hdc); +} + +WINGDIAPI HGLRC APIENTRY +wglCreateLayerContext( + HDC hdc, + int iLayerPlane ) +{ + overrideOpenGL32EntryPoints(); + return (HGLRC)(UINT_PTR)DrvCreateLayerContext( hdc, iLayerPlane ); +} + +WINGDIAPI BOOL APIENTRY +wglDeleteContext( + HGLRC hglrc ) +{ + return DrvDeleteContext((DHGLRC)(UINT_PTR)hglrc ); +} + + +WINGDIAPI HGLRC APIENTRY +wglGetCurrentContext( VOID ) +{ + return (HGLRC)(UINT_PTR)stw_get_current_context(); +} + +WINGDIAPI HDC APIENTRY +wglGetCurrentDC( VOID ) +{ + return stw_get_current_dc(); +} + +WINGDIAPI HDC APIENTRY +wglGetCurrentReadDCARB( VOID ) +{ + return stw_get_current_read_dc(); +} + + +WINGDIAPI BOOL APIENTRY +wglMakeCurrent( + HDC hdc, + HGLRC hglrc ) +{ + return DrvSetContext( hdc, (DHGLRC)(UINT_PTR)hglrc, NULL ) ? TRUE : FALSE; +} + + +WINGDIAPI BOOL APIENTRY +wglSwapBuffers( + HDC hdc ) +{ + return DrvSwapBuffers( hdc ); +} + + +WINGDIAPI DWORD WINAPI +wglSwapMultipleBuffers(UINT n, + CONST WGLSWAP *ps) +{ + UINT i; + + for (i =0; i < n; ++i) + wglSwapBuffers(ps->hdc); + + return 0; +} + + +WINGDIAPI BOOL APIENTRY +wglSwapLayerBuffers( + HDC hdc, + UINT fuPlanes ) +{ + return DrvSwapLayerBuffers( hdc, fuPlanes ); +} + +WINGDIAPI PROC APIENTRY +wglGetProcAddress( + LPCSTR lpszProc ) +{ + return DrvGetProcAddress( lpszProc ); +} + + +WINGDIAPI int APIENTRY +wglChoosePixelFormat( + HDC hdc, + CONST PIXELFORMATDESCRIPTOR *ppfd ) +{ + if (ppfd->nSize != sizeof( PIXELFORMATDESCRIPTOR ) || ppfd->nVersion != 1) + return 0; + if (ppfd->iPixelType != PFD_TYPE_RGBA) + return 0; + if (!(ppfd->dwFlags & PFD_DRAW_TO_WINDOW)) + return 0; + if (!(ppfd->dwFlags & PFD_SUPPORT_OPENGL)) + return 0; + if (ppfd->dwFlags & PFD_DRAW_TO_BITMAP) + return 0; + if (ppfd->dwFlags & PFD_SUPPORT_GDI) + return 0; + if (!(ppfd->dwFlags & PFD_STEREO_DONTCARE) && (ppfd->dwFlags & PFD_STEREO)) + return 0; + + return stw_pixelformat_choose( hdc, ppfd ); +} + +WINGDIAPI int APIENTRY +wglDescribePixelFormat( + HDC hdc, + int iPixelFormat, + UINT nBytes, + LPPIXELFORMATDESCRIPTOR ppfd ) +{ + return DrvDescribePixelFormat( hdc, iPixelFormat, nBytes, ppfd ); +} + +WINGDIAPI int APIENTRY +wglGetPixelFormat( + HDC hdc ) +{ + return stw_pixelformat_get( hdc ); +} + +WINGDIAPI BOOL APIENTRY +wglSetPixelFormat( + HDC hdc, + int iPixelFormat, + const PIXELFORMATDESCRIPTOR *ppfd ) +{ + /* SetPixelFormat (hence wglSetPixelFormat) must not touch ppfd, per + * http://msdn.microsoft.com/en-us/library/dd369049(v=vs.85).aspx + */ + (void) ppfd; + + return DrvSetPixelFormat( hdc, iPixelFormat ); +} + + +WINGDIAPI BOOL APIENTRY +wglUseFontBitmapsA( + HDC hdc, + DWORD first, + DWORD count, + DWORD listBase ) +{ + return wglUseFontBitmapsW(hdc, first, count, listBase); +} + +WINGDIAPI BOOL APIENTRY +wglShareLists( + HGLRC hglrc1, + HGLRC hglrc2 ) +{ + return DrvShareLists((DHGLRC)(UINT_PTR)hglrc1, + (DHGLRC)(UINT_PTR)hglrc2); +} + +WINGDIAPI BOOL APIENTRY +wglUseFontBitmapsW( + HDC hdc, + DWORD first, + DWORD count, + DWORD listBase ) +{ + GLYPHMETRICS gm; + MAT2 tra; + FIXED one, minus_one, zero; + void *buffer = NULL; + BOOL result = TRUE; + + one.value = 1; + one.fract = 0; + minus_one.value = -1; + minus_one.fract = 0; + zero.value = 0; + zero.fract = 0; + + tra.eM11 = one; + tra.eM22 = minus_one; + tra.eM12 = tra.eM21 = zero; + + for (int i = 0; i < count; i++) { + DWORD size = GetGlyphOutline(hdc, first + i, GGO_BITMAP, &gm, 0, + NULL, &tra); + + glNewList(listBase + i, GL_COMPILE); + + if (size != GDI_ERROR) { + if (size == 0) { + glBitmap(0, 0, (GLfloat)-gm.gmptGlyphOrigin.x, + (GLfloat)gm.gmptGlyphOrigin.y, + (GLfloat)gm.gmCellIncX, + (GLfloat)gm.gmCellIncY, NULL); + } + else { + buffer = realloc(buffer, size); + size = GetGlyphOutline(hdc, first + i, GGO_BITMAP, &gm, + size, buffer, &tra); + + glBitmap(gm.gmBlackBoxX, gm.gmBlackBoxY, + -gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y, + gm.gmCellIncX, gm.gmCellIncY, buffer); + } + } + else { + result = FALSE; + } + + glEndList(); + } + + free(buffer); + + return result; +} + +WINGDIAPI BOOL APIENTRY +wglUseFontOutlinesA( + HDC hdc, + DWORD first, + DWORD count, + DWORD listBase, + FLOAT deviation, + FLOAT extrusion, + int format, + LPGLYPHMETRICSFLOAT lpgmf ) +{ + (void) hdc; + (void) first; + (void) count; + (void) listBase; + (void) deviation; + (void) extrusion; + (void) format; + (void) lpgmf; + + assert( 0 ); + + return FALSE; +} + +WINGDIAPI BOOL APIENTRY +wglUseFontOutlinesW( + HDC hdc, + DWORD first, + DWORD count, + DWORD listBase, + FLOAT deviation, + FLOAT extrusion, + int format, + LPGLYPHMETRICSFLOAT lpgmf ) +{ + (void) hdc; + (void) first; + (void) count; + (void) listBase; + (void) deviation; + (void) extrusion; + (void) format; + (void) lpgmf; + + assert( 0 ); + + return FALSE; +} + +WINGDIAPI BOOL APIENTRY +wglDescribeLayerPlane( + HDC hdc, + int iPixelFormat, + int iLayerPlane, + UINT nBytes, + LPLAYERPLANEDESCRIPTOR plpd ) +{ + return DrvDescribeLayerPlane(hdc, iPixelFormat, iLayerPlane, nBytes, plpd); +} + +WINGDIAPI int APIENTRY +wglSetLayerPaletteEntries( + HDC hdc, + int iLayerPlane, + int iStart, + int cEntries, + CONST COLORREF *pcr ) +{ + return DrvSetLayerPaletteEntries(hdc, iLayerPlane, iStart, cEntries, pcr); +} + +WINGDIAPI int APIENTRY +wglGetLayerPaletteEntries( + HDC hdc, + int iLayerPlane, + int iStart, + int cEntries, + COLORREF *pcr ) +{ + return DrvGetLayerPaletteEntries(hdc, iLayerPlane, iStart, cEntries, pcr); +} + +WINGDIAPI BOOL APIENTRY +wglRealizeLayerPalette( + HDC hdc, + int iLayerPlane, + BOOL bRealize ) +{ + (void) hdc; + (void) iLayerPlane; + (void) bRealize; + + assert( 0 ); + + return FALSE; +} + + +/* When this library is used as a opengl32.dll drop-in replacement, ensure we + * use the wglCreate/Destroy entrypoints above, and not the true opengl32.dll, + * which could happen if this library's name is not opengl32.dll exactly. + * + * For example, Qt 5.4 bundles this as opengl32sw.dll: + * https://blog.qt.io/blog/2014/11/27/qt-weekly-21-dynamic-opengl-implementation-loading-in-qt-5-4/ + */ +static void +overrideOpenGL32EntryPoints(void) +{ + wglCreateContext_func = &wglCreateContext; + wglDeleteContext_func = &wglDeleteContext; +} diff --git a/src/gallium/frontends/wgl/stw_wgl.h b/src/gallium/frontends/wgl/stw_wgl.h new file mode 100644 index 00000000000..92d70b5da9e --- /dev/null +++ b/src/gallium/frontends/wgl/stw_wgl.h @@ -0,0 +1,89 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef STW_WGL_H_ +#define STW_WGL_H_ + + +#include + +#include + + +/* + * Undeclared APIs exported by opengl32.dll + */ + +WINGDIAPI BOOL WINAPI +wglSwapBuffers(HDC hdc); + +WINGDIAPI int WINAPI +wglChoosePixelFormat(HDC hdc, + CONST PIXELFORMATDESCRIPTOR *ppfd); + +WINGDIAPI int WINAPI +wglDescribePixelFormat(HDC hdc, + int iPixelFormat, + UINT nBytes, + LPPIXELFORMATDESCRIPTOR ppfd); + +WINGDIAPI int WINAPI +wglGetPixelFormat(HDC hdc); + +WINGDIAPI BOOL WINAPI +wglSetPixelFormat(HDC hdc, + int iPixelFormat, + CONST PIXELFORMATDESCRIPTOR *ppfd); + +WINGDIAPI HDC APIENTRY +wglGetCurrentReadDCARB( VOID ); + +WINGDIAPI BOOL APIENTRY +wglMakeContextCurrentARB( + HDC hDrawDC, + HDC hReadDC, + HGLRC hglrc ); + + +#ifndef WGL_SWAPMULTIPLE_MAX + +typedef struct _WGLSWAP +{ + HDC hdc; + UINT uiFlags; +} WGLSWAP; + +#define WGL_SWAPMULTIPLE_MAX 16 + +WINGDIAPI DWORD WINAPI +wglSwapMultipleBuffers(UINT n, + CONST WGLSWAP *ps); + +#endif /* !WGL_SWAPMULTIPLE_MAX */ + + +#endif /* STW_WGL_H_ */ diff --git a/src/gallium/frontends/wgl/stw_winsys.h b/src/gallium/frontends/wgl/stw_winsys.h new file mode 100644 index 00000000000..281b201bc22 --- /dev/null +++ b/src/gallium/frontends/wgl/stw_winsys.h @@ -0,0 +1,107 @@ +/************************************************************************** + * + * Copyright 2008-2009 Vmware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef STW_WINSYS_H +#define STW_WINSYS_H + +#include /* for HDC */ + +#include "pipe/p_compiler.h" + +struct pipe_screen; +struct pipe_context; +struct pipe_resource; + +struct stw_shared_surface; + +struct stw_winsys +{ + struct pipe_screen * + (*create_screen)( void ); + + /* XXX is it actually possible to have non-zero level/layer ??? */ + /** + * Present the color buffer to the window associated with the device context. + */ + void + (*present)( struct pipe_screen *screen, + struct pipe_resource *res, + HDC hDC ); + + /** + * Locally unique identifier (LUID) of the graphics adapter. + * + * @sa GLCBPRESENTBUFFERSDATA::AdapterLuid; + */ + boolean + (*get_adapter_luid)( struct pipe_screen *screen, + LUID *pAdapterLuid ); + + /** + * Open a shared surface (optional). + * + * @sa GLCBPRESENTBUFFERSDATA::hSharedSurface; + */ + struct stw_shared_surface * + (*shared_surface_open)(struct pipe_screen *screen, + HANDLE hSharedSurface); + + /** + * Close a shared surface (optional). + */ + void + (*shared_surface_close)(struct pipe_screen *screen, + struct stw_shared_surface *surface); + + /** + * Compose into a shared surface (optional). + * + * Blit the color buffer into a shared surface. + * + * @sa GLPRESENTBUFFERSDATA::PresentHistoryToken. + */ + void + (*compose)( struct pipe_screen *screen, + struct pipe_resource *res, + struct stw_shared_surface *dest, + LPCRECT pRect, + ULONGLONG PresentHistoryToken ); +}; + +boolean +stw_init(const struct stw_winsys *stw_winsys); + +boolean +stw_init_thread(void); + +void +stw_cleanup_thread(void); + +void +stw_cleanup(void); + +#endif /* STW_WINSYS_H */ diff --git a/src/gallium/frontends/xa/.editorconfig b/src/gallium/frontends/xa/.editorconfig new file mode 100644 index 00000000000..7b12a40ca00 --- /dev/null +++ b/src/gallium/frontends/xa/.editorconfig @@ -0,0 +1,3 @@ +[*.{c,h}] +indent_style = space +indent_size = 4 diff --git a/src/gallium/frontends/xa/Makefile.sources b/src/gallium/frontends/xa/Makefile.sources new file mode 100644 index 00000000000..cdcc4187ac1 --- /dev/null +++ b/src/gallium/frontends/xa/Makefile.sources @@ -0,0 +1,8 @@ +C_SOURCES := \ + xa_composite.c \ + xa_context.c \ + xa_priv.h \ + xa_renderer.c \ + xa_tgsi.c \ + xa_tracker.c \ + xa_yuv.c diff --git a/src/gallium/frontends/xa/README b/src/gallium/frontends/xa/README new file mode 100644 index 00000000000..1f08861588c --- /dev/null +++ b/src/gallium/frontends/xa/README @@ -0,0 +1,72 @@ +/********************************************************** + * Copyright 2009-2011 VMware, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + ********************************************************* + * Authors: + * Zack Rusin + * Thomas Hellstrom + */ + +The XA state tracker is intended as a versioned interface to gallium for +xorg driver writers. Initially it's mostly based on Zack Rusin's +composite / video work for the Xorg state tracker. + +The motivation behind this state tracker is that the Xorg state tracker has +a number of interfaces to work with: + +1) The Xorg sdk (versioned) +2) Gallium3D (not versioned) +3) KMS modesetting (versioned) +4) Driver-private (hopefully versioned) + +Since Gallium3D is not versioned, the Xorg state tracker needs to be compiled +with Gallium, but it's really beneficial to be able to compile xorg drivers +standalone. + +Therefore the xa state tracker is intended to supply the following +functionality: + +1) Versioning. +2) Surface functionality (creation and copying for a basic dri2 implementation) +3) YUV blits for textured Xv. +4) Solid fills without ROP functionality. +5) Copies with format conversion and - reinterpretation but without ROP +6) Xrender- type compositing for general acceleration. + + +The first user will be the vmwgfx xorg driver. When there are more users, +we need to be able to load the appropriate gallium pipe driver, and we +should investigate sharing the loadig mechanism with the EGL state tracker. + +IMPORTANT: +Version compatibilities: +While this library remains OUTSIDE any mesa release branch, +and the major version number is still 0. Any minor bump should be viewed as +an incompatibility event, and any user of this library should test for that +and refuse to use the library if minor versions differ. +As soon as the library enters a mesa release branch, if not earlier, major +will be bumped to 1, and normal incompatibility rules (major bump) +will be followed. +It is allowed to add function interfaces while only bumping minor. Any +user that uses these function interfaces must therefore use lazy symbol +lookups and test minor for compatibility before using such a function. diff --git a/src/gallium/frontends/xa/meson.build b/src/gallium/frontends/xa/meson.build new file mode 100644 index 00000000000..0c3540f0359 --- /dev/null +++ b/src/gallium/frontends/xa/meson.build @@ -0,0 +1,45 @@ +# Copyright © 2017 Intel Corporation + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +xa_version = ['2', '5', '0'] + +xa_conf = configuration_data() +xa_conf.set('XA_MAJOR', xa_version[0]) +xa_conf.set('XA_MINOR', xa_version[1]) +xa_conf.set('XA_PATCH', xa_version[2]) + +xa_tracker_h = configure_file( + configuration : xa_conf, + input : 'xa_tracker.h.in', + output : 'xa_tracker.h', + install_dir : get_option('includedir'), +) + +libxa_st = static_library( + 'xa_st', + [xa_tracker_h, files( + 'xa_composite.c', 'xa_context.c', 'xa_renderer.c', 'xa_tgsi.c', + 'xa_tracker.c', 'xa_yuv.c', + )], + c_args : [c_vis_args, '-pedantic'], + include_directories : [inc_include, inc_src, inc_mapi, inc_mesa, inc_gallium, inc_gallium_aux], +) + +install_headers('xa_composite.h', 'xa_context.h') diff --git a/src/gallium/frontends/xa/xa-indent.sh b/src/gallium/frontends/xa/xa-indent.sh new file mode 100755 index 00000000000..90241a3772e --- /dev/null +++ b/src/gallium/frontends/xa/xa-indent.sh @@ -0,0 +1,3 @@ +#!/bin/sh +indent --linux-style -i4 -ip4 -bad -bap -psl $* + diff --git a/src/gallium/frontends/xa/xa_composite.c b/src/gallium/frontends/xa/xa_composite.c new file mode 100644 index 00000000000..34d78027e27 --- /dev/null +++ b/src/gallium/frontends/xa/xa_composite.c @@ -0,0 +1,592 @@ +/********************************************************** + * Copyright 2009-2011 VMware, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + ********************************************************* + * Authors: + * Zack Rusin + * Thomas Hellstrom + */ + +#include "xa_composite.h" +#include "xa_context.h" +#include "xa_priv.h" +#include "cso_cache/cso_context.h" +#include "util/u_sampler.h" +#include "util/u_inlines.h" + + +/*XXX also in Xrender.h but the including it here breaks compilition */ +#define XFixedToDouble(f) (((double) (f)) / 65536.) + +struct xa_composite_blend { + unsigned op : 8; + + unsigned alpha_dst : 4; + unsigned alpha_src : 4; + + unsigned rgb_src : 8; /**< PIPE_BLENDFACTOR_x */ + unsigned rgb_dst : 8; /**< PIPE_BLENDFACTOR_x */ +}; + +#define XA_BLEND_OP_OVER 3 +static const struct xa_composite_blend xa_blends[] = { + { xa_op_clear, + 0, 0, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO}, + { xa_op_src, + 0, 0, PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ZERO}, + { xa_op_dst, + 0, 0, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ONE}, + { xa_op_over, + 0, 1, PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_INV_SRC_ALPHA}, + { xa_op_over_reverse, + 1, 0, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_ONE}, + { xa_op_in, + 1, 0, PIPE_BLENDFACTOR_DST_ALPHA, PIPE_BLENDFACTOR_ZERO}, + { xa_op_in_reverse, + 0, 1, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_SRC_ALPHA}, + { xa_op_out, + 1, 0, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_ZERO}, + { xa_op_out_reverse, + 0, 1, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_INV_SRC_ALPHA}, + { xa_op_atop, + 1, 1, PIPE_BLENDFACTOR_DST_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA}, + { xa_op_atop_reverse, + 1, 1, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_SRC_ALPHA}, + { xa_op_xor, + 1, 1, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA}, + { xa_op_add, + 0, 0, PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ONE}, +}; + +/* + * The alpha value stored in a L8 texture is read by the + * hardware as color, and R8 is read as red. The source alpha value + * at the end of the fragment shader is stored in all color channels, + * so the correct approach is to blend using DST_COLOR instead of + * DST_ALPHA and then output any color channel (L8) or the red channel (R8). + */ +static unsigned +xa_convert_blend_for_luminance(unsigned factor) +{ + switch(factor) { + case PIPE_BLENDFACTOR_DST_ALPHA: + return PIPE_BLENDFACTOR_DST_COLOR; + case PIPE_BLENDFACTOR_INV_DST_ALPHA: + return PIPE_BLENDFACTOR_INV_DST_COLOR; + default: + break; + } + return factor; +} + +static boolean +blend_for_op(struct xa_composite_blend *blend, + enum xa_composite_op op, + struct xa_picture *src_pic, + struct xa_picture *mask_pic, + struct xa_picture *dst_pic) +{ + const int num_blends = + sizeof(xa_blends)/sizeof(struct xa_composite_blend); + int i; + boolean supported = FALSE; + + /* + * our default in case something goes wrong + */ + *blend = xa_blends[XA_BLEND_OP_OVER]; + + for (i = 0; i < num_blends; ++i) { + if (xa_blends[i].op == op) { + *blend = xa_blends[i]; + supported = TRUE; + break; + } + } + + /* + * No component alpha yet. + */ + if (mask_pic && mask_pic->component_alpha && blend->alpha_src) + return FALSE; + + if (!dst_pic->srf) + return supported; + + if ((dst_pic->srf->tex->format == PIPE_FORMAT_L8_UNORM || + dst_pic->srf->tex->format == PIPE_FORMAT_R8_UNORM)) { + blend->rgb_src = xa_convert_blend_for_luminance(blend->rgb_src); + blend->rgb_dst = xa_convert_blend_for_luminance(blend->rgb_dst); + } + + /* + * If there's no dst alpha channel, adjust the blend op so that we'll treat + * it as always 1. + */ + + if (xa_format_a(dst_pic->pict_format) == 0 && blend->alpha_dst) { + if (blend->rgb_src == PIPE_BLENDFACTOR_DST_ALPHA) + blend->rgb_src = PIPE_BLENDFACTOR_ONE; + else if (blend->rgb_src == PIPE_BLENDFACTOR_INV_DST_ALPHA) + blend->rgb_src = PIPE_BLENDFACTOR_ZERO; + } + + return supported; +} + + +static inline int +xa_repeat_to_gallium(int mode) +{ + switch(mode) { + case xa_wrap_clamp_to_border: + return PIPE_TEX_WRAP_CLAMP_TO_BORDER; + case xa_wrap_repeat: + return PIPE_TEX_WRAP_REPEAT; + case xa_wrap_mirror_repeat: + return PIPE_TEX_WRAP_MIRROR_REPEAT; + case xa_wrap_clamp_to_edge: + return PIPE_TEX_WRAP_CLAMP_TO_EDGE; + default: + break; + } + return PIPE_TEX_WRAP_REPEAT; +} + +static inline boolean +xa_filter_to_gallium(int xrender_filter, int *out_filter) +{ + + switch (xrender_filter) { + case xa_filter_nearest: + *out_filter = PIPE_TEX_FILTER_NEAREST; + break; + case xa_filter_linear: + *out_filter = PIPE_TEX_FILTER_LINEAR; + break; + default: + *out_filter = PIPE_TEX_FILTER_NEAREST; + return FALSE; + } + return TRUE; +} + +static int +xa_is_filter_accelerated(struct xa_picture *pic) +{ + int filter; + if (pic && !xa_filter_to_gallium(pic->filter, &filter)) + return 0; + return 1; +} + +/** + * xa_src_pict_is_accelerated - Check whether we support acceleration + * of the given src_pict type + * + * \param src_pic[in]: Pointer to a union xa_source_pict to check. + * + * \returns TRUE if accelerated, FALSE otherwise. + */ +static boolean +xa_src_pict_is_accelerated(const union xa_source_pict *src_pic) +{ + if (!src_pic) + return TRUE; + + if (src_pic->type == xa_src_pict_solid_fill || + src_pic->type == xa_src_pict_float_solid_fill) + return TRUE; + + return FALSE; +} + +XA_EXPORT int +xa_composite_check_accelerated(const struct xa_composite *comp) +{ + struct xa_picture *src_pic = comp->src; + struct xa_picture *mask_pic = comp->mask; + struct xa_composite_blend blend; + + if (!xa_is_filter_accelerated(src_pic) || + !xa_is_filter_accelerated(comp->mask)) { + return -XA_ERR_INVAL; + } + + if (!xa_src_pict_is_accelerated(src_pic->src_pict) || + (mask_pic && !xa_src_pict_is_accelerated(mask_pic->src_pict))) + return -XA_ERR_INVAL; + + if (!blend_for_op(&blend, comp->op, comp->src, comp->mask, comp->dst)) + return -XA_ERR_INVAL; + + /* + * No component alpha yet. + */ + if (mask_pic && mask_pic->component_alpha && blend.alpha_src) + return -XA_ERR_INVAL; + + return XA_ERR_NONE; +} + +static int +bind_composite_blend_state(struct xa_context *ctx, + const struct xa_composite *comp) +{ + struct xa_composite_blend blend_opt; + struct pipe_blend_state blend; + + if (!blend_for_op(&blend_opt, comp->op, comp->src, comp->mask, comp->dst)) + return -XA_ERR_INVAL; + + memset(&blend, 0, sizeof(struct pipe_blend_state)); + blend.rt[0].blend_enable = 1; + blend.rt[0].colormask = PIPE_MASK_RGBA; + + blend.rt[0].rgb_src_factor = blend_opt.rgb_src; + blend.rt[0].alpha_src_factor = blend_opt.rgb_src; + blend.rt[0].rgb_dst_factor = blend_opt.rgb_dst; + blend.rt[0].alpha_dst_factor = blend_opt.rgb_dst; + + cso_set_blend(ctx->cso, &blend); + return XA_ERR_NONE; +} + +static unsigned int +picture_format_fixups(struct xa_picture *src_pic, + int mask) +{ + boolean set_alpha = FALSE; + boolean swizzle = FALSE; + unsigned ret = 0; + struct xa_surface *src = src_pic->srf; + enum xa_formats src_hw_format, src_pic_format; + enum xa_surface_type src_hw_type, src_pic_type; + + if (!src) + return 0; + + src_hw_format = xa_surface_format(src); + src_pic_format = src_pic->pict_format; + + set_alpha = (xa_format_type_is_color(src_hw_format) && + xa_format_a(src_pic_format) == 0); + + if (set_alpha) + ret |= mask ? FS_MASK_SET_ALPHA : FS_SRC_SET_ALPHA; + + if (src_hw_format == src_pic_format) { + if (src->tex->format == PIPE_FORMAT_L8_UNORM || + src->tex->format == PIPE_FORMAT_R8_UNORM) + return ((mask) ? FS_MASK_LUMINANCE : FS_SRC_LUMINANCE); + + return ret; + } + + src_hw_type = xa_format_type(src_hw_format); + src_pic_type = xa_format_type(src_pic_format); + + swizzle = ((src_hw_type == xa_type_argb && + src_pic_type == xa_type_abgr) || + ((src_hw_type == xa_type_abgr && + src_pic_type == xa_type_argb))); + + if (!swizzle && (src_hw_type != src_pic_type)) + return ret; + + if (swizzle) + ret |= mask ? FS_MASK_SWIZZLE_RGB : FS_SRC_SWIZZLE_RGB; + + return ret; +} + +static void +xa_src_in_mask(float src[4], const float mask[4]) +{ + src[0] *= mask[3]; + src[1] *= mask[3]; + src[2] *= mask[3]; + src[3] *= mask[3]; +} + +/** + * xa_handle_src_pict - Set up xa_context state and fragment shader + * input based on scr_pict type + * + * \param ctx[in, out]: Pointer to the xa context. + * \param src_pict[in]: Pointer to the union xa_source_pict to consider. + * \param is_mask[in]: Whether we're considering a mask picture. + * + * \returns TRUE if succesful, FALSE otherwise. + * + * This function computes some xa_context state used to determine whether + * to upload the solid color and also the solid color itself used as an input + * to the fragment shader. + */ +static boolean +xa_handle_src_pict(struct xa_context *ctx, + const union xa_source_pict *src_pict, + boolean is_mask) +{ + float solid_color[4]; + + switch(src_pict->type) { + case xa_src_pict_solid_fill: + xa_pixel_to_float4(src_pict->solid_fill.color, solid_color); + break; + case xa_src_pict_float_solid_fill: + memcpy(solid_color, src_pict->float_solid_fill.color, + sizeof(solid_color)); + break; + default: + return FALSE; + } + + if (is_mask && ctx->has_solid_src) + xa_src_in_mask(ctx->solid_color, solid_color); + else + memcpy(ctx->solid_color, solid_color, sizeof(solid_color)); + + if (is_mask) + ctx->has_solid_mask = TRUE; + else + ctx->has_solid_src = TRUE; + + return TRUE; +} + +static int +bind_shaders(struct xa_context *ctx, const struct xa_composite *comp) +{ + unsigned vs_traits = 0, fs_traits = 0; + struct xa_shader shader; + struct xa_picture *src_pic = comp->src; + struct xa_picture *mask_pic = comp->mask; + struct xa_picture *dst_pic = comp->dst; + + ctx->has_solid_src = FALSE; + ctx->has_solid_mask = FALSE; + + if (dst_pic && xa_format_type(dst_pic->pict_format) != + xa_format_type(xa_surface_format(dst_pic->srf))) + return -XA_ERR_INVAL; + + if (src_pic) { + if (src_pic->wrap == xa_wrap_clamp_to_border && src_pic->has_transform) + fs_traits |= FS_SRC_REPEAT_NONE; + + fs_traits |= FS_COMPOSITE; + vs_traits |= VS_COMPOSITE; + + if (src_pic->src_pict) { + if (!xa_handle_src_pict(ctx, src_pic->src_pict, false)) + return -XA_ERR_INVAL; + fs_traits |= FS_SRC_SRC; + vs_traits |= VS_SRC_SRC; + } else + fs_traits |= picture_format_fixups(src_pic, 0); + } + + if (mask_pic) { + vs_traits |= VS_MASK; + fs_traits |= FS_MASK; + if (mask_pic->component_alpha) + fs_traits |= FS_CA; + if (mask_pic->src_pict) { + if (!xa_handle_src_pict(ctx, mask_pic->src_pict, true)) + return -XA_ERR_INVAL; + + if (ctx->has_solid_src) { + vs_traits &= ~VS_MASK; + fs_traits &= ~FS_MASK; + } else { + vs_traits |= VS_MASK_SRC; + fs_traits |= FS_MASK_SRC; + } + } else { + if (mask_pic->wrap == xa_wrap_clamp_to_border && + mask_pic->has_transform) + fs_traits |= FS_MASK_REPEAT_NONE; + + fs_traits |= picture_format_fixups(mask_pic, 1); + } + } + + if (ctx->srf->format == PIPE_FORMAT_L8_UNORM || + ctx->srf->format == PIPE_FORMAT_R8_UNORM) + fs_traits |= FS_DST_LUMINANCE; + + shader = xa_shaders_get(ctx->shaders, vs_traits, fs_traits); + cso_set_vertex_shader_handle(ctx->cso, shader.vs); + cso_set_fragment_shader_handle(ctx->cso, shader.fs); + return XA_ERR_NONE; +} + +static void +bind_samplers(struct xa_context *ctx, + const struct xa_composite *comp) +{ + struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; + struct pipe_sampler_state src_sampler, mask_sampler; + struct pipe_sampler_view view_templ; + struct pipe_sampler_view *src_view; + struct pipe_context *pipe = ctx->pipe; + struct xa_picture *src_pic = comp->src; + struct xa_picture *mask_pic = comp->mask; + int num_samplers = 0; + + xa_ctx_sampler_views_destroy(ctx); + memset(&src_sampler, 0, sizeof(struct pipe_sampler_state)); + memset(&mask_sampler, 0, sizeof(struct pipe_sampler_state)); + + if (src_pic && !ctx->has_solid_src) { + unsigned src_wrap = xa_repeat_to_gallium(src_pic->wrap); + int filter; + + (void) xa_filter_to_gallium(src_pic->filter, &filter); + + src_sampler.wrap_s = src_wrap; + src_sampler.wrap_t = src_wrap; + src_sampler.min_img_filter = filter; + src_sampler.mag_img_filter = filter; + src_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST; + src_sampler.normalized_coords = 1; + samplers[0] = &src_sampler; + u_sampler_view_default_template(&view_templ, + src_pic->srf->tex,+ src_pic->srf->tex->format); + src_view = pipe->create_sampler_view(pipe, src_pic->srf->tex, + &view_templ); + ctx->bound_sampler_views[0] = src_view; + num_samplers++; + } + + if (mask_pic && !ctx->has_solid_mask) { + unsigned mask_wrap = xa_repeat_to_gallium(mask_pic->wrap); + int filter; + + (void) xa_filter_to_gallium(mask_pic->filter, &filter); + + mask_sampler.wrap_s = mask_wrap; + mask_sampler.wrap_t = mask_wrap; + mask_sampler.min_img_filter = filter; + mask_sampler.mag_img_filter = filter; + src_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST; + mask_sampler.normalized_coords = 1; + samplers[num_samplers] = &mask_sampler; + u_sampler_view_default_template(&view_templ, + mask_pic->srf->tex, + mask_pic->srf->tex->format); + src_view = pipe->create_sampler_view(pipe, mask_pic->srf->tex, + &view_templ); + ctx->bound_sampler_views[num_samplers] = src_view; + num_samplers++; + } + + cso_set_samplers(ctx->cso, PIPE_SHADER_FRAGMENT, num_samplers, + (const struct pipe_sampler_state **)samplers); + cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, num_samplers, + ctx->bound_sampler_views); + ctx->num_bound_samplers = num_samplers; +} + +XA_EXPORT int +xa_composite_prepare(struct xa_context *ctx, + const struct xa_composite *comp) +{ + struct xa_surface *dst_srf = comp->dst->srf; + int ret; + + ret = xa_ctx_srf_create(ctx, dst_srf); + if (ret != XA_ERR_NONE) + return ret; + + ctx->dst = dst_srf; + renderer_bind_destination(ctx, ctx->srf); + + ret = bind_composite_blend_state(ctx, comp); + if (ret != XA_ERR_NONE) + return ret; + ret = bind_shaders(ctx, comp); + if (ret != XA_ERR_NONE) + return ret; + bind_samplers(ctx, comp); + + if (ctx->num_bound_samplers == 0 ) { /* solid fill */ + renderer_begin_solid(ctx); + } else { + renderer_begin_textures(ctx); + ctx->comp = comp; + } + + xa_ctx_srf_destroy(ctx); + return XA_ERR_NONE; +} + +XA_EXPORT void +xa_composite_rect(struct xa_context *ctx, + int srcX, int srcY, int maskX, int maskY, + int dstX, int dstY, int width, int height) +{ + if (ctx->num_bound_samplers == 0 ) { /* solid fill */ + xa_scissor_update(ctx, dstX, dstY, dstX + width, dstY + height); + renderer_solid(ctx, dstX, dstY, dstX + width, dstY + height); + } else { + const struct xa_composite *comp = ctx->comp; + int pos[6] = {srcX, srcY, maskX, maskY, dstX, dstY}; + const float *src_matrix = NULL; + const float *mask_matrix = NULL; + + xa_scissor_update(ctx, dstX, dstY, dstX + width, dstY + height); + + if (comp->src->has_transform) + src_matrix = comp->src->transform; + if (comp->mask && comp->mask->has_transform) + mask_matrix = comp->mask->transform; + + renderer_texture(ctx, pos, width, height, + src_matrix, mask_matrix); + } +} + +XA_EXPORT void +xa_composite_done(struct xa_context *ctx) +{ + renderer_draw_flush(ctx); + + ctx->comp = NULL; + ctx->has_solid_src = FALSE; + ctx->has_solid_mask = FALSE; + xa_ctx_sampler_views_destroy(ctx); +} + +static const struct xa_composite_allocation a = { + .xa_composite_size = sizeof(struct xa_composite), + .xa_picture_size = sizeof(struct xa_picture), + .xa_source_pict_size = sizeof(union xa_source_pict), +}; + +XA_EXPORT const struct xa_composite_allocation * +xa_composite_allocation(void) +{ + return &a; +} diff --git a/src/gallium/frontends/xa/xa_composite.h b/src/gallium/frontends/xa/xa_composite.h new file mode 100644 index 00000000000..7e3737a63d2 --- /dev/null +++ b/src/gallium/frontends/xa/xa_composite.h @@ -0,0 +1,156 @@ +/********************************************************** + * Copyright 2009-2011 VMware, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + ********************************************************* + * Authors: + * Zack Rusin + * Thomas Hellstrom + */ + +#ifndef _XA_COMPOSITE_H_ +#define _XA_COMPOSITE_H_ + +#include "xa_tracker.h" +#include "xa_context.h" + +/* + * Supported composite ops. + */ +enum xa_composite_op { + xa_op_clear, + xa_op_src, + xa_op_dst, + xa_op_over, + xa_op_over_reverse, + xa_op_in, + xa_op_in_reverse, + xa_op_out, + xa_op_out_reverse, + xa_op_atop, + xa_op_atop_reverse, + xa_op_xor, + xa_op_add +}; + +/* + * Supported filters. + */ +enum xa_composite_filter { + xa_filter_nearest, + xa_filter_linear +}; + +/* + * Supported clamp methods. + */ +enum xa_composite_wrap { + xa_wrap_clamp_to_border, + xa_wrap_repeat, + xa_wrap_mirror_repeat, + xa_wrap_clamp_to_edge +}; + +/* + * Src picture types. + */ +enum xa_composite_src_pict_type { + xa_src_pict_solid_fill, + xa_src_pict_float_solid_fill +}; + + +/* + * struct xa_pict_solid_fill - Description of a solid_fill picture + * Deprecated. Use struct xa_pict_float_solid_fill instead. + */ +struct xa_pict_solid_fill { + enum xa_composite_src_pict_type type; + unsigned int class; + uint32_t color; +}; + +/* + * struct xa_pict_solid_fill - Description of a solid_fill picture + * with color channels represented by floats. + */ +struct xa_pict_float_solid_fill { + enum xa_composite_src_pict_type type; + float color[4]; /* R, G, B, A */ +}; + +union xa_source_pict { + enum xa_composite_src_pict_type type; + struct xa_pict_solid_fill solid_fill; + struct xa_pict_float_solid_fill float_solid_fill; +}; + +struct xa_picture { + enum xa_formats pict_format; + struct xa_surface *srf; + struct xa_surface *alpha_map; + float transform[9]; + int has_transform; + int component_alpha; + enum xa_composite_wrap wrap; + enum xa_composite_filter filter; + union xa_source_pict *src_pict; +}; + +struct xa_composite { + struct xa_picture *src, *mask, *dst; + int op; + int no_solid; +}; + +struct xa_composite_allocation { + unsigned int xa_composite_size; + unsigned int xa_picture_size; + unsigned int xa_source_pict_size; +}; + +/* + * Get allocation sizes for minor bump compatibility. + */ + +extern const struct xa_composite_allocation * +xa_composite_allocation(void); + +/* + * This function checks most things except the format of the hardware + * surfaces, since they are generally not available at the time this + * function is called. Returns usual XA error codes. + */ +extern int +xa_composite_check_accelerated(const struct xa_composite *comp); + +extern int +xa_composite_prepare(struct xa_context *ctx, const struct xa_composite *comp); + +extern void +xa_composite_rect(struct xa_context *ctx, + int srcX, int srcY, int maskX, int maskY, + int dstX, int dstY, int width, int height); +extern void +xa_composite_done(struct xa_context *ctx); + +#endif diff --git a/src/gallium/frontends/xa/xa_context.c b/src/gallium/frontends/xa/xa_context.c new file mode 100644 index 00000000000..a4630cf09ca --- /dev/null +++ b/src/gallium/frontends/xa/xa_context.c @@ -0,0 +1,419 @@ +/********************************************************** + * Copyright 2009-2011 VMware, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + ********************************************************* + * Authors: + * Zack Rusin + * Thomas Hellstrom + */ +#include "xa_context.h" +#include "xa_priv.h" +#include "cso_cache/cso_context.h" +#include "util/u_inlines.h" +#include "util/u_rect.h" +#include "util/u_surface.h" +#include "pipe/p_context.h" + +XA_EXPORT void +xa_context_flush(struct xa_context *ctx) +{ + if (ctx->last_fence) { + struct pipe_screen *screen = ctx->xa->screen; + screen->fence_reference(screen, &ctx->last_fence, NULL); + } + ctx->pipe->flush(ctx->pipe, &ctx->last_fence, 0); +} + +XA_EXPORT struct xa_context * +xa_context_default(struct xa_tracker *xa) +{ + return xa->default_ctx; +} + +XA_EXPORT struct xa_context * +xa_context_create(struct xa_tracker *xa) +{ + struct xa_context *ctx = calloc(1, sizeof(*ctx)); + + ctx->xa = xa; + ctx->pipe = xa->screen->context_create(xa->screen, NULL, 0); + ctx->cso = cso_create_context(ctx->pipe, 0); + ctx->shaders = xa_shaders_create(ctx); + renderer_init_state(ctx); + + return ctx; +} + +XA_EXPORT void +xa_context_destroy(struct xa_context *r) +{ + struct pipe_resource **vsbuf = &r->vs_const_buffer; + struct pipe_resource **fsbuf = &r->fs_const_buffer; + + if (*vsbuf) + pipe_resource_reference(vsbuf, NULL); + + if (*fsbuf) + pipe_resource_reference(fsbuf, NULL); + + if (r->shaders) { + xa_shaders_destroy(r->shaders); + r->shaders = NULL; + } + + xa_ctx_sampler_views_destroy(r); + if (r->srf) + pipe_surface_reference(&r->srf, NULL); + + if (r->cso) { + cso_destroy_context(r->cso); + r->cso = NULL; + } + + r->pipe->destroy(r->pipe); + free(r); +} + +XA_EXPORT int +xa_surface_dma(struct xa_context *ctx, + struct xa_surface *srf, + void *data, + unsigned int pitch, + int to_surface, struct xa_box *boxes, unsigned int num_boxes) +{ + struct pipe_transfer *transfer; + void *map; + int w, h, i; + enum pipe_transfer_usage transfer_direction; + struct pipe_context *pipe = ctx->pipe; + + transfer_direction = (to_surface ? PIPE_TRANSFER_WRITE : + PIPE_TRANSFER_READ); + + for (i = 0; i < num_boxes; ++i, ++boxes) { + w = boxes->x2 - boxes->x1; + h = boxes->y2 - boxes->y1; + + map = pipe_transfer_map(pipe, srf->tex, 0, 0, + transfer_direction, boxes->x1, boxes->y1, + w, h, &transfer); + if (!map) + return -XA_ERR_NORES; + + if (to_surface) { + util_copy_rect(map, srf->tex->format, transfer->stride, + 0, 0, w, h, data, pitch, boxes->x1, boxes->y1); + } else { + util_copy_rect(data, srf->tex->format, pitch, + boxes->x1, boxes->y1, w, h, map, transfer->stride, 0, + 0); + } + pipe->transfer_unmap(pipe, transfer); + } + return XA_ERR_NONE; +} + +XA_EXPORT void * +xa_surface_map(struct xa_context *ctx, + struct xa_surface *srf, unsigned int usage) +{ + void *map; + unsigned int gallium_usage = 0; + struct pipe_context *pipe = ctx->pipe; + + /* + * A surface may only have a single map. + */ + if (srf->transfer) + return NULL; + + if (usage & XA_MAP_READ) + gallium_usage |= PIPE_TRANSFER_READ; + if (usage & XA_MAP_WRITE) + gallium_usage |= PIPE_TRANSFER_WRITE; + if (usage & XA_MAP_MAP_DIRECTLY) + gallium_usage |= PIPE_TRANSFER_MAP_DIRECTLY; + if (usage & XA_MAP_UNSYNCHRONIZED) + gallium_usage |= PIPE_TRANSFER_UNSYNCHRONIZED; + if (usage & XA_MAP_DONTBLOCK) + gallium_usage |= PIPE_TRANSFER_DONTBLOCK; + if (usage & XA_MAP_DISCARD_WHOLE_RESOURCE) + gallium_usage |= PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE; + + if (!(gallium_usage & (PIPE_TRANSFER_READ_WRITE))) + return NULL; + + map = pipe_transfer_map(pipe, srf->tex, 0, 0, + gallium_usage, 0, 0, + srf->tex->width0, srf->tex->height0, + &srf->transfer); + if (!map) + return NULL; + + srf->mapping_pipe = pipe; + return map; +} + +XA_EXPORT void +xa_surface_unmap(struct xa_surface *srf) +{ + if (srf->transfer) { + struct pipe_context *pipe = srf->mapping_pipe; + + pipe->transfer_unmap(pipe, srf->transfer); + srf->transfer = NULL; + } +} + +int +xa_ctx_srf_create(struct xa_context *ctx, struct xa_surface *dst) +{ + struct pipe_screen *screen = ctx->pipe->screen; + struct pipe_surface srf_templ; + + /* + * Cache surfaces unless we change render target + */ + if (ctx->srf) { + if (ctx->srf->texture == dst->tex) + return XA_ERR_NONE; + + pipe_surface_reference(&ctx->srf, NULL); + } + + if (!screen->is_format_supported(screen, dst->tex->format, + PIPE_TEXTURE_2D, 0, 0, + PIPE_BIND_RENDER_TARGET)) + return -XA_ERR_INVAL; + + u_surface_default_template(&srf_templ, dst->tex); + ctx->srf = ctx->pipe->create_surface(ctx->pipe, dst->tex, &srf_templ); + if (!ctx->srf) + return -XA_ERR_NORES; + + return XA_ERR_NONE; +} + +void +xa_ctx_srf_destroy(struct xa_context *ctx) +{ + /* + * Cache surfaces unless we change render target. + * Final destruction on context destroy. + */ +} + +XA_EXPORT int +xa_copy_prepare(struct xa_context *ctx, + struct xa_surface *dst, struct xa_surface *src) +{ + if (src == dst) + return -XA_ERR_INVAL; + + if (src->tex->format != dst->tex->format) { + int ret = xa_ctx_srf_create(ctx, dst); + if (ret != XA_ERR_NONE) + return ret; + renderer_copy_prepare(ctx, ctx->srf, src->tex, + src->fdesc.xa_format, + dst->fdesc.xa_format); + ctx->simple_copy = 0; + } else + ctx->simple_copy = 1; + + ctx->src = src; + ctx->dst = dst; + xa_ctx_srf_destroy(ctx); + + return 0; +} + +XA_EXPORT void +xa_copy(struct xa_context *ctx, + int dx, int dy, int sx, int sy, int width, int height) +{ + struct pipe_box src_box; + + xa_scissor_update(ctx, dx, dy, dx + width, dy + height); + + if (ctx->simple_copy) { + u_box_2d(sx, sy, width, height, &src_box); + ctx->pipe->resource_copy_region(ctx->pipe, + ctx->dst->tex, 0, dx, dy, 0, + ctx->src->tex, + 0, &src_box); + } else + renderer_copy(ctx, dx, dy, sx, sy, width, height, + (float) ctx->src->tex->width0, + (float) ctx->src->tex->height0); +} + +XA_EXPORT void +xa_copy_done(struct xa_context *ctx) +{ + if (!ctx->simple_copy) { + renderer_draw_flush(ctx); + } +} + +static void +bind_solid_blend_state(struct xa_context *ctx) +{ + struct pipe_blend_state blend; + + memset(&blend, 0, sizeof(struct pipe_blend_state)); + blend.rt[0].blend_enable = 0; + blend.rt[0].colormask = PIPE_MASK_RGBA; + + blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; + + cso_set_blend(ctx->cso, &blend); +} + +XA_EXPORT int +xa_solid_prepare(struct xa_context *ctx, struct xa_surface *dst, + uint32_t fg) +{ + unsigned vs_traits, fs_traits; + struct xa_shader shader; + int ret; + + ret = xa_ctx_srf_create(ctx, dst); + if (ret != XA_ERR_NONE) + return ret; + + if (ctx->srf->format == PIPE_FORMAT_L8_UNORM) + xa_pixel_to_float4_a8(fg, ctx->solid_color); + else + xa_pixel_to_float4(fg, ctx->solid_color); + ctx->has_solid_src = 1; + + ctx->dst = dst; + +#if 0 + debug_printf("Color Pixel=(%d, %d, %d, %d), RGBA=(%f, %f, %f, %f)\n", + (fg >> 24) & 0xff, (fg >> 16) & 0xff, + (fg >> 8) & 0xff, (fg >> 0) & 0xff, + exa->solid_color[0], exa->solid_color[1], + exa->solid_color[2], exa->solid_color[3]); +#endif + + vs_traits = VS_SRC_SRC | VS_COMPOSITE; + fs_traits = FS_SRC_SRC | VS_COMPOSITE; + + renderer_bind_destination(ctx, ctx->srf); + bind_solid_blend_state(ctx); + cso_set_samplers(ctx->cso, PIPE_SHADER_FRAGMENT, 0, NULL); + cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, 0, NULL); + + shader = xa_shaders_get(ctx->shaders, vs_traits, fs_traits); + cso_set_vertex_shader_handle(ctx->cso, shader.vs); + cso_set_fragment_shader_handle(ctx->cso, shader.fs); + + renderer_begin_solid(ctx); + + xa_ctx_srf_destroy(ctx); + return XA_ERR_NONE; +} + +XA_EXPORT void +xa_solid(struct xa_context *ctx, int x, int y, int width, int height) +{ + xa_scissor_update(ctx, x, y, x + width, y + height); + renderer_solid(ctx, x, y, x + width, y + height); +} + +XA_EXPORT void +xa_solid_done(struct xa_context *ctx) +{ + renderer_draw_flush(ctx); + ctx->comp = NULL; + ctx->has_solid_src = FALSE; + ctx->num_bound_samplers = 0; +} + +XA_EXPORT struct xa_fence * +xa_fence_get(struct xa_context *ctx) +{ + struct xa_fence *fence = calloc(1, sizeof(*fence)); + struct pipe_screen *screen = ctx->xa->screen; + + if (!fence) + return NULL; + + fence->xa = ctx->xa; + + if (ctx->last_fence == NULL) + fence->pipe_fence = NULL; + else + screen->fence_reference(screen, &fence->pipe_fence, ctx->last_fence); + + return fence; +} + +XA_EXPORT int +xa_fence_wait(struct xa_fence *fence, uint64_t timeout) +{ + if (!fence) + return XA_ERR_NONE; + + if (fence->pipe_fence) { + struct pipe_screen *screen = fence->xa->screen; + boolean timed_out; + + timed_out = !screen->fence_finish(screen, NULL, fence->pipe_fence, timeout); + if (timed_out) + return -XA_ERR_BUSY; + + screen->fence_reference(screen, &fence->pipe_fence, NULL); + } + return XA_ERR_NONE; +} + +XA_EXPORT void +xa_fence_destroy(struct xa_fence *fence) +{ + if (!fence) + return; + + if (fence->pipe_fence) { + struct pipe_screen *screen = fence->xa->screen; + + screen->fence_reference(screen, &fence->pipe_fence, NULL); + } + + free(fence); +} + +void +xa_ctx_sampler_views_destroy(struct xa_context *ctx) +{ + int i; + + for (i = 0; i < ctx->num_bound_samplers; ++i) + pipe_sampler_view_reference(&ctx->bound_sampler_views[i], NULL); + ctx->num_bound_samplers = 0; +} diff --git a/src/gallium/frontends/xa/xa_context.h b/src/gallium/frontends/xa/xa_context.h new file mode 100644 index 00000000000..202b8e56e23 --- /dev/null +++ b/src/gallium/frontends/xa/xa_context.h @@ -0,0 +1,101 @@ +/********************************************************** + * Copyright 2009-2011 VMware, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + ********************************************************* + * Authors: + * Zack Rusin + * Thomas Hellstrom + */ + +#ifndef _XA_CONTEXT_H_ +#define _XA_CONTEXT_H_ +#include "xa_tracker.h" +#include + +struct xa_context; + +extern struct xa_context *xa_context_default(struct xa_tracker *xa); + +extern struct xa_context *xa_context_create(struct xa_tracker *xa); + +extern void xa_context_destroy(struct xa_context *r); + +extern void xa_context_flush(struct xa_context *ctx); + +/** + * xa_yuv_planar_blit - 2D blit with color conversion and scaling. + * + * Performs a scaled blit with color conversion according to + * (R,G,B,A)^T = (CM)^T (Y,U,V,1)^T, where @conversion_matrix or CM in the + * formula is a four by four coefficient matrix. The input variable + * @yuv is an array of three xa_yuv_component surfaces. + */ +extern int xa_yuv_planar_blit(struct xa_context *r, + int src_x, + int src_y, + int src_w, + int src_h, + int dst_x, + int dst_y, + int dst_w, + int dst_h, + struct xa_box *box, + unsigned int num_boxes, + const float conversion_matrix[], + struct xa_surface *dst, struct xa_surface *yuv[]); + +extern int xa_copy_prepare(struct xa_context *ctx, + struct xa_surface *dst, struct xa_surface *src); + +extern void xa_copy(struct xa_context *ctx, + int dx, int dy, int sx, int sy, int width, int height); + +extern void xa_copy_done(struct xa_context *ctx); + +extern int xa_surface_dma(struct xa_context *ctx, + struct xa_surface *srf, + void *data, + unsigned int byte_pitch, + int to_surface, struct xa_box *boxes, + unsigned int num_boxes); + +extern void *xa_surface_map(struct xa_context *ctx, + struct xa_surface *srf, unsigned int usage); + +extern void xa_surface_unmap(struct xa_surface *srf); + +extern int +xa_solid_prepare(struct xa_context *ctx, struct xa_surface *dst, + uint32_t fg); +extern void +xa_solid(struct xa_context *ctx, int x, int y, int width, int height); + +extern void +xa_solid_done(struct xa_context *ctx); + +extern struct xa_fence *xa_fence_get(struct xa_context *ctx); + +extern int xa_fence_wait(struct xa_fence *fence, uint64_t timeout); + +extern void xa_fence_destroy(struct xa_fence *fence); +#endif diff --git a/src/gallium/frontends/xa/xa_priv.h b/src/gallium/frontends/xa/xa_priv.h new file mode 100644 index 00000000000..f368de3b81f --- /dev/null +++ b/src/gallium/frontends/xa/xa_priv.h @@ -0,0 +1,289 @@ +/********************************************************** + * Copyright 2009-2011 VMware, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + ********************************************************* + * Authors: + * Zack Rusin + * Thomas Hellstrom + */ + +#ifndef _XA_PRIV_H_ +#define _XA_PRIV_H_ + +#include "xa_tracker.h" +#include "xa_context.h" +#include "xa_composite.h" + +#include "pipe/p_screen.h" +#include "pipe/p_context.h" +#include "pipe/p_state.h" + +#include "util/u_math.h" + +#if defined(__GNUC__) +#define XA_EXPORT __attribute__ ((visibility("default"))) +#else +#define XA_EXPORT +#endif + +#define XA_VB_SIZE (100 * 4 * 3 * 4) +#define XA_LAST_SURFACE_TYPE (xa_type_yuv_component + 1) +#define XA_MAX_SAMPLERS 3 + +struct xa_fence { + struct pipe_fence_handle *pipe_fence; + struct xa_tracker *xa; +}; + +struct xa_format_descriptor { + enum pipe_format format; + enum xa_formats xa_format; +}; + +struct xa_surface { + int refcount; + struct pipe_resource template; + struct xa_tracker *xa; + struct pipe_resource *tex; + struct pipe_transfer *transfer; + unsigned int flags; + struct xa_format_descriptor fdesc; + struct pipe_context *mapping_pipe; +}; + +struct xa_tracker { + enum xa_formats *supported_formats; + unsigned int format_map[XA_LAST_SURFACE_TYPE][2]; + struct pipe_loader_device *dev; + struct pipe_screen *screen; + struct xa_context *default_ctx; +}; + +struct xa_context { + struct xa_tracker *xa; + struct pipe_context *pipe; + + struct cso_context *cso; + struct xa_shaders *shaders; + + struct pipe_resource *vs_const_buffer; + struct pipe_resource *fs_const_buffer; + + float buffer[XA_VB_SIZE]; + unsigned int buffer_size; + struct pipe_vertex_element velems[3]; + + /* number of attributes per vertex for the current + * draw operation */ + unsigned int attrs_per_vertex; + + unsigned int fb_width; + unsigned int fb_height; + + struct pipe_fence_handle *last_fence; + struct xa_surface *src; + struct xa_surface *dst; + struct pipe_surface *srf; + + /* destination scissor state.. we scissor out untouched parts + * of the dst for the benefit of tilers: + */ + struct pipe_scissor_state scissor; + int scissor_valid; + + int simple_copy; + + int has_solid_src; + int has_solid_mask; + float solid_color[4]; + + unsigned int num_bound_samplers; + struct pipe_sampler_view *bound_sampler_views[XA_MAX_SAMPLERS]; + const struct xa_composite *comp; +}; + +static inline void +xa_scissor_reset(struct xa_context *ctx) +{ + ctx->scissor.maxx = 0; + ctx->scissor.maxy = 0; + ctx->scissor.minx = ~0; + ctx->scissor.miny = ~0; + ctx->scissor_valid = FALSE; +} + +static inline void +xa_scissor_update(struct xa_context *ctx, unsigned minx, unsigned miny, + unsigned maxx, unsigned maxy) +{ + ctx->scissor.maxx = MAX2(ctx->scissor.maxx, maxx); + ctx->scissor.maxy = MAX2(ctx->scissor.maxy, maxy); + ctx->scissor.minx = MIN2(ctx->scissor.minx, minx); + ctx->scissor.miny = MIN2(ctx->scissor.miny, miny); + ctx->scissor_valid = TRUE; +} + +enum xa_vs_traits { + VS_COMPOSITE = 1 << 0, + VS_MASK = 1 << 1, + VS_SRC_SRC = 1 << 2, + VS_MASK_SRC = 1 << 3, + VS_YUV = 1 << 4, +}; + +enum xa_fs_traits { + FS_COMPOSITE = 1 << 0, + FS_MASK = 1 << 1, + FS_SRC_SRC = 1 << 2, + FS_MASK_SRC = 1 << 3, + FS_YUV = 1 << 4, + FS_SRC_REPEAT_NONE = 1 << 5, + FS_MASK_REPEAT_NONE = 1 << 6, + FS_SRC_SWIZZLE_RGB = 1 << 7, + FS_MASK_SWIZZLE_RGB = 1 << 8, + FS_SRC_SET_ALPHA = 1 << 9, + FS_MASK_SET_ALPHA = 1 << 10, + FS_SRC_LUMINANCE = 1 << 11, + FS_MASK_LUMINANCE = 1 << 12, + FS_DST_LUMINANCE = 1 << 13, + FS_CA = 1 << 14, +}; + +struct xa_shader { + void *fs; + void *vs; +}; + +struct xa_shaders; + +/* + * Inline utilities + */ + +static inline int +xa_min(int a, int b) +{ + return ((a <= b) ? a : b); +} + +static inline void +xa_pixel_to_float4(uint32_t pixel, float *color) +{ + uint32_t r, g, b, a; + + a = (pixel >> 24) & 0xff; + r = (pixel >> 16) & 0xff; + g = (pixel >> 8) & 0xff; + b = (pixel >> 0) & 0xff; + color[0] = ((float)r) / 255.; + color[1] = ((float)g) / 255.; + color[2] = ((float)b) / 255.; + color[3] = ((float)a) / 255.; +} + +static inline void +xa_pixel_to_float4_a8(uint32_t pixel, float *color) +{ + uint32_t a; + + a = (pixel >> 24) & 0xff; + color[0] = ((float)a) / 255.; + color[1] = ((float)a) / 255.; + color[2] = ((float)a) / 255.; + color[3] = ((float)a) / 255.; +} + +/* + * xa_tgsi.c + */ + +extern struct xa_shaders *xa_shaders_create(struct xa_context *); + +void xa_shaders_destroy(struct xa_shaders *shaders); + +struct xa_shader xa_shaders_get(struct xa_shaders *shaders, + unsigned vs_traits, unsigned fs_traits); + +/* + * xa_context.c + */ +extern void +xa_context_flush(struct xa_context *ctx); + +extern int +xa_ctx_srf_create(struct xa_context *ctx, struct xa_surface *dst); + +extern void +xa_ctx_srf_destroy(struct xa_context *ctx); + +extern void +xa_ctx_sampler_views_destroy(struct xa_context *ctx); + +/* + * xa_renderer.c + */ +void renderer_set_constants(struct xa_context *r, + int shader_type, const float *params, + int param_bytes); + +void renderer_draw_yuv(struct xa_context *r, + float src_x, + float src_y, + float src_w, + float src_h, + int dst_x, + int dst_y, int dst_w, int dst_h, + struct xa_surface *srf[]); + +void renderer_bind_destination(struct xa_context *r, + struct pipe_surface *surface); + +void renderer_init_state(struct xa_context *r); +void renderer_copy_prepare(struct xa_context *r, + struct pipe_surface *dst_surface, + struct pipe_resource *src_texture, + const enum xa_formats src_xa_format, + const enum xa_formats dst_xa_format); + +void renderer_copy(struct xa_context *r, int dx, + int dy, + int sx, + int sy, + int width, int height, float src_width, float src_height); + +void renderer_draw_flush(struct xa_context *r); + +void renderer_begin_solid(struct xa_context *r); +void renderer_solid(struct xa_context *r, + int x0, int y0, int x1, int y1); +void +renderer_begin_textures(struct xa_context *r); + +void +renderer_texture(struct xa_context *r, + int *pos, + int width, int height, + const float *src_matrix, + const float *mask_matrix); + +#endif diff --git a/src/gallium/frontends/xa/xa_renderer.c b/src/gallium/frontends/xa/xa_renderer.c new file mode 100644 index 00000000000..89548ad7019 --- /dev/null +++ b/src/gallium/frontends/xa/xa_renderer.c @@ -0,0 +1,636 @@ +/********************************************************** + * Copyright 2009-2011 VMware, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + ********************************************************* + * Authors: + * Zack Rusin + */ + +#include "xa_context.h" +#include "xa_priv.h" +#include +#include "cso_cache/cso_context.h" +#include "util/u_inlines.h" +#include "util/u_sampler.h" +#include "util/u_draw_quad.h" + +#define floatsEqual(x, y) (fabsf(x - y) <= 0.00001f * MIN2(fabsf(x), fabsf(y))) +#define floatIsZero(x) (floatsEqual((x) + 1, 1)) + +#define NUM_COMPONENTS 4 + +void + + +renderer_set_constants(struct xa_context *r, + int shader_type, const float *params, int param_bytes); + +static inline boolean +is_affine(const float *matrix) +{ + return floatIsZero(matrix[2]) && floatIsZero(matrix[5]) + && floatsEqual(matrix[8], 1); +} + +static inline void +map_point(const float *mat, float x, float y, float *out_x, float *out_y) +{ + if (!mat) { + *out_x = x; + *out_y = y; + return; + } + + *out_x = mat[0] * x + mat[3] * y + mat[6]; + *out_y = mat[1] * x + mat[4] * y + mat[7]; + if (!is_affine(mat)) { + float w = 1 / (mat[2] * x + mat[5] * y + mat[8]); + + *out_x *= w; + *out_y *= w; + } +} + +static inline void +renderer_draw(struct xa_context *r) +{ + int num_verts = r->buffer_size / (r->attrs_per_vertex * NUM_COMPONENTS); + + if (!r->buffer_size) + return; + + if (!r->scissor_valid) { + r->scissor.minx = 0; + r->scissor.miny = 0; + r->scissor.maxx = r->dst->tex->width0; + r->scissor.maxy = r->dst->tex->height0; + } + + r->pipe->set_scissor_states(r->pipe, 0, 1, &r->scissor); + + struct cso_velems_state velems; + velems.count = r->attrs_per_vertex; + memcpy(velems.velems, r->velems, sizeof(r->velems[0]) * velems.count); + + cso_set_vertex_elements(r->cso, &velems); + util_draw_user_vertex_buffer(r->cso, r->buffer, PIPE_PRIM_QUADS, + num_verts, /* verts */ + r->attrs_per_vertex); /* attribs/vert */ + r->buffer_size = 0; + + xa_scissor_reset(r); +} + +static inline void +renderer_draw_conditional(struct xa_context *r, int next_batch) +{ + if (r->buffer_size + next_batch >= XA_VB_SIZE || + (next_batch == 0 && r->buffer_size)) { + renderer_draw(r); + } +} + +void +renderer_init_state(struct xa_context *r) +{ + struct pipe_depth_stencil_alpha_state dsa; + struct pipe_rasterizer_state raster; + unsigned i; + + /* set common initial clip state */ + memset(&dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state)); + cso_set_depth_stencil_alpha(r->cso, &dsa); + + /* XXX: move to renderer_init_state? */ + memset(&raster, 0, sizeof(struct pipe_rasterizer_state)); + raster.half_pixel_center = 1; + raster.bottom_edge_rule = 1; + raster.depth_clip_near = 1; + raster.depth_clip_far = 1; + raster.scissor = 1; + cso_set_rasterizer(r->cso, &raster); + + /* vertex elements state */ + memset(&r->velems[0], 0, sizeof(r->velems[0]) * 3); + for (i = 0; i < 3; i++) { + r->velems[i].src_offset = i * 4 * sizeof(float); + r->velems[i].instance_divisor = 0; + r->velems[i].vertex_buffer_index = 0; + r->velems[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + } +} + +static inline void +add_vertex_none(struct xa_context *r, float x, float y) +{ + float *vertex = r->buffer + r->buffer_size; + + vertex[0] = x; + vertex[1] = y; + vertex[2] = 0.f; /*z */ + vertex[3] = 1.f; /*w */ + + r->buffer_size += 4; +} + +static inline void +add_vertex_1tex(struct xa_context *r, float x, float y, float s, float t) +{ + float *vertex = r->buffer + r->buffer_size; + + vertex[0] = x; + vertex[1] = y; + vertex[2] = 0.f; /*z */ + vertex[3] = 1.f; /*w */ + + vertex[4] = s; /*s */ + vertex[5] = t; /*t */ + vertex[6] = 0.f; /*r */ + vertex[7] = 1.f; /*q */ + + r->buffer_size += 8; +} + +static inline void +add_vertex_2tex(struct xa_context *r, + float x, float y, float s0, float t0, float s1, float t1) +{ + float *vertex = r->buffer + r->buffer_size; + + vertex[0] = x; + vertex[1] = y; + vertex[2] = 0.f; /*z */ + vertex[3] = 1.f; /*w */ + + vertex[4] = s0; /*s */ + vertex[5] = t0; /*t */ + vertex[6] = 0.f; /*r */ + vertex[7] = 1.f; /*q */ + + vertex[8] = s1; /*s */ + vertex[9] = t1; /*t */ + vertex[10] = 0.f; /*r */ + vertex[11] = 1.f; /*q */ + + r->buffer_size += 12; +} + +static void +compute_src_coords(float sx, float sy, const struct pipe_resource *src, + const float *src_matrix, + float width, float height, + float tc0[2], float tc1[2], float tc2[2], float tc3[2]) +{ + tc0[0] = sx; + tc0[1] = sy; + tc1[0] = sx + width; + tc1[1] = sy; + tc2[0] = sx + width; + tc2[1] = sy + height; + tc3[0] = sx; + tc3[1] = sy + height; + + if (src_matrix) { + map_point(src_matrix, tc0[0], tc0[1], &tc0[0], &tc0[1]); + map_point(src_matrix, tc1[0], tc1[1], &tc1[0], &tc1[1]); + map_point(src_matrix, tc2[0], tc2[1], &tc2[0], &tc2[1]); + map_point(src_matrix, tc3[0], tc3[1], &tc3[0], &tc3[1]); + } + + tc0[0] /= src->width0; + tc1[0] /= src->width0; + tc2[0] /= src->width0; + tc3[0] /= src->width0; + tc0[1] /= src->height0; + tc1[1] /= src->height0; + tc2[1] /= src->height0; + tc3[1] /= src->height0; +} + +static void +add_vertex_data1(struct xa_context *r, + float srcX, float srcY, float dstX, float dstY, + float width, float height, + const struct pipe_resource *src, const float *src_matrix) +{ + float tc0[2], tc1[2], tc2[2], tc3[2]; + + compute_src_coords(srcX, srcY, src, src_matrix, width, height, + tc0, tc1, tc2, tc3); + /* 1st vertex */ + add_vertex_1tex(r, dstX, dstY, tc0[0], tc0[1]); + /* 2nd vertex */ + add_vertex_1tex(r, dstX + width, dstY, tc1[0], tc1[1]); + /* 3rd vertex */ + add_vertex_1tex(r, dstX + width, dstY + height, tc2[0], tc2[1]); + /* 4th vertex */ + add_vertex_1tex(r, dstX, dstY + height, tc3[0], tc3[1]); +} + +static void +add_vertex_data2(struct xa_context *r, + float srcX, float srcY, float maskX, float maskY, + float dstX, float dstY, float width, float height, + struct pipe_resource *src, + struct pipe_resource *mask, + const float *src_matrix, const float *mask_matrix) +{ + float spt0[2], spt1[2], spt2[2], spt3[2]; + float mpt0[2], mpt1[2], mpt2[2], mpt3[2]; + + compute_src_coords(srcX, srcY, src, src_matrix, width, height, + spt0, spt1, spt2, spt3); + compute_src_coords(maskX, maskY, mask, mask_matrix, width, height, + mpt0, mpt1, mpt2, mpt3); + + /* 1st vertex */ + add_vertex_2tex(r, dstX, dstY, + spt0[0], spt0[1], mpt0[0], mpt0[1]); + /* 2nd vertex */ + add_vertex_2tex(r, dstX + width, dstY, + spt1[0], spt1[1], mpt1[0], mpt1[1]); + /* 3rd vertex */ + add_vertex_2tex(r, dstX + width, dstY + height, + spt2[0], spt2[1], mpt2[0], mpt2[1]); + /* 4th vertex */ + add_vertex_2tex(r, dstX, dstY + height, + spt3[0], spt3[1], mpt3[0], mpt3[1]); +} + +static void +setup_vertex_data_yuv(struct xa_context *r, + float srcX, + float srcY, + float srcW, + float srcH, + float dstX, + float dstY, + float dstW, float dstH, struct xa_surface *srf[]) +{ + float s0, t0, s1, t1; + float spt0[2], spt1[2]; + struct pipe_resource *tex; + + spt0[0] = srcX; + spt0[1] = srcY; + spt1[0] = srcX + srcW; + spt1[1] = srcY + srcH; + + tex = srf[0]->tex; + s0 = spt0[0] / tex->width0; + t0 = spt0[1] / tex->height0; + s1 = spt1[0] / tex->width0; + t1 = spt1[1] / tex->height0; + + /* 1st vertex */ + add_vertex_1tex(r, dstX, dstY, s0, t0); + /* 2nd vertex */ + add_vertex_1tex(r, dstX + dstW, dstY, s1, t0); + /* 3rd vertex */ + add_vertex_1tex(r, dstX + dstW, dstY + dstH, s1, t1); + /* 4th vertex */ + add_vertex_1tex(r, dstX, dstY + dstH, s0, t1); +} + +/* Set up framebuffer, viewport and vertex shader constant buffer + * state for a particular destinaton surface. In all our rendering, + * these concepts are linked. + */ +void +renderer_bind_destination(struct xa_context *r, + struct pipe_surface *surface) +{ + int width = surface->width; + int height = surface->height; + + struct pipe_framebuffer_state fb; + struct pipe_viewport_state viewport; + + xa_scissor_reset(r); + + /* Framebuffer uses actual surface width/height + */ + memset(&fb, 0, sizeof fb); + fb.width = surface->width; + fb.height = surface->height; + fb.nr_cbufs = 1; + fb.cbufs[0] = surface; + fb.zsbuf = 0; + + /* Viewport just touches the bit we're interested in: + */ + viewport.scale[0] = width / 2.f; + viewport.scale[1] = height / 2.f; + viewport.scale[2] = 1.0; + viewport.translate[0] = width / 2.f; + viewport.translate[1] = height / 2.f; + viewport.translate[2] = 0.0; + + /* Constant buffer set up to match viewport dimensions: + */ + if (r->fb_width != width || r->fb_height != height) { + float vs_consts[8] = { + 2.f / width, 2.f / height, 1, 1, + -1, -1, 0, 0 + }; + + r->fb_width = width; + r->fb_height = height; + + renderer_set_constants(r, PIPE_SHADER_VERTEX, + vs_consts, sizeof vs_consts); + } + + cso_set_framebuffer(r->cso, &fb); + cso_set_viewport(r->cso, &viewport); +} + +void +renderer_set_constants(struct xa_context *r, + int shader_type, const float *params, int param_bytes) +{ + struct pipe_resource **cbuf = + (shader_type == PIPE_SHADER_VERTEX) ? &r->vs_const_buffer : + &r->fs_const_buffer; + + pipe_resource_reference(cbuf, NULL); + *cbuf = pipe_buffer_create_const0(r->pipe->screen, + PIPE_BIND_CONSTANT_BUFFER, + PIPE_USAGE_DEFAULT, + param_bytes); + + if (*cbuf) { + pipe_buffer_write(r->pipe, *cbuf, 0, param_bytes, params); + } + pipe_set_constant_buffer(r->pipe, shader_type, 0, *cbuf); +} + +void +renderer_copy_prepare(struct xa_context *r, + struct pipe_surface *dst_surface, + struct pipe_resource *src_texture, + const enum xa_formats src_xa_format, + const enum xa_formats dst_xa_format) +{ + struct pipe_context *pipe = r->pipe; + struct pipe_screen *screen = pipe->screen; + struct xa_shader shader; + uint32_t fs_traits = FS_COMPOSITE; + + assert(screen->is_format_supported(screen, dst_surface->format, + PIPE_TEXTURE_2D, 0, 0, + PIPE_BIND_RENDER_TARGET)); + (void)screen; + + renderer_bind_destination(r, dst_surface); + + /* set misc state we care about */ + { + struct pipe_blend_state blend; + + memset(&blend, 0, sizeof(blend)); + blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend.rt[0].colormask = PIPE_MASK_RGBA; + cso_set_blend(r->cso, &blend); + } + + /* sampler */ + { + struct pipe_sampler_state sampler; + const struct pipe_sampler_state *p_sampler = &sampler; + + memset(&sampler, 0, sizeof(sampler)); + sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; + sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; + sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; + sampler.normalized_coords = 1; + cso_set_samplers(r->cso, PIPE_SHADER_FRAGMENT, 1, &p_sampler); + r->num_bound_samplers = 1; + } + + /* texture/sampler view */ + { + struct pipe_sampler_view templ; + struct pipe_sampler_view *src_view; + + u_sampler_view_default_template(&templ, + src_texture, src_texture->format); + src_view = pipe->create_sampler_view(pipe, src_texture, &templ); + cso_set_sampler_views(r->cso, PIPE_SHADER_FRAGMENT, 1, &src_view); + pipe_sampler_view_reference(&src_view, NULL); + } + + /* shaders */ + if (src_texture->format == PIPE_FORMAT_L8_UNORM || + src_texture->format == PIPE_FORMAT_R8_UNORM) + fs_traits |= FS_SRC_LUMINANCE; + if (dst_surface->format == PIPE_FORMAT_L8_UNORM || + dst_surface->format == PIPE_FORMAT_R8_UNORM) + fs_traits |= FS_DST_LUMINANCE; + if (xa_format_a(dst_xa_format) != 0 && + xa_format_a(src_xa_format) == 0) + fs_traits |= FS_SRC_SET_ALPHA; + + shader = xa_shaders_get(r->shaders, VS_COMPOSITE, fs_traits); + cso_set_vertex_shader_handle(r->cso, shader.vs); + cso_set_fragment_shader_handle(r->cso, shader.fs); + + r->buffer_size = 0; + r->attrs_per_vertex = 2; +} + +void +renderer_copy(struct xa_context *r, + int dx, + int dy, + int sx, + int sy, + int width, int height, float src_width, float src_height) +{ + float s0, t0, s1, t1; + float x0, y0, x1, y1; + + /* XXX: could put the texcoord scaling calculation into the vertex + * shader. + */ + s0 = sx / src_width; + s1 = (sx + width) / src_width; + t0 = sy / src_height; + t1 = (sy + height) / src_height; + + x0 = dx; + x1 = dx + width; + y0 = dy; + y1 = dy + height; + + /* draw quad */ + renderer_draw_conditional(r, 4 * 8); + add_vertex_1tex(r, x0, y0, s0, t0); + add_vertex_1tex(r, x1, y0, s1, t0); + add_vertex_1tex(r, x1, y1, s1, t1); + add_vertex_1tex(r, x0, y1, s0, t1); +} + +void +renderer_draw_yuv(struct xa_context *r, + float src_x, + float src_y, + float src_w, + float src_h, + int dst_x, + int dst_y, int dst_w, int dst_h, struct xa_surface *srf[]) +{ + const int num_attribs = 2; /*pos + tex coord */ + + setup_vertex_data_yuv(r, + src_x, src_y, src_w, src_h, + dst_x, dst_y, dst_w, dst_h, srf); + + if (!r->scissor_valid) { + r->scissor.minx = 0; + r->scissor.miny = 0; + r->scissor.maxx = r->dst->tex->width0; + r->scissor.maxy = r->dst->tex->height0; + } + + r->pipe->set_scissor_states(r->pipe, 0, 1, &r->scissor); + + struct cso_velems_state velems; + velems.count = num_attribs; + memcpy(velems.velems, r->velems, sizeof(r->velems[0]) * velems.count); + + cso_set_vertex_elements(r->cso, &velems); + util_draw_user_vertex_buffer(r->cso, r->buffer, PIPE_PRIM_QUADS, + 4, /* verts */ + num_attribs); /* attribs/vert */ + r->buffer_size = 0; + + xa_scissor_reset(r); +} + +void +renderer_begin_solid(struct xa_context *r) +{ + r->buffer_size = 0; + r->attrs_per_vertex = 1; + renderer_set_constants(r, PIPE_SHADER_FRAGMENT, r->solid_color, + 4 * sizeof(float)); +} + +void +renderer_solid(struct xa_context *r, + int x0, int y0, int x1, int y1) +{ + /* + * debug_printf("solid rect[(%d, %d), (%d, %d)], rgba[%f, %f, %f, %f]\n", + * x0, y0, x1, y1, color[0], color[1], color[2], color[3]); */ + + renderer_draw_conditional(r, 4 * 4); + + /* 1st vertex */ + add_vertex_none(r, x0, y0); + /* 2nd vertex */ + add_vertex_none(r, x1, y0); + /* 3rd vertex */ + add_vertex_none(r, x1, y1); + /* 4th vertex */ + add_vertex_none(r, x0, y1); +} + +void +renderer_draw_flush(struct xa_context *r) +{ + renderer_draw_conditional(r, 0); +} + +void +renderer_begin_textures(struct xa_context *r) +{ + r->attrs_per_vertex = 1 + r->num_bound_samplers; + r->buffer_size = 0; + if (r->has_solid_src || r->has_solid_mask) + renderer_set_constants(r, PIPE_SHADER_FRAGMENT, r->solid_color, + 4 * sizeof(float)); +} + +void +renderer_texture(struct xa_context *r, + int *pos, + int width, int height, + const float *src_matrix, + const float *mask_matrix) +{ + struct pipe_sampler_view **sampler_view = r->bound_sampler_views; + +#if 0 + if (src_matrix) { + debug_printf("src_matrix = \n"); + debug_printf("%f, %f, %f\n", src_matrix[0], src_matrix[1], src_matrix[2]); + debug_printf("%f, %f, %f\n", src_matrix[3], src_matrix[4], src_matrix[5]); + debug_printf("%f, %f, %f\n", src_matrix[6], src_matrix[7], src_matrix[8]); + } + if (mask_matrix) { + debug_printf("mask_matrix = \n"); + debug_printf("%f, %f, %f\n", mask_matrix[0], mask_matrix[1], mask_matrix[2]); + debug_printf("%f, %f, %f\n", mask_matrix[3], mask_matrix[4], mask_matrix[5]); + debug_printf("%f, %f, %f\n", mask_matrix[6], mask_matrix[7], mask_matrix[8]); + } +#endif + + switch(r->attrs_per_vertex) { + case 2: + renderer_draw_conditional(r, 4 * 8); + if (!r->has_solid_src) { + add_vertex_data1(r, + pos[0], pos[1], /* src */ + pos[4], pos[5], /* dst */ + width, height, + sampler_view[0]->texture, src_matrix); + } else { + add_vertex_data1(r, + pos[2], pos[3], /* mask */ + pos[4], pos[5], /* dst */ + width, height, + sampler_view[0]->texture, mask_matrix); + } + break; + case 3: + renderer_draw_conditional(r, 4 * 12); + add_vertex_data2(r, + pos[0], pos[1], /* src */ + pos[2], pos[3], /* mask */ + pos[4], pos[5], /* dst */ + width, height, + sampler_view[0]->texture, sampler_view[1]->texture, + src_matrix, mask_matrix); + break; + default: + break; + } +} diff --git a/src/gallium/frontends/xa/xa_tgsi.c b/src/gallium/frontends/xa/xa_tgsi.c new file mode 100644 index 00000000000..83f6db128c3 --- /dev/null +++ b/src/gallium/frontends/xa/xa_tgsi.c @@ -0,0 +1,500 @@ +/********************************************************** + * Copyright 2009-2011 VMware, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + ********************************************************* + * Authors: + * Zack Rusin + */ +#include "xa_priv.h" + +#include "pipe/p_format.h" +#include "pipe/p_context.h" +#include "pipe/p_state.h" +#include "pipe/p_shader_tokens.h" + +#include "util/u_memory.h" + +#include "tgsi/tgsi_ureg.h" + +#include "cso_cache/cso_context.h" +#include "cso_cache/cso_hash.h" + +/* Vertex shader: + * IN[0] = vertex pos + * IN[1] = src tex coord | solid fill color + * IN[2] = mask tex coord + * IN[3] = dst tex coord + * CONST[0] = (2/dst_width, 2/dst_height, 1, 1) + * CONST[1] = (-1, -1, 0, 0) + * + * OUT[0] = vertex pos + * OUT[1] = src tex coord + * OUT[2] = mask tex coord + * OUT[3] = dst tex coord + */ + +/* Fragment shader. Samplers are allocated when needed. + * SAMP[0] = sampler for first texture (src or mask if src is solid) + * SAMP[1] = sampler for second texture (mask or none) + * IN[0] = first texture coordinates if present + * IN[1] = second texture coordinates if present + * CONST[0] = Solid color (src if src solid or mask if mask solid + * or src in mask if both solid). + * + * OUT[0] = color + */ + +static void +print_fs_traits(int fs_traits) +{ + const char *strings[] = { + "FS_COMPOSITE", /* = 1 << 0, */ + "FS_MASK", /* = 1 << 1, */ + "FS_SRC_SRC", /* = 1 << 2, */ + "FS_MASK_SRC", /* = 1 << 3, */ + "FS_YUV", /* = 1 << 4, */ + "FS_SRC_REPEAT_NONE", /* = 1 << 5, */ + "FS_MASK_REPEAT_NONE", /* = 1 << 6, */ + "FS_SRC_SWIZZLE_RGB", /* = 1 << 7, */ + "FS_MASK_SWIZZLE_RGB", /* = 1 << 8, */ + "FS_SRC_SET_ALPHA", /* = 1 << 9, */ + "FS_MASK_SET_ALPHA", /* = 1 << 10, */ + "FS_SRC_LUMINANCE", /* = 1 << 11, */ + "FS_MASK_LUMINANCE", /* = 1 << 12, */ + "FS_DST_LUMINANCE", /* = 1 << 13, */ + "FS_CA", /* = 1 << 14, */ + }; + int i, k; + + debug_printf("%s: ", __func__); + + for (i = 0, k = 1; k < (1 << 16); i++, k <<= 1) { + if (fs_traits & k) + debug_printf("%s, ", strings[i]); + } + + debug_printf("\n"); +} + +struct xa_shaders { + struct xa_context *r; + + struct cso_hash vs_hash; + struct cso_hash fs_hash; +}; + +static inline void +src_in_mask(struct ureg_program *ureg, + struct ureg_dst dst, + struct ureg_src src, + struct ureg_src mask, + unsigned mask_luminance, boolean component_alpha) +{ + if (mask_luminance) + if (component_alpha) { + ureg_MOV(ureg, dst, src); + ureg_MUL(ureg, ureg_writemask(dst, TGSI_WRITEMASK_W), + src, ureg_scalar(mask, TGSI_SWIZZLE_X)); + } else { + ureg_MUL(ureg, dst, src, ureg_scalar(mask, TGSI_SWIZZLE_X)); + } + else if (!component_alpha) + ureg_MUL(ureg, dst, src, ureg_scalar(mask, TGSI_SWIZZLE_W)); + else + ureg_MUL(ureg, dst, src, mask); +} + +static struct ureg_src +vs_normalize_coords(struct ureg_program *ureg, + struct ureg_src coords, + struct ureg_src const0, struct ureg_src const1) +{ + struct ureg_dst tmp = ureg_DECL_temporary(ureg); + struct ureg_src ret; + + ureg_MAD(ureg, tmp, coords, const0, const1); + ret = ureg_src(tmp); + ureg_release_temporary(ureg, tmp); + return ret; +} + +static void * +create_vs(struct pipe_context *pipe, unsigned vs_traits) +{ + struct ureg_program *ureg; + struct ureg_src src; + struct ureg_dst dst; + struct ureg_src const0, const1; + boolean is_composite = (vs_traits & VS_COMPOSITE) != 0; + boolean has_mask = (vs_traits & VS_MASK) != 0; + boolean is_yuv = (vs_traits & VS_YUV) != 0; + boolean is_src_src = (vs_traits & VS_SRC_SRC) != 0; + boolean is_mask_src = (vs_traits & VS_MASK_SRC) != 0; + unsigned input_slot = 0; + + ureg = ureg_create(PIPE_SHADER_VERTEX); + if (ureg == NULL) + return 0; + + const0 = ureg_DECL_constant(ureg, 0); + const1 = ureg_DECL_constant(ureg, 1); + + /* it has to be either a fill or a composite op */ + src = ureg_DECL_vs_input(ureg, input_slot++); + dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0); + src = vs_normalize_coords(ureg, src, const0, const1); + ureg_MOV(ureg, dst, src); + + if (is_yuv) { + src = ureg_DECL_vs_input(ureg, input_slot++); + dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 0); + ureg_MOV(ureg, dst, src); + } + + if (is_composite) { + if (!is_src_src || (has_mask && !is_mask_src)) { + src = ureg_DECL_vs_input(ureg, input_slot++); + dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 0); + ureg_MOV(ureg, dst, src); + } + + if (!is_src_src && (has_mask && !is_mask_src)) { + src = ureg_DECL_vs_input(ureg, input_slot++); + dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 1); + ureg_MOV(ureg, dst, src); + } + } + + ureg_END(ureg); + + return ureg_create_shader_and_destroy(ureg, pipe); +} + +static void * +create_yuv_shader(struct pipe_context *pipe, struct ureg_program *ureg) +{ + struct ureg_src y_sampler, u_sampler, v_sampler; + struct ureg_src pos; + struct ureg_src matrow0, matrow1, matrow2, matrow3; + struct ureg_dst y, u, v, rgb; + struct ureg_dst out = ureg_DECL_output(ureg, + TGSI_SEMANTIC_COLOR, + 0); + + pos = ureg_DECL_fs_input(ureg, + TGSI_SEMANTIC_GENERIC, 0, + TGSI_INTERPOLATE_PERSPECTIVE); + + rgb = ureg_DECL_temporary(ureg); + y = ureg_DECL_temporary(ureg); + u = ureg_DECL_temporary(ureg); + v = ureg_DECL_temporary(ureg); + + y_sampler = ureg_DECL_sampler(ureg, 0); + u_sampler = ureg_DECL_sampler(ureg, 1); + v_sampler = ureg_DECL_sampler(ureg, 2); + + ureg_DECL_sampler_view(ureg, 0, TGSI_TEXTURE_2D, + TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT, + TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT); + ureg_DECL_sampler_view(ureg, 1, TGSI_TEXTURE_2D, + TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT, + TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT); + ureg_DECL_sampler_view(ureg, 2, TGSI_TEXTURE_2D, + TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT, + TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT); + + matrow0 = ureg_DECL_constant(ureg, 0); + matrow1 = ureg_DECL_constant(ureg, 1); + matrow2 = ureg_DECL_constant(ureg, 2); + matrow3 = ureg_DECL_constant(ureg, 3); + + ureg_TEX(ureg, y, TGSI_TEXTURE_2D, pos, y_sampler); + ureg_TEX(ureg, u, TGSI_TEXTURE_2D, pos, u_sampler); + ureg_TEX(ureg, v, TGSI_TEXTURE_2D, pos, v_sampler); + + ureg_MOV(ureg, rgb, matrow3); + ureg_MAD(ureg, rgb, + ureg_scalar(ureg_src(y), TGSI_SWIZZLE_X), matrow0, ureg_src(rgb)); + ureg_MAD(ureg, rgb, + ureg_scalar(ureg_src(u), TGSI_SWIZZLE_X), matrow1, ureg_src(rgb)); + ureg_MAD(ureg, rgb, + ureg_scalar(ureg_src(v), TGSI_SWIZZLE_X), matrow2, ureg_src(rgb)); + + ureg_MOV(ureg, out, ureg_src(rgb)); + + ureg_release_temporary(ureg, rgb); + ureg_release_temporary(ureg, y); + ureg_release_temporary(ureg, u); + ureg_release_temporary(ureg, v); + + ureg_END(ureg); + + return ureg_create_shader_and_destroy(ureg, pipe); +} + +static inline void +xrender_tex(struct ureg_program *ureg, + struct ureg_dst dst, + struct ureg_src coords, + struct ureg_src sampler, + const struct ureg_src *imm0, + boolean repeat_none, boolean swizzle, boolean set_alpha) +{ + if (repeat_none) { + struct ureg_dst tmp0 = ureg_DECL_temporary(ureg); + struct ureg_dst tmp1 = ureg_DECL_temporary(ureg); + + ureg_SGT(ureg, tmp1, ureg_swizzle(coords, + TGSI_SWIZZLE_X, + TGSI_SWIZZLE_Y, + TGSI_SWIZZLE_X, + TGSI_SWIZZLE_Y), ureg_scalar(*imm0, + TGSI_SWIZZLE_X)); + ureg_SLT(ureg, tmp0, + ureg_swizzle(coords, TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y, + TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y), ureg_scalar(*imm0, + TGSI_SWIZZLE_W)); + ureg_MIN(ureg, tmp0, ureg_src(tmp0), ureg_src(tmp1)); + ureg_MIN(ureg, tmp0, ureg_scalar(ureg_src(tmp0), TGSI_SWIZZLE_X), + ureg_scalar(ureg_src(tmp0), TGSI_SWIZZLE_Y)); + ureg_TEX(ureg, tmp1, TGSI_TEXTURE_2D, coords, sampler); + if (swizzle) + ureg_MOV(ureg, tmp1, ureg_swizzle(ureg_src(tmp1), + TGSI_SWIZZLE_Z, + TGSI_SWIZZLE_Y, TGSI_SWIZZLE_X, + TGSI_SWIZZLE_W)); + if (set_alpha) + ureg_MOV(ureg, + ureg_writemask(tmp1, TGSI_WRITEMASK_W), + ureg_scalar(*imm0, TGSI_SWIZZLE_W)); + ureg_MUL(ureg, dst, ureg_src(tmp1), ureg_src(tmp0)); + ureg_release_temporary(ureg, tmp0); + ureg_release_temporary(ureg, tmp1); + } else { + if (swizzle) { + struct ureg_dst tmp = ureg_DECL_temporary(ureg); + + ureg_TEX(ureg, tmp, TGSI_TEXTURE_2D, coords, sampler); + ureg_MOV(ureg, dst, ureg_swizzle(ureg_src(tmp), + TGSI_SWIZZLE_Z, + TGSI_SWIZZLE_Y, TGSI_SWIZZLE_X, + TGSI_SWIZZLE_W)); + ureg_release_temporary(ureg, tmp); + } else { + ureg_TEX(ureg, dst, TGSI_TEXTURE_2D, coords, sampler); + } + if (set_alpha) + ureg_MOV(ureg, + ureg_writemask(dst, TGSI_WRITEMASK_W), + ureg_scalar(*imm0, TGSI_SWIZZLE_W)); + } +} + +static void +read_input(struct ureg_program *ureg, + struct ureg_dst dst, + const struct ureg_src *imm0, + boolean repeat_none, boolean swizzle, boolean set_alpha, + boolean is_src, unsigned *cur_constant, unsigned *cur_sampler) +{ + struct ureg_src input, sampler; + + if (is_src) { + input = ureg_DECL_constant(ureg, (*cur_constant)++); + ureg_MOV(ureg, dst, input); + } else { + sampler = ureg_DECL_sampler(ureg, *cur_sampler); + ureg_DECL_sampler_view(ureg, *cur_sampler, TGSI_TEXTURE_2D, + TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT, + TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT); + input = ureg_DECL_fs_input(ureg, + TGSI_SEMANTIC_GENERIC, (*cur_sampler)++, + TGSI_INTERPOLATE_PERSPECTIVE); + xrender_tex(ureg, dst, input, sampler, imm0, + repeat_none, swizzle, set_alpha); + } +} + +static void * +create_fs(struct pipe_context *pipe, unsigned fs_traits) +{ + struct ureg_program *ureg; + struct ureg_dst src, mask; + struct ureg_dst out; + struct ureg_src imm0 = { 0 }; + unsigned has_mask = (fs_traits & FS_MASK) != 0; + unsigned is_yuv = (fs_traits & FS_YUV) != 0; + unsigned src_repeat_none = (fs_traits & FS_SRC_REPEAT_NONE) != 0; + unsigned mask_repeat_none = (fs_traits & FS_MASK_REPEAT_NONE) != 0; + unsigned src_swizzle = (fs_traits & FS_SRC_SWIZZLE_RGB) != 0; + unsigned mask_swizzle = (fs_traits & FS_MASK_SWIZZLE_RGB) != 0; + unsigned src_set_alpha = (fs_traits & FS_SRC_SET_ALPHA) != 0; + unsigned mask_set_alpha = (fs_traits & FS_MASK_SET_ALPHA) != 0; + unsigned src_luminance = (fs_traits & FS_SRC_LUMINANCE) != 0; + unsigned mask_luminance = (fs_traits & FS_MASK_LUMINANCE) != 0; + unsigned dst_luminance = (fs_traits & FS_DST_LUMINANCE) != 0; + unsigned is_src_src = (fs_traits & FS_SRC_SRC) != 0; + unsigned is_mask_src = (fs_traits & FS_MASK_SRC) != 0; + boolean component_alpha = (fs_traits & FS_CA) != 0; + unsigned cur_sampler = 0; + unsigned cur_constant = 0; + +#if 0 + print_fs_traits(fs_traits); +#else + (void)print_fs_traits; +#endif + + ureg = ureg_create(PIPE_SHADER_FRAGMENT); + if (ureg == NULL) + return 0; + + if (is_yuv) + return create_yuv_shader(pipe, ureg); + + out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0); + + if (src_repeat_none || mask_repeat_none || + src_set_alpha || mask_set_alpha || src_luminance) { + imm0 = ureg_imm4f(ureg, 0, 0, 0, 1); + } + + src = (has_mask || src_luminance || dst_luminance) ? + ureg_DECL_temporary(ureg) : out; + + read_input(ureg, src, &imm0, src_repeat_none, src_swizzle, + src_set_alpha, is_src_src, &cur_constant, &cur_sampler); + + if (src_luminance) { + ureg_MOV(ureg, src, ureg_scalar(ureg_src(src), TGSI_SWIZZLE_X)); + ureg_MOV(ureg, ureg_writemask(src, TGSI_WRITEMASK_XYZ), + ureg_scalar(imm0, TGSI_SWIZZLE_X)); + if (!has_mask && !dst_luminance) + ureg_MOV(ureg, out, ureg_src(src)); + } + + if (has_mask) { + mask = ureg_DECL_temporary(ureg); + read_input(ureg, mask, &imm0, mask_repeat_none, + mask_swizzle, mask_set_alpha, is_mask_src, &cur_constant, + &cur_sampler); + + src_in_mask(ureg, (dst_luminance) ? src : out, ureg_src(src), + ureg_src(mask), mask_luminance, component_alpha); + + ureg_release_temporary(ureg, mask); + } + + if (dst_luminance) { + /* + * Make sure the alpha channel goes into the output L8 surface. + */ + ureg_MOV(ureg, out, ureg_scalar(ureg_src(src), TGSI_SWIZZLE_W)); + } + + ureg_END(ureg); + + return ureg_create_shader_and_destroy(ureg, pipe); +} + +struct xa_shaders * +xa_shaders_create(struct xa_context *r) +{ + struct xa_shaders *sc = CALLOC_STRUCT(xa_shaders); + + sc->r = r; + cso_hash_init(&sc->vs_hash); + cso_hash_init(&sc->fs_hash); + + return sc; +} + +static void +cache_destroy(struct pipe_context *pipe, + struct cso_hash *hash, unsigned processor) +{ + struct cso_hash_iter iter = cso_hash_first_node(hash); + + while (!cso_hash_iter_is_null(iter)) { + void *shader = (void *)cso_hash_iter_data(iter); + + if (processor == PIPE_SHADER_FRAGMENT) { + pipe->delete_fs_state(pipe, shader); + } else if (processor == PIPE_SHADER_VERTEX) { + pipe->delete_vs_state(pipe, shader); + } + iter = cso_hash_erase(hash, iter); + } + cso_hash_deinit(hash); +} + +void +xa_shaders_destroy(struct xa_shaders *sc) +{ + cache_destroy(sc->r->pipe, &sc->vs_hash, PIPE_SHADER_VERTEX); + cache_destroy(sc->r->pipe, &sc->fs_hash, PIPE_SHADER_FRAGMENT); + + FREE(sc); +} + +static inline void * +shader_from_cache(struct pipe_context *pipe, + unsigned type, struct cso_hash *hash, unsigned key) +{ + void *shader = 0; + + struct cso_hash_iter iter = cso_hash_find(hash, key); + + if (cso_hash_iter_is_null(iter)) { + if (type == PIPE_SHADER_VERTEX) + shader = create_vs(pipe, key); + else + shader = create_fs(pipe, key); + cso_hash_insert(hash, key, shader); + } else + shader = (void *)cso_hash_iter_data(iter); + + return shader; +} + +struct xa_shader +xa_shaders_get(struct xa_shaders *sc, unsigned vs_traits, unsigned fs_traits) +{ + struct xa_shader shader = { NULL, NULL }; + void *vs, *fs; + + vs = shader_from_cache(sc->r->pipe, PIPE_SHADER_VERTEX, + &sc->vs_hash, vs_traits); + fs = shader_from_cache(sc->r->pipe, PIPE_SHADER_FRAGMENT, + &sc->fs_hash, fs_traits); + + debug_assert(vs && fs); + if (!vs || !fs) + return shader; + + shader.vs = vs; + shader.fs = fs; + + return shader; +} diff --git a/src/gallium/frontends/xa/xa_tracker.c b/src/gallium/frontends/xa/xa_tracker.c new file mode 100644 index 00000000000..31162606375 --- /dev/null +++ b/src/gallium/frontends/xa/xa_tracker.c @@ -0,0 +1,578 @@ +/********************************************************** + * Copyright 2009-2011 VMware, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + ********************************************************* + * Authors: + * Thomas Hellstrom + */ + +#include +#include "xa_tracker.h" +#include "xa_priv.h" +#include "pipe/p_state.h" +#include "pipe/p_format.h" +#include "pipe-loader/pipe_loader.h" +#include "frontend/drm_driver.h" +#include "util/u_inlines.h" + +/* + * format_map [xa_surface_type][first..last in list]. + * Needs to be updated when enum xa_formats is updated. + */ + +static const enum xa_formats preferred_a[] = { xa_format_a8 }; + +static const enum xa_formats preferred_argb[] = + { xa_format_a8r8g8b8, xa_format_x8r8g8b8, xa_format_r5g6b5, + xa_format_x1r5g5b5 +}; +static const enum xa_formats preferred_z[] = + { xa_format_z32, xa_format_z24, xa_format_z16 }; +static const enum xa_formats preferred_sz[] = + { xa_format_x8z24, xa_format_s8z24 }; +static const enum xa_formats preferred_zs[] = + { xa_format_z24x8, xa_format_z24s8 }; +static const enum xa_formats preferred_yuv[] = { xa_format_yuv8 }; + +static const enum xa_formats *preferred[] = + { NULL, preferred_a, preferred_argb, NULL, NULL, + preferred_z, preferred_zs, preferred_sz, preferred_yuv +}; + +static const unsigned int num_preferred[] = { 0, + sizeof(preferred_a) / sizeof(enum xa_formats), + sizeof(preferred_argb) / sizeof(enum xa_formats), + 0, + 0, + sizeof(preferred_z) / sizeof(enum xa_formats), + sizeof(preferred_zs) / sizeof(enum xa_formats), + sizeof(preferred_sz) / sizeof(enum xa_formats), + sizeof(preferred_yuv) / sizeof(enum xa_formats) +}; + +static const unsigned int stype_bind[XA_LAST_SURFACE_TYPE] = { 0, + PIPE_BIND_SAMPLER_VIEW, + PIPE_BIND_SAMPLER_VIEW, + PIPE_BIND_SAMPLER_VIEW, + PIPE_BIND_SAMPLER_VIEW, + PIPE_BIND_DEPTH_STENCIL, + PIPE_BIND_DEPTH_STENCIL, + PIPE_BIND_DEPTH_STENCIL, + PIPE_BIND_SAMPLER_VIEW +}; + +static struct xa_format_descriptor +xa_get_pipe_format(struct xa_tracker *xa, enum xa_formats xa_format) +{ + struct xa_format_descriptor fdesc; + + fdesc.xa_format = xa_format; + + switch (xa_format) { + case xa_format_a8: + if (xa->screen->is_format_supported(xa->screen, PIPE_FORMAT_R8_UNORM, + PIPE_TEXTURE_2D, 0, 0, + stype_bind[xa_type_a] | + PIPE_BIND_RENDER_TARGET)) + fdesc.format = PIPE_FORMAT_R8_UNORM; + else + fdesc.format = PIPE_FORMAT_L8_UNORM; + break; + case xa_format_a8r8g8b8: + fdesc.format = PIPE_FORMAT_B8G8R8A8_UNORM; + break; + case xa_format_x8r8g8b8: + fdesc.format = PIPE_FORMAT_B8G8R8X8_UNORM; + break; + case xa_format_r5g6b5: + fdesc.format = PIPE_FORMAT_B5G6R5_UNORM; + break; + case xa_format_x1r5g5b5: + fdesc.format = PIPE_FORMAT_B5G5R5A1_UNORM; + break; + case xa_format_a4r4g4b4: + fdesc.format = PIPE_FORMAT_B4G4R4A4_UNORM; + break; + case xa_format_a2b10g10r10: + fdesc.format = PIPE_FORMAT_R10G10B10A2_UNORM; + break; + case xa_format_x2b10g10r10: + fdesc.format = PIPE_FORMAT_R10G10B10X2_UNORM; + break; + case xa_format_b8g8r8a8: + fdesc.format = PIPE_FORMAT_A8R8G8B8_UNORM; + break; + case xa_format_b8g8r8x8: + fdesc.format = PIPE_FORMAT_X8R8G8B8_UNORM; + break; + case xa_format_z24: + fdesc.format = PIPE_FORMAT_Z24X8_UNORM; + break; + case xa_format_z16: + fdesc.format = PIPE_FORMAT_Z16_UNORM; + break; + case xa_format_z32: + fdesc.format = PIPE_FORMAT_Z32_UNORM; + break; + case xa_format_x8z24: + fdesc.format = PIPE_FORMAT_Z24X8_UNORM; + break; + case xa_format_z24x8: + fdesc.format = PIPE_FORMAT_X8Z24_UNORM; + break; + case xa_format_s8z24: + fdesc.format = PIPE_FORMAT_Z24_UNORM_S8_UINT; + break; + case xa_format_z24s8: + fdesc.format = PIPE_FORMAT_S8_UINT_Z24_UNORM; + break; + case xa_format_yuv8: + if (xa->screen->is_format_supported(xa->screen, PIPE_FORMAT_R8_UNORM, + PIPE_TEXTURE_2D, 0, 0, + stype_bind[xa_type_yuv_component])) + fdesc.format = PIPE_FORMAT_R8_UNORM; + else + fdesc.format = PIPE_FORMAT_L8_UNORM; + break; + default: + fdesc.xa_format = xa_format_unknown; + break; + } + return fdesc; +} + +XA_EXPORT struct xa_tracker * +xa_tracker_create(int drm_fd) +{ + struct xa_tracker *xa = calloc(1, sizeof(struct xa_tracker)); + enum xa_surface_type stype; + unsigned int num_formats; + + if (!xa) + return NULL; + + if (pipe_loader_drm_probe_fd(&xa->dev, drm_fd)) + xa->screen = pipe_loader_create_screen(xa->dev); + + if (!xa->screen) + goto out_no_screen; + + xa->default_ctx = xa_context_create(xa); + if (!xa->default_ctx) + goto out_no_pipe; + + num_formats = 0; + for (stype = 0; stype < XA_LAST_SURFACE_TYPE; ++stype) + num_formats += num_preferred[stype]; + + num_formats += 1; + xa->supported_formats = calloc(num_formats, sizeof(*xa->supported_formats)); + if (!xa->supported_formats) + goto out_sf_alloc_fail; + + xa->supported_formats[0] = xa_format_unknown; + num_formats = 1; + memset(xa->format_map, 0, sizeof(xa->format_map)); + + for (stype = 0; stype < XA_LAST_SURFACE_TYPE; ++stype) { + unsigned int bind = stype_bind[stype]; + enum xa_formats xa_format; + int i; + + for (i = 0; i < num_preferred[stype]; ++i) { + xa_format = preferred[stype][i]; + + struct xa_format_descriptor fdesc = + xa_get_pipe_format(xa, xa_format); + + if (xa->screen->is_format_supported(xa->screen, fdesc.format, + PIPE_TEXTURE_2D, 0, 0, bind)) { + if (xa->format_map[stype][0] == 0) + xa->format_map[stype][0] = num_formats; + xa->format_map[stype][1] = num_formats; + xa->supported_formats[num_formats++] = xa_format; + } + } + } + return xa; + + out_sf_alloc_fail: + xa_context_destroy(xa->default_ctx); + out_no_pipe: + xa->screen->destroy(xa->screen); + out_no_screen: + if (xa->dev) + pipe_loader_release(&xa->dev, 1); + + free(xa); + return NULL; +} + +XA_EXPORT void +xa_tracker_destroy(struct xa_tracker *xa) +{ + free(xa->supported_formats); + xa_context_destroy(xa->default_ctx); + xa->screen->destroy(xa->screen); + pipe_loader_release(&xa->dev, 1); + /* CHECK: The XA API user preserves ownership of the original fd */ + free(xa); +} + +static int +xa_flags_compat(unsigned int old_flags, unsigned int new_flags) +{ + unsigned int flag_diff = (old_flags ^ new_flags); + + if (flag_diff == 0) + return 1; + + if (flag_diff & XA_FLAG_SHARED) + return 0; + /* + * Don't recreate if we're dropping the render target flag. + */ + if (flag_diff & XA_FLAG_RENDER_TARGET) + return ((new_flags & XA_FLAG_RENDER_TARGET) == 0); + + /* + * Don't recreate if we're dropping the scanout flag. + */ + if (flag_diff & XA_FLAG_SCANOUT) + return ((new_flags & XA_FLAG_SCANOUT) == 0); + + /* + * Always recreate for unknown / unimplemented flags. + */ + return 0; +} + +static struct xa_format_descriptor +xa_get_format_stype_depth(struct xa_tracker *xa, + enum xa_surface_type stype, unsigned int depth) +{ + unsigned int i; + struct xa_format_descriptor fdesc; + int found = 0; + + for (i = xa->format_map[stype][0]; i <= xa->format_map[stype][1]; ++i) { + fdesc = xa_get_pipe_format(xa, xa->supported_formats[i]); + if (fdesc.xa_format != xa_format_unknown && + xa_format_depth(fdesc.xa_format) == depth) { + found = 1; + break; + } + } + + if (!found) + fdesc.xa_format = xa_format_unknown; + + return fdesc; +} + +XA_EXPORT int +xa_format_check_supported(struct xa_tracker *xa, + enum xa_formats xa_format, unsigned int flags) +{ + struct xa_format_descriptor fdesc = xa_get_pipe_format(xa, xa_format); + unsigned int bind; + + if (fdesc.xa_format == xa_format_unknown) + return -XA_ERR_INVAL; + + bind = stype_bind[xa_format_type(fdesc.xa_format)]; + if (flags & XA_FLAG_SHARED) + bind |= PIPE_BIND_SHARED; + if (flags & XA_FLAG_RENDER_TARGET) + bind |= PIPE_BIND_RENDER_TARGET; + if (flags & XA_FLAG_SCANOUT) + bind |= PIPE_BIND_SCANOUT; + + if (!xa->screen->is_format_supported(xa->screen, fdesc.format, + PIPE_TEXTURE_2D, 0, 0, bind)) + return -XA_ERR_INVAL; + + return XA_ERR_NONE; +} + +static unsigned +handle_type(enum xa_handle_type type) +{ + switch (type) { + case xa_handle_type_kms: + return WINSYS_HANDLE_TYPE_KMS; + case xa_handle_type_fd: + return WINSYS_HANDLE_TYPE_FD; + case xa_handle_type_shared: + default: + return WINSYS_HANDLE_TYPE_SHARED; + } +} + +static struct xa_surface * +surface_create(struct xa_tracker *xa, + int width, + int height, + int depth, + enum xa_surface_type stype, + enum xa_formats xa_format, unsigned int flags, + struct winsys_handle *whandle) +{ + struct pipe_resource *template; + struct xa_surface *srf; + struct xa_format_descriptor fdesc; + + if (xa_format == xa_format_unknown) + fdesc = xa_get_format_stype_depth(xa, stype, depth); + else + fdesc = xa_get_pipe_format(xa, xa_format); + + if (fdesc.xa_format == xa_format_unknown) + return NULL; + + srf = calloc(1, sizeof(*srf)); + if (!srf) + return NULL; + + template = &srf->template; + template->format = fdesc.format; + template->target = PIPE_TEXTURE_2D; + template->width0 = width; + template->height0 = height; + template->depth0 = 1; + template->array_size = 1; + template->last_level = 0; + template->bind = stype_bind[xa_format_type(fdesc.xa_format)]; + + if (flags & XA_FLAG_SHARED) + template->bind |= PIPE_BIND_SHARED; + if (flags & XA_FLAG_RENDER_TARGET) + template->bind |= PIPE_BIND_RENDER_TARGET; + if (flags & XA_FLAG_SCANOUT) + template->bind |= PIPE_BIND_SCANOUT; + + if (whandle) + srf->tex = xa->screen->resource_from_handle(xa->screen, template, whandle, + PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE); + else + srf->tex = xa->screen->resource_create(xa->screen, template); + if (!srf->tex) + goto out_no_tex; + + srf->refcount = 1; + srf->xa = xa; + srf->flags = flags; + srf->fdesc = fdesc; + + return srf; + out_no_tex: + free(srf); + return NULL; +} + + +XA_EXPORT struct xa_surface * +xa_surface_create(struct xa_tracker *xa, + int width, + int height, + int depth, + enum xa_surface_type stype, + enum xa_formats xa_format, unsigned int flags) +{ + return surface_create(xa, width, height, depth, stype, xa_format, flags, NULL); +} + + +XA_EXPORT struct xa_surface * +xa_surface_from_handle(struct xa_tracker *xa, + int width, + int height, + int depth, + enum xa_surface_type stype, + enum xa_formats xa_format, unsigned int flags, + uint32_t handle, uint32_t stride) +{ + return xa_surface_from_handle2(xa, width, height, depth, stype, xa_format, + WINSYS_HANDLE_TYPE_SHARED, flags, handle, + stride); +} + +XA_EXPORT struct xa_surface * +xa_surface_from_handle2(struct xa_tracker *xa, + int width, + int height, + int depth, + enum xa_surface_type stype, + enum xa_formats xa_format, unsigned int flags, + enum xa_handle_type type, + uint32_t handle, uint32_t stride) +{ + struct winsys_handle whandle; + memset(&whandle, 0, sizeof(whandle)); + whandle.type = handle_type(type); + whandle.handle = handle; + whandle.stride = stride; + return surface_create(xa, width, height, depth, stype, xa_format, flags, &whandle); +} + +XA_EXPORT int +xa_surface_redefine(struct xa_surface *srf, + int width, + int height, + int depth, + enum xa_surface_type stype, + enum xa_formats xa_format, + unsigned int new_flags, + int copy_contents) +{ + struct pipe_resource *template = &srf->template; + struct pipe_resource *texture; + struct pipe_box src_box; + struct xa_tracker *xa = srf->xa; + int save_width; + int save_height; + unsigned int save_format; + struct xa_format_descriptor fdesc; + + + if (xa_format == xa_format_unknown) + fdesc = xa_get_format_stype_depth(xa, stype, depth); + else + fdesc = xa_get_pipe_format(xa, xa_format); + + if (width == template->width0 && height == template->height0 && + template->format == fdesc.format && + xa_flags_compat(srf->flags, new_flags)) + return XA_ERR_NONE; + + template->bind = stype_bind[xa_format_type(fdesc.xa_format)]; + if (new_flags & XA_FLAG_SHARED) + template->bind |= PIPE_BIND_SHARED; + if (new_flags & XA_FLAG_RENDER_TARGET) + template->bind |= PIPE_BIND_RENDER_TARGET; + if (new_flags & XA_FLAG_SCANOUT) + template->bind |= PIPE_BIND_SCANOUT; + + if (copy_contents) { + if (!xa_format_type_is_color(fdesc.xa_format) || + xa_format_type(fdesc.xa_format) == xa_type_a) + return -XA_ERR_INVAL; + + if (!xa->screen->is_format_supported(xa->screen, fdesc.format, + PIPE_TEXTURE_2D, 0, 0, + template->bind | + PIPE_BIND_RENDER_TARGET)) + return -XA_ERR_INVAL; + } + + save_width = template->width0; + save_height = template->height0; + save_format = template->format; + + template->width0 = width; + template->height0 = height; + template->format = fdesc.format; + + texture = xa->screen->resource_create(xa->screen, template); + if (!texture) { + template->width0 = save_width; + template->height0 = save_height; + template->format = save_format; + return -XA_ERR_NORES; + } + + if (copy_contents) { + struct pipe_context *pipe = xa->default_ctx->pipe; + + u_box_origin_2d(xa_min(save_width, template->width0), + xa_min(save_height, template->height0), &src_box); + pipe->resource_copy_region(pipe, texture, + 0, 0, 0, 0, srf->tex, 0, &src_box); + xa_context_flush(xa->default_ctx); + } + + pipe_resource_reference(&srf->tex, texture); + pipe_resource_reference(&texture, NULL); + srf->fdesc = fdesc; + srf->flags = new_flags; + + return XA_ERR_NONE; +} + +XA_EXPORT struct xa_surface* +xa_surface_ref(struct xa_surface *srf) +{ + if (srf == NULL) { + return NULL; + } + srf->refcount++; + return srf; +} + +XA_EXPORT void +xa_surface_unref(struct xa_surface *srf) +{ + if (srf == NULL || --srf->refcount) { + return; + } + pipe_resource_reference(&srf->tex, NULL); + free(srf); +} + +XA_EXPORT void +xa_tracker_version(int *major, int *minor, int *patch) +{ + *major = XA_TRACKER_VERSION_MAJOR; + *minor = XA_TRACKER_VERSION_MINOR; + *patch = XA_TRACKER_VERSION_PATCH; +} + +XA_EXPORT int +xa_surface_handle(struct xa_surface *srf, + enum xa_handle_type type, + uint32_t * handle, unsigned int *stride) +{ + struct winsys_handle whandle; + + struct pipe_screen *screen = srf->xa->screen; + boolean res; + + memset(&whandle, 0, sizeof(whandle)); + whandle.type = handle_type(type); + res = screen->resource_get_handle(screen, srf->xa->default_ctx->pipe, + srf->tex, &whandle, + PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE); + if (!res) + return -XA_ERR_INVAL; + + *handle = whandle.handle; + *stride = whandle.stride; + + return XA_ERR_NONE; +} + +XA_EXPORT enum xa_formats +xa_surface_format(const struct xa_surface *srf) +{ + return srf->fdesc.xa_format; +} diff --git a/src/gallium/frontends/xa/xa_tracker.h.in b/src/gallium/frontends/xa/xa_tracker.h.in new file mode 100644 index 00000000000..3d136707152 --- /dev/null +++ b/src/gallium/frontends/xa/xa_tracker.h.in @@ -0,0 +1,217 @@ +/********************************************************** + * Copyright 2009-2011 VMware, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * The format encoding idea is partially borrowed from libpixman, but it is not + * considered a "substantial part of the software", so the pixman copyright + * is left out for simplicity, and acknowledgment is instead given in this way. + * + ********************************************************* + * Authors: + * Zack Rusin + * Thomas Hellstrom + */ + +#ifndef _XA_TRACKER_H_ +#define _XA_TRACKER_H_ + +#include + +#define XA_TRACKER_VERSION_MAJOR @XA_MAJOR@ +#define XA_TRACKER_VERSION_MINOR @XA_MINOR@ +#define XA_TRACKER_VERSION_PATCH @XA_PATCH@ + +#define XA_FLAG_SHARED (1 << 0) +#define XA_FLAG_RENDER_TARGET (1 << 1) +#define XA_FLAG_SCANOUT (1 << 2) + +#define XA_MAP_READ (1 << 0) +#define XA_MAP_WRITE (1 << 1) +#define XA_MAP_MAP_DIRECTLY (1 << 2) +#define XA_MAP_UNSYNCHRONIZED (1 << 3) +#define XA_MAP_DONTBLOCK (1 << 4) +#define XA_MAP_DISCARD_WHOLE_RESOURCE (1 << 5) + +#define XA_ERR_NONE 0 +#define XA_ERR_NORES 1 +#define XA_ERR_INVAL 2 +#define XA_ERR_BUSY 3 + +enum xa_surface_type { + xa_type_other, + xa_type_a, + xa_type_argb, + xa_type_abgr, + xa_type_bgra, + xa_type_z, + xa_type_zs, + xa_type_sz, + xa_type_yuv_component +}; + +/* + * Note that these formats should not be assumed to be binary compatible with + * pixman formats, but with the below macros and a format type map, + * conversion should be simple. Macros for now. We might replace with + * inline functions. + */ + +#define xa_format(bpp,type,a,r,g,b) (((bpp) << 24) | \ + ((type) << 16) | \ + ((a) << 12) | \ + ((r) << 8) | \ + ((g) << 4) | \ + ((b))) +/* + * Non-RGBA one- and two component formats. + */ + +#define xa_format_c(bpp,type,c1,c2) (((bpp) << 24) | \ + ((type) << 16) | \ + ((c1) << 8) | \ + ((c2))) +#define xa_format_bpp(f) (((f) >> 24) ) +#define xa_format_type(f) (((f) >> 16) & 0xff) +#define xa_format_a(f) (((f) >> 12) & 0x0f) +#define xa_format_r(f) (((f) >> 8) & 0x0f) +#define xa_format_g(f) (((f) >> 4) & 0x0f) +#define xa_format_b(f) (((f) ) & 0x0f) +#define xa_format_rgb(f) (((f) ) & 0xfff) +#define xa_format_c1(f) (((f) >> 8 ) & 0xff) +#define xa_format_c2(f) (((f) ) & 0xff) +#define xa_format_argb_depth(f) (xa_format_a(f) + \ + xa_format_r(f) + \ + xa_format_g(f) + \ + xa_format_b(f)) +#define xa_format_c_depth(f) (xa_format_c1(f) + \ + xa_format_c2(f)) + +static inline int +xa_format_type_is_color(uint32_t xa_format) +{ + return (xa_format_type(xa_format) < xa_type_z); +} + +static inline unsigned int +xa_format_depth(uint32_t xa_format) +{ + return ((xa_format_type_is_color(xa_format)) ? + xa_format_argb_depth(xa_format) : xa_format_c_depth(xa_format)); +} + +enum xa_formats { + xa_format_unknown = 0, + xa_format_a8 = xa_format(8, xa_type_a, 8, 0, 0, 0), + + xa_format_a8r8g8b8 = xa_format(32, xa_type_argb, 8, 8, 8, 8), + xa_format_x8r8g8b8 = xa_format(32, xa_type_argb, 0, 8, 8, 8), + xa_format_r5g6b5 = xa_format(16, xa_type_argb, 0, 5, 6, 5), + xa_format_x1r5g5b5 = xa_format(16, xa_type_argb, 0, 5, 5, 5), + xa_format_a4r4g4b4 = xa_format(16, xa_type_argb, 4, 4, 4, 4), + xa_format_a2b10g10r10 = xa_format(32, xa_type_abgr, 2, 10, 10, 10), + xa_format_x2b10g10r10 = xa_format(32, xa_type_abgr, 0, 10, 10, 10), + xa_format_b8g8r8a8 = xa_format(32, xa_type_bgra, 8, 8, 8, 8), + xa_format_b8g8r8x8 = xa_format(32, xa_type_bgra, 0, 8, 8, 8), + + xa_format_z16 = xa_format_c(16, xa_type_z, 16, 0), + xa_format_z32 = xa_format_c(32, xa_type_z, 32, 0), + xa_format_z24 = xa_format_c(32, xa_type_z, 24, 0), + + xa_format_x8z24 = xa_format_c(32, xa_type_sz, 24, 0), + xa_format_s8z24 = xa_format_c(32, xa_type_sz, 24, 8), + xa_format_z24x8 = xa_format_c(32, xa_type_zs, 24, 0), + xa_format_z24s8 = xa_format_c(32, xa_type_zs, 24, 8), + + xa_format_yuv8 = xa_format_c(8, xa_type_yuv_component, 8, 0) +}; + +struct xa_tracker; +struct xa_surface; + +struct xa_box { + uint16_t x1, y1, x2, y2; +}; + +enum xa_handle_type { + xa_handle_type_shared, + xa_handle_type_kms, + xa_handle_type_fd, +}; + +extern void xa_tracker_version(int *major, int *minor, int *patch); + +extern struct xa_tracker *xa_tracker_create(int drm_fd); + +extern void xa_tracker_destroy(struct xa_tracker *xa); + +extern int xa_format_check_supported(struct xa_tracker *xa, + enum xa_formats xa_format, + unsigned int flags); + +extern struct xa_surface *xa_surface_create(struct xa_tracker *xa, + int width, + int height, + int depth, + enum xa_surface_type stype, + enum xa_formats pform, + unsigned int flags); + +extern struct xa_surface * xa_surface_from_handle(struct xa_tracker *xa, + int width, + int height, + int depth, + enum xa_surface_type stype, + enum xa_formats pform, + unsigned int flags, + uint32_t handle, uint32_t stride); +extern struct xa_surface * +xa_surface_from_handle2(struct xa_tracker *xa, + int width, + int height, + int depth, + enum xa_surface_type stype, + enum xa_formats xa_format, + unsigned int flags, + enum xa_handle_type type, + uint32_t handle, + uint32_t stride); + +enum xa_formats xa_surface_format(const struct xa_surface *srf); + +extern struct xa_surface *xa_surface_ref(struct xa_surface *srf); +extern void xa_surface_unref(struct xa_surface *srf); + +extern int xa_surface_redefine(struct xa_surface *srf, + int width, + int height, + int depth, + enum xa_surface_type stype, + enum xa_formats rgb_format, + unsigned int new_flags, + int copy_contents); + +extern int xa_surface_handle(struct xa_surface *srf, + enum xa_handle_type type, + uint32_t * handle, + unsigned int *byte_stride); + +#endif diff --git a/src/gallium/frontends/xa/xa_yuv.c b/src/gallium/frontends/xa/xa_yuv.c new file mode 100644 index 00000000000..97a1833ff15 --- /dev/null +++ b/src/gallium/frontends/xa/xa_yuv.c @@ -0,0 +1,163 @@ +/********************************************************** + * Copyright 2009-2011 VMware, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + ********************************************************* + * Authors: + * Zack Rusin + * Thomas Hellstrom + */ + +#include "xa_context.h" +#include "xa_priv.h" +#include "util/u_inlines.h" +#include "util/u_sampler.h" +#include "util/u_surface.h" +#include "cso_cache/cso_context.h" + +static void +xa_yuv_bind_blend_state(struct xa_context *r) +{ + struct pipe_blend_state blend; + + memset(&blend, 0, sizeof(struct pipe_blend_state)); + blend.rt[0].blend_enable = 0; + blend.rt[0].colormask = PIPE_MASK_RGBA; + + /* porter&duff src */ + blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; + + cso_set_blend(r->cso, &blend); +} + +static void +xa_yuv_bind_shaders(struct xa_context *r) +{ + unsigned vs_traits = 0, fs_traits = 0; + struct xa_shader shader; + + vs_traits |= VS_YUV; + fs_traits |= FS_YUV; + + shader = xa_shaders_get(r->shaders, vs_traits, fs_traits); + cso_set_vertex_shader_handle(r->cso, shader.vs); + cso_set_fragment_shader_handle(r->cso, shader.fs); +} + +static void +xa_yuv_bind_samplers(struct xa_context *r, struct xa_surface *yuv[]) +{ + struct pipe_sampler_state *samplers[3]; + struct pipe_sampler_state sampler; + struct pipe_sampler_view view_templ; + unsigned int i; + + memset(&sampler, 0, sizeof(struct pipe_sampler_state)); + + sampler.wrap_s = PIPE_TEX_WRAP_CLAMP; + sampler.wrap_t = PIPE_TEX_WRAP_CLAMP; + sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR; + sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR; + sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST; + sampler.normalized_coords = 1; + + for (i = 0; i < 3; ++i) { + samplers[i] = &sampler; + u_sampler_view_default_template(&view_templ, yuv[i]->tex, + yuv[i]->tex->format); + + r->bound_sampler_views[i] = + r->pipe->create_sampler_view(r->pipe, yuv[i]->tex, &view_templ); + } + r->num_bound_samplers = 3; + cso_set_samplers(r->cso, PIPE_SHADER_FRAGMENT, 3, (const struct pipe_sampler_state **)samplers); + cso_set_sampler_views(r->cso, PIPE_SHADER_FRAGMENT, 3, r->bound_sampler_views); +} + +static void +xa_yuv_fs_constants(struct xa_context *r, const float conversion_matrix[]) +{ + const int param_bytes = 16 * sizeof(float); + + renderer_set_constants(r, PIPE_SHADER_FRAGMENT, + conversion_matrix, param_bytes); +} + +XA_EXPORT int +xa_yuv_planar_blit(struct xa_context *r, + int src_x, + int src_y, + int src_w, + int src_h, + int dst_x, + int dst_y, + int dst_w, + int dst_h, + struct xa_box *box, + unsigned int num_boxes, + const float conversion_matrix[], + struct xa_surface *dst, struct xa_surface *yuv[]) +{ + float scale_x; + float scale_y; + int ret; + + if (dst_w == 0 || dst_h == 0) + return XA_ERR_NONE; + + ret = xa_ctx_srf_create(r, dst); + if (ret != XA_ERR_NONE) + return -XA_ERR_NORES; + + renderer_bind_destination(r, r->srf); + xa_yuv_bind_blend_state(r); + xa_yuv_bind_shaders(r); + xa_yuv_bind_samplers(r, yuv); + xa_yuv_fs_constants(r, conversion_matrix); + + scale_x = (float)src_w / (float)dst_w; + scale_y = (float)src_h / (float)dst_h; + + while (num_boxes--) { + int x = box->x1; + int y = box->y1; + int w = box->x2 - box->x1; + int h = box->y2 - box->y1; + + xa_scissor_update(r, x, y, box->x2, box->y2); + renderer_draw_yuv(r, + (float)src_x + scale_x * (x - dst_x), + (float)src_y + scale_y * (y - dst_y), + scale_x * w, scale_y * h, x, y, w, h, yuv); + box++; + } + + xa_context_flush(r); + + xa_ctx_sampler_views_destroy(r); + xa_ctx_srf_destroy(r); + + return XA_ERR_NONE; +} diff --git a/src/gallium/frontends/xvmc/Makefile.sources b/src/gallium/frontends/xvmc/Makefile.sources new file mode 100644 index 00000000000..814357bf25d --- /dev/null +++ b/src/gallium/frontends/xvmc/Makefile.sources @@ -0,0 +1,7 @@ +C_SOURCES := \ + attributes.c \ + block.c \ + context.c \ + surface.c \ + subpicture.c \ + xvmc_private.h diff --git a/src/gallium/frontends/xvmc/attributes.c b/src/gallium/frontends/xvmc/attributes.c new file mode 100644 index 00000000000..6e4d78a9a29 --- /dev/null +++ b/src/gallium/frontends/xvmc/attributes.c @@ -0,0 +1,153 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include +#include + +#include +#include +#include + +#include "vl/vl_compositor.h" + +#include "xvmc_private.h" + +#define XV_BRIGHTNESS "XV_BRIGHTNESS" +#define XV_CONTRAST "XV_CONTRAST" +#define XV_SATURATION "XV_SATURATION" +#define XV_HUE "XV_HUE" +#define XV_COLORSPACE "XV_COLORSPACE" + +static const XvAttribute attributes[] = { + { XvGettable | XvSettable, -1000, 1000, XV_BRIGHTNESS }, + { XvGettable | XvSettable, -1000, 1000, XV_CONTRAST }, + { XvGettable | XvSettable, -1000, 1000, XV_SATURATION }, + { XvGettable | XvSettable, -1000, 1000, XV_HUE }, + { XvGettable | XvSettable, 0, 1, XV_COLORSPACE } +}; + +PUBLIC +XvAttribute* XvMCQueryAttributes(Display *dpy, XvMCContext *context, int *number) +{ + XvAttribute *result; + + assert(dpy && number); + + if (!context || !context->privData) + return NULL; + + result = malloc(sizeof(attributes)); + if (!result) + return NULL; + + memcpy(result, attributes, sizeof(attributes)); + *number = sizeof(attributes) / sizeof(XvAttribute); + + XVMC_MSG(XVMC_TRACE, "[XvMC] Returning %d attributes for context %p.\n", *number, context); + + return result; +} + +PUBLIC +Status XvMCSetAttribute(Display *dpy, XvMCContext *context, Atom attribute, int value) +{ + XvMCContextPrivate *context_priv; + const char *attr; + vl_csc_matrix csc; + + assert(dpy); + + if (!context || !context->privData) + return XvMCBadContext; + + context_priv = context->privData; + + attr = XGetAtomName(dpy, attribute); + if (!attr) + return XvMCBadContext; + + if (strcmp(attr, XV_BRIGHTNESS) == 0) + context_priv->procamp.brightness = value / 1000.0f; + else if (strcmp(attr, XV_CONTRAST) == 0) + context_priv->procamp.contrast = value / 1000.0f + 1.0f; + else if (strcmp(attr, XV_SATURATION) == 0) + context_priv->procamp.saturation = value / 1000.0f + 1.0f; + else if (strcmp(attr, XV_HUE) == 0) + context_priv->procamp.hue = value / 1000.0f; + else if (strcmp(attr, XV_COLORSPACE) == 0) + context_priv->color_standard = value ? + VL_CSC_COLOR_STANDARD_BT_601 : + VL_CSC_COLOR_STANDARD_BT_709; + else + return BadName; + + vl_csc_get_matrix + ( + context_priv->color_standard, + &context_priv->procamp, true, &csc + ); + vl_compositor_set_csc_matrix(&context_priv->cstate, (const vl_csc_matrix *)&csc, 1.0f, 0.0f); + + XVMC_MSG(XVMC_TRACE, "[XvMC] Set attribute %s to value %d.\n", attr, value); + + return Success; +} + +PUBLIC +Status XvMCGetAttribute(Display *dpy, XvMCContext *context, Atom attribute, int *value) +{ + XvMCContextPrivate *context_priv; + const char *attr; + + assert(dpy); + + if (!context || !context->privData) + return XvMCBadContext; + + context_priv = context->privData; + + attr = XGetAtomName(dpy, attribute); + if (!attr) + return XvMCBadContext; + + if (strcmp(attr, XV_BRIGHTNESS) == 0) + *value = context_priv->procamp.brightness * 1000; + else if (strcmp(attr, XV_CONTRAST) == 0) + *value = context_priv->procamp.contrast * 1000 - 1000; + else if (strcmp(attr, XV_SATURATION) == 0) + *value = context_priv->procamp.saturation * 1000 + 1000; + else if (strcmp(attr, XV_HUE) == 0) + *value = context_priv->procamp.hue * 1000; + else if (strcmp(attr, XV_COLORSPACE) == 0) + *value = context_priv->color_standard == VL_CSC_COLOR_STANDARD_BT_709; + else + return BadName; + + XVMC_MSG(XVMC_TRACE, "[XvMC] Got value %d for attribute %s.\n", *value, attr); + + return Success; +} diff --git a/src/gallium/frontends/xvmc/block.c b/src/gallium/frontends/xvmc/block.c new file mode 100644 index 00000000000..80296280247 --- /dev/null +++ b/src/gallium/frontends/xvmc/block.c @@ -0,0 +1,95 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include + +#include +#include + +#include "util/u_memory.h" + +#include "xvmc_private.h" + +PUBLIC +Status XvMCCreateBlocks(Display *dpy, XvMCContext *context, unsigned int num_blocks, XvMCBlockArray *blocks) +{ + assert(dpy); + + if (!context) + return XvMCBadContext; + if (num_blocks == 0) + return BadValue; + + assert(blocks); + + blocks->context_id = context->context_id; + blocks->num_blocks = num_blocks; + blocks->blocks = MALLOC(BLOCK_SIZE_BYTES * num_blocks); + blocks->privData = NULL; + + return Success; +} + +PUBLIC +Status XvMCDestroyBlocks(Display *dpy, XvMCBlockArray *blocks) +{ + assert(dpy); + assert(blocks); + FREE(blocks->blocks); + + return Success; +} + +PUBLIC +Status XvMCCreateMacroBlocks(Display *dpy, XvMCContext *context, unsigned int num_blocks, XvMCMacroBlockArray *blocks) +{ + assert(dpy); + + if (!context) + return XvMCBadContext; + if (num_blocks == 0) + return BadValue; + + assert(blocks); + + blocks->context_id = context->context_id; + blocks->num_blocks = num_blocks; + blocks->macro_blocks = MALLOC(sizeof(XvMCMacroBlock) * num_blocks); + blocks->privData = NULL; + + return Success; +} + +PUBLIC +Status XvMCDestroyMacroBlocks(Display *dpy, XvMCMacroBlockArray *blocks) +{ + assert(dpy); + assert(blocks); + FREE(blocks->macro_blocks); + + return Success; +} diff --git a/src/gallium/frontends/xvmc/context.c b/src/gallium/frontends/xvmc/context.c new file mode 100644 index 00000000000..1ecff5e8ac1 --- /dev/null +++ b/src/gallium/frontends/xvmc/context.c @@ -0,0 +1,344 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include + +#include +#include + +#include "pipe/p_screen.h" +#include "pipe/p_video_codec.h" +#include "pipe/p_video_state.h" +#include "pipe/p_state.h" + +#include "util/u_memory.h" + +#include "vl/vl_csc.h" +#include "vl/vl_winsys.h" + +#include "xvmc_private.h" + +static Status Validate(Display *dpy, XvPortID port, int surface_type_id, + unsigned int width, unsigned int height, int flags, + bool *found_port, int *screen, int *chroma_format, + int *mc_type, int *surface_flags, + unsigned short *subpic_max_w, + unsigned short *subpic_max_h) +{ + bool found_surface = false; + XvAdaptorInfo *adaptor_info; + unsigned int num_adaptors; + int num_types; + unsigned int max_width = 0, max_height = 0; + Status ret; + + assert(dpy); + assert(found_port); + assert(screen); + assert(chroma_format); + assert(mc_type); + assert(surface_flags); + assert(subpic_max_w); + assert(subpic_max_h); + + *found_port = false; + + for (int i = 0; i < XScreenCount(dpy); ++i) { + ret = XvQueryAdaptors(dpy, XRootWindow(dpy, i), &num_adaptors, &adaptor_info); + if (ret != Success) + return ret; + + for (unsigned int j = 0; j < num_adaptors && !*found_port; ++j) { + for (unsigned int k = 0; k < adaptor_info[j].num_ports && !*found_port; ++k) { + XvMCSurfaceInfo *surface_info; + + if (adaptor_info[j].base_id + k != port) + continue; + + *found_port = true; + + surface_info = XvMCListSurfaceTypes(dpy, adaptor_info[j].base_id, &num_types); + if (!surface_info) { + XvFreeAdaptorInfo(adaptor_info); + return BadAlloc; + } + + for (int l = 0; l < num_types && !found_surface; ++l) { + if (surface_info[l].surface_type_id != surface_type_id) + continue; + + found_surface = true; + max_width = surface_info[l].max_width; + max_height = surface_info[l].max_height; + *chroma_format = surface_info[l].chroma_format; + *mc_type = surface_info[l].mc_type; + *surface_flags = surface_info[l].flags; + *subpic_max_w = surface_info[l].subpicture_max_width; + *subpic_max_h = surface_info[l].subpicture_max_height; + *screen = i; + + XVMC_MSG(XVMC_TRACE, "[XvMC] Found requested context surface format.\n" \ + "[XvMC] screen=%u, port=%u\n" \ + "[XvMC] id=0x%08X\n" \ + "[XvMC] max width=%u, max height=%u\n" \ + "[XvMC] chroma format=0x%08X\n" \ + "[XvMC] acceleration level=0x%08X\n" \ + "[XvMC] flags=0x%08X\n" \ + "[XvMC] subpicture max width=%u, max height=%u\n", + i, port, surface_type_id, max_width, max_height, *chroma_format, + *mc_type, *surface_flags, *subpic_max_w, *subpic_max_h); + } + + free(surface_info); + } + } + + XvFreeAdaptorInfo(adaptor_info); + } + + if (!*found_port) { + XVMC_MSG(XVMC_ERR, "[XvMC] Could not find a suitable port.\n"); + return XvBadPort; + } + if (!found_surface) { + XVMC_MSG(XVMC_ERR, "[XvMC] Could not find a suitable surface.\n"); + return BadMatch; + } + if (width > max_width || height > max_height) { + XVMC_MSG(XVMC_ERR, "[XvMC] Requested context dimensions (w=%u,h=%u) too large (max w=%u,h=%u).\n", + width, height, max_width, max_height); + return BadValue; + } + if (flags != XVMC_DIRECT && flags != 0) { + XVMC_MSG(XVMC_ERR, "[XvMC] Invalid context flags 0x%08X.\n", flags); + return BadValue; + } + + return Success; +} + +static enum pipe_video_profile ProfileToPipe(int xvmc_profile) +{ + if (xvmc_profile & XVMC_MPEG_1) + assert(0); + if (xvmc_profile & XVMC_MPEG_2) + return PIPE_VIDEO_PROFILE_MPEG2_MAIN; + if (xvmc_profile & XVMC_H263) + assert(0); + if (xvmc_profile & XVMC_MPEG_4) + assert(0); + + assert(0); + + XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized profile 0x%08X.\n", xvmc_profile); + + return -1; +} + +static enum pipe_video_chroma_format FormatToPipe(int xvmc_format) +{ + switch (xvmc_format) { + case XVMC_CHROMA_FORMAT_420: + return PIPE_VIDEO_CHROMA_FORMAT_420; + case XVMC_CHROMA_FORMAT_422: + return PIPE_VIDEO_CHROMA_FORMAT_422; + case XVMC_CHROMA_FORMAT_444: + return PIPE_VIDEO_CHROMA_FORMAT_444; + default: + assert(0); + } + + XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized format 0x%08X.\n", xvmc_format); + + return -1; +} + +PUBLIC +Status XvMCCreateContext(Display *dpy, XvPortID port, int surface_type_id, + int width, int height, int flags, XvMCContext *context) +{ + bool found_port; + int scrn = 0; + int chroma_format = 0; + int mc_type = 0; + int surface_flags = 0; + unsigned short subpic_max_w = 0; + unsigned short subpic_max_h = 0; + Status ret; + struct vl_screen *vscreen; + struct pipe_context *pipe; + struct pipe_video_codec templat = {0}; + XvMCContextPrivate *context_priv; + vl_csc_matrix csc; + + XVMC_MSG(XVMC_TRACE, "[XvMC] Creating context %p.\n", context); + + assert(dpy); + + if (!context) + return XvMCBadContext; + + ret = Validate(dpy, port, surface_type_id, width, height, flags, + &found_port, &scrn, &chroma_format, &mc_type, &surface_flags, + &subpic_max_w, &subpic_max_h); + + /* Success and XvBadPort have the same value */ + if (ret != Success || !found_port) + return ret; + + /* XXX: Current limits */ + if (chroma_format != XVMC_CHROMA_FORMAT_420) { + XVMC_MSG(XVMC_ERR, "[XvMC] Cannot decode requested surface type. Unsupported chroma format.\n"); + return BadImplementation; + } + if ((mc_type & ~XVMC_IDCT) != (XVMC_MOCOMP | XVMC_MPEG_2)) { + XVMC_MSG(XVMC_ERR, "[XvMC] Cannot decode requested surface type. Non-MPEG2/Mocomp/iDCT acceleration unsupported.\n"); + return BadImplementation; + } + if (surface_flags & XVMC_INTRA_UNSIGNED) { + XVMC_MSG(XVMC_ERR, "[XvMC] Cannot decode requested surface type. Unsigned intra unsupported.\n"); + return BadImplementation; + } + + context_priv = CALLOC(1, sizeof(XvMCContextPrivate)); + if (!context_priv) + return BadAlloc; + + /* TODO: Reuse screen if process creates another context */ + vscreen = vl_dri3_screen_create(dpy, scrn); + if (!vscreen) + vscreen = vl_dri2_screen_create(dpy, scrn); + + if (!vscreen) { + XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL screen.\n"); + FREE(context_priv); + return BadAlloc; + } + + pipe = vscreen->pscreen->context_create(vscreen->pscreen, NULL, 0); + if (!pipe) { + XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL context.\n"); + vscreen->destroy(vscreen); + FREE(context_priv); + return BadAlloc; + } + + templat.profile = ProfileToPipe(mc_type); + templat.entrypoint = (mc_type & XVMC_IDCT) ? PIPE_VIDEO_ENTRYPOINT_IDCT : PIPE_VIDEO_ENTRYPOINT_MC; + templat.chroma_format = FormatToPipe(chroma_format); + templat.width = width; + templat.height = height; + templat.max_references = 2; + templat.expect_chunked_decode = true; + + context_priv->decoder = pipe->create_video_codec(pipe, &templat); + + if (!context_priv->decoder) { + XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL decoder.\n"); + pipe->destroy(pipe); + vscreen->destroy(vscreen); + FREE(context_priv); + return BadAlloc; + } + + if (!vl_compositor_init(&context_priv->compositor, pipe)) { + XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL compositor.\n"); + context_priv->decoder->destroy(context_priv->decoder); + pipe->destroy(pipe); + vscreen->destroy(vscreen); + FREE(context_priv); + return BadAlloc; + } + + if (!vl_compositor_init_state(&context_priv->cstate, pipe)) { + XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL compositor state.\n"); + vl_compositor_cleanup(&context_priv->compositor); + context_priv->decoder->destroy(context_priv->decoder); + pipe->destroy(pipe); + vscreen->destroy(vscreen); + FREE(context_priv); + return BadAlloc; + } + + + context_priv->color_standard = + debug_get_bool_option("G3DVL_NO_CSC", FALSE) ? + VL_CSC_COLOR_STANDARD_IDENTITY : VL_CSC_COLOR_STANDARD_BT_601; + context_priv->procamp = vl_default_procamp; + + vl_csc_get_matrix + ( + context_priv->color_standard, + &context_priv->procamp, true, &csc + ); + vl_compositor_set_csc_matrix(&context_priv->cstate, (const vl_csc_matrix *)&csc, 1.0f, 0.0f); + + context_priv->vscreen = vscreen; + context_priv->pipe = pipe; + context_priv->subpicture_max_width = subpic_max_w; + context_priv->subpicture_max_height = subpic_max_h; + + context->context_id = XAllocID(dpy); + context->surface_type_id = surface_type_id; + context->width = width; + context->height = height; + context->flags = flags; + context->port = port; + context->privData = context_priv; + + SyncHandle(); + + XVMC_MSG(XVMC_TRACE, "[XvMC] Context %p created.\n", context); + + return Success; +} + +PUBLIC +Status XvMCDestroyContext(Display *dpy, XvMCContext *context) +{ + XvMCContextPrivate *context_priv; + + XVMC_MSG(XVMC_TRACE, "[XvMC] Destroying context %p.\n", context); + + assert(dpy); + + if (!context || !context->privData) + return XvMCBadContext; + + context_priv = context->privData; + context_priv->decoder->destroy(context_priv->decoder); + vl_compositor_cleanup_state(&context_priv->cstate); + vl_compositor_cleanup(&context_priv->compositor); + context_priv->pipe->destroy(context_priv->pipe); + context_priv->vscreen->destroy(context_priv->vscreen); + FREE(context_priv); + context->privData = NULL; + + XVMC_MSG(XVMC_TRACE, "[XvMC] Context %p destroyed.\n", context); + + return Success; +} diff --git a/src/gallium/frontends/xvmc/meson.build b/src/gallium/frontends/xvmc/meson.build new file mode 100644 index 00000000000..9022bf4d0a6 --- /dev/null +++ b/src/gallium/frontends/xvmc/meson.build @@ -0,0 +1,63 @@ +# Copyright © 2017, 2019 Intel Corporation + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +libxvmc_st = static_library( + 'xvmc_st', + files('attributes.c', 'block.c', 'context.c', 'surface.c', 'subpicture.c'), + c_args : [c_vis_args], + include_directories : [inc_include, inc_src, inc_mapi, inc_mesa, inc_gallium, inc_gallium_aux], + dependencies : [ + dep_xvmc, dep_x11_xcb, dep_xcb, dep_xcb_dri2, dep_xcb_dri3, dep_xv, + dep_libdrm, + ], +) + +# These tests will not work without a working xvmc configuration. +if with_tools.contains('xvmc') + # pkg-config was added in 1.0.12, so allow fallback + dep_xvmcw = dependency('xvmc-wrapper', required : false) + if not dep_xvmcw.found() + dep_xvmcw = cc.find_library('XvMCW') + endif + dep_real_xvmc = dependency('xvmc') + + foreach x : ['context', 'surface', 'subpicture', 'blocks', 'rendering'] + _name = 'xvmc_@0@'.format(x) + executable( + _name, + files('tests/test_@0@.c'.format(x), 'tests/testlib.c'), + dependencies : [ + dep_real_xvmc, dep_x11_xcb, dep_xcb, dep_xcb_dri2, dep_xcb_dri3, + dep_xvmcw, dep_xv, + ], + install: true, + ) + endforeach + + executable( + 'xvmc_bench', + files('tests/xvmc_bench.c', 'tests/testlib.c'), + dependencies : [ + dep_real_xvmc, dep_x11_xcb, dep_xcb, dep_xcb_dri2, dep_xcb_dri3, + dep_xvmcw, dep_xv, + ], + install: true, + ) +endif diff --git a/src/gallium/frontends/xvmc/subpicture.c b/src/gallium/frontends/xvmc/subpicture.c new file mode 100644 index 00000000000..42eefe74e69 --- /dev/null +++ b/src/gallium/frontends/xvmc/subpicture.c @@ -0,0 +1,602 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include + +#include +#include + +#include "pipe/p_screen.h" +#include "pipe/p_video_codec.h" +#include "pipe/p_state.h" + +#include "util/u_memory.h" +#include "util/u_math.h" +#include "util/format/u_format.h" +#include "util/u_sampler.h" +#include "util/u_surface.h" +#include "util/u_rect.h" +#include "vl/vl_winsys.h" + +#include "xvmc_private.h" + +#define FOURCC_RGB 0x0000003 +#define FOURCC_AI44 0x34344941 +#define FOURCC_IA44 0x34344149 + +static enum pipe_format XvIDToPipe(struct pipe_screen *screen, + int xvimage_id) +{ + enum pipe_format ret; + assert(screen); + + switch (xvimage_id) { + case FOURCC_RGB: + ret = PIPE_FORMAT_B8G8R8X8_UNORM; + break; + + case FOURCC_AI44: + ret = PIPE_FORMAT_R4A4_UNORM; + if (!screen->is_format_supported( + screen, ret, PIPE_TEXTURE_2D, 0, 0, PIPE_BIND_SAMPLER_VIEW)) + ret = PIPE_FORMAT_B4G4R4A4_UNORM; + break; + + case FOURCC_IA44: + ret = PIPE_FORMAT_A4R4_UNORM; + if (!screen->is_format_supported( + screen, ret, PIPE_TEXTURE_2D, 0, 0, PIPE_BIND_SAMPLER_VIEW)) + ret = PIPE_FORMAT_B4G4R4A4_UNORM; + break; + + default: + XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized Xv image ID 0x%08X.\n", xvimage_id); + return PIPE_FORMAT_NONE; + } + + if (!screen->is_format_supported( + screen, ret, PIPE_TEXTURE_2D, 0, 0, PIPE_BIND_SAMPLER_VIEW)) { + XVMC_MSG(XVMC_ERR, "[XvMC] Unsupported 2D format %s for Xv image ID 0x%08X.\n", util_format_name(ret), xvimage_id); + ret = PIPE_FORMAT_NONE; + } + return ret; + +} + +static unsigned NumPaletteEntries4XvID(int xvimage_id) +{ + switch (xvimage_id) { + case FOURCC_RGB: + return 0; + + case FOURCC_AI44: + case FOURCC_IA44: + return 16; + + default: + XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized Xv image ID 0x%08X.\n", xvimage_id); + return 0; + } +} + +static int PipeToComponentOrder(struct pipe_screen *screen, + enum pipe_format format, + enum pipe_format *palette_format, + char *component_order) +{ + assert(screen); + assert(component_order); + assert(palette_format); + + switch (format) { + case PIPE_FORMAT_B8G8R8X8_UNORM: + return 0; + + case PIPE_FORMAT_A4R4_UNORM: + case PIPE_FORMAT_R4A4_UNORM: + case PIPE_FORMAT_B4G4R4A4_UNORM: + *palette_format = PIPE_FORMAT_R8G8B8X8_UNORM; + component_order[0] = 'Y'; + component_order[1] = 'U'; + component_order[2] = 'V'; + component_order[3] = 'A'; + if (!screen->is_format_supported( + screen, *palette_format, PIPE_TEXTURE_1D, 0, 0, + PIPE_BIND_SAMPLER_VIEW)) { + /* One of these formats better be supported... */ + *palette_format = PIPE_FORMAT_B8G8R8X8_UNORM; + component_order[0] = 'V'; + component_order[2] = 'Y'; + } + return 4; + + default: + XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized PIPE_FORMAT 0x%08X.\n", format); + component_order[0] = 0; + component_order[1] = 0; + component_order[2] = 0; + component_order[3] = 0; + return 0; + } +} + +static Status Validate(Display *dpy, XvPortID port, int surface_type_id, int xvimage_id) +{ + XvImageFormatValues *subpictures; + int num_subpics; + int i; + + subpictures = XvMCListSubpictureTypes(dpy, port, surface_type_id, &num_subpics); + if (num_subpics < 1) { + free(subpictures); + return BadMatch; + } + if (!subpictures) + return BadAlloc; + + for (i = 0; i < num_subpics; ++i) { + if (subpictures[i].id == xvimage_id) { + XVMC_MSG(XVMC_TRACE, "[XvMC] Found requested subpicture format.\n" \ + "[XvMC] port=%u\n" \ + "[XvMC] surface id=0x%08X\n" \ + "[XvMC] image id=0x%08X\n" \ + "[XvMC] type=%08X\n" \ + "[XvMC] byte order=%08X\n" \ + "[XvMC] bits per pixel=%u\n" \ + "[XvMC] format=%08X\n" \ + "[XvMC] num planes=%d\n", + port, surface_type_id, xvimage_id, subpictures[i].type, subpictures[i].byte_order, + subpictures[i].bits_per_pixel, subpictures[i].format, subpictures[i].num_planes); + if (subpictures[i].type == XvRGB) { + XVMC_MSG(XVMC_TRACE, "[XvMC] depth=%d\n" \ + "[XvMC] red mask=0x%08X\n" \ + "[XvMC] green mask=0x%08X\n" \ + "[XvMC] blue mask=0x%08X\n", + subpictures[i].depth, subpictures[i].red_mask, + subpictures[i].green_mask, subpictures[i].blue_mask); + } + else if (subpictures[i].type == XvYUV) { + XVMC_MSG(XVMC_TRACE, "[XvMC] y sample bits=0x%08X\n" \ + "[XvMC] u sample bits=0x%08X\n" \ + "[XvMC] v sample bits=0x%08X\n" \ + "[XvMC] horz y period=%u\n" \ + "[XvMC] horz u period=%u\n" \ + "[XvMC] horz v period=%u\n" \ + "[XvMC] vert y period=%u\n" \ + "[XvMC] vert u period=%u\n" \ + "[XvMC] vert v period=%u\n", + subpictures[i].y_sample_bits, subpictures[i].u_sample_bits, subpictures[i].v_sample_bits, + subpictures[i].horz_y_period, subpictures[i].horz_u_period, subpictures[i].horz_v_period, + subpictures[i].vert_y_period, subpictures[i].vert_u_period, subpictures[i].vert_v_period); + } + break; + } + } + + free(subpictures); + + return i < num_subpics ? Success : BadMatch; +} + +static void +upload_sampler(struct pipe_context *pipe, struct pipe_sampler_view *dst, + const struct pipe_box *dst_box, const void *src, unsigned src_stride, + unsigned src_x, unsigned src_y) +{ + struct pipe_transfer *transfer; + void *map; + + map = pipe->transfer_map(pipe, dst->texture, 0, PIPE_TRANSFER_WRITE, + dst_box, &transfer); + if (!map) + return; + + util_copy_rect(map, dst->texture->format, transfer->stride, 0, 0, + dst_box->width, dst_box->height, + src, src_stride, src_x, src_y); + + pipe->transfer_unmap(pipe, transfer); +} + +static void +upload_sampler_convert(struct pipe_context *pipe, struct pipe_sampler_view *dst, + const struct pipe_box *dst_box, const XvImage *image, + unsigned src_x, unsigned src_y) +{ + struct pipe_transfer *transfer; + int i, j; + char *map, *src; + + map = pipe->transfer_map(pipe, dst->texture, 0, PIPE_TRANSFER_WRITE, + dst_box, &transfer); + if (!map) + return; + + src = image->data; + src += src_y * image->width + src_x; + if (image->id == FOURCC_AI44) { + /* The format matches what we want, we just have to insert dummy + * bytes. So just copy the same value in twice. + */ + for (i = 0; i < dst_box->height; i++, map += transfer->stride, src += image->width) + for (j = 0; j < dst_box->width; j++) + map[j * 2 + 0] = map[j * 2 + 1] = src[j]; + } else { + assert(image->id == FOURCC_IA44); + /* Same idea as above, but we have to swap the low and high nibbles. + */ + for (i = 0; i < dst_box->height; i++, map += transfer->stride, src += image->width) + for (j = 0; j < dst_box->width; j++) + map[j * 2 + 0] = map[j * 2 + 1] = (src[j] >> 4) | (src[j] << 4); + } + + pipe->transfer_unmap(pipe, transfer); +} + +PUBLIC +Status XvMCCreateSubpicture(Display *dpy, XvMCContext *context, XvMCSubpicture *subpicture, + unsigned short width, unsigned short height, int xvimage_id) +{ + XvMCContextPrivate *context_priv; + XvMCSubpicturePrivate *subpicture_priv; + struct pipe_context *pipe; + struct pipe_resource tex_templ, *tex; + struct pipe_sampler_view sampler_templ; + enum pipe_format palette_format; + Status ret; + + XVMC_MSG(XVMC_TRACE, "[XvMC] Creating subpicture %p.\n", subpicture); + + assert(dpy); + + if (!context) + return XvMCBadContext; + + context_priv = context->privData; + pipe = context_priv->pipe; + + if (!subpicture) + return XvMCBadSubpicture; + + if (width > context_priv->subpicture_max_width || + height > context_priv->subpicture_max_height) + return BadValue; + + ret = Validate(dpy, context->port, context->surface_type_id, xvimage_id); + if (ret != Success) + return ret; + + subpicture_priv = CALLOC(1, sizeof(XvMCSubpicturePrivate)); + if (!subpicture_priv) + return BadAlloc; + + memset(&tex_templ, 0, sizeof(tex_templ)); + tex_templ.target = PIPE_TEXTURE_2D; + tex_templ.format = XvIDToPipe(pipe->screen, xvimage_id); + tex_templ.last_level = 0; + if (pipe->screen->get_video_param(pipe->screen, + PIPE_VIDEO_PROFILE_UNKNOWN, + PIPE_VIDEO_ENTRYPOINT_UNKNOWN, + PIPE_VIDEO_CAP_NPOT_TEXTURES)) { + tex_templ.width0 = width; + tex_templ.height0 = height; + } + else { + tex_templ.width0 = util_next_power_of_two(width); + tex_templ.height0 = util_next_power_of_two(height); + } + tex_templ.depth0 = 1; + tex_templ.array_size = 1; + tex_templ.usage = PIPE_USAGE_DYNAMIC; + tex_templ.bind = PIPE_BIND_SAMPLER_VIEW; + tex_templ.flags = 0; + + tex = pipe->screen->resource_create(pipe->screen, &tex_templ); + + memset(&sampler_templ, 0, sizeof(sampler_templ)); + u_sampler_view_default_template(&sampler_templ, tex, tex->format); + + subpicture_priv->sampler = pipe->create_sampler_view(pipe, tex, &sampler_templ); + pipe_resource_reference(&tex, NULL); + if (!subpicture_priv->sampler) { + FREE(subpicture_priv); + return BadAlloc; + } + + subpicture_priv->context = context; + subpicture->subpicture_id = XAllocID(dpy); + subpicture->context_id = context->context_id; + subpicture->xvimage_id = xvimage_id; + subpicture->width = width; + subpicture->height = height; + subpicture->num_palette_entries = NumPaletteEntries4XvID(xvimage_id); + subpicture->entry_bytes = PipeToComponentOrder( + pipe->screen, tex_templ.format, &palette_format, + subpicture->component_order); + subpicture->privData = subpicture_priv; + + if (subpicture->num_palette_entries > 0) { + tex_templ.target = PIPE_TEXTURE_1D; + tex_templ.format = palette_format; + tex_templ.width0 = subpicture->num_palette_entries; + tex_templ.height0 = 1; + tex_templ.usage = PIPE_USAGE_DEFAULT; + + tex = pipe->screen->resource_create(pipe->screen, &tex_templ); + + memset(&sampler_templ, 0, sizeof(sampler_templ)); + u_sampler_view_default_template(&sampler_templ, tex, tex->format); + sampler_templ.swizzle_a = PIPE_SWIZZLE_1; + subpicture_priv->palette = pipe->create_sampler_view(pipe, tex, &sampler_templ); + pipe_resource_reference(&tex, NULL); + if (!subpicture_priv->sampler) { + FREE(subpicture_priv); + return BadAlloc; + } + } + + SyncHandle(); + + XVMC_MSG(XVMC_TRACE, "[XvMC] Subpicture %p created.\n", subpicture); + + return Success; +} + +PUBLIC +Status XvMCClearSubpicture(Display *dpy, XvMCSubpicture *subpicture, short x, short y, + unsigned short width, unsigned short height, unsigned int color) +{ + XvMCSubpicturePrivate *subpicture_priv; + XvMCContextPrivate *context_priv; + struct pipe_context *pipe; + struct pipe_sampler_view *dst; + struct pipe_box dst_box = {x, y, 0, width, height, 1}; + struct pipe_transfer *transfer; + union util_color uc; + void *map; + + assert(dpy); + + if (!subpicture) + return XvMCBadSubpicture; + + /* Convert color to float */ + util_format_unpack_rgba(PIPE_FORMAT_B8G8R8A8_UNORM, uc.f, &color, 1); + + subpicture_priv = subpicture->privData; + context_priv = subpicture_priv->context->privData; + pipe = context_priv->pipe; + dst = subpicture_priv->sampler; + + /* TODO: Assert clear rect is within bounds? Or clip? */ + map = pipe->transfer_map(pipe, dst->texture, 0, PIPE_TRANSFER_WRITE, + &dst_box, &transfer); + if (!map) + return XvMCBadSubpicture; + + util_fill_rect(map, dst->texture->format, transfer->stride, 0, 0, + dst_box.width, dst_box.height, &uc); + + pipe->transfer_unmap(pipe, transfer); + return Success; +} + +PUBLIC +Status XvMCCompositeSubpicture(Display *dpy, XvMCSubpicture *subpicture, XvImage *image, + short srcx, short srcy, unsigned short width, unsigned short height, + short dstx, short dsty) +{ + XvMCSubpicturePrivate *subpicture_priv; + XvMCContextPrivate *context_priv; + struct pipe_context *pipe; + struct pipe_box dst_box = {dstx, dsty, 0, width, height, 1}; + unsigned src_stride; + + XVMC_MSG(XVMC_TRACE, "[XvMC] Compositing subpicture %p.\n", subpicture); + + assert(dpy); + + if (!subpicture) + return XvMCBadSubpicture; + + assert(image); + + if (subpicture->xvimage_id != image->id) + return BadMatch; + + /* No planar support for now */ + if (image->num_planes != 1) + return BadMatch; + + subpicture_priv = subpicture->privData; + context_priv = subpicture_priv->context->privData; + pipe = context_priv->pipe; + + /* clipping should be done by upload_sampler and regardles what the documentation + says image->pitches[0] doesn't seems to be in bytes, so don't use it */ + if ((image->id == FOURCC_IA44 || image->id == FOURCC_AI44) && + subpicture_priv->sampler->texture->format == PIPE_FORMAT_B4G4R4A4_UNORM) { + upload_sampler_convert(pipe, subpicture_priv->sampler, &dst_box, image, srcx, srcy); + } else { + src_stride = image->width * util_format_get_blocksize(subpicture_priv->sampler->texture->format); + upload_sampler(pipe, subpicture_priv->sampler, &dst_box, image->data, src_stride, srcx, srcy); + } + + XVMC_MSG(XVMC_TRACE, "[XvMC] Subpicture %p composited.\n", subpicture); + + return Success; +} + +PUBLIC +Status XvMCDestroySubpicture(Display *dpy, XvMCSubpicture *subpicture) +{ + XvMCSubpicturePrivate *subpicture_priv; + + XVMC_MSG(XVMC_TRACE, "[XvMC] Destroying subpicture %p.\n", subpicture); + + assert(dpy); + + if (!subpicture) + return XvMCBadSubpicture; + + subpicture_priv = subpicture->privData; + pipe_sampler_view_reference(&subpicture_priv->sampler, NULL); + pipe_sampler_view_reference(&subpicture_priv->palette, NULL); + FREE(subpicture_priv); + + XVMC_MSG(XVMC_TRACE, "[XvMC] Subpicture %p destroyed.\n", subpicture); + + return Success; +} + +PUBLIC +Status XvMCSetSubpicturePalette(Display *dpy, XvMCSubpicture *subpicture, unsigned char *palette) +{ + XvMCSubpicturePrivate *subpicture_priv; + XvMCContextPrivate *context_priv; + struct pipe_context *pipe; + struct pipe_box dst_box = {0, 0, 0, 0, 1, 1}; + + assert(dpy); + assert(palette); + + if (!subpicture) + return XvMCBadSubpicture; + + subpicture_priv = subpicture->privData; + context_priv = subpicture_priv->context->privData; + pipe = context_priv->pipe; + + dst_box.width = subpicture->num_palette_entries; + + upload_sampler(pipe, subpicture_priv->palette, &dst_box, palette, 0, 0, 0); + + XVMC_MSG(XVMC_TRACE, "[XvMC] Palette of Subpicture %p set.\n", subpicture); + + return Success; +} + +PUBLIC +Status XvMCBlendSubpicture(Display *dpy, XvMCSurface *target_surface, XvMCSubpicture *subpicture, + short subx, short suby, unsigned short subw, unsigned short subh, + short surfx, short surfy, unsigned short surfw, unsigned short surfh) +{ + struct u_rect src_rect = {subx, subx + subw, suby, suby + subh}; + struct u_rect dst_rect = {surfx, surfx + surfw, surfy, surfy + surfh}; + + XvMCSurfacePrivate *surface_priv; + XvMCSubpicturePrivate *subpicture_priv; + + XVMC_MSG(XVMC_TRACE, "[XvMC] Associating subpicture %p with surface %p.\n", subpicture, target_surface); + + assert(dpy); + + if (!target_surface) + return XvMCBadSurface; + + if (!subpicture) + return XvMCBadSubpicture; + + if (target_surface->context_id != subpicture->context_id) + return BadMatch; + + /* TODO: Verify against subpicture independent scaling */ + + surface_priv = target_surface->privData; + subpicture_priv = subpicture->privData; + + /* TODO: Assert rects are within bounds? Or clip? */ + subpicture_priv->src_rect = src_rect; + subpicture_priv->dst_rect = dst_rect; + + surface_priv->subpicture = subpicture; + subpicture_priv->surface = target_surface; + + return Success; +} + +PUBLIC +Status XvMCBlendSubpicture2(Display *dpy, XvMCSurface *source_surface, XvMCSurface *target_surface, + XvMCSubpicture *subpicture, short subx, short suby, unsigned short subw, unsigned short subh, + short surfx, short surfy, unsigned short surfw, unsigned short surfh) +{ + assert(dpy); + + if (!source_surface || !target_surface) + return XvMCBadSurface; + + if (!subpicture) + return XvMCBadSubpicture; + + if (source_surface->context_id != subpicture->context_id) + return BadMatch; + + if (source_surface->context_id != subpicture->context_id) + return BadMatch; + + /* TODO: Assert rects are within bounds? Or clip? */ + + return Success; +} + +PUBLIC +Status XvMCSyncSubpicture(Display *dpy, XvMCSubpicture *subpicture) +{ + assert(dpy); + + if (!subpicture) + return XvMCBadSubpicture; + + return Success; +} + +PUBLIC +Status XvMCFlushSubpicture(Display *dpy, XvMCSubpicture *subpicture) +{ + assert(dpy); + + if (!subpicture) + return XvMCBadSubpicture; + + return Success; +} + +PUBLIC +Status XvMCGetSubpictureStatus(Display *dpy, XvMCSubpicture *subpicture, int *status) +{ + assert(dpy); + + if (!subpicture) + return XvMCBadSubpicture; + + assert(status); + + /* TODO */ + *status = 0; + + return Success; +} diff --git a/src/gallium/frontends/xvmc/surface.c b/src/gallium/frontends/xvmc/surface.c new file mode 100644 index 00000000000..03ee59482c6 --- /dev/null +++ b/src/gallium/frontends/xvmc/surface.c @@ -0,0 +1,539 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include +#include + +#include + +#include "pipe/p_video_codec.h" +#include "pipe/p_video_state.h" +#include "pipe/p_state.h" + +#include "util/macros.h" +#include "util/u_inlines.h" +#include "util/u_memory.h" +#include "util/u_math.h" +#include "vl/vl_winsys.h" + +#include "xvmc_private.h" + +static void +MacroBlocksToPipe(XvMCContextPrivate *context, + XvMCSurfacePrivate *surface, + unsigned int xvmc_picture_structure, + const XvMCMacroBlock *xvmc_mb, + const XvMCBlockArray *xvmc_blocks, + struct pipe_mpeg12_macroblock *mb, + unsigned int num_macroblocks) +{ + unsigned int i, j, k; + + assert(xvmc_mb); + assert(xvmc_blocks); + assert(num_macroblocks); + + for (; num_macroblocks > 0; --num_macroblocks) { + mb->base.codec = PIPE_VIDEO_FORMAT_MPEG12; + mb->x = xvmc_mb->x; + mb->y = xvmc_mb->y; + mb->macroblock_type = xvmc_mb->macroblock_type; + + switch (xvmc_picture_structure) { + case XVMC_FRAME_PICTURE: + mb->macroblock_modes.bits.frame_motion_type = xvmc_mb->motion_type; + mb->macroblock_modes.bits.field_motion_type = 0; + break; + + case XVMC_TOP_FIELD: + case XVMC_BOTTOM_FIELD: + mb->macroblock_modes.bits.frame_motion_type = 0; + mb->macroblock_modes.bits.field_motion_type = xvmc_mb->motion_type; + break; + + default: + assert(0); + } + + mb->macroblock_modes.bits.dct_type = xvmc_mb->dct_type; + mb->motion_vertical_field_select = xvmc_mb->motion_vertical_field_select; + + for (i = 0; i < 2; ++i) + for (j = 0; j < 2; ++j) + for (k = 0; k < 2; ++k) + mb->PMV[i][j][k] = xvmc_mb->PMV[i][j][k]; + + mb->coded_block_pattern = xvmc_mb->coded_block_pattern; + mb->blocks = xvmc_blocks->blocks + xvmc_mb->index * BLOCK_SIZE_SAMPLES; + mb->num_skipped_macroblocks = 0; + + ++xvmc_mb; + ++mb; + } +} + +static void +GetPictureDescription(XvMCSurfacePrivate *surface, struct pipe_mpeg12_picture_desc *desc) +{ + unsigned i, num_refs = 0; + + assert(surface && desc); + + memset(desc, 0, sizeof(*desc)); + desc->base.profile = PIPE_VIDEO_PROFILE_MPEG1; + desc->picture_structure = surface->picture_structure; + for (i = 0; i < 2; ++i) { + if (surface->ref[i]) { + XvMCSurfacePrivate *ref = surface->ref[i]->privData; + + if (ref) + desc->ref[num_refs++] = ref->video_buffer; + } + } +} + +static void +RecursiveEndFrame(XvMCSurfacePrivate *surface) +{ + XvMCContextPrivate *context_priv; + unsigned i; + + assert(surface); + + context_priv = surface->context->privData; + + for ( i = 0; i < 2; ++i ) { + if (surface->ref[i]) { + XvMCSurface *ref = surface->ref[i]; + + assert(ref); + + surface->ref[i] = NULL; + RecursiveEndFrame(ref->privData); + surface->ref[i] = ref; + } + } + + if (surface->picture_structure) { + struct pipe_mpeg12_picture_desc desc; + GetPictureDescription(surface, &desc); + surface->picture_structure = 0; + + for (i = 0; i < 2; ++i) + surface->ref[i] = NULL; + + context_priv->decoder->end_frame(context_priv->decoder, surface->video_buffer, &desc.base); + } +} + +PUBLIC +Status XvMCCreateSurface(Display *dpy, XvMCContext *context, XvMCSurface *surface) +{ + XvMCContextPrivate *context_priv; + struct pipe_context *pipe; + XvMCSurfacePrivate *surface_priv; + struct pipe_video_buffer tmpl; + + XVMC_MSG(XVMC_TRACE, "[XvMC] Creating surface %p.\n", surface); + + assert(dpy); + + if (!context) + return XvMCBadContext; + if (!surface) + return XvMCBadSurface; + + context_priv = context->privData; + pipe = context_priv->pipe; + + surface_priv = CALLOC(1, sizeof(XvMCSurfacePrivate)); + if (!surface_priv) + return BadAlloc; + + memset(&tmpl, 0, sizeof(tmpl)); + tmpl.buffer_format = pipe->screen->get_video_param + ( + pipe->screen, + context_priv->decoder->profile, + context_priv->decoder->entrypoint, + PIPE_VIDEO_CAP_PREFERED_FORMAT + ); + assert(pipe_format_to_chroma_format(tmpl.buffer_format) == context_priv->decoder->chroma_format); + tmpl.width = context_priv->decoder->width; + tmpl.height = context_priv->decoder->height; + tmpl.interlaced = pipe->screen->get_video_param + ( + pipe->screen, + context_priv->decoder->profile, + context_priv->decoder->entrypoint, + PIPE_VIDEO_CAP_PREFERS_INTERLACED + ); + + surface_priv->video_buffer = pipe->create_video_buffer(pipe, &tmpl); + if (!surface_priv->video_buffer) { + FREE(surface_priv); + return BadAlloc; + } + surface_priv->context = context; + + surface->surface_id = XAllocID(dpy); + surface->context_id = context->context_id; + surface->surface_type_id = context->surface_type_id; + surface->width = context->width; + surface->height = context->height; + surface->privData = surface_priv; + + SyncHandle(); + + XVMC_MSG(XVMC_TRACE, "[XvMC] Surface %p created.\n", surface); + + return Success; +} + +PUBLIC +Status XvMCRenderSurface(Display *dpy, XvMCContext *context, unsigned int picture_structure, + XvMCSurface *target_surface, XvMCSurface *past_surface, XvMCSurface *future_surface, + unsigned int flags, unsigned int num_macroblocks, unsigned int first_macroblock, + XvMCMacroBlockArray *macroblocks, XvMCBlockArray *blocks +) +{ + struct pipe_mpeg12_macroblock mb[num_macroblocks]; + struct pipe_video_codec *decoder; + struct pipe_mpeg12_picture_desc desc; + + XvMCContextPrivate *context_priv; + XvMCSurfacePrivate *target_surface_priv; + ASSERTED XvMCSurfacePrivate *past_surface_priv; + ASSERTED XvMCSurfacePrivate *future_surface_priv; + XvMCMacroBlock *xvmc_mb; + + XVMC_MSG(XVMC_TRACE, "[XvMC] Rendering to surface %p, with past %p and future %p\n", + target_surface, past_surface, future_surface); + + assert(dpy); + + if (!context || !context->privData) + return XvMCBadContext; + if (!target_surface || !target_surface->privData) + return XvMCBadSurface; + + if (picture_structure != XVMC_TOP_FIELD && + picture_structure != XVMC_BOTTOM_FIELD && + picture_structure != XVMC_FRAME_PICTURE) + return BadValue; + /* Bkwd pred equivalent to fwd (past && !future) */ + if (future_surface && !past_surface) + return BadMatch; + + assert(context->context_id == target_surface->context_id); + assert(!past_surface || context->context_id == past_surface->context_id); + assert(!future_surface || context->context_id == future_surface->context_id); + + assert(macroblocks); + assert(blocks); + + assert(macroblocks->context_id == context->context_id); + assert(blocks->context_id == context->context_id); + + assert(flags == 0 || flags == XVMC_SECOND_FIELD); + + context_priv = context->privData; + decoder = context_priv->decoder; + + target_surface_priv = target_surface->privData; + past_surface_priv = past_surface ? past_surface->privData : NULL; + future_surface_priv = future_surface ? future_surface->privData : NULL; + + assert(target_surface_priv->context == context); + assert(!past_surface || past_surface_priv->context == context); + assert(!future_surface || future_surface_priv->context == context); + + // call end frame on all referenced frames + if (past_surface) + RecursiveEndFrame(past_surface->privData); + + if (future_surface) + RecursiveEndFrame(future_surface->privData); + + xvmc_mb = macroblocks->macro_blocks + first_macroblock; + + /* If the surface we're rendering hasn't changed the ref frames shouldn't change. */ + if (target_surface_priv->picture_structure > 0 && ( + target_surface_priv->picture_structure != picture_structure || + target_surface_priv->ref[0] != past_surface || + target_surface_priv->ref[1] != future_surface || + (xvmc_mb->x == 0 && xvmc_mb->y == 0))) { + + // If they change anyway we must assume that the current frame is ended + RecursiveEndFrame(target_surface_priv); + } + + target_surface_priv->ref[0] = past_surface; + target_surface_priv->ref[1] = future_surface; + + if (target_surface_priv->picture_structure) + GetPictureDescription(target_surface_priv, &desc); + else { + target_surface_priv->picture_structure = picture_structure; + GetPictureDescription(target_surface_priv, &desc); + decoder->begin_frame(decoder, target_surface_priv->video_buffer, &desc.base); + } + + MacroBlocksToPipe(context_priv, target_surface_priv, picture_structure, + xvmc_mb, blocks, mb, num_macroblocks); + + context_priv->decoder->decode_macroblock(context_priv->decoder, + target_surface_priv->video_buffer, + &desc.base, + &mb[0].base, num_macroblocks); + + XVMC_MSG(XVMC_TRACE, "[XvMC] Submitted surface %p for rendering.\n", target_surface); + + return Success; +} + +PUBLIC +Status XvMCFlushSurface(Display *dpy, XvMCSurface *surface) +{ + assert(dpy); + + if (!surface) + return XvMCBadSurface; + + // don't call flush here, because this is usually + // called once for every slice instead of every frame + + XVMC_MSG(XVMC_TRACE, "[XvMC] Flushing surface %p\n", surface); + + return Success; +} + +PUBLIC +Status XvMCSyncSurface(Display *dpy, XvMCSurface *surface) +{ + assert(dpy); + + if (!surface) + return XvMCBadSurface; + + XVMC_MSG(XVMC_TRACE, "[XvMC] Syncing surface %p\n", surface); + + return Success; +} + +PUBLIC +Status XvMCPutSurface(Display *dpy, XvMCSurface *surface, Drawable drawable, + short srcx, short srcy, unsigned short srcw, unsigned short srch, + short destx, short desty, unsigned short destw, unsigned short desth, + int flags) +{ + static int dump_window = -1; + + struct pipe_context *pipe; + struct vl_compositor *compositor; + struct vl_compositor_state *cstate; + struct vl_screen *vscreen; + + XvMCSurfacePrivate *surface_priv; + XvMCContextPrivate *context_priv; + XvMCSubpicturePrivate *subpicture_priv; + XvMCContext *context; + struct u_rect src_rect = {srcx, srcx + srcw, srcy, srcy + srch}; + struct u_rect dst_rect = {destx, destx + destw, desty, desty + desth}; + + struct pipe_resource *tex; + struct pipe_surface surf_templ, *surf; + struct u_rect *dirty_area; + + XVMC_MSG(XVMC_TRACE, "[XvMC] Displaying surface %p.\n", surface); + + assert(dpy); + + if (!surface || !surface->privData) + return XvMCBadSurface; + + surface_priv = surface->privData; + context = surface_priv->context; + context_priv = context->privData; + + assert(flags == XVMC_TOP_FIELD || flags == XVMC_BOTTOM_FIELD || flags == XVMC_FRAME_PICTURE); + assert(srcx + srcw - 1 < surface->width); + assert(srcy + srch - 1 < surface->height); + + subpicture_priv = surface_priv->subpicture ? surface_priv->subpicture->privData : NULL; + pipe = context_priv->pipe; + compositor = &context_priv->compositor; + cstate = &context_priv->cstate; + vscreen = context_priv->vscreen; + + tex = vscreen->texture_from_drawable(vscreen, (void *)drawable); + dirty_area = vscreen->get_dirty_area(vscreen); + + memset(&surf_templ, 0, sizeof(surf_templ)); + surf_templ.format = tex->format; + surf = pipe->create_surface(pipe, tex, &surf_templ); + + if (!surf) + return BadDrawable; + + /* + * Some apps (mplayer) hit these asserts because they call + * this function after the window has been resized by the WM + * but before they've handled the corresponding XEvent and + * know about the new dimensions. The output should be clipped + * until the app updates destw and desth. + */ + /* + assert(destx + destw - 1 < drawable_surface->width); + assert(desty + desth - 1 < drawable_surface->height); + */ + + RecursiveEndFrame(surface_priv); + + context_priv->decoder->flush(context_priv->decoder); + + vl_compositor_clear_layers(cstate); + vl_compositor_set_buffer_layer(cstate, compositor, 0, surface_priv->video_buffer, + &src_rect, NULL, VL_COMPOSITOR_WEAVE); + + if (subpicture_priv) { + XVMC_MSG(XVMC_TRACE, "[XvMC] Surface %p has subpicture %p.\n", surface, surface_priv->subpicture); + + assert(subpicture_priv->surface == surface); + + if (subpicture_priv->palette) + vl_compositor_set_palette_layer(cstate, compositor, 1, subpicture_priv->sampler, subpicture_priv->palette, + &subpicture_priv->src_rect, &subpicture_priv->dst_rect, true); + else + vl_compositor_set_rgba_layer(cstate, compositor, 1, subpicture_priv->sampler, + &subpicture_priv->src_rect, &subpicture_priv->dst_rect, NULL); + + surface_priv->subpicture = NULL; + subpicture_priv->surface = NULL; + } + + // Workaround for r600g, there seems to be a bug in the fence refcounting code + pipe->screen->fence_reference(pipe->screen, &surface_priv->fence, NULL); + + vl_compositor_set_layer_dst_area(cstate, 0, &dst_rect); + vl_compositor_set_layer_dst_area(cstate, 1, &dst_rect); + vl_compositor_render(cstate, compositor, surf, dirty_area, true); + + pipe->flush(pipe, &surface_priv->fence, 0); + + XVMC_MSG(XVMC_TRACE, "[XvMC] Submitted surface %p for display. Pushing to front buffer.\n", surface); + + pipe->screen->flush_frontbuffer(pipe->screen, tex, 0, 0, + vscreen->get_private(vscreen), NULL); + + if(dump_window == -1) { + dump_window = debug_get_num_option("XVMC_DUMP", 0); + } + + if(dump_window) { + static unsigned int framenum = 0; + char cmd[256]; + + sprintf(cmd, "xwd -id %d -out xvmc_frame_%08d.xwd", (int)drawable, ++framenum); + if (system(cmd) != 0) + XVMC_MSG(XVMC_ERR, "[XvMC] Dumping surface %p failed.\n", surface); + } + + XVMC_MSG(XVMC_TRACE, "[XvMC] Pushed surface %p to front buffer.\n", surface); + + return Success; +} + +PUBLIC +Status XvMCGetSurfaceStatus(Display *dpy, XvMCSurface *surface, int *status) +{ + struct pipe_context *pipe; + XvMCSurfacePrivate *surface_priv; + XvMCContextPrivate *context_priv; + + assert(dpy); + + if (!surface) + return XvMCBadSurface; + + assert(status); + + surface_priv = surface->privData; + context_priv = surface_priv->context->privData; + pipe = context_priv->pipe; + + *status = 0; + + if (surface_priv->fence) + if (!pipe->screen->fence_finish(pipe->screen, NULL, surface_priv->fence, 0)) + *status |= XVMC_RENDERING; + + return Success; +} + +PUBLIC +Status XvMCDestroySurface(Display *dpy, XvMCSurface *surface) +{ + XvMCSurfacePrivate *surface_priv; + XvMCContextPrivate *context_priv; + + XVMC_MSG(XVMC_TRACE, "[XvMC] Destroying surface %p.\n", surface); + + assert(dpy); + + if (!surface || !surface->privData) + return XvMCBadSurface; + + surface_priv = surface->privData; + context_priv = surface_priv->context->privData; + + if (surface_priv->picture_structure) { + struct pipe_mpeg12_picture_desc desc; + GetPictureDescription(surface_priv, &desc); + context_priv->decoder->end_frame(context_priv->decoder, surface_priv->video_buffer, &desc.base); + } + surface_priv->video_buffer->destroy(surface_priv->video_buffer); + FREE(surface_priv); + surface->privData = NULL; + + XVMC_MSG(XVMC_TRACE, "[XvMC] Surface %p destroyed.\n", surface); + + return Success; +} + +PUBLIC +Status XvMCHideSurface(Display *dpy, XvMCSurface *surface) +{ + assert(dpy); + + if (!surface || !surface->privData) + return XvMCBadSurface; + + /* No op, only for overlaid rendering */ + + return Success; +} diff --git a/src/gallium/frontends/xvmc/tests/test_blocks.c b/src/gallium/frontends/xvmc/tests/test_blocks.c new file mode 100644 index 00000000000..53c29bc5ae1 --- /dev/null +++ b/src/gallium/frontends/xvmc/tests/test_blocks.c @@ -0,0 +1,115 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/* Force assertions, even on release builds. */ +#undef NDEBUG +#include +#include +#include +#include "testlib.h" + +int main(int argc, char **argv) +{ + const unsigned int width = 16, height = 16; + const unsigned int min_required_blocks = 1, min_required_macroblocks = 1; + const unsigned int mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2}; + + Display *display; + XvPortID port_num; + int surface_type_id; + unsigned int is_overlay, intra_unsigned; + int colorkey; + XvMCContext context; + XvMCSurface surface; + XvMCBlockArray blocks = {0}; + XvMCMacroBlockArray macroblocks = {0}; + + display = XOpenDisplay(NULL); + + if (!GetPort + ( + display, + width, + height, + XVMC_CHROMA_FORMAT_420, + mc_types, + 2, + &port_num, + &surface_type_id, + &is_overlay, + &intra_unsigned + )) + { + XCloseDisplay(display); + fprintf(stderr, "Error, unable to find a good port.\n"); + exit(1); + } + + if (is_overlay) + { + Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0); + XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey); + } + + assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, &context) == Success); + assert(XvMCCreateSurface(display, &context, &surface) == Success); + + /* Test NULL context */ + assert(XvMCCreateBlocks(display, NULL, 1, &blocks) == XvMCBadContext); + /* Test 0 blocks */ + assert(XvMCCreateBlocks(display, &context, 0, &blocks) == BadValue); + /* Test valid params */ + assert(XvMCCreateBlocks(display, &context, min_required_blocks, &blocks) == Success); + /* Test context id assigned and correct */ + assert(blocks.context_id == context.context_id); + /* Test number of blocks assigned and correct */ + assert(blocks.num_blocks == min_required_blocks); + /* Test block pointer valid */ + assert(blocks.blocks != NULL); + /* Test NULL context */ + assert(XvMCCreateMacroBlocks(display, NULL, 1, ¯oblocks) == XvMCBadContext); + /* Test 0 macroblocks */ + assert(XvMCCreateMacroBlocks(display, &context, 0, ¯oblocks) == BadValue); + /* Test valid params */ + assert(XvMCCreateMacroBlocks(display, &context, min_required_macroblocks, ¯oblocks) == Success); + /* Test context id assigned and correct */ + assert(macroblocks.context_id == context.context_id); + /* Test macroblock pointer valid */ + assert(macroblocks.macro_blocks != NULL); + /* Test valid params */ + assert(XvMCDestroyMacroBlocks(display, ¯oblocks) == Success); + /* Test valid params */ + assert(XvMCDestroyBlocks(display, &blocks) == Success); + + assert(XvMCDestroySurface(display, &surface) == Success); + assert(XvMCDestroyContext(display, &context) == Success); + + XvUngrabPort(display, port_num, CurrentTime); + XCloseDisplay(display); + + return 0; +} diff --git a/src/gallium/frontends/xvmc/tests/test_context.c b/src/gallium/frontends/xvmc/tests/test_context.c new file mode 100644 index 00000000000..81d26fcffd5 --- /dev/null +++ b/src/gallium/frontends/xvmc/tests/test_context.c @@ -0,0 +1,123 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/* Force assertions, even on release builds. */ +#undef NDEBUG +#include +#include +#include +#include "testlib.h" + +int main(int argc, char **argv) +{ + const unsigned int width = 16, height = 16; + const unsigned int mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2}; + + Display *display; + XvPortID port_num; + int surface_type_id; + unsigned int is_overlay, intra_unsigned; + int colorkey; + XvMCContext context = {0}; + + display = XOpenDisplay(NULL); + + if (!GetPort + ( + display, + width, + height, + XVMC_CHROMA_FORMAT_420, + mc_types, + 2, + &port_num, + &surface_type_id, + &is_overlay, + &intra_unsigned + )) + { + XCloseDisplay(display); + fprintf(stderr, "Error, unable to find a good port.\n"); + exit(1); + } + + if (is_overlay) + { + Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0); + XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey); + } + + /* Test NULL context */ + /* XXX: XvMCBadContext not a valid return for XvMCCreateContext in the XvMC API, but openChrome driver returns it */ + assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, NULL) == XvMCBadContext); + /* Test invalid port */ + /* XXX: Success and XvBadPort have the same value, if this call actually gets passed the validation step as of now we'll crash later */ + assert(XvMCCreateContext(display, -1, surface_type_id, width, height, XVMC_DIRECT, &context) == XvBadPort); + /* Test invalid surface */ + assert(XvMCCreateContext(display, port_num, -1, width, height, XVMC_DIRECT, &context) == BadMatch); + /* Test invalid flags */ + assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, -1, &context) == BadValue); + /* Test huge width */ + assert(XvMCCreateContext(display, port_num, surface_type_id, 16384, height, XVMC_DIRECT, &context) == BadValue); + /* Test huge height */ + assert(XvMCCreateContext(display, port_num, surface_type_id, width, 16384, XVMC_DIRECT, &context) == BadValue); + /* Test huge width & height */ + assert(XvMCCreateContext(display, port_num, surface_type_id, 16384, 16384, XVMC_DIRECT, &context) == BadValue); + /* Test valid params */ + assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, &context) == Success); + /* Test context id assigned */ + assert(context.context_id != 0); + /* Test surface type id assigned and correct */ + assert(context.surface_type_id == surface_type_id); + /* Test width & height assigned and correct */ + assert(context.width == width && context.height == height); + /* Test port assigned and correct */ + assert(context.port == port_num); + /* Test flags assigned and correct */ + assert(context.flags == XVMC_DIRECT); + /* Test NULL context */ + assert(XvMCDestroyContext(display, NULL) == XvMCBadContext); + /* Test valid params */ + assert(XvMCDestroyContext(display, &context) == Success); + /* Test awkward but valid width */ + assert(XvMCCreateContext(display, port_num, surface_type_id, width + 1, height, XVMC_DIRECT, &context) == Success); + assert(context.width >= width + 1); + assert(XvMCDestroyContext(display, &context) == Success); + /* Test awkward but valid height */ + assert(XvMCCreateContext(display, port_num, surface_type_id, width, height + 1, XVMC_DIRECT, &context) == Success); + assert(context.height >= height + 1); + assert(XvMCDestroyContext(display, &context) == Success); + /* Test awkward but valid width & height */ + assert(XvMCCreateContext(display, port_num, surface_type_id, width + 1, height + 1, XVMC_DIRECT, &context) == Success); + assert(context.width >= width + 1 && context.height >= height + 1); + assert(XvMCDestroyContext(display, &context) == Success); + + XvUngrabPort(display, port_num, CurrentTime); + XCloseDisplay(display); + + return 0; +} diff --git a/src/gallium/frontends/xvmc/tests/test_rendering.c b/src/gallium/frontends/xvmc/tests/test_rendering.c new file mode 100644 index 00000000000..c5494ecc8c2 --- /dev/null +++ b/src/gallium/frontends/xvmc/tests/test_rendering.c @@ -0,0 +1,330 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/* Force assertions, even on release builds. */ +#undef NDEBUG +#include +#include +#include +#include +#include "testlib.h" + +#define BLOCK_WIDTH 8 +#define BLOCK_HEIGHT 8 +#define BLOCK_SIZE (BLOCK_WIDTH * BLOCK_HEIGHT) +#define MACROBLOCK_WIDTH 16 +#define MACROBLOCK_HEIGHT 16 +#define MACROBLOCK_WIDTH_IN_BLOCKS (MACROBLOCK_WIDTH / BLOCK_WIDTH) +#define MACROBLOCK_HEIGHT_IN_BLOCKS (MACROBLOCK_HEIGHT / BLOCK_HEIGHT) +#define BLOCKS_PER_MACROBLOCK 6 + +#define INPUT_WIDTH 64 +#define INPUT_HEIGHT 64 +#define INPUT_WIDTH_IN_MACROBLOCKS (INPUT_WIDTH / MACROBLOCK_WIDTH) +#define INPUT_HEIGHT_IN_MACROBLOCKS (INPUT_HEIGHT / MACROBLOCK_HEIGHT) +#define NUM_MACROBLOCKS (INPUT_WIDTH_IN_MACROBLOCKS * INPUT_HEIGHT_IN_MACROBLOCKS) + +#define DEFAULT_OUTPUT_WIDTH INPUT_WIDTH +#define DEFAULT_OUTPUT_HEIGHT INPUT_HEIGHT +#define DEFAULT_ACCEPTABLE_ERR 0.01 + +static void ParseArgs(int argc, char **argv, unsigned int *output_width, unsigned int *output_height, double *acceptable_error, int *prompt) +{ + int fail = 0; + int i; + + *output_width = DEFAULT_OUTPUT_WIDTH; + *output_height = DEFAULT_OUTPUT_HEIGHT; + *acceptable_error = DEFAULT_ACCEPTABLE_ERR; + *prompt = 0; + + for (i = 1; i < argc && !fail; ++i) + { + if (!strcmp(argv[i], "-w")) + { + if (sscanf(argv[++i], "%u", output_width) != 1) + fail = 1; + } + else if (!strcmp(argv[i], "-h")) + { + if (sscanf(argv[++i], "%u", output_height) != 1) + fail = 1; + } + else if (!strcmp(argv[i], "-e")) + { + if (sscanf(argv[++i], "%lf", acceptable_error) != 1) + fail = 1; + } + else if (!strcmp(argv[i], "-p")) + *prompt = 1; + else + fail = 1; + } + + if (fail) + { + fprintf( + stderr, + "Bad argument.\n" + "\n" + "Usage: %s [options]\n" + "\t-w \tOutput width\n" + "\t-h \tOutput height\n" + "\t-e \tAcceptable margin of error per pixel, from 0 to 1\n" + "\t-p\tPrompt for quit\n", + argv[0] + ); + exit(1); + } +} + +static void Gradient(short *block, unsigned int start, unsigned int stop, int horizontal, unsigned int intra_unsigned) +{ + unsigned int x, y; + unsigned int range = stop - start; + + if (horizontal) + { + for (y = 0; y < BLOCK_HEIGHT; ++y) + for (x = 0; x < BLOCK_WIDTH; ++x) { + *block = (short)(start + range * (x / (float)(BLOCK_WIDTH - 1))); + if (intra_unsigned) + *block += 1 << 10; + block++; + } + } + else + { + for (y = 0; y < BLOCK_HEIGHT; ++y) + for (x = 0; x < BLOCK_WIDTH; ++x) { + *block = (short)(start + range * (y / (float)(BLOCK_WIDTH - 1))); + if (intra_unsigned) + *block += 1 << 10; + block++; + } + } +} + +int main(int argc, char **argv) +{ + unsigned int output_width; + unsigned int output_height; + double acceptable_error; + int prompt; + Display *display; + Window root, window; + const unsigned int mc_types[] = {XVMC_MOCOMP | XVMC_MPEG_2}; + XvPortID port_num; + int surface_type_id; + unsigned int is_overlay, intra_unsigned; + int colorkey; + XvMCContext context; + XvMCSurface surface; + XvMCBlockArray block_array; + XvMCMacroBlockArray mb_array; + int mbx, mby, bx, by; + XvMCMacroBlock *mb; + short *blocks; + int quit = 0; + + ParseArgs(argc, argv, &output_width, &output_height, &acceptable_error, &prompt); + + display = XOpenDisplay(NULL); + + if (!GetPort + ( + display, + INPUT_WIDTH, + INPUT_HEIGHT, + XVMC_CHROMA_FORMAT_420, + mc_types, + sizeof(mc_types)/sizeof(*mc_types), + &port_num, + &surface_type_id, + &is_overlay, + &intra_unsigned + )) + { + XCloseDisplay(display); + fprintf(stderr, "Error, unable to find a good port.\n"); + exit(1); + } + + if (is_overlay) + { + Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0); + XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey); + } + + root = XDefaultRootWindow(display); + window = XCreateSimpleWindow(display, root, 0, 0, output_width, output_height, 0, 0, colorkey); + + assert(XvMCCreateContext(display, port_num, surface_type_id, INPUT_WIDTH, INPUT_HEIGHT, XVMC_DIRECT, &context) == Success); + assert(XvMCCreateSurface(display, &context, &surface) == Success); + assert(XvMCCreateBlocks(display, &context, NUM_MACROBLOCKS * BLOCKS_PER_MACROBLOCK, &block_array) == Success); + assert(XvMCCreateMacroBlocks(display, &context, NUM_MACROBLOCKS, &mb_array) == Success); + + mb = mb_array.macro_blocks; + blocks = block_array.blocks; + + for (mby = 0; mby < INPUT_HEIGHT_IN_MACROBLOCKS; ++mby) + for (mbx = 0; mbx < INPUT_WIDTH_IN_MACROBLOCKS; ++mbx) + { + mb->x = mbx; + mb->y = mby; + mb->macroblock_type = XVMC_MB_TYPE_INTRA; + /*mb->motion_type = ;*/ + /*mb->motion_vertical_field_select = ;*/ + mb->dct_type = XVMC_DCT_TYPE_FRAME; + /*mb->PMV[0][0][0] = ; + mb->PMV[0][0][1] = ; + mb->PMV[0][1][0] = ; + mb->PMV[0][1][1] = ; + mb->PMV[1][0][0] = ; + mb->PMV[1][0][1] = ; + mb->PMV[1][1][0] = ; + mb->PMV[1][1][1] = ;*/ + mb->index = (mby * INPUT_WIDTH_IN_MACROBLOCKS + mbx) * BLOCKS_PER_MACROBLOCK; + mb->coded_block_pattern = 0x3F; + + mb++; + + for (by = 0; by < MACROBLOCK_HEIGHT_IN_BLOCKS; ++by) + for (bx = 0; bx < MACROBLOCK_WIDTH_IN_BLOCKS; ++bx) + { + const int start = 16, stop = 235, range = stop - start; + + Gradient + ( + blocks, + (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))), + (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))), + 1, + intra_unsigned + ); + + blocks += BLOCK_SIZE; + } + + for (by = 0; by < MACROBLOCK_HEIGHT_IN_BLOCKS / 2; ++by) + for (bx = 0; bx < MACROBLOCK_WIDTH_IN_BLOCKS / 2; ++bx) + { + const int start = 16, stop = 240, range = stop - start; + + Gradient + ( + blocks, + (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))), + (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))), + 1, + intra_unsigned + ); + + blocks += BLOCK_SIZE; + + Gradient + ( + blocks, + (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))), + (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))), + 1, + intra_unsigned + ); + + blocks += BLOCK_SIZE; + } + } + + XSelectInput(display, window, ExposureMask | KeyPressMask); + XMapWindow(display, window); + XSync(display, 0); + + /* Test NULL context */ + assert(XvMCRenderSurface(display, NULL, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == XvMCBadContext); + /* Test NULL surface */ + assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, NULL, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == XvMCBadSurface); + /* Test bad picture structure */ + assert(XvMCRenderSurface(display, &context, 0, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == BadValue); + /* Test valid params */ + assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == Success); + + /* Test NULL surface */ + assert(XvMCPutSurface(display, NULL, window, 0, 0, INPUT_WIDTH, INPUT_HEIGHT, 0, 0, output_width, output_height, XVMC_FRAME_PICTURE) == XvMCBadSurface); + /* Test bad window */ + /* XXX: X halts with a bad drawable for some reason, doesn't return BadDrawable as expected */ + /*assert(XvMCPutSurface(display, &surface, 0, 0, 0, width, height, 0, 0, width, height, XVMC_FRAME_PICTURE) == BadDrawable);*/ + + if (prompt) + { + puts("Press any button to quit..."); + + while (!quit) + { + if (XPending(display) > 0) + { + XEvent event; + + XNextEvent(display, &event); + + switch (event.type) + { + case Expose: + { + /* Test valid params */ + assert + ( + XvMCPutSurface + ( + display, &surface, window, + 0, 0, INPUT_WIDTH, INPUT_HEIGHT, + 0, 0, output_width, output_height, + XVMC_FRAME_PICTURE + ) == Success + ); + break; + } + case KeyPress: + { + quit = 1; + break; + } + } + } + } + } + + assert(XvMCDestroyBlocks(display, &block_array) == Success); + assert(XvMCDestroyMacroBlocks(display, &mb_array) == Success); + assert(XvMCDestroySurface(display, &surface) == Success); + assert(XvMCDestroyContext(display, &context) == Success); + + XvUngrabPort(display, port_num, CurrentTime); + XDestroyWindow(display, window); + XCloseDisplay(display); + + return 0; +} diff --git a/src/gallium/frontends/xvmc/tests/test_subpicture.c b/src/gallium/frontends/xvmc/tests/test_subpicture.c new file mode 100644 index 00000000000..006972fa8ee --- /dev/null +++ b/src/gallium/frontends/xvmc/tests/test_subpicture.c @@ -0,0 +1,189 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/* Force assertions, even on release builds. */ +#undef NDEBUG +#include +#include +#include +#include "testlib.h" + +static void PrintGUID(const char *guid) +{ + int i; + printf("\tguid: "); + for (i = 0; i < 4; ++i) + printf("%c,", guid[i] == 0 ? '0' : guid[i]); + for (; i < 15; ++i) + printf("%x,", (unsigned char)guid[i]); + printf("%x\n", (unsigned int)guid[15]); +} + +static void PrintComponentOrder(const char *co) +{ + int i; + printf("\tcomponent_order:\n\t "); + for (i = 0; i < 4; ++i) + printf("%c,", co[i] == 0 ? '0' : co[i]); + for (; i < 31; ++i) + printf("%x,", (unsigned int)co[i]); + printf("%x\n", (unsigned int)co[31]); +} + +int main(int argc, char **argv) +{ + const unsigned int width = 16, height = 16; + const unsigned int mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2}; + const unsigned int subpic_width = 16, subpic_height = 16; + + Display *display; + XvPortID port_num; + int surface_type_id; + unsigned int is_overlay, intra_unsigned; + int colorkey; + XvMCContext context; + XvImageFormatValues *subpics; + int num_subpics; + XvMCSubpicture subpicture = {0}; + int i; + + display = XOpenDisplay(NULL); + + if (!GetPort + ( + display, + width, + height, + XVMC_CHROMA_FORMAT_420, + mc_types, + 2, + &port_num, + &surface_type_id, + &is_overlay, + &intra_unsigned + )) + { + XCloseDisplay(display); + fprintf(stderr, "Error, unable to find a good port.\n"); + exit(1); + } + + if (is_overlay) + { + Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0); + XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey); + } + + assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, &context) == Success); + + subpics = XvMCListSubpictureTypes(display, port_num, surface_type_id, &num_subpics); + assert((subpics && num_subpics) > 0 || (!subpics && num_subpics == 0)); + + for (i = 0; i < num_subpics; ++i) + { + printf("Subpicture %d:\n", i); + printf("\tid: 0x%08x\n", subpics[i].id); + printf("\ttype: %s\n", subpics[i].type == XvRGB ? "XvRGB" : (subpics[i].type == XvYUV ? "XvYUV" : "Unknown")); + printf("\tbyte_order: %s\n", subpics[i].byte_order == LSBFirst ? "LSB First" : (subpics[i].byte_order == MSBFirst ? "MSB First" : "Unknown")); + PrintGUID(subpics[i].guid); + printf("\tbpp: %u\n", subpics[i].bits_per_pixel); + printf("\tformat: %s\n", subpics[i].format == XvPacked ? "XvPacked" : (subpics[i].format == XvPlanar ? "XvPlanar" : "Unknown")); + printf("\tnum_planes: %u\n", subpics[i].num_planes); + + if (subpics[i].type == XvRGB) + { + printf("\tdepth: %u\n", subpics[i].depth); + printf("\tred_mask: 0x%08x\n", subpics[i].red_mask); + printf("\tgreen_mask: 0x%08x\n", subpics[i].green_mask); + printf("\tblue_mask: 0x%08x\n", subpics[i].blue_mask); + } + else if (subpics[i].type == XvYUV) + { + printf("\ty_sample_bits: %u\n", subpics[i].y_sample_bits); + printf("\tu_sample_bits: %u\n", subpics[i].u_sample_bits); + printf("\tv_sample_bits: %u\n", subpics[i].v_sample_bits); + printf("\thorz_y_period: %u\n", subpics[i].horz_y_period); + printf("\thorz_u_period: %u\n", subpics[i].horz_u_period); + printf("\thorz_v_period: %u\n", subpics[i].horz_v_period); + printf("\tvert_y_period: %u\n", subpics[i].vert_y_period); + printf("\tvert_u_period: %u\n", subpics[i].vert_u_period); + printf("\tvert_v_period: %u\n", subpics[i].vert_v_period); + } + PrintComponentOrder(subpics[i].component_order); + printf("\tscanline_order: %s\n", subpics[i].scanline_order == XvTopToBottom ? "XvTopToBottom" : (subpics[i].scanline_order == XvBottomToTop ? "XvBottomToTop" : "Unknown")); + } + + if (num_subpics == 0) + { + printf("Subpictures not supported, nothing to test.\n"); + return 0; + } + + /* Test NULL context */ + assert(XvMCCreateSubpicture(display, NULL, &subpicture, subpic_width, subpic_height, subpics[0].id) == XvMCBadContext); + /* Test NULL subpicture */ + assert(XvMCCreateSubpicture(display, &context, NULL, subpic_width, subpic_height, subpics[0].id) == XvMCBadSubpicture); + /* Test invalid subpicture */ + assert(XvMCCreateSubpicture(display, &context, &subpicture, subpic_width, subpic_height, -1) == BadMatch); + /* Test huge width */ + assert(XvMCCreateSubpicture(display, &context, &subpicture, 16384, subpic_height, subpics[0].id) == BadValue); + /* Test huge height */ + assert(XvMCCreateSubpicture(display, &context, &subpicture, subpic_width, 16384, subpics[0].id) == BadValue); + /* Test huge width & height */ + assert(XvMCCreateSubpicture(display, &context, &subpicture, 16384, 16384, subpics[0].id) == BadValue); + for (i = 0; i < num_subpics; ++i) + { + /* Test valid params */ + assert(XvMCCreateSubpicture(display, &context, &subpicture, subpic_width, subpic_height, subpics[i].id) == Success); + /* Test subpicture id assigned */ + assert(subpicture.subpicture_id != 0); + /* Test context id assigned and correct */ + assert(subpicture.context_id == context.context_id); + /* Test subpicture type id assigned and correct */ + assert(subpicture.xvimage_id == subpics[i].id); + /* Test width & height assigned and correct */ + assert(subpicture.width == width && subpicture.height == height); + if (subpics[i].type == XvRGB) + /* Test no palette support */ + assert(subpicture.num_palette_entries == 0 && subpicture.entry_bytes == 0); + else + /* Test palette support */ + assert(subpicture.num_palette_entries == 16 && subpicture.entry_bytes == 4); + /* Test valid params */ + assert(XvMCDestroySubpicture(display, &subpicture) == Success); + } + /* Test NULL surface */ + assert(XvMCDestroySubpicture(display, NULL) == XvMCBadSubpicture); + + assert(XvMCDestroyContext(display, &context) == Success); + + free(subpics); + XvUngrabPort(display, port_num, CurrentTime); + XCloseDisplay(display); + + return 0; +} diff --git a/src/gallium/frontends/xvmc/tests/test_surface.c b/src/gallium/frontends/xvmc/tests/test_surface.c new file mode 100644 index 00000000000..d5a121d5ab0 --- /dev/null +++ b/src/gallium/frontends/xvmc/tests/test_surface.c @@ -0,0 +1,102 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/* Force assertions, even on release builds. */ +#undef NDEBUG +#include +#include +#include +#include "testlib.h" + +int main(int argc, char **argv) +{ + const unsigned int width = 16, height = 16; + const unsigned int mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2}; + + Display *display; + XvPortID port_num; + int surface_type_id; + unsigned int is_overlay, intra_unsigned; + int colorkey; + XvMCContext context; + XvMCSurface surface = {0}; + + display = XOpenDisplay(NULL); + + if (!GetPort + ( + display, + width, + height, + XVMC_CHROMA_FORMAT_420, + mc_types, + 2, + &port_num, + &surface_type_id, + &is_overlay, + &intra_unsigned + )) + { + XCloseDisplay(display); + fprintf(stderr, "Error, unable to find a good port.\n"); + exit(1); + } + + if (is_overlay) + { + Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0); + XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey); + } + + assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, &context) == Success); + + /* Test NULL context */ + assert(XvMCCreateSurface(display, NULL, &surface) == XvMCBadContext); + /* Test NULL surface */ + assert(XvMCCreateSurface(display, &context, NULL) == XvMCBadSurface); + /* Test valid params */ + assert(XvMCCreateSurface(display, &context, &surface) == Success); + /* Test surface id assigned */ + assert(surface.surface_id != 0); + /* Test context id assigned and correct */ + assert(surface.context_id == context.context_id); + /* Test surface type id assigned and correct */ + assert(surface.surface_type_id == surface_type_id); + /* Test width & height assigned and correct */ + assert(surface.width == width && surface.height == height); + /* Test valid params */ + assert(XvMCDestroySurface(display, &surface) == Success); + /* Test NULL surface */ + assert(XvMCDestroySurface(display, NULL) == XvMCBadSurface); + + assert(XvMCDestroyContext(display, &context) == Success); + + XvUngrabPort(display, port_num, CurrentTime); + XCloseDisplay(display); + + return 0; +} diff --git a/src/gallium/frontends/xvmc/tests/testlib.c b/src/gallium/frontends/xvmc/tests/testlib.c new file mode 100644 index 00000000000..a943f6bcd95 --- /dev/null +++ b/src/gallium/frontends/xvmc/tests/testlib.c @@ -0,0 +1,147 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "testlib.h" +#include +#include + +/* +void test(int pred, const char *pred_string, const char *doc_string, const char *file, unsigned int line) +{ + fputs(doc_string, stderr); + if (!pred) + fprintf(stderr, " FAIL!\n\t\"%s\" at %s:%u\n", pred_string, file, line); + else + fputs(" PASS!\n", stderr); +} +*/ + +int GetPort +( + Display *display, + unsigned int width, + unsigned int height, + unsigned int chroma_format, + const unsigned int *mc_types, + unsigned int num_mc_types, + XvPortID *port_id, + int *surface_type_id, + unsigned int *is_overlay, + unsigned int *intra_unsigned +) +{ + unsigned int found_port = 0; + XvAdaptorInfo *adaptor_info; + unsigned int num_adaptors; + int num_types; + int ev_base, err_base; + unsigned int i, j, k, l; + + if (!XvMCQueryExtension(display, &ev_base, &err_base)) + return 0; + if (XvQueryAdaptors(display, XDefaultRootWindow(display), &num_adaptors, &adaptor_info) != Success) + return 0; + + for (i = 0; i < num_adaptors && !found_port; ++i) + { + if (adaptor_info[i].type & XvImageMask) + { + XvMCSurfaceInfo *surface_info = XvMCListSurfaceTypes(display, adaptor_info[i].base_id, &num_types); + + if (surface_info) + { + for (j = 0; j < num_types && !found_port; ++j) + { + if + ( + surface_info[j].chroma_format == chroma_format && + surface_info[j].max_width >= width && + surface_info[j].max_height >= height + ) + { + for (k = 0; k < num_mc_types && !found_port; ++k) + { + if ((surface_info[j].mc_type & mc_types[k]) == mc_types[k]) + { + for (l = 0; l < adaptor_info[i].num_ports && !found_port; ++l) + { + if (XvGrabPort(display, adaptor_info[i].base_id + l, CurrentTime) == Success) + { + *port_id = adaptor_info[i].base_id + l; + *surface_type_id = surface_info[j].surface_type_id; + *is_overlay = surface_info[j].flags & XVMC_OVERLAID_SURFACE; + *intra_unsigned = surface_info[j].flags & XVMC_INTRA_UNSIGNED; + found_port = 1; + } + } + } + } + } + } + + free(surface_info); + } + } + } + + XvFreeAdaptorInfo(adaptor_info); + + return found_port; +} + +unsigned int align(unsigned int value, unsigned int alignment) +{ + return (value + alignment - 1) & ~(alignment - 1); +} + +/* From the glibc manual */ +int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y) +{ + /* Perform the carry for the later subtraction by updating y. */ + if (x->tv_usec < y->tv_usec) + { + int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1; + y->tv_usec -= 1000000 * nsec; + y->tv_sec += nsec; + } + if (x->tv_usec - y->tv_usec > 1000000) + { + int nsec = (x->tv_usec - y->tv_usec) / 1000000; + y->tv_usec += 1000000 * nsec; + y->tv_sec -= nsec; + } + + /* + * Compute the time remaining to wait. + * tv_usec is certainly positive. + */ + result->tv_sec = x->tv_sec - y->tv_sec; + result->tv_usec = x->tv_usec - y->tv_usec; + + /* Return 1 if result is negative. */ + return x->tv_sec < y->tv_sec; +} diff --git a/src/gallium/frontends/xvmc/tests/testlib.h b/src/gallium/frontends/xvmc/tests/testlib.h new file mode 100644 index 00000000000..783f35a4b18 --- /dev/null +++ b/src/gallium/frontends/xvmc/tests/testlib.h @@ -0,0 +1,69 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef testlib_h +#define testlib_h + +/* +#define TEST(pred, doc) test(pred, #pred, doc, __FILE__, __LINE__) + +void test(int pred, const char *pred_string, const char *doc_string, const char *file, unsigned int line); +*/ + +#include +#include +#include + +/* + * display: IN A valid X display + * width, height: IN Surface size that the port must display + * chroma_format: IN Chroma format that the port must display + * mc_types, num_mc_types: IN List of MC types that the port must support, first port that matches the first mc_type will be returned + * port_id: OUT Your port's ID + * surface_type_id: OUT Your port's surface ID + * is_overlay: OUT If 1, port uses overlay surfaces, you need to set a colorkey + * intra_unsigned: OUT If 1, port uses unsigned values for intra-coded blocks + */ +int GetPort +( + Display *display, + unsigned int width, + unsigned int height, + unsigned int chroma_format, + const unsigned int *mc_types, + unsigned int num_mc_types, + XvPortID *port_id, + int *surface_type_id, + unsigned int *is_overlay, + unsigned int *intra_unsigned +); + +unsigned int align(unsigned int value, unsigned int alignment); + +int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y); + +#endif diff --git a/src/gallium/frontends/xvmc/tests/xvmc_bench.c b/src/gallium/frontends/xvmc/tests/xvmc_bench.c new file mode 100644 index 00000000000..dbd705639f6 --- /dev/null +++ b/src/gallium/frontends/xvmc/tests/xvmc_bench.c @@ -0,0 +1,309 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/* Force assertions, even on release builds. */ +#undef NDEBUG +#include +#include +#include +#include +#include +#include "testlib.h" + +#define MACROBLOCK_WIDTH 16 +#define MACROBLOCK_HEIGHT 16 +#define BLOCKS_PER_MACROBLOCK 6 + +#define DEFAULT_INPUT_WIDTH 720 +#define DEFAULT_INPUT_HEIGHT 480 +#define DEFAULT_REPS 100 + +#define PIPELINE_STEP_MC 1 +#define PIPELINE_STEP_CSC 2 +#define PIPELINE_STEP_SWAP 4 + +#define MB_TYPE_I 1 +#define MB_TYPE_P 2 +#define MB_TYPE_B 4 + +struct Config +{ + unsigned int input_width; + unsigned int input_height; + unsigned int output_width; + unsigned int output_height; + unsigned int pipeline; + unsigned int mb_types; + unsigned int reps; +}; + +void ParseArgs(int argc, char **argv, struct Config *config); + +void ParseArgs(int argc, char **argv, struct Config *config) +{ + int fail = 0; + int i; + + config->input_width = DEFAULT_INPUT_WIDTH; + config->input_height = DEFAULT_INPUT_HEIGHT; + config->output_width = 0; + config->output_height = 0; + config->pipeline = 0; + config->mb_types = 0; + config->reps = DEFAULT_REPS; + + for (i = 1; i < argc && !fail; ++i) + { + if (!strcmp(argv[i], "-iw")) + { + if (sscanf(argv[++i], "%u", &config->input_width) != 1) + fail = 1; + } + else if (!strcmp(argv[i], "-ih")) + { + if (sscanf(argv[++i], "%u", &config->input_height) != 1) + fail = 1; + } + else if (!strcmp(argv[i], "-ow")) + { + if (sscanf(argv[++i], "%u", &config->output_width) != 1) + fail = 1; + } + else if (!strcmp(argv[i], "-oh")) + { + if (sscanf(argv[++i], "%u", &config->output_height) != 1) + fail = 1; + } + else if (!strcmp(argv[i], "-p")) + { + char *token = strtok(argv[++i], ","); + + while (token && !fail) + { + if (!strcmp(token, "mc")) + config->pipeline |= PIPELINE_STEP_MC; + else if (!strcmp(token, "csc")) + config->pipeline |= PIPELINE_STEP_CSC; + else if (!strcmp(token, "swp")) + config->pipeline |= PIPELINE_STEP_SWAP; + else + fail = 1; + + if (!fail) + token = strtok(NULL, ","); + } + } + else if (!strcmp(argv[i], "-mb")) + { + char *token = strtok(argv[++i], ","); + + while (token && !fail) + { + if (strcmp(token, "i") == 0) + config->mb_types |= MB_TYPE_I; + else if (strcmp(token, "p") == 0) + config->mb_types |= MB_TYPE_P; + else if (strcmp(token, "b") == 0) + config->mb_types |= MB_TYPE_B; + else + fail = 1; + + if (!fail) + token = strtok(NULL, ","); + } + } + else if (!strcmp(argv[i], "-r")) + { + if (sscanf(argv[++i], "%u", &config->reps) != 1) + fail = 1; + } + else + fail = 1; + } + + if (fail) + { + fprintf( + stderr, + "Bad argument.\n" + "\n" + "Usage: %s [options]\n" + "\t-iw \tInput width\n" + "\t-ih \tInput height\n" + "\t-ow \tOutput width\n" + "\t-oh \tOutput height\n" + "\t-p \tPipeline to test\n" + "\t-mb \tMacroBlock types to use\n" + "\t-r \tRepetitions\n\n" + "\tPipeline steps: mc,csc,swap\n" + "\tMB types: i,p,b\n", + argv[0] + ); + exit(1); + } + + if (config->output_width == 0) + config->output_width = config->input_width; + if (config->output_height == 0) + config->output_height = config->input_height; + if (!config->pipeline) + config->pipeline = PIPELINE_STEP_MC | PIPELINE_STEP_CSC | PIPELINE_STEP_SWAP; + if (!config->mb_types) + config->mb_types = MB_TYPE_I | MB_TYPE_P | MB_TYPE_B; +} + +int main(int argc, char **argv) +{ + struct Config config; + Display *display; + Window root, window; + const unsigned int mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2}; + XvPortID port_num; + int surface_type_id; + unsigned int is_overlay, intra_unsigned; + int colorkey; + XvMCContext context; + XvMCSurface surface; + XvMCBlockArray block_array; + XvMCMacroBlockArray mb_array; + unsigned int mbw, mbh; + unsigned int mbx, mby; + unsigned int reps; + struct timeval start, stop, diff; + double diff_secs; + + ParseArgs(argc, argv, &config); + + mbw = align(config.input_width, MACROBLOCK_WIDTH) / MACROBLOCK_WIDTH; + mbh = align(config.input_height, MACROBLOCK_HEIGHT) / MACROBLOCK_HEIGHT; + + display = XOpenDisplay(NULL); + + if (!GetPort + ( + display, + config.input_width, + config.input_height, + XVMC_CHROMA_FORMAT_420, + mc_types, + 2, + &port_num, + &surface_type_id, + &is_overlay, + &intra_unsigned + )) + { + XCloseDisplay(display); + fprintf(stderr, "Error, unable to find a good port.\n"); + exit(1); + } + + if (is_overlay) + { + Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0); + XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey); + } + else + { + colorkey = 0; + } + + root = XDefaultRootWindow(display); + window = XCreateSimpleWindow(display, root, 0, 0, config.output_width, config.output_height, 0, 0, colorkey); + + assert(XvMCCreateContext(display, port_num, surface_type_id, config.input_width, config.input_height, XVMC_DIRECT, &context) == Success); + assert(XvMCCreateSurface(display, &context, &surface) == Success); + assert(XvMCCreateBlocks(display, &context, mbw * mbh * BLOCKS_PER_MACROBLOCK, &block_array) == Success); + assert(XvMCCreateMacroBlocks(display, &context, mbw * mbh, &mb_array) == Success); + + for (mby = 0; mby < mbh; ++mby) + for (mbx = 0; mbx < mbw; ++mbx) + { + mb_array.macro_blocks[mby * mbw + mbx].x = mbx; + mb_array.macro_blocks[mby * mbw + mbx].y = mby; + mb_array.macro_blocks[mby * mbw + mbx].macroblock_type = XVMC_MB_TYPE_INTRA; + /*mb->motion_type = ;*/ + /*mb->motion_vertical_field_select = ;*/ + mb_array.macro_blocks[mby * mbw + mbx].dct_type = XVMC_DCT_TYPE_FRAME; + /*mb->PMV[0][0][0] = ; + mb->PMV[0][0][1] = ; + mb->PMV[0][1][0] = ; + mb->PMV[0][1][1] = ; + mb->PMV[1][0][0] = ; + mb->PMV[1][0][1] = ; + mb->PMV[1][1][0] = ; + mb->PMV[1][1][1] = ;*/ + mb_array.macro_blocks[mby * mbw + mbx].index = (mby * mbw + mbx) * BLOCKS_PER_MACROBLOCK; + mb_array.macro_blocks[mby * mbw + mbx].coded_block_pattern = 0x3F; + } + + XSelectInput(display, window, ExposureMask | KeyPressMask); + XMapWindow(display, window); + XSync(display, 0); + + gettimeofday(&start, NULL); + + for (reps = 0; reps < config.reps; ++reps) + { + if (config.pipeline & PIPELINE_STEP_MC) + { + assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, mbw * mbh, 0, &mb_array, &block_array) == Success); + assert(XvMCFlushSurface(display, &surface) == Success); + } + if (config.pipeline & PIPELINE_STEP_CSC) + assert(XvMCPutSurface(display, &surface, window, 0, 0, config.input_width, config.input_height, 0, 0, config.output_width, config.output_height, XVMC_FRAME_PICTURE) == Success); + } + + gettimeofday(&stop, NULL); + + timeval_subtract(&diff, &stop, &start); + diff_secs = (double)diff.tv_sec + (double)diff.tv_usec / 1000000.0; + + printf("XvMC Benchmark\n"); + printf("Input: %u,%u\nOutput: %u,%u\n", config.input_width, config.input_height, config.output_width, config.output_height); + printf("Pipeline: "); + if (config.pipeline & PIPELINE_STEP_MC) + printf("|mc|"); + if (config.pipeline & PIPELINE_STEP_CSC) + printf("|csc|"); + if (config.pipeline & PIPELINE_STEP_SWAP) + printf("|swap|"); + printf("\n"); + printf("Reps: %u\n", config.reps); + printf("Total time: %.2lf (%.2lf reps / sec)\n", diff_secs, config.reps / diff_secs); + + assert(XvMCDestroyBlocks(display, &block_array) == Success); + assert(XvMCDestroyMacroBlocks(display, &mb_array) == Success); + assert(XvMCDestroySurface(display, &surface) == Success); + assert(XvMCDestroyContext(display, &context) == Success); + + XvUngrabPort(display, port_num, CurrentTime); + XDestroyWindow(display, window); + XCloseDisplay(display); + + return 0; +} diff --git a/src/gallium/frontends/xvmc/xvmc_private.h b/src/gallium/frontends/xvmc/xvmc_private.h new file mode 100644 index 00000000000..a1d026f704e --- /dev/null +++ b/src/gallium/frontends/xvmc/xvmc_private.h @@ -0,0 +1,125 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef xvmc_private_h +#define xvmc_private_h + +#include +#include + +#include "pipe/p_video_state.h" + +#include "util/u_debug.h" +#include "util/u_math.h" + +#include "vl/vl_csc.h" +#include "vl/vl_compositor.h" + +#define BLOCK_SIZE_SAMPLES 64 +#define BLOCK_SIZE_BYTES (BLOCK_SIZE_SAMPLES * 2) + +struct pipe_video_codec; +struct pipe_video_buffer; + +struct pipe_sampler_view; +struct pipe_fence_handle; + +typedef struct +{ + struct vl_screen *vscreen; + struct pipe_context *pipe; + struct pipe_video_codec *decoder; + + enum VL_CSC_COLOR_STANDARD color_standard; + struct vl_procamp procamp; + struct vl_compositor compositor; + struct vl_compositor_state cstate; + + unsigned short subpicture_max_width; + unsigned short subpicture_max_height; + +} XvMCContextPrivate; + +typedef struct +{ + struct pipe_video_buffer *video_buffer; + + /* nonzero if this picture is already being decoded */ + unsigned picture_structure; + + XvMCSurface *ref[2]; + + struct pipe_fence_handle *fence; + + /* The subpicture associated with this surface, if any. */ + XvMCSubpicture *subpicture; + + /* Some XvMC functions take a surface but not a context, + so we keep track of which context each surface belongs to. */ + XvMCContext *context; +} XvMCSurfacePrivate; + +typedef struct +{ + struct pipe_sampler_view *sampler; + + /* optional palette for this subpicture */ + struct pipe_sampler_view *palette; + + struct u_rect src_rect; + struct u_rect dst_rect; + + /* The surface this subpicture is currently associated with, if any. */ + XvMCSurface *surface; + + /* Some XvMC functions take a subpicture but not a context, + so we keep track of which context each subpicture belongs to. */ + XvMCContext *context; +} XvMCSubpicturePrivate; + +#define XVMC_OUT 0 +#define XVMC_ERR 1 +#define XVMC_WARN 2 +#define XVMC_TRACE 3 + +static inline void XVMC_MSG(int level, const char *fmt, ...) +{ + static int debug_level = -1; + + if (debug_level == -1) { + debug_level = MAX2(debug_get_num_option("XVMC_DEBUG", 0), 0); + } + + if (level <= debug_level) { + va_list ap; + va_start(ap, fmt); + _debug_vprintf(fmt, ap); + va_end(ap); + } +} + +#endif /* xvmc_private_h */ diff --git a/src/gallium/include/frontend/api.h b/src/gallium/include/frontend/api.h new file mode 100644 index 00000000000..5bcb8d9fea6 --- /dev/null +++ b/src/gallium/include/frontend/api.h @@ -0,0 +1,575 @@ +/********************************************************** + * Copyright 2010 VMware, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + **********************************************************/ + + +#ifndef _API_H_ +#define _API_H_ + +#include "pipe/p_format.h" + +/** + * \file API for communication between state trackers and state tracker + * managers. + * + * While both are state tackers, we use the term state tracker for rendering + * APIs such as OpenGL or OpenVG, and state tracker manager for window system + * APIs such as EGL or GLX in this file. + * + * This file defines an API to be implemented by both state trackers and state + * tracker managers. + */ + +/** + * The supported rendering API of a state tracker. + */ +enum st_api_type { + ST_API_OPENGL, + ST_API_OPENVG, + + ST_API_COUNT +}; + +/** + * The profile of a context. + */ +enum st_profile_type +{ + ST_PROFILE_DEFAULT, /**< OpenGL compatibility profile */ + ST_PROFILE_OPENGL_CORE, /**< OpenGL 3.2+ core profile */ + ST_PROFILE_OPENGL_ES1, /**< OpenGL ES 1.x */ + ST_PROFILE_OPENGL_ES2 /**< OpenGL ES 2.0 */ +}; + +/* for profile_mask in st_api */ +#define ST_PROFILE_DEFAULT_MASK (1 << ST_PROFILE_DEFAULT) +#define ST_PROFILE_OPENGL_CORE_MASK (1 << ST_PROFILE_OPENGL_CORE) +#define ST_PROFILE_OPENGL_ES1_MASK (1 << ST_PROFILE_OPENGL_ES1) +#define ST_PROFILE_OPENGL_ES2_MASK (1 << ST_PROFILE_OPENGL_ES2) + +/** + * Optional API/state tracker features. + */ +enum st_api_feature +{ + ST_API_FEATURE_MS_VISUALS /**< support for multisample visuals */ +}; + +/* for feature_mask in st_api */ +#define ST_API_FEATURE_MS_VISUALS_MASK (1 << ST_API_FEATURE_MS_VISUALS) + +/** + * New context flags for GL 3.0 and beyond. + * + * Profile information (core vs. compatibilty for OpenGL 3.2+) is communicated + * through the \c st_profile_type, not through flags. + */ +#define ST_CONTEXT_FLAG_DEBUG (1 << 0) +#define ST_CONTEXT_FLAG_FORWARD_COMPATIBLE (1 << 1) +#define ST_CONTEXT_FLAG_ROBUST_ACCESS (1 << 2) +#define ST_CONTEXT_FLAG_RESET_NOTIFICATION_ENABLED (1 << 3) +#define ST_CONTEXT_FLAG_NO_ERROR (1 << 4) +#define ST_CONTEXT_FLAG_RELEASE_NONE (1 << 5) +#define ST_CONTEXT_FLAG_HIGH_PRIORITY (1 << 6) +#define ST_CONTEXT_FLAG_LOW_PRIORITY (1 << 7) + +/** + * Reasons that context creation might fail. + */ +enum st_context_error { + ST_CONTEXT_SUCCESS = 0, + ST_CONTEXT_ERROR_NO_MEMORY, + ST_CONTEXT_ERROR_BAD_API, + ST_CONTEXT_ERROR_BAD_VERSION, + ST_CONTEXT_ERROR_BAD_FLAG, + ST_CONTEXT_ERROR_UNKNOWN_ATTRIBUTE, + ST_CONTEXT_ERROR_UNKNOWN_FLAG +}; + +/** + * Used in st_context_iface->teximage. + */ +enum st_texture_type { + ST_TEXTURE_1D, + ST_TEXTURE_2D, + ST_TEXTURE_3D, + ST_TEXTURE_RECT +}; + +/** + * Available attachments of framebuffer. + */ +enum st_attachment_type { + ST_ATTACHMENT_FRONT_LEFT, + ST_ATTACHMENT_BACK_LEFT, + ST_ATTACHMENT_FRONT_RIGHT, + ST_ATTACHMENT_BACK_RIGHT, + ST_ATTACHMENT_DEPTH_STENCIL, + ST_ATTACHMENT_ACCUM, + ST_ATTACHMENT_SAMPLE, + + ST_ATTACHMENT_COUNT, + ST_ATTACHMENT_INVALID = -1 +}; + +/* for buffer_mask in st_visual */ +#define ST_ATTACHMENT_FRONT_LEFT_MASK (1 << ST_ATTACHMENT_FRONT_LEFT) +#define ST_ATTACHMENT_BACK_LEFT_MASK (1 << ST_ATTACHMENT_BACK_LEFT) +#define ST_ATTACHMENT_FRONT_RIGHT_MASK (1 << ST_ATTACHMENT_FRONT_RIGHT) +#define ST_ATTACHMENT_BACK_RIGHT_MASK (1 << ST_ATTACHMENT_BACK_RIGHT) +#define ST_ATTACHMENT_DEPTH_STENCIL_MASK (1 << ST_ATTACHMENT_DEPTH_STENCIL) +#define ST_ATTACHMENT_ACCUM_MASK (1 << ST_ATTACHMENT_ACCUM) +#define ST_ATTACHMENT_SAMPLE_MASK (1 << ST_ATTACHMENT_SAMPLE) + +/** + * Flush flags. + */ +#define ST_FLUSH_FRONT (1 << 0) +#define ST_FLUSH_END_OF_FRAME (1 << 1) +#define ST_FLUSH_WAIT (1 << 2) +#define ST_FLUSH_FENCE_FD (1 << 3) + +/** + * Value to st_manager->get_param function. + */ +enum st_manager_param { + /** + * The dri state tracker on old libGL's doesn't do the right thing + * with regards to invalidating the framebuffers. + * + * For the mesa state tracker that means that it needs to invalidate + * the framebuffer in glViewport itself. + */ + ST_MANAGER_BROKEN_INVALIDATE +}; + +struct pipe_context; +struct pipe_resource; +struct pipe_fence_handle; +struct util_queue_monitoring; + +/** + * Used in st_manager_iface->get_egl_image. + */ +struct st_egl_image +{ + /* this is owned by the caller */ + struct pipe_resource *texture; + + /* format only differs from texture->format for multi-planar (YUV): */ + enum pipe_format format; + + unsigned level; + unsigned layer; + /* GL internal format. */ + unsigned internalformat; +}; + +/** + * Represent the visual of a framebuffer. + */ +struct st_visual +{ + bool no_config; + + /** + * Available buffers. Bitfield of ST_ATTACHMENT_*_MASK bits. + */ + unsigned buffer_mask; + + /** + * Buffer formats. The formats are always set even when the buffer is + * not available. + */ + enum pipe_format color_format; + enum pipe_format depth_stencil_format; + enum pipe_format accum_format; + unsigned samples; + + /** + * Desired render buffer. + */ + enum st_attachment_type render_buffer; +}; + + +/** + * Configuration options from driconf + */ +struct st_config_options +{ + bool disable_blend_func_extended; + bool disable_glsl_line_continuations; + bool disable_arb_gpu_shader5; + bool force_glsl_extensions_warn; + unsigned force_glsl_version; + bool allow_glsl_extension_directive_midshader; + bool allow_glsl_builtin_const_expression; + bool allow_glsl_relaxed_es; + bool allow_glsl_builtin_variable_redeclaration; + bool allow_higher_compat_version; + bool glsl_zero_init; + bool vs_position_always_invariant; + bool force_glsl_abs_sqrt; + bool allow_glsl_cross_stage_interpolation_mismatch; + bool allow_glsl_layout_qualifier_on_function_parameters; + bool allow_draw_out_of_order; + bool force_integer_tex_nearest; + char *force_gl_vendor; + unsigned char config_options_sha1[20]; +}; + +/** + * Represent the attributes of a context. + */ +struct st_context_attribs +{ + /** + * The profile and minimal version to support. + * + * The valid profiles and versions are rendering API dependent. The latest + * version satisfying the request should be returned. + */ + enum st_profile_type profile; + int major, minor; + + /** Mask of ST_CONTEXT_FLAG_x bits */ + unsigned flags; + + /** + * The visual of the framebuffers the context will be bound to. + */ + struct st_visual visual; + + /** + * Configuration options. + */ + struct st_config_options options; +}; + +struct st_context_iface; +struct st_manager; + +/** + * Represent a windowing system drawable. + * + * The framebuffer is implemented by the state tracker manager and + * used by the state trackers. + * + * Instead of the winsys poking into the API context to figure + * out what buffers that might be needed in the future by the API + * context, it calls into the framebuffer to get the textures. + * + * This structure along with the notify_invalid_framebuffer + * allows framebuffers to be shared between different threads + * but at the same make the API context free from thread + * synchronization primitves, with the exception of a small + * atomic flag used for notification of framebuffer dirty status. + * + * The thread synchronization is put inside the framebuffer + * and only called once the framebuffer has become dirty. + */ +struct st_framebuffer_iface +{ + /** + * Atomic stamp which changes when framebuffers need to be updated. + */ + int32_t stamp; + + /** + * Identifier that uniquely identifies the framebuffer interface object. + */ + uint32_t ID; + + /** + * The state tracker manager that manages this object. + */ + struct st_manager *state_manager; + + /** + * Available for the state tracker manager to use. + */ + void *st_manager_private; + + /** + * The visual of a framebuffer. + */ + const struct st_visual *visual; + + /** + * Flush the front buffer. + * + * On some window systems, changes to the front buffers are not immediately + * visible. They need to be flushed. + * + * @att is one of the front buffer attachments. + */ + bool (*flush_front)(struct st_context_iface *stctx, + struct st_framebuffer_iface *stfbi, + enum st_attachment_type statt); + + /** + * The state tracker asks for the textures it needs. + * + * It should try to only ask for attachments that it currently renders + * to, thus allowing the winsys to delay the allocation of textures not + * needed. For example front buffer attachments are not needed if you + * only do back buffer rendering. + * + * The implementor of this function needs to also ensure + * thread safty as this call might be done from multiple threads. + * + * The returned textures are owned by the caller. They should be + * unreferenced when no longer used. If this function is called multiple + * times with different sets of attachments, those buffers not included in + * the last call might be destroyed. This behavior might change in the + * future. + */ + bool (*validate)(struct st_context_iface *stctx, + struct st_framebuffer_iface *stfbi, + const enum st_attachment_type *statts, + unsigned count, + struct pipe_resource **out); + bool (*flush_swapbuffers) (struct st_context_iface *stctx, + struct st_framebuffer_iface *stfbi); +}; + +/** + * Represent a rendering context. + * + * This entity is created from st_api and used by the state tracker manager. + */ +struct st_context_iface +{ + /** + * Available for the state tracker and the manager to use. + */ + void *st_context_private; + void *st_manager_private; + + /** + * The state tracker manager that manages this object. + */ + struct st_manager *state_manager; + + /** + * The CSO context associated with this context in case we need to draw + * something before swap buffers. + */ + struct cso_context *cso_context; + + /** + * The gallium context. + */ + struct pipe_context *pipe; + + /** + * Destroy the context. + */ + void (*destroy)(struct st_context_iface *stctxi); + + /** + * Flush all drawing from context to the pipe also flushes the pipe. + */ + void (*flush)(struct st_context_iface *stctxi, unsigned flags, + struct pipe_fence_handle **fence, + void (*notify_before_flush_cb) (void*), + void* notify_before_flush_cb_args); + + /** + * Replace the texture image of a texture object at the specified level. + * + * This function is optional. + */ + bool (*teximage)(struct st_context_iface *stctxi, + enum st_texture_type target, + int level, enum pipe_format internal_format, + struct pipe_resource *tex, bool mipmap); + + /** + * Used to implement glXCopyContext. + */ + void (*copy)(struct st_context_iface *stctxi, + struct st_context_iface *stsrci, unsigned mask); + + /** + * Used to implement wglShareLists. + */ + bool (*share)(struct st_context_iface *stctxi, + struct st_context_iface *stsrci); + + /** + * Start the thread if the API has a worker thread. + * Called after the context has been created and fully initialized on both + * sides (e.g. st/mesa and st/dri). + */ + void (*start_thread)(struct st_context_iface *stctxi); + + /** + * If the API is multithreaded, wait for all queued commands to complete. + * Called from the main thread. + */ + void (*thread_finish)(struct st_context_iface *stctxi); +}; + + +/** + * Represent a state tracker manager. + * + * This interface is implemented by the state tracker manager. It corresponds + * to a "display" in the window system. + */ +struct st_manager +{ + struct pipe_screen *screen; + + /** + * Look up and return the info of an EGLImage. + * + * This is used to implement for example EGLImageTargetTexture2DOES. + * The GLeglImageOES agrument of that call is passed directly to this + * function call and the information needed to access this is returned + * in the given struct out. + * + * @smapi: manager owning the caller context + * @stctx: caller context + * @egl_image: EGLImage that caller recived + * @out: return struct filled out with access information. + * + * This function is optional. + */ + bool (*get_egl_image)(struct st_manager *smapi, + void *egl_image, + struct st_egl_image *out); + + /** + * Query an manager param. + */ + int (*get_param)(struct st_manager *smapi, + enum st_manager_param param); + + /** + * Call the loader function setBackgroundContext. Called from the worker + * thread. + */ + void (*set_background_context)(struct st_context_iface *stctxi, + struct util_queue_monitoring *queue_info); + + /** + * Destroy any private data used by the state tracker manager. + */ + void (*destroy)(struct st_manager *smapi); + + /** + * Available for the state tracker manager to use. + */ + void *st_manager_private; +}; + +/** + * Represent a rendering API such as OpenGL or OpenVG. + * + * Implemented by the state tracker and used by the state tracker manager. + */ +struct st_api +{ + /** + * The name of the rendering API. This is informative. + */ + const char *name; + + /** + * The supported rendering API. + */ + enum st_api_type api; + + /** + * The supported profiles. Tested with ST_PROFILE_*_MASK. + */ + unsigned profile_mask; + + /** + * The supported optional features. Tested with ST_FEATURE_*_MASK. + */ + unsigned feature_mask; + + /** + * Destroy the API. + */ + void (*destroy)(struct st_api *stapi); + + /** + * Query supported OpenGL versions. (if applicable) + * The format is (major*10+minor). + */ + void (*query_versions)(struct st_api *stapi, struct st_manager *sm, + struct st_config_options *options, + int *gl_core_version, + int *gl_compat_version, + int *gl_es1_version, + int *gl_es2_version); + + /** + * Create a rendering context. + */ + struct st_context_iface *(*create_context)(struct st_api *stapi, + struct st_manager *smapi, + const struct st_context_attribs *attribs, + enum st_context_error *error, + struct st_context_iface *stsharei); + + /** + * Bind the context to the calling thread with draw and read as drawables. + * + * The framebuffers might be NULL, or might have different visuals than the + * context does. + */ + bool (*make_current)(struct st_api *stapi, + struct st_context_iface *stctxi, + struct st_framebuffer_iface *stdrawi, + struct st_framebuffer_iface *streadi); + + /** + * Get the currently bound context in the calling thread. + */ + struct st_context_iface *(*get_current)(struct st_api *stapi); + + /** + * Notify the st manager the framebuffer interface object + * is no longer valid. + */ + void (*destroy_drawable)(struct st_api *stapi, + struct st_framebuffer_iface *stfbi); +}; + +/** + * Return true if the visual has the specified buffers. + */ +static inline bool +st_visual_have_buffers(const struct st_visual *visual, unsigned mask) +{ + return ((visual->buffer_mask & mask) == mask); +} + +#endif /* _API_H_ */ diff --git a/src/gallium/include/frontend/drisw_api.h b/src/gallium/include/frontend/drisw_api.h new file mode 100644 index 00000000000..4b5d36c1797 --- /dev/null +++ b/src/gallium/include/frontend/drisw_api.h @@ -0,0 +1,27 @@ +#ifndef _DRISW_API_H_ +#define _DRISW_API_H_ + +#include "pipe/p_compiler.h" +#include "sw_winsys.h" + +struct pipe_screen; +struct dri_drawable; + +/** + * This callback struct is intended for the winsys to call the loader. + */ +struct drisw_loader_funcs +{ + void (*get_image) (struct dri_drawable *dri_drawable, + int x, int y, unsigned width, unsigned height, unsigned stride, + void *data); + void (*put_image) (struct dri_drawable *dri_drawable, + void *data, unsigned width, unsigned height); + void (*put_image2) (struct dri_drawable *dri_drawable, + void *data, int x, int y, unsigned width, unsigned height, unsigned stride); + void (*put_image_shm) (struct dri_drawable *dri_drawable, + int shmid, char *shmaddr, unsigned offset, unsigned offset_x, + int x, int y, unsigned width, unsigned height, unsigned stride); +}; + +#endif diff --git a/src/gallium/include/frontend/drm_driver.h b/src/gallium/include/frontend/drm_driver.h new file mode 100644 index 00000000000..f8d77a79721 --- /dev/null +++ b/src/gallium/include/frontend/drm_driver.h @@ -0,0 +1,49 @@ + +#ifndef _DRM_DRIVER_H_ +#define _DRM_DRIVER_H_ + +#include "pipe/p_compiler.h" + +#include "winsys_handle.h" + +struct pipe_screen; +struct pipe_screen_config; +struct pipe_context; +struct pipe_resource; + +struct drm_driver_descriptor +{ + /** + * Identifying prefix/suffix of the binary, used by the pipe-loader. + */ + const char *driver_name; + + /** + * Pointer to the XML string describing driver-specific driconf options. + * Use DRI_CONF_* macros to create the string. + */ + const char **driconf_xml; + + /** + * Create a pipe srcreen. + * + * This function does any wrapping of the screen. + * For example wrapping trace or rbug debugging drivers around it. + */ + struct pipe_screen* (*create_screen)(int drm_fd, + const struct pipe_screen_config *config); +}; + +extern const struct drm_driver_descriptor driver_descriptor; + +/** + * Instantiate a drm_driver_descriptor struct. + */ +#define DRM_DRIVER_DESCRIPTOR(driver_name_str, driconf, func) \ +const struct drm_driver_descriptor driver_descriptor = { \ + .driver_name = driver_name_str, \ + .driconf_xml = driconf, \ + .create_screen = func, \ +}; + +#endif diff --git a/src/gallium/include/frontend/graw.h b/src/gallium/include/frontend/graw.h new file mode 100644 index 00000000000..af81cc8871b --- /dev/null +++ b/src/gallium/include/frontend/graw.h @@ -0,0 +1,96 @@ +/************************************************************************** + * + * Copyright 2010 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef GALLIUM_RAW_H +#define GALLIUM_RAW_H + +/* This is an API for exercising gallium functionality in a + * platform-neutral fashion. Whatever platform integration is + * necessary to implement this interface is orchestrated by the + * individual target building this entity. + * + * For instance, the graw-xlib target includes code to implement these + * interfaces on top of the X window system. + * + * Programs using this interface may additionally benefit from some of + * the utilities currently in the libgallium.a library, especially + * those for parsing text representations of TGSI shaders. + */ + +#include "pipe/p_compiler.h" +#include "pipe/p_format.h" + +struct pipe_context; +struct pipe_screen; +struct pipe_surface; + +/* Returns a handle to be used with flush_frontbuffer()/present(). + * + * Query format support with screen::is_format_supported and usage + * XXX. + */ +PUBLIC struct pipe_screen *graw_create_window_and_screen( int x, + int y, + unsigned width, + unsigned height, + enum pipe_format format, + void **handle); + +PUBLIC void graw_set_display_func( void (*func)( void ) ); +PUBLIC void graw_main_loop( void ); + +PUBLIC void *graw_parse_geometry_shader( struct pipe_context *pipe, + const char *text ); + +PUBLIC void *graw_parse_vertex_shader( struct pipe_context *pipe, + const char *text ); + +PUBLIC void *graw_parse_fragment_shader( struct pipe_context *pipe, + const char *text ); + +/* Parse a single command-line option, if any. Options include: + * + * -o + * + * If an option has been successfully parsed, argi is updated + * to point just after the option and return TRUE. + */ +PUBLIC bool graw_parse_args(int *argi, int argc, char *argv[]); + +/* Saves surface contents to a file. + * + * If filename is NULL, the filename provided with the `-o' option + * is used. If the option has not been specified, the surface + * will not be saved. + * + * Returns TRUE if the surface has been saved. + */ +PUBLIC bool graw_save_surface_to_file(struct pipe_context *pipe, + struct pipe_surface *surface, + const char *filename); + +#endif diff --git a/src/gallium/include/frontend/opencl_interop.h b/src/gallium/include/frontend/opencl_interop.h new file mode 100644 index 00000000000..498364472b6 --- /dev/null +++ b/src/gallium/include/frontend/opencl_interop.h @@ -0,0 +1,40 @@ +/************************************************************************** + * + * Copyright 2015 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef OPENCL_INTEROP_H +#define OPENCL_INTEROP_H + +/* dlsym these without the "_t" suffix. You should get the correct symbols + * if the OpenCL driver is loaded. + */ + +typedef bool (*opencl_dri_event_add_ref_t)(void *cl_event); +typedef bool (*opencl_dri_event_release_t)(void *cl_event); +typedef bool (*opencl_dri_event_wait_t)(void *cl_event, uint64_t timeout); +typedef struct pipe_fence_handle *(*opencl_dri_event_get_fence_t)(void *cl_event); + +#endif /* OPENCL_INTEROP_H */ diff --git a/src/gallium/include/frontend/sw_driver.h b/src/gallium/include/frontend/sw_driver.h new file mode 100644 index 00000000000..1d59bd5fe56 --- /dev/null +++ b/src/gallium/include/frontend/sw_driver.h @@ -0,0 +1,21 @@ + +#ifndef _SW_DRIVER_H_ +#define _SW_DRIVER_H_ + +#include "pipe/p_compiler.h" + +struct pipe_screen; +struct sw_winsys; + +struct sw_driver_descriptor +{ + struct pipe_screen *(*create_screen)(struct sw_winsys *ws); + struct { + const char * const name; + struct sw_winsys *(*create_winsys)(); + } winsys[]; +}; + +extern const struct sw_driver_descriptor swrast_driver_descriptor; + +#endif diff --git a/src/gallium/include/frontend/sw_winsys.h b/src/gallium/include/frontend/sw_winsys.h new file mode 100644 index 00000000000..86eca9defca --- /dev/null +++ b/src/gallium/include/frontend/sw_winsys.h @@ -0,0 +1,145 @@ +/************************************************************************** + * + * Copyright 2007-2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/** + * @file + * Software rasterizer winsys. + */ + + +#ifndef SW_WINSYS_H +#define SW_WINSYS_H + + +#include "pipe/p_format.h" +#include "frontend/winsys_handle.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +struct pipe_screen; +struct pipe_context; +struct pipe_resource; +struct pipe_box; + +/** + * Opaque pointer. + */ +struct sw_displaytarget; + + +/** + * This is the interface that sw expects any window system + * hosting it to implement. + * + * sw is for the most part a self sufficient driver. The only thing it + * does not know is how to display a surface. + */ +struct sw_winsys +{ + void + (*destroy)( struct sw_winsys *ws ); + + bool + (*is_displaytarget_format_supported)( struct sw_winsys *ws, + unsigned tex_usage, + enum pipe_format format ); + + /** + * Allocate storage for a render target. + * + * Often surfaces which are meant to be blitted to the front screen (i.e., + * display targets) must be allocated with special characteristics, memory + * pools, or obtained directly from the windowing system. + * + * This callback is invoked by the pipe_screen when creating a texture marked + * with the PIPE_BIND_DISPLAY_TARGET flag to get the underlying + * storage. + */ + struct sw_displaytarget * + (*displaytarget_create)( struct sw_winsys *ws, + unsigned tex_usage, + enum pipe_format format, + unsigned width, unsigned height, + unsigned alignment, + const void *front_private, + unsigned *stride ); + + /** + * Used to implement texture_from_handle. + */ + struct sw_displaytarget * + (*displaytarget_from_handle)( struct sw_winsys *ws, + const struct pipe_resource *templat, + struct winsys_handle *whandle, + unsigned *stride ); + + /** + * Used to implement texture_get_handle. + */ + bool + (*displaytarget_get_handle)( struct sw_winsys *ws, + struct sw_displaytarget *dt, + struct winsys_handle *whandle ); + + /** + * \param flags bitmask of PIPE_TRANSFER_x flags + */ + void * + (*displaytarget_map)( struct sw_winsys *ws, + struct sw_displaytarget *dt, + unsigned flags ); + + void + (*displaytarget_unmap)( struct sw_winsys *ws, + struct sw_displaytarget *dt ); + + /** + * @sa pipe_screen:flush_frontbuffer. + * + * This call will likely become asynchronous eventually. + */ + void + (*displaytarget_display)( struct sw_winsys *ws, + struct sw_displaytarget *dt, + void *context_private, + struct pipe_box *box ); + + void + (*displaytarget_destroy)( struct sw_winsys *ws, + struct sw_displaytarget *dt ); +}; + + + +#ifdef __cplusplus +} +#endif + +#endif /* SW_WINSYS_H */ diff --git a/src/gallium/include/frontend/vdpau_dmabuf.h b/src/gallium/include/frontend/vdpau_dmabuf.h new file mode 100644 index 00000000000..f838c925f30 --- /dev/null +++ b/src/gallium/include/frontend/vdpau_dmabuf.h @@ -0,0 +1,94 @@ +/************************************************************************** + * + * Copyright 2016 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/* + * Authors: + * Christian König + * + */ + +#ifndef _VDPAU_DMABUF_H_ +#define _VDPAU_DMABUF_H_ + +#include + +/* driver specific functions for NV_vdpau_interop */ +#ifndef VDP_FUNC_ID_BASE_DRIVER +#define VDP_FUNC_ID_BASE_DRIVER 0x2000 +#endif + +/* New DMA-buf based implementation */ +#define VDP_FUNC_ID_VIDEO_SURFACE_DMA_BUF (VDP_FUNC_ID_BASE_DRIVER + 2) +#define VDP_FUNC_ID_OUTPUT_SURFACE_DMA_BUF (VDP_FUNC_ID_BASE_DRIVER + 3) + +/* Define some more internal RGBA formats for more + * robust handling of Video Surfaces + */ +#define VDP_RGBA_FORMAT_R8 (-1) +#define VDP_RGBA_FORMAT_R8G8 (-2) + +struct VdpSurfaceDMABufDesc { + /* DMA-buf file descriptor */ + uint32_t handle; + /* Width in pixel */ + uint32_t width; + /* Height in pixel */ + uint32_t height; + /* Offset in bytes */ + uint32_t offset; + /* Stride in bytes */ + uint32_t stride; + /* VDP_RGBA_FORMAT_* as defined in the VDPAU spec and above. */ + uint32_t format; +}; + +/** + * \brief Video surface planes + */ +typedef uint32_t VdpVideoSurfacePlane; + +/** \hideinitializer \brief Luma top field */ +#define VDP_VIDEO_SURFACE_PLANE_LUMA_TOP ((VdpVideoSurfacePlane)0) +/** \hideinitializer \brief Luma bottom field */ +#define VDP_VIDEO_SURFACE_PLANE_LUMA_BOTTOM ((VdpVideoSurfacePlane)1) +/** \hideinitializer \brief Chroma top field */ +#define VDP_VIDEO_SURFACE_PLANE_CHROMA_TOP ((VdpVideoSurfacePlane)2) +/** \hideinitializer \brief Chroma bottom field */ +#define VDP_VIDEO_SURFACE_PLANE_CHROMA_BOTTOM ((VdpVideoSurfacePlane)3) + +typedef VdpStatus VdpVideoSurfaceDMABuf( + VdpVideoSurface surface, + VdpVideoSurfacePlane plane, + struct VdpSurfaceDMABufDesc * result +); + +typedef VdpStatus VdpOutputSurfaceDMABuf( + VdpOutputSurface surface, + struct VdpSurfaceDMABufDesc * result +); + +#endif /* _VDPAU_DMABUF_H_ */ diff --git a/src/gallium/include/frontend/vdpau_funcs.h b/src/gallium/include/frontend/vdpau_funcs.h new file mode 100644 index 00000000000..66e3c23ede4 --- /dev/null +++ b/src/gallium/include/frontend/vdpau_funcs.h @@ -0,0 +1,65 @@ +/************************************************************************** + * + * Copyright 2016 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/* + * Authors: + * Christian König + * + */ + +#ifndef _VDPAU_FUNCS_H_ +#define _VDPAU_FUNCS_H_ + +#include "vdpau_dmabuf.h" + +/* Used for implementing NV_vdpau_interop */ +static inline enum pipe_format +VdpFormatRGBAToPipe(uint32_t vdpau_format) +{ + switch (vdpau_format) { + case VDP_RGBA_FORMAT_R8: + return PIPE_FORMAT_R8_UNORM; + case VDP_RGBA_FORMAT_R8G8: + return PIPE_FORMAT_R8G8_UNORM; + case VDP_RGBA_FORMAT_A8: + return PIPE_FORMAT_A8_UNORM; + case VDP_RGBA_FORMAT_B10G10R10A2: + return PIPE_FORMAT_B10G10R10A2_UNORM; + case VDP_RGBA_FORMAT_B8G8R8A8: + return PIPE_FORMAT_B8G8R8A8_UNORM; + case VDP_RGBA_FORMAT_R10G10B10A2: + return PIPE_FORMAT_R10G10B10A2_UNORM; + case VDP_RGBA_FORMAT_R8G8B8A8: + return PIPE_FORMAT_R8G8B8A8_UNORM; + default: + assert(0); + } + + return PIPE_FORMAT_NONE; +} + +#endif /* _VDPAU_FUNCS_H_ */ diff --git a/src/gallium/include/frontend/vdpau_interop.h b/src/gallium/include/frontend/vdpau_interop.h new file mode 100644 index 00000000000..04d455a370a --- /dev/null +++ b/src/gallium/include/frontend/vdpau_interop.h @@ -0,0 +1,54 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/* + * Authors: + * Christian König + * + */ + +#ifndef _VDPAU_INTEROP_H_ +#define _VDPAU_INTEROP_H_ + +/* driver specific functions for NV_vdpau_interop */ +#ifndef VDP_FUNC_ID_BASE_DRIVER +#define VDP_FUNC_ID_BASE_DRIVER 0x2000 +#endif + +/* Older implementation relying on passing pipe_video_buffer and + * pipe_resources around. Deprecated and shouldn't be used for new things. + */ +#define VDP_FUNC_ID_VIDEO_SURFACE_GALLIUM (VDP_FUNC_ID_BASE_DRIVER + 0) +#define VDP_FUNC_ID_OUTPUT_SURFACE_GALLIUM (VDP_FUNC_ID_BASE_DRIVER + 1) + +struct pipe_resource; +struct pipe_video_buffer; + +typedef struct pipe_video_buffer *VdpVideoSurfaceGallium(uint32_t surface); +typedef struct pipe_resource *VdpOutputSurfaceGallium(uint32_t surface); + +#endif /* _VDPAU_INTEROP_H_ */ diff --git a/src/gallium/include/frontend/winsys_handle.h b/src/gallium/include/frontend/winsys_handle.h new file mode 100644 index 00000000000..78f5f4b36f2 --- /dev/null +++ b/src/gallium/include/frontend/winsys_handle.h @@ -0,0 +1,69 @@ + +#ifndef _WINSYS_HANDLE_H_ +#define _WINSYS_HANDLE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define WINSYS_HANDLE_TYPE_SHARED 0 +#define WINSYS_HANDLE_TYPE_KMS 1 +#define WINSYS_HANDLE_TYPE_FD 2 +#define WINSYS_HANDLE_TYPE_SHMID 3 + +/** + * For use with pipe_screen::{texture_from_handle|texture_get_handle}. + */ +struct winsys_handle +{ + /** + * Input for texture_from_handle, valid values are + * WINSYS_HANDLE_TYPE_SHARED or WINSYS_HANDLE_TYPE_FD. + * Input to texture_get_handle, + * to select handle for kms, flink, or prime. + */ + unsigned type; + /** + * Input for texture_get_handle, allows to export the offset + * of a specific layer of an array texture. + */ + unsigned layer; + /** + * Input for texture_get_handle, allows to export of a specific plane of a + * texture. + */ + unsigned plane; + /** + * Input to texture_from_handle. + * Output for texture_get_handle. + */ + unsigned handle; + /** + * Input to texture_from_handle. + * Output for texture_get_handle. + */ + unsigned stride; + /** + * Input to texture_from_handle. + * Output for texture_get_handle. + */ + unsigned offset; + + /** + * Input to resource_from_handle. + * Output from resource_get_handle. + */ + uint64_t format; + + /** + * Input to resource_from_handle. + * Output from resource_get_handle. + */ + uint64_t modifier; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* _WINSYS_HANDLE_H_ */ diff --git a/src/gallium/include/frontend/xlibsw_api.h b/src/gallium/include/frontend/xlibsw_api.h new file mode 100644 index 00000000000..49ffa5df13f --- /dev/null +++ b/src/gallium/include/frontend/xlibsw_api.h @@ -0,0 +1,19 @@ +#ifndef XLIB_SW_WINSYS_H +#define XLIB_SW_WINSYS_H + +#include "frontend/sw_winsys.h" +#include + + +/* This is what the xlib software winsys expects to find in the + * "private" field of flush_frontbuffers(). + * + * Xlib-based state trackers somehow need to know this. + */ +struct xlib_drawable { + Visual *visual; + int depth; + Drawable drawable; +}; + +#endif diff --git a/src/gallium/include/state_tracker/drisw_api.h b/src/gallium/include/state_tracker/drisw_api.h deleted file mode 100644 index 4b5d36c1797..00000000000 --- a/src/gallium/include/state_tracker/drisw_api.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef _DRISW_API_H_ -#define _DRISW_API_H_ - -#include "pipe/p_compiler.h" -#include "sw_winsys.h" - -struct pipe_screen; -struct dri_drawable; - -/** - * This callback struct is intended for the winsys to call the loader. - */ -struct drisw_loader_funcs -{ - void (*get_image) (struct dri_drawable *dri_drawable, - int x, int y, unsigned width, unsigned height, unsigned stride, - void *data); - void (*put_image) (struct dri_drawable *dri_drawable, - void *data, unsigned width, unsigned height); - void (*put_image2) (struct dri_drawable *dri_drawable, - void *data, int x, int y, unsigned width, unsigned height, unsigned stride); - void (*put_image_shm) (struct dri_drawable *dri_drawable, - int shmid, char *shmaddr, unsigned offset, unsigned offset_x, - int x, int y, unsigned width, unsigned height, unsigned stride); -}; - -#endif diff --git a/src/gallium/include/state_tracker/drm_driver.h b/src/gallium/include/state_tracker/drm_driver.h deleted file mode 100644 index f8d77a79721..00000000000 --- a/src/gallium/include/state_tracker/drm_driver.h +++ /dev/null @@ -1,49 +0,0 @@ - -#ifndef _DRM_DRIVER_H_ -#define _DRM_DRIVER_H_ - -#include "pipe/p_compiler.h" - -#include "winsys_handle.h" - -struct pipe_screen; -struct pipe_screen_config; -struct pipe_context; -struct pipe_resource; - -struct drm_driver_descriptor -{ - /** - * Identifying prefix/suffix of the binary, used by the pipe-loader. - */ - const char *driver_name; - - /** - * Pointer to the XML string describing driver-specific driconf options. - * Use DRI_CONF_* macros to create the string. - */ - const char **driconf_xml; - - /** - * Create a pipe srcreen. - * - * This function does any wrapping of the screen. - * For example wrapping trace or rbug debugging drivers around it. - */ - struct pipe_screen* (*create_screen)(int drm_fd, - const struct pipe_screen_config *config); -}; - -extern const struct drm_driver_descriptor driver_descriptor; - -/** - * Instantiate a drm_driver_descriptor struct. - */ -#define DRM_DRIVER_DESCRIPTOR(driver_name_str, driconf, func) \ -const struct drm_driver_descriptor driver_descriptor = { \ - .driver_name = driver_name_str, \ - .driconf_xml = driconf, \ - .create_screen = func, \ -}; - -#endif diff --git a/src/gallium/include/state_tracker/graw.h b/src/gallium/include/state_tracker/graw.h deleted file mode 100644 index af81cc8871b..00000000000 --- a/src/gallium/include/state_tracker/graw.h +++ /dev/null @@ -1,96 +0,0 @@ -/************************************************************************** - * - * Copyright 2010 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#ifndef GALLIUM_RAW_H -#define GALLIUM_RAW_H - -/* This is an API for exercising gallium functionality in a - * platform-neutral fashion. Whatever platform integration is - * necessary to implement this interface is orchestrated by the - * individual target building this entity. - * - * For instance, the graw-xlib target includes code to implement these - * interfaces on top of the X window system. - * - * Programs using this interface may additionally benefit from some of - * the utilities currently in the libgallium.a library, especially - * those for parsing text representations of TGSI shaders. - */ - -#include "pipe/p_compiler.h" -#include "pipe/p_format.h" - -struct pipe_context; -struct pipe_screen; -struct pipe_surface; - -/* Returns a handle to be used with flush_frontbuffer()/present(). - * - * Query format support with screen::is_format_supported and usage - * XXX. - */ -PUBLIC struct pipe_screen *graw_create_window_and_screen( int x, - int y, - unsigned width, - unsigned height, - enum pipe_format format, - void **handle); - -PUBLIC void graw_set_display_func( void (*func)( void ) ); -PUBLIC void graw_main_loop( void ); - -PUBLIC void *graw_parse_geometry_shader( struct pipe_context *pipe, - const char *text ); - -PUBLIC void *graw_parse_vertex_shader( struct pipe_context *pipe, - const char *text ); - -PUBLIC void *graw_parse_fragment_shader( struct pipe_context *pipe, - const char *text ); - -/* Parse a single command-line option, if any. Options include: - * - * -o - * - * If an option has been successfully parsed, argi is updated - * to point just after the option and return TRUE. - */ -PUBLIC bool graw_parse_args(int *argi, int argc, char *argv[]); - -/* Saves surface contents to a file. - * - * If filename is NULL, the filename provided with the `-o' option - * is used. If the option has not been specified, the surface - * will not be saved. - * - * Returns TRUE if the surface has been saved. - */ -PUBLIC bool graw_save_surface_to_file(struct pipe_context *pipe, - struct pipe_surface *surface, - const char *filename); - -#endif diff --git a/src/gallium/include/state_tracker/opencl_interop.h b/src/gallium/include/state_tracker/opencl_interop.h deleted file mode 100644 index 498364472b6..00000000000 --- a/src/gallium/include/state_tracker/opencl_interop.h +++ /dev/null @@ -1,40 +0,0 @@ -/************************************************************************** - * - * Copyright 2015 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#ifndef OPENCL_INTEROP_H -#define OPENCL_INTEROP_H - -/* dlsym these without the "_t" suffix. You should get the correct symbols - * if the OpenCL driver is loaded. - */ - -typedef bool (*opencl_dri_event_add_ref_t)(void *cl_event); -typedef bool (*opencl_dri_event_release_t)(void *cl_event); -typedef bool (*opencl_dri_event_wait_t)(void *cl_event, uint64_t timeout); -typedef struct pipe_fence_handle *(*opencl_dri_event_get_fence_t)(void *cl_event); - -#endif /* OPENCL_INTEROP_H */ diff --git a/src/gallium/include/state_tracker/st_api.h b/src/gallium/include/state_tracker/st_api.h deleted file mode 100644 index 3777449e61d..00000000000 --- a/src/gallium/include/state_tracker/st_api.h +++ /dev/null @@ -1,575 +0,0 @@ -/********************************************************** - * Copyright 2010 VMware, Inc. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - **********************************************************/ - - -#ifndef _ST_API_H_ -#define _ST_API_H_ - -#include "pipe/p_format.h" - -/** - * \file API for communication between state trackers and state tracker - * managers. - * - * While both are state tackers, we use the term state tracker for rendering - * APIs such as OpenGL or OpenVG, and state tracker manager for window system - * APIs such as EGL or GLX in this file. - * - * This file defines an API to be implemented by both state trackers and state - * tracker managers. - */ - -/** - * The supported rendering API of a state tracker. - */ -enum st_api_type { - ST_API_OPENGL, - ST_API_OPENVG, - - ST_API_COUNT -}; - -/** - * The profile of a context. - */ -enum st_profile_type -{ - ST_PROFILE_DEFAULT, /**< OpenGL compatibility profile */ - ST_PROFILE_OPENGL_CORE, /**< OpenGL 3.2+ core profile */ - ST_PROFILE_OPENGL_ES1, /**< OpenGL ES 1.x */ - ST_PROFILE_OPENGL_ES2 /**< OpenGL ES 2.0 */ -}; - -/* for profile_mask in st_api */ -#define ST_PROFILE_DEFAULT_MASK (1 << ST_PROFILE_DEFAULT) -#define ST_PROFILE_OPENGL_CORE_MASK (1 << ST_PROFILE_OPENGL_CORE) -#define ST_PROFILE_OPENGL_ES1_MASK (1 << ST_PROFILE_OPENGL_ES1) -#define ST_PROFILE_OPENGL_ES2_MASK (1 << ST_PROFILE_OPENGL_ES2) - -/** - * Optional API/state tracker features. - */ -enum st_api_feature -{ - ST_API_FEATURE_MS_VISUALS /**< support for multisample visuals */ -}; - -/* for feature_mask in st_api */ -#define ST_API_FEATURE_MS_VISUALS_MASK (1 << ST_API_FEATURE_MS_VISUALS) - -/** - * New context flags for GL 3.0 and beyond. - * - * Profile information (core vs. compatibilty for OpenGL 3.2+) is communicated - * through the \c st_profile_type, not through flags. - */ -#define ST_CONTEXT_FLAG_DEBUG (1 << 0) -#define ST_CONTEXT_FLAG_FORWARD_COMPATIBLE (1 << 1) -#define ST_CONTEXT_FLAG_ROBUST_ACCESS (1 << 2) -#define ST_CONTEXT_FLAG_RESET_NOTIFICATION_ENABLED (1 << 3) -#define ST_CONTEXT_FLAG_NO_ERROR (1 << 4) -#define ST_CONTEXT_FLAG_RELEASE_NONE (1 << 5) -#define ST_CONTEXT_FLAG_HIGH_PRIORITY (1 << 6) -#define ST_CONTEXT_FLAG_LOW_PRIORITY (1 << 7) - -/** - * Reasons that context creation might fail. - */ -enum st_context_error { - ST_CONTEXT_SUCCESS = 0, - ST_CONTEXT_ERROR_NO_MEMORY, - ST_CONTEXT_ERROR_BAD_API, - ST_CONTEXT_ERROR_BAD_VERSION, - ST_CONTEXT_ERROR_BAD_FLAG, - ST_CONTEXT_ERROR_UNKNOWN_ATTRIBUTE, - ST_CONTEXT_ERROR_UNKNOWN_FLAG -}; - -/** - * Used in st_context_iface->teximage. - */ -enum st_texture_type { - ST_TEXTURE_1D, - ST_TEXTURE_2D, - ST_TEXTURE_3D, - ST_TEXTURE_RECT -}; - -/** - * Available attachments of framebuffer. - */ -enum st_attachment_type { - ST_ATTACHMENT_FRONT_LEFT, - ST_ATTACHMENT_BACK_LEFT, - ST_ATTACHMENT_FRONT_RIGHT, - ST_ATTACHMENT_BACK_RIGHT, - ST_ATTACHMENT_DEPTH_STENCIL, - ST_ATTACHMENT_ACCUM, - ST_ATTACHMENT_SAMPLE, - - ST_ATTACHMENT_COUNT, - ST_ATTACHMENT_INVALID = -1 -}; - -/* for buffer_mask in st_visual */ -#define ST_ATTACHMENT_FRONT_LEFT_MASK (1 << ST_ATTACHMENT_FRONT_LEFT) -#define ST_ATTACHMENT_BACK_LEFT_MASK (1 << ST_ATTACHMENT_BACK_LEFT) -#define ST_ATTACHMENT_FRONT_RIGHT_MASK (1 << ST_ATTACHMENT_FRONT_RIGHT) -#define ST_ATTACHMENT_BACK_RIGHT_MASK (1 << ST_ATTACHMENT_BACK_RIGHT) -#define ST_ATTACHMENT_DEPTH_STENCIL_MASK (1 << ST_ATTACHMENT_DEPTH_STENCIL) -#define ST_ATTACHMENT_ACCUM_MASK (1 << ST_ATTACHMENT_ACCUM) -#define ST_ATTACHMENT_SAMPLE_MASK (1 << ST_ATTACHMENT_SAMPLE) - -/** - * Flush flags. - */ -#define ST_FLUSH_FRONT (1 << 0) -#define ST_FLUSH_END_OF_FRAME (1 << 1) -#define ST_FLUSH_WAIT (1 << 2) -#define ST_FLUSH_FENCE_FD (1 << 3) - -/** - * Value to st_manager->get_param function. - */ -enum st_manager_param { - /** - * The dri state tracker on old libGL's doesn't do the right thing - * with regards to invalidating the framebuffers. - * - * For the mesa state tracker that means that it needs to invalidate - * the framebuffer in glViewport itself. - */ - ST_MANAGER_BROKEN_INVALIDATE -}; - -struct pipe_context; -struct pipe_resource; -struct pipe_fence_handle; -struct util_queue_monitoring; - -/** - * Used in st_manager_iface->get_egl_image. - */ -struct st_egl_image -{ - /* this is owned by the caller */ - struct pipe_resource *texture; - - /* format only differs from texture->format for multi-planar (YUV): */ - enum pipe_format format; - - unsigned level; - unsigned layer; - /* GL internal format. */ - unsigned internalformat; -}; - -/** - * Represent the visual of a framebuffer. - */ -struct st_visual -{ - bool no_config; - - /** - * Available buffers. Bitfield of ST_ATTACHMENT_*_MASK bits. - */ - unsigned buffer_mask; - - /** - * Buffer formats. The formats are always set even when the buffer is - * not available. - */ - enum pipe_format color_format; - enum pipe_format depth_stencil_format; - enum pipe_format accum_format; - unsigned samples; - - /** - * Desired render buffer. - */ - enum st_attachment_type render_buffer; -}; - - -/** - * Configuration options from driconf - */ -struct st_config_options -{ - bool disable_blend_func_extended; - bool disable_glsl_line_continuations; - bool disable_arb_gpu_shader5; - bool force_glsl_extensions_warn; - unsigned force_glsl_version; - bool allow_glsl_extension_directive_midshader; - bool allow_glsl_builtin_const_expression; - bool allow_glsl_relaxed_es; - bool allow_glsl_builtin_variable_redeclaration; - bool allow_higher_compat_version; - bool glsl_zero_init; - bool vs_position_always_invariant; - bool force_glsl_abs_sqrt; - bool allow_glsl_cross_stage_interpolation_mismatch; - bool allow_glsl_layout_qualifier_on_function_parameters; - bool allow_draw_out_of_order; - bool force_integer_tex_nearest; - char *force_gl_vendor; - unsigned char config_options_sha1[20]; -}; - -/** - * Represent the attributes of a context. - */ -struct st_context_attribs -{ - /** - * The profile and minimal version to support. - * - * The valid profiles and versions are rendering API dependent. The latest - * version satisfying the request should be returned. - */ - enum st_profile_type profile; - int major, minor; - - /** Mask of ST_CONTEXT_FLAG_x bits */ - unsigned flags; - - /** - * The visual of the framebuffers the context will be bound to. - */ - struct st_visual visual; - - /** - * Configuration options. - */ - struct st_config_options options; -}; - -struct st_context_iface; -struct st_manager; - -/** - * Represent a windowing system drawable. - * - * The framebuffer is implemented by the state tracker manager and - * used by the state trackers. - * - * Instead of the winsys poking into the API context to figure - * out what buffers that might be needed in the future by the API - * context, it calls into the framebuffer to get the textures. - * - * This structure along with the notify_invalid_framebuffer - * allows framebuffers to be shared between different threads - * but at the same make the API context free from thread - * synchronization primitves, with the exception of a small - * atomic flag used for notification of framebuffer dirty status. - * - * The thread synchronization is put inside the framebuffer - * and only called once the framebuffer has become dirty. - */ -struct st_framebuffer_iface -{ - /** - * Atomic stamp which changes when framebuffers need to be updated. - */ - int32_t stamp; - - /** - * Identifier that uniquely identifies the framebuffer interface object. - */ - uint32_t ID; - - /** - * The state tracker manager that manages this object. - */ - struct st_manager *state_manager; - - /** - * Available for the state tracker manager to use. - */ - void *st_manager_private; - - /** - * The visual of a framebuffer. - */ - const struct st_visual *visual; - - /** - * Flush the front buffer. - * - * On some window systems, changes to the front buffers are not immediately - * visible. They need to be flushed. - * - * @att is one of the front buffer attachments. - */ - bool (*flush_front)(struct st_context_iface *stctx, - struct st_framebuffer_iface *stfbi, - enum st_attachment_type statt); - - /** - * The state tracker asks for the textures it needs. - * - * It should try to only ask for attachments that it currently renders - * to, thus allowing the winsys to delay the allocation of textures not - * needed. For example front buffer attachments are not needed if you - * only do back buffer rendering. - * - * The implementor of this function needs to also ensure - * thread safty as this call might be done from multiple threads. - * - * The returned textures are owned by the caller. They should be - * unreferenced when no longer used. If this function is called multiple - * times with different sets of attachments, those buffers not included in - * the last call might be destroyed. This behavior might change in the - * future. - */ - bool (*validate)(struct st_context_iface *stctx, - struct st_framebuffer_iface *stfbi, - const enum st_attachment_type *statts, - unsigned count, - struct pipe_resource **out); - bool (*flush_swapbuffers) (struct st_context_iface *stctx, - struct st_framebuffer_iface *stfbi); -}; - -/** - * Represent a rendering context. - * - * This entity is created from st_api and used by the state tracker manager. - */ -struct st_context_iface -{ - /** - * Available for the state tracker and the manager to use. - */ - void *st_context_private; - void *st_manager_private; - - /** - * The state tracker manager that manages this object. - */ - struct st_manager *state_manager; - - /** - * The CSO context associated with this context in case we need to draw - * something before swap buffers. - */ - struct cso_context *cso_context; - - /** - * The gallium context. - */ - struct pipe_context *pipe; - - /** - * Destroy the context. - */ - void (*destroy)(struct st_context_iface *stctxi); - - /** - * Flush all drawing from context to the pipe also flushes the pipe. - */ - void (*flush)(struct st_context_iface *stctxi, unsigned flags, - struct pipe_fence_handle **fence, - void (*notify_before_flush_cb) (void*), - void* notify_before_flush_cb_args); - - /** - * Replace the texture image of a texture object at the specified level. - * - * This function is optional. - */ - bool (*teximage)(struct st_context_iface *stctxi, - enum st_texture_type target, - int level, enum pipe_format internal_format, - struct pipe_resource *tex, bool mipmap); - - /** - * Used to implement glXCopyContext. - */ - void (*copy)(struct st_context_iface *stctxi, - struct st_context_iface *stsrci, unsigned mask); - - /** - * Used to implement wglShareLists. - */ - bool (*share)(struct st_context_iface *stctxi, - struct st_context_iface *stsrci); - - /** - * Start the thread if the API has a worker thread. - * Called after the context has been created and fully initialized on both - * sides (e.g. st/mesa and st/dri). - */ - void (*start_thread)(struct st_context_iface *stctxi); - - /** - * If the API is multithreaded, wait for all queued commands to complete. - * Called from the main thread. - */ - void (*thread_finish)(struct st_context_iface *stctxi); -}; - - -/** - * Represent a state tracker manager. - * - * This interface is implemented by the state tracker manager. It corresponds - * to a "display" in the window system. - */ -struct st_manager -{ - struct pipe_screen *screen; - - /** - * Look up and return the info of an EGLImage. - * - * This is used to implement for example EGLImageTargetTexture2DOES. - * The GLeglImageOES agrument of that call is passed directly to this - * function call and the information needed to access this is returned - * in the given struct out. - * - * @smapi: manager owning the caller context - * @stctx: caller context - * @egl_image: EGLImage that caller recived - * @out: return struct filled out with access information. - * - * This function is optional. - */ - bool (*get_egl_image)(struct st_manager *smapi, - void *egl_image, - struct st_egl_image *out); - - /** - * Query an manager param. - */ - int (*get_param)(struct st_manager *smapi, - enum st_manager_param param); - - /** - * Call the loader function setBackgroundContext. Called from the worker - * thread. - */ - void (*set_background_context)(struct st_context_iface *stctxi, - struct util_queue_monitoring *queue_info); - - /** - * Destroy any private data used by the state tracker manager. - */ - void (*destroy)(struct st_manager *smapi); - - /** - * Available for the state tracker manager to use. - */ - void *st_manager_private; -}; - -/** - * Represent a rendering API such as OpenGL or OpenVG. - * - * Implemented by the state tracker and used by the state tracker manager. - */ -struct st_api -{ - /** - * The name of the rendering API. This is informative. - */ - const char *name; - - /** - * The supported rendering API. - */ - enum st_api_type api; - - /** - * The supported profiles. Tested with ST_PROFILE_*_MASK. - */ - unsigned profile_mask; - - /** - * The supported optional features. Tested with ST_FEATURE_*_MASK. - */ - unsigned feature_mask; - - /** - * Destroy the API. - */ - void (*destroy)(struct st_api *stapi); - - /** - * Query supported OpenGL versions. (if applicable) - * The format is (major*10+minor). - */ - void (*query_versions)(struct st_api *stapi, struct st_manager *sm, - struct st_config_options *options, - int *gl_core_version, - int *gl_compat_version, - int *gl_es1_version, - int *gl_es2_version); - - /** - * Create a rendering context. - */ - struct st_context_iface *(*create_context)(struct st_api *stapi, - struct st_manager *smapi, - const struct st_context_attribs *attribs, - enum st_context_error *error, - struct st_context_iface *stsharei); - - /** - * Bind the context to the calling thread with draw and read as drawables. - * - * The framebuffers might be NULL, or might have different visuals than the - * context does. - */ - bool (*make_current)(struct st_api *stapi, - struct st_context_iface *stctxi, - struct st_framebuffer_iface *stdrawi, - struct st_framebuffer_iface *streadi); - - /** - * Get the currently bound context in the calling thread. - */ - struct st_context_iface *(*get_current)(struct st_api *stapi); - - /** - * Notify the st manager the framebuffer interface object - * is no longer valid. - */ - void (*destroy_drawable)(struct st_api *stapi, - struct st_framebuffer_iface *stfbi); -}; - -/** - * Return true if the visual has the specified buffers. - */ -static inline bool -st_visual_have_buffers(const struct st_visual *visual, unsigned mask) -{ - return ((visual->buffer_mask & mask) == mask); -} - -#endif /* _ST_API_H_ */ diff --git a/src/gallium/include/state_tracker/sw_driver.h b/src/gallium/include/state_tracker/sw_driver.h deleted file mode 100644 index 1d59bd5fe56..00000000000 --- a/src/gallium/include/state_tracker/sw_driver.h +++ /dev/null @@ -1,21 +0,0 @@ - -#ifndef _SW_DRIVER_H_ -#define _SW_DRIVER_H_ - -#include "pipe/p_compiler.h" - -struct pipe_screen; -struct sw_winsys; - -struct sw_driver_descriptor -{ - struct pipe_screen *(*create_screen)(struct sw_winsys *ws); - struct { - const char * const name; - struct sw_winsys *(*create_winsys)(); - } winsys[]; -}; - -extern const struct sw_driver_descriptor swrast_driver_descriptor; - -#endif diff --git a/src/gallium/include/state_tracker/sw_winsys.h b/src/gallium/include/state_tracker/sw_winsys.h deleted file mode 100644 index 43a73830f6b..00000000000 --- a/src/gallium/include/state_tracker/sw_winsys.h +++ /dev/null @@ -1,145 +0,0 @@ -/************************************************************************** - * - * Copyright 2007-2009 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/** - * @file - * Software rasterizer winsys. - */ - - -#ifndef SW_WINSYS_H -#define SW_WINSYS_H - - -#include "pipe/p_format.h" -#include "state_tracker/winsys_handle.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -struct pipe_screen; -struct pipe_context; -struct pipe_resource; -struct pipe_box; - -/** - * Opaque pointer. - */ -struct sw_displaytarget; - - -/** - * This is the interface that sw expects any window system - * hosting it to implement. - * - * sw is for the most part a self sufficient driver. The only thing it - * does not know is how to display a surface. - */ -struct sw_winsys -{ - void - (*destroy)( struct sw_winsys *ws ); - - bool - (*is_displaytarget_format_supported)( struct sw_winsys *ws, - unsigned tex_usage, - enum pipe_format format ); - - /** - * Allocate storage for a render target. - * - * Often surfaces which are meant to be blitted to the front screen (i.e., - * display targets) must be allocated with special characteristics, memory - * pools, or obtained directly from the windowing system. - * - * This callback is invoked by the pipe_screen when creating a texture marked - * with the PIPE_BIND_DISPLAY_TARGET flag to get the underlying - * storage. - */ - struct sw_displaytarget * - (*displaytarget_create)( struct sw_winsys *ws, - unsigned tex_usage, - enum pipe_format format, - unsigned width, unsigned height, - unsigned alignment, - const void *front_private, - unsigned *stride ); - - /** - * Used to implement texture_from_handle. - */ - struct sw_displaytarget * - (*displaytarget_from_handle)( struct sw_winsys *ws, - const struct pipe_resource *templat, - struct winsys_handle *whandle, - unsigned *stride ); - - /** - * Used to implement texture_get_handle. - */ - bool - (*displaytarget_get_handle)( struct sw_winsys *ws, - struct sw_displaytarget *dt, - struct winsys_handle *whandle ); - - /** - * \param flags bitmask of PIPE_TRANSFER_x flags - */ - void * - (*displaytarget_map)( struct sw_winsys *ws, - struct sw_displaytarget *dt, - unsigned flags ); - - void - (*displaytarget_unmap)( struct sw_winsys *ws, - struct sw_displaytarget *dt ); - - /** - * @sa pipe_screen:flush_frontbuffer. - * - * This call will likely become asynchronous eventually. - */ - void - (*displaytarget_display)( struct sw_winsys *ws, - struct sw_displaytarget *dt, - void *context_private, - struct pipe_box *box ); - - void - (*displaytarget_destroy)( struct sw_winsys *ws, - struct sw_displaytarget *dt ); -}; - - - -#ifdef __cplusplus -} -#endif - -#endif /* SW_WINSYS_H */ diff --git a/src/gallium/include/state_tracker/vdpau_dmabuf.h b/src/gallium/include/state_tracker/vdpau_dmabuf.h deleted file mode 100644 index f838c925f30..00000000000 --- a/src/gallium/include/state_tracker/vdpau_dmabuf.h +++ /dev/null @@ -1,94 +0,0 @@ -/************************************************************************** - * - * Copyright 2016 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/* - * Authors: - * Christian König - * - */ - -#ifndef _VDPAU_DMABUF_H_ -#define _VDPAU_DMABUF_H_ - -#include - -/* driver specific functions for NV_vdpau_interop */ -#ifndef VDP_FUNC_ID_BASE_DRIVER -#define VDP_FUNC_ID_BASE_DRIVER 0x2000 -#endif - -/* New DMA-buf based implementation */ -#define VDP_FUNC_ID_VIDEO_SURFACE_DMA_BUF (VDP_FUNC_ID_BASE_DRIVER + 2) -#define VDP_FUNC_ID_OUTPUT_SURFACE_DMA_BUF (VDP_FUNC_ID_BASE_DRIVER + 3) - -/* Define some more internal RGBA formats for more - * robust handling of Video Surfaces - */ -#define VDP_RGBA_FORMAT_R8 (-1) -#define VDP_RGBA_FORMAT_R8G8 (-2) - -struct VdpSurfaceDMABufDesc { - /* DMA-buf file descriptor */ - uint32_t handle; - /* Width in pixel */ - uint32_t width; - /* Height in pixel */ - uint32_t height; - /* Offset in bytes */ - uint32_t offset; - /* Stride in bytes */ - uint32_t stride; - /* VDP_RGBA_FORMAT_* as defined in the VDPAU spec and above. */ - uint32_t format; -}; - -/** - * \brief Video surface planes - */ -typedef uint32_t VdpVideoSurfacePlane; - -/** \hideinitializer \brief Luma top field */ -#define VDP_VIDEO_SURFACE_PLANE_LUMA_TOP ((VdpVideoSurfacePlane)0) -/** \hideinitializer \brief Luma bottom field */ -#define VDP_VIDEO_SURFACE_PLANE_LUMA_BOTTOM ((VdpVideoSurfacePlane)1) -/** \hideinitializer \brief Chroma top field */ -#define VDP_VIDEO_SURFACE_PLANE_CHROMA_TOP ((VdpVideoSurfacePlane)2) -/** \hideinitializer \brief Chroma bottom field */ -#define VDP_VIDEO_SURFACE_PLANE_CHROMA_BOTTOM ((VdpVideoSurfacePlane)3) - -typedef VdpStatus VdpVideoSurfaceDMABuf( - VdpVideoSurface surface, - VdpVideoSurfacePlane plane, - struct VdpSurfaceDMABufDesc * result -); - -typedef VdpStatus VdpOutputSurfaceDMABuf( - VdpOutputSurface surface, - struct VdpSurfaceDMABufDesc * result -); - -#endif /* _VDPAU_DMABUF_H_ */ diff --git a/src/gallium/include/state_tracker/vdpau_funcs.h b/src/gallium/include/state_tracker/vdpau_funcs.h deleted file mode 100644 index 66e3c23ede4..00000000000 --- a/src/gallium/include/state_tracker/vdpau_funcs.h +++ /dev/null @@ -1,65 +0,0 @@ -/************************************************************************** - * - * Copyright 2016 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/* - * Authors: - * Christian König - * - */ - -#ifndef _VDPAU_FUNCS_H_ -#define _VDPAU_FUNCS_H_ - -#include "vdpau_dmabuf.h" - -/* Used for implementing NV_vdpau_interop */ -static inline enum pipe_format -VdpFormatRGBAToPipe(uint32_t vdpau_format) -{ - switch (vdpau_format) { - case VDP_RGBA_FORMAT_R8: - return PIPE_FORMAT_R8_UNORM; - case VDP_RGBA_FORMAT_R8G8: - return PIPE_FORMAT_R8G8_UNORM; - case VDP_RGBA_FORMAT_A8: - return PIPE_FORMAT_A8_UNORM; - case VDP_RGBA_FORMAT_B10G10R10A2: - return PIPE_FORMAT_B10G10R10A2_UNORM; - case VDP_RGBA_FORMAT_B8G8R8A8: - return PIPE_FORMAT_B8G8R8A8_UNORM; - case VDP_RGBA_FORMAT_R10G10B10A2: - return PIPE_FORMAT_R10G10B10A2_UNORM; - case VDP_RGBA_FORMAT_R8G8B8A8: - return PIPE_FORMAT_R8G8B8A8_UNORM; - default: - assert(0); - } - - return PIPE_FORMAT_NONE; -} - -#endif /* _VDPAU_FUNCS_H_ */ diff --git a/src/gallium/include/state_tracker/vdpau_interop.h b/src/gallium/include/state_tracker/vdpau_interop.h deleted file mode 100644 index 04d455a370a..00000000000 --- a/src/gallium/include/state_tracker/vdpau_interop.h +++ /dev/null @@ -1,54 +0,0 @@ -/************************************************************************** - * - * Copyright 2013 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/* - * Authors: - * Christian König - * - */ - -#ifndef _VDPAU_INTEROP_H_ -#define _VDPAU_INTEROP_H_ - -/* driver specific functions for NV_vdpau_interop */ -#ifndef VDP_FUNC_ID_BASE_DRIVER -#define VDP_FUNC_ID_BASE_DRIVER 0x2000 -#endif - -/* Older implementation relying on passing pipe_video_buffer and - * pipe_resources around. Deprecated and shouldn't be used for new things. - */ -#define VDP_FUNC_ID_VIDEO_SURFACE_GALLIUM (VDP_FUNC_ID_BASE_DRIVER + 0) -#define VDP_FUNC_ID_OUTPUT_SURFACE_GALLIUM (VDP_FUNC_ID_BASE_DRIVER + 1) - -struct pipe_resource; -struct pipe_video_buffer; - -typedef struct pipe_video_buffer *VdpVideoSurfaceGallium(uint32_t surface); -typedef struct pipe_resource *VdpOutputSurfaceGallium(uint32_t surface); - -#endif /* _VDPAU_INTEROP_H_ */ diff --git a/src/gallium/include/state_tracker/winsys_handle.h b/src/gallium/include/state_tracker/winsys_handle.h deleted file mode 100644 index 78f5f4b36f2..00000000000 --- a/src/gallium/include/state_tracker/winsys_handle.h +++ /dev/null @@ -1,69 +0,0 @@ - -#ifndef _WINSYS_HANDLE_H_ -#define _WINSYS_HANDLE_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#define WINSYS_HANDLE_TYPE_SHARED 0 -#define WINSYS_HANDLE_TYPE_KMS 1 -#define WINSYS_HANDLE_TYPE_FD 2 -#define WINSYS_HANDLE_TYPE_SHMID 3 - -/** - * For use with pipe_screen::{texture_from_handle|texture_get_handle}. - */ -struct winsys_handle -{ - /** - * Input for texture_from_handle, valid values are - * WINSYS_HANDLE_TYPE_SHARED or WINSYS_HANDLE_TYPE_FD. - * Input to texture_get_handle, - * to select handle for kms, flink, or prime. - */ - unsigned type; - /** - * Input for texture_get_handle, allows to export the offset - * of a specific layer of an array texture. - */ - unsigned layer; - /** - * Input for texture_get_handle, allows to export of a specific plane of a - * texture. - */ - unsigned plane; - /** - * Input to texture_from_handle. - * Output for texture_get_handle. - */ - unsigned handle; - /** - * Input to texture_from_handle. - * Output for texture_get_handle. - */ - unsigned stride; - /** - * Input to texture_from_handle. - * Output for texture_get_handle. - */ - unsigned offset; - - /** - * Input to resource_from_handle. - * Output from resource_get_handle. - */ - uint64_t format; - - /** - * Input to resource_from_handle. - * Output from resource_get_handle. - */ - uint64_t modifier; -}; - -#ifdef __cplusplus -} -#endif - -#endif /* _WINSYS_HANDLE_H_ */ diff --git a/src/gallium/include/state_tracker/xlibsw_api.h b/src/gallium/include/state_tracker/xlibsw_api.h deleted file mode 100644 index 930127981eb..00000000000 --- a/src/gallium/include/state_tracker/xlibsw_api.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef XLIB_SW_WINSYS_H -#define XLIB_SW_WINSYS_H - -#include "state_tracker/sw_winsys.h" -#include - - -/* This is what the xlib software winsys expects to find in the - * "private" field of flush_frontbuffers(). - * - * Xlib-based state trackers somehow need to know this. - */ -struct xlib_drawable { - Visual *visual; - int depth; - Drawable drawable; -}; - -#endif diff --git a/src/gallium/meson.build b/src/gallium/meson.build index 1f81fcf1fd5..ba26a50bced 100644 --- a/src/gallium/meson.build +++ b/src/gallium/meson.build @@ -168,52 +168,52 @@ if with_gallium_opencl # consumer subdir('targets/pipe-loader') - subdir('state_trackers/clover') + subdir('frontends/clover') subdir('targets/opencl') endif if with_dri - subdir('state_trackers/dri') + subdir('frontends/dri') subdir('targets/dri') endif if with_osmesa == 'gallium' - subdir('state_trackers/osmesa') + subdir('frontends/osmesa') subdir('targets/osmesa') endif if with_glx == 'gallium-xlib' subdir('winsys/sw/xlib') - subdir('state_trackers/glx/xlib') + subdir('frontends/glx/xlib') subdir('targets/libgl-xlib') endif if with_gallium_vdpau - subdir('state_trackers/vdpau') + subdir('frontends/vdpau') subdir('targets/vdpau') endif if with_gallium_xvmc - subdir('state_trackers/xvmc') + subdir('frontends/xvmc') subdir('targets/xvmc') endif if with_gallium_omx != 'disabled' - subdir('state_trackers/omx') + subdir('frontends/omx') subdir('targets/omx') endif if with_gallium_va - subdir('state_trackers/va') + subdir('frontends/va') subdir('targets/va') endif if with_gallium_xa - subdir('state_trackers/xa') + subdir('frontends/xa') subdir('targets/xa') endif if with_platform_haiku - subdir('state_trackers/hgl') + subdir('frontends/hgl') subdir('targets/haiku-softpipe') endif if with_gallium_st_nine - subdir('state_trackers/nine') + subdir('frontends/nine') subdir('targets/d3dadapter9') endif if with_platform_windows - subdir('state_trackers/wgl') + subdir('frontends/wgl') subdir('targets/libgl-gdi') endif if with_tests diff --git a/src/gallium/state_trackers/README b/src/gallium/state_trackers/README deleted file mode 100644 index 28dd27bbd50..00000000000 --- a/src/gallium/state_trackers/README +++ /dev/null @@ -1,2 +0,0 @@ -This directory is a placeholder for incubating state-trackers. Mesa's -state-tracker is in src/mesa. diff --git a/src/gallium/state_trackers/clover/Doxyfile b/src/gallium/state_trackers/clover/Doxyfile deleted file mode 100644 index 19337bbd656..00000000000 --- a/src/gallium/state_trackers/clover/Doxyfile +++ /dev/null @@ -1,1716 +0,0 @@ -# Doxyfile 1.7.4 - -# This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project. -# -# All text after a hash (#) is considered a comment and will be ignored. -# The format is: -# TAG = value [value, ...] -# For lists items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" "). - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- - -# This tag specifies the encoding used for all characters in the config file -# that follow. The default is UTF-8 which is also the encoding used for all -# text before the first occurrence of this tag. Doxygen uses libiconv (or the -# iconv built into libc) for the transcoding. See -# http://www.gnu.org/software/libiconv for the list of possible encodings. - -DOXYFILE_ENCODING = UTF-8 - -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded -# by quotes) that should identify the project. - -PROJECT_NAME = Clover - -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or -# if some version control system is used. - -PROJECT_NUMBER = - -# Using the PROJECT_BRIEF tag one can provide an optional one line description -# for a project that appears at the top of each page and should give viewer -# a quick idea about the purpose of the project. Keep the description short. - -PROJECT_BRIEF = - -# With the PROJECT_LOGO tag one can specify an logo or icon that is -# included in the documentation. The maximum height of the logo should not -# exceed 55 pixels and the maximum width should not exceed 200 pixels. -# Doxygen will copy the logo to the output directory. - -PROJECT_LOGO = - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location -# where doxygen was started. If left blank the current directory will be used. - -OUTPUT_DIRECTORY = - -# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create -# 4096 sub-directories (in 2 levels) under the output directory of each output -# format and will distribute the generated files over these directories. -# Enabling this option can be useful when feeding doxygen a huge amount of -# source files, where putting all generated files in the same directory would -# otherwise cause performance problems for the file system. - -CREATE_SUBDIRS = NO - -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, -# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, -# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English -# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, -# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, -# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. - -OUTPUT_LANGUAGE = English - -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). -# Set to NO to disable this. - -BRIEF_MEMBER_DESC = YES - -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the -# brief descriptions will be completely suppressed. - -REPEAT_BRIEF = YES - -# This tag implements a quasi-intelligent brief description abbreviator -# that is used to form the text in various listings. Each string -# in this list, if found as the leading text of the brief description, will be -# stripped from the text and the result after processing the whole list, is -# used as the annotated text. Otherwise, the brief description is used as-is. -# If left blank, the following values are used ("$name" is automatically -# replaced with the name of the entity): "The $name class" "The $name widget" -# "The $name file" "is" "provides" "specifies" "contains" -# "represents" "a" "an" "the" - -ABBREVIATE_BRIEF = - -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief -# description. - -ALWAYS_DETAILED_SEC = NO - -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all -# inherited members of a class in the documentation of that class as if those -# members were ordinary class members. Constructors, destructors and assignment -# operators of the base classes will not be shown. - -INLINE_INHERITED_MEMB = NO - -# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full -# path before files name in the file list and in the header files. If set -# to NO the shortest path that makes the file name unique will be used. - -FULL_PATH_NAMES = YES - -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user-defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the -# path to strip. - -STRIP_FROM_PATH = - -# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of -# the path mentioned in the documentation of a class, which tells -# the reader which header file to include in order to use a class. -# If left blank only the name of the header file containing the class -# definition is used. Otherwise one should specify the include paths that -# are normally passed to the compiler using the -I flag. - -STRIP_FROM_INC_PATH = - -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter -# (but less readable) file names. This can be useful if your file system -# doesn't support long names like on DOS, Mac, or CD-ROM. - -SHORT_NAMES = NO - -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like regular Qt-style comments -# (thus requiring an explicit @brief command for a brief description.) - -JAVADOC_AUTOBRIEF = YES - -# If the QT_AUTOBRIEF tag is set to YES then Doxygen will -# interpret the first line (until the first dot) of a Qt-style -# comment as the brief description. If set to NO, the comments -# will behave just like regular Qt-style comments (thus requiring -# an explicit \brief command for a brief description.) - -QT_AUTOBRIEF = NO - -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen -# treat a multi-line C++ special comment block (i.e. a block of //! or /// -# comments) as a brief description. This used to be the default behaviour. -# The new default is to treat a multi-line C++ comment block as a detailed -# description. Set this tag to YES if you prefer the old behaviour instead. - -MULTILINE_CPP_IS_BRIEF = NO - -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it -# re-implements. - -INHERIT_DOCS = YES - -# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce -# a new page for each member. If set to NO, the documentation of a member will -# be part of the file/class/namespace that contains it. - -SEPARATE_MEMBER_PAGES = NO - -# The TAB_SIZE tag can be used to set the number of spaces in a tab. -# Doxygen uses this value to replace tabs by spaces in code fragments. - -TAB_SIZE = 8 - -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user-defined paragraph with heading "Side Effects:". -# You can put \n's in the value part of an alias to insert newlines. - -ALIASES = - -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C -# sources only. Doxygen will then generate output that is more tailored for C. -# For instance, some of the names that are used will be different. The list -# of all members will be omitted, etc. - -OPTIMIZE_OUTPUT_FOR_C = NO - -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java -# sources only. Doxygen will then generate output that is more tailored for -# Java. For instance, namespaces will be presented as packages, qualified -# scopes will look different, etc. - -OPTIMIZE_OUTPUT_JAVA = NO - -# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran -# sources only. Doxygen will then generate output that is more tailored for -# Fortran. - -OPTIMIZE_FOR_FORTRAN = NO - -# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL -# sources. Doxygen will then generate output that is tailored for -# VHDL. - -OPTIMIZE_OUTPUT_VHDL = NO - -# Doxygen selects the parser to use depending on the extension of the files it -# parses. With this tag you can assign which parser to use for a given extension. -# Doxygen has a built-in mapping, but you can override or extend it using this -# tag. The format is ext=language, where ext is a file extension, and language -# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, -# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make -# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C -# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions -# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. - -EXTENSION_MAPPING = - -# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want -# to include (a tag file for) the STL sources as input, then you should -# set this tag to YES in order to let doxygen match functions declarations and -# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. -# func(std::string) {}). This also makes the inheritance and collaboration -# diagrams that involve STL classes more complete and accurate. - -BUILTIN_STL_SUPPORT = YES - -# If you use Microsoft's C++/CLI language, you should set this option to YES to -# enable parsing support. - -CPP_CLI_SUPPORT = NO - -# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. -# Doxygen will parse them like normal C++ but will assume all classes use public -# instead of private inheritance when no explicit protection keyword is present. - -SIP_SUPPORT = NO - -# For Microsoft's IDL there are propget and propput attributes to indicate getter -# and setter methods for a property. Setting this option to YES (the default) -# will make doxygen replace the get and set methods by a property in the -# documentation. This will only work if the methods are indeed getting or -# setting a simple type. If this is not the case, or you want to show the -# methods anyway, you should set this option to NO. - -IDL_PROPERTY_SUPPORT = YES - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default -# all members of a group must be documented explicitly. - -DISTRIBUTE_GROUP_DOC = NO - -# Set the SUBGROUPING tag to YES (the default) to allow class member groups of -# the same type (for instance a group of public functions) to be put as a -# subgroup of that type (e.g. under the Public Functions section). Set it to -# NO to prevent subgrouping. Alternatively, this can be done per class using -# the \nosubgrouping command. - -SUBGROUPING = YES - -# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and -# unions are shown inside the group in which they are included (e.g. using -# @ingroup) instead of on a separate page (for HTML and Man pages) or -# section (for LaTeX and RTF). - -INLINE_GROUPED_CLASSES = NO - -# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum -# is documented as struct, union, or enum with the name of the typedef. So -# typedef struct TypeS {} TypeT, will appear in the documentation as a struct -# with name TypeT. When disabled the typedef will appear as a member of a file, -# namespace, or class. And the struct will be named TypeS. This can typically -# be useful for C code in case the coding convention dictates that all compound -# types are typedef'ed and only the typedef is referenced, never the tag name. - -TYPEDEF_HIDES_STRUCT = NO - -# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to -# determine which symbols to keep in memory and which to flush to disk. -# When the cache is full, less often used symbols will be written to disk. -# For small to medium size projects (<1000 input files) the default value is -# probably good enough. For larger projects a too small cache size can cause -# doxygen to be busy swapping symbols to and from disk most of the time -# causing a significant performance penalty. -# If the system has enough physical memory increasing the cache will improve the -# performance by keeping more symbols in memory. Note that the value works on -# a logarithmic scale so increasing the size by one will roughly double the -# memory usage. The cache size is given by this formula: -# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, -# corresponding to a cache size of 2^16 = 65536 symbols - -SYMBOL_CACHE_SIZE = 0 - -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- - -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless -# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES - -EXTRACT_ALL = NO - -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class -# will be included in the documentation. - -EXTRACT_PRIVATE = NO - -# If the EXTRACT_STATIC tag is set to YES all static members of a file -# will be included in the documentation. - -EXTRACT_STATIC = NO - -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) -# defined locally in source files will be included in the documentation. -# If set to NO only classes defined in header files are included. - -EXTRACT_LOCAL_CLASSES = YES - -# This flag is only useful for Objective-C code. When set to YES local -# methods, which are defined in the implementation section but not in -# the interface are included in the documentation. -# If set to NO (the default) only methods in the interface are included. - -EXTRACT_LOCAL_METHODS = NO - -# If this flag is set to YES, the members of anonymous namespaces will be -# extracted and appear in the documentation as a namespace called -# 'anonymous_namespace{file}', where file will be replaced with the base -# name of the file that contains the anonymous namespace. By default -# anonymous namespaces are hidden. - -EXTRACT_ANON_NSPACES = YES - -# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all -# undocumented members of documented classes, files or namespaces. -# If set to NO (the default) these members will be included in the -# various overviews, but no documentation section is generated. -# This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_MEMBERS = NO - -# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. -# If set to NO (the default) these classes will be included in the various -# overviews. This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_CLASSES = NO - -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all -# friend (class|struct|union) declarations. -# If set to NO (the default) these declarations will be included in the -# documentation. - -HIDE_FRIEND_COMPOUNDS = NO - -# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any -# documentation blocks found inside the body of a function. -# If set to NO (the default) these blocks will be appended to the -# function's detailed documentation block. - -HIDE_IN_BODY_DOCS = NO - -# The INTERNAL_DOCS tag determines if documentation -# that is typed after a \internal command is included. If the tag is set -# to NO (the default) then the documentation will be excluded. -# Set it to YES to include the internal documentation. - -INTERNAL_DOCS = NO - -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower-case letters. If set to YES upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# and Mac users are advised to set this option to NO. - -CASE_SENSE_NAMES = YES - -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the -# documentation. If set to YES the scope will be hidden. - -HIDE_SCOPE_NAMES = NO - -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put a list of the files that are included by a file in the documentation -# of that file. - -SHOW_INCLUDE_FILES = YES - -# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen -# will list include files with double quotes in the documentation -# rather than with sharp brackets. - -FORCE_LOCAL_INCLUDES = NO - -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] -# is inserted in the documentation for inline members. - -INLINE_INFO = YES - -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in -# declaration order. - -SORT_MEMBER_DOCS = YES - -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the -# brief documentation of file, namespace and class members alphabetically -# by member name. If set to NO (the default) the members will appear in -# declaration order. - -SORT_BRIEF_DOCS = NO - -# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen -# will sort the (brief and detailed) documentation of class members so that -# constructors and destructors are listed first. If set to NO (the default) -# the constructors will appear in the respective orders defined by -# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. -# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO -# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. - -SORT_MEMBERS_CTORS_1ST = NO - -# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the -# hierarchy of group names into alphabetical order. If set to NO (the default) -# the group names will appear in their defined order. - -SORT_GROUP_NAMES = NO - -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be -# sorted by fully-qualified names, including namespaces. If set to -# NO (the default), the class list will be sorted only by class name, -# not including the namespace part. -# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the -# alphabetical list. - -SORT_BY_SCOPE_NAME = NO - -# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to -# do proper type resolution of all parameters of a function it will reject a -# match between the prototype and the implementation of a member function even -# if there is only one candidate or it is obvious which candidate to choose -# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen -# will still accept a match between prototype and implementation in such cases. - -STRICT_PROTO_MATCHING = NO - -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo -# commands in the documentation. - -GENERATE_TODOLIST = YES - -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test -# commands in the documentation. - -GENERATE_TESTLIST = YES - -# The GENERATE_BUGLIST tag can be used to enable (YES) or -# disable (NO) the bug list. This list is created by putting \bug -# commands in the documentation. - -GENERATE_BUGLIST = YES - -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or -# disable (NO) the deprecated list. This list is created by putting -# \deprecated commands in the documentation. - -GENERATE_DEPRECATEDLIST= YES - -# The ENABLED_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if sectionname ... \endif. - -ENABLED_SECTIONS = - -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or macro consists of for it to appear in -# the documentation. If the initializer consists of more lines than specified -# here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and macros in the -# documentation can be controlled using \showinitializer or \hideinitializer -# command in the documentation regardless of this setting. - -MAX_INITIALIZER_LINES = 30 - -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated -# at the bottom of the documentation of classes and structs. If set to YES the -# list will mention the files that were used to generate the documentation. - -SHOW_USED_FILES = YES - -# If the sources in your project are distributed over multiple directories -# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy -# in the documentation. The default is NO. - -SHOW_DIRECTORIES = NO - -# Set the SHOW_FILES tag to NO to disable the generation of the Files page. -# This will remove the Files entry from the Quick Index and from the -# Folder Tree View (if specified). The default is YES. - -SHOW_FILES = YES - -# Set the SHOW_NAMESPACES tag to NO to disable the generation of the -# Namespaces page. -# This will remove the Namespaces entry from the Quick Index -# and from the Folder Tree View (if specified). The default is YES. - -SHOW_NAMESPACES = YES - -# The FILE_VERSION_FILTER tag can be used to specify a program or script that -# doxygen should invoke to get the current version for each file (typically from -# the version control system). Doxygen will invoke the program by executing (via -# popen()) the command , where is the value of -# the FILE_VERSION_FILTER tag, and is the name of an input file -# provided by doxygen. Whatever the program writes to standard output -# is used as the file version. See the manual for examples. - -FILE_VERSION_FILTER = - -# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed -# by doxygen. The layout file controls the global structure of the generated -# output files in an output format independent way. The create the layout file -# that represents doxygen's defaults, run doxygen with the -l option. -# You can optionally specify a file name after the option, if omitted -# DoxygenLayout.xml will be used as the name of the layout file. - -LAYOUT_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- - -# The QUIET tag can be used to turn on/off the messages that are generated -# by doxygen. Possible values are YES and NO. If left blank NO is used. - -QUIET = NO - -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank -# NO is used. - -WARNINGS = YES - -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will -# automatically be disabled. - -WARN_IF_UNDOCUMENTED = NO - -# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some -# parameters in a documented function, or documenting parameters that -# don't exist or using markup commands wrongly. - -WARN_IF_DOC_ERROR = YES - -# The WARN_NO_PARAMDOC option can be enabled to get warnings for -# functions that are documented, but have no documentation for their parameters -# or return value. If set to NO (the default) doxygen will only warn about -# wrong or incomplete parameter documentation, but not about the absence of -# documentation. - -WARN_NO_PARAMDOC = NO - -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the -# warning originated and the warning text. Optionally the format may contain -# $version, which will be replaced by the version of the file (if it could -# be obtained via FILE_VERSION_FILTER) - -WARN_FORMAT = "$file:$line: $text" - -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written -# to stderr. - -WARN_LOGFILE = - -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- - -# The INPUT tag can be used to specify the files and/or directories that contain -# documented source files. You may enter file names like "myfile.cpp" or -# directories like "/usr/src/myproject". Separate the files or directories -# with spaces. - -INPUT = api/ core/ util/ - -# This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is -# also the default input encoding. Doxygen uses libiconv (or the iconv built -# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for -# the list of possible encodings. - -INPUT_ENCODING = UTF-8 - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank the following patterns are tested: -# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh -# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py -# *.f90 *.f *.for *.vhd *.vhdl - -FILE_PATTERNS = - -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. -# If left blank NO is used. - -RECURSIVE = NO - -# The EXCLUDE tag can be used to specify files and/or directories that should -# excluded from the INPUT source files. This way you can easily exclude a -# subdirectory from a directory tree whose root is specified with the INPUT tag. - -EXCLUDE = - -# The EXCLUDE_SYMLINKS tag can be used select whether or not files or -# directories that are symbolic links (a Unix file system feature) are excluded -# from the input. - -EXCLUDE_SYMLINKS = NO - -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. Note that the wildcards are matched -# against the file with absolute path, so to exclude all test directories -# for example use the pattern */test/* - -EXCLUDE_PATTERNS = - -# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names -# (namespaces, classes, functions, etc.) that should be excluded from the -# output. The symbol name can be a fully qualified name, a word, or if the -# wildcard * is used, a substring. Examples: ANamespace, AClass, -# AClass::ANamespace, ANamespace::*Test - -EXCLUDE_SYMBOLS = - -# The EXAMPLE_PATH tag can be used to specify one or more files or -# directories that contain example code fragments that are included (see -# the \include command). - -EXAMPLE_PATH = - -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank all files are included. - -EXAMPLE_PATTERNS = - -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude -# commands irrespective of the value of the RECURSIVE tag. -# Possible values are YES and NO. If left blank NO is used. - -EXAMPLE_RECURSIVE = NO - -# The IMAGE_PATH tag can be used to specify one or more files or -# directories that contain image that are included in the documentation (see -# the \image command). - -IMAGE_PATH = - -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command , where -# is the value of the INPUT_FILTER tag, and is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. -# If FILTER_PATTERNS is specified, this tag will be -# ignored. - -INPUT_FILTER = - -# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. -# Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. -# The filters are a list of the form: -# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further -# info on how filters are used. If FILTER_PATTERNS is empty or if -# non of the patterns match the file name, INPUT_FILTER is applied. - -FILTER_PATTERNS = - -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source -# files to browse (i.e. when SOURCE_BROWSER is set to YES). - -FILTER_SOURCE_FILES = NO - -# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file -# pattern. A pattern will override the setting for FILTER_PATTERN (if any) -# and it is also possible to disable source filtering for a specific pattern -# using *.ext= (so without naming a filter). This option only has effect when -# FILTER_SOURCE_FILES is enabled. - -FILTER_SOURCE_PATTERNS = - -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- - -# If the SOURCE_BROWSER tag is set to YES then a list of source files will -# be generated. Documented entities will be cross-referenced with these sources. -# Note: To get rid of all source code in the generated output, make sure also -# VERBATIM_HEADERS is set to NO. - -SOURCE_BROWSER = NO - -# Setting the INLINE_SOURCES tag to YES will include the body -# of functions and classes directly in the documentation. - -INLINE_SOURCES = NO - -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code -# fragments. Normal C and C++ comments will always remain visible. - -STRIP_CODE_COMMENTS = YES - -# If the REFERENCED_BY_RELATION tag is set to YES -# then for each documented function all documented -# functions referencing it will be listed. - -REFERENCED_BY_RELATION = NO - -# If the REFERENCES_RELATION tag is set to YES -# then for each documented function all documented entities -# called/used by that function will be listed. - -REFERENCES_RELATION = NO - -# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) -# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from -# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will -# link to the source code. -# Otherwise they will link to the documentation. - -REFERENCES_LINK_SOURCE = YES - -# If the USE_HTAGS tag is set to YES then the references to source code -# will point to the HTML generated by the htags(1) tool instead of doxygen -# built-in source browser. The htags tool is part of GNU's global source -# tagging system (see http://www.gnu.org/software/global/global.html). You -# will need version 4.8.6 or higher. - -USE_HTAGS = NO - -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for -# which an include is specified. Set to NO to disable this. - -VERBATIM_HEADERS = YES - -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- - -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -# of all compounds will be generated. Enable this if the project -# contains a lot of classes, structs, unions or interfaces. - -ALPHABETICAL_INDEX = YES - -# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns -# in which this list will be split (can be a number in the range [1..20]) - -COLS_IN_ALPHA_INDEX = 5 - -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that -# should be ignored while generating the index headers. - -IGNORE_PREFIX = - -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output. - -GENERATE_HTML = YES - -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `html' will be used as the default path. - -HTML_OUTPUT = html - -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for -# each generated HTML page (for example: .htm,.php,.asp). If it is left blank -# doxygen will generate files with .html extension. - -HTML_FILE_EXTENSION = .html - -# The HTML_HEADER tag can be used to specify a personal HTML header for -# each generated HTML page. If it is left blank doxygen will generate a -# standard header. Note that when using a custom header you are responsible -# for the proper inclusion of any scripts and style sheets that doxygen -# needs, which is dependent on the configuration options used. -# It is adviced to generate a default header using "doxygen -w html -# header.html footer.html stylesheet.css YourConfigFile" and then modify -# that header. Note that the header is subject to change so you typically -# have to redo this when upgrading to a newer version of doxygen or when changing the value of configuration settings such as GENERATE_TREEVIEW! - -HTML_HEADER = - -# The HTML_FOOTER tag can be used to specify a personal HTML footer for -# each generated HTML page. If it is left blank doxygen will generate a -# standard footer. - -HTML_FOOTER = - -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If the tag is left blank doxygen -# will generate a default style sheet. Note that doxygen will try to copy -# the style sheet file to the HTML output directory, so don't put your own -# stylesheet in the HTML output directory as well, or it will be erased! - -HTML_STYLESHEET = - -# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or -# other source files which should be copied to the HTML output directory. Note -# that these files will be copied to the base HTML output directory. Use the -# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these -# files. In the HTML_STYLESHEET file, use the file name only. Also note that -# the files will be copied as-is; there are no commands or markers available. - -HTML_EXTRA_FILES = - -# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. -# Doxygen will adjust the colors in the stylesheet and background images -# according to this color. Hue is specified as an angle on a colorwheel, -# see http://en.wikipedia.org/wiki/Hue for more information. -# For instance the value 0 represents red, 60 is yellow, 120 is green, -# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. -# The allowed range is 0 to 359. - -HTML_COLORSTYLE_HUE = 220 - -# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of -# the colors in the HTML output. For a value of 0 the output will use -# grayscales only. A value of 255 will produce the most vivid colors. - -HTML_COLORSTYLE_SAT = 100 - -# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to -# the luminance component of the colors in the HTML output. Values below -# 100 gradually make the output lighter, whereas values above 100 make -# the output darker. The value divided by 100 is the actual gamma applied, -# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, -# and 100 does not change the gamma. - -HTML_COLORSTYLE_GAMMA = 80 - -# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML -# page will contain the date and time when the page was generated. Setting -# this to NO can help when comparing the output of multiple runs. - -HTML_TIMESTAMP = YES - -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to -# NO a bullet list will be used. - -HTML_ALIGN_MEMBERS = YES - -# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML -# documentation will contain sections that can be hidden and shown after the -# page has loaded. For this to work a browser that supports -# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox -# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). - -HTML_DYNAMIC_SECTIONS = NO - -# If the GENERATE_DOCSET tag is set to YES, additional index files -# will be generated that can be used as input for Apple's Xcode 3 -# integrated development environment, introduced with OSX 10.5 (Leopard). -# To create a documentation set, doxygen will generate a Makefile in the -# HTML output directory. Running make will produce the docset in that -# directory and running "make install" will install the docset in -# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find -# it at startup. -# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html -# for more information. - -GENERATE_DOCSET = NO - -# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the -# feed. A documentation feed provides an umbrella under which multiple -# documentation sets from a single provider (such as a company or product suite) -# can be grouped. - -DOCSET_FEEDNAME = "Doxygen generated docs" - -# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that -# should uniquely identify the documentation set bundle. This should be a -# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen -# will append .docset to the name. - -DOCSET_BUNDLE_ID = org.doxygen.Project - -# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify -# the documentation publisher. This should be a reverse domain-name style -# string, e.g. com.mycompany.MyDocSet.documentation. - -DOCSET_PUBLISHER_ID = org.doxygen.Publisher - -# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. - -DOCSET_PUBLISHER_NAME = Publisher - -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) -# of the generated HTML documentation. - -GENERATE_HTMLHELP = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can -# be used to specify the file name of the resulting .chm file. You -# can add a path in front of the file if the result should not be -# written to the html output directory. - -CHM_FILE = - -# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can -# be used to specify the location (absolute path including file name) of -# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run -# the HTML help compiler on the generated index.hhp. - -HHC_LOCATION = - -# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag -# controls if a separate .chi index file is generated (YES) or that -# it should be included in the master .chm file (NO). - -GENERATE_CHI = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING -# is used to encode HtmlHelp index (hhk), content (hhc) and project file -# content. - -CHM_INDEX_ENCODING = - -# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag -# controls whether a binary table of contents is generated (YES) or a -# normal table of contents (NO) in the .chm file. - -BINARY_TOC = NO - -# The TOC_EXPAND flag can be set to YES to add extra items for group members -# to the contents of the HTML help documentation and to the tree view. - -TOC_EXPAND = NO - -# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and -# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated -# that can be used as input for Qt's qhelpgenerator to generate a -# Qt Compressed Help (.qch) of the generated HTML documentation. - -GENERATE_QHP = NO - -# If the QHG_LOCATION tag is specified, the QCH_FILE tag can -# be used to specify the file name of the resulting .qch file. -# The path specified is relative to the HTML output folder. - -QCH_FILE = - -# The QHP_NAMESPACE tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#namespace - -QHP_NAMESPACE = org.doxygen.Project - -# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#virtual-folders - -QHP_VIRTUAL_FOLDER = doc - -# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to -# add. For more information please see -# http://doc.trolltech.com/qthelpproject.html#custom-filters - -QHP_CUST_FILTER_NAME = - -# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the -# custom filter to add. For more information please see -# -# Qt Help Project / Custom Filters. - -QHP_CUST_FILTER_ATTRS = - -# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this -# project's -# filter section matches. -# -# Qt Help Project / Filter Attributes. - -QHP_SECT_FILTER_ATTRS = - -# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can -# be used to specify the location of Qt's qhelpgenerator. -# If non-empty doxygen will try to run qhelpgenerator on the generated -# .qhp file. - -QHG_LOCATION = - -# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files -# will be generated, which together with the HTML files, form an Eclipse help -# plugin. To install this plugin and make it available under the help contents -# menu in Eclipse, the contents of the directory containing the HTML and XML -# files needs to be copied into the plugins directory of eclipse. The name of -# the directory within the plugins directory should be the same as -# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before -# the help appears. - -GENERATE_ECLIPSEHELP = NO - -# A unique identifier for the eclipse help plugin. When installing the plugin -# the directory name containing the HTML and XML files should also have -# this name. - -ECLIPSE_DOC_ID = org.doxygen.Project - -# The DISABLE_INDEX tag can be used to turn on/off the condensed index at -# top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. - -DISABLE_INDEX = NO - -# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values -# (range [0,1..20]) that doxygen will group on one line in the generated HTML -# documentation. Note that a value of 0 will completely suppress the enum -# values from appearing in the overview section. - -ENUM_VALUES_PER_LINE = 4 - -# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index -# structure should be generated to display hierarchical information. -# If the tag value is set to YES, a side panel will be generated -# containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). -# Windows users are probably better off using the HTML help feature. - -GENERATE_TREEVIEW = NO - -# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, -# and Class Hierarchy pages using a tree view instead of an ordered list. - -USE_INLINE_TREES = NO - -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree -# is shown. - -TREEVIEW_WIDTH = 250 - -# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open -# links to external symbols imported via tag files in a separate window. - -EXT_LINKS_IN_WINDOW = NO - -# Use this tag to change the font size of Latex formulas included -# as images in the HTML documentation. The default is 10. Note that -# when you change the font size after a successful doxygen run you need -# to manually remove any form_*.png images from the HTML output directory -# to force them to be regenerated. - -FORMULA_FONTSIZE = 10 - -# Use the FORMULA_TRANPARENT tag to determine whether or not the images -# generated for formulas are transparent PNGs. Transparent PNGs are -# not supported properly for IE 6.0, but are supported on all modern browsers. -# Note that when changing this option you need to delete any form_*.png files -# in the HTML output before the changes have effect. - -FORMULA_TRANSPARENT = YES - -# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax -# (see http://www.mathjax.org) which uses client side Javascript for the -# rendering instead of using prerendered bitmaps. Use this if you do not -# have LaTeX installed or if you want to formulas look prettier in the HTML -# output. When enabled you also need to install MathJax separately and -# configure the path to it using the MATHJAX_RELPATH option. - -USE_MATHJAX = NO - -# When MathJax is enabled you need to specify the location relative to the -# HTML output directory using the MATHJAX_RELPATH option. The destination -# directory should contain the MathJax.js script. For instance, if the mathjax -# directory is located at the same level as the HTML output directory, then -# MATHJAX_RELPATH should be ../mathjax. The default value points to the -# mathjax.org site, so you can quickly see the result without installing -# MathJax, but it is strongly recommended to install a local copy of MathJax -# before deployment. - -MATHJAX_RELPATH = http://www.mathjax.org/mathjax - -# When the SEARCHENGINE tag is enabled doxygen will generate a search box -# for the HTML output. The underlying search engine uses javascript -# and DHTML and should work on any modern browser. Note that when using -# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets -# (GENERATE_DOCSET) there is already a search function so this one should -# typically be disabled. For large projects the javascript based search engine -# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. - -SEARCHENGINE = YES - -# When the SERVER_BASED_SEARCH tag is enabled the search engine will be -# implemented using a PHP enabled web server instead of at the web client -# using Javascript. Doxygen will generate the search PHP script and index -# file to put on the web server. The advantage of the server -# based approach is that it scales better to large projects and allows -# full text search. The disadvantages are that it is more difficult to setup -# and does not have live searching capabilities. - -SERVER_BASED_SEARCH = NO - -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- - -# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will -# generate Latex output. - -GENERATE_LATEX = YES - -# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `latex' will be used as the default path. - -LATEX_OUTPUT = latex - -# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be -# invoked. If left blank `latex' will be used as the default command name. -# Note that when enabling USE_PDFLATEX this option is only used for -# generating bitmaps for formulas in the HTML output, but not in the -# Makefile that is written to the output directory. - -LATEX_CMD_NAME = latex - -# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to -# generate index for LaTeX. If left blank `makeindex' will be used as the -# default command name. - -MAKEINDEX_CMD_NAME = makeindex - -# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact -# LaTeX documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_LATEX = NO - -# The PAPER_TYPE tag can be used to set the paper type that is used -# by the printer. Possible values are: a4, letter, legal and -# executive. If left blank a4wide will be used. - -PAPER_TYPE = a4 - -# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX -# packages that should be included in the LaTeX output. - -EXTRA_PACKAGES = - -# The LATEX_HEADER tag can be used to specify a personal LaTeX header for -# the generated latex document. The header should contain everything until -# the first chapter. If it is left blank doxygen will generate a -# standard header. Notice: only use this tag if you know what you are doing! - -LATEX_HEADER = - -# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for -# the generated latex document. The footer should contain everything after -# the last chapter. If it is left blank doxygen will generate a -# standard footer. Notice: only use this tag if you know what you are doing! - -LATEX_FOOTER = - -# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated -# is prepared for conversion to pdf (using ps2pdf). The pdf file will -# contain links (just like the HTML output) instead of page references -# This makes the output suitable for online browsing using a pdf viewer. - -PDF_HYPERLINKS = YES - -# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of -# plain latex in the generated Makefile. Set this option to YES to get a -# higher quality PDF documentation. - -USE_PDFLATEX = YES - -# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. -# command to the generated LaTeX files. This will instruct LaTeX to keep -# running if errors occur, instead of asking the user for help. -# This option is also used when generating formulas in HTML. - -LATEX_BATCHMODE = NO - -# If LATEX_HIDE_INDICES is set to YES then doxygen will not -# include the index chapters (such as File Index, Compound Index, etc.) -# in the output. - -LATEX_HIDE_INDICES = NO - -# If LATEX_SOURCE_CODE is set to YES then doxygen will include -# source code with syntax highlighting in the LaTeX output. -# Note that which sources are shown also depends on other settings -# such as SOURCE_BROWSER. - -LATEX_SOURCE_CODE = NO - -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- - -# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output -# The RTF output is optimized for Word 97 and may not look very pretty with -# other RTF readers or editors. - -GENERATE_RTF = NO - -# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `rtf' will be used as the default path. - -RTF_OUTPUT = rtf - -# If the COMPACT_RTF tag is set to YES Doxygen generates more compact -# RTF documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_RTF = NO - -# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated -# will contain hyperlink fields. The RTF file will -# contain links (just like the HTML output) instead of page references. -# This makes the output suitable for online browsing using WORD or other -# programs which support those fields. -# Note: wordpad (write) and others do not support links. - -RTF_HYPERLINKS = NO - -# Load stylesheet definitions from file. Syntax is similar to doxygen's -# config file, i.e. a series of assignments. You only have to provide -# replacements, missing definitions are set to their default value. - -RTF_STYLESHEET_FILE = - -# Set optional variables used in the generation of an rtf document. -# Syntax is similar to doxygen's config file. - -RTF_EXTENSIONS_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- - -# If the GENERATE_MAN tag is set to YES (the default) Doxygen will -# generate man pages - -GENERATE_MAN = NO - -# The MAN_OUTPUT tag is used to specify where the man pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `man' will be used as the default path. - -MAN_OUTPUT = man - -# The MAN_EXTENSION tag determines the extension that is added to -# the generated man pages (default is the subroutine's section .3) - -MAN_EXTENSION = .3 - -# If the MAN_LINKS tag is set to YES and Doxygen generates man output, -# then it will generate one additional man file for each entity -# documented in the real man page(s). These additional files -# only source the real man page, but without them the man command -# would be unable to find the correct page. The default is NO. - -MAN_LINKS = NO - -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- - -# If the GENERATE_XML tag is set to YES Doxygen will -# generate an XML file that captures the structure of -# the code including all documentation. - -GENERATE_XML = NO - -# The XML_OUTPUT tag is used to specify where the XML pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `xml' will be used as the default path. - -XML_OUTPUT = xml - -# The XML_SCHEMA tag can be used to specify an XML schema, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_SCHEMA = - -# The XML_DTD tag can be used to specify an XML DTD, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_DTD = - -# If the XML_PROGRAMLISTING tag is set to YES Doxygen will -# dump the program listings (including syntax highlighting -# and cross-referencing information) to the XML output. Note that -# enabling this will significantly increase the size of the XML output. - -XML_PROGRAMLISTING = YES - -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- - -# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will -# generate an AutoGen Definitions (see autogen.sf.net) file -# that captures the structure of the code including all -# documentation. Note that this feature is still experimental -# and incomplete at the moment. - -GENERATE_AUTOGEN_DEF = NO - -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- - -# If the GENERATE_PERLMOD tag is set to YES Doxygen will -# generate a Perl module file that captures the structure of -# the code including all documentation. Note that this -# feature is still experimental and incomplete at the -# moment. - -GENERATE_PERLMOD = NO - -# If the PERLMOD_LATEX tag is set to YES Doxygen will generate -# the necessary Makefile rules, Perl scripts and LaTeX code to be able -# to generate PDF and DVI output from the Perl module output. - -PERLMOD_LATEX = NO - -# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be -# nicely formatted so it can be parsed by a human reader. -# This is useful -# if you want to understand what is going on. -# On the other hand, if this -# tag is set to NO the size of the Perl module output will be much smaller -# and Perl will parse it just the same. - -PERLMOD_PRETTY = YES - -# The names of the make variables in the generated doxyrules.make file -# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. -# This is useful so different doxyrules.make files included by the same -# Makefile don't overwrite each other's variables. - -PERLMOD_MAKEVAR_PREFIX = - -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- - -# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will -# evaluate all C-preprocessor directives found in the sources and include -# files. - -ENABLE_PREPROCESSING = YES - -# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro -# names in the source code. If set to NO (the default) only conditional -# compilation will be performed. Macro expansion can be done in a controlled -# way by setting EXPAND_ONLY_PREDEF to YES. - -MACRO_EXPANSION = NO - -# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES -# then the macro expansion is limited to the macros specified with the -# PREDEFINED and EXPAND_AS_DEFINED tags. - -EXPAND_ONLY_PREDEF = NO - -# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files -# pointed to by INCLUDE_PATH will be searched when a #include is found. - -SEARCH_INCLUDES = YES - -# The INCLUDE_PATH tag can be used to specify one or more directories that -# contain include files that are not input files but should be processed by -# the preprocessor. - -INCLUDE_PATH = - -# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard -# patterns (like *.h and *.hpp) to filter out the header-files in the -# directories. If left blank, the patterns specified with FILE_PATTERNS will -# be used. - -INCLUDE_FILE_PATTERNS = - -# The PREDEFINED tag can be used to specify one or more macro names that -# are defined before the preprocessor is started (similar to the -D option of -# gcc). The argument of the tag is a list of macros of the form: name -# or name=definition (no spaces). If the definition and the = are -# omitted =1 is assumed. To prevent a macro definition from being -# undefined via #undef or recursively expanded use the := operator -# instead of the = operator. - -PREDEFINED = - -# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then -# this tag can be used to specify a list of macro names that should be expanded. -# The macro definition that is found in the sources will be used. -# Use the PREDEFINED tag if you want to use a different macro definition that -# overrules the definition found in the source code. - -EXPAND_AS_DEFINED = - -# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then -# doxygen's preprocessor will remove all references to function-like macros -# that are alone on a line, have an all uppercase name, and do not end with a -# semicolon, because these will confuse the parser if not removed. - -SKIP_FUNCTION_MACROS = YES - -#--------------------------------------------------------------------------- -# Configuration::additions related to external references -#--------------------------------------------------------------------------- - -# The TAGFILES option can be used to specify one or more tagfiles. -# Optionally an initial location of the external documentation -# can be added for each tagfile. The format of a tag file without -# this location is as follows: -# -# TAGFILES = file1 file2 ... -# Adding location for the tag files is done as follows: -# -# TAGFILES = file1=loc1 "file2 = loc2" ... -# where "loc1" and "loc2" can be relative or absolute paths or -# URLs. If a location is present for each tag, the installdox tool -# does not have to be run to correct the links. -# Note that each tag file must have a unique name -# (where the name does NOT include the path) -# If a tag file is not located in the directory in which doxygen -# is run, you must also specify the path to the tagfile here. - -TAGFILES = - -# When a file name is specified after GENERATE_TAGFILE, doxygen will create -# a tag file that is based on the input files it reads. - -GENERATE_TAGFILE = - -# If the ALLEXTERNALS tag is set to YES all external classes will be listed -# in the class index. If set to NO only the inherited external classes -# will be listed. - -ALLEXTERNALS = NO - -# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed -# in the modules index. If set to NO, only the current project's groups will -# be listed. - -EXTERNAL_GROUPS = YES - -# The PERL_PATH should be the absolute path and name of the perl script -# interpreter (i.e. the result of `which perl'). - -PERL_PATH = /usr/bin/perl - -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- - -# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will -# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base -# or super classes. Setting the tag to NO turns the diagrams off. Note that -# this option also works with HAVE_DOT disabled, but it is recommended to -# install and use dot, since it yields more powerful graphs. - -CLASS_DIAGRAMS = YES - -# You can define message sequence charts within doxygen comments using the \msc -# command. Doxygen will then run the mscgen tool (see -# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the -# documentation. The MSCGEN_PATH tag allows you to specify the directory where -# the mscgen tool resides. If left empty the tool is assumed to be found in the -# default search path. - -MSCGEN_PATH = - -# If set to YES, the inheritance and collaboration graphs will hide -# inheritance and usage relations if the target is undocumented -# or is not a class. - -HIDE_UNDOC_RELATIONS = YES - -# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is -# available from the path. This tool is part of Graphviz, a graph visualization -# toolkit from AT&T and Lucent Bell Labs. The other options in this section -# have no effect if this option is set to NO (the default) - -HAVE_DOT = NO - -# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is -# allowed to run in parallel. When set to 0 (the default) doxygen will -# base this on the number of processors available in the system. You can set it -# explicitly to a value larger than 0 to get control over the balance -# between CPU load and processing speed. - -DOT_NUM_THREADS = 0 - -# By default doxygen will write a font called Helvetica to the output -# directory and reference it in all dot files that doxygen generates. -# When you want a differently looking font you can specify the font name -# using DOT_FONTNAME. You need to make sure dot is able to find the font, -# which can be done by putting it in a standard location or by setting the -# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory -# containing the font. - -DOT_FONTNAME = Helvetica - -# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. -# The default size is 10pt. - -DOT_FONTSIZE = 10 - -# By default doxygen will tell dot to use the output directory to look for the -# FreeSans.ttf font (which doxygen will put there itself). If you specify a -# different font using DOT_FONTNAME you can set the path where dot -# can find it using this tag. - -DOT_FONTPATH = - -# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect inheritance relations. Setting this tag to YES will force the -# the CLASS_DIAGRAMS tag to NO. - -CLASS_GRAPH = YES - -# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect implementation dependencies (inheritance, containment, and -# class references variables) of the class with other documented classes. - -COLLABORATION_GRAPH = YES - -# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for groups, showing the direct groups dependencies - -GROUP_GRAPHS = YES - -# If the UML_LOOK tag is set to YES doxygen will generate inheritance and -# collaboration diagrams in a style similar to the OMG's Unified Modeling -# Language. - -UML_LOOK = NO - -# If set to YES, the inheritance and collaboration graphs will show the -# relations between templates and their instances. - -TEMPLATE_RELATIONS = NO - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT -# tags are set to YES then doxygen will generate a graph for each documented -# file showing the direct and indirect include dependencies of the file with -# other documented files. - -INCLUDE_GRAPH = YES - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and -# HAVE_DOT tags are set to YES then doxygen will generate a graph for each -# documented header file showing the documented files that directly or -# indirectly include this file. - -INCLUDED_BY_GRAPH = YES - -# If the CALL_GRAPH and HAVE_DOT options are set to YES then -# doxygen will generate a call dependency graph for every global function -# or class method. Note that enabling this option will significantly increase -# the time of a run. So in most cases it will be better to enable call graphs -# for selected functions only using the \callgraph command. - -CALL_GRAPH = NO - -# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then -# doxygen will generate a caller dependency graph for every global function -# or class method. Note that enabling this option will significantly increase -# the time of a run. So in most cases it will be better to enable caller -# graphs for selected functions only using the \callergraph command. - -CALLER_GRAPH = NO - -# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen -# will generate a graphical hierarchy of all classes instead of a textual one. - -GRAPHICAL_HIERARCHY = YES - -# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES -# then doxygen will show the dependencies a directory has on other directories -# in a graphical way. The dependency relations are determined by the #include -# relations between the files in the directories. - -DIRECTORY_GRAPH = YES - -# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images -# generated by dot. Possible values are svg, png, jpg, or gif. -# If left blank png will be used. - -DOT_IMAGE_FORMAT = png - -# The tag DOT_PATH can be used to specify the path where the dot tool can be -# found. If left blank, it is assumed the dot tool can be found in the path. - -DOT_PATH = - -# The DOTFILE_DIRS tag can be used to specify one or more directories that -# contain dot files that are included in the documentation (see the -# \dotfile command). - -DOTFILE_DIRS = - -# The MSCFILE_DIRS tag can be used to specify one or more directories that -# contain msc files that are included in the documentation (see the -# \mscfile command). - -MSCFILE_DIRS = - -# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of -# nodes that will be shown in the graph. If the number of nodes in a graph -# becomes larger than this value, doxygen will truncate the graph, which is -# visualized by representing a node as a red box. Note that doxygen if the -# number of direct children of the root node in a graph is already larger than -# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note -# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. - -DOT_GRAPH_MAX_NODES = 50 - -# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the -# graphs generated by dot. A depth value of 3 means that only nodes reachable -# from the root by following a path via at most 3 edges will be shown. Nodes -# that lay further from the root node will be omitted. Note that setting this -# option to 1 or 2 may greatly reduce the computation time needed for large -# code bases. Also note that the size of a graph can be further restricted by -# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. - -MAX_DOT_GRAPH_DEPTH = 0 - -# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent -# background. This is disabled by default, because dot on Windows does not -# seem to support this out of the box. Warning: Depending on the platform used, -# enabling this option may lead to badly anti-aliased labels on the edges of -# a graph (i.e. they become hard to read). - -DOT_TRANSPARENT = NO - -# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output -# files in one run (i.e. multiple -o and -T options on the command line). This -# makes dot run faster, but since only newer versions of dot (>1.8.10) -# support this, this feature is disabled by default. - -DOT_MULTI_TARGETS = NO - -# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will -# generate a legend page explaining the meaning of the various boxes and -# arrows in the dot generated graphs. - -GENERATE_LEGEND = YES - -# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will -# remove the intermediate dot files that are used to generate -# the various graphs. - -DOT_CLEANUP = YES diff --git a/src/gallium/state_trackers/clover/Makefile.sources b/src/gallium/state_trackers/clover/Makefile.sources deleted file mode 100644 index 38f94981fb6..00000000000 --- a/src/gallium/state_trackers/clover/Makefile.sources +++ /dev/null @@ -1,68 +0,0 @@ -CPP_SOURCES := \ - api/context.cpp \ - api/device.cpp \ - api/dispatch.cpp \ - api/dispatch.hpp \ - api/event.cpp \ - api/interop.cpp \ - api/kernel.cpp \ - api/memory.cpp \ - api/platform.cpp \ - api/program.cpp \ - api/queue.cpp \ - api/sampler.cpp \ - api/transfer.cpp \ - api/util.hpp \ - core/context.cpp \ - core/context.hpp \ - core/device.cpp \ - core/device.hpp \ - core/error.hpp \ - core/event.cpp \ - core/event.hpp \ - core/format.cpp \ - core/format.hpp \ - core/kernel.cpp \ - core/kernel.hpp \ - core/memory.cpp \ - core/memory.hpp \ - core/module.cpp \ - core/module.hpp \ - core/object.hpp \ - core/platform.cpp \ - core/platform.hpp \ - core/program.cpp \ - core/program.hpp \ - core/property.hpp \ - core/queue.cpp \ - core/queue.hpp \ - core/resource.cpp \ - core/resource.hpp \ - core/sampler.cpp \ - core/sampler.hpp \ - core/timestamp.cpp \ - core/timestamp.hpp \ - util/adaptor.hpp \ - util/algebra.hpp \ - util/algorithm.hpp \ - util/factor.hpp \ - util/functional.hpp \ - util/lazy.hpp \ - util/pointer.hpp \ - util/range.hpp \ - util/tuple.hpp - -LLVM_SOURCES := \ - llvm/codegen/bitcode.cpp \ - llvm/codegen/common.cpp \ - llvm/codegen/native.cpp \ - llvm/codegen.hpp \ - llvm/compat.hpp \ - llvm/invocation.cpp \ - llvm/invocation.hpp \ - llvm/metadata.hpp \ - llvm/util.hpp - -SPIRV_SOURCES := \ - spirv/invocation.cpp \ - spirv/invocation.hpp diff --git a/src/gallium/state_trackers/clover/api/context.cpp b/src/gallium/state_trackers/clover/api/context.cpp deleted file mode 100644 index c0cd2d32b95..00000000000 --- a/src/gallium/state_trackers/clover/api/context.cpp +++ /dev/null @@ -1,144 +0,0 @@ -// -// Copyright 2012 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#include "api/util.hpp" -#include "core/context.hpp" -#include "core/platform.hpp" - -using namespace clover; - -CLOVER_API cl_context -clCreateContext(const cl_context_properties *d_props, cl_uint num_devs, - const cl_device_id *d_devs, - void (CL_CALLBACK *pfn_notify)(const char *, const void *, - size_t, void *), - void *user_data, cl_int *r_errcode) try { - auto props = obj(d_props); - auto devs = objs(d_devs, num_devs); - - if (!pfn_notify && user_data) - throw error(CL_INVALID_VALUE); - - for (auto &prop : props) { - if (prop.first == CL_CONTEXT_PLATFORM) - obj(prop.second.as()); - else - throw error(CL_INVALID_PROPERTY); - } - - const auto notify = (!pfn_notify ? context::notify_action() : - [=](const char *s) { - pfn_notify(s, NULL, 0, user_data); - }); - - ret_error(r_errcode, CL_SUCCESS); - return desc(new context(props, devs, notify)); - -} catch (error &e) { - ret_error(r_errcode, e); - return NULL; -} - -CLOVER_API cl_context -clCreateContextFromType(const cl_context_properties *d_props, - cl_device_type type, - void (CL_CALLBACK *pfn_notify)( - const char *, const void *, size_t, void *), - void *user_data, cl_int *r_errcode) try { - cl_platform_id d_platform; - cl_uint num_platforms; - cl_int ret; - std::vector devs; - cl_uint num_devices; - - ret = clGetPlatformIDs(1, &d_platform, &num_platforms); - if (ret || !num_platforms) - throw error(CL_INVALID_PLATFORM); - - ret = clGetDeviceIDs(d_platform, type, 0, NULL, &num_devices); - if (ret) - throw error(CL_DEVICE_NOT_FOUND); - devs.resize(num_devices); - ret = clGetDeviceIDs(d_platform, type, num_devices, devs.data(), 0); - if (ret) - throw error(CL_DEVICE_NOT_FOUND); - - return clCreateContext(d_props, num_devices, devs.data(), pfn_notify, - user_data, r_errcode); - -} catch (error &e) { - ret_error(r_errcode, e); - return NULL; -} - -CLOVER_API cl_int -clRetainContext(cl_context d_ctx) try { - obj(d_ctx).retain(); - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clReleaseContext(cl_context d_ctx) try { - if (obj(d_ctx).release()) - delete pobj(d_ctx); - - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clGetContextInfo(cl_context d_ctx, cl_context_info param, - size_t size, void *r_buf, size_t *r_size) try { - property_buffer buf { r_buf, size, r_size }; - auto &ctx = obj(d_ctx); - - switch (param) { - case CL_CONTEXT_REFERENCE_COUNT: - buf.as_scalar() = ctx.ref_count(); - break; - - case CL_CONTEXT_NUM_DEVICES: - buf.as_scalar() = ctx.devices().size(); - break; - - case CL_CONTEXT_DEVICES: - buf.as_vector() = descs(ctx.devices()); - break; - - case CL_CONTEXT_PROPERTIES: - buf.as_vector() = desc(ctx.properties()); - break; - - default: - throw error(CL_INVALID_VALUE); - } - - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} diff --git a/src/gallium/state_trackers/clover/api/device.cpp b/src/gallium/state_trackers/clover/api/device.cpp deleted file mode 100644 index 042f2eda21c..00000000000 --- a/src/gallium/state_trackers/clover/api/device.cpp +++ /dev/null @@ -1,421 +0,0 @@ -// -// Copyright 2012 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#include "api/util.hpp" -#include "core/platform.hpp" -#include "core/device.hpp" -#include "git_sha1.h" - -using namespace clover; - -CLOVER_API cl_int -clGetDeviceIDs(cl_platform_id d_platform, cl_device_type device_type, - cl_uint num_entries, cl_device_id *rd_devices, - cl_uint *rnum_devices) try { - auto &platform = obj(d_platform); - std::vector d_devs; - - if ((!num_entries && rd_devices) || - (!rnum_devices && !rd_devices)) - throw error(CL_INVALID_VALUE); - - // Collect matching devices - for (device &dev : platform) { - if (((device_type & CL_DEVICE_TYPE_DEFAULT) && - dev == platform.front()) || - (device_type & dev.type())) - d_devs.push_back(desc(dev)); - } - - if (d_devs.empty()) - throw error(CL_DEVICE_NOT_FOUND); - - // ...and return the requested data. - if (rnum_devices) - *rnum_devices = d_devs.size(); - if (rd_devices) - copy(range(d_devs.begin(), - std::min((unsigned)d_devs.size(), num_entries)), - rd_devices); - - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clCreateSubDevices(cl_device_id d_dev, - const cl_device_partition_property *props, - cl_uint num_devs, cl_device_id *rd_devs, - cl_uint *rnum_devs) { - // There are no currently supported partitioning schemes. - return CL_INVALID_VALUE; -} - -CLOVER_API cl_int -clRetainDevice(cl_device_id d_dev) try { - obj(d_dev); - - // The reference count doesn't change for root devices. - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clReleaseDevice(cl_device_id d_dev) try { - obj(d_dev); - - // The reference count doesn't change for root devices. - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clGetDeviceInfo(cl_device_id d_dev, cl_device_info param, - size_t size, void *r_buf, size_t *r_size) try { - property_buffer buf { r_buf, size, r_size }; - auto &dev = obj(d_dev); - - switch (param) { - case CL_DEVICE_TYPE: - buf.as_scalar() = dev.type(); - break; - - case CL_DEVICE_VENDOR_ID: - buf.as_scalar() = dev.vendor_id(); - break; - - case CL_DEVICE_MAX_COMPUTE_UNITS: - buf.as_scalar() = dev.max_compute_units(); - break; - - case CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS: - buf.as_scalar() = dev.max_block_size().size(); - break; - - case CL_DEVICE_MAX_WORK_ITEM_SIZES: - buf.as_vector() = dev.max_block_size(); - break; - - case CL_DEVICE_MAX_WORK_GROUP_SIZE: - buf.as_scalar() = dev.max_threads_per_block(); - break; - - case CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR: - buf.as_scalar() = 16; - break; - - case CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT: - buf.as_scalar() = 8; - break; - - case CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT: - buf.as_scalar() = 4; - break; - - case CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG: - buf.as_scalar() = 2; - break; - - case CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT: - buf.as_scalar() = 4; - break; - - case CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE: - buf.as_scalar() = dev.has_doubles() ? 2 : 0; - break; - - case CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF: - buf.as_scalar() = dev.has_halves() ? 8 : 0; - break; - - case CL_DEVICE_MAX_CLOCK_FREQUENCY: - buf.as_scalar() = dev.max_clock_frequency(); - break; - - case CL_DEVICE_ADDRESS_BITS: - buf.as_scalar() = dev.address_bits(); - break; - - case CL_DEVICE_MAX_READ_IMAGE_ARGS: - buf.as_scalar() = dev.max_images_read(); - break; - - case CL_DEVICE_MAX_WRITE_IMAGE_ARGS: - buf.as_scalar() = dev.max_images_write(); - break; - - case CL_DEVICE_MAX_MEM_ALLOC_SIZE: - buf.as_scalar() = dev.max_mem_alloc_size(); - break; - - case CL_DEVICE_IMAGE2D_MAX_WIDTH: - case CL_DEVICE_IMAGE2D_MAX_HEIGHT: - buf.as_scalar() = 1 << dev.max_image_levels_2d(); - break; - - case CL_DEVICE_IMAGE3D_MAX_WIDTH: - case CL_DEVICE_IMAGE3D_MAX_HEIGHT: - case CL_DEVICE_IMAGE3D_MAX_DEPTH: - buf.as_scalar() = 1 << dev.max_image_levels_3d(); - break; - - case CL_DEVICE_IMAGE_MAX_BUFFER_SIZE: - buf.as_scalar() = dev.max_image_buffer_size(); - break; - - case CL_DEVICE_IMAGE_MAX_ARRAY_SIZE: - buf.as_scalar() = dev.max_image_array_number(); - break; - - case CL_DEVICE_IMAGE_SUPPORT: - buf.as_scalar() = dev.image_support(); - break; - - case CL_DEVICE_MAX_PARAMETER_SIZE: - buf.as_scalar() = dev.max_mem_input(); - break; - - case CL_DEVICE_MAX_SAMPLERS: - buf.as_scalar() = dev.max_samplers(); - break; - - case CL_DEVICE_MEM_BASE_ADDR_ALIGN: - buf.as_scalar() = 8 * - std::max(dev.mem_base_addr_align(), (cl_uint) sizeof(cl_long) * 16); - break; - - case CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE: - buf.as_scalar() = 128; - break; - - case CL_DEVICE_HALF_FP_CONFIG: - // This is the "mandated minimum half precision floating-point - // capability" for OpenCL 1.x. - buf.as_scalar() = - CL_FP_INF_NAN | CL_FP_ROUND_TO_NEAREST; - break; - - case CL_DEVICE_SINGLE_FP_CONFIG: - // This is the "mandated minimum single precision floating-point - // capability" for OpenCL 1.1. In OpenCL 1.2, nothing is required for - // custom devices. - buf.as_scalar() = - CL_FP_INF_NAN | CL_FP_ROUND_TO_NEAREST; - break; - - case CL_DEVICE_DOUBLE_FP_CONFIG: - if (dev.has_doubles()) - // This is the "mandated minimum double precision floating-point - // capability" - buf.as_scalar() = - CL_FP_FMA - | CL_FP_ROUND_TO_NEAREST - | CL_FP_ROUND_TO_ZERO - | CL_FP_ROUND_TO_INF - | CL_FP_INF_NAN - | CL_FP_DENORM; - else - buf.as_scalar() = 0; - break; - - case CL_DEVICE_GLOBAL_MEM_CACHE_TYPE: - buf.as_scalar() = CL_NONE; - break; - - case CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE: - buf.as_scalar() = 0; - break; - - case CL_DEVICE_GLOBAL_MEM_CACHE_SIZE: - buf.as_scalar() = 0; - break; - - case CL_DEVICE_GLOBAL_MEM_SIZE: - buf.as_scalar() = dev.max_mem_global(); - break; - - case CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE: - buf.as_scalar() = dev.max_const_buffer_size(); - break; - - case CL_DEVICE_MAX_CONSTANT_ARGS: - buf.as_scalar() = dev.max_const_buffers(); - break; - - case CL_DEVICE_LOCAL_MEM_TYPE: - buf.as_scalar() = CL_LOCAL; - break; - - case CL_DEVICE_LOCAL_MEM_SIZE: - buf.as_scalar() = dev.max_mem_local(); - break; - - case CL_DEVICE_ERROR_CORRECTION_SUPPORT: - buf.as_scalar() = CL_FALSE; - break; - - case CL_DEVICE_PROFILING_TIMER_RESOLUTION: - buf.as_scalar() = 0; - break; - - case CL_DEVICE_ENDIAN_LITTLE: - buf.as_scalar() = (dev.endianness() == PIPE_ENDIAN_LITTLE); - break; - - case CL_DEVICE_AVAILABLE: - case CL_DEVICE_COMPILER_AVAILABLE: - case CL_DEVICE_LINKER_AVAILABLE: - buf.as_scalar() = CL_TRUE; - break; - - case CL_DEVICE_EXECUTION_CAPABILITIES: - buf.as_scalar() = CL_EXEC_KERNEL; - break; - - case CL_DEVICE_QUEUE_PROPERTIES: - buf.as_scalar() = CL_QUEUE_PROFILING_ENABLE; - break; - - case CL_DEVICE_BUILT_IN_KERNELS: - buf.as_string() = ""; - break; - - case CL_DEVICE_NAME: - buf.as_string() = dev.device_name(); - break; - - case CL_DEVICE_VENDOR: - buf.as_string() = dev.vendor_name(); - break; - - case CL_DRIVER_VERSION: - buf.as_string() = PACKAGE_VERSION; - break; - - case CL_DEVICE_PROFILE: - buf.as_string() = "FULL_PROFILE"; - break; - - case CL_DEVICE_VERSION: - buf.as_string() = "OpenCL " + dev.device_version() + " Mesa " PACKAGE_VERSION MESA_GIT_SHA1; - break; - - case CL_DEVICE_EXTENSIONS: - buf.as_string() = dev.supported_extensions(); - break; - - case CL_DEVICE_PLATFORM: - buf.as_scalar() = desc(dev.platform); - break; - - case CL_DEVICE_HOST_UNIFIED_MEMORY: - buf.as_scalar() = dev.has_unified_memory(); - break; - - case CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR: - buf.as_scalar() = 16; - break; - - case CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT: - buf.as_scalar() = 8; - break; - - case CL_DEVICE_NATIVE_VECTOR_WIDTH_INT: - buf.as_scalar() = 4; - break; - - case CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG: - buf.as_scalar() = 2; - break; - - case CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT: - buf.as_scalar() = 4; - break; - - case CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE: - buf.as_scalar() = dev.has_doubles() ? 2 : 0; - break; - - case CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF: - buf.as_scalar() = dev.has_halves() ? 8 : 0; - break; - - case CL_DEVICE_OPENCL_C_VERSION: - buf.as_string() = "OpenCL C " + dev.device_clc_version() + " "; - break; - - case CL_DEVICE_PRINTF_BUFFER_SIZE: - // Per the spec, the minimum value for the FULL profile is 1 MB. - // However, clover is not ready yet to support it - buf.as_scalar() = 0 /* 1024 */; - break; - - case CL_DEVICE_PREFERRED_INTEROP_USER_SYNC: - buf.as_scalar() = CL_TRUE; - break; - - case CL_DEVICE_PARENT_DEVICE: - buf.as_scalar() = NULL; - break; - - case CL_DEVICE_PARTITION_MAX_SUB_DEVICES: - buf.as_scalar() = 0; - break; - - case CL_DEVICE_PARTITION_PROPERTIES: - buf.as_vector() = - desc(property_list()); - break; - - case CL_DEVICE_PARTITION_AFFINITY_DOMAIN: - buf.as_scalar() = 0; - break; - - case CL_DEVICE_PARTITION_TYPE: - buf.as_vector() = - desc(property_list()); - break; - - case CL_DEVICE_REFERENCE_COUNT: - buf.as_scalar() = 1; - break; - - case CL_DEVICE_SVM_CAPABILITIES: - case CL_DEVICE_SVM_CAPABILITIES_ARM: - buf.as_scalar() = dev.svm_support(); - break; - - default: - throw error(CL_INVALID_VALUE); - } - - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} diff --git a/src/gallium/state_trackers/clover/api/dispatch.cpp b/src/gallium/state_trackers/clover/api/dispatch.cpp deleted file mode 100644 index 6e1b0351afa..00000000000 --- a/src/gallium/state_trackers/clover/api/dispatch.cpp +++ /dev/null @@ -1,174 +0,0 @@ -// -// Copyright 2013 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#include "api/dispatch.hpp" - -namespace clover { - const cl_icd_dispatch _dispatch = { - clGetPlatformIDs, - GetPlatformInfo, - clGetDeviceIDs, - clGetDeviceInfo, - clCreateContext, - clCreateContextFromType, - clRetainContext, - clReleaseContext, - clGetContextInfo, - clCreateCommandQueue, - clRetainCommandQueue, - clReleaseCommandQueue, - clGetCommandQueueInfo, - NULL, // clSetCommandQueueProperty - clCreateBuffer, - clCreateImage2D, - clCreateImage3D, - clRetainMemObject, - clReleaseMemObject, - clGetSupportedImageFormats, - clGetMemObjectInfo, - clGetImageInfo, - clCreateSampler, - clRetainSampler, - clReleaseSampler, - clGetSamplerInfo, - clCreateProgramWithSource, - clCreateProgramWithBinary, - clRetainProgram, - clReleaseProgram, - clBuildProgram, - clUnloadCompiler, - clGetProgramInfo, - clGetProgramBuildInfo, - clCreateKernel, - clCreateKernelsInProgram, - clRetainKernel, - clReleaseKernel, - clSetKernelArg, - clGetKernelInfo, - clGetKernelWorkGroupInfo, - clWaitForEvents, - clGetEventInfo, - clRetainEvent, - clReleaseEvent, - clGetEventProfilingInfo, - clFlush, - clFinish, - clEnqueueReadBuffer, - clEnqueueWriteBuffer, - clEnqueueCopyBuffer, - clEnqueueReadImage, - clEnqueueWriteImage, - clEnqueueCopyImage, - clEnqueueCopyImageToBuffer, - clEnqueueCopyBufferToImage, - clEnqueueMapBuffer, - clEnqueueMapImage, - clEnqueueUnmapMemObject, - clEnqueueNDRangeKernel, - clEnqueueTask, - clEnqueueNativeKernel, - clEnqueueMarker, - clEnqueueWaitForEvents, - clEnqueueBarrier, - GetExtensionFunctionAddress, - NULL, // clCreateFromGLBuffer - NULL, // clCreateFromGLTexture2D - NULL, // clCreateFromGLTexture3D - NULL, // clCreateFromGLRenderbuffer - NULL, // clGetGLObjectInfo - NULL, // clGetGLTextureInfo - NULL, // clEnqueueAcquireGLObjects - NULL, // clEnqueueReleaseGLObjects - NULL, // clGetGLContextInfoKHR - NULL, // clGetDeviceIDsFromD3D10KHR - NULL, // clCreateFromD3D10BufferKHR - NULL, // clCreateFromD3D10Texture2DKHR - NULL, // clCreateFromD3D10Texture3DKHR - NULL, // clEnqueueAcquireD3D10ObjectsKHR - NULL, // clEnqueueReleaseD3D10ObjectsKHR - clSetEventCallback, - clCreateSubBuffer, - clSetMemObjectDestructorCallback, - clCreateUserEvent, - clSetUserEventStatus, - clEnqueueReadBufferRect, - clEnqueueWriteBufferRect, - clEnqueueCopyBufferRect, - NULL, // clCreateSubDevicesEXT - NULL, // clRetainDeviceEXT - NULL, // clReleaseDeviceEXT - NULL, // clCreateEventFromGLsyncKHR - clCreateSubDevices, - clRetainDevice, - clReleaseDevice, - clCreateImage, - clCreateProgramWithBuiltInKernels, - clCompileProgram, - clLinkProgram, - clUnloadPlatformCompiler, - clGetKernelArgInfo, - clEnqueueFillBuffer, - clEnqueueFillImage, - clEnqueueMigrateMemObjects, - clEnqueueMarkerWithWaitList, - clEnqueueBarrierWithWaitList, - GetExtensionFunctionAddressForPlatform, - NULL, // clCreateFromGLTexture - NULL, // clGetDeviceIDsFromD3D11KHR - NULL, // clCreateFromD3D11BufferKHR - NULL, // clCreateFromD3D11Texture2DKHR - NULL, // clCreateFromD3D11Texture3DKHR - NULL, // clCreateFromDX9MediaSurfaceKHR - NULL, // clEnqueueAcquireD3D11ObjectsKHR - NULL, // clEnqueueReleaseD3D11ObjectsKHR - NULL, // clGetDeviceIDsFromDX9MediaAdapterKHR - NULL, // clEnqueueAcquireDX9MediaSurfacesKHR - NULL, // clEnqueueReleaseDX9MediaSurfacesKHR - NULL, // clCreateFromEGLImageKHR - NULL, // clEnqueueAcquireEGLObjectsKHR - NULL, // clEnqueueReleaseEGLObjectsKHR - NULL, // clCreateEventFromEGLSyncKHR - clCreateCommandQueueWithProperties, - NULL, // clCreatePipe - NULL, // clGetPipeInfo - clSVMAlloc, - clSVMFree, - clEnqueueSVMFree, - clEnqueueSVMMemcpy, - clEnqueueSVMMemFill, - clEnqueueSVMMap, - clEnqueueSVMUnmap, - NULL, // clCreateSamplerWithProperties - clSetKernelArgSVMPointer, - clSetKernelExecInfo, - NULL, // clGetKernelSubGroupInfoKHR - NULL, // clCloneKernel - NULL, // clCreateProgramWithIL - clEnqueueSVMMigrateMem, - NULL, // clGetDeviceAndHostTimer - NULL, // clGetHostTimer - NULL, // clGetKernelSubGroupInfo - NULL, // clSetDefaultDeviceCommandQueue - NULL, // clSetProgramReleaseCallback - NULL, // clSetProgramSpecializationConstant - }; -} diff --git a/src/gallium/state_trackers/clover/api/dispatch.hpp b/src/gallium/state_trackers/clover/api/dispatch.hpp deleted file mode 100644 index ea835ed6da4..00000000000 --- a/src/gallium/state_trackers/clover/api/dispatch.hpp +++ /dev/null @@ -1,105 +0,0 @@ -// -// Copyright 2013 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#ifndef API_DISPATCH_HPP -#define API_DISPATCH_HPP - -#include "CL/cl.h" -#include "CL/cl_ext.h" -#include "CL/cl_egl.h" -#include "CL/cl_gl.h" -#include "CL/cl_icd.h" - -namespace clover { - extern const cl_icd_dispatch _dispatch; - - cl_int - GetPlatformInfo(cl_platform_id d_platform, cl_platform_info param, - size_t size, void *r_buf, size_t *r_size); - - void * - GetExtensionFunctionAddress(const char *p_name); - - void * - GetExtensionFunctionAddressForPlatform(cl_platform_id d_platform, - const char *p_name); - - cl_int - IcdGetPlatformIDsKHR(cl_uint num_entries, cl_platform_id *rd_platforms, - cl_uint *rnum_platforms); - - cl_int - EnqueueSVMFree(cl_command_queue command_queue, - cl_uint num_svm_pointers, - void *svm_pointers[], - void (CL_CALLBACK *pfn_free_func) ( - cl_command_queue queue, cl_uint num_svm_pointers, - void *svm_pointers[], void *user_data), - void *user_data, - cl_uint num_events_in_wait_list, - const cl_event *event_wait_list, - cl_event *event, - cl_int cmd); - - cl_int - EnqueueSVMMemcpy(cl_command_queue command_queue, - cl_bool blocking_copy, - void *dst_ptr, - const void *src_ptr, - size_t size, - cl_uint num_events_in_wait_list, - const cl_event *event_wait_list, - cl_event *event, - cl_int cmd); - - cl_int - EnqueueSVMMap(cl_command_queue command_queue, - cl_bool blocking_map, - cl_map_flags map_flags, - void *svm_ptr, - size_t size, - cl_uint num_events_in_wait_list, - const cl_event *event_wait_list, - cl_event *event, - cl_int cmd); - - cl_int - EnqueueSVMMemFill(cl_command_queue command_queue, - void *svm_ptr, - const void *pattern, - size_t pattern_size, - size_t size, - cl_uint num_events_in_wait_list, - const cl_event *event_wait_list, - cl_event *event, - cl_int cmd); - - cl_int - EnqueueSVMUnmap(cl_command_queue command_queue, - void *svm_ptr, - cl_uint num_events_in_wait_list, - const cl_event *event_wait_list, - cl_event *event, - cl_int cmd); -} - -#endif diff --git a/src/gallium/state_trackers/clover/api/event.cpp b/src/gallium/state_trackers/clover/api/event.cpp deleted file mode 100644 index 3f89644d0a4..00000000000 --- a/src/gallium/state_trackers/clover/api/event.cpp +++ /dev/null @@ -1,309 +0,0 @@ -// -// Copyright 2012 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#include "api/util.hpp" -#include "core/event.hpp" - -using namespace clover; - -CLOVER_API cl_event -clCreateUserEvent(cl_context d_ctx, cl_int *r_errcode) try { - auto &ctx = obj(d_ctx); - - ret_error(r_errcode, CL_SUCCESS); - return desc(new soft_event(ctx, {}, false)); - -} catch (error &e) { - ret_error(r_errcode, e); - return NULL; -} - -CLOVER_API cl_int -clSetUserEventStatus(cl_event d_ev, cl_int status) try { - auto &sev = obj(d_ev); - - if (status > 0) - return CL_INVALID_VALUE; - - if (sev.status() <= 0) - return CL_INVALID_OPERATION; - - if (status) - sev.abort(status); - else - sev.trigger(); - - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clWaitForEvents(cl_uint num_evs, const cl_event *d_evs) try { - auto evs = objs(d_evs, num_evs); - - for (auto &ev : evs) { - if (ev.context() != evs.front().context()) - throw error(CL_INVALID_CONTEXT); - - if (ev.status() < 0) - throw error(CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST); - } - - // Create a temporary soft event that depends on all the events in - // the wait list - auto sev = create(evs.front().context(), evs, true); - - // ...and wait on it. - sev().wait(); - - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clGetEventInfo(cl_event d_ev, cl_event_info param, - size_t size, void *r_buf, size_t *r_size) try { - property_buffer buf { r_buf, size, r_size }; - auto &ev = obj(d_ev); - - switch (param) { - case CL_EVENT_COMMAND_QUEUE: - buf.as_scalar() = desc(ev.queue()); - break; - - case CL_EVENT_CONTEXT: - buf.as_scalar() = desc(ev.context()); - break; - - case CL_EVENT_COMMAND_TYPE: - buf.as_scalar() = ev.command(); - break; - - case CL_EVENT_COMMAND_EXECUTION_STATUS: - buf.as_scalar() = ev.status(); - break; - - case CL_EVENT_REFERENCE_COUNT: - buf.as_scalar() = ev.ref_count(); - break; - - default: - throw error(CL_INVALID_VALUE); - } - - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clSetEventCallback(cl_event d_ev, cl_int type, - void (CL_CALLBACK *pfn_notify)(cl_event, cl_int, void *), - void *user_data) try { - auto &ev = obj(d_ev); - - if (!pfn_notify || - (type != CL_COMPLETE && type != CL_SUBMITTED && type != CL_RUNNING)) - throw error(CL_INVALID_VALUE); - - // Create a temporary soft event that depends on ev, with - // pfn_notify as completion action. - create(ev.context(), ref_vector { ev }, true, - [=, &ev](event &) { - ev.wait(); - pfn_notify(desc(ev), ev.status(), user_data); - }); - - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clRetainEvent(cl_event d_ev) try { - obj(d_ev).retain(); - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clReleaseEvent(cl_event d_ev) try { - if (obj(d_ev).release()) - delete pobj(d_ev); - - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clEnqueueMarker(cl_command_queue d_q, cl_event *rd_ev) try { - auto &q = obj(d_q); - - if (!rd_ev) - throw error(CL_INVALID_VALUE); - - *rd_ev = desc(new hard_event(q, CL_COMMAND_MARKER, {})); - - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clEnqueueMarkerWithWaitList(cl_command_queue d_q, cl_uint num_deps, - const cl_event *d_deps, cl_event *rd_ev) try { - auto &q = obj(d_q); - auto deps = objs(d_deps, num_deps); - - for (auto &ev : deps) { - if (ev.context() != q.context()) - throw error(CL_INVALID_CONTEXT); - } - - // Create a hard event that depends on the events in the wait list: - // previous commands in the same queue are implicitly serialized - // with respect to it -- hard events always are. - auto hev = create(q, CL_COMMAND_MARKER, deps); - - ret_object(rd_ev, hev); - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clEnqueueBarrier(cl_command_queue d_q) try { - obj(d_q); - - // No need to do anything, q preserves data ordering strictly. - - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clEnqueueBarrierWithWaitList(cl_command_queue d_q, cl_uint num_deps, - const cl_event *d_deps, cl_event *rd_ev) try { - auto &q = obj(d_q); - auto deps = objs(d_deps, num_deps); - - for (auto &ev : deps) { - if (ev.context() != q.context()) - throw error(CL_INVALID_CONTEXT); - } - - // Create a hard event that depends on the events in the wait list: - // subsequent commands in the same queue will be implicitly - // serialized with respect to it -- hard events always are. - auto hev = create(q, CL_COMMAND_BARRIER, deps); - - ret_object(rd_ev, hev); - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clEnqueueWaitForEvents(cl_command_queue d_q, cl_uint num_evs, - const cl_event *d_evs) try { - // The wait list is mandatory for clEnqueueWaitForEvents(). - objs(d_evs, num_evs); - - return clEnqueueBarrierWithWaitList(d_q, num_evs, d_evs, NULL); - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clGetEventProfilingInfo(cl_event d_ev, cl_profiling_info param, - size_t size, void *r_buf, size_t *r_size) try { - property_buffer buf { r_buf, size, r_size }; - hard_event &hev = dynamic_cast(obj(d_ev)); - - if (hev.status() != CL_COMPLETE) - throw error(CL_PROFILING_INFO_NOT_AVAILABLE); - - switch (param) { - case CL_PROFILING_COMMAND_QUEUED: - buf.as_scalar() = hev.time_queued(); - break; - - case CL_PROFILING_COMMAND_SUBMIT: - buf.as_scalar() = hev.time_submit(); - break; - - case CL_PROFILING_COMMAND_START: - buf.as_scalar() = hev.time_start(); - break; - - case CL_PROFILING_COMMAND_END: - buf.as_scalar() = hev.time_end(); - break; - - default: - throw error(CL_INVALID_VALUE); - } - - return CL_SUCCESS; - -} catch (std::bad_cast &e) { - return CL_PROFILING_INFO_NOT_AVAILABLE; - -} catch (lazy::undefined_error &e) { - return CL_PROFILING_INFO_NOT_AVAILABLE; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clFinish(cl_command_queue d_q) try { - auto &q = obj(d_q); - - // Create a temporary hard event -- it implicitly depends on all - // the previously queued hard events. - auto hev = create(q, 0, ref_vector {}); - - // And wait on it. - hev().wait(); - - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} diff --git a/src/gallium/state_trackers/clover/api/interop.cpp b/src/gallium/state_trackers/clover/api/interop.cpp deleted file mode 100644 index b96069f5167..00000000000 --- a/src/gallium/state_trackers/clover/api/interop.cpp +++ /dev/null @@ -1,69 +0,0 @@ -// -// Copyright 2015 Advanced Micro Devices, Inc. -// All Rights Reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#include "core/event.hpp" -#include "api/util.hpp" - -using namespace clover; - -extern "C" { - -PUBLIC bool -opencl_dri_event_add_ref(cl_event event) -{ - /* This should fail if the event hasn't been created by - * clEnqueueReleaseGLObjects or clEnqueueReleaseEGLObjects. - * - * TODO: implement the CL functions - */ - return false; /*return clRetainEvent(event) == CL_SUCCESS;*/ -} - -PUBLIC bool -opencl_dri_event_release(cl_event event) -{ - return clReleaseEvent(event) == CL_SUCCESS; -} - -PUBLIC bool -opencl_dri_event_wait(cl_event event, uint64_t timeout) try { - if (!timeout) { - return obj(event).status() == CL_COMPLETE; - } - - obj(event).wait(); - return true; - -} catch (error &) { - return false; -} - -PUBLIC struct pipe_fence_handle * -opencl_dri_event_get_fence(cl_event event) try { - return obj(event).fence(); - -} catch (error &) { - return NULL; -} - -} diff --git a/src/gallium/state_trackers/clover/api/kernel.cpp b/src/gallium/state_trackers/clover/api/kernel.cpp deleted file mode 100644 index 31a87b63868..00000000000 --- a/src/gallium/state_trackers/clover/api/kernel.cpp +++ /dev/null @@ -1,390 +0,0 @@ -// -// Copyright 2012 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#include "api/util.hpp" -#include "core/kernel.hpp" -#include "core/event.hpp" - -using namespace clover; - -CLOVER_API cl_kernel -clCreateKernel(cl_program d_prog, const char *name, cl_int *r_errcode) try { - auto &prog = obj(d_prog); - - if (!name) - throw error(CL_INVALID_VALUE); - - auto &sym = find(name_equals(name), prog.symbols()); - - ret_error(r_errcode, CL_SUCCESS); - return new kernel(prog, name, range(sym.args)); - -} catch (std::out_of_range &e) { - ret_error(r_errcode, CL_INVALID_KERNEL_NAME); - return NULL; - -} catch (error &e) { - ret_error(r_errcode, e); - return NULL; -} - -CLOVER_API cl_int -clCreateKernelsInProgram(cl_program d_prog, cl_uint count, - cl_kernel *rd_kerns, cl_uint *r_count) try { - auto &prog = obj(d_prog); - auto &syms = prog.symbols(); - - if (rd_kerns && count < syms.size()) - throw error(CL_INVALID_VALUE); - - if (rd_kerns) - copy(map([&](const module::symbol &sym) { - return desc(new kernel(prog, - std::string(sym.name.begin(), - sym.name.end()), - range(sym.args))); - }, syms), - rd_kerns); - - if (r_count) - *r_count = syms.size(); - - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clRetainKernel(cl_kernel d_kern) try { - obj(d_kern).retain(); - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clReleaseKernel(cl_kernel d_kern) try { - if (obj(d_kern).release()) - delete pobj(d_kern); - - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clSetKernelArg(cl_kernel d_kern, cl_uint idx, size_t size, - const void *value) try { - obj(d_kern).args().at(idx).set(size, value); - return CL_SUCCESS; - -} catch (std::out_of_range &e) { - return CL_INVALID_ARG_INDEX; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clGetKernelInfo(cl_kernel d_kern, cl_kernel_info param, - size_t size, void *r_buf, size_t *r_size) try { - property_buffer buf { r_buf, size, r_size }; - auto &kern = obj(d_kern); - - switch (param) { - case CL_KERNEL_FUNCTION_NAME: - buf.as_string() = kern.name(); - break; - - case CL_KERNEL_NUM_ARGS: - buf.as_scalar() = kern.args().size(); - break; - - case CL_KERNEL_REFERENCE_COUNT: - buf.as_scalar() = kern.ref_count(); - break; - - case CL_KERNEL_CONTEXT: - buf.as_scalar() = desc(kern.program().context()); - break; - - case CL_KERNEL_PROGRAM: - buf.as_scalar() = desc(kern.program()); - break; - - default: - throw error(CL_INVALID_VALUE); - } - - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clGetKernelWorkGroupInfo(cl_kernel d_kern, cl_device_id d_dev, - cl_kernel_work_group_info param, - size_t size, void *r_buf, size_t *r_size) try { - property_buffer buf { r_buf, size, r_size }; - auto &kern = obj(d_kern); - auto &dev = (d_dev ? *pobj(d_dev) : unique(kern.program().devices())); - - if (!count(dev, kern.program().devices())) - throw error(CL_INVALID_DEVICE); - - switch (param) { - case CL_KERNEL_WORK_GROUP_SIZE: - buf.as_scalar() = dev.max_threads_per_block(); - break; - - case CL_KERNEL_COMPILE_WORK_GROUP_SIZE: - buf.as_vector() = kern.required_block_size(); - break; - - case CL_KERNEL_LOCAL_MEM_SIZE: - buf.as_scalar() = kern.mem_local(); - break; - - case CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE: - buf.as_scalar() = dev.subgroup_size(); - break; - - case CL_KERNEL_PRIVATE_MEM_SIZE: - buf.as_scalar() = kern.mem_private(); - break; - - default: - throw error(CL_INVALID_VALUE); - } - - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); - -} catch (std::out_of_range &e) { - return CL_INVALID_DEVICE; -} - -CLOVER_API cl_int -clGetKernelArgInfo(cl_kernel d_kern, - cl_uint idx, cl_kernel_arg_info param, - size_t size, void *r_buf, size_t *r_size) { - CLOVER_NOT_SUPPORTED_UNTIL("1.2"); - return CL_KERNEL_ARG_INFO_NOT_AVAILABLE; -} - -namespace { - /// - /// Common argument checking shared by kernel invocation commands. - /// - void - validate_common(const command_queue &q, kernel &kern, - const ref_vector &deps) { - if (kern.program().context() != q.context() || - any_of([&](const event &ev) { - return ev.context() != q.context(); - }, deps)) - throw error(CL_INVALID_CONTEXT); - - if (any_of([](kernel::argument &arg) { - return !arg.set(); - }, kern.args())) - throw error(CL_INVALID_KERNEL_ARGS); - - // If the command queue's device is not associated to the program, we get - // a module, with no sections, which will also fail the following test. - auto &m = kern.program().build(q.device()).binary; - if (!any_of(type_equals(module::section::text_executable), m.secs)) - throw error(CL_INVALID_PROGRAM_EXECUTABLE); - } - - std::vector - validate_grid_size(const command_queue &q, cl_uint dims, - const size_t *d_grid_size) { - auto grid_size = range(d_grid_size, dims); - - if (dims < 1 || dims > q.device().max_block_size().size()) - throw error(CL_INVALID_WORK_DIMENSION); - - if (!d_grid_size || any_of(is_zero(), grid_size)) - throw error(CL_INVALID_GLOBAL_WORK_SIZE); - - return grid_size; - } - - std::vector - validate_grid_offset(const command_queue &q, cl_uint dims, - const size_t *d_grid_offset) { - if (d_grid_offset) - return range(d_grid_offset, dims); - else - return std::vector(dims, 0); - } - - std::vector - validate_block_size(const command_queue &q, const kernel &kern, - cl_uint dims, const size_t *d_grid_size, - const size_t *d_block_size) { - auto grid_size = range(d_grid_size, dims); - - if (d_block_size) { - auto block_size = range(d_block_size, dims); - - if (any_of(is_zero(), block_size) || - any_of(greater(), block_size, q.device().max_block_size())) - throw error(CL_INVALID_WORK_ITEM_SIZE); - - if (any_of(modulus(), grid_size, block_size)) - throw error(CL_INVALID_WORK_GROUP_SIZE); - - if (fold(multiplies(), 1u, block_size) > - q.device().max_threads_per_block()) - throw error(CL_INVALID_WORK_GROUP_SIZE); - - return block_size; - - } else { - return kern.optimal_block_size(q, grid_size); - } - } -} - -CLOVER_API cl_int -clEnqueueNDRangeKernel(cl_command_queue d_q, cl_kernel d_kern, - cl_uint dims, const size_t *d_grid_offset, - const size_t *d_grid_size, const size_t *d_block_size, - cl_uint num_deps, const cl_event *d_deps, - cl_event *rd_ev) try { - auto &q = obj(d_q); - auto &kern = obj(d_kern); - auto deps = objs(d_deps, num_deps); - auto grid_size = validate_grid_size(q, dims, d_grid_size); - auto grid_offset = validate_grid_offset(q, dims, d_grid_offset); - auto block_size = validate_block_size(q, kern, dims, - d_grid_size, d_block_size); - - validate_common(q, kern, deps); - - auto hev = create( - q, CL_COMMAND_NDRANGE_KERNEL, deps, - [=, &kern, &q](event &) { - kern.launch(q, grid_offset, grid_size, block_size); - }); - - ret_object(rd_ev, hev); - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clEnqueueTask(cl_command_queue d_q, cl_kernel d_kern, - cl_uint num_deps, const cl_event *d_deps, - cl_event *rd_ev) try { - auto &q = obj(d_q); - auto &kern = obj(d_kern); - auto deps = objs(d_deps, num_deps); - - validate_common(q, kern, deps); - - auto hev = create( - q, CL_COMMAND_TASK, deps, - [=, &kern, &q](event &) { - kern.launch(q, { 0 }, { 1 }, { 1 }); - }); - - ret_object(rd_ev, hev); - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clEnqueueNativeKernel(cl_command_queue d_q, void (*func)(void *), - void *args, size_t args_size, - cl_uint num_mems, const cl_mem *d_mems, - const void **mem_handles, cl_uint num_deps, - const cl_event *d_deps, cl_event *rd_ev) { - return CL_INVALID_OPERATION; -} - -CLOVER_API cl_int -clSetKernelArgSVMPointer(cl_kernel d_kern, - cl_uint arg_index, - const void *arg_value) try { - obj(d_kern).args().at(arg_index).set_svm(arg_value); - return CL_SUCCESS; - -} catch (std::out_of_range &e) { - return CL_INVALID_ARG_INDEX; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clSetKernelExecInfo(cl_kernel d_kern, - cl_kernel_exec_info param_name, - size_t param_value_size, - const void *param_value) try { - auto &kern = obj(d_kern); - const bool has_system_svm = all_of(std::mem_fn(&device::has_system_svm), - kern.program().context().devices()); - - if (!param_value) - return CL_INVALID_VALUE; - - switch (param_name) { - case CL_KERNEL_EXEC_INFO_SVM_FINE_GRAIN_SYSTEM: - case CL_KERNEL_EXEC_INFO_SVM_FINE_GRAIN_SYSTEM_ARM: { - if (param_value_size != sizeof(cl_bool)) - return CL_INVALID_VALUE; - - cl_bool val = *static_cast(param_value); - if (val == CL_TRUE && !has_system_svm) - return CL_INVALID_OPERATION; - else - return CL_SUCCESS; - } - - case CL_KERNEL_EXEC_INFO_SVM_PTRS: - case CL_KERNEL_EXEC_INFO_SVM_PTRS_ARM: - if (has_system_svm) - return CL_SUCCESS; - - CLOVER_NOT_SUPPORTED_UNTIL("2.0"); - return CL_INVALID_VALUE; - - default: - return CL_INVALID_VALUE; - } - -} catch (error &e) { - return e.get(); -} diff --git a/src/gallium/state_trackers/clover/api/memory.cpp b/src/gallium/state_trackers/clover/api/memory.cpp deleted file mode 100644 index e03793339c1..00000000000 --- a/src/gallium/state_trackers/clover/api/memory.cpp +++ /dev/null @@ -1,497 +0,0 @@ -// -// Copyright 2012 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#include "util/u_math.h" -#include "api/util.hpp" -#include "core/memory.hpp" -#include "core/format.hpp" - -using namespace clover; - -namespace { - cl_mem_flags - validate_flags(cl_mem d_parent, cl_mem_flags d_flags, bool svm) { - const cl_mem_flags dev_access_flags = - CL_MEM_READ_WRITE | CL_MEM_WRITE_ONLY | CL_MEM_READ_ONLY; - const cl_mem_flags host_ptr_flags = - CL_MEM_USE_HOST_PTR | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR; - const cl_mem_flags host_access_flags = - CL_MEM_HOST_WRITE_ONLY | CL_MEM_HOST_READ_ONLY | CL_MEM_HOST_NO_ACCESS; - const cl_mem_flags svm_flags = - CL_MEM_SVM_FINE_GRAIN_BUFFER | CL_MEM_SVM_ATOMICS; - - const cl_mem_flags valid_flags = - dev_access_flags - | (svm || d_parent ? 0 : host_ptr_flags) - | (svm ? svm_flags : host_access_flags); - - if ((d_flags & ~valid_flags) || - util_bitcount(d_flags & dev_access_flags) > 1 || - util_bitcount(d_flags & host_access_flags) > 1) - throw error(CL_INVALID_VALUE); - - if ((d_flags & CL_MEM_USE_HOST_PTR) && - (d_flags & (CL_MEM_COPY_HOST_PTR | CL_MEM_ALLOC_HOST_PTR))) - throw error(CL_INVALID_VALUE); - - if ((d_flags & CL_MEM_SVM_ATOMICS) && - !(d_flags & CL_MEM_SVM_FINE_GRAIN_BUFFER)) - throw error(CL_INVALID_VALUE); - - if (d_parent) { - const auto &parent = obj(d_parent); - const cl_mem_flags flags = (d_flags | - (d_flags & dev_access_flags ? 0 : - parent.flags() & dev_access_flags) | - (d_flags & host_access_flags ? 0 : - parent.flags() & host_access_flags) | - (parent.flags() & host_ptr_flags)); - - if (~flags & parent.flags() & (dev_access_flags & ~CL_MEM_READ_WRITE)) - throw error(CL_INVALID_VALUE); - - // Check if new host access flags cause a mismatch between - // host-read/write-only. - if (!(flags & CL_MEM_HOST_NO_ACCESS) && - (~flags & parent.flags() & host_access_flags)) - throw error(CL_INVALID_VALUE); - - return flags; - - } else { - return d_flags | (d_flags & dev_access_flags ? 0 : CL_MEM_READ_WRITE); - } - } -} - -CLOVER_API cl_mem -clCreateBuffer(cl_context d_ctx, cl_mem_flags d_flags, size_t size, - void *host_ptr, cl_int *r_errcode) try { - const cl_mem_flags flags = validate_flags(NULL, d_flags, false); - auto &ctx = obj(d_ctx); - - if (bool(host_ptr) != bool(flags & (CL_MEM_USE_HOST_PTR | - CL_MEM_COPY_HOST_PTR))) - throw error(CL_INVALID_HOST_PTR); - - if (!size || - size > fold(maximum(), cl_ulong(0), - map(std::mem_fn(&device::max_mem_alloc_size), ctx.devices()) - )) - throw error(CL_INVALID_BUFFER_SIZE); - - ret_error(r_errcode, CL_SUCCESS); - return new root_buffer(ctx, flags, size, host_ptr); - -} catch (error &e) { - ret_error(r_errcode, e); - return NULL; -} - -CLOVER_API cl_mem -clCreateSubBuffer(cl_mem d_mem, cl_mem_flags d_flags, - cl_buffer_create_type op, - const void *op_info, cl_int *r_errcode) try { - auto &parent = obj(d_mem); - const cl_mem_flags flags = validate_flags(d_mem, d_flags, false); - - if (op == CL_BUFFER_CREATE_TYPE_REGION) { - auto reg = reinterpret_cast(op_info); - - if (!reg || - reg->origin > parent.size() || - reg->origin + reg->size > parent.size()) - throw error(CL_INVALID_VALUE); - - if (!reg->size) - throw error(CL_INVALID_BUFFER_SIZE); - - ret_error(r_errcode, CL_SUCCESS); - return new sub_buffer(parent, flags, reg->origin, reg->size); - - } else { - throw error(CL_INVALID_VALUE); - } - -} catch (error &e) { - ret_error(r_errcode, e); - return NULL; -} - -CLOVER_API cl_mem -clCreateImage(cl_context d_ctx, cl_mem_flags d_flags, - const cl_image_format *format, - const cl_image_desc *desc, - void *host_ptr, cl_int *r_errcode) try { - auto &ctx = obj(d_ctx); - - if (!any_of(std::mem_fn(&device::image_support), ctx.devices())) - throw error(CL_INVALID_OPERATION); - - if (!format) - throw error(CL_INVALID_IMAGE_FORMAT_DESCRIPTOR); - - if (!desc) - throw error(CL_INVALID_IMAGE_DESCRIPTOR); - - if (desc->image_array_size == 0 && - (desc->image_type == CL_MEM_OBJECT_IMAGE1D_ARRAY || - desc->image_type == CL_MEM_OBJECT_IMAGE2D_ARRAY)) - throw error(CL_INVALID_IMAGE_DESCRIPTOR); - - if (!host_ptr && - (desc->image_row_pitch || desc->image_slice_pitch)) - throw error(CL_INVALID_IMAGE_DESCRIPTOR); - - if (desc->num_mip_levels || desc->num_samples) - throw error(CL_INVALID_IMAGE_DESCRIPTOR); - - if (bool(desc->buffer) != (desc->image_type == CL_MEM_OBJECT_IMAGE1D_BUFFER)) - throw error(CL_INVALID_IMAGE_DESCRIPTOR); - - if (bool(host_ptr) != bool(d_flags & (CL_MEM_USE_HOST_PTR | - CL_MEM_COPY_HOST_PTR))) - throw error(CL_INVALID_HOST_PTR); - - const cl_mem_flags flags = validate_flags(desc->buffer, d_flags, false); - - if (!supported_formats(ctx, desc->image_type).count(*format)) - throw error(CL_IMAGE_FORMAT_NOT_SUPPORTED); - - ret_error(r_errcode, CL_SUCCESS); - - switch (desc->image_type) { - case CL_MEM_OBJECT_IMAGE2D: - if (!desc->image_width || !desc->image_height) - throw error(CL_INVALID_IMAGE_SIZE); - - if (all_of([=](const device &dev) { - const size_t max = 1 << dev.max_image_levels_2d(); - return (desc->image_width > max || - desc->image_height > max); - }, ctx.devices())) - throw error(CL_INVALID_IMAGE_SIZE); - - return new image2d(ctx, flags, format, - desc->image_width, desc->image_height, - desc->image_row_pitch, host_ptr); - - case CL_MEM_OBJECT_IMAGE3D: - if (!desc->image_width || !desc->image_height || !desc->image_depth) - throw error(CL_INVALID_IMAGE_SIZE); - - if (all_of([=](const device &dev) { - const size_t max = 1 << dev.max_image_levels_3d(); - return (desc->image_width > max || - desc->image_height > max || - desc->image_depth > max); - }, ctx.devices())) - throw error(CL_INVALID_IMAGE_SIZE); - - return new image3d(ctx, flags, format, - desc->image_width, desc->image_height, - desc->image_depth, desc->image_row_pitch, - desc->image_slice_pitch, host_ptr); - - case CL_MEM_OBJECT_IMAGE1D: - case CL_MEM_OBJECT_IMAGE1D_ARRAY: - case CL_MEM_OBJECT_IMAGE1D_BUFFER: - case CL_MEM_OBJECT_IMAGE2D_ARRAY: - // XXX - Not implemented. - throw error(CL_IMAGE_FORMAT_NOT_SUPPORTED); - - default: - throw error(CL_INVALID_IMAGE_DESCRIPTOR); - } - -} catch (error &e) { - ret_error(r_errcode, e); - return NULL; -} - -CLOVER_API cl_mem -clCreateImage2D(cl_context d_ctx, cl_mem_flags d_flags, - const cl_image_format *format, - size_t width, size_t height, size_t row_pitch, - void *host_ptr, cl_int *r_errcode) { - const cl_image_desc desc = { CL_MEM_OBJECT_IMAGE2D, width, height, 0, 0, - row_pitch, 0, 0, 0, NULL }; - - return clCreateImage(d_ctx, d_flags, format, &desc, host_ptr, r_errcode); -} - -CLOVER_API cl_mem -clCreateImage3D(cl_context d_ctx, cl_mem_flags d_flags, - const cl_image_format *format, - size_t width, size_t height, size_t depth, - size_t row_pitch, size_t slice_pitch, - void *host_ptr, cl_int *r_errcode) { - const cl_image_desc desc = { CL_MEM_OBJECT_IMAGE3D, width, height, depth, 0, - row_pitch, slice_pitch, 0, 0, NULL }; - - return clCreateImage(d_ctx, d_flags, format, &desc, host_ptr, r_errcode); -} - -CLOVER_API cl_int -clGetSupportedImageFormats(cl_context d_ctx, cl_mem_flags flags, - cl_mem_object_type type, cl_uint count, - cl_image_format *r_buf, cl_uint *r_count) try { - auto &ctx = obj(d_ctx); - auto formats = supported_formats(ctx, type); - - validate_flags(NULL, flags, false); - - if (r_buf && !r_count) - throw error(CL_INVALID_VALUE); - - if (r_buf) - std::copy_n(formats.begin(), - std::min((cl_uint)formats.size(), count), - r_buf); - - if (r_count) - *r_count = formats.size(); - - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clGetMemObjectInfo(cl_mem d_mem, cl_mem_info param, - size_t size, void *r_buf, size_t *r_size) try { - property_buffer buf { r_buf, size, r_size }; - auto &mem = obj(d_mem); - - switch (param) { - case CL_MEM_TYPE: - buf.as_scalar() = mem.type(); - break; - - case CL_MEM_FLAGS: - buf.as_scalar() = mem.flags(); - break; - - case CL_MEM_SIZE: - buf.as_scalar() = mem.size(); - break; - - case CL_MEM_HOST_PTR: - buf.as_scalar() = mem.host_ptr(); - break; - - case CL_MEM_MAP_COUNT: - buf.as_scalar() = 0; - break; - - case CL_MEM_REFERENCE_COUNT: - buf.as_scalar() = mem.ref_count(); - break; - - case CL_MEM_CONTEXT: - buf.as_scalar() = desc(mem.context()); - break; - - case CL_MEM_ASSOCIATED_MEMOBJECT: { - sub_buffer *sub = dynamic_cast(&mem); - buf.as_scalar() = (sub ? desc(sub->parent()) : NULL); - break; - } - case CL_MEM_OFFSET: { - sub_buffer *sub = dynamic_cast(&mem); - buf.as_scalar() = (sub ? sub->offset() : 0); - break; - } - case CL_MEM_USES_SVM_POINTER: - case CL_MEM_USES_SVM_POINTER_ARM: { - // with system SVM all host ptrs are SVM pointers - // TODO: once we support devices with lower levels of SVM, we have to - // check the ptr in more detail - const bool system_svm = all_of(std::mem_fn(&device::has_system_svm), - mem.context().devices()); - buf.as_scalar() = mem.host_ptr() && system_svm; - break; - } - default: - throw error(CL_INVALID_VALUE); - } - - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clGetImageInfo(cl_mem d_mem, cl_image_info param, - size_t size, void *r_buf, size_t *r_size) try { - property_buffer buf { r_buf, size, r_size }; - auto &img = obj(d_mem); - - switch (param) { - case CL_IMAGE_FORMAT: - buf.as_scalar() = img.format(); - break; - - case CL_IMAGE_ELEMENT_SIZE: - buf.as_scalar() = 0; - break; - - case CL_IMAGE_ROW_PITCH: - buf.as_scalar() = img.row_pitch(); - break; - - case CL_IMAGE_SLICE_PITCH: - buf.as_scalar() = img.slice_pitch(); - break; - - case CL_IMAGE_WIDTH: - buf.as_scalar() = img.width(); - break; - - case CL_IMAGE_HEIGHT: - buf.as_scalar() = img.height(); - break; - - case CL_IMAGE_DEPTH: - buf.as_scalar() = img.depth(); - break; - - default: - throw error(CL_INVALID_VALUE); - } - - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clRetainMemObject(cl_mem d_mem) try { - obj(d_mem).retain(); - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clReleaseMemObject(cl_mem d_mem) try { - if (obj(d_mem).release()) - delete pobj(d_mem); - - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clSetMemObjectDestructorCallback(cl_mem d_mem, - void (CL_CALLBACK *pfn_notify)(cl_mem, void *), - void *user_data) try { - auto &mem = obj(d_mem); - - if (!pfn_notify) - return CL_INVALID_VALUE; - - mem.destroy_notify([=]{ pfn_notify(d_mem, user_data); }); - - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clEnqueueFillBuffer(cl_command_queue command_queue, cl_mem buffer, - const void *pattern, size_t pattern_size, - size_t offset, size_t size, - cl_uint num_events_in_wait_list, - const cl_event *event_wait_list, - cl_event *event) { - CLOVER_NOT_SUPPORTED_UNTIL("1.2"); - return CL_INVALID_VALUE; -} - -CLOVER_API cl_int -clEnqueueFillImage(cl_command_queue command_queue, cl_mem image, - const void *fill_color, - const size_t *origin, const size_t *region, - cl_uint num_events_in_wait_list, - const cl_event *event_wait_list, - cl_event *event) { - CLOVER_NOT_SUPPORTED_UNTIL("1.2"); - return CL_INVALID_VALUE; -} - -CLOVER_API void * -clSVMAlloc(cl_context d_ctx, - cl_svm_mem_flags flags, - size_t size, - unsigned int alignment) try { - auto &ctx = obj(d_ctx); - validate_flags(NULL, flags, true); - - if (!size || - size > fold(minimum(), cl_ulong(ULONG_MAX), - map(std::mem_fn(&device::max_mem_alloc_size), ctx.devices()))) - return nullptr; - - if (!util_is_power_of_two_or_zero(alignment)) - return nullptr; - - if (!alignment) - alignment = 0x80; // sizeof(long16) - - bool can_emulate = all_of(std::mem_fn(&device::has_system_svm), ctx.devices()); - if (can_emulate) { - // we can ignore all the flags as it's not required to honor them. - void *ptr = nullptr; - if (alignment < sizeof(void*)) - alignment = sizeof(void*); - posix_memalign(&ptr, alignment, size); - return ptr; - } - - CLOVER_NOT_SUPPORTED_UNTIL("2.0"); - return nullptr; - -} catch (error &e) { - return nullptr; -} - -CLOVER_API void -clSVMFree(cl_context d_ctx, - void *svm_pointer) try { - auto &ctx = obj(d_ctx); - bool can_emulate = all_of(std::mem_fn(&device::has_system_svm), ctx.devices()); - - if (can_emulate) - return free(svm_pointer); - - CLOVER_NOT_SUPPORTED_UNTIL("2.0"); - -} catch (error &e) { -} diff --git a/src/gallium/state_trackers/clover/api/platform.cpp b/src/gallium/state_trackers/clover/api/platform.cpp deleted file mode 100644 index 7360461e62f..00000000000 --- a/src/gallium/state_trackers/clover/api/platform.cpp +++ /dev/null @@ -1,235 +0,0 @@ -// -// Copyright 2012 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#include - -#include "api/dispatch.hpp" -#include "api/util.hpp" -#include "core/platform.hpp" -#include "git_sha1.h" -#include "util/u_debug.h" - -using namespace clover; - -namespace { - platform _clover_platform; -} - -CLOVER_API cl_int -clGetPlatformIDs(cl_uint num_entries, cl_platform_id *rd_platforms, - cl_uint *rnum_platforms) { - if ((!num_entries && rd_platforms) || - (!rnum_platforms && !rd_platforms)) - return CL_INVALID_VALUE; - - if (rnum_platforms) - *rnum_platforms = 1; - if (rd_platforms) - *rd_platforms = desc(_clover_platform); - - return CL_SUCCESS; -} - -cl_int -clover::GetPlatformInfo(cl_platform_id d_platform, cl_platform_info param, - size_t size, void *r_buf, size_t *r_size) try { - property_buffer buf { r_buf, size, r_size }; - - auto &platform = obj(d_platform); - - switch (param) { - case CL_PLATFORM_PROFILE: - buf.as_string() = "FULL_PROFILE"; - break; - - case CL_PLATFORM_VERSION: { - static const std::string version_string = - debug_get_option("CLOVER_PLATFORM_VERSION_OVERRIDE", "1.1"); - - buf.as_string() = "OpenCL " + version_string + " Mesa " PACKAGE_VERSION MESA_GIT_SHA1; - break; - } - case CL_PLATFORM_NAME: - buf.as_string() = "Clover"; - break; - - case CL_PLATFORM_VENDOR: - buf.as_string() = "Mesa"; - break; - - case CL_PLATFORM_EXTENSIONS: - buf.as_string() = platform.supported_extensions(); - break; - - case CL_PLATFORM_ICD_SUFFIX_KHR: - buf.as_string() = "MESA"; - break; - - default: - throw error(CL_INVALID_VALUE); - } - - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -void * -clover::GetExtensionFunctionAddressForPlatform(cl_platform_id d_platform, - const char *p_name) try { - obj(d_platform); - return GetExtensionFunctionAddress(p_name); - -} catch (error &e) { - return NULL; -} - -namespace { - -cl_int -enqueueSVMFreeARM(cl_command_queue command_queue, - cl_uint num_svm_pointers, - void *svm_pointers[], - void (CL_CALLBACK *pfn_free_func) ( - cl_command_queue queue, cl_uint num_svm_pointers, - void *svm_pointers[], void *user_data), - void *user_data, - cl_uint num_events_in_wait_list, - const cl_event *event_wait_list, - cl_event *event) { - - return EnqueueSVMFree(command_queue, num_svm_pointers, svm_pointers, - pfn_free_func, user_data, num_events_in_wait_list, - event_wait_list, event, CL_COMMAND_SVM_FREE_ARM); -} - -cl_int -enqueueSVMMapARM(cl_command_queue command_queue, - cl_bool blocking_map, - cl_map_flags map_flags, - void *svm_ptr, - size_t size, - cl_uint num_events_in_wait_list, - const cl_event *event_wait_list, - cl_event *event) { - - return EnqueueSVMMap(command_queue, blocking_map, map_flags, svm_ptr, size, - num_events_in_wait_list, event_wait_list, event, - CL_COMMAND_SVM_MAP_ARM); -} - -cl_int -enqueueSVMMemcpyARM(cl_command_queue command_queue, - cl_bool blocking_copy, - void *dst_ptr, - const void *src_ptr, - size_t size, - cl_uint num_events_in_wait_list, - const cl_event *event_wait_list, - cl_event *event) { - - return EnqueueSVMMemcpy(command_queue, blocking_copy, dst_ptr, src_ptr, - size, num_events_in_wait_list, event_wait_list, - event, CL_COMMAND_SVM_MEMCPY_ARM); -} - -cl_int -enqueueSVMMemFillARM(cl_command_queue command_queue, - void *svm_ptr, - const void *pattern, - size_t pattern_size, - size_t size, - cl_uint num_events_in_wait_list, - const cl_event *event_wait_list, - cl_event *event) { - - return EnqueueSVMMemFill(command_queue, svm_ptr, pattern, pattern_size, - size, num_events_in_wait_list, event_wait_list, - event, CL_COMMAND_SVM_MEMFILL_ARM); -} - -cl_int -enqueueSVMUnmapARM(cl_command_queue command_queue, - void *svm_ptr, - cl_uint num_events_in_wait_list, - const cl_event *event_wait_list, - cl_event *event) { - - return EnqueueSVMUnmap(command_queue, svm_ptr, num_events_in_wait_list, - event_wait_list, event, CL_COMMAND_SVM_UNMAP_ARM); -} - -const std::unordered_map -ext_funcs = { - // cl_arm_shared_virtual_memory - { "clEnqueueSVMFreeARM", reinterpret_cast(enqueueSVMFreeARM) }, - { "clEnqueueSVMMapARM", reinterpret_cast(enqueueSVMMapARM) }, - { "clEnqueueSVMMemcpyARM", reinterpret_cast(enqueueSVMMemcpyARM) }, - { "clEnqueueSVMMemFillARM", reinterpret_cast(enqueueSVMMemFillARM) }, - { "clEnqueueSVMUnmapARM", reinterpret_cast(enqueueSVMUnmapARM) }, - { "clSetKernelArgSVMPointerARM", reinterpret_cast(clSetKernelArgSVMPointer) }, - { "clSetKernelExecInfoARM", reinterpret_cast(clSetKernelExecInfo) }, - { "clSVMAllocARM", reinterpret_cast(clSVMAlloc) }, - { "clSVMFreeARM", reinterpret_cast(clSVMFree) }, - - // cl_khr_icd - { "clIcdGetPlatformIDsKHR", reinterpret_cast(IcdGetPlatformIDsKHR) }, -}; - -} // anonymous namespace - -void * -clover::GetExtensionFunctionAddress(const char *p_name) try { - return ext_funcs.at(p_name); -} catch (...) { - return nullptr; -} - -cl_int -clover::IcdGetPlatformIDsKHR(cl_uint num_entries, cl_platform_id *rd_platforms, - cl_uint *rnum_platforms) { - return clGetPlatformIDs(num_entries, rd_platforms, rnum_platforms); -} - -CLOVER_ICD_API cl_int -clGetPlatformInfo(cl_platform_id d_platform, cl_platform_info param, - size_t size, void *r_buf, size_t *r_size) { - return GetPlatformInfo(d_platform, param, size, r_buf, r_size); -} - -CLOVER_ICD_API void * -clGetExtensionFunctionAddress(const char *p_name) { - return GetExtensionFunctionAddress(p_name); -} - -CLOVER_ICD_API void * -clGetExtensionFunctionAddressForPlatform(cl_platform_id d_platform, - const char *p_name) { - return GetExtensionFunctionAddressForPlatform(d_platform, p_name); -} - -CLOVER_ICD_API cl_int -clIcdGetPlatformIDsKHR(cl_uint num_entries, cl_platform_id *rd_platforms, - cl_uint *rnum_platforms) { - return IcdGetPlatformIDsKHR(num_entries, rd_platforms, rnum_platforms); -} diff --git a/src/gallium/state_trackers/clover/api/program.cpp b/src/gallium/state_trackers/clover/api/program.cpp deleted file mode 100644 index 33f843e9c87..00000000000 --- a/src/gallium/state_trackers/clover/api/program.cpp +++ /dev/null @@ -1,479 +0,0 @@ -// -// Copyright 2012 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#include "api/util.hpp" -#include "core/program.hpp" -#include "util/u_debug.h" - -#include - -using namespace clover; - -namespace { - void - validate_build_common(const program &prog, cl_uint num_devs, - const cl_device_id *d_devs, - void (*pfn_notify)(cl_program, void *), - void *user_data) { - if (!pfn_notify && user_data) - throw error(CL_INVALID_VALUE); - - if (prog.kernel_ref_count()) - throw error(CL_INVALID_OPERATION); - - if (any_of([&](const device &dev) { - return !count(dev, prog.devices()); - }, objs(d_devs, num_devs))) - throw error(CL_INVALID_DEVICE); - } -} - -CLOVER_API cl_program -clCreateProgramWithSource(cl_context d_ctx, cl_uint count, - const char **strings, const size_t *lengths, - cl_int *r_errcode) try { - auto &ctx = obj(d_ctx); - std::string source; - - if (!count || !strings || - any_of(is_zero(), range(strings, count))) - throw error(CL_INVALID_VALUE); - - // Concatenate all the provided fragments together - for (unsigned i = 0; i < count; ++i) - source += (lengths && lengths[i] ? - std::string(strings[i], strings[i] + lengths[i]) : - std::string(strings[i])); - - // ...and create a program object for them. - ret_error(r_errcode, CL_SUCCESS); - return new program(ctx, source); - -} catch (error &e) { - ret_error(r_errcode, e); - return NULL; -} - -CLOVER_API cl_program -clCreateProgramWithBinary(cl_context d_ctx, cl_uint n, - const cl_device_id *d_devs, - const size_t *lengths, - const unsigned char **binaries, - cl_int *r_status, cl_int *r_errcode) try { - auto &ctx = obj(d_ctx); - auto devs = objs(d_devs, n); - - if (!lengths || !binaries) - throw error(CL_INVALID_VALUE); - - if (any_of([&](const device &dev) { - return !count(dev, ctx.devices()); - }, devs)) - throw error(CL_INVALID_DEVICE); - - // Deserialize the provided binaries, - std::vector> result = map( - [](const unsigned char *p, size_t l) -> std::pair { - if (!p || !l) - return { CL_INVALID_VALUE, {} }; - - try { - std::stringbuf bin( { (char*)p, l } ); - std::istream s(&bin); - - return { CL_SUCCESS, module::deserialize(s) }; - - } catch (std::istream::failure &e) { - return { CL_INVALID_BINARY, {} }; - } - }, - range(binaries, n), - range(lengths, n)); - - // update the status array, - if (r_status) - copy(map(keys(), result), r_status); - - if (any_of(key_equals(CL_INVALID_VALUE), result)) - throw error(CL_INVALID_VALUE); - - if (any_of(key_equals(CL_INVALID_BINARY), result)) - throw error(CL_INVALID_BINARY); - - // initialize a program object with them. - ret_error(r_errcode, CL_SUCCESS); - return new program(ctx, devs, map(values(), result)); - -} catch (error &e) { - ret_error(r_errcode, e); - return NULL; -} - -CLOVER_API cl_program -clCreateProgramWithBuiltInKernels(cl_context d_ctx, cl_uint n, - const cl_device_id *d_devs, - const char *kernel_names, - cl_int *r_errcode) try { - auto &ctx = obj(d_ctx); - auto devs = objs(d_devs, n); - - if (any_of([&](const device &dev) { - return !count(dev, ctx.devices()); - }, devs)) - throw error(CL_INVALID_DEVICE); - - // No currently supported built-in kernels. - throw error(CL_INVALID_VALUE); - -} catch (error &e) { - ret_error(r_errcode, e); - return NULL; -} - - -CLOVER_API cl_int -clRetainProgram(cl_program d_prog) try { - obj(d_prog).retain(); - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clReleaseProgram(cl_program d_prog) try { - if (obj(d_prog).release()) - delete pobj(d_prog); - - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clBuildProgram(cl_program d_prog, cl_uint num_devs, - const cl_device_id *d_devs, const char *p_opts, - void (*pfn_notify)(cl_program, void *), - void *user_data) try { - auto &prog = obj(d_prog); - auto devs = - (d_devs ? objs(d_devs, num_devs) : ref_vector(prog.devices())); - const auto opts = std::string(p_opts ? p_opts : "") + " " + - debug_get_option("CLOVER_EXTRA_BUILD_OPTIONS", ""); - - validate_build_common(prog, num_devs, d_devs, pfn_notify, user_data); - - if (prog.has_source) { - prog.compile(devs, opts); - prog.link(devs, opts, { prog }); - } else if (any_of([&](const device &dev){ - return prog.build(dev).binary_type() != CL_PROGRAM_BINARY_TYPE_EXECUTABLE; - }, devs)) { - // According to the OpenCL 1.2 specification, “if program is created - // with clCreateProgramWithBinary, then the program binary must be an - // executable binary (not a compiled binary or library).” - throw error(CL_INVALID_BINARY); - } - - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clCompileProgram(cl_program d_prog, cl_uint num_devs, - const cl_device_id *d_devs, const char *p_opts, - cl_uint num_headers, const cl_program *d_header_progs, - const char **header_names, - void (*pfn_notify)(cl_program, void *), - void *user_data) try { - auto &prog = obj(d_prog); - auto devs = - (d_devs ? objs(d_devs, num_devs) : ref_vector(prog.devices())); - const auto opts = std::string(p_opts ? p_opts : "") + " " + - debug_get_option("CLOVER_EXTRA_COMPILE_OPTIONS", ""); - header_map headers; - - validate_build_common(prog, num_devs, d_devs, pfn_notify, user_data); - - if (bool(num_headers) != bool(header_names)) - throw error(CL_INVALID_VALUE); - - if (!prog.has_source) - throw error(CL_INVALID_OPERATION); - - for_each([&](const char *name, const program &header) { - if (!header.has_source) - throw error(CL_INVALID_OPERATION); - - if (!any_of(key_equals(name), headers)) - headers.push_back(std::pair( - name, header.source())); - }, - range(header_names, num_headers), - objs(d_header_progs, num_headers)); - - prog.compile(devs, opts, headers); - return CL_SUCCESS; - -} catch (invalid_build_options_error &e) { - return CL_INVALID_COMPILER_OPTIONS; - -} catch (build_error &e) { - return CL_COMPILE_PROGRAM_FAILURE; - -} catch (error &e) { - return e.get(); -} - -namespace { - ref_vector - validate_link_devices(const ref_vector &progs, - const ref_vector &all_devs, - const std::string &opts) { - std::vector devs; - const bool create_library = - opts.find("-create-library") != std::string::npos; - const bool enable_link_options = - opts.find("-enable-link-options") != std::string::npos; - const bool has_link_options = - opts.find("-cl-denorms-are-zero") != std::string::npos || - opts.find("-cl-no-signed-zeroes") != std::string::npos || - opts.find("-cl-unsafe-math-optimizations") != std::string::npos || - opts.find("-cl-finite-math-only") != std::string::npos || - opts.find("-cl-fast-relaxed-math") != std::string::npos || - opts.find("-cl-no-subgroup-ifp") != std::string::npos; - - // According to the OpenCL 1.2 specification, "[the - // -enable-link-options] option must be specified with the - // create-library option". - if (enable_link_options && !create_library) - throw error(CL_INVALID_LINKER_OPTIONS); - - // According to the OpenCL 1.2 specification, "the - // [program linking options] can be specified when linking a program - // executable". - if (has_link_options && create_library) - throw error(CL_INVALID_LINKER_OPTIONS); - - for (auto &dev : all_devs) { - const auto has_binary = [&](const program &prog) { - const auto t = prog.build(dev).binary_type(); - return t == CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT || - t == CL_PROGRAM_BINARY_TYPE_LIBRARY; - }; - - // According to the OpenCL 1.2 specification, a library is made of - // “compiled binaries specified in input_programs argument to - // clLinkProgram“; compiled binaries does not refer to libraries: - // “input_programs is an array of program objects that are compiled - // binaries or libraries that are to be linked to create the program - // executable”. - if (create_library && any_of([&](const program &prog) { - const auto t = prog.build(dev).binary_type(); - return t != CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT; - }, progs)) - throw error(CL_INVALID_OPERATION); - - // According to the CL 1.2 spec, when "all programs specified [..] - // contain a compiled binary or library for the device [..] a link is - // performed", - else if (all_of(has_binary, progs)) - devs.push_back(&dev); - - // otherwise if "none of the programs contain a compiled binary or - // library for that device [..] no link is performed. All other - // cases will return a CL_INVALID_OPERATION error." - else if (any_of(has_binary, progs)) - throw error(CL_INVALID_OPERATION); - - // According to the OpenCL 1.2 specification, "[t]he linker may apply - // [program linking options] to all compiled program objects - // specified to clLinkProgram. The linker may apply these options - // only to libraries which were created with the - // -enable-link-option." - else if (has_link_options && any_of([&](const program &prog) { - const auto t = prog.build(dev).binary_type(); - return !(t == CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT || - (t == CL_PROGRAM_BINARY_TYPE_LIBRARY && - prog.build(dev).opts.find("-enable-link-options") != - std::string::npos)); - }, progs)) - throw error(CL_INVALID_LINKER_OPTIONS); - } - - return map(derefs(), devs); - } -} - -CLOVER_API cl_program -clLinkProgram(cl_context d_ctx, cl_uint num_devs, const cl_device_id *d_devs, - const char *p_opts, cl_uint num_progs, const cl_program *d_progs, - void (*pfn_notify) (cl_program, void *), void *user_data, - cl_int *r_errcode) try { - auto &ctx = obj(d_ctx); - const auto opts = std::string(p_opts ? p_opts : "") + " " + - debug_get_option("CLOVER_EXTRA_LINK_OPTIONS", ""); - auto progs = objs(d_progs, num_progs); - auto all_devs = - (d_devs ? objs(d_devs, num_devs) : ref_vector(ctx.devices())); - auto prog = create(ctx, all_devs); - auto devs = validate_link_devices(progs, all_devs, opts); - - validate_build_common(prog, num_devs, d_devs, pfn_notify, user_data); - - try { - prog().link(devs, opts, progs); - ret_error(r_errcode, CL_SUCCESS); - - } catch (build_error &e) { - ret_error(r_errcode, CL_LINK_PROGRAM_FAILURE); - } - - return ret_object(prog); - -} catch (invalid_build_options_error &e) { - ret_error(r_errcode, CL_INVALID_LINKER_OPTIONS); - return NULL; - -} catch (error &e) { - ret_error(r_errcode, e); - return NULL; -} - -CLOVER_API cl_int -clUnloadCompiler() { - return CL_SUCCESS; -} - -CLOVER_API cl_int -clUnloadPlatformCompiler(cl_platform_id d_platform) { - return CL_SUCCESS; -} - -CLOVER_API cl_int -clGetProgramInfo(cl_program d_prog, cl_program_info param, - size_t size, void *r_buf, size_t *r_size) try { - property_buffer buf { r_buf, size, r_size }; - auto &prog = obj(d_prog); - - switch (param) { - case CL_PROGRAM_REFERENCE_COUNT: - buf.as_scalar() = prog.ref_count(); - break; - - case CL_PROGRAM_CONTEXT: - buf.as_scalar() = desc(prog.context()); - break; - - case CL_PROGRAM_NUM_DEVICES: - buf.as_scalar() = (prog.devices().size() ? - prog.devices().size() : - prog.context().devices().size()); - break; - - case CL_PROGRAM_DEVICES: - buf.as_vector() = (prog.devices().size() ? - descs(prog.devices()) : - descs(prog.context().devices())); - break; - - case CL_PROGRAM_SOURCE: - buf.as_string() = prog.source(); - break; - - case CL_PROGRAM_BINARY_SIZES: - buf.as_vector() = map([&](const device &dev) { - return prog.build(dev).binary.size(); - }, - prog.devices()); - break; - - case CL_PROGRAM_BINARIES: - buf.as_matrix() = map([&](const device &dev) { - std::stringbuf bin; - std::ostream s(&bin); - prog.build(dev).binary.serialize(s); - return bin.str(); - }, - prog.devices()); - break; - - case CL_PROGRAM_NUM_KERNELS: - buf.as_scalar() = prog.symbols().size(); - break; - - case CL_PROGRAM_KERNEL_NAMES: - buf.as_string() = fold([](const std::string &a, const module::symbol &s) { - return ((a.empty() ? "" : a + ";") + s.name); - }, std::string(), prog.symbols()); - break; - - default: - throw error(CL_INVALID_VALUE); - } - - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clGetProgramBuildInfo(cl_program d_prog, cl_device_id d_dev, - cl_program_build_info param, - size_t size, void *r_buf, size_t *r_size) try { - property_buffer buf { r_buf, size, r_size }; - auto &prog = obj(d_prog); - auto &dev = obj(d_dev); - - if (!count(dev, prog.context().devices())) - return CL_INVALID_DEVICE; - - switch (param) { - case CL_PROGRAM_BUILD_STATUS: - buf.as_scalar() = prog.build(dev).status(); - break; - - case CL_PROGRAM_BUILD_OPTIONS: - buf.as_string() = prog.build(dev).opts; - break; - - case CL_PROGRAM_BUILD_LOG: - buf.as_string() = prog.build(dev).log; - break; - - case CL_PROGRAM_BINARY_TYPE: - buf.as_scalar() = prog.build(dev).binary_type(); - break; - - default: - throw error(CL_INVALID_VALUE); - } - - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} diff --git a/src/gallium/state_trackers/clover/api/queue.cpp b/src/gallium/state_trackers/clover/api/queue.cpp deleted file mode 100644 index 65b271b216f..00000000000 --- a/src/gallium/state_trackers/clover/api/queue.cpp +++ /dev/null @@ -1,135 +0,0 @@ -// -// Copyright 2012 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#include "api/util.hpp" -#include "core/queue.hpp" - -using namespace clover; - -CLOVER_API cl_command_queue -clCreateCommandQueue(cl_context d_ctx, cl_device_id d_dev, - cl_command_queue_properties props, - cl_int *r_errcode) try { - auto &ctx = obj(d_ctx); - auto &dev = obj(d_dev); - - if (!count(dev, ctx.devices())) - throw error(CL_INVALID_DEVICE); - - if (props & ~(CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE | - CL_QUEUE_PROFILING_ENABLE)) - throw error(CL_INVALID_VALUE); - - ret_error(r_errcode, CL_SUCCESS); - return new command_queue(ctx, dev, props); - -} catch (error &e) { - ret_error(r_errcode, e); - return NULL; -} - -CLOVER_API cl_int -clRetainCommandQueue(cl_command_queue d_q) try { - obj(d_q).retain(); - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clReleaseCommandQueue(cl_command_queue d_q) try { - auto &q = obj(d_q); - - q.flush(); - - if (q.release()) - delete pobj(d_q); - - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clGetCommandQueueInfo(cl_command_queue d_q, cl_command_queue_info param, - size_t size, void *r_buf, size_t *r_size) try { - property_buffer buf { r_buf, size, r_size }; - auto &q = obj(d_q); - - switch (param) { - case CL_QUEUE_CONTEXT: - buf.as_scalar() = desc(q.context()); - break; - - case CL_QUEUE_DEVICE: - buf.as_scalar() = desc(q.device()); - break; - - case CL_QUEUE_REFERENCE_COUNT: - buf.as_scalar() = q.ref_count(); - break; - - case CL_QUEUE_PROPERTIES: - buf.as_scalar() = q.properties(); - break; - - default: - throw error(CL_INVALID_VALUE); - } - - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clFlush(cl_command_queue d_q) try { - obj(d_q).flush(); - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_command_queue -clCreateCommandQueueWithProperties(cl_context context, cl_device_id device, - const cl_queue_properties *properties, - cl_int *errcode_ret) try { - cl_command_queue_properties props = 0; - if (properties) { - for (auto idx = 0; properties[idx]; idx += 2) { - if (properties[idx] == CL_QUEUE_PROPERTIES) - props |= properties[idx + 1]; - else - throw error(CL_INVALID_VALUE); - } - } - - return clCreateCommandQueue(context, device, props, errcode_ret); - -} catch (error &e) { - ret_error(errcode_ret, e); - return NULL; -} diff --git a/src/gallium/state_trackers/clover/api/sampler.cpp b/src/gallium/state_trackers/clover/api/sampler.cpp deleted file mode 100644 index 482e55a9ce9..00000000000 --- a/src/gallium/state_trackers/clover/api/sampler.cpp +++ /dev/null @@ -1,100 +0,0 @@ -// -// Copyright 2012 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#include "api/util.hpp" -#include "core/sampler.hpp" - -using namespace clover; - -CLOVER_API cl_sampler -clCreateSampler(cl_context d_ctx, cl_bool norm_mode, - cl_addressing_mode addr_mode, cl_filter_mode filter_mode, - cl_int *r_errcode) try { - auto &ctx = obj(d_ctx); - - if (!any_of(std::mem_fn(&device::image_support), ctx.devices())) - throw error(CL_INVALID_OPERATION); - - ret_error(r_errcode, CL_SUCCESS); - return new sampler(ctx, norm_mode, addr_mode, filter_mode); - -} catch (error &e) { - ret_error(r_errcode, e); - return NULL; -} - -CLOVER_API cl_int -clRetainSampler(cl_sampler d_s) try { - obj(d_s).retain(); - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clReleaseSampler(cl_sampler d_s) try { - if (obj(d_s).release()) - delete pobj(d_s); - - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clGetSamplerInfo(cl_sampler d_s, cl_sampler_info param, - size_t size, void *r_buf, size_t *r_size) try { - property_buffer buf { r_buf, size, r_size }; - auto &s = obj(d_s); - - switch (param) { - case CL_SAMPLER_REFERENCE_COUNT: - buf.as_scalar() = s.ref_count(); - break; - - case CL_SAMPLER_CONTEXT: - buf.as_scalar() = desc(s.context()); - break; - - case CL_SAMPLER_NORMALIZED_COORDS: - buf.as_scalar() = s.norm_mode(); - break; - - case CL_SAMPLER_ADDRESSING_MODE: - buf.as_scalar() = s.addr_mode(); - break; - - case CL_SAMPLER_FILTER_MODE: - buf.as_scalar() = s.filter_mode(); - break; - - default: - throw error(CL_INVALID_VALUE); - } - - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} diff --git a/src/gallium/state_trackers/clover/api/transfer.cpp b/src/gallium/state_trackers/clover/api/transfer.cpp deleted file mode 100644 index fa8741e02b4..00000000000 --- a/src/gallium/state_trackers/clover/api/transfer.cpp +++ /dev/null @@ -1,1059 +0,0 @@ -// -// Copyright 2012 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#include - -#include "util/bitscan.h" - -#include "api/dispatch.hpp" -#include "api/util.hpp" -#include "core/event.hpp" -#include "core/memory.hpp" - -using namespace clover; - -namespace { - typedef resource::vector vector_t; - - vector_t - vector(const size_t *p) { - return range(p, 3); - } - - vector_t - pitch(const vector_t ®ion, vector_t pitch) { - for (auto x : zip(tail(pitch), - map(multiplies(), region, pitch))) { - // The spec defines a value of zero as the natural pitch, - // i.e. the unaligned size of the previous dimension. - if (std::get<0>(x) == 0) - std::get<0>(x) = std::get<1>(x); - } - - return pitch; - } - - /// - /// Size of a region in bytes. - /// - size_t - size(const vector_t &pitch, const vector_t ®ion) { - if (any_of(is_zero(), region)) - return 0; - else - return dot(pitch, region - vector_t{ 0, 1, 1 }); - } - - /// - /// Common argument checking shared by memory transfer commands. - /// - void - validate_common(command_queue &q, - const ref_vector &deps) { - if (any_of([&](const event &ev) { - return ev.context() != q.context(); - }, deps)) - throw error(CL_INVALID_CONTEXT); - } - - /// - /// Common error checking for a buffer object argument. - /// - void - validate_object(command_queue &q, buffer &mem, const vector_t &origin, - const vector_t &pitch, const vector_t ®ion) { - if (mem.context() != q.context()) - throw error(CL_INVALID_CONTEXT); - - // The region must fit within the specified pitch, - if (any_of(greater(), map(multiplies(), pitch, region), tail(pitch))) - throw error(CL_INVALID_VALUE); - - // ...and within the specified object. - if (dot(pitch, origin) + size(pitch, region) > mem.size()) - throw error(CL_INVALID_VALUE); - - if (any_of(is_zero(), region)) - throw error(CL_INVALID_VALUE); - } - - /// - /// Common error checking for an image argument. - /// - void - validate_object(command_queue &q, image &img, - const vector_t &orig, const vector_t ®ion) { - vector_t size = { img.width(), img.height(), img.depth() }; - - if (!q.device().image_support()) - throw error(CL_INVALID_OPERATION); - - if (img.context() != q.context()) - throw error(CL_INVALID_CONTEXT); - - if (any_of(greater(), orig + region, size)) - throw error(CL_INVALID_VALUE); - - if (any_of(is_zero(), region)) - throw error(CL_INVALID_VALUE); - } - - /// - /// Common error checking for a host pointer argument. - /// - void - validate_object(command_queue &q, const void *ptr, const vector_t &orig, - const vector_t &pitch, const vector_t ®ion) { - if (!ptr) - throw error(CL_INVALID_VALUE); - - // The region must fit within the specified pitch. - if (any_of(greater(), map(multiplies(), pitch, region), tail(pitch))) - throw error(CL_INVALID_VALUE); - } - - /// - /// Common argument checking for a copy between two buffer objects. - /// - void - validate_copy(command_queue &q, buffer &dst_mem, - const vector_t &dst_orig, const vector_t &dst_pitch, - buffer &src_mem, - const vector_t &src_orig, const vector_t &src_pitch, - const vector_t ®ion) { - if (dst_mem == src_mem) { - auto dst_offset = dot(dst_pitch, dst_orig); - auto src_offset = dot(src_pitch, src_orig); - - if (interval_overlaps()( - dst_offset, dst_offset + size(dst_pitch, region), - src_offset, src_offset + size(src_pitch, region))) - throw error(CL_MEM_COPY_OVERLAP); - } - } - - /// - /// Common argument checking for a copy between two image objects. - /// - void - validate_copy(command_queue &q, - image &dst_img, const vector_t &dst_orig, - image &src_img, const vector_t &src_orig, - const vector_t ®ion) { - if (dst_img.format() != src_img.format()) - throw error(CL_IMAGE_FORMAT_MISMATCH); - - if (dst_img == src_img) { - if (all_of(interval_overlaps(), - dst_orig, dst_orig + region, - src_orig, src_orig + region)) - throw error(CL_MEM_COPY_OVERLAP); - } - } - - /// - /// Checks that the host access flags of the memory object are - /// within the allowed set \a flags. - /// - void - validate_object_access(const memory_obj &mem, const cl_mem_flags flags) { - if (mem.flags() & ~flags & - (CL_MEM_HOST_READ_ONLY | CL_MEM_HOST_WRITE_ONLY | - CL_MEM_HOST_NO_ACCESS)) - throw error(CL_INVALID_OPERATION); - } - - /// - /// Checks that the mapping flags are correct. - /// - void - validate_map_flags(const memory_obj &mem, const cl_map_flags flags) { - if ((flags & (CL_MAP_WRITE | CL_MAP_READ)) && - (flags & CL_MAP_WRITE_INVALIDATE_REGION)) - throw error(CL_INVALID_VALUE); - - if (flags & CL_MAP_READ) - validate_object_access(mem, CL_MEM_HOST_READ_ONLY); - - if (flags & (CL_MAP_WRITE | CL_MAP_WRITE_INVALIDATE_REGION)) - validate_object_access(mem, CL_MEM_HOST_WRITE_ONLY); - } - - /// - /// Class that encapsulates the task of mapping an object of type - /// \a T. The return value of get() should be implicitly - /// convertible to \a void *. - /// - template - struct _map { - static mapping - get(command_queue &q, T obj, cl_map_flags flags, - size_t offset, size_t size) { - return { q, obj->resource(q), flags, true, - {{ offset }}, {{ size, 1, 1 }} }; - } - }; - - template<> - struct _map { - static void * - get(command_queue &q, void *obj, cl_map_flags flags, - size_t offset, size_t size) { - return (char *)obj + offset; - } - }; - - template<> - struct _map { - static const void * - get(command_queue &q, const void *obj, cl_map_flags flags, - size_t offset, size_t size) { - return (const char *)obj + offset; - } - }; - - /// - /// Software copy from \a src_obj to \a dst_obj. They can be - /// either pointers or memory objects. - /// - template - std::function - soft_copy_op(command_queue &q, - T dst_obj, const vector_t &dst_orig, const vector_t &dst_pitch, - S src_obj, const vector_t &src_orig, const vector_t &src_pitch, - const vector_t ®ion) { - return [=, &q](event &) { - auto dst = _map::get(q, dst_obj, CL_MAP_WRITE, - dot(dst_pitch, dst_orig), - size(dst_pitch, region)); - auto src = _map::get(q, src_obj, CL_MAP_READ, - dot(src_pitch, src_orig), - size(src_pitch, region)); - vector_t v = {}; - - for (v[2] = 0; v[2] < region[2]; ++v[2]) { - for (v[1] = 0; v[1] < region[1]; ++v[1]) { - std::memcpy( - static_cast(dst) + dot(dst_pitch, v), - static_cast(src) + dot(src_pitch, v), - src_pitch[0] * region[0]); - } - } - }; - } - - /// - /// Hardware copy from \a src_obj to \a dst_obj. - /// - template - std::function - hard_copy_op(command_queue &q, T dst_obj, const vector_t &dst_orig, - S src_obj, const vector_t &src_orig, const vector_t ®ion) { - return [=, &q](event &) { - dst_obj->resource(q).copy(q, dst_orig, region, - src_obj->resource(q), src_orig); - }; - } -} - -CLOVER_API cl_int -clEnqueueReadBuffer(cl_command_queue d_q, cl_mem d_mem, cl_bool blocking, - size_t offset, size_t size, void *ptr, - cl_uint num_deps, const cl_event *d_deps, - cl_event *rd_ev) try { - auto &q = obj(d_q); - auto &mem = obj(d_mem); - auto deps = objs(d_deps, num_deps); - vector_t region = { size, 1, 1 }; - vector_t obj_origin = { offset }; - auto obj_pitch = pitch(region, {{ 1 }}); - - validate_common(q, deps); - validate_object(q, ptr, {}, obj_pitch, region); - validate_object(q, mem, obj_origin, obj_pitch, region); - validate_object_access(mem, CL_MEM_HOST_READ_ONLY); - - auto hev = create( - q, CL_COMMAND_READ_BUFFER, deps, - soft_copy_op(q, ptr, {}, obj_pitch, - &mem, obj_origin, obj_pitch, - region)); - - if (blocking) - hev().wait_signalled(); - - ret_object(rd_ev, hev); - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clEnqueueWriteBuffer(cl_command_queue d_q, cl_mem d_mem, cl_bool blocking, - size_t offset, size_t size, const void *ptr, - cl_uint num_deps, const cl_event *d_deps, - cl_event *rd_ev) try { - auto &q = obj(d_q); - auto &mem = obj(d_mem); - auto deps = objs(d_deps, num_deps); - vector_t region = { size, 1, 1 }; - vector_t obj_origin = { offset }; - auto obj_pitch = pitch(region, {{ 1 }}); - - validate_common(q, deps); - validate_object(q, mem, obj_origin, obj_pitch, region); - validate_object(q, ptr, {}, obj_pitch, region); - validate_object_access(mem, CL_MEM_HOST_WRITE_ONLY); - - auto hev = create( - q, CL_COMMAND_WRITE_BUFFER, deps, - soft_copy_op(q, &mem, obj_origin, obj_pitch, - ptr, {}, obj_pitch, - region)); - - if (blocking) - hev().wait_signalled(); - - ret_object(rd_ev, hev); - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clEnqueueReadBufferRect(cl_command_queue d_q, cl_mem d_mem, cl_bool blocking, - const size_t *p_obj_origin, - const size_t *p_host_origin, - const size_t *p_region, - size_t obj_row_pitch, size_t obj_slice_pitch, - size_t host_row_pitch, size_t host_slice_pitch, - void *ptr, - cl_uint num_deps, const cl_event *d_deps, - cl_event *rd_ev) try { - auto &q = obj(d_q); - auto &mem = obj(d_mem); - auto deps = objs(d_deps, num_deps); - auto region = vector(p_region); - auto obj_origin = vector(p_obj_origin); - auto obj_pitch = pitch(region, {{ 1, obj_row_pitch, obj_slice_pitch }}); - auto host_origin = vector(p_host_origin); - auto host_pitch = pitch(region, {{ 1, host_row_pitch, host_slice_pitch }}); - - validate_common(q, deps); - validate_object(q, ptr, host_origin, host_pitch, region); - validate_object(q, mem, obj_origin, obj_pitch, region); - validate_object_access(mem, CL_MEM_HOST_READ_ONLY); - - auto hev = create( - q, CL_COMMAND_READ_BUFFER_RECT, deps, - soft_copy_op(q, ptr, host_origin, host_pitch, - &mem, obj_origin, obj_pitch, - region)); - - if (blocking) - hev().wait_signalled(); - - ret_object(rd_ev, hev); - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clEnqueueWriteBufferRect(cl_command_queue d_q, cl_mem d_mem, cl_bool blocking, - const size_t *p_obj_origin, - const size_t *p_host_origin, - const size_t *p_region, - size_t obj_row_pitch, size_t obj_slice_pitch, - size_t host_row_pitch, size_t host_slice_pitch, - const void *ptr, - cl_uint num_deps, const cl_event *d_deps, - cl_event *rd_ev) try { - auto &q = obj(d_q); - auto &mem = obj(d_mem); - auto deps = objs(d_deps, num_deps); - auto region = vector(p_region); - auto obj_origin = vector(p_obj_origin); - auto obj_pitch = pitch(region, {{ 1, obj_row_pitch, obj_slice_pitch }}); - auto host_origin = vector(p_host_origin); - auto host_pitch = pitch(region, {{ 1, host_row_pitch, host_slice_pitch }}); - - validate_common(q, deps); - validate_object(q, mem, obj_origin, obj_pitch, region); - validate_object(q, ptr, host_origin, host_pitch, region); - validate_object_access(mem, CL_MEM_HOST_WRITE_ONLY); - - auto hev = create( - q, CL_COMMAND_WRITE_BUFFER_RECT, deps, - soft_copy_op(q, &mem, obj_origin, obj_pitch, - ptr, host_origin, host_pitch, - region)); - - if (blocking) - hev().wait_signalled(); - - ret_object(rd_ev, hev); - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clEnqueueCopyBuffer(cl_command_queue d_q, cl_mem d_src_mem, cl_mem d_dst_mem, - size_t src_offset, size_t dst_offset, size_t size, - cl_uint num_deps, const cl_event *d_deps, - cl_event *rd_ev) try { - auto &q = obj(d_q); - auto &src_mem = obj(d_src_mem); - auto &dst_mem = obj(d_dst_mem); - auto deps = objs(d_deps, num_deps); - vector_t region = { size, 1, 1 }; - vector_t dst_origin = { dst_offset }; - auto dst_pitch = pitch(region, {{ 1 }}); - vector_t src_origin = { src_offset }; - auto src_pitch = pitch(region, {{ 1 }}); - - validate_common(q, deps); - validate_object(q, dst_mem, dst_origin, dst_pitch, region); - validate_object(q, src_mem, src_origin, src_pitch, region); - validate_copy(q, dst_mem, dst_origin, dst_pitch, - src_mem, src_origin, src_pitch, region); - - auto hev = create( - q, CL_COMMAND_COPY_BUFFER, deps, - hard_copy_op(q, &dst_mem, dst_origin, - &src_mem, src_origin, region)); - - ret_object(rd_ev, hev); - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clEnqueueCopyBufferRect(cl_command_queue d_q, cl_mem d_src_mem, - cl_mem d_dst_mem, - const size_t *p_src_origin, const size_t *p_dst_origin, - const size_t *p_region, - size_t src_row_pitch, size_t src_slice_pitch, - size_t dst_row_pitch, size_t dst_slice_pitch, - cl_uint num_deps, const cl_event *d_deps, - cl_event *rd_ev) try { - auto &q = obj(d_q); - auto &src_mem = obj(d_src_mem); - auto &dst_mem = obj(d_dst_mem); - auto deps = objs(d_deps, num_deps); - auto region = vector(p_region); - auto dst_origin = vector(p_dst_origin); - auto dst_pitch = pitch(region, {{ 1, dst_row_pitch, dst_slice_pitch }}); - auto src_origin = vector(p_src_origin); - auto src_pitch = pitch(region, {{ 1, src_row_pitch, src_slice_pitch }}); - - validate_common(q, deps); - validate_object(q, dst_mem, dst_origin, dst_pitch, region); - validate_object(q, src_mem, src_origin, src_pitch, region); - validate_copy(q, dst_mem, dst_origin, dst_pitch, - src_mem, src_origin, src_pitch, region); - - auto hev = create( - q, CL_COMMAND_COPY_BUFFER_RECT, deps, - soft_copy_op(q, &dst_mem, dst_origin, dst_pitch, - &src_mem, src_origin, src_pitch, - region)); - - ret_object(rd_ev, hev); - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clEnqueueReadImage(cl_command_queue d_q, cl_mem d_mem, cl_bool blocking, - const size_t *p_origin, const size_t *p_region, - size_t row_pitch, size_t slice_pitch, void *ptr, - cl_uint num_deps, const cl_event *d_deps, - cl_event *rd_ev) try { - auto &q = obj(d_q); - auto &img = obj(d_mem); - auto deps = objs(d_deps, num_deps); - auto region = vector(p_region); - auto dst_pitch = pitch(region, {{ img.pixel_size(), - row_pitch, slice_pitch }}); - auto src_origin = vector(p_origin); - auto src_pitch = pitch(region, {{ img.pixel_size(), - img.row_pitch(), img.slice_pitch() }}); - - validate_common(q, deps); - validate_object(q, ptr, {}, dst_pitch, region); - validate_object(q, img, src_origin, region); - validate_object_access(img, CL_MEM_HOST_READ_ONLY); - - auto hev = create( - q, CL_COMMAND_READ_IMAGE, deps, - soft_copy_op(q, ptr, {}, dst_pitch, - &img, src_origin, src_pitch, - region)); - - if (blocking) - hev().wait_signalled(); - - ret_object(rd_ev, hev); - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clEnqueueWriteImage(cl_command_queue d_q, cl_mem d_mem, cl_bool blocking, - const size_t *p_origin, const size_t *p_region, - size_t row_pitch, size_t slice_pitch, const void *ptr, - cl_uint num_deps, const cl_event *d_deps, - cl_event *rd_ev) try { - auto &q = obj(d_q); - auto &img = obj(d_mem); - auto deps = objs(d_deps, num_deps); - auto region = vector(p_region); - auto dst_origin = vector(p_origin); - auto dst_pitch = pitch(region, {{ img.pixel_size(), - img.row_pitch(), img.slice_pitch() }}); - auto src_pitch = pitch(region, {{ img.pixel_size(), - row_pitch, slice_pitch }}); - - validate_common(q, deps); - validate_object(q, img, dst_origin, region); - validate_object(q, ptr, {}, src_pitch, region); - validate_object_access(img, CL_MEM_HOST_WRITE_ONLY); - - auto hev = create( - q, CL_COMMAND_WRITE_IMAGE, deps, - soft_copy_op(q, &img, dst_origin, dst_pitch, - ptr, {}, src_pitch, - region)); - - if (blocking) - hev().wait_signalled(); - - ret_object(rd_ev, hev); - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clEnqueueCopyImage(cl_command_queue d_q, cl_mem d_src_mem, cl_mem d_dst_mem, - const size_t *p_src_origin, const size_t *p_dst_origin, - const size_t *p_region, - cl_uint num_deps, const cl_event *d_deps, - cl_event *rd_ev) try { - auto &q = obj(d_q); - auto &src_img = obj(d_src_mem); - auto &dst_img = obj(d_dst_mem); - auto deps = objs(d_deps, num_deps); - auto region = vector(p_region); - auto dst_origin = vector(p_dst_origin); - auto src_origin = vector(p_src_origin); - - validate_common(q, deps); - validate_object(q, dst_img, dst_origin, region); - validate_object(q, src_img, src_origin, region); - validate_copy(q, dst_img, dst_origin, src_img, src_origin, region); - - auto hev = create( - q, CL_COMMAND_COPY_IMAGE, deps, - hard_copy_op(q, &dst_img, dst_origin, - &src_img, src_origin, - region)); - - ret_object(rd_ev, hev); - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clEnqueueCopyImageToBuffer(cl_command_queue d_q, - cl_mem d_src_mem, cl_mem d_dst_mem, - const size_t *p_src_origin, const size_t *p_region, - size_t dst_offset, - cl_uint num_deps, const cl_event *d_deps, - cl_event *rd_ev) try { - auto &q = obj(d_q); - auto &src_img = obj(d_src_mem); - auto &dst_mem = obj(d_dst_mem); - auto deps = objs(d_deps, num_deps); - auto region = vector(p_region); - vector_t dst_origin = { dst_offset }; - auto dst_pitch = pitch(region, {{ src_img.pixel_size() }}); - auto src_origin = vector(p_src_origin); - auto src_pitch = pitch(region, {{ src_img.pixel_size(), - src_img.row_pitch(), - src_img.slice_pitch() }}); - - validate_common(q, deps); - validate_object(q, dst_mem, dst_origin, dst_pitch, region); - validate_object(q, src_img, src_origin, region); - - auto hev = create( - q, CL_COMMAND_COPY_IMAGE_TO_BUFFER, deps, - soft_copy_op(q, &dst_mem, dst_origin, dst_pitch, - &src_img, src_origin, src_pitch, - region)); - - ret_object(rd_ev, hev); - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clEnqueueCopyBufferToImage(cl_command_queue d_q, - cl_mem d_src_mem, cl_mem d_dst_mem, - size_t src_offset, - const size_t *p_dst_origin, const size_t *p_region, - cl_uint num_deps, const cl_event *d_deps, - cl_event *rd_ev) try { - auto &q = obj(d_q); - auto &src_mem = obj(d_src_mem); - auto &dst_img = obj(d_dst_mem); - auto deps = objs(d_deps, num_deps); - auto region = vector(p_region); - auto dst_origin = vector(p_dst_origin); - auto dst_pitch = pitch(region, {{ dst_img.pixel_size(), - dst_img.row_pitch(), - dst_img.slice_pitch() }}); - vector_t src_origin = { src_offset }; - auto src_pitch = pitch(region, {{ dst_img.pixel_size() }}); - - validate_common(q, deps); - validate_object(q, dst_img, dst_origin, region); - validate_object(q, src_mem, src_origin, src_pitch, region); - - auto hev = create( - q, CL_COMMAND_COPY_BUFFER_TO_IMAGE, deps, - soft_copy_op(q, &dst_img, dst_origin, dst_pitch, - &src_mem, src_origin, src_pitch, - region)); - - ret_object(rd_ev, hev); - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API void * -clEnqueueMapBuffer(cl_command_queue d_q, cl_mem d_mem, cl_bool blocking, - cl_map_flags flags, size_t offset, size_t size, - cl_uint num_deps, const cl_event *d_deps, - cl_event *rd_ev, cl_int *r_errcode) try { - auto &q = obj(d_q); - auto &mem = obj(d_mem); - auto deps = objs(d_deps, num_deps); - vector_t region = { size, 1, 1 }; - vector_t obj_origin = { offset }; - auto obj_pitch = pitch(region, {{ 1 }}); - - validate_common(q, deps); - validate_object(q, mem, obj_origin, obj_pitch, region); - validate_map_flags(mem, flags); - - void *map = mem.resource(q).add_map(q, flags, blocking, obj_origin, region); - - auto hev = create(q, CL_COMMAND_MAP_BUFFER, deps); - if (blocking) - hev().wait_signalled(); - - ret_object(rd_ev, hev); - ret_error(r_errcode, CL_SUCCESS); - return map; - -} catch (error &e) { - ret_error(r_errcode, e); - return NULL; -} - -CLOVER_API void * -clEnqueueMapImage(cl_command_queue d_q, cl_mem d_mem, cl_bool blocking, - cl_map_flags flags, - const size_t *p_origin, const size_t *p_region, - size_t *row_pitch, size_t *slice_pitch, - cl_uint num_deps, const cl_event *d_deps, - cl_event *rd_ev, cl_int *r_errcode) try { - auto &q = obj(d_q); - auto &img = obj(d_mem); - auto deps = objs(d_deps, num_deps); - auto region = vector(p_region); - auto origin = vector(p_origin); - - validate_common(q, deps); - validate_object(q, img, origin, region); - validate_map_flags(img, flags); - - void *map = img.resource(q).add_map(q, flags, blocking, origin, region); - - auto hev = create(q, CL_COMMAND_MAP_IMAGE, deps); - if (blocking) - hev().wait_signalled(); - - ret_object(rd_ev, hev); - ret_error(r_errcode, CL_SUCCESS); - return map; - -} catch (error &e) { - ret_error(r_errcode, e); - return NULL; -} - -CLOVER_API cl_int -clEnqueueUnmapMemObject(cl_command_queue d_q, cl_mem d_mem, void *ptr, - cl_uint num_deps, const cl_event *d_deps, - cl_event *rd_ev) try { - auto &q = obj(d_q); - auto &mem = obj(d_mem); - auto deps = objs(d_deps, num_deps); - - validate_common(q, deps); - - auto hev = create( - q, CL_COMMAND_UNMAP_MEM_OBJECT, deps, - [=, &q, &mem](event &) { - mem.resource(q).del_map(ptr); - }); - - ret_object(rd_ev, hev); - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clEnqueueMigrateMemObjects(cl_command_queue command_queue, - cl_uint num_mem_objects, - const cl_mem *mem_objects, - cl_mem_migration_flags flags, - cl_uint num_events_in_wait_list, - const cl_event *event_wait_list, - cl_event *event) { - CLOVER_NOT_SUPPORTED_UNTIL("1.2"); - return CL_INVALID_VALUE; -} - -cl_int -clover::EnqueueSVMFree(cl_command_queue d_q, - cl_uint num_svm_pointers, - void *svm_pointers[], - void (CL_CALLBACK *pfn_free_func) ( - cl_command_queue queue, cl_uint num_svm_pointers, - void *svm_pointers[], void *user_data), - void *user_data, - cl_uint num_events_in_wait_list, - const cl_event *event_wait_list, - cl_event *event, - cl_int cmd) try { - - if (bool(num_svm_pointers) != bool(svm_pointers)) - return CL_INVALID_VALUE; - - auto &q = obj(d_q); - bool can_emulate = q.device().has_system_svm(); - auto deps = objs(event_wait_list, num_events_in_wait_list); - - validate_common(q, deps); - - std::vector svm_pointers_cpy(svm_pointers, - svm_pointers + num_svm_pointers); - if (!pfn_free_func) { - if (!can_emulate) { - CLOVER_NOT_SUPPORTED_UNTIL("2.0"); - return CL_INVALID_VALUE; - } - pfn_free_func = [](cl_command_queue, cl_uint num_svm_pointers, - void *svm_pointers[], void *) { - for (void *p : range(svm_pointers, num_svm_pointers)) - free(p); - }; - } - - auto hev = create(q, cmd, deps, - [=](clover::event &) mutable { - pfn_free_func(d_q, num_svm_pointers, svm_pointers_cpy.data(), - user_data); - }); - - ret_object(event, hev); - return CL_SUCCESS; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clEnqueueSVMFree(cl_command_queue d_q, - cl_uint num_svm_pointers, - void *svm_pointers[], - void (CL_CALLBACK *pfn_free_func) ( - cl_command_queue queue, cl_uint num_svm_pointers, - void *svm_pointers[], void *user_data), - void *user_data, - cl_uint num_events_in_wait_list, - const cl_event *event_wait_list, - cl_event *event) { - - return EnqueueSVMFree(d_q, num_svm_pointers, svm_pointers, - pfn_free_func, user_data, num_events_in_wait_list, - event_wait_list, event, CL_COMMAND_SVM_FREE); -} - -cl_int -clover::EnqueueSVMMemcpy(cl_command_queue d_q, - cl_bool blocking_copy, - void *dst_ptr, - const void *src_ptr, - size_t size, - cl_uint num_events_in_wait_list, - const cl_event *event_wait_list, - cl_event *event, - cl_int cmd) try { - - if (dst_ptr == nullptr || src_ptr == nullptr) - return CL_INVALID_VALUE; - - if (static_cast(abs(reinterpret_cast(dst_ptr) - - reinterpret_cast(src_ptr))) < size) - return CL_MEM_COPY_OVERLAP; - - auto &q = obj(d_q); - bool can_emulate = q.device().has_system_svm(); - auto deps = objs(event_wait_list, num_events_in_wait_list); - - validate_common(q, deps); - - if (can_emulate) { - auto hev = create(q, cmd, deps, - [=](clover::event &) { - memcpy(dst_ptr, src_ptr, size); - }); - - if (blocking_copy) - hev().wait(); - ret_object(event, hev); - return CL_SUCCESS; - } - - CLOVER_NOT_SUPPORTED_UNTIL("2.0"); - return CL_INVALID_VALUE; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clEnqueueSVMMemcpy(cl_command_queue d_q, - cl_bool blocking_copy, - void *dst_ptr, - const void *src_ptr, - size_t size, - cl_uint num_events_in_wait_list, - const cl_event *event_wait_list, - cl_event *event) { - - return EnqueueSVMMemcpy(d_q, blocking_copy, dst_ptr, src_ptr, - size, num_events_in_wait_list, event_wait_list, - event, CL_COMMAND_SVM_MEMCPY); -} - -cl_int -clover::EnqueueSVMMemFill(cl_command_queue d_q, - void *svm_ptr, - const void *pattern, - size_t pattern_size, - size_t size, - cl_uint num_events_in_wait_list, - const cl_event *event_wait_list, - cl_event *event, - cl_int cmd) try { - - if (svm_ptr == nullptr || pattern == nullptr || - !util_is_power_of_two_nonzero(pattern_size) || - pattern_size > 128 || - !ptr_is_aligned(svm_ptr, pattern_size) || - size % pattern_size) - return CL_INVALID_VALUE; - - auto &q = obj(d_q); - bool can_emulate = q.device().has_system_svm(); - auto deps = objs(event_wait_list, num_events_in_wait_list); - - validate_common(q, deps); - - if (can_emulate) { - auto hev = create(q, cmd, deps, - [=](clover::event &) { - void *ptr = svm_ptr; - for (size_t s = size; s; s -= pattern_size) { - memcpy(ptr, pattern, pattern_size); - ptr = static_cast(ptr) + pattern_size; - } - }); - - ret_object(event, hev); - return CL_SUCCESS; - } - - CLOVER_NOT_SUPPORTED_UNTIL("2.0"); - return CL_INVALID_VALUE; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clEnqueueSVMMemFill(cl_command_queue d_q, - void *svm_ptr, - const void *pattern, - size_t pattern_size, - size_t size, - cl_uint num_events_in_wait_list, - const cl_event *event_wait_list, - cl_event *event) { - - return EnqueueSVMMemFill(d_q, svm_ptr, pattern, pattern_size, - size, num_events_in_wait_list, event_wait_list, - event, CL_COMMAND_SVM_MEMFILL); -} - -cl_int -clover::EnqueueSVMMap(cl_command_queue d_q, - cl_bool blocking_map, - cl_map_flags map_flags, - void *svm_ptr, - size_t size, - cl_uint num_events_in_wait_list, - const cl_event *event_wait_list, - cl_event *event, - cl_int cmd) try { - - if (svm_ptr == nullptr || size == 0) - return CL_INVALID_VALUE; - - auto &q = obj(d_q); - bool can_emulate = q.device().has_system_svm(); - auto deps = objs(event_wait_list, num_events_in_wait_list); - - validate_common(q, deps); - - if (can_emulate) { - auto hev = create(q, cmd, deps, - [](clover::event &) { }); - - ret_object(event, hev); - return CL_SUCCESS; - } - - CLOVER_NOT_SUPPORTED_UNTIL("2.0"); - return CL_INVALID_VALUE; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clEnqueueSVMMap(cl_command_queue d_q, - cl_bool blocking_map, - cl_map_flags map_flags, - void *svm_ptr, - size_t size, - cl_uint num_events_in_wait_list, - const cl_event *event_wait_list, - cl_event *event) { - - return EnqueueSVMMap(d_q, blocking_map, map_flags, svm_ptr, size, - num_events_in_wait_list, event_wait_list, event, - CL_COMMAND_SVM_MAP); -} - -cl_int -clover::EnqueueSVMUnmap(cl_command_queue d_q, - void *svm_ptr, - cl_uint num_events_in_wait_list, - const cl_event *event_wait_list, - cl_event *event, - cl_int cmd) try { - - if (svm_ptr == nullptr) - return CL_INVALID_VALUE; - - auto &q = obj(d_q); - bool can_emulate = q.device().has_system_svm(); - auto deps = objs(event_wait_list, num_events_in_wait_list); - - validate_common(q, deps); - - if (can_emulate) { - auto hev = create(q, cmd, deps, - [](clover::event &) { }); - - ret_object(event, hev); - return CL_SUCCESS; - } - - CLOVER_NOT_SUPPORTED_UNTIL("2.0"); - return CL_INVALID_VALUE; - -} catch (error &e) { - return e.get(); -} - -CLOVER_API cl_int -clEnqueueSVMUnmap(cl_command_queue d_q, - void *svm_ptr, - cl_uint num_events_in_wait_list, - const cl_event *event_wait_list, - cl_event *event) { - - return EnqueueSVMUnmap(d_q, svm_ptr, num_events_in_wait_list, - event_wait_list, event, CL_COMMAND_SVM_UNMAP); -} - -CLOVER_API cl_int -clEnqueueSVMMigrateMem(cl_command_queue d_q, - cl_uint num_svm_pointers, - const void **svm_pointers, - const size_t *sizes, - const cl_mem_migration_flags flags, - cl_uint num_events_in_wait_list, - const cl_event *event_wait_list, - cl_event *event) { - CLOVER_NOT_SUPPORTED_UNTIL("2.1"); - return CL_INVALID_VALUE; -} diff --git a/src/gallium/state_trackers/clover/api/util.hpp b/src/gallium/state_trackers/clover/api/util.hpp deleted file mode 100644 index 66bd12597c6..00000000000 --- a/src/gallium/state_trackers/clover/api/util.hpp +++ /dev/null @@ -1,84 +0,0 @@ -// -// Copyright 2012 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#ifndef CLOVER_API_UTIL_HPP -#define CLOVER_API_UTIL_HPP - -#include -#include - -#include "core/error.hpp" -#include "core/property.hpp" -#include "util/algorithm.hpp" - -#ifdef HAVE_CLOVER_ICD -#define CLOVER_API -#define CLOVER_ICD_API PUBLIC -#else -#define CLOVER_API PUBLIC -#define CLOVER_ICD_API PUBLIC -#endif - -#define CLOVER_NOT_SUPPORTED_UNTIL(version) \ - do { \ - std::cerr << "CL user error: " << __func__ \ - << "() requires OpenCL version " << (version) \ - << " or greater." << std::endl; \ - } while (0) - -namespace clover { - /// - /// Return an error code in \a p if non-zero. - /// - inline void - ret_error(cl_int *p, const clover::error &e) { - if (p) - *p = e.get(); - } - - /// - /// Return a clover object in \a p if non-zero incrementing the - /// reference count of the object. - /// - template - void - ret_object(typename T::descriptor_type **p, - const intrusive_ref &v) { - if (p) { - v().retain(); - *p = desc(v()); - } - } - - /// - /// Return an API object from an intrusive reference to a Clover object, - /// incrementing the reference count of the object. - /// - template - typename T::descriptor_type * - ret_object(const intrusive_ref &v) { - v().retain(); - return desc(v()); - } -} - -#endif diff --git a/src/gallium/state_trackers/clover/core/compiler.hpp b/src/gallium/state_trackers/clover/core/compiler.hpp deleted file mode 100644 index 6ef30df9b7f..00000000000 --- a/src/gallium/state_trackers/clover/core/compiler.hpp +++ /dev/null @@ -1,68 +0,0 @@ -// -// Copyright 2019 Red Hat, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#ifndef CLOVER_CORE_COMPILER_HPP -#define CLOVER_CORE_COMPILER_HPP - -#include "core/device.hpp" -#include "core/module.hpp" -#include "llvm/invocation.hpp" -#include "nir/invocation.hpp" -#include "spirv/invocation.hpp" - -namespace clover { - namespace compiler { - static inline module - compile_program(const std::string &source, const header_map &headers, - const device &dev, const std::string &opts, - std::string &log) { - switch (dev.ir_format()) { -#ifdef HAVE_CLOVER_SPIRV - case PIPE_SHADER_IR_NIR_SERIALIZED: - return llvm::compile_to_spirv(source, headers, dev, opts, log); -#endif - case PIPE_SHADER_IR_NATIVE: - return llvm::compile_program(source, headers, dev, opts, log); - default: - unreachable("device with unsupported IR"); - throw error(CL_INVALID_VALUE); - } - } - - static inline module - link_program(const std::vector &ms, const device &dev, - const std::string &opts, std::string &log) { - switch (dev.ir_format()) { - case PIPE_SHADER_IR_NIR_SERIALIZED: - return nir::spirv_to_nir(spirv::link_program(ms, dev, opts, log), - dev, log); - case PIPE_SHADER_IR_NATIVE: - return llvm::link_program(ms, dev, opts, log); - default: - unreachable("device with unsupported IR"); - throw error(CL_INVALID_VALUE); - } - } - } -} - -#endif diff --git a/src/gallium/state_trackers/clover/core/context.cpp b/src/gallium/state_trackers/clover/core/context.cpp deleted file mode 100644 index c3e20829384..00000000000 --- a/src/gallium/state_trackers/clover/core/context.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// -// Copyright 2012 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#include "core/context.hpp" - -using namespace clover; - -context::context(const property_list &props, - const ref_vector &devs, - const notify_action ¬ify) : - notify(notify), props(props), devs(devs) { -} - -bool -context::operator==(const context &ctx) const { - return this == &ctx; -} - -bool -context::operator!=(const context &ctx) const { - return this != &ctx; -} - -const context::property_list & -context::properties() const { - return props; -} - -context::device_range -context::devices() const { - return map(evals(), devs); -} diff --git a/src/gallium/state_trackers/clover/core/context.hpp b/src/gallium/state_trackers/clover/core/context.hpp deleted file mode 100644 index 7b22ccae78f..00000000000 --- a/src/gallium/state_trackers/clover/core/context.hpp +++ /dev/null @@ -1,67 +0,0 @@ -// -// Copyright 2012 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#ifndef CLOVER_CORE_CONTEXT_HPP -#define CLOVER_CORE_CONTEXT_HPP - -#include "core/object.hpp" -#include "core/device.hpp" -#include "core/property.hpp" - -namespace clover { - class context : public ref_counter, public _cl_context { - private: - typedef adaptor_range< - evals, const std::vector> & - > device_range; - typedef clover::property_list property_list; - - public: - typedef std::function notify_action; - - context(const property_list &props, const ref_vector &devs, - const notify_action ¬ify); - - context(const context &ctx) = delete; - context & - operator=(const context &ctx) = delete; - - bool - operator==(const context &ctx) const; - bool - operator!=(const context &ctx) const; - - const property_list & - properties() const; - - device_range - devices() const; - - const notify_action notify; - - private: - property_list props; - const std::vector> devs; - }; -} - -#endif diff --git a/src/gallium/state_trackers/clover/core/device.cpp b/src/gallium/state_trackers/clover/core/device.cpp deleted file mode 100644 index 609885c21bc..00000000000 --- a/src/gallium/state_trackers/clover/core/device.cpp +++ /dev/null @@ -1,337 +0,0 @@ -// -// Copyright 2012 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#include -#include "core/device.hpp" -#include "core/platform.hpp" -#include "pipe/p_screen.h" -#include "pipe/p_state.h" -#include "util/bitscan.h" -#include "util/u_debug.h" - -using namespace clover; - -namespace { - template - std::vector - get_compute_param(pipe_screen *pipe, pipe_shader_ir ir_format, - pipe_compute_cap cap) { - int sz = pipe->get_compute_param(pipe, ir_format, cap, NULL); - std::vector v(sz / sizeof(T)); - - pipe->get_compute_param(pipe, ir_format, cap, &v.front()); - return v; - } -} - -device::device(clover::platform &platform, pipe_loader_device *ldev) : - platform(platform), ldev(ldev) { - pipe = pipe_loader_create_screen(ldev); - if (pipe && pipe->get_param(pipe, PIPE_CAP_COMPUTE)) { - if (supports_ir(PIPE_SHADER_IR_NATIVE)) - return; -#ifdef HAVE_CLOVER_SPIRV - if (supports_ir(PIPE_SHADER_IR_NIR_SERIALIZED)) - return; -#endif - } - if (pipe) - pipe->destroy(pipe); - throw error(CL_INVALID_DEVICE); -} - -device::~device() { - if (pipe) - pipe->destroy(pipe); - if (ldev) - pipe_loader_release(&ldev, 1); -} - -bool -device::operator==(const device &dev) const { - return this == &dev; -} - -cl_device_type -device::type() const { - switch (ldev->type) { - case PIPE_LOADER_DEVICE_SOFTWARE: - return CL_DEVICE_TYPE_CPU; - case PIPE_LOADER_DEVICE_PCI: - case PIPE_LOADER_DEVICE_PLATFORM: - return CL_DEVICE_TYPE_GPU; - default: - unreachable("Unknown device type."); - } -} - -cl_uint -device::vendor_id() const { - switch (ldev->type) { - case PIPE_LOADER_DEVICE_SOFTWARE: - case PIPE_LOADER_DEVICE_PLATFORM: - return 0; - case PIPE_LOADER_DEVICE_PCI: - return ldev->u.pci.vendor_id; - default: - unreachable("Unknown device type."); - } -} - -size_t -device::max_images_read() const { - return PIPE_MAX_SHADER_IMAGES; -} - -size_t -device::max_images_write() const { - return PIPE_MAX_SHADER_IMAGES; -} - -size_t -device::max_image_buffer_size() const { - return pipe->get_param(pipe, PIPE_CAP_MAX_TEXTURE_BUFFER_SIZE); -} - -cl_uint -device::max_image_levels_2d() const { - return util_last_bit(pipe->get_param(pipe, PIPE_CAP_MAX_TEXTURE_2D_SIZE)); -} - -cl_uint -device::max_image_levels_3d() const { - return pipe->get_param(pipe, PIPE_CAP_MAX_TEXTURE_3D_LEVELS); -} - -size_t -device::max_image_array_number() const { - return pipe->get_param(pipe, PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS); -} - -cl_uint -device::max_samplers() const { - return pipe->get_shader_param(pipe, PIPE_SHADER_COMPUTE, - PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS); -} - -cl_ulong -device::max_mem_global() const { - return get_compute_param(pipe, ir_format(), - PIPE_COMPUTE_CAP_MAX_GLOBAL_SIZE)[0]; -} - -cl_ulong -device::max_mem_local() const { - return get_compute_param(pipe, ir_format(), - PIPE_COMPUTE_CAP_MAX_LOCAL_SIZE)[0]; -} - -cl_ulong -device::max_mem_input() const { - return get_compute_param(pipe, ir_format(), - PIPE_COMPUTE_CAP_MAX_INPUT_SIZE)[0]; -} - -cl_ulong -device::max_const_buffer_size() const { - return pipe->get_shader_param(pipe, PIPE_SHADER_COMPUTE, - PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE); -} - -cl_uint -device::max_const_buffers() const { - return pipe->get_shader_param(pipe, PIPE_SHADER_COMPUTE, - PIPE_SHADER_CAP_MAX_CONST_BUFFERS); -} - -size_t -device::max_threads_per_block() const { - return get_compute_param( - pipe, ir_format(), PIPE_COMPUTE_CAP_MAX_THREADS_PER_BLOCK)[0]; -} - -cl_ulong -device::max_mem_alloc_size() const { - return get_compute_param(pipe, ir_format(), - PIPE_COMPUTE_CAP_MAX_MEM_ALLOC_SIZE)[0]; -} - -cl_uint -device::max_clock_frequency() const { - return get_compute_param(pipe, ir_format(), - PIPE_COMPUTE_CAP_MAX_CLOCK_FREQUENCY)[0]; -} - -cl_uint -device::max_compute_units() const { - return get_compute_param(pipe, ir_format(), - PIPE_COMPUTE_CAP_MAX_COMPUTE_UNITS)[0]; -} - -bool -device::image_support() const { - return get_compute_param(pipe, ir_format(), - PIPE_COMPUTE_CAP_IMAGES_SUPPORTED)[0]; -} - -bool -device::has_doubles() const { - return pipe->get_param(pipe, PIPE_CAP_DOUBLES); -} - -bool -device::has_halves() const { - return pipe->get_shader_param(pipe, PIPE_SHADER_COMPUTE, - PIPE_SHADER_CAP_FP16); -} - -bool -device::has_int64_atomics() const { - return pipe->get_shader_param(pipe, PIPE_SHADER_COMPUTE, - PIPE_SHADER_CAP_INT64_ATOMICS); -} - -bool -device::has_unified_memory() const { - return pipe->get_param(pipe, PIPE_CAP_UMA); -} - -cl_uint -device::mem_base_addr_align() const { - return sysconf(_SC_PAGESIZE); -} - -cl_device_svm_capabilities -device::svm_support() const { - // Without CAP_RESOURCE_FROM_USER_MEMORY SVM and CL_MEM_USE_HOST_PTR - // interactions won't work according to spec as clover manages a GPU side - // copy of the host data. - // - // The biggest problem are memory buffers created with CL_MEM_USE_HOST_PTR, - // but the application and/or the kernel updates the memory via SVM and not - // the cl_mem buffer. - // We can't even do proper tracking on what memory might have been accessed - // as the host ptr to the buffer could be within a SVM region, where through - // the CL API there is no reliable way of knowing if a certain cl_mem buffer - // was accessed by a kernel or not and the runtime can't reliably know from - // which side the GPU buffer content needs to be updated. - // - // Another unsolvable scenario is a cl_mem object passed by cl_mem reference - // and SVM pointer into the same kernel at the same time. - if (pipe->get_param(pipe, PIPE_CAP_RESOURCE_FROM_USER_MEMORY) && - pipe->get_param(pipe, PIPE_CAP_SYSTEM_SVM)) - // we can emulate all lower levels if we support fine grain system - return CL_DEVICE_SVM_FINE_GRAIN_SYSTEM | - CL_DEVICE_SVM_COARSE_GRAIN_BUFFER | - CL_DEVICE_SVM_FINE_GRAIN_BUFFER; - return 0; -} - -std::vector -device::max_block_size() const { - auto v = get_compute_param(pipe, ir_format(), - PIPE_COMPUTE_CAP_MAX_BLOCK_SIZE); - return { v.begin(), v.end() }; -} - -cl_uint -device::subgroup_size() const { - return get_compute_param(pipe, ir_format(), - PIPE_COMPUTE_CAP_SUBGROUP_SIZE)[0]; -} - -cl_uint -device::address_bits() const { - return get_compute_param(pipe, ir_format(), - PIPE_COMPUTE_CAP_ADDRESS_BITS)[0]; -} - -std::string -device::device_name() const { - return pipe->get_name(pipe); -} - -std::string -device::vendor_name() const { - return pipe->get_device_vendor(pipe); -} - -enum pipe_shader_ir -device::ir_format() const { - if (supports_ir(PIPE_SHADER_IR_NATIVE)) - return PIPE_SHADER_IR_NATIVE; - - assert(supports_ir(PIPE_SHADER_IR_NIR_SERIALIZED)); - return PIPE_SHADER_IR_NIR_SERIALIZED; -} - -std::string -device::ir_target() const { - std::vector target = get_compute_param( - pipe, ir_format(), PIPE_COMPUTE_CAP_IR_TARGET); - return { target.data() }; -} - -enum pipe_endian -device::endianness() const { - return (enum pipe_endian)pipe->get_param(pipe, PIPE_CAP_ENDIANNESS); -} - -std::string -device::device_version() const { - static const std::string device_version = - debug_get_option("CLOVER_DEVICE_VERSION_OVERRIDE", "1.1"); - return device_version; -} - -std::string -device::device_clc_version() const { - static const std::string device_clc_version = - debug_get_option("CLOVER_DEVICE_CLC_VERSION_OVERRIDE", "1.1"); - return device_clc_version; -} - -bool -device::supports_ir(enum pipe_shader_ir ir) const { - return pipe->get_shader_param(pipe, PIPE_SHADER_COMPUTE, - PIPE_SHADER_CAP_SUPPORTED_IRS) & (1 << ir); -} - -std::string -device::supported_extensions() const { - return - "cl_khr_byte_addressable_store" - " cl_khr_global_int32_base_atomics" - " cl_khr_global_int32_extended_atomics" - " cl_khr_local_int32_base_atomics" - " cl_khr_local_int32_extended_atomics" - + std::string(has_int64_atomics() ? " cl_khr_int64_base_atomics" : "") - + std::string(has_int64_atomics() ? " cl_khr_int64_extended_atomics" : "") - + std::string(has_doubles() ? " cl_khr_fp64" : "") - + std::string(has_halves() ? " cl_khr_fp16" : "") - + std::string(svm_support() ? " cl_arm_shared_virtual_memory" : ""); -} - -const void * -device::get_compiler_options(enum pipe_shader_ir ir) const { - return pipe->get_compiler_options(pipe, ir, PIPE_SHADER_COMPUTE); -} diff --git a/src/gallium/state_trackers/clover/core/device.hpp b/src/gallium/state_trackers/clover/core/device.hpp deleted file mode 100644 index 597f9489b2c..00000000000 --- a/src/gallium/state_trackers/clover/core/device.hpp +++ /dev/null @@ -1,109 +0,0 @@ -// -// Copyright 2012 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#ifndef CLOVER_CORE_DEVICE_HPP -#define CLOVER_CORE_DEVICE_HPP - -#include -#include - -#include "core/object.hpp" -#include "core/format.hpp" -#include "pipe-loader/pipe_loader.h" - -namespace clover { - class platform; - class root_resource; - class hard_event; - - class device : public ref_counter, public _cl_device_id { - public: - device(clover::platform &platform, pipe_loader_device *ldev); - ~device(); - - device(const device &dev) = delete; - device & - operator=(const device &dev) = delete; - - bool - operator==(const device &dev) const; - - cl_device_type type() const; - cl_uint vendor_id() const; - size_t max_images_read() const; - size_t max_images_write() const; - size_t max_image_buffer_size() const; - cl_uint max_image_levels_2d() const; - cl_uint max_image_levels_3d() const; - size_t max_image_array_number() const; - cl_uint max_samplers() const; - cl_ulong max_mem_global() const; - cl_ulong max_mem_local() const; - cl_ulong max_mem_input() const; - cl_ulong max_const_buffer_size() const; - cl_uint max_const_buffers() const; - size_t max_threads_per_block() const; - cl_ulong max_mem_alloc_size() const; - cl_uint max_clock_frequency() const; - cl_uint max_compute_units() const; - bool image_support() const; - bool has_doubles() const; - bool has_halves() const; - bool has_int64_atomics() const; - bool has_unified_memory() const; - cl_uint mem_base_addr_align() const; - cl_device_svm_capabilities svm_support() const; - - std::vector max_block_size() const; - cl_uint subgroup_size() const; - cl_uint address_bits() const; - std::string device_name() const; - std::string vendor_name() const; - std::string device_version() const; - std::string device_clc_version() const; - enum pipe_shader_ir ir_format() const; - std::string ir_target() const; - enum pipe_endian endianness() const; - bool supports_ir(enum pipe_shader_ir ir) const; - std::string supported_extensions() const; - - friend class command_queue; - friend class root_resource; - friend class hard_event; - friend std::set - supported_formats(const context &, cl_mem_object_type); - const void *get_compiler_options(enum pipe_shader_ir ir) const; - - clover::platform &platform; - - inline bool - has_system_svm() const { - return svm_support() & CL_DEVICE_SVM_FINE_GRAIN_SYSTEM; - } - - private: - pipe_screen *pipe; - pipe_loader_device *ldev; - }; -} - -#endif diff --git a/src/gallium/state_trackers/clover/core/error.hpp b/src/gallium/state_trackers/clover/core/error.hpp deleted file mode 100644 index 0490c19a276..00000000000 --- a/src/gallium/state_trackers/clover/core/error.hpp +++ /dev/null @@ -1,202 +0,0 @@ -// -// Copyright 2013 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#ifndef CLOVER_CORE_ERROR_HPP -#define CLOVER_CORE_ERROR_HPP - -#include "CL/cl.h" - -#include -#include - -namespace clover { - class command_queue; - class context; - class device; - class event; - class hard_event; - class soft_event; - class kernel; - class memory_obj; - class buffer; - class root_buffer; - class sub_buffer; - class image; - class image2d; - class image3d; - class platform; - class program; - class sampler; - - /// - /// Class that represents an error that can be converted to an - /// OpenCL status code. - /// - class error : public std::runtime_error { - public: - error(cl_int code, std::string what = "") : - std::runtime_error(what), code(code) { - } - - cl_int get() const { - return code; - } - - protected: - cl_int code; - }; - - class invalid_build_options_error : public error { - public: - invalid_build_options_error(const std::string &what = "") : - error(CL_INVALID_BUILD_OPTIONS, what) {} - }; - - class build_error : public error { - public: - build_error(const std::string &what = "") : - error(CL_BUILD_PROGRAM_FAILURE, what) {} - }; - - template - class invalid_object_error; - - template<> - class invalid_object_error : public error { - public: - invalid_object_error(std::string what = "") : - error(CL_INVALID_COMMAND_QUEUE, what) {} - }; - - template<> - class invalid_object_error : public error { - public: - invalid_object_error(std::string what = "") : - error(CL_INVALID_CONTEXT, what) {} - }; - - template<> - class invalid_object_error : public error { - public: - invalid_object_error(std::string what = "") : - error(CL_INVALID_DEVICE, what) {} - }; - - template<> - class invalid_object_error : public error { - public: - invalid_object_error(std::string what = "") : - error(CL_INVALID_EVENT, what) {} - }; - - template<> - class invalid_object_error : public error { - public: - invalid_object_error(std::string what = "") : - error(CL_INVALID_EVENT, what) {} - }; - - template<> - class invalid_object_error : public error { - public: - invalid_object_error(std::string what = "") : - error(CL_INVALID_KERNEL, what) {} - }; - - template<> - class invalid_object_error : public error { - public: - invalid_object_error(std::string what = "") : - error(CL_INVALID_MEM_OBJECT, what) {} - }; - - template<> - class invalid_object_error : public error { - public: - invalid_object_error(std::string what = "") : - error(CL_INVALID_MEM_OBJECT, what) {} - }; - - template<> - class invalid_object_error : public error { - public: - invalid_object_error(std::string what = "") : - error(CL_INVALID_MEM_OBJECT, what) {} - }; - - template<> - class invalid_object_error : public error { - public: - invalid_object_error(std::string what = "") : - error(CL_INVALID_MEM_OBJECT, what) {} - }; - - template<> - class invalid_object_error : public error { - public: - invalid_object_error(std::string what = "") : - error(CL_INVALID_MEM_OBJECT, what) {} - }; - - template<> - class invalid_object_error : public error { - public: - invalid_object_error(std::string what = "") : - error(CL_INVALID_MEM_OBJECT, what) {} - }; - - template<> - class invalid_object_error : public error { - public: - invalid_object_error(std::string what = "") : - error(CL_INVALID_MEM_OBJECT, what) {} - }; - - template<> - class invalid_object_error : public error { - public: - invalid_object_error(std::string what = "") : - error(CL_INVALID_PLATFORM, what) {} - }; - - template<> - class invalid_object_error : public error { - public: - invalid_object_error(std::string what = "") : - error(CL_INVALID_PROGRAM, what) {} - }; - - template<> - class invalid_object_error : public error { - public: - invalid_object_error(std::string what = "") : - error(CL_INVALID_SAMPLER, what) {} - }; - - class invalid_wait_list_error : public error { - public: - invalid_wait_list_error(std::string what = "") : - error(CL_INVALID_EVENT_WAIT_LIST, what) {} - }; -} - -#endif diff --git a/src/gallium/state_trackers/clover/core/event.cpp b/src/gallium/state_trackers/clover/core/event.cpp deleted file mode 100644 index 3d313ce8969..00000000000 --- a/src/gallium/state_trackers/clover/core/event.cpp +++ /dev/null @@ -1,267 +0,0 @@ -// -// Copyright 2012 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#include "core/event.hpp" -#include "pipe/p_screen.h" - -using namespace clover; - -event::event(clover::context &ctx, const ref_vector &deps, - action action_ok, action action_fail) : - context(ctx), _wait_count(1), _status(0), - action_ok(action_ok), action_fail(action_fail) { - for (auto &ev : deps) - ev.chain(*this); -} - -event::~event() { -} - -std::vector> -event::trigger_self() { - std::lock_guard lock(mutex); - std::vector> evs; - - if (_wait_count && !--_wait_count) - std::swap(_chain, evs); - - cv.notify_all(); - return evs; -} - -void -event::trigger() try { - if (wait_count() == 1) - action_ok(*this); - - for (event &ev : trigger_self()) - ev.trigger(); -} catch (error &e) { - abort(e.get()); -} - -std::vector> -event::abort_self(cl_int status) { - std::lock_guard lock(mutex); - std::vector> evs; - - _status = status; - _wait_count = 0; - std::swap(_chain, evs); - - cv.notify_all(); - return evs; -} - -void -event::abort(cl_int status) { - action_fail(*this); - - for (event &ev : abort_self(status)) - ev.abort(status); -} - -unsigned -event::wait_count() const { - std::lock_guard lock(mutex); - return _wait_count; -} - -bool -event::signalled() const { - return !wait_count(); -} - -cl_int -event::status() const { - std::lock_guard lock(mutex); - return _status; -} - -void -event::chain(event &ev) { - std::unique_lock lock(mutex, std::defer_lock); - std::unique_lock lock_ev(ev.mutex, std::defer_lock); - std::lock(lock, lock_ev); - - if (_wait_count) { - ev._wait_count++; - _chain.push_back(ev); - } - ev.deps.push_back(*this); -} - -void -event::wait_signalled() const { - std::unique_lock lock(mutex); - cv.wait(lock, [=]{ return !_wait_count; }); -} - -void -event::wait() const { - for (event &ev : deps) - ev.wait(); - - wait_signalled(); -} - -hard_event::hard_event(command_queue &q, cl_command_type command, - const ref_vector &deps, action action) : - event(q.context(), deps, profile(q, action), [](event &ev){}), - _queue(q), _command(command), _fence(NULL) { - if (q.profiling_enabled()) - _time_queued = timestamp::current(q); - - q.sequence(*this); - trigger(); -} - -hard_event::~hard_event() { - pipe_screen *screen = queue()->device().pipe; - screen->fence_reference(screen, &_fence, NULL); -} - -cl_int -hard_event::status() const { - pipe_screen *screen = queue()->device().pipe; - - if (event::status() < 0) - return event::status(); - - else if (!_fence) - return CL_QUEUED; - - else if (!screen->fence_finish(screen, NULL, _fence, 0)) - return CL_SUBMITTED; - - else - return CL_COMPLETE; -} - -command_queue * -hard_event::queue() const { - return &_queue(); -} - -cl_command_type -hard_event::command() const { - return _command; -} - -void -hard_event::wait() const { - pipe_screen *screen = queue()->device().pipe; - - event::wait(); - - if (status() == CL_QUEUED) - queue()->flush(); - - if (!_fence || - !screen->fence_finish(screen, NULL, _fence, PIPE_TIMEOUT_INFINITE)) - throw error(CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST); -} - -const lazy & -hard_event::time_queued() const { - return _time_queued; -} - -const lazy & -hard_event::time_submit() const { - return _time_submit; -} - -const lazy & -hard_event::time_start() const { - return _time_start; -} - -const lazy & -hard_event::time_end() const { - return _time_end; -} - -void -hard_event::fence(pipe_fence_handle *fence) { - pipe_screen *screen = queue()->device().pipe; - screen->fence_reference(screen, &_fence, fence); -} - -event::action -hard_event::profile(command_queue &q, const action &action) const { - if (q.profiling_enabled()) { - return [&q, action] (event &ev) { - auto &hev = static_cast(ev); - - hev._time_submit = timestamp::current(q); - hev._time_start = timestamp::query(q); - - action(ev); - - hev._time_end = timestamp::query(q); - }; - - } else { - return action; - } -} - -soft_event::soft_event(clover::context &ctx, const ref_vector &deps, - bool _trigger, action action) : - event(ctx, deps, action, action) { - if (_trigger) - trigger(); -} - -cl_int -soft_event::status() const { - if (event::status() < 0) - return event::status(); - - else if (!signalled() || - any_of([](const event &ev) { - return ev.status() != CL_COMPLETE; - }, deps)) - return CL_SUBMITTED; - - else - return CL_COMPLETE; -} - -command_queue * -soft_event::queue() const { - return NULL; -} - -cl_command_type -soft_event::command() const { - return CL_COMMAND_USER; -} - -void -soft_event::wait() const { - event::wait(); - - if (status() != CL_COMPLETE) - throw error(CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST); -} diff --git a/src/gallium/state_trackers/clover/core/event.hpp b/src/gallium/state_trackers/clover/core/event.hpp deleted file mode 100644 index 03c97bcf4da..00000000000 --- a/src/gallium/state_trackers/clover/core/event.hpp +++ /dev/null @@ -1,164 +0,0 @@ -// -// Copyright 2012 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#ifndef CLOVER_CORE_EVENT_HPP -#define CLOVER_CORE_EVENT_HPP - -#include -#include - -#include "core/object.hpp" -#include "core/queue.hpp" -#include "core/timestamp.hpp" -#include "util/lazy.hpp" - -namespace clover { - /// - /// Class that represents a task that might be executed - /// asynchronously at some point in the future. - /// - /// An event consists of a list of dependencies, a boolean - /// signalled() flag, and an associated task. An event is - /// considered signalled as soon as all its dependencies (if any) - /// are signalled as well, and the trigger() method is called; at - /// that point the associated task will be started through the - /// specified \a action_ok. If the abort() method is called - /// instead, the specified \a action_fail is executed and the - /// associated task will never be started. Dependent events will - /// be aborted recursively. - /// - /// The execution status of the associated task can be queried - /// using the status() method, and it can be waited for completion - /// using the wait() method. - /// - class event : public ref_counter, public _cl_event { - public: - typedef std::function action; - - event(clover::context &ctx, const ref_vector &deps, - action action_ok, action action_fail); - virtual ~event(); - - event(const event &ev) = delete; - event & - operator=(const event &ev) = delete; - - void trigger(); - void abort(cl_int status); - bool signalled() const; - - virtual cl_int status() const; - virtual command_queue *queue() const = 0; - virtual cl_command_type command() const = 0; - void wait_signalled() const; - virtual void wait() const; - - virtual struct pipe_fence_handle *fence() const { - return NULL; - } - - const intrusive_ref context; - - protected: - void chain(event &ev); - - std::vector> deps; - - private: - std::vector> trigger_self(); - std::vector> abort_self(cl_int status); - unsigned wait_count() const; - - unsigned _wait_count; - cl_int _status; - action action_ok; - action action_fail; - std::vector> _chain; - mutable std::condition_variable cv; - mutable std::mutex mutex; - }; - - /// - /// Class that represents a task executed by a command queue. - /// - /// Similar to a normal clover::event. In addition it's associated - /// with a given command queue \a q and a given OpenCL \a command. - /// hard_event instances created for the same queue are implicitly - /// ordered with respect to each other, and they are implicitly - /// triggered on construction. - /// - /// A hard_event is considered complete when the associated - /// hardware task finishes execution. - /// - class hard_event : public event { - public: - hard_event(command_queue &q, cl_command_type command, - const ref_vector &deps, - action action = [](event &){}); - ~hard_event(); - - virtual cl_int status() const; - virtual command_queue *queue() const; - virtual cl_command_type command() const; - virtual void wait() const; - - const lazy &time_queued() const; - const lazy &time_submit() const; - const lazy &time_start() const; - const lazy &time_end() const; - - friend class command_queue; - - virtual struct pipe_fence_handle *fence() const { - return _fence; - } - - private: - virtual void fence(pipe_fence_handle *fence); - action profile(command_queue &q, const action &action) const; - - const intrusive_ref _queue; - cl_command_type _command; - pipe_fence_handle *_fence; - lazy _time_queued, _time_submit, _time_start, _time_end; - }; - - /// - /// Class that represents a software event. - /// - /// A soft_event is not associated with any specific hardware task - /// or command queue. It's considered complete as soon as all its - /// dependencies finish execution. - /// - class soft_event : public event { - public: - soft_event(clover::context &ctx, const ref_vector &deps, - bool trigger, action action = [](event &){}); - - virtual cl_int status() const; - virtual command_queue *queue() const; - virtual cl_command_type command() const; - virtual void wait() const; - }; -} - -#endif diff --git a/src/gallium/state_trackers/clover/core/format.cpp b/src/gallium/state_trackers/clover/core/format.cpp deleted file mode 100644 index dee1872c829..00000000000 --- a/src/gallium/state_trackers/clover/core/format.cpp +++ /dev/null @@ -1,162 +0,0 @@ -// -// Copyright 2012 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#include "core/format.hpp" -#include "core/memory.hpp" -#include "pipe/p_screen.h" -#include "pipe/p_context.h" - -namespace clover { - static const std::map formats { - { { CL_BGRA, CL_UNORM_INT8 }, PIPE_FORMAT_B8G8R8A8_UNORM }, - { { CL_ARGB, CL_UNORM_INT8 }, PIPE_FORMAT_A8R8G8B8_UNORM }, - { { CL_RGB, CL_UNORM_SHORT_565 }, PIPE_FORMAT_B5G6R5_UNORM }, - { { CL_LUMINANCE, CL_UNORM_INT8 }, PIPE_FORMAT_L8_UNORM }, - { { CL_A, CL_UNORM_INT8 }, PIPE_FORMAT_A8_UNORM }, - { { CL_INTENSITY, CL_UNORM_INT8 }, PIPE_FORMAT_I8_UNORM }, - { { CL_LUMINANCE, CL_UNORM_INT16 }, PIPE_FORMAT_L16_UNORM }, - { { CL_R, CL_FLOAT }, PIPE_FORMAT_R32_FLOAT }, - { { CL_RG, CL_FLOAT }, PIPE_FORMAT_R32G32_FLOAT }, - { { CL_RGB, CL_FLOAT }, PIPE_FORMAT_R32G32B32_FLOAT }, - { { CL_RGBA, CL_FLOAT }, PIPE_FORMAT_R32G32B32A32_FLOAT }, - { { CL_R, CL_UNORM_INT16 }, PIPE_FORMAT_R16_UNORM }, - { { CL_RG, CL_UNORM_INT16 }, PIPE_FORMAT_R16G16_UNORM }, - { { CL_RGB, CL_UNORM_INT16 }, PIPE_FORMAT_R16G16B16_UNORM }, - { { CL_RGBA, CL_UNORM_INT16 }, PIPE_FORMAT_R16G16B16A16_UNORM }, - { { CL_R, CL_SNORM_INT16 }, PIPE_FORMAT_R16_SNORM }, - { { CL_RG, CL_SNORM_INT16 }, PIPE_FORMAT_R16G16_SNORM }, - { { CL_RGB, CL_SNORM_INT16 }, PIPE_FORMAT_R16G16B16_SNORM }, - { { CL_RGBA, CL_SNORM_INT16 }, PIPE_FORMAT_R16G16B16A16_SNORM }, - { { CL_R, CL_UNORM_INT8 }, PIPE_FORMAT_R8_UNORM }, - { { CL_RG, CL_UNORM_INT8 }, PIPE_FORMAT_R8G8_UNORM }, - { { CL_RGB, CL_UNORM_INT8 }, PIPE_FORMAT_R8G8B8_UNORM }, - { { CL_RGBA, CL_UNORM_INT8 }, PIPE_FORMAT_R8G8B8A8_UNORM }, - { { CL_R, CL_SNORM_INT8 }, PIPE_FORMAT_R8_SNORM }, - { { CL_RG, CL_SNORM_INT8 }, PIPE_FORMAT_R8G8_SNORM }, - { { CL_RGB, CL_SNORM_INT8 }, PIPE_FORMAT_R8G8B8_SNORM }, - { { CL_RGBA, CL_SNORM_INT8 }, PIPE_FORMAT_R8G8B8A8_SNORM }, - { { CL_R, CL_HALF_FLOAT }, PIPE_FORMAT_R16_FLOAT }, - { { CL_RG, CL_HALF_FLOAT }, PIPE_FORMAT_R16G16_FLOAT }, - { { CL_RGB, CL_HALF_FLOAT }, PIPE_FORMAT_R16G16B16_FLOAT }, - { { CL_RGBA, CL_HALF_FLOAT }, PIPE_FORMAT_R16G16B16A16_FLOAT }, - { { CL_RGBx, CL_UNORM_SHORT_555 }, PIPE_FORMAT_B5G5R5X1_UNORM }, - { { CL_RGBx, CL_UNORM_INT8 }, PIPE_FORMAT_R8G8B8X8_UNORM }, - { { CL_A, CL_UNORM_INT16 }, PIPE_FORMAT_A16_UNORM }, - { { CL_INTENSITY, CL_UNORM_INT16 }, PIPE_FORMAT_I16_UNORM }, - { { CL_LUMINANCE, CL_SNORM_INT8 }, PIPE_FORMAT_L8_SNORM }, - { { CL_INTENSITY, CL_SNORM_INT8 }, PIPE_FORMAT_I8_SNORM }, - { { CL_A, CL_SNORM_INT16 }, PIPE_FORMAT_A16_SNORM }, - { { CL_LUMINANCE, CL_SNORM_INT16 }, PIPE_FORMAT_L16_SNORM }, - { { CL_INTENSITY, CL_SNORM_INT16 }, PIPE_FORMAT_I16_SNORM }, - { { CL_A, CL_HALF_FLOAT }, PIPE_FORMAT_A16_FLOAT }, - { { CL_LUMINANCE, CL_HALF_FLOAT }, PIPE_FORMAT_L16_FLOAT }, - { { CL_INTENSITY, CL_HALF_FLOAT }, PIPE_FORMAT_I16_FLOAT }, - { { CL_A, CL_FLOAT }, PIPE_FORMAT_A32_FLOAT }, - { { CL_LUMINANCE, CL_FLOAT }, PIPE_FORMAT_L32_FLOAT }, - { { CL_INTENSITY, CL_FLOAT }, PIPE_FORMAT_I32_FLOAT }, - { { CL_RA, CL_UNORM_INT8 }, PIPE_FORMAT_R8A8_UNORM }, - { { CL_R, CL_UNSIGNED_INT8 }, PIPE_FORMAT_R8_UINT }, - { { CL_RG, CL_UNSIGNED_INT8 }, PIPE_FORMAT_R8G8_UINT }, - { { CL_RGB, CL_UNSIGNED_INT8 }, PIPE_FORMAT_R8G8B8_UINT }, - { { CL_RGBA, CL_UNSIGNED_INT8 }, PIPE_FORMAT_R8G8B8A8_UINT }, - { { CL_R, CL_SIGNED_INT8 }, PIPE_FORMAT_R8_SINT }, - { { CL_RG, CL_SIGNED_INT8 }, PIPE_FORMAT_R8G8_SINT }, - { { CL_RGB, CL_SIGNED_INT8 }, PIPE_FORMAT_R8G8B8_SINT }, - { { CL_RGBA, CL_SIGNED_INT8 }, PIPE_FORMAT_R8G8B8A8_SINT }, - { { CL_R, CL_UNSIGNED_INT16 }, PIPE_FORMAT_R16_UINT }, - { { CL_RG, CL_UNSIGNED_INT16 }, PIPE_FORMAT_R16G16_UINT }, - { { CL_RGB, CL_UNSIGNED_INT16 }, PIPE_FORMAT_R16G16B16_UINT }, - { { CL_RGBA, CL_UNSIGNED_INT16 }, PIPE_FORMAT_R16G16B16A16_UINT }, - { { CL_R, CL_SIGNED_INT16 }, PIPE_FORMAT_R16_SINT }, - { { CL_RG, CL_SIGNED_INT16 }, PIPE_FORMAT_R16G16_SINT }, - { { CL_RGB, CL_SIGNED_INT16 }, PIPE_FORMAT_R16G16B16_SINT }, - { { CL_RGBA, CL_SIGNED_INT16 }, PIPE_FORMAT_R16G16B16A16_SINT }, - { { CL_R, CL_UNSIGNED_INT32 }, PIPE_FORMAT_R32_UINT }, - { { CL_RG, CL_UNSIGNED_INT32 }, PIPE_FORMAT_R32G32_UINT }, - { { CL_RGB, CL_UNSIGNED_INT32 }, PIPE_FORMAT_R32G32B32_UINT }, - { { CL_RGBA, CL_UNSIGNED_INT32 }, PIPE_FORMAT_R32G32B32A32_UINT }, - { { CL_R, CL_SIGNED_INT32 }, PIPE_FORMAT_R32_SINT }, - { { CL_RG, CL_SIGNED_INT32 }, PIPE_FORMAT_R32G32_SINT }, - { { CL_RGB, CL_SIGNED_INT32 }, PIPE_FORMAT_R32G32B32_SINT }, - { { CL_RGBA, CL_SIGNED_INT32 }, PIPE_FORMAT_R32G32B32A32_SINT }, - { { CL_A, CL_UNSIGNED_INT8 }, PIPE_FORMAT_A8_UINT }, - { { CL_INTENSITY, CL_UNSIGNED_INT8 }, PIPE_FORMAT_I8_UINT }, - { { CL_LUMINANCE, CL_UNSIGNED_INT8 }, PIPE_FORMAT_L8_UINT }, - { { CL_A, CL_SIGNED_INT8 }, PIPE_FORMAT_A8_SINT }, - { { CL_INTENSITY, CL_SIGNED_INT8 }, PIPE_FORMAT_I8_SINT }, - { { CL_LUMINANCE, CL_SIGNED_INT8 }, PIPE_FORMAT_L8_SINT }, - { { CL_A, CL_UNSIGNED_INT16 }, PIPE_FORMAT_A16_UINT }, - { { CL_INTENSITY, CL_UNSIGNED_INT16 }, PIPE_FORMAT_I16_UINT }, - { { CL_LUMINANCE, CL_UNSIGNED_INT16 }, PIPE_FORMAT_L16_UINT }, - { { CL_A, CL_SIGNED_INT16 }, PIPE_FORMAT_A16_SINT }, - { { CL_INTENSITY, CL_SIGNED_INT16 }, PIPE_FORMAT_I16_SINT }, - { { CL_LUMINANCE, CL_SIGNED_INT16 }, PIPE_FORMAT_L16_SINT }, - { { CL_A, CL_UNSIGNED_INT32 }, PIPE_FORMAT_A32_UINT }, - { { CL_INTENSITY, CL_UNSIGNED_INT32 }, PIPE_FORMAT_I32_UINT }, - { { CL_LUMINANCE, CL_UNSIGNED_INT32 }, PIPE_FORMAT_L32_UINT }, - { { CL_A, CL_SIGNED_INT32 }, PIPE_FORMAT_A32_SINT }, - { { CL_INTENSITY, CL_SIGNED_INT32 }, PIPE_FORMAT_I32_SINT }, - { { CL_LUMINANCE, CL_SIGNED_INT32 }, PIPE_FORMAT_L32_SINT } - }; - - pipe_texture_target - translate_target(cl_mem_object_type type) { - switch (type) { - case CL_MEM_OBJECT_BUFFER: - return PIPE_BUFFER; - case CL_MEM_OBJECT_IMAGE2D: - return PIPE_TEXTURE_2D; - case CL_MEM_OBJECT_IMAGE3D: - return PIPE_TEXTURE_3D; - default: - throw error(CL_INVALID_VALUE); - } - } - - pipe_format - translate_format(const cl_image_format &format) { - auto it = formats.find(format); - - if (it == formats.end()) - throw error(CL_IMAGE_FORMAT_NOT_SUPPORTED); - - return it->second; - } - - std::set - supported_formats(const context &ctx, cl_mem_object_type type) { - std::set s; - pipe_texture_target target = translate_target(type); - unsigned bindings = (PIPE_BIND_SAMPLER_VIEW | - PIPE_BIND_COMPUTE_RESOURCE); - - for (auto f : formats) { - if (all_of([=](const device &dev) { - return dev.pipe->is_format_supported( - dev.pipe, f.second, target, 1, 1, bindings); - }, ctx.devices())) - s.insert(f.first); - } - - return s; - } -} diff --git a/src/gallium/state_trackers/clover/core/format.hpp b/src/gallium/state_trackers/clover/core/format.hpp deleted file mode 100644 index a8b7053c5dc..00000000000 --- a/src/gallium/state_trackers/clover/core/format.hpp +++ /dev/null @@ -1,62 +0,0 @@ -// -// Copyright 2012 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#ifndef CLOVER_CORE_FORMAT_HPP -#define CLOVER_CORE_FORMAT_HPP - -#include - -#include "core/object.hpp" -#include "pipe/p_defines.h" -#include "pipe/p_format.h" - -namespace clover { - pipe_texture_target translate_target(cl_mem_object_type type); - pipe_format translate_format(const cl_image_format &format); - - /// - /// Return all the image formats supported by a given context for - /// the given memory object type. - /// - std::set supported_formats(const context &ctx, - cl_mem_object_type type); -} - -static inline bool -operator<(const cl_image_format &a, const cl_image_format &b) { - return (a.image_channel_order != b.image_channel_order ? - a.image_channel_order < b.image_channel_order : - a.image_channel_data_type < b.image_channel_data_type); -} - -static inline bool -operator==(const cl_image_format &a, const cl_image_format &b) { - return (a.image_channel_order == b.image_channel_order && - a.image_channel_data_type == b.image_channel_data_type); -} - -static inline bool -operator!=(const cl_image_format &a, const cl_image_format &b) { - return !(a == b); -} - -#endif diff --git a/src/gallium/state_trackers/clover/core/kernel.cpp b/src/gallium/state_trackers/clover/core/kernel.cpp deleted file mode 100644 index 7d839767aa0..00000000000 --- a/src/gallium/state_trackers/clover/core/kernel.cpp +++ /dev/null @@ -1,610 +0,0 @@ -// -// Copyright 2012 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#include "core/kernel.hpp" -#include "core/resource.hpp" -#include "util/factor.hpp" -#include "util/u_math.h" -#include "pipe/p_context.h" - -using namespace clover; - -kernel::kernel(clover::program &prog, const std::string &name, - const std::vector &margs) : - program(prog), _name(name), exec(*this), - program_ref(prog._kernel_ref_counter) { - for (auto &marg : margs) { - if (marg.semantic == module::argument::general) - _args.emplace_back(argument::create(marg)); - } -} - -template -static inline std::vector -pad_vector(command_queue &q, const V &v, uint x) { - std::vector w { v.begin(), v.end() }; - w.resize(q.device().max_block_size().size(), x); - return w; -} - -void -kernel::launch(command_queue &q, - const std::vector &grid_offset, - const std::vector &grid_size, - const std::vector &block_size) { - const auto m = program().build(q.device()).binary; - const auto reduced_grid_size = - map(divides(), grid_size, block_size); - void *st = exec.bind(&q, grid_offset); - struct pipe_grid_info info = {}; - - // The handles are created during exec_context::bind(), so we need make - // sure to call exec_context::bind() before retrieving them. - std::vector g_handles = map([&](size_t h) { - return (uint32_t *)&exec.input[h]; - }, exec.g_handles); - - q.pipe->bind_compute_state(q.pipe, st); - q.pipe->bind_sampler_states(q.pipe, PIPE_SHADER_COMPUTE, - 0, exec.samplers.size(), - exec.samplers.data()); - - q.pipe->set_sampler_views(q.pipe, PIPE_SHADER_COMPUTE, 0, - exec.sviews.size(), exec.sviews.data()); - q.pipe->set_compute_resources(q.pipe, 0, exec.resources.size(), - exec.resources.data()); - q.pipe->set_global_binding(q.pipe, 0, exec.g_buffers.size(), - exec.g_buffers.data(), g_handles.data()); - - // Fill information for the launch_grid() call. - info.work_dim = grid_size.size(); - copy(pad_vector(q, block_size, 1), info.block); - copy(pad_vector(q, reduced_grid_size, 1), info.grid); - info.pc = find(name_equals(_name), m.syms).offset; - info.input = exec.input.data(); - - q.pipe->launch_grid(q.pipe, &info); - - q.pipe->set_global_binding(q.pipe, 0, exec.g_buffers.size(), NULL, NULL); - q.pipe->set_compute_resources(q.pipe, 0, exec.resources.size(), NULL); - q.pipe->set_sampler_views(q.pipe, PIPE_SHADER_COMPUTE, 0, - exec.sviews.size(), NULL); - q.pipe->bind_sampler_states(q.pipe, PIPE_SHADER_COMPUTE, 0, - exec.samplers.size(), NULL); - - q.pipe->memory_barrier(q.pipe, PIPE_BARRIER_GLOBAL_BUFFER); - exec.unbind(); -} - -size_t -kernel::mem_local() const { - size_t sz = 0; - - for (auto &arg : args()) { - if (dynamic_cast(&arg)) - sz += arg.storage(); - } - - return sz; -} - -size_t -kernel::mem_private() const { - return 0; -} - -const std::string & -kernel::name() const { - return _name; -} - -std::vector -kernel::optimal_block_size(const command_queue &q, - const std::vector &grid_size) const { - return factor::find_grid_optimal_factor( - q.device().max_threads_per_block(), q.device().max_block_size(), - grid_size); -} - -std::vector -kernel::required_block_size() const { - return { 0, 0, 0 }; -} - -kernel::argument_range -kernel::args() { - return map(derefs(), _args); -} - -kernel::const_argument_range -kernel::args() const { - return map(derefs(), _args); -} - -const module & -kernel::module(const command_queue &q) const { - return program().build(q.device()).binary; -} - -kernel::exec_context::exec_context(kernel &kern) : - kern(kern), q(NULL), mem_local(0), st(NULL), cs() { -} - -kernel::exec_context::~exec_context() { - if (st) - q->pipe->delete_compute_state(q->pipe, st); -} - -void * -kernel::exec_context::bind(intrusive_ptr _q, - const std::vector &grid_offset) { - std::swap(q, _q); - - // Bind kernel arguments. - auto &m = kern.program().build(q->device()).binary; - auto msym = find(name_equals(kern.name()), m.syms); - auto margs = msym.args; - auto msec = find(id_equals(msym.section), m.secs); - auto explicit_arg = kern._args.begin(); - - for (auto &marg : margs) { - switch (marg.semantic) { - case module::argument::general: - (*(explicit_arg++))->bind(*this, marg); - break; - - case module::argument::grid_dimension: { - const cl_uint dimension = grid_offset.size(); - auto arg = argument::create(marg); - - arg->set(sizeof(dimension), &dimension); - arg->bind(*this, marg); - break; - } - case module::argument::grid_offset: { - for (cl_uint x : pad_vector(*q, grid_offset, 0)) { - auto arg = argument::create(marg); - - arg->set(sizeof(x), &x); - arg->bind(*this, marg); - } - break; - } - case module::argument::image_size: { - auto img = dynamic_cast(**(explicit_arg - 1)).get(); - std::vector image_size{ - static_cast(img->width()), - static_cast(img->height()), - static_cast(img->depth())}; - for (auto x : image_size) { - auto arg = argument::create(marg); - - arg->set(sizeof(x), &x); - arg->bind(*this, marg); - } - break; - } - case module::argument::image_format: { - auto img = dynamic_cast(**(explicit_arg - 1)).get(); - cl_image_format fmt = img->format(); - std::vector image_format{ - static_cast(fmt.image_channel_data_type), - static_cast(fmt.image_channel_order)}; - for (auto x : image_format) { - auto arg = argument::create(marg); - - arg->set(sizeof(x), &x); - arg->bind(*this, marg); - } - break; - } - } - } - - // Create a new compute state if anything changed. - if (!st || q != _q || - cs.req_local_mem != mem_local || - cs.req_input_mem != input.size()) { - if (st) - _q->pipe->delete_compute_state(_q->pipe, st); - - cs.ir_type = q->device().ir_format(); - cs.prog = &(msec.data[0]); - cs.req_local_mem = mem_local; - cs.req_input_mem = input.size(); - st = q->pipe->create_compute_state(q->pipe, &cs); - if (!st) { - unbind(); // Cleanup - throw error(CL_OUT_OF_RESOURCES); - } - } - - return st; -} - -void -kernel::exec_context::unbind() { - for (auto &arg : kern.args()) - arg.unbind(*this); - - input.clear(); - samplers.clear(); - sviews.clear(); - resources.clear(); - g_buffers.clear(); - g_handles.clear(); - mem_local = 0; -} - -namespace { - template - std::vector - bytes(const T& x) { - return { (uint8_t *)&x, (uint8_t *)&x + sizeof(x) }; - } - - /// - /// Transform buffer \a v from the native byte order into the byte - /// order specified by \a e. - /// - template - void - byteswap(T &v, pipe_endian e) { - if (PIPE_ENDIAN_NATIVE != e) - std::reverse(v.begin(), v.end()); - } - - /// - /// Pad buffer \a v to the next multiple of \a n. - /// - template - void - align(T &v, size_t n) { - v.resize(util_align_npot(v.size(), n)); - } - - bool - msb(const std::vector &s) { - if (PIPE_ENDIAN_NATIVE == PIPE_ENDIAN_LITTLE) - return s.back() & 0x80; - else - return s.front() & 0x80; - } - - /// - /// Resize buffer \a v to size \a n using sign or zero extension - /// according to \a ext. - /// - template - void - extend(T &v, enum module::argument::ext_type ext, size_t n) { - const size_t m = std::min(v.size(), n); - const bool sign_ext = (ext == module::argument::sign_ext); - const uint8_t fill = (sign_ext && msb(v) ? ~0 : 0); - T w(n, fill); - - if (PIPE_ENDIAN_NATIVE == PIPE_ENDIAN_LITTLE) - std::copy_n(v.begin(), m, w.begin()); - else - std::copy_n(v.end() - m, m, w.end() - m); - - std::swap(v, w); - } - - /// - /// Append buffer \a w to \a v. - /// - template - void - insert(T &v, const T &w) { - v.insert(v.end(), w.begin(), w.end()); - } - - /// - /// Append \a n elements to the end of buffer \a v. - /// - template - size_t - allocate(T &v, size_t n) { - size_t pos = v.size(); - v.resize(pos + n); - return pos; - } -} - -std::unique_ptr -kernel::argument::create(const module::argument &marg) { - switch (marg.type) { - case module::argument::scalar: - return std::unique_ptr(new scalar_argument(marg.size)); - - case module::argument::global: - return std::unique_ptr(new global_argument); - - case module::argument::local: - return std::unique_ptr(new local_argument); - - case module::argument::constant: - return std::unique_ptr(new constant_argument); - - case module::argument::image2d_rd: - case module::argument::image3d_rd: - return std::unique_ptr(new image_rd_argument); - - case module::argument::image2d_wr: - case module::argument::image3d_wr: - return std::unique_ptr(new image_wr_argument); - - case module::argument::sampler: - return std::unique_ptr(new sampler_argument); - - } - throw error(CL_INVALID_KERNEL_DEFINITION); -} - -kernel::argument::argument() : _set(false) { -} - -bool -kernel::argument::set() const { - return _set; -} - -size_t -kernel::argument::storage() const { - return 0; -} - -kernel::scalar_argument::scalar_argument(size_t size) : size(size) { -} - -void -kernel::scalar_argument::set(size_t size, const void *value) { - if (!value) - throw error(CL_INVALID_ARG_VALUE); - - if (size != this->size) - throw error(CL_INVALID_ARG_SIZE); - - v = { (uint8_t *)value, (uint8_t *)value + size }; - _set = true; -} - -void -kernel::scalar_argument::bind(exec_context &ctx, - const module::argument &marg) { - auto w = v; - - extend(w, marg.ext_type, marg.target_size); - byteswap(w, ctx.q->device().endianness()); - align(ctx.input, marg.target_align); - insert(ctx.input, w); -} - -void -kernel::scalar_argument::unbind(exec_context &ctx) { -} - -void -kernel::global_argument::set(size_t size, const void *value) { - if (size != sizeof(cl_mem)) - throw error(CL_INVALID_ARG_SIZE); - - buf = pobj(value ? *(cl_mem *)value : NULL); - svm = nullptr; - _set = true; -} - -void -kernel::global_argument::set_svm(const void *value) { - svm = value; - buf = nullptr; - _set = true; -} - -void -kernel::global_argument::bind(exec_context &ctx, - const module::argument &marg) { - align(ctx.input, marg.target_align); - - if (buf) { - const resource &r = buf->resource(*ctx.q); - ctx.g_handles.push_back(ctx.input.size()); - ctx.g_buffers.push_back(r.pipe); - - // How to handle multi-demensional offsets? - // We don't need to. Buffer offsets are always - // one-dimensional. - auto v = bytes(r.offset[0]); - extend(v, marg.ext_type, marg.target_size); - byteswap(v, ctx.q->device().endianness()); - insert(ctx.input, v); - } else if (svm) { - auto v = bytes(svm); - extend(v, marg.ext_type, marg.target_size); - byteswap(v, ctx.q->device().endianness()); - insert(ctx.input, v); - } else { - // Null pointer. - allocate(ctx.input, marg.target_size); - } -} - -void -kernel::global_argument::unbind(exec_context &ctx) { -} - -size_t -kernel::local_argument::storage() const { - return _storage; -} - -void -kernel::local_argument::set(size_t size, const void *value) { - if (value) - throw error(CL_INVALID_ARG_VALUE); - - if (!size) - throw error(CL_INVALID_ARG_SIZE); - - _storage = size; - _set = true; -} - -void -kernel::local_argument::bind(exec_context &ctx, - const module::argument &marg) { - auto v = bytes(ctx.mem_local); - - extend(v, module::argument::zero_ext, marg.target_size); - byteswap(v, ctx.q->device().endianness()); - align(ctx.input, marg.target_align); - insert(ctx.input, v); - - ctx.mem_local += _storage; -} - -void -kernel::local_argument::unbind(exec_context &ctx) { -} - -void -kernel::constant_argument::set(size_t size, const void *value) { - if (size != sizeof(cl_mem)) - throw error(CL_INVALID_ARG_SIZE); - - buf = pobj(value ? *(cl_mem *)value : NULL); - _set = true; -} - -void -kernel::constant_argument::bind(exec_context &ctx, - const module::argument &marg) { - align(ctx.input, marg.target_align); - - if (buf) { - resource &r = buf->resource(*ctx.q); - auto v = bytes(ctx.resources.size() << 24 | r.offset[0]); - - extend(v, module::argument::zero_ext, marg.target_size); - byteswap(v, ctx.q->device().endianness()); - insert(ctx.input, v); - - st = r.bind_surface(*ctx.q, false); - ctx.resources.push_back(st); - } else { - // Null pointer. - allocate(ctx.input, marg.target_size); - } -} - -void -kernel::constant_argument::unbind(exec_context &ctx) { - if (buf) - buf->resource(*ctx.q).unbind_surface(*ctx.q, st); -} - -void -kernel::image_rd_argument::set(size_t size, const void *value) { - if (!value) - throw error(CL_INVALID_ARG_VALUE); - - if (size != sizeof(cl_mem)) - throw error(CL_INVALID_ARG_SIZE); - - img = &obj(*(cl_mem *)value); - _set = true; -} - -void -kernel::image_rd_argument::bind(exec_context &ctx, - const module::argument &marg) { - auto v = bytes(ctx.sviews.size()); - - extend(v, module::argument::zero_ext, marg.target_size); - byteswap(v, ctx.q->device().endianness()); - align(ctx.input, marg.target_align); - insert(ctx.input, v); - - st = img->resource(*ctx.q).bind_sampler_view(*ctx.q); - ctx.sviews.push_back(st); -} - -void -kernel::image_rd_argument::unbind(exec_context &ctx) { - img->resource(*ctx.q).unbind_sampler_view(*ctx.q, st); -} - -void -kernel::image_wr_argument::set(size_t size, const void *value) { - if (!value) - throw error(CL_INVALID_ARG_VALUE); - - if (size != sizeof(cl_mem)) - throw error(CL_INVALID_ARG_SIZE); - - img = &obj(*(cl_mem *)value); - _set = true; -} - -void -kernel::image_wr_argument::bind(exec_context &ctx, - const module::argument &marg) { - auto v = bytes(ctx.resources.size()); - - extend(v, module::argument::zero_ext, marg.target_size); - byteswap(v, ctx.q->device().endianness()); - align(ctx.input, marg.target_align); - insert(ctx.input, v); - - st = img->resource(*ctx.q).bind_surface(*ctx.q, true); - ctx.resources.push_back(st); -} - -void -kernel::image_wr_argument::unbind(exec_context &ctx) { - img->resource(*ctx.q).unbind_surface(*ctx.q, st); -} - -void -kernel::sampler_argument::set(size_t size, const void *value) { - if (!value) - throw error(CL_INVALID_SAMPLER); - - if (size != sizeof(cl_sampler)) - throw error(CL_INVALID_ARG_SIZE); - - s = &obj(*(cl_sampler *)value); - _set = true; -} - -void -kernel::sampler_argument::bind(exec_context &ctx, - const module::argument &marg) { - st = s->bind(*ctx.q); - ctx.samplers.push_back(st); -} - -void -kernel::sampler_argument::unbind(exec_context &ctx) { - s->unbind(*ctx.q, st); -} diff --git a/src/gallium/state_trackers/clover/core/kernel.hpp b/src/gallium/state_trackers/clover/core/kernel.hpp deleted file mode 100644 index 4441091f300..00000000000 --- a/src/gallium/state_trackers/clover/core/kernel.hpp +++ /dev/null @@ -1,251 +0,0 @@ -// -// Copyright 2012 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#ifndef CLOVER_CORE_KERNEL_HPP -#define CLOVER_CORE_KERNEL_HPP - -#include - -#include "core/object.hpp" -#include "core/program.hpp" -#include "core/memory.hpp" -#include "core/sampler.hpp" -#include "pipe/p_state.h" - -namespace clover { - class kernel : public ref_counter, public _cl_kernel { - private: - /// - /// Class containing all the state required to execute a compute - /// kernel. - /// - struct exec_context { - exec_context(kernel &kern); - ~exec_context(); - - exec_context(const exec_context &) = delete; - exec_context & - operator=(const exec_context &) = delete; - - void *bind(intrusive_ptr _q, - const std::vector &grid_offset); - void unbind(); - - kernel &kern; - intrusive_ptr q; - - std::vector input; - std::vector samplers; - std::vector sviews; - std::vector resources; - std::vector g_buffers; - std::vector g_handles; - size_t mem_local; - - private: - void *st; - pipe_compute_state cs; - }; - - public: - class argument { - public: - static std::unique_ptr - create(const module::argument &marg); - - argument(const argument &arg) = delete; - argument & - operator=(const argument &arg) = delete; - - /// \a true if the argument has been set. - bool set() const; - - /// Storage space required for the referenced object. - virtual size_t storage() const; - - /// Set this argument to some object. - virtual void set(size_t size, const void *value) = 0; - - /// Set this argument to an SVM pointer. - virtual void set_svm(const void *value) { - throw error(CL_INVALID_ARG_INDEX); - }; - - /// Allocate the necessary resources to bind the specified - /// object to this argument, and update \a ctx accordingly. - virtual void bind(exec_context &ctx, - const module::argument &marg) = 0; - - /// Free any resources that were allocated in bind(). - virtual void unbind(exec_context &ctx) = 0; - - virtual ~argument() {}; - protected: - argument(); - - bool _set; - }; - - private: - typedef adaptor_range< - derefs, std::vector> & - > argument_range; - - typedef adaptor_range< - derefs, const std::vector> & - > const_argument_range; - - public: - kernel(clover::program &prog, const std::string &name, - const std::vector &margs); - - kernel(const kernel &kern) = delete; - kernel & - operator=(const kernel &kern) = delete; - - void launch(command_queue &q, - const std::vector &grid_offset, - const std::vector &grid_size, - const std::vector &block_size); - - size_t mem_local() const; - size_t mem_private() const; - - const std::string &name() const; - - std::vector - optimal_block_size(const command_queue &q, - const std::vector &grid_size) const; - std::vector - required_block_size() const; - - argument_range args(); - const_argument_range args() const; - - const intrusive_ref program; - - private: - const clover::module &module(const command_queue &q) const; - - class scalar_argument : public argument { - public: - scalar_argument(size_t size); - - virtual void set(size_t size, const void *value); - virtual void bind(exec_context &ctx, - const module::argument &marg); - virtual void unbind(exec_context &ctx); - - private: - size_t size; - std::vector v; - }; - - class global_argument : public argument { - public: - virtual void set(size_t size, const void *value); - virtual void set_svm(const void *value); - virtual void bind(exec_context &ctx, - const module::argument &marg); - virtual void unbind(exec_context &ctx); - - private: - buffer *buf; - const void *svm; - }; - - class local_argument : public argument { - public: - virtual size_t storage() const; - - virtual void set(size_t size, const void *value); - virtual void bind(exec_context &ctx, - const module::argument &marg); - virtual void unbind(exec_context &ctx); - - private: - size_t _storage = 0; - }; - - class constant_argument : public argument { - public: - virtual void set(size_t size, const void *value); - virtual void bind(exec_context &ctx, - const module::argument &marg); - virtual void unbind(exec_context &ctx); - - private: - buffer *buf; - pipe_surface *st; - }; - - class image_argument : public argument { - public: - const image *get() const { - return img; - } - protected: - image *img; - }; - - class image_rd_argument : public image_argument { - public: - virtual void set(size_t size, const void *value); - virtual void bind(exec_context &ctx, - const module::argument &marg); - virtual void unbind(exec_context &ctx); - - private: - pipe_sampler_view *st; - }; - - class image_wr_argument : public image_argument { - public: - virtual void set(size_t size, const void *value); - virtual void bind(exec_context &ctx, - const module::argument &marg); - virtual void unbind(exec_context &ctx); - - private: - pipe_surface *st; - }; - - class sampler_argument : public argument { - public: - virtual void set(size_t size, const void *value); - virtual void bind(exec_context &ctx, - const module::argument &marg); - virtual void unbind(exec_context &ctx); - - private: - sampler *s; - void *st; - }; - - std::vector> _args; - std::string _name; - exec_context exec; - const ref_holder program_ref; - }; -} - -#endif diff --git a/src/gallium/state_trackers/clover/core/memory.cpp b/src/gallium/state_trackers/clover/core/memory.cpp deleted file mode 100644 index ed13d92c281..00000000000 --- a/src/gallium/state_trackers/clover/core/memory.cpp +++ /dev/null @@ -1,214 +0,0 @@ -// -// Copyright 2012 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#include "core/memory.hpp" -#include "core/resource.hpp" -#include "util/format/u_format.h" - -using namespace clover; - -memory_obj::memory_obj(clover::context &ctx, cl_mem_flags flags, - size_t size, void *host_ptr) : - context(ctx), _flags(flags), - _size(size), _host_ptr(host_ptr) { - if (flags & CL_MEM_COPY_HOST_PTR) - data.append((char *)host_ptr, size); -} - -memory_obj::~memory_obj() { - while (_destroy_notify.size()) { - _destroy_notify.top()(); - _destroy_notify.pop(); - } -} - -bool -memory_obj::operator==(const memory_obj &obj) const { - return this == &obj; -} - -void -memory_obj::destroy_notify(std::function f) { - _destroy_notify.push(f); -} - -cl_mem_flags -memory_obj::flags() const { - return _flags; -} - -size_t -memory_obj::size() const { - return _size; -} - -void * -memory_obj::host_ptr() const { - return _host_ptr; -} - -buffer::buffer(clover::context &ctx, cl_mem_flags flags, - size_t size, void *host_ptr) : - memory_obj(ctx, flags, size, host_ptr) { -} - -cl_mem_object_type -buffer::type() const { - return CL_MEM_OBJECT_BUFFER; -} - -root_buffer::root_buffer(clover::context &ctx, cl_mem_flags flags, - size_t size, void *host_ptr) : - buffer(ctx, flags, size, host_ptr) { -} - -resource & -root_buffer::resource(command_queue &q) { - // Create a new resource if there's none for this device yet. - if (!resources.count(&q.device())) { - auto r = (!resources.empty() ? - new root_resource(q.device(), *this, - *resources.begin()->second) : - new root_resource(q.device(), *this, q, data)); - - resources.insert(std::make_pair(&q.device(), - std::unique_ptr(r))); - data.clear(); - } - - return *resources.find(&q.device())->second; -} - -sub_buffer::sub_buffer(root_buffer &parent, cl_mem_flags flags, - size_t offset, size_t size) : - buffer(parent.context(), flags, size, - (char *)parent.host_ptr() + offset), - parent(parent), _offset(offset) { -} - -resource & -sub_buffer::resource(command_queue &q) { - // Create a new resource if there's none for this device yet. - if (!resources.count(&q.device())) { - auto r = new sub_resource(parent().resource(q), {{ offset() }}); - - resources.insert(std::make_pair(&q.device(), - std::unique_ptr(r))); - } - - return *resources.find(&q.device())->second; -} - -size_t -sub_buffer::offset() const { - return _offset; -} - -image::image(clover::context &ctx, cl_mem_flags flags, - const cl_image_format *format, - size_t width, size_t height, size_t depth, - size_t row_pitch, size_t slice_pitch, size_t size, - void *host_ptr) : - memory_obj(ctx, flags, size, host_ptr), - _format(*format), _width(width), _height(height), _depth(depth), - _row_pitch(row_pitch), _slice_pitch(slice_pitch) { -} - -resource & -image::resource(command_queue &q) { - // Create a new resource if there's none for this device yet. - if (!resources.count(&q.device())) { - auto r = (!resources.empty() ? - new root_resource(q.device(), *this, - *resources.begin()->second) : - new root_resource(q.device(), *this, q, data)); - - resources.insert(std::make_pair(&q.device(), - std::unique_ptr(r))); - data.clear(); - } - - return *resources.find(&q.device())->second; -} - -cl_image_format -image::format() const { - return _format; -} - -size_t -image::width() const { - return _width; -} - -size_t -image::height() const { - return _height; -} - -size_t -image::depth() const { - return _depth; -} - -size_t -image::pixel_size() const { - return util_format_get_blocksize(translate_format(_format)); -} - -size_t -image::row_pitch() const { - return _row_pitch; -} - -size_t -image::slice_pitch() const { - return _slice_pitch; -} - -image2d::image2d(clover::context &ctx, cl_mem_flags flags, - const cl_image_format *format, size_t width, - size_t height, size_t row_pitch, - void *host_ptr) : - image(ctx, flags, format, width, height, 1, - row_pitch, 0, height * row_pitch, host_ptr) { -} - -cl_mem_object_type -image2d::type() const { - return CL_MEM_OBJECT_IMAGE2D; -} - -image3d::image3d(clover::context &ctx, cl_mem_flags flags, - const cl_image_format *format, - size_t width, size_t height, size_t depth, - size_t row_pitch, size_t slice_pitch, - void *host_ptr) : - image(ctx, flags, format, width, height, depth, - row_pitch, slice_pitch, depth * slice_pitch, - host_ptr) { -} - -cl_mem_object_type -image3d::type() const { - return CL_MEM_OBJECT_IMAGE3D; -} diff --git a/src/gallium/state_trackers/clover/core/memory.hpp b/src/gallium/state_trackers/clover/core/memory.hpp deleted file mode 100644 index bd6da6be4d1..00000000000 --- a/src/gallium/state_trackers/clover/core/memory.hpp +++ /dev/null @@ -1,159 +0,0 @@ -// -// Copyright 2012 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#ifndef CLOVER_CORE_MEMORY_HPP -#define CLOVER_CORE_MEMORY_HPP - -#include -#include -#include -#include - -#include "core/object.hpp" -#include "core/queue.hpp" -#include "core/resource.hpp" - -namespace clover { - class memory_obj : public ref_counter, public _cl_mem { - protected: - memory_obj(clover::context &ctx, cl_mem_flags flags, - size_t size, void *host_ptr); - - memory_obj(const memory_obj &obj) = delete; - memory_obj & - operator=(const memory_obj &obj) = delete; - - public: - virtual ~memory_obj(); - - bool - operator==(const memory_obj &obj) const; - - virtual cl_mem_object_type type() const = 0; - virtual clover::resource &resource(command_queue &q) = 0; - - void destroy_notify(std::function f); - cl_mem_flags flags() const; - size_t size() const; - void *host_ptr() const; - - const intrusive_ref context; - - private: - cl_mem_flags _flags; - size_t _size; - void *_host_ptr; - std::stack> _destroy_notify; - - protected: - std::string data; - }; - - class buffer : public memory_obj { - protected: - buffer(clover::context &ctx, cl_mem_flags flags, - size_t size, void *host_ptr); - - public: - virtual cl_mem_object_type type() const; - }; - - class root_buffer : public buffer { - public: - root_buffer(clover::context &ctx, cl_mem_flags flags, - size_t size, void *host_ptr); - - virtual clover::resource &resource(command_queue &q); - - private: - std::map> resources; - }; - - class sub_buffer : public buffer { - public: - sub_buffer(root_buffer &parent, cl_mem_flags flags, - size_t offset, size_t size); - - virtual clover::resource &resource(command_queue &q); - size_t offset() const; - - const intrusive_ref parent; - - private: - size_t _offset; - std::map> resources; - }; - - class image : public memory_obj { - protected: - image(clover::context &ctx, cl_mem_flags flags, - const cl_image_format *format, - size_t width, size_t height, size_t depth, - size_t row_pitch, size_t slice_pitch, size_t size, - void *host_ptr); - - public: - virtual clover::resource &resource(command_queue &q); - cl_image_format format() const; - size_t width() const; - size_t height() const; - size_t depth() const; - size_t pixel_size() const; - size_t row_pitch() const; - size_t slice_pitch() const; - - private: - cl_image_format _format; - size_t _width; - size_t _height; - size_t _depth; - size_t _row_pitch; - size_t _slice_pitch; - std::map> resources; - }; - - class image2d : public image { - public: - image2d(clover::context &ctx, cl_mem_flags flags, - const cl_image_format *format, size_t width, - size_t height, size_t row_pitch, - void *host_ptr); - - virtual cl_mem_object_type type() const; - }; - - class image3d : public image { - public: - image3d(clover::context &ctx, cl_mem_flags flags, - const cl_image_format *format, - size_t width, size_t height, size_t depth, - size_t row_pitch, size_t slice_pitch, - void *host_ptr); - - virtual cl_mem_object_type type() const; - }; -} - -#endif diff --git a/src/gallium/state_trackers/clover/core/module.cpp b/src/gallium/state_trackers/clover/core/module.cpp deleted file mode 100644 index a6c5b98d8e0..00000000000 --- a/src/gallium/state_trackers/clover/core/module.cpp +++ /dev/null @@ -1,228 +0,0 @@ -// -// Copyright 2012 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#include -#include - -#include "core/module.hpp" - -using namespace clover; - -namespace { - template - struct _serializer; - - /// Serialize the specified object. - template - void - _proc(std::ostream &os, const T &x) { - _serializer::proc(os, x); - } - - /// Deserialize the specified object. - template - void - _proc(std::istream &is, T &x) { - _serializer::proc(is, x); - } - - template - T - _proc(std::istream &is) { - T x; - _serializer::proc(is, x); - return x; - } - - /// Calculate the size of the specified object. - template - void - _proc(module::size_t &sz, const T &x) { - _serializer::proc(sz, x); - } - - /// (De)serialize a scalar value. - template - struct _serializer::value>::type> { - static void - proc(std::ostream &os, const T &x) { - os.write(reinterpret_cast(&x), sizeof(x)); - } - - static void - proc(std::istream &is, T &x) { - is.read(reinterpret_cast(&x), sizeof(x)); - } - - static void - proc(module::size_t &sz, const T &x) { - sz += sizeof(x); - } - }; - - /// (De)serialize a vector. - template - struct _serializer, - typename std::enable_if< - !std::is_scalar::value>::type> { - static void - proc(std::ostream &os, const std::vector &v) { - _proc(os, v.size()); - - for (size_t i = 0; i < v.size(); i++) - _proc(os, v[i]); - } - - static void - proc(std::istream &is, std::vector &v) { - v.resize(_proc(is)); - - for (size_t i = 0; i < v.size(); i++) - new(&v[i]) T(_proc(is)); - } - - static void - proc(module::size_t &sz, const std::vector &v) { - sz += sizeof(uint32_t); - - for (size_t i = 0; i < v.size(); i++) - _proc(sz, v[i]); - } - }; - - template - struct _serializer, - typename std::enable_if< - std::is_scalar::value>::type> { - static void - proc(std::ostream &os, const std::vector &v) { - _proc(os, v.size()); - os.write(reinterpret_cast(&v[0]), - v.size() * sizeof(T)); - } - - static void - proc(std::istream &is, std::vector &v) { - v.resize(_proc(is)); - is.read(reinterpret_cast(&v[0]), - v.size() * sizeof(T)); - } - - static void - proc(module::size_t &sz, const std::vector &v) { - sz += sizeof(uint32_t) + sizeof(T) * v.size(); - } - }; - - /// (De)serialize a string. - template<> - struct _serializer { - static void - proc(std::ostream &os, const std::string &s) { - _proc(os, s.size()); - os.write(&s[0], s.size() * sizeof(std::string::value_type)); - } - - static void - proc(std::istream &is, std::string &s) { - s.resize(_proc(is)); - is.read(&s[0], s.size() * sizeof(std::string::value_type)); - } - - static void - proc(module::size_t &sz, const std::string &s) { - sz += sizeof(uint32_t) + sizeof(std::string::value_type) * s.size(); - } - }; - - /// (De)serialize a module::section. - template<> - struct _serializer { - template - static void - proc(S &s, QT &x) { - _proc(s, x.id); - _proc(s, x.type); - _proc(s, x.size); - _proc(s, x.data); - } - }; - - /// (De)serialize a module::argument. - template<> - struct _serializer { - template - static void - proc(S &s, QT &x) { - _proc(s, x.type); - _proc(s, x.size); - _proc(s, x.target_size); - _proc(s, x.target_align); - _proc(s, x.ext_type); - _proc(s, x.semantic); - } - }; - - /// (De)serialize a module::symbol. - template<> - struct _serializer { - template - static void - proc(S &s, QT &x) { - _proc(s, x.name); - _proc(s, x.section); - _proc(s, x.offset); - _proc(s, x.args); - } - }; - - /// (De)serialize a module. - template<> - struct _serializer { - template - static void - proc(S &s, QT &x) { - _proc(s, x.syms); - _proc(s, x.secs); - } - }; -}; - -namespace clover { - void - module::serialize(std::ostream &os) const { - _proc(os, *this); - } - - module - module::deserialize(std::istream &is) { - return _proc(is); - } - - module::size_t - module::size() const { - size_t sz = 0; - _proc(sz, *this); - return sz; - } -} diff --git a/src/gallium/state_trackers/clover/core/module.hpp b/src/gallium/state_trackers/clover/core/module.hpp deleted file mode 100644 index 2ddd26426fb..00000000000 --- a/src/gallium/state_trackers/clover/core/module.hpp +++ /dev/null @@ -1,128 +0,0 @@ -// -// Copyright 2012 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#ifndef CLOVER_CORE_MODULE_HPP -#define CLOVER_CORE_MODULE_HPP - -#include -#include - -namespace clover { - struct module { - typedef uint32_t resource_id; - typedef uint32_t size_t; - - struct section { - enum type { - text_intermediate, - text_library, - text_executable, - data_constant, - data_global, - data_local, - data_private - }; - - section(resource_id id, enum type type, size_t size, - const std::vector &data) : - id(id), type(type), size(size), data(data) { } - section() : id(0), type(text_intermediate), size(0), data() { } - - resource_id id; - type type; - size_t size; - std::vector data; - }; - - struct argument { - enum type { - scalar, - constant, - global, - local, - image2d_rd, - image2d_wr, - image3d_rd, - image3d_wr, - sampler - }; - - enum ext_type { - zero_ext, - sign_ext - }; - - enum semantic { - general, - grid_dimension, - grid_offset, - image_size, - image_format - }; - - argument(enum type type, size_t size, - size_t target_size, size_t target_align, - enum ext_type ext_type, - enum semantic semantic = general) : - type(type), size(size), - target_size(target_size), target_align(target_align), - ext_type(ext_type), semantic(semantic) { } - - argument(enum type type, size_t size) : - type(type), size(size), - target_size(size), target_align(1), - ext_type(zero_ext), semantic(general) { } - - argument() : type(scalar), size(0), - target_size(0), target_align(1), - ext_type(zero_ext), semantic(general) { } - - type type; - size_t size; - size_t target_size; - size_t target_align; - ext_type ext_type; - semantic semantic; - }; - - struct symbol { - symbol(const std::string &name, resource_id section, - size_t offset, const std::vector &args) : - name(name), section(section), offset(offset), args(args) { } - symbol() : name(), section(0), offset(0), args() { } - - std::string name; - resource_id section; - size_t offset; - std::vector args; - }; - - void serialize(std::ostream &os) const; - static module deserialize(std::istream &is); - size_t size() const; - - std::vector syms; - std::vector

      secs; - }; -} - -#endif diff --git a/src/gallium/state_trackers/clover/core/object.hpp b/src/gallium/state_trackers/clover/core/object.hpp deleted file mode 100644 index 8fc2175d236..00000000000 --- a/src/gallium/state_trackers/clover/core/object.hpp +++ /dev/null @@ -1,239 +0,0 @@ -// -// Copyright 2013 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#ifndef CLOVER_CORE_OBJECT_HPP -#define CLOVER_CORE_OBJECT_HPP - -#include -#include -#include - -#include "CL/cl.h" - -#include "core/error.hpp" -#include "core/property.hpp" -#include "api/dispatch.hpp" -#include "util/macros.h" - -/// -/// Main namespace of the CL state tracker. -/// -namespace clover { - /// - /// Class that represents a CL API object. - /// - template - struct descriptor { - typedef T object_type; - typedef S descriptor_type; - - descriptor() : dispatch(&_dispatch) { - static_assert(std::is_standard_layout::value, - "ICD requires CL API objects to be standard layout."); - } - - const cl_icd_dispatch *dispatch; - }; - - struct default_tag; - struct allow_empty_tag; - struct wait_list_tag; - struct property_list_tag; - - namespace detail { - template - struct descriptor_traits { - typedef T object_type; - - static void - validate(D *d) { - auto o = static_cast(d); - if (!o || o->dispatch != &_dispatch || - !dynamic_cast(o)) - throw invalid_object_error(); - } - - static void - validate_list(D * const *ds, size_t n) { - if (!ds || !n) - throw error(CL_INVALID_VALUE); - } - }; - - template - struct descriptor_traits { - typedef typename D::object_type object_type; - - static void - validate(D *d) { - if (!d || d->dispatch != &_dispatch) - throw invalid_object_error(); - } - - static void - validate_list(D *const *ds, size_t n) { - if (!ds || !n) - throw error(CL_INVALID_VALUE); - } - }; - - template - struct descriptor_traits { - typedef typename D::object_type object_type; - - static void - validate(D *d) { - if (!d || d->dispatch != &_dispatch) - throw invalid_object_error(); - } - - static void - validate_list(D *const *ds, size_t n) { - if (bool(ds) != bool(n)) - throw error(CL_INVALID_VALUE); - } - }; - - template - struct descriptor_traits { - typedef typename D::object_type object_type; - - static void - validate(D *d) { - if (!d || d->dispatch != &_dispatch) - throw invalid_wait_list_error(); - } - - static void - validate_list(D *const *ds, size_t n) { - if (bool(ds) != bool(n)) - throw invalid_wait_list_error(); - } - }; - } - - /// - /// Get a Clover object from an API object performing object - /// validation. - /// - /// \a T can either be the Clover object type to return or a \a tag - /// object to select some special validation behavior by means of a - /// specialization of the detail::descriptor_traits template. The - /// default behavior is to infer the most general Clover object - /// type for the given API object. - /// - template - typename detail::descriptor_traits::object_type & - obj(D *d) { - detail::descriptor_traits::validate(d); - - return static_cast< - typename detail::descriptor_traits::object_type &>(*d); - } - - /// - /// Get a pointer to a Clover object from an API object performing - /// object validation. Returns \c NULL if its argument is \c NULL. - /// - /// \sa obj - /// - template - typename detail::descriptor_traits::object_type * - pobj(D *d) { - if (d) - detail::descriptor_traits::validate(d); - - return static_cast< - typename detail::descriptor_traits::object_type *>(d); - } - - /// - /// Get an API object from a Clover object. - /// - template - typename O::descriptor_type * - desc(O &o) { - return static_cast(&o); - } - - /// - /// Get an API object from a pointer to a Clover object. - /// - template - typename O::descriptor_type * - desc(O *o) { - return static_cast(o); - } - - /// - /// Get a range of Clover objects from a range of API objects - /// performing object validation. - /// - /// \sa obj - /// - template - ref_vector::object_type> - objs(D *const *ds, size_t n) { - detail::descriptor_traits::validate_list(ds, n); - return map(obj, range(ds, n)); - } - - /// - /// Get a range of API objects from a range of Clover objects. - /// - template - std::vector - descs(const Os &os) { - return map([](typename Os::value_type &o) { - return desc(o); - }, os); - } -} - -struct _cl_context : - public clover::descriptor {}; - -struct _cl_device_id : - public clover::descriptor {}; - -struct _cl_event : - public clover::descriptor {}; - -struct _cl_kernel : - public clover::descriptor {}; - -struct _cl_mem : - public clover::descriptor {}; - -struct _cl_platform_id : - public clover::descriptor {}; - -struct _cl_program : - public clover::descriptor {}; - -struct _cl_command_queue : - public clover::descriptor {}; - -struct _cl_sampler : - public clover::descriptor {}; - -#endif diff --git a/src/gallium/state_trackers/clover/core/platform.cpp b/src/gallium/state_trackers/clover/core/platform.cpp deleted file mode 100644 index ddd63fc5a0d..00000000000 --- a/src/gallium/state_trackers/clover/core/platform.cpp +++ /dev/null @@ -1,46 +0,0 @@ -// -// Copyright 2012 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#include "core/platform.hpp" - -using namespace clover; - -platform::platform() : adaptor_range(evals(), devs) { - int n = pipe_loader_probe(NULL, 0); - std::vector ldevs(n); - - pipe_loader_probe(&ldevs.front(), n); - - for (pipe_loader_device *ldev : ldevs) { - try { - if (ldev) - devs.push_back(create(*this, ldev)); - } catch (error &) { - pipe_loader_release(&ldev, 1); - } - } -} - -std::string -platform::supported_extensions() const { - return "cl_khr_icd"; -} diff --git a/src/gallium/state_trackers/clover/core/platform.hpp b/src/gallium/state_trackers/clover/core/platform.hpp deleted file mode 100644 index b94434c983c..00000000000 --- a/src/gallium/state_trackers/clover/core/platform.hpp +++ /dev/null @@ -1,50 +0,0 @@ -// -// Copyright 2013 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#ifndef CLOVER_CORE_PLATFORM_HPP -#define CLOVER_CORE_PLATFORM_HPP - -#include - -#include "core/object.hpp" -#include "core/device.hpp" -#include "util/range.hpp" - -namespace clover { - class platform : public _cl_platform_id, - public adaptor_range< - evals, std::vector> &> { - public: - platform(); - - platform(const platform &platform) = delete; - platform & - operator=(const platform &platform) = delete; - - std::string supported_extensions() const; - - protected: - std::vector> devs; - }; -} - -#endif diff --git a/src/gallium/state_trackers/clover/core/program.cpp b/src/gallium/state_trackers/clover/core/program.cpp deleted file mode 100644 index 526e06a26c3..00000000000 --- a/src/gallium/state_trackers/clover/core/program.cpp +++ /dev/null @@ -1,135 +0,0 @@ -// -// Copyright 2012 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#include "core/compiler.hpp" -#include "core/program.hpp" - -using namespace clover; - -program::program(clover::context &ctx, const std::string &source) : - has_source(true), context(ctx), _devices(ctx.devices()), _source(source), - _kernel_ref_counter(0) { -} - -program::program(clover::context &ctx, - const ref_vector &devs, - const std::vector &binaries) : - has_source(false), context(ctx), - _devices(devs), _kernel_ref_counter(0) { - for_each([&](device &dev, const module &bin) { - _builds[&dev] = { bin }; - }, - devs, binaries); -} - -void -program::compile(const ref_vector &devs, const std::string &opts, - const header_map &headers) { - if (has_source) { - _devices = devs; - - for (auto &dev : devs) { - std::string log; - - try { - const module m = - compiler::compile_program(_source, headers, dev, opts, log); - _builds[&dev] = { m, opts, log }; - } catch (...) { - _builds[&dev] = { module(), opts, log }; - throw; - } - } - } -} - -void -program::link(const ref_vector &devs, const std::string &opts, - const ref_vector &progs) { - _devices = devs; - - for (auto &dev : devs) { - const std::vector ms = map([&](const program &prog) { - return prog.build(dev).binary; - }, progs); - std::string log = _builds[&dev].log; - - try { - const module m = compiler::link_program(ms, dev, opts, log); - _builds[&dev] = { m, opts, log }; - } catch (...) { - _builds[&dev] = { module(), opts, log }; - throw; - } - } -} - -const std::string & -program::source() const { - return _source; -} - -program::device_range -program::devices() const { - return map(evals(), _devices); -} - -cl_build_status -program::build::status() const { - if (!binary.secs.empty()) - return CL_BUILD_SUCCESS; - else if (log.size()) - return CL_BUILD_ERROR; - else - return CL_BUILD_NONE; -} - -cl_program_binary_type -program::build::binary_type() const { - if (any_of(type_equals(module::section::text_intermediate), binary.secs)) - return CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT; - else if (any_of(type_equals(module::section::text_library), binary.secs)) - return CL_PROGRAM_BINARY_TYPE_LIBRARY; - else if (any_of(type_equals(module::section::text_executable), binary.secs)) - return CL_PROGRAM_BINARY_TYPE_EXECUTABLE; - else - return CL_PROGRAM_BINARY_TYPE_NONE; -} - -const struct program::build & -program::build(const device &dev) const { - static const struct build null; - return _builds.count(&dev) ? _builds.find(&dev)->second : null; -} - -const std::vector & -program::symbols() const { - if (_builds.empty()) - throw error(CL_INVALID_PROGRAM_EXECUTABLE); - - return _builds.begin()->second.binary.syms; -} - -unsigned -program::kernel_ref_count() const { - return _kernel_ref_counter.ref_count(); -} diff --git a/src/gallium/state_trackers/clover/core/program.hpp b/src/gallium/state_trackers/clover/core/program.hpp deleted file mode 100644 index 05964e78a79..00000000000 --- a/src/gallium/state_trackers/clover/core/program.hpp +++ /dev/null @@ -1,91 +0,0 @@ -// -// Copyright 2012 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#ifndef CLOVER_CORE_PROGRAM_HPP -#define CLOVER_CORE_PROGRAM_HPP - -#include - -#include "core/object.hpp" -#include "core/context.hpp" -#include "core/module.hpp" - -namespace clover { - typedef std::vector> header_map; - - class program : public ref_counter, public _cl_program { - private: - typedef adaptor_range< - evals, const std::vector> &> device_range; - - public: - program(clover::context &ctx, - const std::string &source); - program(clover::context &ctx, - const ref_vector &devs = {}, - const std::vector &binaries = {}); - - program(const program &prog) = delete; - program & - operator=(const program &prog) = delete; - - void compile(const ref_vector &devs, const std::string &opts, - const header_map &headers = {}); - void link(const ref_vector &devs, const std::string &opts, - const ref_vector &progs); - - const bool has_source; - const std::string &source() const; - - device_range devices() const; - - struct build { - build(const module &m = {}, const std::string &opts = {}, - const std::string &log = {}) : binary(m), opts(opts), log(log) {} - - cl_build_status status() const; - cl_program_binary_type binary_type() const; - - module binary; - std::string opts; - std::string log; - }; - - const build &build(const device &dev) const; - - const std::vector &symbols() const; - - unsigned kernel_ref_count() const; - - const intrusive_ref context; - - friend class kernel; - - private: - std::vector> _devices; - std::map _builds; - std::string _source; - ref_counter _kernel_ref_counter; - }; -} - -#endif diff --git a/src/gallium/state_trackers/clover/core/property.hpp b/src/gallium/state_trackers/clover/core/property.hpp deleted file mode 100644 index 7f8e17684d9..00000000000 --- a/src/gallium/state_trackers/clover/core/property.hpp +++ /dev/null @@ -1,261 +0,0 @@ -// -// Copyright 2013 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#ifndef CLOVER_CORE_PROPERTY_HPP -#define CLOVER_CORE_PROPERTY_HPP - -#include - -#include "util/range.hpp" -#include "util/algorithm.hpp" - -namespace clover { - class property_buffer; - - namespace detail { - template - class property_scalar { - public: - property_scalar(property_buffer &buf) : buf(buf) { - } - - inline property_scalar & - operator=(const T &x); - - private: - property_buffer &buf; - }; - - template - class property_vector { - public: - property_vector(property_buffer &buf) : buf(buf) { - } - - template - inline property_vector & - operator=(const S &v); - - private: - property_buffer &buf; - }; - - template - class property_matrix { - public: - property_matrix(property_buffer &buf) : buf(buf) { - } - - template - inline property_matrix & - operator=(const S &v); - - private: - property_buffer &buf; - }; - - class property_string { - public: - property_string(property_buffer &buf) : buf(buf) { - } - - inline property_string & - operator=(const std::string &v); - - private: - property_buffer &buf; - }; - }; - - /// - /// Return value buffer used by the CL property query functions. - /// - class property_buffer { - public: - property_buffer(void *r_buf, size_t size, size_t *r_size) : - r_buf(r_buf), size(size), r_size(r_size) { - } - - template - detail::property_scalar - as_scalar() { - return { *this }; - } - - template - detail::property_vector - as_vector() { - return { *this }; - } - - template - detail::property_matrix - as_matrix() { - return { *this }; - } - - detail::property_string - as_string() { - return { *this }; - } - - template - iterator_range - allocate(size_t n) { - if (r_buf && size < n * sizeof(T)) - throw error(CL_INVALID_VALUE); - - if (r_size) - *r_size = n * sizeof(T); - - if (r_buf) - return range((T *)r_buf, n); - else - return { }; - } - - private: - void *const r_buf; - const size_t size; - size_t *const r_size; - }; - - namespace detail { - template - inline property_scalar & - property_scalar::operator=(const T &x) { - auto r = buf.allocate(1); - - if (!r.empty()) - r.front() = x; - - return *this; - } - - template - template - inline property_vector & - property_vector::operator=(const S &v) { - auto r = buf.allocate(v.size()); - - if (!r.empty()) - copy(v, r.begin()); - - return *this; - } - - template - template - inline property_matrix & - property_matrix::operator=(const S &v) { - auto r = buf.allocate(v.size()); - - if (!r.empty()) - for_each([](typename S::value_type src, T *dst) { - if (dst) - copy(src, dst); - }, v, r); - - return *this; - } - - inline property_string & - property_string::operator=(const std::string &v) { - auto r = buf.allocate(v.size() + 1); - - if (!r.empty()) - copy(range(v.begin(), r.size()), r.begin()); - - return *this; - } - }; - - template - class property_element { - public: - property_element() : x() { - } - - property_element(T x) : x(x) { - } - - template - S - as() const { - assert(sizeof(S) <= sizeof(T)); - return reinterpret_cast(x); - } - - private: - T x; - }; - - template - using property_list = std::map>; - - struct property_list_tag; - - /// - /// Create a clover::property_list object from a zero-terminated - /// CL property list. - /// - template::value>::type> - property_list - obj(const D *d_props) { - property_list props; - - while (d_props && *d_props) { - auto key = *d_props++; - auto value = *d_props++; - - if (props.count(key)) - throw error(CL_INVALID_PROPERTY); - - props.insert({ key, value }); - } - - return props; - } - - /// - /// Create a zero-terminated CL property list from a - /// clover::property_list object. - /// - template - std::vector - desc(const property_list &props) { - std::vector d_props; - - for (auto &prop : props) { - d_props.push_back(prop.first); - d_props.push_back(prop.second.template as()); - } - - d_props.push_back(0); - - return d_props; - } -} - -#endif diff --git a/src/gallium/state_trackers/clover/core/queue.cpp b/src/gallium/state_trackers/clover/core/queue.cpp deleted file mode 100644 index c91b97ad15e..00000000000 --- a/src/gallium/state_trackers/clover/core/queue.cpp +++ /dev/null @@ -1,102 +0,0 @@ -// -// Copyright 2012 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#include "core/queue.hpp" -#include "core/event.hpp" -#include "pipe/p_screen.h" -#include "pipe/p_context.h" -#include "pipe/p_state.h" - -using namespace clover; - -namespace { - void - debug_notify_callback(void *data, - unsigned *id, - enum pipe_debug_type type, - const char *fmt, - va_list args) { - const command_queue *queue = (const command_queue *)data; - char buffer[1024]; - vsnprintf(buffer, sizeof(buffer), fmt, args); - queue->context().notify(buffer); - } -} - -command_queue::command_queue(clover::context &ctx, clover::device &dev, - cl_command_queue_properties props) : - context(ctx), device(dev), props(props) { - pipe = dev.pipe->context_create(dev.pipe, NULL, PIPE_CONTEXT_COMPUTE_ONLY); - if (!pipe) - throw error(CL_INVALID_DEVICE); - - if (ctx.notify) { - struct pipe_debug_callback cb; - memset(&cb, 0, sizeof(cb)); - cb.debug_message = &debug_notify_callback; - cb.data = this; - if (pipe->set_debug_callback) - pipe->set_debug_callback(pipe, &cb); - } -} - -command_queue::~command_queue() { - pipe->destroy(pipe); -} - -void -command_queue::flush() { - pipe_screen *screen = device().pipe; - pipe_fence_handle *fence = NULL; - - std::lock_guard lock(queued_events_mutex); - if (!queued_events.empty()) { - pipe->flush(pipe, &fence, 0); - - while (!queued_events.empty() && - queued_events.front()().signalled()) { - queued_events.front()().fence(fence); - queued_events.pop_front(); - } - - screen->fence_reference(screen, &fence, NULL); - } -} - -cl_command_queue_properties -command_queue::properties() const { - return props; -} - -bool -command_queue::profiling_enabled() const { - return props & CL_QUEUE_PROFILING_ENABLE; -} - -void -command_queue::sequence(hard_event &ev) { - std::lock_guard lock(queued_events_mutex); - if (!queued_events.empty()) - queued_events.back()().chain(ev); - - queued_events.push_back(ev); -} diff --git a/src/gallium/state_trackers/clover/core/queue.hpp b/src/gallium/state_trackers/clover/core/queue.hpp deleted file mode 100644 index bddb86c0e4c..00000000000 --- a/src/gallium/state_trackers/clover/core/queue.hpp +++ /dev/null @@ -1,78 +0,0 @@ -// -// Copyright 2012 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#ifndef CLOVER_CORE_QUEUE_HPP -#define CLOVER_CORE_QUEUE_HPP - -#include -#include - -#include "core/object.hpp" -#include "core/context.hpp" -#include "core/timestamp.hpp" -#include "pipe/p_context.h" - -namespace clover { - class resource; - class mapping; - class hard_event; - - class command_queue : public ref_counter, public _cl_command_queue { - public: - command_queue(clover::context &ctx, clover::device &dev, - cl_command_queue_properties props); - ~command_queue(); - - command_queue(const command_queue &q) = delete; - command_queue & - operator=(const command_queue &q) = delete; - - void flush(); - - cl_command_queue_properties properties() const; - bool profiling_enabled() const; - - const intrusive_ref context; - const intrusive_ref device; - - friend class resource; - friend class root_resource; - friend class mapping; - friend class hard_event; - friend class sampler; - friend class kernel; - friend class clover::timestamp::query; - friend class clover::timestamp::current; - - private: - /// Serialize a hardware event with respect to the previous ones, - /// and push it to the pending list. - void sequence(hard_event &ev); - - cl_command_queue_properties props; - pipe_context *pipe; - std::mutex queued_events_mutex; - std::deque> queued_events; - }; -} - -#endif diff --git a/src/gallium/state_trackers/clover/core/resource.cpp b/src/gallium/state_trackers/clover/core/resource.cpp deleted file mode 100644 index dd207982588..00000000000 --- a/src/gallium/state_trackers/clover/core/resource.cpp +++ /dev/null @@ -1,231 +0,0 @@ -// -// Copyright 2012 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#include "core/resource.hpp" -#include "core/memory.hpp" -#include "pipe/p_screen.h" -#include "util/u_sampler.h" -#include "util/format/u_format.h" -#include "util/u_inlines.h" - -using namespace clover; - -namespace { - class box { - public: - box(const resource::vector &origin, const resource::vector &size) : - pipe({ (int)origin[0], (int16_t)origin[1], - (int16_t)origin[2], (int)size[0], - (int16_t)size[1], (int16_t)size[2] }) { - } - - operator const pipe_box *() { - return &pipe; - } - - protected: - pipe_box pipe; - }; -} - -resource::resource(clover::device &dev, memory_obj &obj) : - device(dev), obj(obj), pipe(NULL), offset() { -} - -resource::~resource() { -} - -void -resource::copy(command_queue &q, const vector &origin, const vector ®ion, - resource &src_res, const vector &src_origin) { - auto p = offset + origin; - - q.pipe->resource_copy_region(q.pipe, pipe, 0, p[0], p[1], p[2], - src_res.pipe, 0, - box(src_res.offset + src_origin, region)); -} - -void * -resource::add_map(command_queue &q, cl_map_flags flags, bool blocking, - const vector &origin, const vector ®ion) { - maps.emplace_back(q, *this, flags, blocking, origin, region); - return maps.back(); -} - -void -resource::del_map(void *p) { - erase_if([&](const mapping &m) { - return static_cast(m) == p; - }, maps); -} - -unsigned -resource::map_count() const { - return maps.size(); -} - -pipe_sampler_view * -resource::bind_sampler_view(command_queue &q) { - pipe_sampler_view info; - - u_sampler_view_default_template(&info, pipe, pipe->format); - return q.pipe->create_sampler_view(q.pipe, pipe, &info); -} - -void -resource::unbind_sampler_view(command_queue &q, - pipe_sampler_view *st) { - q.pipe->sampler_view_destroy(q.pipe, st); -} - -pipe_surface * -resource::bind_surface(command_queue &q, bool rw) { - pipe_surface info {}; - - info.format = pipe->format; - info.writable = rw; - - if (pipe->target == PIPE_BUFFER) - info.u.buf.last_element = pipe->width0 - 1; - - return q.pipe->create_surface(q.pipe, pipe, &info); -} - -void -resource::unbind_surface(command_queue &q, pipe_surface *st) { - q.pipe->surface_destroy(q.pipe, st); -} - -root_resource::root_resource(clover::device &dev, memory_obj &obj, - command_queue &q, const std::string &data) : - resource(dev, obj) { - pipe_resource info {}; - const bool user_ptr_support = dev.pipe->get_param(dev.pipe, - PIPE_CAP_RESOURCE_FROM_USER_MEMORY); - - if (image *img = dynamic_cast(&obj)) { - info.format = translate_format(img->format()); - info.width0 = img->width(); - info.height0 = img->height(); - info.depth0 = img->depth(); - } else { - info.width0 = obj.size(); - info.height0 = 1; - info.depth0 = 1; - } - - info.array_size = 1; - info.target = translate_target(obj.type()); - info.bind = (PIPE_BIND_SAMPLER_VIEW | - PIPE_BIND_COMPUTE_RESOURCE | - PIPE_BIND_GLOBAL); - - if (obj.flags() & CL_MEM_USE_HOST_PTR && user_ptr_support) { - // Page alignment is normally required for this, just try, hope for the - // best and fall back if it fails. - pipe = dev.pipe->resource_from_user_memory(dev.pipe, &info, obj.host_ptr()); - if (pipe) - return; - } - - if (obj.flags() & (CL_MEM_ALLOC_HOST_PTR | CL_MEM_USE_HOST_PTR)) { - info.usage = PIPE_USAGE_STAGING; - } - - pipe = dev.pipe->resource_create(dev.pipe, &info); - if (!pipe) - throw error(CL_OUT_OF_RESOURCES); - - if (obj.flags() & (CL_MEM_USE_HOST_PTR | CL_MEM_COPY_HOST_PTR)) { - const void *data_ptr = !data.empty() ? data.data() : obj.host_ptr(); - box rect { {{ 0, 0, 0 }}, {{ info.width0, info.height0, info.depth0 }} }; - unsigned cpp = util_format_get_blocksize(info.format); - - if (pipe->target == PIPE_BUFFER) - q.pipe->buffer_subdata(q.pipe, pipe, PIPE_TRANSFER_WRITE, - 0, info.width0, data_ptr); - else - q.pipe->texture_subdata(q.pipe, pipe, 0, PIPE_TRANSFER_WRITE, - rect, data_ptr, cpp * info.width0, - cpp * info.width0 * info.height0); - } -} - -root_resource::root_resource(clover::device &dev, memory_obj &obj, - root_resource &r) : - resource(dev, obj) { - assert(0); // XXX -- resource shared among dev and r.dev -} - -root_resource::~root_resource() { - pipe_resource_reference(&this->pipe, NULL); -} - -sub_resource::sub_resource(resource &r, const vector &offset) : - resource(r.device(), r.obj) { - this->pipe = r.pipe; - this->offset = r.offset + offset; -} - -mapping::mapping(command_queue &q, resource &r, - cl_map_flags flags, bool blocking, - const resource::vector &origin, - const resource::vector ®ion) : - pctx(q.pipe), pres(NULL) { - unsigned usage = ((flags & CL_MAP_WRITE ? PIPE_TRANSFER_WRITE : 0 ) | - (flags & CL_MAP_READ ? PIPE_TRANSFER_READ : 0 ) | - (flags & CL_MAP_WRITE_INVALIDATE_REGION ? - PIPE_TRANSFER_DISCARD_RANGE : 0) | - (!blocking ? PIPE_TRANSFER_UNSYNCHRONIZED : 0)); - - p = pctx->transfer_map(pctx, r.pipe, 0, usage, - box(origin + r.offset, region), &pxfer); - if (!p) { - pxfer = NULL; - throw error(CL_OUT_OF_RESOURCES); - } - pipe_resource_reference(&pres, r.pipe); -} - -mapping::mapping(mapping &&m) : - pctx(m.pctx), pxfer(m.pxfer), pres(m.pres), p(m.p) { - m.pctx = NULL; - m.pxfer = NULL; - m.pres = NULL; - m.p = NULL; -} - -mapping::~mapping() { - if (pxfer) { - pctx->transfer_unmap(pctx, pxfer); - } - pipe_resource_reference(&pres, NULL); -} - -mapping & -mapping::operator=(mapping m) { - std::swap(pctx, m.pctx); - std::swap(pxfer, m.pxfer); - std::swap(pres, m.pres); - std::swap(p, m.p); - return *this; -} diff --git a/src/gallium/state_trackers/clover/core/resource.hpp b/src/gallium/state_trackers/clover/core/resource.hpp deleted file mode 100644 index 3b994b4008b..00000000000 --- a/src/gallium/state_trackers/clover/core/resource.hpp +++ /dev/null @@ -1,133 +0,0 @@ -// -// Copyright 2012 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#ifndef CLOVER_CORE_RESOURCE_HPP -#define CLOVER_CORE_RESOURCE_HPP - -#include - -#include "core/queue.hpp" -#include "util/algebra.hpp" -#include "pipe/p_state.h" - -namespace clover { - class memory_obj; - class mapping; - - /// - /// Class that represents a device-specific instance of some memory - /// object. - /// - class resource { - public: - typedef std::array vector; - - virtual ~resource(); - - resource(const resource &r) = delete; - resource & - operator=(const resource &r) = delete; - - void copy(command_queue &q, const vector &origin, const vector ®ion, - resource &src_resource, const vector &src_origin); - - void *add_map(command_queue &q, cl_map_flags flags, bool blocking, - const vector &origin, const vector ®ion); - void del_map(void *p); - unsigned map_count() const; - - const intrusive_ref device; - memory_obj &obj; - - friend class sub_resource; - friend class mapping; - friend class kernel; - - protected: - resource(clover::device &dev, memory_obj &obj); - - pipe_sampler_view *bind_sampler_view(command_queue &q); - void unbind_sampler_view(command_queue &q, - pipe_sampler_view *st); - - pipe_surface *bind_surface(command_queue &q, bool rw); - void unbind_surface(command_queue &q, pipe_surface *st); - - pipe_resource *pipe; - vector offset; - - private: - std::list maps; - }; - - /// - /// Resource associated with its own top-level data storage - /// allocated in some device. - /// - class root_resource : public resource { - public: - root_resource(clover::device &dev, memory_obj &obj, - command_queue &q, const std::string &data); - root_resource(clover::device &dev, memory_obj &obj, root_resource &r); - virtual ~root_resource(); - }; - - /// - /// Resource that reuses a portion of some other resource as data - /// storage. - /// - class sub_resource : public resource { - public: - sub_resource(resource &r, const vector &offset); - }; - - /// - /// Class that represents a mapping of some resource into the CPU - /// memory space. - /// - class mapping { - public: - mapping(command_queue &q, resource &r, cl_map_flags flags, - bool blocking, const resource::vector &origin, - const resource::vector ®ion); - mapping(mapping &&m); - ~mapping(); - - mapping & - operator=(mapping m); - - mapping(const mapping &m) = delete; - - template - operator T *() const { - return (T *)p; - } - - private: - pipe_context *pctx; - pipe_transfer *pxfer; - pipe_resource *pres; - void *p; - }; -} - -#endif diff --git a/src/gallium/state_trackers/clover/core/sampler.cpp b/src/gallium/state_trackers/clover/core/sampler.cpp deleted file mode 100644 index 6f2784b538e..00000000000 --- a/src/gallium/state_trackers/clover/core/sampler.cpp +++ /dev/null @@ -1,73 +0,0 @@ -// -// Copyright 2012 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#include "core/sampler.hpp" -#include "pipe/p_state.h" - -using namespace clover; - -sampler::sampler(clover::context &ctx, bool norm_mode, - cl_addressing_mode addr_mode, - cl_filter_mode filter_mode) : - context(ctx), _norm_mode(norm_mode), - _addr_mode(addr_mode), _filter_mode(filter_mode) { -} - -bool -sampler::norm_mode() { - return _norm_mode; -} - -cl_addressing_mode -sampler::addr_mode() { - return _addr_mode; -} - -cl_filter_mode -sampler::filter_mode() { - return _filter_mode; -} - -void * -sampler::bind(command_queue &q) { - struct pipe_sampler_state info {}; - - info.normalized_coords = norm_mode(); - - info.wrap_s = info.wrap_t = info.wrap_r = - (addr_mode() == CL_ADDRESS_CLAMP_TO_EDGE ? PIPE_TEX_WRAP_CLAMP_TO_EDGE : - addr_mode() == CL_ADDRESS_CLAMP ? PIPE_TEX_WRAP_CLAMP_TO_BORDER : - addr_mode() == CL_ADDRESS_REPEAT ? PIPE_TEX_WRAP_REPEAT : - addr_mode() == CL_ADDRESS_MIRRORED_REPEAT ? PIPE_TEX_WRAP_MIRROR_REPEAT : - PIPE_TEX_WRAP_CLAMP_TO_EDGE); - - info.min_img_filter = info.mag_img_filter = - (filter_mode() == CL_FILTER_LINEAR ? PIPE_TEX_FILTER_LINEAR : - PIPE_TEX_FILTER_NEAREST); - - return q.pipe->create_sampler_state(q.pipe, &info); -} - -void -sampler::unbind(command_queue &q, void *st) { - q.pipe->delete_sampler_state(q.pipe, st); -} diff --git a/src/gallium/state_trackers/clover/core/sampler.hpp b/src/gallium/state_trackers/clover/core/sampler.hpp deleted file mode 100644 index 2632c3067fa..00000000000 --- a/src/gallium/state_trackers/clover/core/sampler.hpp +++ /dev/null @@ -1,58 +0,0 @@ -// -// Copyright 2012 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#ifndef CLOVER_CORE_SAMPLER_HPP -#define CLOVER_CORE_SAMPLER_HPP - -#include "core/object.hpp" -#include "core/queue.hpp" - -namespace clover { - class sampler : public ref_counter, public _cl_sampler { - public: - sampler(clover::context &ctx, bool norm_mode, - cl_addressing_mode addr_mode, - cl_filter_mode filter_mode); - - sampler(const sampler &s) = delete; - sampler & - operator=(const sampler &s) = delete; - - bool norm_mode(); - cl_addressing_mode addr_mode(); - cl_filter_mode filter_mode(); - - const intrusive_ref context; - - friend class kernel; - - private: - void *bind(command_queue &q); - void unbind(command_queue &q, void *st); - - bool _norm_mode; - cl_addressing_mode _addr_mode; - cl_filter_mode _filter_mode; - }; -} - -#endif diff --git a/src/gallium/state_trackers/clover/core/timestamp.cpp b/src/gallium/state_trackers/clover/core/timestamp.cpp deleted file mode 100644 index 3fd341f30da..00000000000 --- a/src/gallium/state_trackers/clover/core/timestamp.cpp +++ /dev/null @@ -1,64 +0,0 @@ -// -// Copyright 2013 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#include "core/timestamp.hpp" -#include "core/queue.hpp" -#include "pipe/p_screen.h" -#include "pipe/p_context.h" - -using namespace clover; - -timestamp::query::query(command_queue &q) : - q(q), - _query(q.pipe->create_query(q.pipe, PIPE_QUERY_TIMESTAMP, 0)) { - q.pipe->end_query(q.pipe, _query); -} - -timestamp::query::query(query &&other) : - q(other.q), - _query(other._query) { - other._query = NULL; -} - -timestamp::query::~query() { - if (_query) - q().pipe->destroy_query(q().pipe, _query); -} - -cl_ulong -timestamp::query::operator()() const { - pipe_query_result result; - - if (!q().pipe->get_query_result(q().pipe, _query, false, &result)) - throw error(CL_PROFILING_INFO_NOT_AVAILABLE); - - return result.u64; -} - -timestamp::current::current(command_queue &q) : - result(q.pipe->screen->get_timestamp(q.pipe->screen)) { -} - -cl_ulong -timestamp::current::operator()() const { - return result; -} diff --git a/src/gallium/state_trackers/clover/core/timestamp.hpp b/src/gallium/state_trackers/clover/core/timestamp.hpp deleted file mode 100644 index b4b2c83eb92..00000000000 --- a/src/gallium/state_trackers/clover/core/timestamp.hpp +++ /dev/null @@ -1,74 +0,0 @@ -// -// Copyright 2013 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#ifndef CLOVER_CORE_TIMESTAMP_HPP -#define CLOVER_CORE_TIMESTAMP_HPP - -#include "core/object.hpp" - -struct pipe_query; - -namespace clover { - class command_queue; - - namespace timestamp { - /// - /// Emit a timestamp query that is executed asynchronously by - /// the command queue \a q. - /// - class query { - public: - query(command_queue &q); - query(query &&other); - ~query(); - - query &operator=(const query &) = delete; - - /// - /// Retrieve the query results. - /// - cl_ulong operator()() const; - - private: - const intrusive_ref q; - pipe_query *_query; - }; - - /// - /// Get the current timestamp value. - /// - class current { - public: - current(command_queue &q); - - /// - /// Retrieve the query results. - /// - cl_ulong operator()() const; - - private: - cl_ulong result; - }; - } -} - -#endif diff --git a/src/gallium/state_trackers/clover/llvm/codegen.hpp b/src/gallium/state_trackers/clover/llvm/codegen.hpp deleted file mode 100644 index e35627c4729..00000000000 --- a/src/gallium/state_trackers/clover/llvm/codegen.hpp +++ /dev/null @@ -1,68 +0,0 @@ -// -// Copyright 2016 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -/// -/// \file -/// Tools to generate various forms of binary code from existing LLVM IR in -/// the given llvm::Module object and output the result as a clover::module. -/// - -#ifndef CLOVER_LLVM_CODEGEN_HPP -#define CLOVER_LLVM_CODEGEN_HPP - -#include "llvm/util.hpp" -#include "core/module.hpp" - -#include - -#include - -namespace clover { - namespace llvm { - std::string - print_module_bitcode(const ::llvm::Module &mod); - - module - build_module_library(const ::llvm::Module &mod, - enum module::section::type section_type); - - std::unique_ptr< ::llvm::Module> - parse_module_library(const module &m, ::llvm::LLVMContext &ctx, - std::string &r_log); - - module - build_module_native(::llvm::Module &mod, const target &target, - const clang::CompilerInstance &c, - std::string &r_log); - - std::string - print_module_native(const ::llvm::Module &mod, const target &target); - - module - build_module_common(const ::llvm::Module &mod, - const std::vector &code, - const std::map &offsets, - const clang::CompilerInstance &c); - } -} - -#endif diff --git a/src/gallium/state_trackers/clover/llvm/codegen/bitcode.cpp b/src/gallium/state_trackers/clover/llvm/codegen/bitcode.cpp deleted file mode 100644 index 7434e8cf6c9..00000000000 --- a/src/gallium/state_trackers/clover/llvm/codegen/bitcode.cpp +++ /dev/null @@ -1,91 +0,0 @@ -// -// Copyright 2012-2016 Francisco Jerez -// Copyright 2012-2016 Advanced Micro Devices, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -/// -/// \file -/// Trivial codegen back-end that simply passes through the existing LLVM IR -/// and either formats it so it can be consumed by pipe drivers (if -/// build_module_bitcode() is used) or serializes so it can be deserialized at -/// a later point and passed to the actual codegen back-end (if -/// build_module_library() / parse_module_library() is used), potentially -/// after linking against other bitcode object files. -/// - -#include "llvm/codegen.hpp" -#include "llvm/compat.hpp" -#include "llvm/metadata.hpp" -#include "core/error.hpp" -#include "util/algorithm.hpp" - -#include -#include -#if LLVM_VERSION_MAJOR < 4 -#include -#else -#include -#include -#endif -#include - -using namespace clover; -using namespace clover::llvm; - -namespace { - std::vector - emit_code(const ::llvm::Module &mod) { - ::llvm::SmallVector data; - ::llvm::raw_svector_ostream os { data }; - compat::write_bitcode_to_file(mod, os); - return { os.str().begin(), os.str().end() }; - } -} - -std::string -clover::llvm::print_module_bitcode(const ::llvm::Module &mod) { - std::string s; - ::llvm::raw_string_ostream os { s }; - mod.print(os, NULL); - return os.str(); -} - -module -clover::llvm::build_module_library(const ::llvm::Module &mod, - enum module::section::type section_type) { - module m; - const auto code = emit_code(mod); - m.secs.emplace_back(0, section_type, code.size(), code); - return m; -} - -std::unique_ptr< ::llvm::Module> -clover::llvm::parse_module_library(const module &m, ::llvm::LLVMContext &ctx, - std::string &r_log) { - auto mod = ::llvm::parseBitcodeFile(::llvm::MemoryBufferRef( - as_string(m.secs[0].data), " "), ctx); - - compat::handle_module_error(mod, [&](const std::string &s) { - fail(r_log, error(CL_INVALID_PROGRAM), s); - }); - - return std::unique_ptr< ::llvm::Module>(std::move(*mod)); -} diff --git a/src/gallium/state_trackers/clover/llvm/codegen/common.cpp b/src/gallium/state_trackers/clover/llvm/codegen/common.cpp deleted file mode 100644 index 730ba5a2ff7..00000000000 --- a/src/gallium/state_trackers/clover/llvm/codegen/common.cpp +++ /dev/null @@ -1,209 +0,0 @@ -// -// Copyright 2012-2016 Francisco Jerez -// Copyright 2012-2016 Advanced Micro Devices, Inc. -// Copyright 2015 Zoltan Gilian -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -/// -/// \file -/// Codegen back-end-independent part of the construction of an executable -/// clover::module, including kernel argument metadata extraction and -/// formatting of the pre-generated binary code in a form that can be -/// understood by pipe drivers. -/// - -#include "llvm/codegen.hpp" -#include "llvm/metadata.hpp" - -#include "CL/cl.h" - -#include "pipe/p_state.h" -#include "util/u_math.h" - -#include - -using namespace clover; -using namespace clover::llvm; - -using ::llvm::Module; -using ::llvm::Function; -using ::llvm::Type; -using ::llvm::isa; -using ::llvm::cast; -using ::llvm::dyn_cast; - -namespace { - enum module::argument::type - get_image_type(const std::string &type, - const std::string &qual) { - if (type == "image2d_t" && qual == "read_only") - return module::argument::image2d_rd; - else if (type == "image2d_t" && qual == "write_only") - return module::argument::image2d_wr; - else if (type == "image3d_t" && qual == "read_only") - return module::argument::image3d_rd; - else if (type == "image3d_t" && qual == "write_only") - return module::argument::image3d_wr; - else - unreachable("Unknown image type"); - } - - std::vector - make_kernel_args(const Module &mod, const std::string &kernel_name, - const clang::CompilerInstance &c) { - std::vector args; - const Function &f = *mod.getFunction(kernel_name); - ::llvm::DataLayout dl(&mod); - const auto size_type = - dl.getSmallestLegalIntType(mod.getContext(), sizeof(cl_uint) * 8); - - for (const auto &arg : f.args()) { - const auto arg_type = arg.getType(); - - // OpenCL 1.2 specification, Ch. 6.1.5: "A built-in data - // type that is not a power of two bytes in size must be - // aligned to the next larger power of two. - // This rule applies to built-in types only, not structs or unions." - const unsigned arg_store_size = dl.getTypeStoreSize(arg_type); - const unsigned arg_api_size = dl.getTypeAllocSize(arg_type); - - const auto target_type = compat::get_abi_type(arg_type, mod); - const unsigned target_size = dl.getTypeStoreSize(target_type); - const unsigned target_align = dl.getABITypeAlignment(target_type); - - const auto type_name = get_argument_metadata(f, arg, - "kernel_arg_type"); - - if (type_name == "image2d_t" || type_name == "image3d_t") { - // Image. - const auto access_qual = get_argument_metadata( - f, arg, "kernel_arg_access_qual"); - args.emplace_back(get_image_type(type_name, access_qual), - arg_store_size, target_size, - target_align, module::argument::zero_ext); - - } else if (type_name == "__llvm_image_size") { - // Image size implicit argument. - args.emplace_back(module::argument::scalar, sizeof(cl_uint), - dl.getTypeStoreSize(size_type), - dl.getABITypeAlignment(size_type), - module::argument::zero_ext, - module::argument::image_size); - - } else if (type_name == "__llvm_image_format") { - // Image format implicit argument. - args.emplace_back(module::argument::scalar, sizeof(cl_uint), - dl.getTypeStoreSize(size_type), - dl.getABITypeAlignment(size_type), - module::argument::zero_ext, - module::argument::image_format); - - } else { - // Other types. - const auto actual_type = - isa< ::llvm::PointerType>(arg_type) && arg.hasByValAttr() ? - cast< ::llvm::PointerType>(arg_type)->getElementType() : arg_type; - - if (actual_type->isPointerTy()) { - const unsigned address_space = - cast< ::llvm::PointerType>(actual_type)->getAddressSpace(); - - if (address_space == compat::target_address_space( - c.getTarget(), clang::LangAS::opencl_local)) { - args.emplace_back(module::argument::local, arg_api_size, - target_size, target_align, - module::argument::zero_ext); - } else { - // XXX: Correctly handle constant address space. There is no - // way for r600g to pass a handle for constant buffers back - // to clover like it can for global buffers, so - // creating constant arguments will break r600g. For now, - // continue treating constant buffers as global buffers - // until we can come up with a way to create handles for - // constant buffers. - args.emplace_back(module::argument::global, arg_api_size, - target_size, target_align, - module::argument::zero_ext); - } - - } else { - const bool needs_sign_ext = f.getAttributes().hasAttribute( - arg.getArgNo() + 1, ::llvm::Attribute::SExt); - - args.emplace_back(module::argument::scalar, arg_api_size, - target_size, target_align, - (needs_sign_ext ? module::argument::sign_ext : - module::argument::zero_ext)); - } - } - } - - // Append implicit arguments. XXX - The types, ordering and - // vector size of the implicit arguments should depend on the - // target according to the selected calling convention. - args.emplace_back(module::argument::scalar, sizeof(cl_uint), - dl.getTypeStoreSize(size_type), - dl.getABITypeAlignment(size_type), - module::argument::zero_ext, - module::argument::grid_dimension); - - args.emplace_back(module::argument::scalar, sizeof(cl_uint), - dl.getTypeStoreSize(size_type), - dl.getABITypeAlignment(size_type), - module::argument::zero_ext, - module::argument::grid_offset); - - return args; - } - - module::section - make_text_section(const std::vector &code) { - const pipe_binary_program_header header { uint32_t(code.size()) }; - module::section text { 0, module::section::text_executable, - header.num_bytes, {} }; - - text.data.insert(text.data.end(), reinterpret_cast(&header), - reinterpret_cast(&header) + sizeof(header)); - text.data.insert(text.data.end(), code.begin(), code.end()); - - return text; - } -} - -module -clover::llvm::build_module_common(const Module &mod, - const std::vector &code, - const std::map &offsets, - const clang::CompilerInstance &c) { - module m; - - for (const auto &llvm_name : map(std::mem_fn(&Function::getName), - get_kernels(mod))) { - const ::std::string name(llvm_name); - if (offsets.count(name)) - m.syms.emplace_back(name, 0, offsets.at(name), - make_kernel_args(mod, name, c)); - } - - m.secs.push_back(make_text_section(code)); - return m; -} diff --git a/src/gallium/state_trackers/clover/llvm/codegen/native.cpp b/src/gallium/state_trackers/clover/llvm/codegen/native.cpp deleted file mode 100644 index 52346131200..00000000000 --- a/src/gallium/state_trackers/clover/llvm/codegen/native.cpp +++ /dev/null @@ -1,163 +0,0 @@ -// -// Copyright 2012-2016 Francisco Jerez -// Copyright 2012-2016 Advanced Micro Devices, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -/// -/// \file -/// Generate code using an arbitrary LLVM back-end capable of emitting -/// executable code as an ELF object file. -/// - -#include "llvm/codegen.hpp" -#include "llvm/compat.hpp" -#include "llvm/util.hpp" -#include "core/error.hpp" - -#include -#include -#include - -#include -#include - -using namespace clover; -using namespace clover::llvm; -using ::llvm::TargetMachine; - -namespace { - namespace elf { - std::unique_ptr - get(const std::vector &code) { - // One of the libelf implementations - // (http://www.mr511.de/software/english.htm) requires calling - // elf_version() before elf_memory(). - elf_version(EV_CURRENT); - return { elf_memory(const_cast(code.data()), code.size()), - elf_end }; - } - - Elf_Scn * - get_symbol_table(Elf *elf) { - size_t section_str_index; - elf_getshdrstrndx(elf, §ion_str_index); - - for (Elf_Scn *s = elf_nextscn(elf, NULL); s; s = elf_nextscn(elf, s)) { - GElf_Shdr header; - if (gelf_getshdr(s, &header) != &header) - return nullptr; - - if (!std::strcmp(elf_strptr(elf, section_str_index, header.sh_name), - ".symtab")) - return s; - } - - return nullptr; - } - - std::map - get_symbol_offsets(Elf *elf, Elf_Scn *symtab) { - Elf_Data *const symtab_data = elf_getdata(symtab, NULL); - GElf_Shdr header; - if (gelf_getshdr(symtab, &header) != &header) - return {}; - - std::map symbol_offsets; - GElf_Sym symbol; - unsigned i = 0; - - while (GElf_Sym *s = gelf_getsym(symtab_data, i++, &symbol)) { - const char *name = elf_strptr(elf, header.sh_link, s->st_name); - symbol_offsets[name] = s->st_value; - } - - return symbol_offsets; - } - } - - std::map - get_symbol_offsets(const std::vector &code, std::string &r_log) { - const auto elf = elf::get(code); - const auto symtab = elf::get_symbol_table(elf.get()); - if (!symtab) - fail(r_log, build_error(), "Unable to find symbol table."); - - return elf::get_symbol_offsets(elf.get(), symtab); - } - - std::vector - emit_code(::llvm::Module &mod, const target &target, - compat::CodeGenFileType ft, - std::string &r_log) { - std::string err; - auto t = ::llvm::TargetRegistry::lookupTarget(target.triple, err); - if (!t) - fail(r_log, build_error(), err); - - std::unique_ptr tm { - t->createTargetMachine(target.triple, target.cpu, "", {}, - ::llvm::None, compat::default_code_model, - ::llvm::CodeGenOpt::Default) }; - if (!tm) - fail(r_log, build_error(), - "Could not create TargetMachine: " + target.triple); - - ::llvm::SmallVector data; - - { - ::llvm::legacy::PassManager pm; - ::llvm::raw_svector_ostream os { data }; - - mod.setDataLayout(tm->createDataLayout()); - tm->Options.MCOptions.AsmVerbose = - (ft == compat::CGFT_AssemblyFile); - - if (compat::add_passes_to_emit_file(*tm, pm, os, ft)) - fail(r_log, build_error(), "TargetMachine can't emit this file"); - - pm.run(mod); - } - - return { data.begin(), data.end() }; - } -} - -module -clover::llvm::build_module_native(::llvm::Module &mod, const target &target, - const clang::CompilerInstance &c, - std::string &r_log) { - const auto code = emit_code(mod, target, - compat::CGFT_ObjectFile, r_log); - return build_module_common(mod, code, get_symbol_offsets(code, r_log), c); -} - -std::string -clover::llvm::print_module_native(const ::llvm::Module &mod, - const target &target) { - std::string log; - try { - std::unique_ptr< ::llvm::Module> cmod { compat::clone_module(mod) }; - return as_string(emit_code(*cmod, target, - compat::CGFT_AssemblyFile, log)); - } catch (...) { - return "Couldn't output native disassembly: " + log; - } -} diff --git a/src/gallium/state_trackers/clover/llvm/compat.hpp b/src/gallium/state_trackers/clover/llvm/compat.hpp deleted file mode 100644 index 51902739acc..00000000000 --- a/src/gallium/state_trackers/clover/llvm/compat.hpp +++ /dev/null @@ -1,216 +0,0 @@ -// -// Copyright 2016 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -/// -/// \file -/// Some thin wrappers around the Clang/LLVM API used to preserve -/// compatibility with older API versions while keeping the ifdef clutter low -/// in the rest of the clover::llvm subtree. In case of an API break please -/// consider whether it's possible to preserve backwards compatibility by -/// introducing a new one-liner inline function or typedef here under the -/// compat namespace in order to keep the running code free from preprocessor -/// conditionals. -/// - -#ifndef CLOVER_LLVM_COMPAT_HPP -#define CLOVER_LLVM_COMPAT_HPP - -#include "util/algorithm.hpp" - -#include -#if LLVM_VERSION_MAJOR < 4 -#include -#else -#include -#include -#endif - -#include -#include -#include -#include -#include -#if LLVM_VERSION_MAJOR >= 4 -#include -#else -#include -#endif - -#include -#include - -#include -#include - -#if LLVM_VERSION_MAJOR >= 8 -#include -#else -#include -#endif - -#if LLVM_VERSION_MAJOR >= 10 -#include -#endif - -namespace clover { - namespace llvm { - namespace compat { - -#if LLVM_VERSION_MAJOR >= 10 - const auto CGFT_ObjectFile = ::llvm::CGFT_ObjectFile; - const auto CGFT_AssemblyFile = ::llvm::CGFT_AssemblyFile; - typedef ::llvm::CodeGenFileType CodeGenFileType; -#else - const auto CGFT_ObjectFile = ::llvm::TargetMachine::CGFT_ObjectFile; - const auto CGFT_AssemblyFile = - ::llvm::TargetMachine::CGFT_AssemblyFile; - typedef ::llvm::TargetMachine::CodeGenFileType CodeGenFileType; -#endif - - template - unsigned target_address_space(const T &target, const AS lang_as) { - const auto &map = target.getAddressSpaceMap(); -#if LLVM_VERSION_MAJOR >= 5 - return map[static_cast(lang_as)]; -#else - return map[lang_as - clang::LangAS::Offset]; -#endif - } - -#if LLVM_VERSION_MAJOR >= 10 - const clang::InputKind ik_opencl = clang::Language::OpenCL; -#elif LLVM_VERSION_MAJOR >= 5 - const clang::InputKind ik_opencl = clang::InputKind::OpenCL; -#else - const clang::InputKind ik_opencl = clang::IK_OpenCL; -#endif - -#if LLVM_VERSION_MAJOR >= 5 - const clang::LangStandard::Kind lang_opencl10 = clang::LangStandard::lang_opencl10; -#else - const clang::LangStandard::Kind lang_opencl10 = clang::LangStandard::lang_opencl; -#endif - - inline void - add_link_bitcode_file(clang::CodeGenOptions &opts, - const std::string &path) { -#if LLVM_VERSION_MAJOR >= 5 - clang::CodeGenOptions::BitcodeFileToLink F; - - F.Filename = path; - F.PropagateAttrs = true; - F.LinkFlags = ::llvm::Linker::Flags::None; - opts.LinkBitcodeFiles.emplace_back(F); -#else - opts.LinkBitcodeFiles.emplace_back(::llvm::Linker::Flags::None, path); -#endif - } - -#if LLVM_VERSION_MAJOR >= 6 - const auto default_code_model = ::llvm::None; -#else - const auto default_code_model = ::llvm::CodeModel::Default; -#endif - - template void - handle_module_error(M &mod, const F &f) { -#if LLVM_VERSION_MAJOR >= 4 - if (::llvm::Error err = mod.takeError()) - ::llvm::handleAllErrors(std::move(err), [&](::llvm::ErrorInfoBase &eib) { - f(eib.message()); - }); -#else - if (!mod) - f(mod.getError().message()); -#endif - } - - template void - set_diagnostic_handler(::llvm::LLVMContext &ctx, - T *diagnostic_handler, void *data) { -#if LLVM_VERSION_MAJOR >= 6 - ctx.setDiagnosticHandlerCallBack(diagnostic_handler, data); -#else - ctx.setDiagnosticHandler(diagnostic_handler, data); -#endif - } - - inline std::unique_ptr< ::llvm::Module> - clone_module(const ::llvm::Module &mod) - { -#if LLVM_VERSION_MAJOR >= 7 - return ::llvm::CloneModule(mod); -#else - return ::llvm::CloneModule(&mod); -#endif - } - - template void - write_bitcode_to_file(const ::llvm::Module &mod, T &os) - { -#if LLVM_VERSION_MAJOR >= 7 - ::llvm::WriteBitcodeToFile(mod, os); -#else - ::llvm::WriteBitcodeToFile(&mod, os); -#endif - } - - template - bool add_passes_to_emit_file(TM &tm, PM &pm, OS &os, FT &ft) - { -#if LLVM_VERSION_MAJOR >= 7 - return tm.addPassesToEmitFile(pm, os, nullptr, ft); -#else - return tm.addPassesToEmitFile(pm, os, ft); -#endif - } - - template inline bool - create_compiler_invocation_from_args(clang::CompilerInvocation &cinv, - T copts, - clang::DiagnosticsEngine &diag) - { -#if LLVM_VERSION_MAJOR >= 10 - return clang::CompilerInvocation::CreateFromArgs( - cinv, copts, diag); -#else - return clang::CompilerInvocation::CreateFromArgs( - cinv, copts.data(), copts.data() + copts.size(), diag); -#endif - } - - template - T get_abi_type(const T &arg_type, const M &mod) { -#if LLVM_VERSION_MAJOR >= 7 - return arg_type; -#else - ::llvm::DataLayout dl(&mod); - const unsigned arg_store_size = dl.getTypeStoreSize(arg_type); - return !arg_type->isIntegerTy() ? arg_type : - dl.getSmallestLegalIntType(mod.getContext(), arg_store_size * 8); -#endif - } - } - } -} - -#endif diff --git a/src/gallium/state_trackers/clover/llvm/invocation.cpp b/src/gallium/state_trackers/clover/llvm/invocation.cpp deleted file mode 100644 index 95a9d036622..00000000000 --- a/src/gallium/state_trackers/clover/llvm/invocation.cpp +++ /dev/null @@ -1,465 +0,0 @@ -// -// Copyright 2012-2016 Francisco Jerez -// Copyright 2012-2016 Advanced Micro Devices, Inc. -// Copyright 2014-2016 Jan Vesely -// Copyright 2014-2015 Serge Martin -// Copyright 2015 Zoltan Gilian -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#include -#include -#include -#include -#include -#include -#ifdef HAVE_CLOVER_SPIRV -#include -#endif - -#include -#include -#include -#include -#include - -// We need to include internal headers last, because the internal headers -// include CL headers which have #define's like: -// -//#define cl_khr_gl_sharing 1 -//#define cl_khr_icd 1 -// -// Which will break the compilation of clang/Basic/OpenCLOptions.h - -#include "core/error.hpp" -#include "llvm/codegen.hpp" -#include "llvm/compat.hpp" -#include "llvm/invocation.hpp" -#include "llvm/metadata.hpp" -#include "llvm/util.hpp" -#ifdef HAVE_CLOVER_SPIRV -#include "spirv/invocation.hpp" -#endif -#include "util/algorithm.hpp" - - -using namespace clover; -using namespace clover::llvm; - -using ::llvm::Function; -using ::llvm::LLVMContext; -using ::llvm::Module; -using ::llvm::raw_string_ostream; - -namespace { - - struct cl_version { - std::string version_str; // CL Version - unsigned version_number; // Numeric CL Version - }; - - static const unsigned ANY_VERSION = 999; - const cl_version cl_versions[] = { - { "1.0", 100}, - { "1.1", 110}, - { "1.2", 120}, - { "2.0", 200}, - { "2.1", 210}, - { "2.2", 220}, - }; - - struct clc_version_lang_std { - unsigned version_number; // CLC Version - clang::LangStandard::Kind clc_lang_standard; - }; - - const clc_version_lang_std cl_version_lang_stds[] = { - { 100, compat::lang_opencl10}, - { 110, clang::LangStandard::lang_opencl11}, - { 120, clang::LangStandard::lang_opencl12}, - { 200, clang::LangStandard::lang_opencl20}, - }; - - void - init_targets() { - static bool targets_initialized = false; - if (!targets_initialized) { - LLVMInitializeAllTargets(); - LLVMInitializeAllTargetInfos(); - LLVMInitializeAllTargetMCs(); - LLVMInitializeAllAsmParsers(); - LLVMInitializeAllAsmPrinters(); - targets_initialized = true; - } - } - - void - diagnostic_handler(const ::llvm::DiagnosticInfo &di, void *data) { - if (di.getSeverity() == ::llvm::DS_Error) { - raw_string_ostream os { *reinterpret_cast(data) }; - ::llvm::DiagnosticPrinterRawOStream printer { os }; - di.print(printer); - throw build_error(); - } - } - - std::unique_ptr - create_context(std::string &r_log) { - init_targets(); - std::unique_ptr ctx { new LLVMContext }; - compat::set_diagnostic_handler(*ctx, diagnostic_handler, &r_log); - return ctx; - } - - const struct clc_version_lang_std& - get_cl_lang_standard(unsigned requested, unsigned max = ANY_VERSION) { - for (const struct clc_version_lang_std &version : cl_version_lang_stds) { - if (version.version_number == max || - version.version_number == requested) { - return version; - } - } - throw build_error("Unknown/Unsupported language version"); - } - - const struct cl_version& - get_cl_version(const std::string &version_str, - unsigned max = ANY_VERSION) { - for (const struct cl_version &version : cl_versions) { - if (version.version_number == max || version.version_str == version_str) { - return version; - } - } - throw build_error("Unknown/Unsupported language version"); - } - - clang::LangStandard::Kind - get_lang_standard_from_version_str(const std::string &version_str, - bool is_build_opt = false) { - - //Per CL 2.0 spec, section 5.8.4.5: - // If it's an option, use the value directly. - // If it's a device version, clamp to max 1.x version, a.k.a. 1.2 - const cl_version version = - get_cl_version(version_str, is_build_opt ? ANY_VERSION : 120); - - const struct clc_version_lang_std standard = - get_cl_lang_standard(version.version_number); - - return standard.clc_lang_standard; - } - - clang::LangStandard::Kind - get_language_version(const std::vector &opts, - const std::string &device_version) { - - const std::string search = "-cl-std=CL"; - - for (auto &opt: opts) { - auto pos = opt.find(search); - if (pos == 0){ - const auto ver = opt.substr(pos + search.size()); - const auto device_ver = get_cl_version(device_version); - const auto requested = get_cl_version(ver); - if (requested.version_number > device_ver.version_number) { - throw build_error(); - } - return get_lang_standard_from_version_str(ver, true); - } - } - - return get_lang_standard_from_version_str(device_version); - } - - std::unique_ptr - create_compiler_instance(const device &dev, const std::string& ir_target, - const std::vector &opts, - std::string &r_log) { - std::unique_ptr c { new clang::CompilerInstance }; - clang::TextDiagnosticBuffer *diag_buffer = new clang::TextDiagnosticBuffer; - clang::DiagnosticsEngine diag { new clang::DiagnosticIDs, - new clang::DiagnosticOptions, diag_buffer }; - - // Parse the compiler options. A file name should be present at the end - // and must have the .cl extension in order for the CompilerInvocation - // class to recognize it as an OpenCL source file. - const std::vector copts = - map(std::mem_fn(&std::string::c_str), opts); - - const target &target = ir_target; - const std::string &device_clc_version = dev.device_clc_version(); - - if (!compat::create_compiler_invocation_from_args( - c->getInvocation(), copts, diag)) - throw invalid_build_options_error(); - - diag_buffer->FlushDiagnostics(diag); - if (diag.hasErrorOccurred()) - throw invalid_build_options_error(); - - c->getTargetOpts().CPU = target.cpu; - c->getTargetOpts().Triple = target.triple; - c->getLangOpts().NoBuiltin = true; - - // This is a workaround for a Clang bug which causes the number - // of warnings and errors to be printed to stderr. - // http://www.llvm.org/bugs/show_bug.cgi?id=19735 - c->getDiagnosticOpts().ShowCarets = false; - - c->getInvocation().setLangDefaults(c->getLangOpts(), - compat::ik_opencl, ::llvm::Triple(target.triple), - c->getPreprocessorOpts(), - get_language_version(opts, device_clc_version)); - - c->createDiagnostics(new clang::TextDiagnosticPrinter( - *new raw_string_ostream(r_log), - &c->getDiagnosticOpts(), true)); - - c->setTarget(clang::TargetInfo::CreateTargetInfo( - c->getDiagnostics(), c->getInvocation().TargetOpts)); - - return c; - } - - std::unique_ptr - compile(LLVMContext &ctx, clang::CompilerInstance &c, - const std::string &name, const std::string &source, - const header_map &headers, const device &dev, - const std::string &opts, bool use_libclc, std::string &r_log) { - c.getFrontendOpts().ProgramAction = clang::frontend::EmitLLVMOnly; - c.getHeaderSearchOpts().UseBuiltinIncludes = true; - c.getHeaderSearchOpts().UseStandardSystemIncludes = true; - c.getHeaderSearchOpts().ResourceDir = CLANG_RESOURCE_DIR; - - if (use_libclc) { - // Add libclc generic search path - c.getHeaderSearchOpts().AddPath(LIBCLC_INCLUDEDIR, - clang::frontend::Angled, - false, false); - - // Add libclc include - c.getPreprocessorOpts().Includes.push_back("clc/clc.h"); - } else { - // Add opencl-c generic search path - c.getHeaderSearchOpts().AddPath(CLANG_RESOURCE_DIR, - clang::frontend::Angled, - false, false); - - // Add opencl include - c.getPreprocessorOpts().Includes.push_back("opencl-c.h"); - } - - // Add definition for the OpenCL version - c.getPreprocessorOpts().addMacroDef("__OPENCL_VERSION__=" + - std::to_string(get_cl_version( - dev.device_version()).version_number)); - - // clc.h requires that this macro be defined: - c.getPreprocessorOpts().addMacroDef("cl_clang_storage_class_specifiers"); - c.getPreprocessorOpts().addRemappedFile( - name, ::llvm::MemoryBuffer::getMemBuffer(source).release()); - - if (headers.size()) { - const std::string tmp_header_path = "/tmp/clover/"; - - c.getHeaderSearchOpts().AddPath(tmp_header_path, - clang::frontend::Angled, - false, false); - - for (const auto &header : headers) - c.getPreprocessorOpts().addRemappedFile( - tmp_header_path + header.first, - ::llvm::MemoryBuffer::getMemBuffer(header.second).release()); - } - - // Tell clang to link this file before performing any - // optimizations. This is required so that we can replace calls - // to the OpenCL C barrier() builtin with calls to target - // intrinsics that have the noduplicate attribute. This - // attribute will prevent Clang from creating illegal uses of - // barrier() (e.g. Moving barrier() inside a conditional that is - // no executed by all threads) during its optimizaton passes. - if (use_libclc) - compat::add_link_bitcode_file(c.getCodeGenOpts(), - LIBCLC_LIBEXECDIR + dev.ir_target() + ".bc"); - - // Compile the code - clang::EmitLLVMOnlyAction act(&ctx); - if (!c.ExecuteAction(act)) - throw build_error(); - - return act.takeModule(); - } -} - -module -clover::llvm::compile_program(const std::string &source, - const header_map &headers, - const device &dev, - const std::string &opts, - std::string &r_log) { - if (has_flag(debug::clc)) - debug::log(".cl", "// Options: " + opts + '\n' + source); - - auto ctx = create_context(r_log); - auto c = create_compiler_instance(dev, dev.ir_target(), - tokenize(opts + " input.cl"), r_log); - auto mod = compile(*ctx, *c, "input.cl", source, headers, dev, opts, true, - r_log); - - if (has_flag(debug::llvm)) - debug::log(".ll", print_module_bitcode(*mod)); - - return build_module_library(*mod, module::section::text_intermediate); -} - -namespace { - void - optimize(Module &mod, unsigned optimization_level, - bool internalize_symbols) { - ::llvm::legacy::PassManager pm; - - // By default, the function internalizer pass will look for a function - // called "main" and then mark all other functions as internal. Marking - // functions as internal enables the optimizer to perform optimizations - // like function inlining and global dead-code elimination. - // - // When there is no "main" function in a module, the internalize pass will - // treat the module like a library, and it won't internalize any functions. - // Since there is no "main" function in our kernels, we need to tell - // the internalizer pass that this module is not a library by passing a - // list of kernel functions to the internalizer. The internalizer will - // treat the functions in the list as "main" functions and internalize - // all of the other functions. - if (internalize_symbols) { - std::vector names = - map(std::mem_fn(&Function::getName), get_kernels(mod)); - pm.add(::llvm::createInternalizePass( - [=](const ::llvm::GlobalValue &gv) { - return std::find(names.begin(), names.end(), - gv.getName()) != names.end(); - })); - } - - ::llvm::PassManagerBuilder pmb; - pmb.OptLevel = optimization_level; - pmb.LibraryInfo = new ::llvm::TargetLibraryInfoImpl( - ::llvm::Triple(mod.getTargetTriple())); - pmb.populateModulePassManager(pm); - pm.run(mod); - } - - std::unique_ptr - link(LLVMContext &ctx, const clang::CompilerInstance &c, - const std::vector &modules, std::string &r_log) { - std::unique_ptr mod { new Module("link", ctx) }; - std::unique_ptr< ::llvm::Linker> linker { new ::llvm::Linker(*mod) }; - - for (auto &m : modules) { - if (linker->linkInModule(parse_module_library(m, ctx, r_log))) - throw build_error(); - } - - return mod; - } -} - -module -clover::llvm::link_program(const std::vector &modules, - const device &dev, const std::string &opts, - std::string &r_log) { - std::vector options = tokenize(opts + " input.cl"); - const bool create_library = count("-create-library", options); - erase_if(equals("-create-library"), options); - - auto ctx = create_context(r_log); - auto c = create_compiler_instance(dev, dev.ir_target(), options, r_log); - auto mod = link(*ctx, *c, modules, r_log); - - optimize(*mod, c->getCodeGenOpts().OptimizationLevel, !create_library); - - static std::atomic_uint seq(0); - const std::string id = "." + mod->getModuleIdentifier() + "-" + - std::to_string(seq++); - - if (has_flag(debug::llvm)) - debug::log(id + ".ll", print_module_bitcode(*mod)); - - if (create_library) { - return build_module_library(*mod, module::section::text_library); - - } else if (dev.ir_format() == PIPE_SHADER_IR_NATIVE) { - if (has_flag(debug::native)) - debug::log(id + ".asm", print_module_native(*mod, dev.ir_target())); - - return build_module_native(*mod, dev.ir_target(), *c, r_log); - - } else { - unreachable("Unsupported IR."); - } -} - -#ifdef HAVE_CLOVER_SPIRV -module -clover::llvm::compile_to_spirv(const std::string &source, - const header_map &headers, - const device &dev, - const std::string &opts, - std::string &r_log) { - if (has_flag(debug::clc)) - debug::log(".cl", "// Options: " + opts + '\n' + source); - - auto ctx = create_context(r_log); - const std::string target = dev.address_bits() == 32u ? - "-spir-unknown-unknown" : - "-spir64-unknown-unknown"; - auto c = create_compiler_instance(dev, target, - tokenize(opts + " input.cl"), r_log); - auto mod = compile(*ctx, *c, "input.cl", source, headers, dev, opts, false, - r_log); - - if (has_flag(debug::llvm)) - debug::log(".ll", print_module_bitcode(*mod)); - - std::string error_msg; - if (!::llvm::regularizeLlvmForSpirv(mod.get(), error_msg)) { - r_log += "Failed to regularize LLVM IR for SPIR-V: " + error_msg + ".\n"; - throw error(CL_INVALID_VALUE); - } - - std::ostringstream os; - if (!::llvm::writeSpirv(mod.get(), os, error_msg)) { - r_log += "Translation from LLVM IR to SPIR-V failed: " + error_msg + ".\n"; - throw error(CL_INVALID_VALUE); - } - - const std::string osContent = os.str(); - std::vector binary(osContent.begin(), osContent.end()); - if (binary.empty()) { - r_log += "Failed to retrieve SPIR-V binary.\n"; - throw error(CL_INVALID_VALUE); - } - - if (has_flag(debug::spirv)) - debug::log(".spvasm", spirv::print_module(binary, dev.device_version())); - - return spirv::compile_program(binary, dev, r_log); -} -#endif diff --git a/src/gallium/state_trackers/clover/llvm/invocation.hpp b/src/gallium/state_trackers/clover/llvm/invocation.hpp deleted file mode 100644 index 1f0e9db2cf7..00000000000 --- a/src/gallium/state_trackers/clover/llvm/invocation.hpp +++ /dev/null @@ -1,54 +0,0 @@ -// -// Copyright 2016 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#ifndef CLOVER_LLVM_INVOCATION_HPP -#define CLOVER_LLVM_INVOCATION_HPP - -#include "core/error.hpp" -#include "core/module.hpp" -#include "core/program.hpp" -#include "pipe/p_defines.h" - -namespace clover { - namespace llvm { - module compile_program(const std::string &source, - const header_map &headers, - const device &device, - const std::string &opts, - std::string &r_log); - - module link_program(const std::vector &modules, - const device &device, - const std::string &opts, - std::string &r_log); - -#ifdef HAVE_CLOVER_SPIRV - module compile_to_spirv(const std::string &source, - const header_map &headers, - const device &dev, - const std::string &opts, - std::string &r_log); -#endif - } -} - -#endif diff --git a/src/gallium/state_trackers/clover/llvm/metadata.hpp b/src/gallium/state_trackers/clover/llvm/metadata.hpp deleted file mode 100644 index 58042f4b4da..00000000000 --- a/src/gallium/state_trackers/clover/llvm/metadata.hpp +++ /dev/null @@ -1,86 +0,0 @@ -// -// Copyright 2016 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -/// -/// \file -/// Utility functions for LLVM IR metadata introspection. -/// - -#ifndef CLOVER_LLVM_METADATA_HPP -#define CLOVER_LLVM_METADATA_HPP - -#include "llvm/compat.hpp" -#include "util/algorithm.hpp" - -#include -#include -#include -#include - -namespace clover { - namespace llvm { - namespace detail { - inline bool - is_kernel(const ::llvm::Function &f) { - return f.getMetadata("kernel_arg_type"); - } - - inline iterator_range< ::llvm::MDNode::op_iterator> - get_kernel_metadata_operands(const ::llvm::Function &f, - const std::string &name) { - const auto data_node = f.getMetadata(name); - return range(data_node->op_begin(), data_node->op_end()); - } - } - - /// - /// Extract the string metadata node \p name corresponding to the kernel - /// argument given by \p arg. - /// - inline std::string - get_argument_metadata(const ::llvm::Function &f, - const ::llvm::Argument &arg, - const std::string &name) { - return ::llvm::cast< ::llvm::MDString>( - detail::get_kernel_metadata_operands(f, name)[arg.getArgNo()]) - ->getString().str(); - } - - /// - /// Return a vector with all CL kernel functions found in the LLVM - /// module \p mod. - /// - inline std::vector - get_kernels(const ::llvm::Module &mod) { - std::vector fs; - - for (auto &f : mod.getFunctionList()) { - if (detail::is_kernel(f)) - fs.push_back(&f); - } - - return fs; - } - } -} - -#endif diff --git a/src/gallium/state_trackers/clover/llvm/util.hpp b/src/gallium/state_trackers/clover/llvm/util.hpp deleted file mode 100644 index 02e73e65071..00000000000 --- a/src/gallium/state_trackers/clover/llvm/util.hpp +++ /dev/null @@ -1,137 +0,0 @@ -// -// Copyright 2012-2016 Francisco Jerez -// Copyright 2012-2016 Advanced Micro Devices, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#ifndef CLOVER_LLVM_UTIL_HPP -#define CLOVER_LLVM_UTIL_HPP - -#include "core/error.hpp" -#include "util/u_debug.h" - -#include -#include -#include -#include - -namespace clover { - namespace llvm { - template void - fail(std::string &r_log, E &&e, const std::string &s) { - r_log += s; - throw e; - } - - inline std::vector - tokenize(const std::string &s) { - std::vector ss; - std::ostringstream oss; - - // OpenCL programs can pass a quoted argument, most frequently the - // include path. This is useful so that path containing spaces is - // treated as a single argument instead of being split by the spaces. - // Additionally, the argument should also be unquoted before being - // passed to the compiler. We avoid using std::string::replace here to - // remove quotes, as the single and double quote characters can be a - // part of the file name. - bool escape_next = false; - bool in_quote_double = false; - bool in_quote_single = false; - - for (auto c : s) { - if (escape_next) { - oss.put(c); - escape_next = false; - } else if (c == '\\') { - escape_next = true; - } else if (c == '"' && !in_quote_single) { - in_quote_double = !in_quote_double; - } else if (c == '\'' && !in_quote_double) { - in_quote_single = !in_quote_single; - } else if (c != ' ' || in_quote_single || in_quote_double) { - oss.put(c); - } else if (oss.tellp() > 0) { - ss.emplace_back(oss.str()); - oss.str(""); - } - } - - if (oss.tellp() > 0) - ss.emplace_back(oss.str()); - - if (in_quote_double || in_quote_single) - throw invalid_build_options_error(); - - return ss; - } - - inline std::string - as_string(const std::vector &v) { - return { v.begin(), v.end() }; - } - - struct target { - target(const std::string &s) : - cpu(s.begin(), s.begin() + s.find_first_of("-")), - triple(s.begin() + s.find_first_of("-") + 1, s.end()) {} - - std::string cpu; - std::string triple; - }; - - namespace debug { - enum flag { - clc = 1 << 0, - llvm = 1 << 1, - native = 1 << 2, - spirv = 1 << 3, - }; - - inline bool - has_flag(flag f) { - static const struct debug_named_value debug_options[] = { - { "clc", clc, "Dump the OpenCL C code for all kernels." }, - { "llvm", llvm, "Dump the generated LLVM IR for all kernels." }, - { "native", native, "Dump kernel assembly code for targets " - "specifying PIPE_SHADER_IR_NATIVE" }, - { "spirv", spirv, "Dump the generated SPIR-V for all kernels." }, - DEBUG_NAMED_VALUE_END - }; - static const unsigned flags = - debug_get_flags_option("CLOVER_DEBUG", debug_options, 0); - - return flags & f; - } - - inline void - log(const std::string &suffix, const std::string &s) { - const std::string path = debug_get_option("CLOVER_DEBUG_FILE", - "stderr"); - if (path == "stderr") - std::cerr << s; - else - std::ofstream(path + suffix, std::ios::app) << s; - } - } - } -} - -#endif diff --git a/src/gallium/state_trackers/clover/meson.build b/src/gallium/state_trackers/clover/meson.build deleted file mode 100644 index 7606a6beaf6..00000000000 --- a/src/gallium/state_trackers/clover/meson.build +++ /dev/null @@ -1,164 +0,0 @@ -# Copyright © 2017-2018 Intel Corporation - -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: - -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. - -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -clover_cpp_args = [] -clover_opencl_cpp_args = [ - '-DCL_TARGET_OPENCL_VERSION=220', - '-DCL_USE_DEPRECATED_OPENCL_1_0_APIS', - '-DCL_USE_DEPRECATED_OPENCL_1_1_APIS', - '-DCL_USE_DEPRECATED_OPENCL_1_2_APIS', - '-DCL_USE_DEPRECATED_OPENCL_2_0_APIS', - '-DCL_USE_DEPRECATED_OPENCL_2_1_APIS' -] -clover_spirv_cpp_args = [] -clover_incs = [inc_include, inc_src, inc_gallium, inc_gallium_aux] - -# the CL header files declare attributes on the CL types. Compilers warn if -# we use them as template arguments. Disable the warning as there isn't -# anything we can do about it -if cpp.has_argument('-Wno-ignored-attributes') - clover_cpp_args += '-Wno-ignored-attributes' -endif - -if with_opencl_icd - clover_cpp_args += '-DHAVE_CLOVER_ICD' -endif - -if with_opencl_spirv - clover_spirv_cpp_args += '-DHAVE_CLOVER_SPIRV' -endif - -libclllvm = static_library( - 'clllvm', - files( - 'llvm/codegen/bitcode.cpp', - 'llvm/codegen/common.cpp', - 'llvm/codegen/native.cpp', - 'llvm/codegen.hpp', - 'llvm/compat.hpp', - 'llvm/invocation.cpp', - 'llvm/invocation.hpp', - 'llvm/metadata.hpp', - 'llvm/util.hpp', - ), - include_directories : clover_incs, - cpp_args : [ - clover_cpp_args, - clover_opencl_cpp_args, - clover_spirv_cpp_args, - cpp_vis_args, - '-DLIBCLC_INCLUDEDIR="@0@/"'.format(dep_clc.get_pkgconfig_variable('includedir')), - '-DLIBCLC_LIBEXECDIR="@0@/"'.format(dep_clc.get_pkgconfig_variable('libexecdir')), - '-DCLANG_RESOURCE_DIR="@0@"'.format(join_paths( - dep_llvm.get_configtool_variable('libdir'), 'clang', - dep_llvm.version(), 'include', - )), - ], - dependencies : [dep_llvm, dep_elf, dep_llvmspirvlib], - override_options : clover_cpp_std, -) - -libclspirv = static_library( - 'clspirv', - files('spirv/invocation.cpp', 'spirv/invocation.hpp'), - include_directories : clover_incs, - cpp_args : [clover_opencl_cpp_args, clover_spirv_cpp_args, cpp_vis_args], - dependencies : [dep_spirv_tools], - override_options : clover_cpp_std, -) - -libclnir = static_library( - 'clnir', - files('nir/invocation.cpp', 'nir/invocation.hpp'), - include_directories : [clover_incs, inc_mesa], - dependencies : idep_nir, - cpp_args : [clover_opencl_cpp_args, clover_spirv_cpp_args, cpp_vis_args], - override_options : clover_cpp_std, -) - -clover_files = files( - 'api/context.cpp', - 'api/device.cpp', - 'api/dispatch.cpp', - 'api/dispatch.hpp', - 'api/event.cpp', - 'api/interop.cpp', - 'api/kernel.cpp', - 'api/memory.cpp', - 'api/platform.cpp', - 'api/program.cpp', - 'api/queue.cpp', - 'api/sampler.cpp', - 'api/transfer.cpp', - 'api/util.hpp', - 'core/compiler.hpp', - 'core/context.cpp', - 'core/context.hpp', - 'core/device.cpp', - 'core/device.hpp', - 'core/error.hpp', - 'core/event.cpp', - 'core/event.hpp', - 'core/format.cpp', - 'core/format.hpp', - 'core/kernel.cpp', - 'core/kernel.hpp', - 'core/memory.cpp', - 'core/memory.hpp', - 'core/module.cpp', - 'core/module.hpp', - 'core/object.hpp', - 'core/platform.cpp', - 'core/platform.hpp', - 'core/program.cpp', - 'core/program.hpp', - 'core/property.hpp', - 'core/queue.cpp', - 'core/queue.hpp', - 'core/resource.cpp', - 'core/resource.hpp', - 'core/sampler.cpp', - 'core/sampler.hpp', - 'core/timestamp.cpp', - 'core/timestamp.hpp', - 'util/adaptor.hpp', - 'util/algebra.hpp', - 'util/algorithm.hpp', - 'util/factor.hpp', - 'util/functional.hpp', - 'util/lazy.hpp', - 'util/pointer.hpp', - 'util/range.hpp', - 'util/tuple.hpp', -) - -libclover = static_library( - 'clover', - [clover_files, sha1_h], - include_directories : clover_incs, - cpp_args : [ - clover_opencl_cpp_args, - clover_spirv_cpp_args, - clover_cpp_args, - cpp_vis_args - ], - link_with : [libclllvm, libclspirv, libclnir], - override_options : clover_cpp_std, -) diff --git a/src/gallium/state_trackers/clover/nir/invocation.cpp b/src/gallium/state_trackers/clover/nir/invocation.cpp deleted file mode 100644 index 46440d96e09..00000000000 --- a/src/gallium/state_trackers/clover/nir/invocation.cpp +++ /dev/null @@ -1,173 +0,0 @@ -// -// Copyright 2019 Karol Herbst -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#include "invocation.hpp" - -#include - -#include "core/device.hpp" -#include "core/error.hpp" -#include "pipe/p_state.h" -#include "util/algorithm.hpp" -#include "util/functional.hpp" - -#include -#include -#include -#include - -using namespace clover; - -#ifdef HAVE_CLOVER_SPIRV - -// Refs and unrefs the glsl_type_singleton. -static class glsl_type_ref { -public: - glsl_type_ref() { - glsl_type_singleton_init_or_ref(); - } - - ~glsl_type_ref() { - glsl_type_singleton_decref(); - } -} glsl_type_ref; - -static const nir_shader_compiler_options * -dev_get_nir_compiler_options(const device &dev) -{ - const void *co = dev.get_compiler_options(PIPE_SHADER_IR_NIR); - return static_cast(co); -} - -module clover::nir::spirv_to_nir(const module &mod, const device &dev, - std::string &r_log) -{ - struct spirv_to_nir_options spirv_options = {}; - spirv_options.environment = NIR_SPIRV_OPENCL; - spirv_options.caps.address = true; - spirv_options.caps.float64 = true; - spirv_options.caps.int8 = true; - spirv_options.caps.int16 = true; - spirv_options.caps.int64 = true; - spirv_options.caps.kernel = true; - spirv_options.constant_as_global = true; - - module m; - // We only insert one section. - assert(mod.secs.size() == 1); - auto §ion = mod.secs[0]; - - module::resource_id section_id = 0; - for (const auto &sym : mod.syms) { - assert(sym.section == 0); - - const auto *binary = - reinterpret_cast(section.data.data()); - const uint32_t *data = reinterpret_cast(binary->blob); - const size_t num_words = binary->num_bytes / 4; - const char *name = sym.name.c_str(); - auto *compiler_options = dev_get_nir_compiler_options(dev); - - nir_shader *nir = spirv_to_nir(data, num_words, nullptr, 0, - MESA_SHADER_KERNEL, name, - &spirv_options, compiler_options); - if (!nir) { - r_log += "Translation from SPIR-V to NIR for kernel \"" + sym.name + - "\" failed.\n"; - throw build_error(); - } - - nir->info.cs.local_size_variable = true; - nir_validate_shader(nir, "clover"); - - // Calculate input offsets. - unsigned offset = 0; - nir_foreach_variable_safe(var, &nir->inputs) { - offset = align(offset, glsl_get_cl_alignment(var->type)); - var->data.driver_location = offset; - offset += glsl_get_cl_size(var->type); - } - - // Inline all functions first. - // according to the comment on nir_inline_functions - NIR_PASS_V(nir, nir_lower_variable_initializers, nir_var_function_temp); - NIR_PASS_V(nir, nir_lower_returns); - NIR_PASS_V(nir, nir_inline_functions); - NIR_PASS_V(nir, nir_opt_deref); - - // Pick off the single entrypoint that we want. - foreach_list_typed_safe(nir_function, func, node, &nir->functions) { - if (!func->is_entrypoint) - exec_node_remove(&func->node); - } - assert(exec_list_length(&nir->functions) == 1); - - nir_validate_shader(nir, "clover after function inlining"); - - NIR_PASS_V(nir, nir_lower_variable_initializers, - static_cast(~nir_var_function_temp)); - - // copy propagate to prepare for lower_explicit_io - NIR_PASS_V(nir, nir_split_var_copies); - NIR_PASS_V(nir, nir_opt_copy_prop_vars); - NIR_PASS_V(nir, nir_lower_var_copies); - NIR_PASS_V(nir, nir_lower_vars_to_ssa); - NIR_PASS_V(nir, nir_opt_dce); - - nir_variable_mode modes = (nir_variable_mode)( - nir_var_shader_in | - nir_var_mem_global | - nir_var_mem_shared); - nir_address_format format = nir->info.cs.ptr_size == 64 ? - nir_address_format_64bit_global : nir_address_format_32bit_global; - NIR_PASS_V(nir, nir_lower_explicit_io, modes, format); - - NIR_PASS_V(nir, nir_lower_system_values); - if (compiler_options->lower_int64_options) - NIR_PASS_V(nir, nir_lower_int64, - compiler_options->lower_int64_options); - - NIR_PASS_V(nir, nir_opt_dce); - - struct blob blob; - blob_init(&blob); - nir_serialize(&blob, nir, false); - - const pipe_binary_program_header header { uint32_t(blob.size) }; - module::section text { section_id, module::section::text_executable, header.num_bytes, {} }; - text.data.insert(text.data.end(), reinterpret_cast(&header), - reinterpret_cast(&header) + sizeof(header)); - text.data.insert(text.data.end(), blob.data, blob.data + blob.size); - - m.syms.emplace_back(sym.name, section_id, 0, sym.args); - m.secs.push_back(text); - section_id++; - } - return m; -} -#else -module clover::nir::spirv_to_nir(const module &mod, const device &dev, std::string &r_log) -{ - r_log += "SPIR-V support in clover is not enabled.\n"; - throw error(CL_LINKER_NOT_AVAILABLE); -} -#endif diff --git a/src/gallium/state_trackers/clover/nir/invocation.hpp b/src/gallium/state_trackers/clover/nir/invocation.hpp deleted file mode 100644 index 41407a79765..00000000000 --- a/src/gallium/state_trackers/clover/nir/invocation.hpp +++ /dev/null @@ -1,36 +0,0 @@ -// -// Copyright 2019 Karol Herbst -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#ifndef CLOVER_NIR_INVOCATION_HPP -#define CLOVER_NIR_INVOCATION_HPP - -#include "core/module.hpp" - -namespace clover { - class device; - namespace nir { - // converts a given spirv module to nir - module spirv_to_nir(const module &mod, const device &dev, std::string &r_log); - } -} - -#endif diff --git a/src/gallium/state_trackers/clover/spirv/invocation.cpp b/src/gallium/state_trackers/clover/spirv/invocation.cpp deleted file mode 100644 index 01ced45c13b..00000000000 --- a/src/gallium/state_trackers/clover/spirv/invocation.cpp +++ /dev/null @@ -1,740 +0,0 @@ -// -// Copyright 2018 Pierre Moreau -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#include "invocation.hpp" - -#include -#include -#include -#include - -#ifdef HAVE_CLOVER_SPIRV -#include -#include -#endif - -#include "core/error.hpp" -#include "core/platform.hpp" -#include "invocation.hpp" -#include "llvm/util.hpp" -#include "pipe/p_state.h" -#include "util/algorithm.hpp" -#include "util/functional.hpp" -#include "util/u_math.h" - -#include "compiler/spirv/spirv.h" - -#define SPIRV_HEADER_WORD_SIZE 5 - -using namespace clover; - -#ifdef HAVE_CLOVER_SPIRV -namespace { - - template - T get(const char *source, size_t index) { - const uint32_t *word_ptr = reinterpret_cast(source); - return static_cast(word_ptr[index]); - } - - enum module::argument::type - convert_storage_class(SpvStorageClass storage_class, std::string &err) { - switch (storage_class) { - case SpvStorageClassFunction: - return module::argument::scalar; - case SpvStorageClassUniformConstant: - return module::argument::global; - case SpvStorageClassWorkgroup: - return module::argument::local; - case SpvStorageClassCrossWorkgroup: - return module::argument::global; - default: - err += "Invalid storage type " + std::to_string(storage_class) + "\n"; - throw build_error(); - } - } - - enum module::argument::type - convert_image_type(SpvId id, SpvDim dim, SpvAccessQualifier access, - std::string &err) { - if (dim == SpvDim2D && access == SpvAccessQualifierReadOnly) - return module::argument::image2d_rd; - else if (dim == SpvDim2D && access == SpvAccessQualifierWriteOnly) - return module::argument::image2d_wr; - else if (dim == SpvDim3D && access == SpvAccessQualifierReadOnly) - return module::argument::image3d_rd; - else if (dim == SpvDim3D && access == SpvAccessQualifierWriteOnly) - return module::argument::image3d_wr; - else { - err += "Unknown access qualifier " + std::to_string(access) - + " or dimension " + std::to_string(dim) + " for image " - + std::to_string(id) + ".\n"; - throw build_error(); - } - } - - module::section - make_text_section(const std::vector &code, - enum module::section::type section_type) { - const pipe_binary_program_header header { uint32_t(code.size()) }; - module::section text { 0, section_type, header.num_bytes, {} }; - - text.data.insert(text.data.end(), reinterpret_cast(&header), - reinterpret_cast(&header) + sizeof(header)); - text.data.insert(text.data.end(), code.begin(), code.end()); - - return text; - } - - module - create_module_from_spirv(const std::vector &source, - size_t pointer_byte_size, - std::string &err) { - const size_t length = source.size() / sizeof(uint32_t); - size_t i = SPIRV_HEADER_WORD_SIZE; // Skip header - - std::string kernel_name; - size_t kernel_nb = 0u; - std::vector args; - - module m; - - std::unordered_map kernels; - std::unordered_map types; - std::unordered_map pointer_types; - std::unordered_map constants; - std::unordered_set packed_structures; - std::unordered_map> - func_param_attr_map; - - while (i < length) { - const auto inst = &source[i * sizeof(uint32_t)]; - const auto desc_word = get(inst, 0); - const auto opcode = static_cast(desc_word & SpvOpCodeMask); - const unsigned int num_operands = desc_word >> SpvWordCountShift; - - switch (opcode) { - case SpvOpEntryPoint: - if (get(inst, 1) == SpvExecutionModelKernel) - kernels.emplace(get(inst, 2), - source.data() + (i + 3u) * sizeof(uint32_t)); - break; - - case SpvOpDecorate: { - const auto id = get(inst, 1); - const auto decoration = get(inst, 2); - if (decoration == SpvDecorationCPacked) - packed_structures.emplace(id); - else if (decoration == SpvDecorationFuncParamAttr) { - const auto attribute = - get(inst, 3u); - func_param_attr_map[id].push_back(attribute); - } - break; - } - - case SpvOpGroupDecorate: { - const auto group_id = get(inst, 1); - if (packed_structures.count(group_id)) { - for (unsigned int i = 2u; i < num_operands; ++i) - packed_structures.emplace(get(inst, i)); - } - const auto func_param_attr_iter = - func_param_attr_map.find(group_id); - if (func_param_attr_iter != func_param_attr_map.end()) { - for (unsigned int i = 2u; i < num_operands; ++i) - func_param_attr_map.emplace(get(inst, i), - func_param_attr_iter->second); - } - break; - } - - case SpvOpConstant: - // We only care about constants that represent the size of arrays. - // If they are passed as argument, they will never be more than - // 4GB-wide, and even if they did, a clover::module::argument size - // is represented by an int. - constants[get(inst, 2)] = get(inst, 3u); - break; - - case SpvOpTypeInt: // FALLTHROUGH - case SpvOpTypeFloat: { - const auto size = get(inst, 2) / 8u; - types[get(inst, 1)] = { module::argument::scalar, size, - size, size, - module::argument::zero_ext }; - break; - } - - case SpvOpTypeArray: { - const auto id = get(inst, 1); - const auto type_id = get(inst, 2); - const auto types_iter = types.find(type_id); - if (types_iter == types.end()) - break; - - const auto constant_id = get(inst, 3); - const auto constants_iter = constants.find(constant_id); - if (constants_iter == constants.end()) { - err += "Constant " + std::to_string(constant_id) + - " is missing\n"; - throw build_error(); - } - const auto elem_size = types_iter->second.size; - const auto elem_nbs = constants_iter->second; - const auto size = elem_size * elem_nbs; - types[id] = { module::argument::scalar, size, size, - types_iter->second.target_align, - module::argument::zero_ext }; - break; - } - - case SpvOpTypeStruct: { - const auto id = get(inst, 1); - const bool is_packed = packed_structures.count(id); - - unsigned struct_size = 0u; - unsigned struct_align = 1u; - for (unsigned j = 2u; j < num_operands; ++j) { - const auto type_id = get(inst, j); - const auto types_iter = types.find(type_id); - - // If a type was not found, that means it is not one of the - // types allowed as kernel arguments. And since the module has - // been validated, this means this type is not used for kernel - // arguments, and therefore can be ignored. - if (types_iter == types.end()) - break; - - const auto alignment = is_packed ? 1u - : types_iter->second.target_align; - const auto padding = (-struct_size) & (alignment - 1u); - struct_size += padding + types_iter->second.target_size; - struct_align = std::max(struct_align, alignment); - } - struct_size += (-struct_size) & (struct_align - 1u); - types[id] = { module::argument::scalar, struct_size, struct_size, - struct_align, module::argument::zero_ext }; - break; - } - - case SpvOpTypeVector: { - const auto id = get(inst, 1); - const auto type_id = get(inst, 2); - const auto types_iter = types.find(type_id); - - // If a type was not found, that means it is not one of the - // types allowed as kernel arguments. And since the module has - // been validated, this means this type is not used for kernel - // arguments, and therefore can be ignored. - if (types_iter == types.end()) - break; - - const auto elem_size = types_iter->second.size; - const auto elem_nbs = get(inst, 3); - const auto size = elem_size * elem_nbs; - types[id] = { module::argument::scalar, size, size, size, - module::argument::zero_ext }; - break; - } - - case SpvOpTypeForwardPointer: // FALLTHROUGH - case SpvOpTypePointer: { - const auto id = get(inst, 1); - const auto storage_class = get(inst, 2); - // Input means this is for a builtin variable, which can not be - // passed as an argument to a kernel. - if (storage_class == SpvStorageClassInput) - break; - types[id] = { convert_storage_class(storage_class, err), - sizeof(cl_mem), - static_cast(pointer_byte_size), - static_cast(pointer_byte_size), - module::argument::zero_ext }; - if (opcode == SpvOpTypePointer) - pointer_types[id] = get(inst, 3); - break; - } - - case SpvOpTypeSampler: - types[get(inst, 1)] = { module::argument::sampler, - sizeof(cl_sampler) }; - break; - - case SpvOpTypeImage: { - const auto id = get(inst, 1); - const auto dim = get(inst, 3); - const auto access = get(inst, 9); - types[id] = { convert_image_type(id, dim, access, err), - sizeof(cl_mem), sizeof(cl_mem), sizeof(cl_mem), - module::argument::zero_ext }; - break; - } - - case SpvOpTypePipe: // FALLTHROUGH - case SpvOpTypeQueue: { - err += "TypePipe and TypeQueue are valid SPIR-V 1.0 types, but are " - "not available in the currently supported OpenCL C version." - "\n"; - throw build_error(); - } - - case SpvOpFunction: { - const auto kernels_iter = kernels.find(get(inst, 2)); - if (kernels_iter != kernels.end()) - kernel_name = kernels_iter->second; - break; - } - - case SpvOpFunctionParameter: { - if (kernel_name.empty()) - break; - - const auto type_id = get(inst, 1); - auto arg = types.find(type_id)->second; - const auto &func_param_attr_iter = - func_param_attr_map.find(get(inst, 2)); - if (func_param_attr_iter != func_param_attr_map.end()) { - for (auto &i : func_param_attr_iter->second) { - switch (i) { - case SpvFunctionParameterAttributeSext: - arg.ext_type = module::argument::sign_ext; - break; - case SpvFunctionParameterAttributeZext: - arg.ext_type = module::argument::zero_ext; - break; - case SpvFunctionParameterAttributeByVal: { - const SpvId ptr_type_id = - pointer_types.find(type_id)->second; - arg = types.find(ptr_type_id)->second; - break; - } - default: - break; - } - } - } - args.emplace_back(arg); - break; - } - - case SpvOpFunctionEnd: - if (kernel_name.empty()) - break; - m.syms.emplace_back(kernel_name, 0, kernel_nb, args); - ++kernel_nb; - kernel_name.clear(); - args.clear(); - break; - - default: - break; - } - - i += num_operands; - } - - m.secs.push_back(make_text_section(source, - module::section::text_intermediate)); - return m; - } - - bool - check_capabilities(const device &dev, const std::vector &source, - std::string &r_log) { - const size_t length = source.size() / sizeof(uint32_t); - size_t i = SPIRV_HEADER_WORD_SIZE; // Skip header - - while (i < length) { - const auto desc_word = get(source.data(), i); - const auto opcode = static_cast(desc_word & SpvOpCodeMask); - const unsigned int num_operands = desc_word >> SpvWordCountShift; - - if (opcode != SpvOpCapability) - break; - - const auto capability = get(source.data(), i + 1u); - switch (capability) { - // Mandatory capabilities - case SpvCapabilityAddresses: - case SpvCapabilityFloat16Buffer: - case SpvCapabilityGroups: - case SpvCapabilityInt64: - case SpvCapabilityInt16: - case SpvCapabilityInt8: - case SpvCapabilityKernel: - case SpvCapabilityLinkage: - case SpvCapabilityVector16: - break; - // Optional capabilities - case SpvCapabilityImageBasic: - case SpvCapabilityLiteralSampler: - case SpvCapabilitySampled1D: - case SpvCapabilityImage1D: - case SpvCapabilitySampledBuffer: - case SpvCapabilityImageBuffer: - if (!dev.image_support()) { - r_log += "Capability 'ImageBasic' is not supported.\n"; - return false; - } - break; - case SpvCapabilityFloat64: - if (!dev.has_doubles()) { - r_log += "Capability 'Float64' is not supported.\n"; - return false; - } - break; - // Enabled through extensions - case SpvCapabilityFloat16: - if (!dev.has_halves()) { - r_log += "Capability 'Float16' is not supported.\n"; - return false; - } - break; - case SpvCapabilityInt64Atomics: - if (!dev.has_int64_atomics()) { - r_log += "Capability 'Int64Atomics' is not supported.\n"; - return false; - } - break; - default: - r_log += "Capability '" + std::to_string(capability) + - "' is not supported.\n"; - return false; - } - - i += num_operands; - } - - return true; - } - - bool - check_extensions(const device &dev, const std::vector &source, - std::string &r_log) { - const size_t length = source.size() / sizeof(uint32_t); - size_t i = SPIRV_HEADER_WORD_SIZE; // Skip header - - while (i < length) { - const auto desc_word = get(source.data(), i); - const auto opcode = static_cast(desc_word & SpvOpCodeMask); - const unsigned int num_operands = desc_word >> SpvWordCountShift; - - if (opcode == SpvOpCapability) { - i += num_operands; - continue; - } - if (opcode != SpvOpExtension) - break; - - const char *extension = source.data() + (i + 1u) * sizeof(uint32_t); - const std::string device_extensions = dev.supported_extensions(); - const std::string platform_extensions = - dev.platform.supported_extensions(); - if (device_extensions.find(extension) == std::string::npos && - platform_extensions.find(extension) == std::string::npos) { - r_log += "Extension '" + std::string(extension) + - "' is not supported.\n"; - return false; - } - - i += num_operands; - } - - return true; - } - - bool - check_memory_model(const device &dev, const std::vector &source, - std::string &r_log) { - const size_t length = source.size() / sizeof(uint32_t); - size_t i = SPIRV_HEADER_WORD_SIZE; // Skip header - - while (i < length) { - const auto desc_word = get(source.data(), i); - const auto opcode = static_cast(desc_word & SpvOpCodeMask); - const unsigned int num_operands = desc_word >> SpvWordCountShift; - - switch (opcode) { - case SpvOpMemoryModel: - switch (get(source.data(), i + 1u)) { - case SpvAddressingModelPhysical32: - return dev.address_bits() == 32; - case SpvAddressingModelPhysical64: - return dev.address_bits() == 64; - default: - unreachable("Only Physical32 and Physical64 are valid for OpenCL, and the binary was already validated"); - return false; - } - break; - default: - break; - } - - i += num_operands; - } - - return false; - } - - // Copies the input binary and convert it to the endianness of the host CPU. - std::vector - spirv_to_cpu(const std::vector &binary) - { - const uint32_t first_word = get(binary.data(), 0u); - if (first_word == SpvMagicNumber) - return binary; - - std::vector cpu_endianness_binary(binary.size()); - for (size_t i = 0; i < (binary.size() / 4u); ++i) { - const uint32_t word = get(binary.data(), i); - reinterpret_cast(cpu_endianness_binary.data())[i] = - util_bswap32(word); - } - - return cpu_endianness_binary; - } - -#ifdef HAVE_CLOVER_SPIRV - std::string - format_validator_msg(spv_message_level_t level, const char * /* source */, - const spv_position_t &position, const char *message) { - std::string level_str; - switch (level) { - case SPV_MSG_FATAL: - level_str = "Fatal"; - break; - case SPV_MSG_INTERNAL_ERROR: - level_str = "Internal error"; - break; - case SPV_MSG_ERROR: - level_str = "Error"; - break; - case SPV_MSG_WARNING: - level_str = "Warning"; - break; - case SPV_MSG_INFO: - level_str = "Info"; - break; - case SPV_MSG_DEBUG: - level_str = "Debug"; - break; - } - return "[" + level_str + "] At word No." + - std::to_string(position.index) + ": \"" + message + "\"\n"; - } - - spv_target_env - convert_opencl_str_to_target_env(const std::string &opencl_version) { - if (opencl_version == "2.2") { - return SPV_ENV_OPENCL_2_2; - } else if (opencl_version == "2.1") { - return SPV_ENV_OPENCL_2_1; - } else if (opencl_version == "2.0") { - return SPV_ENV_OPENCL_2_0; - } else if (opencl_version == "1.2" || - opencl_version == "1.1" || - opencl_version == "1.0") { - // SPIR-V is only defined for OpenCL >= 1.2, however some drivers - // might use it with OpenCL 1.0 and 1.1. - return SPV_ENV_OPENCL_1_2; - } else { - throw build_error("Invalid OpenCL version"); - } - } -#endif - -} - -module -clover::spirv::compile_program(const std::vector &binary, - const device &dev, std::string &r_log) { - std::vector source = spirv_to_cpu(binary); - - if (!is_valid_spirv(source, dev.device_version(), r_log)) - throw build_error(); - - if (!check_capabilities(dev, source, r_log)) - throw build_error(); - if (!check_extensions(dev, source, r_log)) - throw build_error(); - if (!check_memory_model(dev, source, r_log)) - throw build_error(); - - return create_module_from_spirv(source, - dev.address_bits() == 32 ? 4u : 8u, r_log); -} - -module -clover::spirv::link_program(const std::vector &modules, - const device &dev, const std::string &opts, - std::string &r_log) { - std::vector options = clover::llvm::tokenize(opts); - - bool create_library = false; - - std::string ignored_options; - for (const std::string &option : options) { - if (option == "-create-library") { - create_library = true; - } else { - ignored_options += "'" + option + "' "; - } - } - if (!ignored_options.empty()) { - r_log += "Ignoring the following link options: " + ignored_options - + "\n"; - } - - spvtools::LinkerOptions linker_options; - linker_options.SetCreateLibrary(create_library); - - module m; - - const auto section_type = create_library ? module::section::text_library : - module::section::text_executable; - - std::vector sections; - sections.reserve(modules.size()); - std::vector lengths; - lengths.reserve(modules.size()); - - auto const validator_consumer = [&r_log](spv_message_level_t level, - const char *source, - const spv_position_t &position, - const char *message) { - r_log += format_validator_msg(level, source, position, message); - }; - - for (const auto &mod : modules) { - const auto &msec = find([](const module::section &sec) { - return sec.type == module::section::text_intermediate || - sec.type == module::section::text_library; - }, mod.secs); - - const auto c_il = ((struct pipe_binary_program_header*)msec.data.data())->blob; - const auto length = msec.size; - - sections.push_back(reinterpret_cast(c_il)); - lengths.push_back(length / sizeof(uint32_t)); - } - - std::vector linked_binary; - - const std::string opencl_version = dev.device_version(); - const spv_target_env target_env = - convert_opencl_str_to_target_env(opencl_version); - - const spvtools::MessageConsumer consumer = validator_consumer; - spvtools::Context context(target_env); - context.SetMessageConsumer(std::move(consumer)); - - if (Link(context, sections.data(), lengths.data(), sections.size(), - &linked_binary, linker_options) != SPV_SUCCESS) - throw error(CL_LINK_PROGRAM_FAILURE); - - std::vector final_binary{ - reinterpret_cast(linked_binary.data()), - reinterpret_cast(linked_binary.data() + - linked_binary.size()) }; - if (!is_valid_spirv(final_binary, opencl_version, r_log)) - throw error(CL_LINK_PROGRAM_FAILURE); - - for (const auto &mod : modules) - m.syms.insert(m.syms.end(), mod.syms.begin(), mod.syms.end()); - - m.secs.emplace_back(make_text_section(final_binary, section_type)); - - return m; -} - -bool -clover::spirv::is_valid_spirv(const std::vector &binary, - const std::string &opencl_version, - std::string &r_log) { - auto const validator_consumer = - [&r_log](spv_message_level_t level, const char *source, - const spv_position_t &position, const char *message) { - r_log += format_validator_msg(level, source, position, message); - }; - - const spv_target_env target_env = - convert_opencl_str_to_target_env(opencl_version); - spvtools::SpirvTools spvTool(target_env); - spvTool.SetMessageConsumer(validator_consumer); - - return spvTool.Validate(reinterpret_cast(binary.data()), - binary.size() / 4u); -} - -std::string -clover::spirv::print_module(const std::vector &binary, - const std::string &opencl_version) { - const spv_target_env target_env = - convert_opencl_str_to_target_env(opencl_version); - spvtools::SpirvTools spvTool(target_env); - spv_context spvContext = spvContextCreate(target_env); - if (!spvContext) - return "Failed to create an spv_context for disassembling the module."; - - spv_text disassembly; - spvBinaryToText(spvContext, - reinterpret_cast(binary.data()), - binary.size() / 4u, SPV_BINARY_TO_TEXT_OPTION_NONE, - &disassembly, nullptr); - spvContextDestroy(spvContext); - - const std::string disassemblyStr = disassembly->str; - spvTextDestroy(disassembly); - - return disassemblyStr; -} - -#else -bool -clover::spirv::is_valid_spirv(const std::vector &/*binary*/, - const std::string &/*opencl_version*/, - std::string &/*r_log*/) { - return false; -} - -module -clover::spirv::compile_program(const std::vector &binary, - const device &dev, std::string &r_log) { - r_log += "SPIR-V support in clover is not enabled.\n"; - throw build_error(); -} - -module -clover::spirv::link_program(const std::vector &/*modules*/, - const device &/*dev*/, const std::string &/*opts*/, - std::string &r_log) { - r_log += "SPIR-V support in clover is not enabled.\n"; - throw error(CL_LINKER_NOT_AVAILABLE); -} - -std::string -clover::spirv::print_module(const std::vector &binary, - const std::string &opencl_version) { - return std::string(); -} -#endif diff --git a/src/gallium/state_trackers/clover/spirv/invocation.hpp b/src/gallium/state_trackers/clover/spirv/invocation.hpp deleted file mode 100644 index 472d8c0de71..00000000000 --- a/src/gallium/state_trackers/clover/spirv/invocation.hpp +++ /dev/null @@ -1,56 +0,0 @@ -// -// Copyright 2018 Pierre Moreau -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#ifndef CLOVER_SPIRV_INVOCATION_HPP -#define CLOVER_SPIRV_INVOCATION_HPP - -#include "core/context.hpp" -#include "core/module.hpp" -#include "core/program.hpp" - -namespace clover { - namespace spirv { - // Returns whether the given binary is considered valid for the given - // OpenCL version. - // - // It uses SPIRV-Tools validator to do the validation, and potential - // warnings and errors are appended to |r_log|. - bool is_valid_spirv(const std::vector &binary, - const std::string &opencl_version, - std::string &r_log); - - // Creates a clover module out of the given SPIR-V binary. - module compile_program(const std::vector &binary, - const device &dev, std::string &r_log); - - // Combines multiple clover modules into a single one, resolving - // link dependencies between them. - module link_program(const std::vector &modules, const device &dev, - const std::string &opts, std::string &r_log); - - // Returns a textual representation of the given binary. - std::string print_module(const std::vector &binary, - const std::string &opencl_version); - } -} - -#endif diff --git a/src/gallium/state_trackers/clover/util/adaptor.hpp b/src/gallium/state_trackers/clover/util/adaptor.hpp deleted file mode 100644 index e9035968573..00000000000 --- a/src/gallium/state_trackers/clover/util/adaptor.hpp +++ /dev/null @@ -1,183 +0,0 @@ -// -// Copyright 2013 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#ifndef CLOVER_UTIL_ADAPTOR_HPP -#define CLOVER_UTIL_ADAPTOR_HPP - -#include - -#include "util/tuple.hpp" -#include "util/pointer.hpp" -#include "util/functional.hpp" - -namespace clover { - namespace detail { - /// - /// Implementation of the iterator concept that transforms the - /// value of the source iterators \a Is on dereference by use of - /// a functor \a F. - /// - /// The exact category of the resulting iterator should be the - /// least common denominator of the source iterator categories. - /// - template - class iterator_adaptor { - public: - typedef std::forward_iterator_tag iterator_category; - typedef typename std::result_of< - F(typename std::iterator_traits::reference...) - >::type reference; - typedef typename std::remove_reference::type value_type; - typedef pseudo_ptr pointer; - typedef std::ptrdiff_t difference_type; - - iterator_adaptor() { - } - - iterator_adaptor(F f, std::tuple &&its) : - f(f), its(std::move(its)) { - } - - reference - operator*() const { - return tuple::apply(f, tuple::map(derefs(), its)); - } - - iterator_adaptor & - operator++() { - tuple::map(preincs(), its); - return *this; - } - - iterator_adaptor - operator++(int) { - auto jt = *this; - ++*this; - return jt; - } - - bool - operator==(const iterator_adaptor &jt) const { - return its == jt.its; - } - - bool - operator!=(const iterator_adaptor &jt) const { - return its != jt.its; - } - - pointer - operator->() const { - return { **this }; - } - - iterator_adaptor & - operator--() { - tuple::map(predecs(), its); - return *this; - } - - iterator_adaptor - operator--(int) { - auto jt = *this; - --*this; - return jt; - } - - iterator_adaptor & - operator+=(difference_type n) { - tuple::map(advances_by(n), its); - return *this; - } - - iterator_adaptor & - operator-=(difference_type n) { - tuple::map(advances_by(-n), its); - return *this; - } - - iterator_adaptor - operator+(difference_type n) const { - auto jt = *this; - jt += n; - return jt; - } - - iterator_adaptor - operator-(difference_type n) const { - auto jt = *this; - jt -= n; - return jt; - } - - difference_type - operator-(const iterator_adaptor &jt) const { - return std::get<0>(its) - std::get<0>(jt.its); - } - - reference - operator[](difference_type n) const { - return *(*this + n); - } - - bool - operator<(iterator_adaptor &jt) const { - return *this - jt < 0; - } - - bool - operator>(iterator_adaptor &jt) const { - return *this - jt > 0; - } - - bool - operator>=(iterator_adaptor &jt) const { - return !(*this < jt); - } - - bool - operator<=(iterator_adaptor &jt) const { - return !(*this > jt); - } - - protected: - F f; - std::tuple its; - }; - - template - iterator_adaptor - operator+(typename iterator_adaptor::difference_type n, - const iterator_adaptor &jt) { - return (jt + n); - } - - template - iterator_adaptor - operator-(typename iterator_adaptor::difference_type n, - const iterator_adaptor &jt) { - return (jt - n); - } - } -} - -#endif diff --git a/src/gallium/state_trackers/clover/util/algebra.hpp b/src/gallium/state_trackers/clover/util/algebra.hpp deleted file mode 100644 index 43a9d8bbf5f..00000000000 --- a/src/gallium/state_trackers/clover/util/algebra.hpp +++ /dev/null @@ -1,160 +0,0 @@ -// -// Copyright 2013 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#ifndef CLOVER_UTIL_ALGEBRA_HPP -#define CLOVER_UTIL_ALGEBRA_HPP - -#include - -#include "util/range.hpp" -#include "util/functional.hpp" - -namespace clover { - /// - /// Class that identifies vectors (in the linear-algebraic sense). - /// - /// There should be a definition of this class for each type that - /// makes sense as vector arithmetic operand. - /// - template - struct vector_traits; - - /// - /// References of vectors are vectors. - /// - template - struct vector_traits::enable> { - typedef void enable; - }; - - /// - /// Constant vectors are vectors. - /// - template - struct vector_traits::enable> { - typedef void enable; - }; - - /// - /// Arrays of arithmetic types are vectors. - /// - template - struct vector_traits, - typename std::enable_if< - std::is_arithmetic::value>::type> { - typedef void enable; - }; - - namespace detail { - template - struct are_defined { - typedef void enable; - }; - } - - /// - /// The result of mapping a vector is a vector. - /// - template - struct vector_traits, - typename detail::are_defined< - typename vector_traits::enable...>::enable> { - typedef void enable; - }; - - /// - /// Vector sum. - /// - template::enable, - typename = typename vector_traits::enable> - adaptor_range - operator+(U &&u, V &&v) { - return map(plus(), std::forward(u), std::forward(v)); - } - - /// - /// Vector difference. - /// - template::enable, - typename = typename vector_traits::enable> - adaptor_range - operator-(U &&u, V &&v) { - return map(minus(), std::forward(u), std::forward(v)); - } - - /// - /// Scalar multiplication. - /// - template::enable> - adaptor_range, U> - operator*(U &&u, T &&a) { - return map(multiplies_by(std::forward(a)), std::forward(u)); - } - - /// - /// Scalar multiplication. - /// - template::enable> - adaptor_range, U> - operator*(T &&a, U &&u) { - return map(multiplies_by(std::forward(a)), std::forward(u)); - } - - /// - /// Additive inverse. - /// - template::enable> - adaptor_range - operator-(U &&u) { - return map(negate(), std::forward(u)); - } - - namespace detail { - template - using dot_type = typename std::common_type< - typename std::remove_reference::type::value_type, - typename std::remove_reference::type::value_type - >::type; - } - - /// - /// Dot product of two vectors. - /// - /// It can also do matrix multiplication if \a u or \a v is a - /// vector of vectors. - /// - template::enable, - typename = typename vector_traits::enable> - detail::dot_type - dot(U &&u, V &&v) { - return fold(plus(), detail::dot_type(), - map(multiplies(), u, v)); - } -} - -#endif diff --git a/src/gallium/state_trackers/clover/util/algorithm.hpp b/src/gallium/state_trackers/clover/util/algorithm.hpp deleted file mode 100644 index 1658458ee18..00000000000 --- a/src/gallium/state_trackers/clover/util/algorithm.hpp +++ /dev/null @@ -1,218 +0,0 @@ -// -// Copyright 2013 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#ifndef CLOVER_UTIL_ALGORITHM_HPP -#define CLOVER_UTIL_ALGORITHM_HPP - -#include -#include - -#include "util/range.hpp" -#include "util/functional.hpp" - -namespace clover { - namespace detail { - template - using preferred_reference_type = decltype(*std::declval().begin()); - } - - /// - /// Return the first element in a range. - /// - template - detail::preferred_reference_type - head(R &&r) { - assert(!r.empty()); - return r.front(); - } - - /// - /// Return all elements in a range but the first. - /// - template - slice_range - tail(R &&r) { - assert(!r.empty()); - return { std::forward(r), 1, r.size() }; - } - - /// - /// Return the only element in a range. - /// - template - detail::preferred_reference_type - unique(R &&r) { - if (r.size() != 1) - throw std::out_of_range(""); - - return r.front(); - } - - /// - /// Combine a variable number of ranges element-wise in a single - /// range of tuples. - /// - template - adaptor_range - zip(Rs &&... rs) { - return map(zips(), std::forward(rs)...); - } - - /// - /// Evaluate the elements of a range. - /// - /// Useful because most of the range algorithms evaluate their - /// result lazily. - /// - template - void - eval(R &&r) { - for (auto i = r.begin(), e = r.end(); i != e; ++i) - *i; - } - - /// - /// Apply functor \a f element-wise on a variable number of ranges - /// \a rs. - /// - /// The functor \a f should take as many arguments as ranges are - /// provided. - /// - template - void - for_each(F &&f, Rs &&... rs) { - eval(map(std::forward(f), std::forward(rs)...)); - } - - /// - /// Copy all elements from range \a r into an output container - /// starting from iterator \a i. - /// - template - void - copy(R &&r, I i) { - for (detail::preferred_reference_type x : r) - *(i++) = x; - } - - /// - /// Reduce the elements of range \a r by applying functor \a f - /// element by element. - /// - /// \a f should take an accumulator value (which is initialized to - /// \a a) and an element value as arguments, and return an updated - /// accumulator value. - /// - /// \returns The final value of the accumulator. - /// - template - A - fold(F &&f, A a, R &&r) { - for (detail::preferred_reference_type x : r) - a = f(a, x); - - return a; - } - - /// - /// Return how many elements of range \a r are equal to \a x. - /// - template - typename std::remove_reference::type::size_type - count(T &&x, R &&r) { - typename std::remove_reference::type::size_type n = 0; - - for (detail::preferred_reference_type y : r) { - if (x == y) - n++; - } - - return n; - } - - /// - /// Return the first element in range \a r for which predicate \a f - /// evaluates to true. - /// - template - detail::preferred_reference_type - find(F &&f, R &&r) { - for (detail::preferred_reference_type x : r) { - if (f(x)) - return x; - } - - throw std::out_of_range(""); - } - - /// - /// Return true if the element-wise application of predicate \a f - /// on \a rs evaluates to true for all elements. - /// - template - bool - all_of(F &&f, Rs &&... rs) { - for (auto b : map(f, rs...)) { - if (!b) - return false; - } - - return true; - } - - /// - /// Return true if the element-wise application of predicate \a f - /// on \a rs evaluates to true for any element. - /// - template - bool - any_of(F &&f, Rs &&... rs) { - for (auto b : map(f, rs...)) { - if (b) - return true; - } - - return false; - } - - /// - /// Erase elements for which predicate \a f evaluates to true from - /// container \a r. - /// - template - void - erase_if(F &&f, R &&r) { - auto i = r.begin(), e = r.end(); - - for (auto j = r.begin(); j != e; ++j) { - if (!f(*j)) { - if (j != i) - *i = std::move(*j); - ++i; - } - } - - r.erase(i, e); - } -} - -#endif diff --git a/src/gallium/state_trackers/clover/util/factor.hpp b/src/gallium/state_trackers/clover/util/factor.hpp deleted file mode 100644 index 76d3bfe343f..00000000000 --- a/src/gallium/state_trackers/clover/util/factor.hpp +++ /dev/null @@ -1,131 +0,0 @@ -// -// Copyright 2013 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#ifndef CLOVER_UTIL_FACTOR_HPP -#define CLOVER_UTIL_FACTOR_HPP - -#include "util/range.hpp" - -namespace clover { - namespace factor { - /// - /// Calculate all prime integer factors of \p x. - /// - /// If \p limit is non-zero, terminate early as soon as enough - /// factors have been collected to reach the product \p limit. - /// - template - std::vector - find_integer_prime_factors(T x, T limit = 0) - { - const T max_d = (limit > 0 && limit < x ? limit : x); - const T min_x = x / max_d; - std::vector factors; - - for (T d = 2; d <= max_d && x > min_x; d++) { - if (x % d == 0) { - for (; x % d == 0; x /= d); - factors.push_back(d); - } - } - - return factors; - } - - namespace detail { - /// - /// Walk the power set of prime factors of the n-dimensional - /// integer array \p grid subject to the constraints given by - /// \p limits. - /// - template - std::pair> - next_grid_factor(const std::pair> &limits, - const std::vector &grid, - const std::vector> &factors, - std::pair> block, - unsigned d = 0, unsigned i = 0) { - if (d >= factors.size()) { - // We're done. - return {}; - - } else if (i >= factors[d].size()) { - // We're done with this grid dimension, try the next. - return next_grid_factor(limits, grid, factors, - std::move(block), d + 1, 0); - - } else { - T f = factors[d][i]; - - // Try the next power of this factor. - block.first *= f; - block.second[d] *= f; - - if (block.first <= limits.first && - block.second[d] <= limits.second[d] && - grid[d] % block.second[d] == 0) { - // We've found a valid grid divisor. - return block; - - } else { - // Overflow, back off to the zeroth power, - while (block.second[d] % f == 0) { - block.second[d] /= f; - block.first /= f; - } - - // ...and carry to the next factor. - return next_grid_factor(limits, grid, factors, - std::move(block), d, i + 1); - } - } - } - } - - /// - /// Find the divisor of the integer array \p grid that gives the - /// highest possible product not greater than \p product_limit - /// subject to the constraints given by \p coord_limit. - /// - template - std::vector - find_grid_optimal_factor(T product_limit, - const std::vector &coord_limit, - const std::vector &grid) { - const std::vector> factors = - map(find_integer_prime_factors, grid, coord_limit); - const auto limits = std::make_pair(product_limit, coord_limit); - auto best = std::make_pair(T(1), std::vector(grid.size(), T(1))); - - for (auto block = best; - block.first != 0 && best.first != product_limit; - block = detail::next_grid_factor(limits, grid, factors, block)) { - if (block.first > best.first) - best = block; - } - - return best.second; - } - } -} - -#endif diff --git a/src/gallium/state_trackers/clover/util/functional.hpp b/src/gallium/state_trackers/clover/util/functional.hpp deleted file mode 100644 index fc281c5c79a..00000000000 --- a/src/gallium/state_trackers/clover/util/functional.hpp +++ /dev/null @@ -1,419 +0,0 @@ -// -// Copyright 2013 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#ifndef CLOVER_UTIL_FUNCTIONAL_HPP -#define CLOVER_UTIL_FUNCTIONAL_HPP - -#include - -namespace clover { - struct identity { - template - typename std::remove_reference::type - operator()(T &&x) const { - return x; - } - }; - - struct plus { - template - typename std::common_type::type - operator()(T x, S y) const { - return x + y; - } - }; - - struct minus { - template - typename std::common_type::type - operator()(T x, S y) const { - return x - y; - } - }; - - struct negate { - template - T - operator()(T x) const { - return -x; - } - }; - - struct multiplies { - template - typename std::common_type::type - operator()(T x, S y) const { - return x * y; - } - }; - - struct divides { - template - typename std::common_type::type - operator()(T x, S y) const { - return x / y; - } - }; - - struct modulus { - template - typename std::common_type::type - operator()(T x, S y) const { - return x % y; - } - }; - - struct minimum { - template - T - operator()(T x) const { - return x; - } - - template - T - operator()(T x, Ts... xs) const { - T y = minimum()(xs...); - return x < y ? x : y; - } - }; - - struct maximum { - template - T - operator()(T x) const { - return x; - } - - template - T - operator()(T x, Ts... xs) const { - T y = maximum()(xs...); - return x < y ? y : x; - } - }; - - struct preincs { - template - T & - operator()(T &x) const { - return ++x; - } - }; - - struct predecs { - template - T & - operator()(T &x) const { - return --x; - } - }; - - template - class multiplies_by_t { - public: - multiplies_by_t(T x) : x(x) { - } - - template - typename std::common_type::type - operator()(S y) const { - return x * y; - } - - private: - T x; - }; - - template - multiplies_by_t - multiplies_by(T x) { - return { x }; - } - - template - class preincs_by_t { - public: - preincs_by_t(T n) : n(n) { - } - - template - S & - operator()(S &x) const { - return x += n; - } - - private: - T n; - }; - - template - preincs_by_t - preincs_by(T n) { - return { n }; - } - - template - class predecs_by_t { - public: - predecs_by_t(T n) : n(n) { - } - - template - S & - operator()(S &x) const { - return x -= n; - } - - private: - T n; - }; - - template - predecs_by_t - predecs_by(T n) { - return { n }; - } - - struct greater { - template - bool - operator()(T x, S y) const { - return x > y; - } - }; - - struct evals { - template - auto - operator()(T &&x) const -> decltype(x()) { - return x(); - } - }; - - struct derefs { - template - auto - operator()(T &&x) const -> decltype(*x) { - return *x; - } - }; - - struct addresses { - template - T * - operator()(T &x) const { - return &x; - } - - template - T * - operator()(std::reference_wrapper x) const { - return &x.get(); - } - }; - - struct begins { - template - auto - operator()(T &x) const -> decltype(x.begin()) { - return x.begin(); - } - }; - - struct ends { - template - auto - operator()(T &x) const -> decltype(x.end()) { - return x.end(); - } - }; - - struct sizes { - template - auto - operator()(T &x) const -> decltype(x.size()) { - return x.size(); - } - }; - - template - class advances_by_t { - public: - advances_by_t(T n) : n(n) { - } - - template - S - operator()(S &&it) const { - std::advance(it, n); - return it; - } - - private: - T n; - }; - - template - advances_by_t - advances_by(T n) { - return { n }; - } - - struct zips { - template - std::tuple - operator()(Ts &&... xs) const { - return std::tuple(std::forward(xs)...); - } - }; - - struct is_zero { - template - bool - operator()(const T &x) const { - return x == 0; - } - }; - - struct keys { - template - auto - operator()(P &&p) const -> decltype(std::get<0>(std::forward

      (p))) { - return std::get<0>(std::forward

      (p)); - } - }; - - struct values { - template - auto - operator()(P &&p) const -> decltype(std::get<1>(std::forward

      (p))) { - return std::get<1>(std::forward

      (p)); - } - }; - - template - class equals_t { - public: - equals_t(T &&x) : x(x) {} - - template - bool - operator()(S &&y) const { - return x == y; - } - - private: - T x; - }; - - template - equals_t - equals(T &&x) { - return { std::forward(x) }; - } - - class name_equals { - public: - name_equals(const std::string &name) : name(name) { - } - - template - bool - operator()(const T &x) const { - return std::string(x.name.begin(), x.name.end()) == name; - } - - private: - const std::string &name; - }; - - class id_equals { - public: - id_equals(const uint32_t id) : id(id) { - } - - template - bool - operator()(const T &x) const { - return x.id == id; - } - - private: - const uint32_t id; - }; - - template - class key_equals_t { - public: - key_equals_t(T &&x) : x(x) { - } - - template - bool - operator()(const P &p) const { - return p.first == x; - } - - private: - T x; - }; - - template - key_equals_t - key_equals(T &&x) { - return { std::forward(x) }; - } - - template - class type_equals_t { - public: - type_equals_t(T type) : type(type) { - } - - template - bool - operator()(const S &x) const { - return x.type == type; - } - - private: - T type; - }; - - template - type_equals_t - type_equals(T x) { - return { x }; - } - - struct interval_overlaps { - template - bool - operator()(T x0, T x1, T y0, T y1) { - return ((x0 <= y0 && y0 < x1) || - (y0 <= x0 && x0 < y1)); - } - }; -} - -#endif diff --git a/src/gallium/state_trackers/clover/util/lazy.hpp b/src/gallium/state_trackers/clover/util/lazy.hpp deleted file mode 100644 index e32a8f8b1b9..00000000000 --- a/src/gallium/state_trackers/clover/util/lazy.hpp +++ /dev/null @@ -1,161 +0,0 @@ -// -// Copyright 2013 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#ifndef CLOVER_UTIL_LAZY_HPP -#define CLOVER_UTIL_LAZY_HPP - -#include -#include -#include - -namespace clover { - namespace detail { - template - class basic_lazy { - public: - virtual - ~basic_lazy() { - } - - virtual basic_lazy * - clone() const = 0; - - virtual - operator T() const = 0; - }; - - template - class deferred_lazy : public basic_lazy { - public: - template - deferred_lazy(G &&f) : f(new F(std::forward(f))) { - } - - virtual basic_lazy * - clone() const { - return new deferred_lazy(*this); - } - - operator T() const { - if (f) { - x = (*f)(); - f = {}; - } - - return x; - } - - private: - mutable std::shared_ptr f; - mutable T x; - }; - - template - class strict_lazy : public basic_lazy { - public: - template - strict_lazy(S &&x) : x(std::forward(x)) { - } - - virtual basic_lazy * - clone() const { - return new strict_lazy(*this); - } - - operator T() const { - return x; - } - - private: - T x; - }; - } - - /// - /// Object that represents a value of type \a T that is calculated - /// lazily as soon as it is required. - /// - template - class lazy { - public: - class undefined_error : std::logic_error { - public: - undefined_error() : std::logic_error("") { - } - }; - - /// - /// Initialize to some fixed value \a x which isn't calculated - /// lazily. - /// - lazy(T x) : obj(new detail::strict_lazy(x)) { - } - - /// - /// Initialize by providing a functor \a f that will calculate - /// the value on-demand. - /// - template - lazy(F &&f) : obj(new detail::deferred_lazy< - T, typename std::remove_reference::type - >(std::forward(f))) { - } - - /// - /// Initialize to undefined. - /// - lazy() : lazy([]() { - throw undefined_error(); - return T(); - }) { - } - - lazy(const lazy &other) : obj(obj->clone()) { - } - - lazy(lazy &&other) : obj(NULL) { - std::swap(obj, other.obj); - } - - ~lazy() { - delete obj; - } - - lazy & - operator=(lazy other) { - std::swap(obj, other.obj); - return *this; - } - - /// - /// Evaluate the value. - /// - operator T() const { - return *obj; - } - - private: - detail::basic_lazy *obj; - }; -} - -#endif diff --git a/src/gallium/state_trackers/clover/util/pointer.hpp b/src/gallium/state_trackers/clover/util/pointer.hpp deleted file mode 100644 index 7bb9951aef6..00000000000 --- a/src/gallium/state_trackers/clover/util/pointer.hpp +++ /dev/null @@ -1,284 +0,0 @@ -// -// Copyright 2013 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#ifndef CLOVER_UTIL_POINTER_HPP -#define CLOVER_UTIL_POINTER_HPP - -#include - -namespace clover { - /// - /// Some helper functions for raw pointer operations - /// - template - static bool - ptr_is_aligned(const T *ptr, uintptr_t a) noexcept { - assert(a == (a & -a)); - uintptr_t ptr_value = reinterpret_cast(ptr); - return (ptr_value & (a - 1)) == 0; - } - - /// - /// Base class for objects that support reference counting. - /// - class ref_counter { - public: - ref_counter(unsigned value = 1) : _ref_count(value) {} - - unsigned - ref_count() const { - return _ref_count; - } - - void - retain() { - _ref_count++; - } - - bool - release() { - return (--_ref_count) == 0; - } - - private: - std::atomic _ref_count; - }; - - /// - /// Simple reference to a clover::ref_counter object. Unlike - /// clover::intrusive_ptr and clover::intrusive_ref, it does nothing - /// special when the reference count drops to zero. - /// - class ref_holder { - public: - ref_holder(ref_counter &o) : p(&o) { - p->retain(); - } - - ref_holder(const ref_holder &ref) : - ref_holder(*ref.p) { - } - - ref_holder(ref_holder &&ref) : - p(ref.p) { - ref.p = NULL; - } - - ~ref_holder() { - if (p) - p->release(); - } - - ref_holder & - operator=(ref_holder ref) { - std::swap(ref.p, p); - return *this; - } - - bool - operator==(const ref_holder &ref) const { - return p == ref.p; - } - - bool - operator!=(const ref_holder &ref) const { - return p != ref.p; - } - - private: - ref_counter *p; - }; - - /// - /// Intrusive smart pointer for objects that implement the - /// clover::ref_counter interface. - /// - template - class intrusive_ptr { - public: - intrusive_ptr(T *q = NULL) : p(q) { - if (p) - p->retain(); - } - - intrusive_ptr(const intrusive_ptr &ptr) : - intrusive_ptr(ptr.p) { - } - - intrusive_ptr(intrusive_ptr &&ptr) : - p(ptr.p) { - ptr.p = NULL; - } - - ~intrusive_ptr() { - if (p && p->release()) - delete p; - } - - intrusive_ptr & - operator=(intrusive_ptr ptr) { - std::swap(ptr.p, p); - return *this; - } - - bool - operator==(const intrusive_ptr &ref) const { - return p == ref.p; - } - - bool - operator!=(const intrusive_ptr &ref) const { - return p != ref.p; - } - - T & - operator*() const { - return *p; - } - - T * - operator->() const { - return p; - } - - T * - operator()() const { - return p; - } - - explicit operator bool() const { - return p; - } - - explicit operator T *() const { - return p; - } - - private: - T *p; - }; - - /// - /// Intrusive smart reference for objects that implement the - /// clover::ref_counter interface. - /// - template - class intrusive_ref { - public: - intrusive_ref(T &o) : p(&o) { - p->retain(); - } - - intrusive_ref(const intrusive_ref &ref) : - intrusive_ref(*ref.p) { - } - - intrusive_ref(intrusive_ref &&ref) : - p(ref.p) { - ref.p = NULL; - } - - ~intrusive_ref() { - if (p && p->release()) - delete p; - } - - intrusive_ref & - operator=(intrusive_ref ref) { - std::swap(ref.p, p); - return *this; - } - - bool - operator==(const intrusive_ref &ref) const { - return p == ref.p; - } - - bool - operator!=(const intrusive_ref &ref) const { - return p != ref.p; - } - - T & - operator()() const { - return *p; - } - - operator T &() const { - return *p; - } - - private: - T *p; - }; - - /// - /// Initialize a clover::intrusive_ref from a newly created object - /// using the specified constructor arguments. - /// - template - intrusive_ref - create(As &&... as) { - intrusive_ref ref { *new T(std::forward(as)...) }; - ref().release(); - return ref; - } - - /// - /// Class that implements the usual pointer interface but in fact - /// contains the object it seems to be pointing to. - /// - template - class pseudo_ptr { - public: - pseudo_ptr(T x) : x(x) { - } - - pseudo_ptr(const pseudo_ptr &p) : x(p.x) { - } - - pseudo_ptr & - operator=(const pseudo_ptr &p) { - x = p.x; - return *this; - } - - T & - operator*() { - return x; - } - - T * - operator->() { - return &x; - } - - explicit operator bool() const { - return true; - } - - private: - T x; - }; -} - -#endif diff --git a/src/gallium/state_trackers/clover/util/range.hpp b/src/gallium/state_trackers/clover/util/range.hpp deleted file mode 100644 index b082359ee86..00000000000 --- a/src/gallium/state_trackers/clover/util/range.hpp +++ /dev/null @@ -1,419 +0,0 @@ -// -// Copyright 2013 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#ifndef CLOVER_UTIL_RANGE_HPP -#define CLOVER_UTIL_RANGE_HPP - -#include -#include - -#include "util/adaptor.hpp" - -namespace clover { - /// - /// Class that identifies container types where the elements of a - /// range can be stored by the type conversion operator. - /// - /// \a T identifies the range element type. - /// - template - struct range_store_traits; - - template - struct range_store_traits> { - typedef void enable; - - template - static std::vector - create(const R &r) { - return { r.begin(), r.end() }; - } - }; - - template - struct range_store_traits> { - typedef void enable; - - template - static std::array - create(const R &r) { - std::array v; - assert(r.size() == v.size()); - copy(r, v.begin()); - return v; - } - }; - - namespace detail { - /// - /// Common functionality that is shared by other implementations - /// of the container concept. - /// - template - class basic_range { - public: - typedef I iterator; - typedef CI const_iterator; - typedef typename std::iterator_traits::value_type value_type; - typedef typename std::iterator_traits::reference - reference; - typedef typename std::iterator_traits::reference - const_reference; - typedef typename std::iterator_traits::difference_type - difference_type; - typedef std::size_t size_type; - - bool - operator==(const basic_range &r) const { - return *static_cast(this) == r; - } - - bool - operator!=(const basic_range &r) const { - return !(*this == r); - } - - iterator - begin() { - return static_cast(this)->begin(); - } - - iterator - end() { - return static_cast(this)->end(); - } - - const_iterator - begin() const { - return static_cast(this)->begin(); - } - - const_iterator - end() const { - return static_cast(this)->end(); - } - - std::reverse_iterator - rbegin() { - return { begin() }; - } - - std::reverse_iterator - rend() { - return { end() }; - } - - reference - front() { - return *begin(); - } - - reference - back() { - return *(end() - 1); - } - - bool - empty() const { - return begin() == end(); - } - - reference - at(size_type i) { - if (i >= static_cast(this)->size()) - throw std::out_of_range(""); - - return begin()[i]; - } - - const_reference - at(size_type i) const { - if (i >= static_cast(this)->size()) - throw std::out_of_range(""); - - return begin()[i]; - } - - reference - operator[](size_type i) { - return begin()[i]; - } - - const_reference - operator[](size_type i) const { - return begin()[i]; - } - - template - using store_traits = range_store_traits< - typename std::remove_cv::type, V - >; - - template::enable> - operator V() const { - return store_traits::create(*static_cast(this)); - } - }; - } - - /// - /// Range that contains all elements delimited by an iterator pair - /// (\a i, \a j). Use range() as convenience constructor. - /// - template - class iterator_range : public detail::basic_range, I, I> { - public: - typedef detail::basic_range, I, I> super; - - iterator_range() : i(), j() { - } - - iterator_range(I i, I j) : i(i), j(j) { - } - - bool - operator==(const iterator_range &r) const { - return i == r.i && j == r.j; - } - - I - begin() const { - return i; - } - - I - end() const { - return j; - } - - typename super::size_type - size() const { - return end() - begin(); - } - - private: - I i, j; - }; - - namespace detail { - template - using preferred_iterator_type = decltype(std::declval().begin()); - } - - /// - /// Range that transforms the contents of a number of source ranges - /// \a os element-wise by using the provided functor \a f. Use - /// map() as convenience constructor. - /// - template - class adaptor_range : - public detail::basic_range, - detail::iterator_adaptor< - F, detail::preferred_iterator_type...>, - detail::iterator_adaptor< - F, detail::preferred_iterator_type...> - > { - public: - typedef detail::basic_range, - detail::iterator_adaptor< - F, detail::preferred_iterator_type...>, - detail::iterator_adaptor< - F, detail::preferred_iterator_type...> - > super; - - template - adaptor_range(G &&f, Rs &&... os) : - f(std::forward(f)), os(std::forward(os)...) { - } - - bool - operator==(const adaptor_range &r) const { - return f == r.f && os == r.os; - } - - typename super::iterator - begin() { - return { f, tuple::map(begins(), os) }; - } - - typename super::iterator - end() { - return { f, tuple::map(advances_by(size()), - tuple::map(begins(), os)) }; - } - - typename super::const_iterator - begin() const { - return { f, tuple::map(begins(), os) }; - } - - typename super::const_iterator - end() const { - return { f, tuple::map(advances_by(size()), - tuple::map(begins(), os)) }; - } - - typename super::size_type - size() const { - return tuple::apply(minimum(), tuple::map(sizes(), os)); - } - - private: - F f; - std::tuple os; - }; - - /// - /// Range that contains all elements delimited by the index pair - /// (\a i, \a j) in the source range \a r. Use slice() as - /// convenience constructor. - /// - template - class slice_range : - public detail::basic_range, - detail::preferred_iterator_type, - detail::preferred_iterator_type> { - public: - typedef detail::basic_range, - detail::preferred_iterator_type, - detail::preferred_iterator_type - > super; - - template - slice_range(R &&r, typename super::size_type i, - typename super::size_type j) : - o(std::forward(r)), i(i), j(j) { - } - - bool - operator==(const slice_range &r) const { - return o == r.o && i == r.i && j == r.j; - } - - typename super::iterator - begin() { - return std::next(o.begin(), i); - } - - typename super::iterator - end() { - return std::next(o.begin(), j); - } - - typename super::const_iterator - begin() const { - return std::next(o.begin(), i); - } - - typename super::const_iterator - end() const { - return std::next(o.begin(), j); - } - - typename super::size_type - size() const { - return j - i; - } - - private: - O o; - typename super::size_type i, j; - }; - - /// - /// Create a range from an iterator pair (\a i, \a j). - /// - /// \sa iterator_range. - /// - template - iterator_range - range(T i, T j) { - return { i, j }; - } - - /// - /// Create a range of \a n elements starting from iterator \a i. - /// - /// \sa iterator_range. - /// - template - iterator_range - range(T i, typename std::iterator_traits::difference_type n) { - return { i, i + n }; - } - - /// - /// Create a range by transforming the contents of a number of - /// source ranges \a rs element-wise using a provided functor \a f. - /// - /// \sa adaptor_range. - /// - template - adaptor_range - map(F &&f, Rs &&... rs) { - return { std::forward(f), std::forward(rs)... }; - } - - /// - /// Create a range identical to another range \a r. - /// - template - adaptor_range - range(R &&r) { - return { identity(), std::forward(r) }; - } - - /// - /// Create a range by taking the elements delimited by the index - /// pair (\a i, \a j) in a source range \a r. - /// - /// \sa slice_range. - /// - template - slice_range - slice(R &&r, typename slice_range::size_type i, - typename slice_range::size_type j) { - return { std::forward(r), i, j }; - } - - /// - /// Range that behaves as a vector of references of type \a T. - /// - /// Useful because STL containers cannot contain references to - /// objects as elements. - /// - template - class ref_vector : public adaptor_range> { - public: - ref_vector(std::initializer_list> il) : - adaptor_range>(derefs(), map(addresses(), il)) { - } - - template - ref_vector(R &&r) : adaptor_range>( - derefs(), map(addresses(), std::forward(r))) { - } - }; -} - -#endif diff --git a/src/gallium/state_trackers/clover/util/tuple.hpp b/src/gallium/state_trackers/clover/util/tuple.hpp deleted file mode 100644 index bd49684a314..00000000000 --- a/src/gallium/state_trackers/clover/util/tuple.hpp +++ /dev/null @@ -1,117 +0,0 @@ -// -// Copyright 2013 Francisco Jerez -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -#ifndef CLOVER_UTIL_TUPLE_HPP -#define CLOVER_UTIL_TUPLE_HPP - -#include - -namespace clover { - namespace tuple { - /// - /// Static sequence of integers. - /// - template - struct integral_sequence; - - /// - /// Static sequence containing all integers from 0 to N-1. - /// - template - struct enumerate { - typedef typename enumerate::type - type; - }; - - template - struct enumerate<0, Is...> { - typedef integral_sequence type; - }; - - namespace detail { - template::type>::value - >::type> - struct _apply; - - template - struct _apply> { - typedef typename std::remove_reference::type func_type; - typedef decltype( - std::declval()(std::get(std::declval())...) - ) value_type; - - static value_type - eval(F &&f, T &&t) { - return f(std::get(std::forward(t))...); - } - }; - } - - /// - /// Evaluate function \a f with the elements of tuple \a t - /// expanded as arguments. - /// - template - typename detail::_apply::value_type - apply(F &&f, T &&t) { - return detail::_apply::eval(std::forward(f), - std::forward(t)); - } - - namespace detail { - template::type>::value - >::type> - struct _map; - - template - struct _map> { - typedef typename std::remove_reference::type func_type; - typedef std::tuple< - decltype(std::declval()( - std::get(std::declval())))... - > value_type; - - static value_type - eval(F &&f, T &&t) { - return value_type(f(std::get(std::forward(t)))...); - } - }; - } - - /// - /// Evaluate function \a f on each element of the tuple \a t and - /// return the resulting values as a new tuple. - /// - template - typename detail::_map::value_type - map(F &&f, T &&t) { - return detail::_map::eval(std::forward(f), - std::forward(t)); - } - } -} - -#endif diff --git a/src/gallium/state_trackers/dri/Android.mk b/src/gallium/state_trackers/dri/Android.mk deleted file mode 100644 index d6f8a6ed247..00000000000 --- a/src/gallium/state_trackers/dri/Android.mk +++ /dev/null @@ -1,55 +0,0 @@ -# Mesa 3-D graphics library -# -# Copyright (C) 2015 Chih-Wei Huang -# Copyright (C) 2015 Android-x86 Open Source Project -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the "Software"), -# to deal in the Software without restriction, including without limitation -# the rights to use, copy, modify, merge, publish, distribute, sublicense, -# and/or sell copies of the Software, and to permit persons to whom the -# Software is furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -# DEALINGS IN THE SOFTWARE. - -LOCAL_PATH := $(call my-dir) - -include $(LOCAL_PATH)/Makefile.sources - -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := \ - $(common_SOURCES) \ - $(dri2_SOURCES) - -LOCAL_C_INCLUDES := \ - $(MESA_TOP)/src/mapi \ - $(MESA_TOP)/src/mesa - -LOCAL_EXPORT_C_INCLUDE_DIRS := \ - $(LOCAL_PATH) \ - $(LOCAL_C_INCLUDES) - -LOCAL_STATIC_LIBRARIES := \ - libmesa_dri_common - -ifneq ($(HAVE_GALLIUM_SOFTPIPE),) -LOCAL_SRC_FILES += $(drisw_SOURCES) -LOCAL_CFLAGS += -DGALLIUM_SOFTPIPE -endif - -LOCAL_MODULE := libmesa_st_dri - -LOCAL_GENERATED_SOURCES := $(MESA_DRI_OPTIONS_H) - -include $(GALLIUM_COMMON_MK) -include $(BUILD_STATIC_LIBRARY) diff --git a/src/gallium/state_trackers/dri/Makefile.sources b/src/gallium/state_trackers/dri/Makefile.sources deleted file mode 100644 index a610293bb11..00000000000 --- a/src/gallium/state_trackers/dri/Makefile.sources +++ /dev/null @@ -1,17 +0,0 @@ -common_SOURCES := \ - dri_context.c \ - dri_context.h \ - dri_drawable.c \ - dri_drawable.h \ - dri_helpers.c \ - dri_helpers.h \ - dri_query_renderer.c \ - dri_query_renderer.h \ - dri_screen.c \ - dri_screen.h - -dri2_SOURCES := \ - dri2.c - -drisw_SOURCES := \ - drisw.c diff --git a/src/gallium/state_trackers/dri/dri2.c b/src/gallium/state_trackers/dri/dri2.c deleted file mode 100644 index ec78d0985ed..00000000000 --- a/src/gallium/state_trackers/dri/dri2.c +++ /dev/null @@ -1,2275 +0,0 @@ -/* - * Mesa 3-D graphics library - * - * Copyright 2009, VMware, Inc. - * All Rights Reserved. - * Copyright (C) 2010 LunarG Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: - * Keith Whitwell Jakob Bornecrantz - * Chia-I Wu - */ - -#include -#include "GL/mesa_glinterop.h" -#include "util/disk_cache.h" -#include "util/u_memory.h" -#include "util/u_inlines.h" -#include "util/format/u_format.h" -#include "util/u_debug.h" -#include "state_tracker/drm_driver.h" -#include "state_tracker/st_cb_bufferobjects.h" -#include "state_tracker/st_cb_fbo.h" -#include "state_tracker/st_cb_texture.h" -#include "state_tracker/st_texture.h" -#include "state_tracker/st_context.h" -#include "pipe-loader/pipe_loader.h" -#include "main/bufferobj.h" -#include "main/texobj.h" - -#include "dri_util.h" - -#include "dri_helpers.h" -#include "dri_drawable.h" -#include "dri_query_renderer.h" - -#include "drm-uapi/drm_fourcc.h" - -struct dri2_buffer -{ - __DRIbuffer base; - struct pipe_resource *resource; -}; - -static inline struct dri2_buffer * -dri2_buffer(__DRIbuffer * driBufferPriv) -{ - return (struct dri2_buffer *) driBufferPriv; -} - -/** - * DRI2 flush extension. - */ -static void -dri2_flush_drawable(__DRIdrawable *dPriv) -{ - dri_flush(dPriv->driContextPriv, dPriv, __DRI2_FLUSH_DRAWABLE, -1); -} - -static void -dri2_invalidate_drawable(__DRIdrawable *dPriv) -{ - struct dri_drawable *drawable = dri_drawable(dPriv); - - dri2InvalidateDrawable(dPriv); - drawable->dPriv->lastStamp = drawable->dPriv->dri2.stamp; - drawable->texture_mask = 0; - - p_atomic_inc(&drawable->base.stamp); -} - -static const __DRI2flushExtension dri2FlushExtension = { - .base = { __DRI2_FLUSH, 4 }, - - .flush = dri2_flush_drawable, - .invalidate = dri2_invalidate_drawable, - .flush_with_flags = dri_flush, -}; - -/** - * Retrieve __DRIbuffer from the DRI loader. - */ -static __DRIbuffer * -dri2_drawable_get_buffers(struct dri_drawable *drawable, - const enum st_attachment_type *atts, - unsigned *count) -{ - __DRIdrawable *dri_drawable = drawable->dPriv; - const __DRIdri2LoaderExtension *loader = drawable->sPriv->dri2.loader; - boolean with_format; - __DRIbuffer *buffers; - int num_buffers; - unsigned attachments[10]; - unsigned num_attachments, i; - - assert(loader); - with_format = dri_with_format(drawable->sPriv); - - num_attachments = 0; - - /* for Xserver 1.6.0 (DRI2 version 1) we always need to ask for the front */ - if (!with_format) - attachments[num_attachments++] = __DRI_BUFFER_FRONT_LEFT; - - for (i = 0; i < *count; i++) { - enum pipe_format format; - unsigned bind; - int att, depth; - - dri_drawable_get_format(drawable, atts[i], &format, &bind); - if (format == PIPE_FORMAT_NONE) - continue; - - switch (atts[i]) { - case ST_ATTACHMENT_FRONT_LEFT: - /* already added */ - if (!with_format) - continue; - att = __DRI_BUFFER_FRONT_LEFT; - break; - case ST_ATTACHMENT_BACK_LEFT: - att = __DRI_BUFFER_BACK_LEFT; - break; - case ST_ATTACHMENT_FRONT_RIGHT: - att = __DRI_BUFFER_FRONT_RIGHT; - break; - case ST_ATTACHMENT_BACK_RIGHT: - att = __DRI_BUFFER_BACK_RIGHT; - break; - default: - continue; - } - - /* - * In this switch statement we must support all formats that - * may occur as the stvis->color_format. - */ - switch(format) { - case PIPE_FORMAT_R16G16B16A16_FLOAT: - depth = 64; - break; - case PIPE_FORMAT_R16G16B16X16_FLOAT: - depth = 48; - break; - case PIPE_FORMAT_B10G10R10A2_UNORM: - case PIPE_FORMAT_R10G10B10A2_UNORM: - case PIPE_FORMAT_BGRA8888_UNORM: - case PIPE_FORMAT_RGBA8888_UNORM: - depth = 32; - break; - case PIPE_FORMAT_R10G10B10X2_UNORM: - case PIPE_FORMAT_B10G10R10X2_UNORM: - depth = 30; - break; - case PIPE_FORMAT_BGRX8888_UNORM: - case PIPE_FORMAT_RGBX8888_UNORM: - depth = 24; - break; - case PIPE_FORMAT_B5G6R5_UNORM: - depth = 16; - break; - default: - depth = util_format_get_blocksizebits(format); - assert(!"Unexpected format in dri2_drawable_get_buffers()"); - } - - attachments[num_attachments++] = att; - if (with_format) { - attachments[num_attachments++] = depth; - } - } - - if (with_format) { - num_attachments /= 2; - buffers = loader->getBuffersWithFormat(dri_drawable, - &dri_drawable->w, &dri_drawable->h, - attachments, num_attachments, - &num_buffers, dri_drawable->loaderPrivate); - } - else { - buffers = loader->getBuffers(dri_drawable, - &dri_drawable->w, &dri_drawable->h, - attachments, num_attachments, - &num_buffers, dri_drawable->loaderPrivate); - } - - if (buffers) - *count = num_buffers; - - return buffers; -} - -static bool -dri_image_drawable_get_buffers(struct dri_drawable *drawable, - struct __DRIimageList *images, - const enum st_attachment_type *statts, - unsigned statts_count) -{ - __DRIdrawable *dPriv = drawable->dPriv; - __DRIscreen *sPriv = drawable->sPriv; - unsigned int image_format = __DRI_IMAGE_FORMAT_NONE; - enum pipe_format pf; - uint32_t buffer_mask = 0; - unsigned i, bind; - - for (i = 0; i < statts_count; i++) { - dri_drawable_get_format(drawable, statts[i], &pf, &bind); - if (pf == PIPE_FORMAT_NONE) - continue; - - switch (statts[i]) { - case ST_ATTACHMENT_FRONT_LEFT: - buffer_mask |= __DRI_IMAGE_BUFFER_FRONT; - break; - case ST_ATTACHMENT_BACK_LEFT: - buffer_mask |= __DRI_IMAGE_BUFFER_BACK; - break; - default: - continue; - } - - switch (pf) { - case PIPE_FORMAT_R16G16B16A16_FLOAT: - image_format = __DRI_IMAGE_FORMAT_ABGR16161616F; - break; - case PIPE_FORMAT_R16G16B16X16_FLOAT: - image_format = __DRI_IMAGE_FORMAT_XBGR16161616F; - break; - case PIPE_FORMAT_B5G5R5A1_UNORM: - image_format = __DRI_IMAGE_FORMAT_ARGB1555; - break; - case PIPE_FORMAT_B5G6R5_UNORM: - image_format = __DRI_IMAGE_FORMAT_RGB565; - break; - case PIPE_FORMAT_BGRX8888_UNORM: - image_format = __DRI_IMAGE_FORMAT_XRGB8888; - break; - case PIPE_FORMAT_BGRA8888_UNORM: - image_format = __DRI_IMAGE_FORMAT_ARGB8888; - break; - case PIPE_FORMAT_RGBX8888_UNORM: - image_format = __DRI_IMAGE_FORMAT_XBGR8888; - break; - case PIPE_FORMAT_RGBA8888_UNORM: - image_format = __DRI_IMAGE_FORMAT_ABGR8888; - break; - case PIPE_FORMAT_B10G10R10X2_UNORM: - image_format = __DRI_IMAGE_FORMAT_XRGB2101010; - break; - case PIPE_FORMAT_B10G10R10A2_UNORM: - image_format = __DRI_IMAGE_FORMAT_ARGB2101010; - break; - case PIPE_FORMAT_R10G10B10X2_UNORM: - image_format = __DRI_IMAGE_FORMAT_XBGR2101010; - break; - case PIPE_FORMAT_R10G10B10A2_UNORM: - image_format = __DRI_IMAGE_FORMAT_ABGR2101010; - break; - default: - image_format = __DRI_IMAGE_FORMAT_NONE; - break; - } - } - - return (*sPriv->image.loader->getBuffers) (dPriv, image_format, - (uint32_t *) &drawable->base.stamp, - dPriv->loaderPrivate, buffer_mask, - images); -} - -static __DRIbuffer * -dri2_allocate_buffer(__DRIscreen *sPriv, - unsigned attachment, unsigned format, - int width, int height) -{ - struct dri_screen *screen = dri_screen(sPriv); - struct dri2_buffer *buffer; - struct pipe_resource templ; - enum pipe_format pf; - unsigned bind = 0; - struct winsys_handle whandle; - - switch (attachment) { - case __DRI_BUFFER_FRONT_LEFT: - case __DRI_BUFFER_FAKE_FRONT_LEFT: - bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; - break; - case __DRI_BUFFER_BACK_LEFT: - bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; - break; - case __DRI_BUFFER_DEPTH: - case __DRI_BUFFER_DEPTH_STENCIL: - case __DRI_BUFFER_STENCIL: - bind = PIPE_BIND_DEPTH_STENCIL; /* XXX sampler? */ - break; - } - - /* because we get the handle and stride */ - bind |= PIPE_BIND_SHARED; - - switch (format) { - case 64: - pf = PIPE_FORMAT_R16G16B16A16_FLOAT; - break; - case 48: - pf = PIPE_FORMAT_R16G16B16X16_FLOAT; - break; - case 32: - pf = PIPE_FORMAT_BGRA8888_UNORM; - break; - case 30: - pf = PIPE_FORMAT_B10G10R10X2_UNORM; - break; - case 24: - pf = PIPE_FORMAT_BGRX8888_UNORM; - break; - case 16: - pf = PIPE_FORMAT_Z16_UNORM; - break; - default: - return NULL; - } - - buffer = CALLOC_STRUCT(dri2_buffer); - if (!buffer) - return NULL; - - memset(&templ, 0, sizeof(templ)); - templ.bind = bind; - templ.format = pf; - templ.target = PIPE_TEXTURE_2D; - templ.last_level = 0; - templ.width0 = width; - templ.height0 = height; - templ.depth0 = 1; - templ.array_size = 1; - - buffer->resource = - screen->base.screen->resource_create(screen->base.screen, &templ); - if (!buffer->resource) { - FREE(buffer); - return NULL; - } - - memset(&whandle, 0, sizeof(whandle)); - if (screen->can_share_buffer) - whandle.type = WINSYS_HANDLE_TYPE_SHARED; - else - whandle.type = WINSYS_HANDLE_TYPE_KMS; - - screen->base.screen->resource_get_handle(screen->base.screen, NULL, - buffer->resource, &whandle, - PIPE_HANDLE_USAGE_EXPLICIT_FLUSH); - - buffer->base.attachment = attachment; - buffer->base.name = whandle.handle; - buffer->base.cpp = util_format_get_blocksize(pf); - buffer->base.pitch = whandle.stride; - - return &buffer->base; -} - -static void -dri2_release_buffer(__DRIscreen *sPriv, __DRIbuffer *bPriv) -{ - struct dri2_buffer *buffer = dri2_buffer(bPriv); - - pipe_resource_reference(&buffer->resource, NULL); - FREE(buffer); -} - -/* - * Backend functions for st_framebuffer interface. - */ - -static void -dri2_allocate_textures(struct dri_context *ctx, - struct dri_drawable *drawable, - const enum st_attachment_type *statts, - unsigned statts_count) -{ - __DRIscreen *sPriv = drawable->sPriv; - __DRIdrawable *dri_drawable = drawable->dPriv; - struct dri_screen *screen = dri_screen(sPriv); - struct pipe_resource templ; - boolean alloc_depthstencil = FALSE; - unsigned i, j, bind; - const __DRIimageLoaderExtension *image = sPriv->image.loader; - /* Image specific variables */ - struct __DRIimageList images; - /* Dri2 specific variables */ - __DRIbuffer *buffers = NULL; - struct winsys_handle whandle; - unsigned num_buffers = statts_count; - - /* First get the buffers from the loader */ - if (image) { - if (!dri_image_drawable_get_buffers(drawable, &images, - statts, statts_count)) - return; - } - else { - buffers = dri2_drawable_get_buffers(drawable, statts, &num_buffers); - if (!buffers || (drawable->old_num == num_buffers && - drawable->old_w == dri_drawable->w && - drawable->old_h == dri_drawable->h && - memcmp(drawable->old, buffers, - sizeof(__DRIbuffer) * num_buffers) == 0)) - return; - } - - /* Second clean useless resources*/ - - /* See if we need a depth-stencil buffer. */ - for (i = 0; i < statts_count; i++) { - if (statts[i] == ST_ATTACHMENT_DEPTH_STENCIL) { - alloc_depthstencil = TRUE; - break; - } - } - - /* Delete the resources we won't need. */ - for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { - /* Don't delete the depth-stencil buffer, we can reuse it. */ - if (i == ST_ATTACHMENT_DEPTH_STENCIL && alloc_depthstencil) - continue; - - /* Flush the texture before unreferencing, so that other clients can - * see what the driver has rendered. - */ - if (i != ST_ATTACHMENT_DEPTH_STENCIL && drawable->textures[i]) { - struct pipe_context *pipe = ctx->st->pipe; - pipe->flush_resource(pipe, drawable->textures[i]); - } - - pipe_resource_reference(&drawable->textures[i], NULL); - } - - if (drawable->stvis.samples > 1) { - for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { - boolean del = TRUE; - - /* Don't delete MSAA resources for the attachments which are enabled, - * we can reuse them. */ - for (j = 0; j < statts_count; j++) { - if (i == statts[j]) { - del = FALSE; - break; - } - } - - if (del) { - pipe_resource_reference(&drawable->msaa_textures[i], NULL); - } - } - } - - /* Third use the buffers retrieved to fill the drawable info */ - - memset(&templ, 0, sizeof(templ)); - templ.target = screen->target; - templ.last_level = 0; - templ.depth0 = 1; - templ.array_size = 1; - - if (image) { - if (images.image_mask & __DRI_IMAGE_BUFFER_FRONT) { - struct pipe_resource **buf = - &drawable->textures[ST_ATTACHMENT_FRONT_LEFT]; - struct pipe_resource *texture = images.front->texture; - - dri_drawable->w = texture->width0; - dri_drawable->h = texture->height0; - - pipe_resource_reference(buf, texture); - } - - if (images.image_mask & __DRI_IMAGE_BUFFER_BACK) { - struct pipe_resource **buf = - &drawable->textures[ST_ATTACHMENT_BACK_LEFT]; - struct pipe_resource *texture = images.back->texture; - - dri_drawable->w = texture->width0; - dri_drawable->h = texture->height0; - - pipe_resource_reference(buf, texture); - } - - /* Note: if there is both a back and a front buffer, - * then they have the same size. - */ - templ.width0 = dri_drawable->w; - templ.height0 = dri_drawable->h; - } - else { - memset(&whandle, 0, sizeof(whandle)); - - /* Process DRI-provided buffers and get pipe_resources. */ - for (i = 0; i < num_buffers; i++) { - __DRIbuffer *buf = &buffers[i]; - enum st_attachment_type statt; - enum pipe_format format; - - switch (buf->attachment) { - case __DRI_BUFFER_FRONT_LEFT: - if (!screen->auto_fake_front) { - continue; /* invalid attachment */ - } - /* fallthrough */ - case __DRI_BUFFER_FAKE_FRONT_LEFT: - statt = ST_ATTACHMENT_FRONT_LEFT; - break; - case __DRI_BUFFER_BACK_LEFT: - statt = ST_ATTACHMENT_BACK_LEFT; - break; - default: - continue; /* invalid attachment */ - } - - dri_drawable_get_format(drawable, statt, &format, &bind); - if (format == PIPE_FORMAT_NONE) - continue; - - /* dri2_drawable_get_buffers has already filled dri_drawable->w - * and dri_drawable->h */ - templ.width0 = dri_drawable->w; - templ.height0 = dri_drawable->h; - templ.format = format; - templ.bind = bind; - whandle.handle = buf->name; - whandle.stride = buf->pitch; - whandle.offset = 0; - whandle.format = format; - whandle.modifier = DRM_FORMAT_MOD_INVALID; - if (screen->can_share_buffer) - whandle.type = WINSYS_HANDLE_TYPE_SHARED; - else - whandle.type = WINSYS_HANDLE_TYPE_KMS; - drawable->textures[statt] = - screen->base.screen->resource_from_handle(screen->base.screen, - &templ, &whandle, - PIPE_HANDLE_USAGE_EXPLICIT_FLUSH); - assert(drawable->textures[statt]); - } - } - - /* Allocate private MSAA colorbuffers. */ - if (drawable->stvis.samples > 1) { - for (i = 0; i < statts_count; i++) { - enum st_attachment_type statt = statts[i]; - - if (statt == ST_ATTACHMENT_DEPTH_STENCIL) - continue; - - if (drawable->textures[statt]) { - templ.format = drawable->textures[statt]->format; - templ.bind = drawable->textures[statt]->bind & - ~(PIPE_BIND_SCANOUT | PIPE_BIND_SHARED); - templ.nr_samples = drawable->stvis.samples; - templ.nr_storage_samples = drawable->stvis.samples; - - /* Try to reuse the resource. - * (the other resource parameters should be constant) - */ - if (!drawable->msaa_textures[statt] || - drawable->msaa_textures[statt]->width0 != templ.width0 || - drawable->msaa_textures[statt]->height0 != templ.height0) { - /* Allocate a new one. */ - pipe_resource_reference(&drawable->msaa_textures[statt], NULL); - - drawable->msaa_textures[statt] = - screen->base.screen->resource_create(screen->base.screen, - &templ); - assert(drawable->msaa_textures[statt]); - - /* If there are any MSAA resources, we should initialize them - * such that they contain the same data as the single-sample - * resources we just got from the X server. - * - * The reason for this is that the state tracker (and - * therefore the app) can access the MSAA resources only. - * The single-sample resources are not exposed - * to the state tracker. - * - */ - dri_pipe_blit(ctx->st->pipe, - drawable->msaa_textures[statt], - drawable->textures[statt]); - } - } - else { - pipe_resource_reference(&drawable->msaa_textures[statt], NULL); - } - } - } - - /* Allocate a private depth-stencil buffer. */ - if (alloc_depthstencil) { - enum st_attachment_type statt = ST_ATTACHMENT_DEPTH_STENCIL; - struct pipe_resource **zsbuf; - enum pipe_format format; - unsigned bind; - - dri_drawable_get_format(drawable, statt, &format, &bind); - - if (format) { - templ.format = format; - templ.bind = bind & ~PIPE_BIND_SHARED; - - if (drawable->stvis.samples > 1) { - templ.nr_samples = drawable->stvis.samples; - templ.nr_storage_samples = drawable->stvis.samples; - zsbuf = &drawable->msaa_textures[statt]; - } - else { - templ.nr_samples = 0; - templ.nr_storage_samples = 0; - zsbuf = &drawable->textures[statt]; - } - - /* Try to reuse the resource. - * (the other resource parameters should be constant) - */ - if (!*zsbuf || - (*zsbuf)->width0 != templ.width0 || - (*zsbuf)->height0 != templ.height0) { - /* Allocate a new one. */ - pipe_resource_reference(zsbuf, NULL); - *zsbuf = screen->base.screen->resource_create(screen->base.screen, - &templ); - assert(*zsbuf); - } - } - else { - pipe_resource_reference(&drawable->msaa_textures[statt], NULL); - pipe_resource_reference(&drawable->textures[statt], NULL); - } - } - - /* For DRI2, we may get the same buffers again from the server. - * To prevent useless imports of gem names, drawable->old* is used - * to bypass the import if we get the same buffers. This doesn't apply - * to DRI3/Wayland, users of image.loader, since the buffer is managed - * by the client (no import), and the back buffer is going to change - * at every redraw. - */ - if (!image) { - drawable->old_num = num_buffers; - drawable->old_w = dri_drawable->w; - drawable->old_h = dri_drawable->h; - memcpy(drawable->old, buffers, sizeof(__DRIbuffer) * num_buffers); - } -} - -static void -dri2_flush_frontbuffer(struct dri_context *ctx, - struct dri_drawable *drawable, - enum st_attachment_type statt) -{ - __DRIdrawable *dri_drawable = drawable->dPriv; - const __DRIimageLoaderExtension *image = drawable->sPriv->image.loader; - const __DRIdri2LoaderExtension *loader = drawable->sPriv->dri2.loader; - struct pipe_context *pipe = ctx->st->pipe; - - if (statt != ST_ATTACHMENT_FRONT_LEFT) - return; - - if (drawable->stvis.samples > 1) { - /* Resolve the front buffer. */ - dri_pipe_blit(ctx->st->pipe, - drawable->textures[ST_ATTACHMENT_FRONT_LEFT], - drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT]); - } - - if (drawable->textures[ST_ATTACHMENT_FRONT_LEFT]) { - pipe->flush_resource(pipe, drawable->textures[ST_ATTACHMENT_FRONT_LEFT]); - } - - pipe->flush(pipe, NULL, 0); - - if (image) { - image->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate); - } - else if (loader->flushFrontBuffer) { - loader->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate); - } -} - -/** - * The struct dri_drawable flush_swapbuffers callback - */ -static void -dri2_flush_swapbuffers(struct dri_context *ctx, - struct dri_drawable *drawable) -{ - __DRIdrawable *dri_drawable = drawable->dPriv; - const __DRIimageLoaderExtension *image = drawable->sPriv->image.loader; - - if (image && image->base.version >= 3 && image->flushSwapBuffers) { - image->flushSwapBuffers(dri_drawable, dri_drawable->loaderPrivate); - } -} - -static void -dri2_update_tex_buffer(struct dri_drawable *drawable, - struct dri_context *ctx, - struct pipe_resource *res) -{ - /* no-op */ -} - -static __DRIimage * -dri2_create_image_from_winsys(__DRIscreen *_screen, - int width, int height, const struct dri2_format_mapping *map, - int num_handles, struct winsys_handle *whandle, - void *loaderPrivate) -{ - struct dri_screen *screen = dri_screen(_screen); - struct pipe_screen *pscreen = screen->base.screen; - __DRIimage *img; - struct pipe_resource templ; - unsigned tex_usage = 0; - int i; - bool use_lowered = false; - - if (pscreen->is_format_supported(pscreen, map->pipe_format, screen->target, 0, 0, - PIPE_BIND_RENDER_TARGET)) - tex_usage |= PIPE_BIND_RENDER_TARGET; - if (pscreen->is_format_supported(pscreen, map->pipe_format, screen->target, 0, 0, - PIPE_BIND_SAMPLER_VIEW)) - tex_usage |= PIPE_BIND_SAMPLER_VIEW; - - if (!tex_usage && util_format_is_yuv(map->pipe_format)) { - /* YUV format sampling can be emulated by the Mesa state tracker by - * using multiple samplers of varying formats. - * If no tex_usage is set and we detect a YUV format, - * test for support of all planes' sampler formats and - * add sampler view usage. - */ - use_lowered = true; - if (dri2_yuv_dma_buf_supported(screen, map)) - tex_usage |= PIPE_BIND_SAMPLER_VIEW; - } - - if (!tex_usage) - return NULL; - - img = CALLOC_STRUCT(__DRIimageRec); - if (!img) - return NULL; - - memset(&templ, 0, sizeof(templ)); - templ.bind = tex_usage; - templ.target = screen->target; - templ.last_level = 0; - templ.depth0 = 1; - templ.array_size = 1; - - for (i = (use_lowered ? map->nplanes : num_handles) - 1; i >= 0; i--) { - struct pipe_resource *tex; - - templ.next = img->texture; - templ.width0 = width >> map->planes[i].width_shift; - templ.height0 = height >> map->planes[i].height_shift; - if (use_lowered) - templ.format = dri2_get_pipe_format_for_dri_format(map->planes[i].dri_format); - else - templ.format = map->pipe_format; - assert(templ.format != PIPE_FORMAT_NONE); - - tex = pscreen->resource_from_handle(pscreen, - &templ, &whandle[use_lowered ? map->planes[i].buffer_index : i], - PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE); - if (!tex) { - pipe_resource_reference(&img->texture, NULL); - FREE(img); - return NULL; - } - - img->texture = tex; - } - - img->level = 0; - img->layer = 0; - img->use = 0; - img->loader_private = loaderPrivate; - - return img; -} - -static __DRIimage * -dri2_create_image_from_name(__DRIscreen *_screen, - int width, int height, int format, - int name, int pitch, void *loaderPrivate) -{ - const struct dri2_format_mapping *map = dri2_get_mapping_by_format(format); - struct winsys_handle whandle; - __DRIimage *img; - - if (!map) - return NULL; - - memset(&whandle, 0, sizeof(whandle)); - whandle.type = WINSYS_HANDLE_TYPE_SHARED; - whandle.handle = name; - whandle.format = map->pipe_format; - whandle.modifier = DRM_FORMAT_MOD_INVALID; - - whandle.stride = pitch * util_format_get_blocksize(map->pipe_format); - - img = dri2_create_image_from_winsys(_screen, width, height, map, - 1, &whandle, loaderPrivate); - - if (!img) - return NULL; - - img->dri_components = map->dri_components; - img->dri_fourcc = map->dri_fourcc; - img->dri_format = map->dri_format; - - return img; -} - -static unsigned -dri2_get_modifier_num_planes(uint64_t modifier, int fourcc) -{ - const struct dri2_format_mapping *map = dri2_get_mapping_by_fourcc(fourcc); - - if (!map) - return 0; - - switch (modifier) { - case I915_FORMAT_MOD_Y_TILED_CCS: - return 2; - case DRM_FORMAT_MOD_BROADCOM_UIF: - case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED: - case DRM_FORMAT_MOD_LINEAR: - /* DRM_FORMAT_MOD_NONE is the same as LINEAR */ - case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_EIGHT_GOB: - case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_FOUR_GOB: - case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_ONE_GOB: - case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_SIXTEEN_GOB: - case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_THIRTYTWO_GOB: - case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_TWO_GOB: - case DRM_FORMAT_MOD_QCOM_COMPRESSED: - case DRM_FORMAT_MOD_VIVANTE_SPLIT_SUPER_TILED: - case DRM_FORMAT_MOD_VIVANTE_SPLIT_TILED: - case DRM_FORMAT_MOD_VIVANTE_SUPER_TILED: - case DRM_FORMAT_MOD_VIVANTE_TILED: - /* FD_FORMAT_MOD_QCOM_TILED is not in drm_fourcc.h */ - case I915_FORMAT_MOD_X_TILED: - case I915_FORMAT_MOD_Y_TILED: - case DRM_FORMAT_MOD_INVALID: - return map->nplanes; - default: - return 0; - } -} - -static __DRIimage * -dri2_create_image_from_fd(__DRIscreen *_screen, - int width, int height, int fourcc, - uint64_t modifier, int *fds, int num_fds, - int *strides, int *offsets, unsigned *error, - void *loaderPrivate) -{ - struct winsys_handle whandles[3]; - const struct dri2_format_mapping *map = dri2_get_mapping_by_fourcc(fourcc); - __DRIimage *img = NULL; - unsigned err = __DRI_IMAGE_ERROR_SUCCESS; - int i, expected_num_fds; - int num_handles = dri2_get_modifier_num_planes(modifier, fourcc); - - if (!map || num_handles == 0) { - err = __DRI_IMAGE_ERROR_BAD_MATCH; - goto exit; - } - - switch (fourcc) { - case DRM_FORMAT_YUYV: - case DRM_FORMAT_UYVY: - expected_num_fds = 1; - break; - default: - expected_num_fds = num_handles; - break; - } - - if (num_fds != expected_num_fds) { - err = __DRI_IMAGE_ERROR_BAD_MATCH; - goto exit; - } - - memset(whandles, 0, sizeof(whandles)); - - for (i = 0; i < num_fds; i++) { - if (fds[i] < 0) { - err = __DRI_IMAGE_ERROR_BAD_ALLOC; - goto exit; - } - - whandles[i].type = WINSYS_HANDLE_TYPE_FD; - whandles[i].handle = (unsigned)fds[i]; - whandles[i].stride = (unsigned)strides[i]; - whandles[i].offset = (unsigned)offsets[i]; - whandles[i].format = map->pipe_format; - whandles[i].modifier = modifier; - whandles[i].plane = i; - } - - img = dri2_create_image_from_winsys(_screen, width, height, map, - num_fds, whandles, loaderPrivate); - if(img == NULL) { - err = __DRI_IMAGE_ERROR_BAD_ALLOC; - goto exit; - } - - img->dri_components = map->dri_components; - img->dri_fourcc = fourcc; - img->dri_format = map->dri_format; - img->imported_dmabuf = TRUE; - -exit: - if (error) - *error = err; - - return img; -} - -static __DRIimage * -dri2_create_image_common(__DRIscreen *_screen, - int width, int height, - int format, unsigned int use, - const uint64_t *modifiers, - const unsigned count, - void *loaderPrivate) -{ - const struct dri2_format_mapping *map = dri2_get_mapping_by_format(format); - struct dri_screen *screen = dri_screen(_screen); - __DRIimage *img; - struct pipe_resource templ; - unsigned tex_usage; - - if (!map) - return NULL; - - tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; - - if (use & __DRI_IMAGE_USE_SCANOUT) - tex_usage |= PIPE_BIND_SCANOUT; - if (use & __DRI_IMAGE_USE_SHARE) - tex_usage |= PIPE_BIND_SHARED; - if (use & __DRI_IMAGE_USE_LINEAR) - tex_usage |= PIPE_BIND_LINEAR; - if (use & __DRI_IMAGE_USE_CURSOR) { - if (width != 64 || height != 64) - return NULL; - tex_usage |= PIPE_BIND_CURSOR; - } - - img = CALLOC_STRUCT(__DRIimageRec); - if (!img) - return NULL; - - memset(&templ, 0, sizeof(templ)); - templ.bind = tex_usage; - templ.format = map->pipe_format; - templ.target = PIPE_TEXTURE_2D; - templ.last_level = 0; - templ.width0 = width; - templ.height0 = height; - templ.depth0 = 1; - templ.array_size = 1; - - if (modifiers) - img->texture = - screen->base.screen - ->resource_create_with_modifiers(screen->base.screen, - &templ, - modifiers, - count); - else - img->texture = - screen->base.screen->resource_create(screen->base.screen, &templ); - if (!img->texture) { - FREE(img); - return NULL; - } - - img->level = 0; - img->layer = 0; - img->dri_format = format; - img->dri_fourcc = map->dri_fourcc; - img->dri_components = 0; - img->use = use; - - img->loader_private = loaderPrivate; - return img; -} - -static __DRIimage * -dri2_create_image(__DRIscreen *_screen, - int width, int height, int format, - unsigned int use, void *loaderPrivate) -{ - return dri2_create_image_common(_screen, width, height, format, use, - NULL /* modifiers */, 0 /* count */, - loaderPrivate); -} - -static __DRIimage * -dri2_create_image_with_modifiers(__DRIscreen *dri_screen, - int width, int height, int format, - const uint64_t *modifiers, - const unsigned count, - void *loaderPrivate) -{ - return dri2_create_image_common(dri_screen, width, height, format, - __DRI_IMAGE_USE_SHARE, modifiers, count, - loaderPrivate); -} - -static bool -dri2_query_image_common(__DRIimage *image, int attrib, int *value) -{ - switch (attrib) { - case __DRI_IMAGE_ATTRIB_FORMAT: - *value = image->dri_format; - return true; - case __DRI_IMAGE_ATTRIB_WIDTH: - *value = image->texture->width0; - return true; - case __DRI_IMAGE_ATTRIB_HEIGHT: - *value = image->texture->height0; - return true; - case __DRI_IMAGE_ATTRIB_COMPONENTS: - if (image->dri_components == 0) - return false; - *value = image->dri_components; - return true; - case __DRI_IMAGE_ATTRIB_FOURCC: - if (image->dri_fourcc) { - *value = image->dri_fourcc; - } else { - const struct dri2_format_mapping *map; - - map = dri2_get_mapping_by_format(image->dri_format); - if (!map) - return false; - - *value = map->dri_fourcc; - } - return true; - default: - return false; - } -} - -static bool -dri2_query_image_by_resource_handle(__DRIimage *image, int attrib, int *value) -{ - struct pipe_screen *pscreen = image->texture->screen; - struct winsys_handle whandle; - unsigned usage; - memset(&whandle, 0, sizeof(whandle)); - whandle.plane = image->plane; - - switch (attrib) { - case __DRI_IMAGE_ATTRIB_STRIDE: - case __DRI_IMAGE_ATTRIB_OFFSET: - case __DRI_IMAGE_ATTRIB_HANDLE: - whandle.type = WINSYS_HANDLE_TYPE_KMS; - break; - case __DRI_IMAGE_ATTRIB_NAME: - whandle.type = WINSYS_HANDLE_TYPE_SHARED; - break; - case __DRI_IMAGE_ATTRIB_FD: - whandle.type = WINSYS_HANDLE_TYPE_FD; - break; - case __DRI_IMAGE_ATTRIB_NUM_PLANES: - *value = 1; - return true; - case __DRI_IMAGE_ATTRIB_MODIFIER_UPPER: - case __DRI_IMAGE_ATTRIB_MODIFIER_LOWER: - whandle.type = WINSYS_HANDLE_TYPE_KMS; - whandle.modifier = DRM_FORMAT_MOD_INVALID; - break; - default: - return false; - } - - usage = PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE; - - if (image->use & __DRI_IMAGE_USE_BACKBUFFER) - usage |= PIPE_HANDLE_USAGE_EXPLICIT_FLUSH; - - if (!pscreen->resource_get_handle(pscreen, NULL, image->texture, - &whandle, usage)) - return false; - - switch (attrib) { - case __DRI_IMAGE_ATTRIB_STRIDE: - *value = whandle.stride; - return true; - case __DRI_IMAGE_ATTRIB_OFFSET: - *value = whandle.offset; - return true; - case __DRI_IMAGE_ATTRIB_HANDLE: - case __DRI_IMAGE_ATTRIB_NAME: - case __DRI_IMAGE_ATTRIB_FD: - *value = whandle.handle; - return true; - case __DRI_IMAGE_ATTRIB_MODIFIER_UPPER: - if (whandle.modifier == DRM_FORMAT_MOD_INVALID) - return false; - *value = (whandle.modifier >> 32) & 0xffffffff; - return true; - case __DRI_IMAGE_ATTRIB_MODIFIER_LOWER: - if (whandle.modifier == DRM_FORMAT_MOD_INVALID) - return false; - *value = whandle.modifier & 0xffffffff; - return true; - default: - return false; - } -} - -static bool -dri2_resource_get_param(__DRIimage *image, enum pipe_resource_param param, - unsigned handle_usage, uint64_t *value) -{ - struct pipe_screen *pscreen = image->texture->screen; - if (!pscreen->resource_get_param) - return false; - - return pscreen->resource_get_param(pscreen, NULL, image->texture, - image->plane, 0, param, handle_usage, - value); -} - -static bool -dri2_query_image_by_resource_param(__DRIimage *image, int attrib, int *value) -{ - enum pipe_resource_param param; - uint64_t res_param; - unsigned handle_usage; - - if (!image->texture->screen->resource_get_param) - return false; - - switch (attrib) { - case __DRI_IMAGE_ATTRIB_STRIDE: - param = PIPE_RESOURCE_PARAM_STRIDE; - break; - case __DRI_IMAGE_ATTRIB_OFFSET: - param = PIPE_RESOURCE_PARAM_OFFSET; - break; - case __DRI_IMAGE_ATTRIB_NUM_PLANES: - param = PIPE_RESOURCE_PARAM_NPLANES; - break; - case __DRI_IMAGE_ATTRIB_MODIFIER_UPPER: - case __DRI_IMAGE_ATTRIB_MODIFIER_LOWER: - param = PIPE_RESOURCE_PARAM_MODIFIER; - break; - case __DRI_IMAGE_ATTRIB_HANDLE: - param = PIPE_RESOURCE_PARAM_HANDLE_TYPE_KMS; - break; - case __DRI_IMAGE_ATTRIB_NAME: - param = PIPE_RESOURCE_PARAM_HANDLE_TYPE_SHARED; - break; - case __DRI_IMAGE_ATTRIB_FD: - param = PIPE_RESOURCE_PARAM_HANDLE_TYPE_FD; - break; - default: - return false; - } - - handle_usage = PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE; - - if (image->use & __DRI_IMAGE_USE_BACKBUFFER) - handle_usage |= PIPE_HANDLE_USAGE_EXPLICIT_FLUSH; - - if (!dri2_resource_get_param(image, param, handle_usage, &res_param)) - return false; - - switch (attrib) { - case __DRI_IMAGE_ATTRIB_STRIDE: - case __DRI_IMAGE_ATTRIB_OFFSET: - case __DRI_IMAGE_ATTRIB_NUM_PLANES: - if (res_param > INT_MAX) - return false; - *value = (int)res_param; - return true; - case __DRI_IMAGE_ATTRIB_HANDLE: - case __DRI_IMAGE_ATTRIB_NAME: - case __DRI_IMAGE_ATTRIB_FD: - if (res_param > UINT_MAX) - return false; - *value = (int)res_param; - return true; - case __DRI_IMAGE_ATTRIB_MODIFIER_UPPER: - if (res_param == DRM_FORMAT_MOD_INVALID) - return false; - *value = (res_param >> 32) & 0xffffffff; - return true; - case __DRI_IMAGE_ATTRIB_MODIFIER_LOWER: - if (res_param == DRM_FORMAT_MOD_INVALID) - return false; - *value = res_param & 0xffffffff; - return true; - default: - return false; - } -} - -static GLboolean -dri2_query_image(__DRIimage *image, int attrib, int *value) -{ - if (dri2_query_image_common(image, attrib, value)) - return GL_TRUE; - else if (dri2_query_image_by_resource_param(image, attrib, value)) - return GL_TRUE; - else if (dri2_query_image_by_resource_handle(image, attrib, value)) - return GL_TRUE; - else - return GL_FALSE; -} - -static __DRIimage * -dri2_dup_image(__DRIimage *image, void *loaderPrivate) -{ - __DRIimage *img; - - img = CALLOC_STRUCT(__DRIimageRec); - if (!img) - return NULL; - - img->texture = NULL; - pipe_resource_reference(&img->texture, image->texture); - img->level = image->level; - img->layer = image->layer; - img->dri_format = image->dri_format; - /* This should be 0 for sub images, but dup is also used for base images. */ - img->dri_components = image->dri_components; - img->loader_private = loaderPrivate; - - return img; -} - -static GLboolean -dri2_validate_usage(__DRIimage *image, unsigned int use) -{ - if (!image || !image->texture) - return false; - - struct pipe_screen *screen = image->texture->screen; - if (!screen->check_resource_capability) - return true; - - /* We don't want to check these: - * __DRI_IMAGE_USE_SHARE (all images are shareable) - * __DRI_IMAGE_USE_BACKBUFFER (all images support this) - */ - unsigned bind = 0; - if (use & __DRI_IMAGE_USE_SCANOUT) - bind |= PIPE_BIND_SCANOUT; - if (use & __DRI_IMAGE_USE_LINEAR) - bind |= PIPE_BIND_LINEAR; - if (use & __DRI_IMAGE_USE_CURSOR) - bind |= PIPE_BIND_CURSOR; - - if (!bind) - return true; - - return screen->check_resource_capability(screen, image->texture, bind); -} - -static __DRIimage * -dri2_from_names(__DRIscreen *screen, int width, int height, int format, - int *names, int num_names, int *strides, int *offsets, - void *loaderPrivate) -{ - const struct dri2_format_mapping *map = dri2_get_mapping_by_format(format); - __DRIimage *img; - struct winsys_handle whandle; - - if (!map) - return NULL; - - if (num_names != 1) - return NULL; - - memset(&whandle, 0, sizeof(whandle)); - whandle.type = WINSYS_HANDLE_TYPE_SHARED; - whandle.handle = names[0]; - whandle.stride = strides[0]; - whandle.offset = offsets[0]; - whandle.format = map->pipe_format; - whandle.modifier = DRM_FORMAT_MOD_INVALID; - - img = dri2_create_image_from_winsys(screen, width, height, map, - 1, &whandle, loaderPrivate); - if (img == NULL) - return NULL; - - img->dri_components = map->dri_components; - img->dri_fourcc = map->dri_fourcc; - img->dri_format = map->pipe_format; - - return img; -} - -static __DRIimage * -dri2_from_planar(__DRIimage *image, int plane, void *loaderPrivate) -{ - __DRIimage *img; - - if (plane < 0) { - return NULL; - } else if (plane > 0) { - uint64_t planes; - if (!dri2_resource_get_param(image, PIPE_RESOURCE_PARAM_NPLANES, 0, - &planes) || - plane >= planes) { - return NULL; - } - } - - if (image->dri_components == 0) { - uint64_t modifier; - if (!dri2_resource_get_param(image, PIPE_RESOURCE_PARAM_MODIFIER, 0, - &modifier) || - modifier == DRM_FORMAT_MOD_INVALID) { - return NULL; - } - } - - img = dri2_dup_image(image, loaderPrivate); - if (img == NULL) - return NULL; - - if (img->texture->screen->resource_changed) - img->texture->screen->resource_changed(img->texture->screen, - img->texture); - - /* set this to 0 for sub images. */ - img->dri_components = 0; - img->plane = plane; - return img; -} - -static __DRIimage * -dri2_from_fds(__DRIscreen *screen, int width, int height, int fourcc, - int *fds, int num_fds, int *strides, int *offsets, - void *loaderPrivate) -{ - return dri2_create_image_from_fd(screen, width, height, fourcc, - DRM_FORMAT_MOD_INVALID, fds, num_fds, - strides, offsets, NULL, loaderPrivate); -} - -static boolean -dri2_query_dma_buf_modifiers(__DRIscreen *_screen, int fourcc, int max, - uint64_t *modifiers, unsigned int *external_only, - int *count) -{ - struct dri_screen *screen = dri_screen(_screen); - struct pipe_screen *pscreen = screen->base.screen; - const struct dri2_format_mapping *map = dri2_get_mapping_by_fourcc(fourcc); - enum pipe_format format; - - if (!map) - return false; - - format = map->pipe_format; - - if (pscreen->is_format_supported(pscreen, format, screen->target, 0, 0, - PIPE_BIND_RENDER_TARGET) || - pscreen->is_format_supported(pscreen, format, screen->target, 0, 0, - PIPE_BIND_SAMPLER_VIEW) || - dri2_yuv_dma_buf_supported(screen, map)) { - if (pscreen->query_dmabuf_modifiers != NULL) - pscreen->query_dmabuf_modifiers(pscreen, format, max, modifiers, - external_only, count); - else - *count = 0; - return true; - } - return false; -} - -static boolean -dri2_query_dma_buf_format_modifier_attribs(__DRIscreen *_screen, - uint32_t fourcc, uint64_t modifier, - int attrib, uint64_t *value) -{ - struct dri_screen *screen = dri_screen(_screen); - struct pipe_screen *pscreen = screen->base.screen; - - if (!pscreen->query_dmabuf_modifiers) - return false; - - switch (attrib) { - case __DRI_IMAGE_FORMAT_MODIFIER_ATTRIB_PLANE_COUNT: { - uint64_t mod_planes = dri2_get_modifier_num_planes(modifier, fourcc); - if (mod_planes > 0) - *value = mod_planes; - return mod_planes > 0; - } - default: - return false; - } -} - -static __DRIimage * -dri2_from_dma_bufs(__DRIscreen *screen, - int width, int height, int fourcc, - int *fds, int num_fds, - int *strides, int *offsets, - enum __DRIYUVColorSpace yuv_color_space, - enum __DRISampleRange sample_range, - enum __DRIChromaSiting horizontal_siting, - enum __DRIChromaSiting vertical_siting, - unsigned *error, - void *loaderPrivate) -{ - __DRIimage *img; - - img = dri2_create_image_from_fd(screen, width, height, fourcc, - DRM_FORMAT_MOD_INVALID, fds, num_fds, - strides, offsets, error, loaderPrivate); - if (img == NULL) - return NULL; - - img->yuv_color_space = yuv_color_space; - img->sample_range = sample_range; - img->horizontal_siting = horizontal_siting; - img->vertical_siting = vertical_siting; - - *error = __DRI_IMAGE_ERROR_SUCCESS; - return img; -} - -static __DRIimage * -dri2_from_dma_bufs2(__DRIscreen *screen, - int width, int height, int fourcc, - uint64_t modifier, int *fds, int num_fds, - int *strides, int *offsets, - enum __DRIYUVColorSpace yuv_color_space, - enum __DRISampleRange sample_range, - enum __DRIChromaSiting horizontal_siting, - enum __DRIChromaSiting vertical_siting, - unsigned *error, - void *loaderPrivate) -{ - __DRIimage *img; - - img = dri2_create_image_from_fd(screen, width, height, fourcc, - modifier, fds, num_fds, strides, offsets, - error, loaderPrivate); - if (img == NULL) - return NULL; - - img->yuv_color_space = yuv_color_space; - img->sample_range = sample_range; - img->horizontal_siting = horizontal_siting; - img->vertical_siting = vertical_siting; - - *error = __DRI_IMAGE_ERROR_SUCCESS; - return img; -} - -static void -dri2_blit_image(__DRIcontext *context, __DRIimage *dst, __DRIimage *src, - int dstx0, int dsty0, int dstwidth, int dstheight, - int srcx0, int srcy0, int srcwidth, int srcheight, - int flush_flag) -{ - struct dri_context *ctx = dri_context(context); - struct pipe_context *pipe = ctx->st->pipe; - struct pipe_screen *screen; - struct pipe_fence_handle *fence; - struct pipe_blit_info blit; - - if (!dst || !src) - return; - - memset(&blit, 0, sizeof(blit)); - blit.dst.resource = dst->texture; - blit.dst.box.x = dstx0; - blit.dst.box.y = dsty0; - blit.dst.box.width = dstwidth; - blit.dst.box.height = dstheight; - blit.dst.box.depth = 1; - blit.dst.format = dst->texture->format; - blit.src.resource = src->texture; - blit.src.box.x = srcx0; - blit.src.box.y = srcy0; - blit.src.box.width = srcwidth; - blit.src.box.height = srcheight; - blit.src.box.depth = 1; - blit.src.format = src->texture->format; - blit.mask = PIPE_MASK_RGBA; - blit.filter = PIPE_TEX_FILTER_NEAREST; - - pipe->blit(pipe, &blit); - - if (flush_flag == __BLIT_FLAG_FLUSH) { - pipe->flush_resource(pipe, dst->texture); - ctx->st->flush(ctx->st, 0, NULL, NULL, NULL); - } else if (flush_flag == __BLIT_FLAG_FINISH) { - screen = dri_screen(ctx->sPriv)->base.screen; - pipe->flush_resource(pipe, dst->texture); - ctx->st->flush(ctx->st, 0, &fence, NULL, NULL); - (void) screen->fence_finish(screen, NULL, fence, PIPE_TIMEOUT_INFINITE); - screen->fence_reference(screen, &fence, NULL); - } -} - -static void * -dri2_map_image(__DRIcontext *context, __DRIimage *image, - int x0, int y0, int width, int height, - unsigned int flags, int *stride, void **data) -{ - struct dri_context *ctx = dri_context(context); - struct pipe_context *pipe = ctx->st->pipe; - enum pipe_transfer_usage pipe_access = 0; - struct pipe_transfer *trans; - void *map; - - if (!image || !data || *data) - return NULL; - - if (flags & __DRI_IMAGE_TRANSFER_READ) - pipe_access |= PIPE_TRANSFER_READ; - if (flags & __DRI_IMAGE_TRANSFER_WRITE) - pipe_access |= PIPE_TRANSFER_WRITE; - - map = pipe_transfer_map(pipe, image->texture, - 0, 0, pipe_access, x0, y0, width, height, - &trans); - if (map) { - *data = trans; - *stride = trans->stride; - } - - return map; -} - -static void -dri2_unmap_image(__DRIcontext *context, __DRIimage *image, void *data) -{ - struct dri_context *ctx = dri_context(context); - struct pipe_context *pipe = ctx->st->pipe; - - pipe_transfer_unmap(pipe, (struct pipe_transfer *)data); -} - -static int -dri2_get_capabilities(__DRIscreen *_screen) -{ - struct dri_screen *screen = dri_screen(_screen); - - return (screen->can_share_buffer ? __DRI_IMAGE_CAP_GLOBAL_NAMES : 0); -} - -/* The extension is modified during runtime if DRI_PRIME is detected */ -static __DRIimageExtension dri2ImageExtension = { - .base = { __DRI_IMAGE, 17 }, - - .createImageFromName = dri2_create_image_from_name, - .createImageFromRenderbuffer = dri2_create_image_from_renderbuffer, - .destroyImage = dri2_destroy_image, - .createImage = dri2_create_image, - .queryImage = dri2_query_image, - .dupImage = dri2_dup_image, - .validateUsage = dri2_validate_usage, - .createImageFromNames = dri2_from_names, - .fromPlanar = dri2_from_planar, - .createImageFromTexture = dri2_create_from_texture, - .createImageFromFds = NULL, - .createImageFromDmaBufs = NULL, - .blitImage = dri2_blit_image, - .getCapabilities = dri2_get_capabilities, - .mapImage = dri2_map_image, - .unmapImage = dri2_unmap_image, - .createImageWithModifiers = NULL, - .createImageFromDmaBufs2 = NULL, - .queryDmaBufFormats = NULL, - .queryDmaBufModifiers = NULL, - .queryDmaBufFormatModifierAttribs = NULL, - .createImageFromRenderbuffer2 = dri2_create_image_from_renderbuffer2, -}; - -static const __DRIrobustnessExtension dri2Robustness = { - .base = { __DRI2_ROBUSTNESS, 1 } -}; - -static int -dri2_interop_query_device_info(__DRIcontext *_ctx, - struct mesa_glinterop_device_info *out) -{ - struct pipe_screen *screen = dri_context(_ctx)->st->pipe->screen; - - /* There is no version 0, thus we do not support it */ - if (out->version == 0) - return MESA_GLINTEROP_INVALID_VERSION; - - out->pci_segment_group = screen->get_param(screen, PIPE_CAP_PCI_GROUP); - out->pci_bus = screen->get_param(screen, PIPE_CAP_PCI_BUS); - out->pci_device = screen->get_param(screen, PIPE_CAP_PCI_DEVICE); - out->pci_function = screen->get_param(screen, PIPE_CAP_PCI_FUNCTION); - - out->vendor_id = screen->get_param(screen, PIPE_CAP_VENDOR_ID); - out->device_id = screen->get_param(screen, PIPE_CAP_DEVICE_ID); - - /* Instruct the caller that we support up-to version one of the interface */ - out->version = 1; - - return MESA_GLINTEROP_SUCCESS; -} - -static int -dri2_interop_export_object(__DRIcontext *_ctx, - struct mesa_glinterop_export_in *in, - struct mesa_glinterop_export_out *out) -{ - struct st_context_iface *st = dri_context(_ctx)->st; - struct pipe_screen *screen = st->pipe->screen; - struct gl_context *ctx = ((struct st_context *)st)->ctx; - struct pipe_resource *res = NULL; - struct winsys_handle whandle; - unsigned target, usage; - boolean success; - - /* There is no version 0, thus we do not support it */ - if (in->version == 0 || out->version == 0) - return MESA_GLINTEROP_INVALID_VERSION; - - /* Validate the target. */ - switch (in->target) { - case GL_TEXTURE_BUFFER: - case GL_TEXTURE_1D: - case GL_TEXTURE_2D: - case GL_TEXTURE_3D: - case GL_TEXTURE_RECTANGLE: - case GL_TEXTURE_1D_ARRAY: - case GL_TEXTURE_2D_ARRAY: - case GL_TEXTURE_CUBE_MAP_ARRAY: - case GL_TEXTURE_CUBE_MAP: - case GL_TEXTURE_2D_MULTISAMPLE: - case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: - case GL_TEXTURE_EXTERNAL_OES: - case GL_RENDERBUFFER: - case GL_ARRAY_BUFFER: - target = in->target; - break; - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - target = GL_TEXTURE_CUBE_MAP; - break; - default: - return MESA_GLINTEROP_INVALID_TARGET; - } - - /* Validate the simple case of miplevel. */ - if ((target == GL_RENDERBUFFER || target == GL_ARRAY_BUFFER) && - in->miplevel != 0) - return MESA_GLINTEROP_INVALID_MIP_LEVEL; - - /* Validate the OpenGL object and get pipe_resource. */ - simple_mtx_lock(&ctx->Shared->Mutex); - - if (target == GL_ARRAY_BUFFER) { - /* Buffer objects. - * - * The error checking is based on the documentation of - * clCreateFromGLBuffer from OpenCL 2.0 SDK. - */ - struct gl_buffer_object *buf = _mesa_lookup_bufferobj(ctx, in->obj); - - /* From OpenCL 2.0 SDK, clCreateFromGLBuffer: - * "CL_INVALID_GL_OBJECT if bufobj is not a GL buffer object or is - * a GL buffer object but does not have an existing data store or - * the size of the buffer is 0." - */ - if (!buf || buf->Size == 0) { - simple_mtx_unlock(&ctx->Shared->Mutex); - return MESA_GLINTEROP_INVALID_OBJECT; - } - - res = st_buffer_object(buf)->buffer; - if (!res) { - /* this shouldn't happen */ - simple_mtx_unlock(&ctx->Shared->Mutex); - return MESA_GLINTEROP_INVALID_OBJECT; - } - - out->buf_offset = 0; - out->buf_size = buf->Size; - - buf->UsageHistory |= USAGE_DISABLE_MINMAX_CACHE; - } else if (target == GL_RENDERBUFFER) { - /* Renderbuffers. - * - * The error checking is based on the documentation of - * clCreateFromGLRenderbuffer from OpenCL 2.0 SDK. - */ - struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, in->obj); - - /* From OpenCL 2.0 SDK, clCreateFromGLRenderbuffer: - * "CL_INVALID_GL_OBJECT if renderbuffer is not a GL renderbuffer - * object or if the width or height of renderbuffer is zero." - */ - if (!rb || rb->Width == 0 || rb->Height == 0) { - simple_mtx_unlock(&ctx->Shared->Mutex); - return MESA_GLINTEROP_INVALID_OBJECT; - } - - /* From OpenCL 2.0 SDK, clCreateFromGLRenderbuffer: - * "CL_INVALID_OPERATION if renderbuffer is a multi-sample GL - * renderbuffer object." - */ - if (rb->NumSamples > 1) { - simple_mtx_unlock(&ctx->Shared->Mutex); - return MESA_GLINTEROP_INVALID_OPERATION; - } - - /* From OpenCL 2.0 SDK, clCreateFromGLRenderbuffer: - * "CL_OUT_OF_RESOURCES if there is a failure to allocate resources - * required by the OpenCL implementation on the device." - */ - res = st_renderbuffer(rb)->texture; - if (!res) { - simple_mtx_unlock(&ctx->Shared->Mutex); - return MESA_GLINTEROP_OUT_OF_RESOURCES; - } - - out->internal_format = rb->InternalFormat; - out->view_minlevel = 0; - out->view_numlevels = 1; - out->view_minlayer = 0; - out->view_numlayers = 1; - } else { - /* Texture objects. - * - * The error checking is based on the documentation of - * clCreateFromGLTexture from OpenCL 2.0 SDK. - */ - struct gl_texture_object *obj = _mesa_lookup_texture(ctx, in->obj); - - if (obj) - _mesa_test_texobj_completeness(ctx, obj); - - /* From OpenCL 2.0 SDK, clCreateFromGLTexture: - * "CL_INVALID_GL_OBJECT if texture is not a GL texture object whose - * type matches texture_target, if the specified miplevel of texture - * is not defined, or if the width or height of the specified - * miplevel is zero or if the GL texture object is incomplete." - */ - if (!obj || - obj->Target != target || - !obj->_BaseComplete || - (in->miplevel > 0 && !obj->_MipmapComplete)) { - simple_mtx_unlock(&ctx->Shared->Mutex); - return MESA_GLINTEROP_INVALID_OBJECT; - } - - if (target == GL_TEXTURE_BUFFER) { - struct st_buffer_object *stBuf = - st_buffer_object(obj->BufferObject); - - if (!stBuf || !stBuf->buffer) { - /* this shouldn't happen */ - simple_mtx_unlock(&ctx->Shared->Mutex); - return MESA_GLINTEROP_INVALID_OBJECT; - } - res = stBuf->buffer; - - out->internal_format = obj->BufferObjectFormat; - out->buf_offset = obj->BufferOffset; - out->buf_size = obj->BufferSize == -1 ? obj->BufferObject->Size : - obj->BufferSize; - - obj->BufferObject->UsageHistory |= USAGE_DISABLE_MINMAX_CACHE; - } else { - /* From OpenCL 2.0 SDK, clCreateFromGLTexture: - * "CL_INVALID_MIP_LEVEL if miplevel is less than the value of - * levelbase (for OpenGL implementations) or zero (for OpenGL ES - * implementations); or greater than the value of q (for both OpenGL - * and OpenGL ES). levelbase and q are defined for the texture in - * section 3.8.10 (Texture Completeness) of the OpenGL 2.1 - * specification and section 3.7.10 of the OpenGL ES 2.0." - */ - if (in->miplevel < obj->BaseLevel || in->miplevel > obj->_MaxLevel) { - simple_mtx_unlock(&ctx->Shared->Mutex); - return MESA_GLINTEROP_INVALID_MIP_LEVEL; - } - - if (!st_finalize_texture(ctx, st->pipe, obj, 0)) { - simple_mtx_unlock(&ctx->Shared->Mutex); - return MESA_GLINTEROP_OUT_OF_RESOURCES; - } - - res = st_get_texobj_resource(obj); - if (!res) { - /* Incomplete texture buffer object? This shouldn't really occur. */ - simple_mtx_unlock(&ctx->Shared->Mutex); - return MESA_GLINTEROP_INVALID_OBJECT; - } - - out->internal_format = obj->Image[0][0]->InternalFormat; - out->view_minlevel = obj->MinLevel; - out->view_numlevels = obj->NumLevels; - out->view_minlayer = obj->MinLayer; - out->view_numlayers = obj->NumLayers; - } - } - - /* Get the handle. */ - switch (in->access) { - case MESA_GLINTEROP_ACCESS_READ_ONLY: - usage = 0; - break; - case MESA_GLINTEROP_ACCESS_READ_WRITE: - case MESA_GLINTEROP_ACCESS_WRITE_ONLY: - usage = PIPE_HANDLE_USAGE_SHADER_WRITE; - break; - default: - usage = 0; - } - - memset(&whandle, 0, sizeof(whandle)); - whandle.type = WINSYS_HANDLE_TYPE_FD; - - success = screen->resource_get_handle(screen, st->pipe, res, &whandle, - usage); - simple_mtx_unlock(&ctx->Shared->Mutex); - - if (!success) - return MESA_GLINTEROP_OUT_OF_HOST_MEMORY; - - out->dmabuf_fd = whandle.handle; - out->out_driver_data_written = 0; - - if (res->target == PIPE_BUFFER) - out->buf_offset += whandle.offset; - - /* Instruct the caller that we support up-to version one of the interface */ - in->version = 1; - out->version = 1; - - return MESA_GLINTEROP_SUCCESS; -} - -static const __DRI2interopExtension dri2InteropExtension = { - .base = { __DRI2_INTEROP, 1 }, - .query_device_info = dri2_interop_query_device_info, - .export_object = dri2_interop_export_object -}; - -/** - * \brief the DRI2bufferDamageExtension set_damage_region method - */ -static void -dri2_set_damage_region(__DRIdrawable *dPriv, unsigned int nrects, int *rects) -{ - struct dri_drawable *drawable = dri_drawable(dPriv); - struct pipe_box *boxes = NULL; - - if (nrects) { - boxes = CALLOC(nrects, sizeof(*boxes)); - assert(boxes); - - for (unsigned int i = 0; i < nrects; i++) { - int *rect = &rects[i * 4]; - - u_box_2d(rect[0], rect[1], rect[2], rect[3], &boxes[i]); - } - } - - FREE(drawable->damage_rects); - drawable->damage_rects = boxes; - drawable->num_damage_rects = nrects; - - /* Only apply the damage region if the BACK_LEFT texture is up-to-date. */ - if (drawable->texture_stamp == drawable->dPriv->lastStamp && - (drawable->texture_mask & (1 << ST_ATTACHMENT_BACK_LEFT))) { - struct pipe_screen *screen = drawable->screen->base.screen; - struct pipe_resource *resource; - - if (drawable->stvis.samples > 1) - resource = drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT]; - else - resource = drawable->textures[ST_ATTACHMENT_BACK_LEFT]; - - screen->set_damage_region(screen, resource, - drawable->num_damage_rects, - drawable->damage_rects); - } -} - -static __DRI2bufferDamageExtension dri2BufferDamageExtension = { - .base = { __DRI2_BUFFER_DAMAGE, 1 }, -}; - -/** - * \brief the DRI2ConfigQueryExtension configQueryb method - */ -static int -dri2GalliumConfigQueryb(__DRIscreen *sPriv, const char *var, - unsigned char *val) -{ - struct dri_screen *screen = dri_screen(sPriv); - - if (!driCheckOption(&screen->dev->option_cache, var, DRI_BOOL)) - return dri2ConfigQueryExtension.configQueryb(sPriv, var, val); - - *val = driQueryOptionb(&screen->dev->option_cache, var); - - return 0; -} - -/** - * \brief the DRI2ConfigQueryExtension configQueryi method - */ -static int -dri2GalliumConfigQueryi(__DRIscreen *sPriv, const char *var, int *val) -{ - struct dri_screen *screen = dri_screen(sPriv); - - if (!driCheckOption(&screen->dev->option_cache, var, DRI_INT) && - !driCheckOption(&screen->dev->option_cache, var, DRI_ENUM)) - return dri2ConfigQueryExtension.configQueryi(sPriv, var, val); - - *val = driQueryOptioni(&screen->dev->option_cache, var); - - return 0; -} - -/** - * \brief the DRI2ConfigQueryExtension configQueryf method - */ -static int -dri2GalliumConfigQueryf(__DRIscreen *sPriv, const char *var, float *val) -{ - struct dri_screen *screen = dri_screen(sPriv); - - if (!driCheckOption(&screen->dev->option_cache, var, DRI_FLOAT)) - return dri2ConfigQueryExtension.configQueryf(sPriv, var, val); - - *val = driQueryOptionf(&screen->dev->option_cache, var); - - return 0; -} - -/** - * \brief the DRI2ConfigQueryExtension struct. - * - * We first query the driver option cache. Then the dri2 option cache. - */ -static const __DRI2configQueryExtension dri2GalliumConfigQueryExtension = { - .base = { __DRI2_CONFIG_QUERY, 1 }, - - .configQueryb = dri2GalliumConfigQueryb, - .configQueryi = dri2GalliumConfigQueryi, - .configQueryf = dri2GalliumConfigQueryf, -}; - -/** - * \brief the DRI2blobExtension set_cache_funcs method - */ -static void -set_blob_cache_funcs(__DRIscreen *sPriv, __DRIblobCacheSet set, - __DRIblobCacheGet get) -{ - struct dri_screen *screen = dri_screen(sPriv); - struct pipe_screen *pscreen = screen->base.screen; - - if (!pscreen->get_disk_shader_cache) - return; - - struct disk_cache *cache = pscreen->get_disk_shader_cache(pscreen); - - if (!cache) - return; - - disk_cache_set_callbacks(cache, set, get); -} - -static const __DRI2blobExtension driBlobExtension = { - .base = { __DRI2_BLOB, 1 }, - .set_cache_funcs = set_blob_cache_funcs -}; - -/* - * Backend function init_screen. - */ - -static const __DRIextension *dri_screen_extensions[] = { - &driTexBufferExtension.base, - &dri2FlushExtension.base, - &dri2ImageExtension.base, - &dri2RendererQueryExtension.base, - &dri2GalliumConfigQueryExtension.base, - &dri2ThrottleExtension.base, - &dri2FenceExtension.base, - &dri2BufferDamageExtension.base, - &dri2InteropExtension.base, - &dri2NoErrorExtension.base, - &driBlobExtension.base, - NULL -}; - -static const __DRIextension *dri_robust_screen_extensions[] = { - &driTexBufferExtension.base, - &dri2FlushExtension.base, - &dri2ImageExtension.base, - &dri2RendererQueryExtension.base, - &dri2GalliumConfigQueryExtension.base, - &dri2ThrottleExtension.base, - &dri2FenceExtension.base, - &dri2InteropExtension.base, - &dri2BufferDamageExtension.base, - &dri2Robustness.base, - &dri2NoErrorExtension.base, - &driBlobExtension.base, - NULL -}; - -/** - * This is the driver specific part of the createNewScreen entry point. - * - * Returns the struct gl_config supported by this driver. - */ -static const __DRIconfig ** -dri2_init_screen(__DRIscreen * sPriv) -{ - const __DRIconfig **configs; - struct dri_screen *screen; - struct pipe_screen *pscreen = NULL; - - screen = CALLOC_STRUCT(dri_screen); - if (!screen) - return NULL; - - screen->sPriv = sPriv; - screen->fd = sPriv->fd; - (void) mtx_init(&screen->opencl_func_mutex, mtx_plain); - - sPriv->driverPrivate = (void *)screen; - - if (pipe_loader_drm_probe_fd(&screen->dev, screen->fd)) { - dri_init_options(screen); - - pscreen = pipe_loader_create_screen(screen->dev); - } - - if (!pscreen) - goto release_pipe; - - screen->throttle = pscreen->get_param(pscreen, PIPE_CAP_THROTTLE); - - if (pscreen->resource_create_with_modifiers) - dri2ImageExtension.createImageWithModifiers = - dri2_create_image_with_modifiers; - - if (pscreen->get_param(pscreen, PIPE_CAP_DMABUF)) { - uint64_t cap; - - if (drmGetCap(sPriv->fd, DRM_CAP_PRIME, &cap) == 0 && - (cap & DRM_PRIME_CAP_IMPORT)) { - dri2ImageExtension.createImageFromFds = dri2_from_fds; - dri2ImageExtension.createImageFromDmaBufs = dri2_from_dma_bufs; - dri2ImageExtension.createImageFromDmaBufs2 = dri2_from_dma_bufs2; - dri2ImageExtension.queryDmaBufFormats = dri2_query_dma_buf_formats; - dri2ImageExtension.queryDmaBufModifiers = - dri2_query_dma_buf_modifiers; - dri2ImageExtension.queryDmaBufFormatModifierAttribs = - dri2_query_dma_buf_format_modifier_attribs; - } - } - - if (pscreen->set_damage_region) - dri2BufferDamageExtension.set_damage_region = dri2_set_damage_region; - - if (pscreen->get_param(pscreen, PIPE_CAP_DEVICE_RESET_STATUS_QUERY)) { - sPriv->extensions = dri_robust_screen_extensions; - screen->has_reset_status_query = true; - } - else - sPriv->extensions = dri_screen_extensions; - - configs = dri_init_screen_helper(screen, pscreen); - if (!configs) - goto destroy_screen; - - screen->can_share_buffer = true; - screen->auto_fake_front = dri_with_format(sPriv); - screen->broken_invalidate = !sPriv->dri2.useInvalidate; - screen->lookup_egl_image = dri2_lookup_egl_image; - - return configs; - -destroy_screen: - dri_destroy_screen_helper(screen); - -release_pipe: - if (screen->dev) - pipe_loader_release(&screen->dev, 1); - - FREE(screen); - return NULL; -} - -/** - * This is the driver specific part of the createNewScreen entry point. - * - * Returns the struct gl_config supported by this driver. - */ -static const __DRIconfig ** -dri_kms_init_screen(__DRIscreen * sPriv) -{ -#if defined(GALLIUM_SOFTPIPE) - const __DRIconfig **configs; - struct dri_screen *screen; - struct pipe_screen *pscreen = NULL; - uint64_t cap; - - screen = CALLOC_STRUCT(dri_screen); - if (!screen) - return NULL; - - screen->sPriv = sPriv; - screen->fd = sPriv->fd; - - sPriv->driverPrivate = (void *)screen; - - if (pipe_loader_sw_probe_kms(&screen->dev, screen->fd)) { - dri_init_options(screen); - pscreen = pipe_loader_create_screen(screen->dev); - } - - if (!pscreen) - goto release_pipe; - - if (pscreen->resource_create_with_modifiers) - dri2ImageExtension.createImageWithModifiers = - dri2_create_image_with_modifiers; - - if (drmGetCap(sPriv->fd, DRM_CAP_PRIME, &cap) == 0 && - (cap & DRM_PRIME_CAP_IMPORT)) { - dri2ImageExtension.createImageFromFds = dri2_from_fds; - dri2ImageExtension.createImageFromDmaBufs = dri2_from_dma_bufs; - dri2ImageExtension.createImageFromDmaBufs2 = dri2_from_dma_bufs2; - dri2ImageExtension.queryDmaBufFormats = dri2_query_dma_buf_formats; - dri2ImageExtension.queryDmaBufModifiers = dri2_query_dma_buf_modifiers; - } - - sPriv->extensions = dri_screen_extensions; - - configs = dri_init_screen_helper(screen, pscreen); - if (!configs) - goto destroy_screen; - - screen->can_share_buffer = false; - screen->auto_fake_front = dri_with_format(sPriv); - screen->broken_invalidate = !sPriv->dri2.useInvalidate; - screen->lookup_egl_image = dri2_lookup_egl_image; - - return configs; - -destroy_screen: - dri_destroy_screen_helper(screen); - -release_pipe: - if (screen->dev) - pipe_loader_release(&screen->dev, 1); - - FREE(screen); -#endif // GALLIUM_SOFTPIPE - return NULL; -} - -static boolean -dri2_create_buffer(__DRIscreen * sPriv, - __DRIdrawable * dPriv, - const struct gl_config * visual, boolean isPixmap) -{ - struct dri_drawable *drawable = NULL; - - if (!dri_create_buffer(sPriv, dPriv, visual, isPixmap)) - return FALSE; - - drawable = dPriv->driverPrivate; - - drawable->allocate_textures = dri2_allocate_textures; - drawable->flush_frontbuffer = dri2_flush_frontbuffer; - drawable->update_tex_buffer = dri2_update_tex_buffer; - drawable->flush_swapbuffers = dri2_flush_swapbuffers; - - return TRUE; -} - -/** - * DRI driver virtual function table. - * - * DRI versions differ in their implementation of init_screen and swap_buffers. - */ -const struct __DriverAPIRec galliumdrm_driver_api = { - .InitScreen = dri2_init_screen, - .DestroyScreen = dri_destroy_screen, - .CreateContext = dri_create_context, - .DestroyContext = dri_destroy_context, - .CreateBuffer = dri2_create_buffer, - .DestroyBuffer = dri_destroy_buffer, - .MakeCurrent = dri_make_current, - .UnbindContext = dri_unbind_context, - - .AllocateBuffer = dri2_allocate_buffer, - .ReleaseBuffer = dri2_release_buffer, -}; - -/** - * DRI driver virtual function table. - * - * KMS/DRM version of the DriverAPI above sporting a different InitScreen - * hook. The latter is used to explicitly initialise the kms_swrast driver - * rather than selecting the approapriate driver as suggested by the loader. - */ -const struct __DriverAPIRec dri_kms_driver_api = { - .InitScreen = dri_kms_init_screen, - .DestroyScreen = dri_destroy_screen, - .CreateContext = dri_create_context, - .DestroyContext = dri_destroy_context, - .CreateBuffer = dri2_create_buffer, - .DestroyBuffer = dri_destroy_buffer, - .MakeCurrent = dri_make_current, - .UnbindContext = dri_unbind_context, - - .AllocateBuffer = dri2_allocate_buffer, - .ReleaseBuffer = dri2_release_buffer, -}; - -/* This is the table of extensions that the loader will dlsym() for. */ -const __DRIextension *galliumdrm_driver_extensions[] = { - &driCoreExtension.base, - &driImageDriverExtension.base, - &driDRI2Extension.base, - &gallium_config_options.base, - NULL -}; - -/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/dri_context.c b/src/gallium/state_trackers/dri/dri_context.c deleted file mode 100644 index 082a9ced91d..00000000000 --- a/src/gallium/state_trackers/dri/dri_context.c +++ /dev/null @@ -1,325 +0,0 @@ -/************************************************************************** - * - * Copyright 2009, VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ -/* - * Author: Keith Whitwell - * Author: Jakob Bornecrantz - */ - -#include "utils.h" - -#include "dri_screen.h" -#include "dri_drawable.h" -#include "dri_context.h" -#include "state_tracker/drm_driver.h" - -#include "pipe/p_context.h" -#include "pipe-loader/pipe_loader.h" -#include "state_tracker/st_context.h" - -#include "util/u_memory.h" - -GLboolean -dri_create_context(gl_api api, const struct gl_config * visual, - __DRIcontext * cPriv, - const struct __DriverContextConfig *ctx_config, - unsigned *error, - void *sharedContextPrivate) -{ - __DRIscreen *sPriv = cPriv->driScreenPriv; - struct dri_screen *screen = dri_screen(sPriv); - struct st_api *stapi = screen->st_api; - struct dri_context *ctx = NULL; - struct st_context_iface *st_share = NULL; - struct st_context_attribs attribs; - enum st_context_error ctx_err = 0; - unsigned allowed_flags = __DRI_CTX_FLAG_DEBUG | - __DRI_CTX_FLAG_FORWARD_COMPATIBLE | - __DRI_CTX_FLAG_NO_ERROR; - unsigned allowed_attribs = - __DRIVER_CONTEXT_ATTRIB_PRIORITY | - __DRIVER_CONTEXT_ATTRIB_RELEASE_BEHAVIOR; - const __DRIbackgroundCallableExtension *backgroundCallable = - screen->sPriv->dri2.backgroundCallable; - const struct driOptionCache *optionCache = &screen->dev->option_cache; - - if (screen->has_reset_status_query) { - allowed_flags |= __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS; - allowed_attribs |= __DRIVER_CONTEXT_ATTRIB_RESET_STRATEGY; - } - - if (ctx_config->flags & ~allowed_flags) { - *error = __DRI_CTX_ERROR_UNKNOWN_FLAG; - goto fail; - } - - if (ctx_config->attribute_mask & ~allowed_attribs) { - *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE; - goto fail; - } - - memset(&attribs, 0, sizeof(attribs)); - switch (api) { - case API_OPENGLES: - attribs.profile = ST_PROFILE_OPENGL_ES1; - break; - case API_OPENGLES2: - attribs.profile = ST_PROFILE_OPENGL_ES2; - break; - case API_OPENGL_COMPAT: - case API_OPENGL_CORE: - if (driQueryOptionb(optionCache, "force_compat_profile")) { - attribs.profile = ST_PROFILE_DEFAULT; - } else { - attribs.profile = api == API_OPENGL_COMPAT ? ST_PROFILE_DEFAULT - : ST_PROFILE_OPENGL_CORE; - } - - attribs.major = ctx_config->major_version; - attribs.minor = ctx_config->minor_version; - - if ((ctx_config->flags & __DRI_CTX_FLAG_FORWARD_COMPATIBLE) != 0) - attribs.flags |= ST_CONTEXT_FLAG_FORWARD_COMPATIBLE; - break; - default: - *error = __DRI_CTX_ERROR_BAD_API; - goto fail; - } - - if ((ctx_config->flags & __DRI_CTX_FLAG_DEBUG) != 0) - attribs.flags |= ST_CONTEXT_FLAG_DEBUG; - - if (ctx_config->flags & __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS) - attribs.flags |= ST_CONTEXT_FLAG_ROBUST_ACCESS; - - if (ctx_config->attribute_mask & __DRIVER_CONTEXT_ATTRIB_RESET_STRATEGY) - if (ctx_config->reset_strategy != __DRI_CTX_RESET_NO_NOTIFICATION) - attribs.flags |= ST_CONTEXT_FLAG_RESET_NOTIFICATION_ENABLED; - - if (ctx_config->flags & __DRI_CTX_FLAG_NO_ERROR) - attribs.flags |= ST_CONTEXT_FLAG_NO_ERROR; - - if (ctx_config->attribute_mask & __DRIVER_CONTEXT_ATTRIB_PRIORITY) { - switch (ctx_config->priority) { - case __DRI_CTX_PRIORITY_LOW: - attribs.flags |= ST_CONTEXT_FLAG_LOW_PRIORITY; - break; - case __DRI_CTX_PRIORITY_HIGH: - attribs.flags |= ST_CONTEXT_FLAG_HIGH_PRIORITY; - break; - default: - break; - } - } - - if ((ctx_config->attribute_mask & __DRIVER_CONTEXT_ATTRIB_RELEASE_BEHAVIOR) - && (ctx_config->release_behavior == __DRI_CTX_RELEASE_BEHAVIOR_NONE)) - attribs.flags |= ST_CONTEXT_FLAG_RELEASE_NONE; - - struct dri_context *share_ctx = NULL; - if (sharedContextPrivate) { - share_ctx = (struct dri_context *)sharedContextPrivate; - st_share = share_ctx->st; - } - - ctx = CALLOC_STRUCT(dri_context); - if (ctx == NULL) { - *error = __DRI_CTX_ERROR_NO_MEMORY; - goto fail; - } - - cPriv->driverPrivate = ctx; - ctx->cPriv = cPriv; - ctx->sPriv = sPriv; - - if (driQueryOptionb(&screen->dev->option_cache, "mesa_no_error")) - attribs.flags |= ST_CONTEXT_FLAG_NO_ERROR; - - attribs.options = screen->options; - dri_fill_st_visual(&attribs.visual, screen, visual); - ctx->st = stapi->create_context(stapi, &screen->base, &attribs, &ctx_err, - st_share); - if (ctx->st == NULL) { - switch (ctx_err) { - case ST_CONTEXT_SUCCESS: - *error = __DRI_CTX_ERROR_SUCCESS; - break; - case ST_CONTEXT_ERROR_NO_MEMORY: - *error = __DRI_CTX_ERROR_NO_MEMORY; - break; - case ST_CONTEXT_ERROR_BAD_API: - *error = __DRI_CTX_ERROR_BAD_API; - break; - case ST_CONTEXT_ERROR_BAD_VERSION: - *error = __DRI_CTX_ERROR_BAD_VERSION; - break; - case ST_CONTEXT_ERROR_BAD_FLAG: - *error = __DRI_CTX_ERROR_BAD_FLAG; - break; - case ST_CONTEXT_ERROR_UNKNOWN_ATTRIBUTE: - *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE; - break; - case ST_CONTEXT_ERROR_UNKNOWN_FLAG: - *error = __DRI_CTX_ERROR_UNKNOWN_FLAG; - break; - } - goto fail; - } - ctx->st->st_manager_private = (void *) ctx; - ctx->stapi = stapi; - - if (ctx->st->cso_context) { - ctx->pp = pp_init(ctx->st->pipe, screen->pp_enabled, ctx->st->cso_context); - ctx->hud = hud_create(ctx->st->cso_context, - share_ctx ? share_ctx->hud : NULL); - } - - /* Do this last. */ - if (ctx->st->start_thread && - driQueryOptionb(&screen->dev->option_cache, "mesa_glthread")) { - - if (backgroundCallable && backgroundCallable->base.version >= 2 && - backgroundCallable->isThreadSafe) { - - if (backgroundCallable->isThreadSafe(cPriv->loaderPrivate)) - ctx->st->start_thread(ctx->st); - else - fprintf(stderr, "dri_create_context: glthread isn't thread safe " - "- missing call XInitThreads\n"); - } else { - fprintf(stderr, "dri_create_context: requested glthread but driver " - "is missing backgroundCallable V2 extension\n"); - } - } - - *error = __DRI_CTX_ERROR_SUCCESS; - return GL_TRUE; - - fail: - if (ctx && ctx->st) - ctx->st->destroy(ctx->st); - - free(ctx); - return GL_FALSE; -} - -void -dri_destroy_context(__DRIcontext * cPriv) -{ - struct dri_context *ctx = dri_context(cPriv); - - if (ctx->hud) { - hud_destroy(ctx->hud, ctx->st->cso_context); - } - - if (ctx->pp) - pp_free(ctx->pp); - - /* No particular reason to wait for command completion before - * destroying a context, but we flush the context here - * to avoid having to add code elsewhere to cope with flushing a - * partially destroyed context. - */ - ctx->st->flush(ctx->st, 0, NULL, NULL, NULL); - ctx->st->destroy(ctx->st); - free(ctx); -} - -/* This is called inside MakeCurrent to unbind the context. */ -GLboolean -dri_unbind_context(__DRIcontext * cPriv) -{ - /* dri_util.c ensures cPriv is not null */ - struct dri_screen *screen = dri_screen(cPriv->driScreenPriv); - struct dri_context *ctx = dri_context(cPriv); - struct st_context_iface *st = ctx->st; - struct st_api *stapi = screen->st_api; - - if (--ctx->bind_count == 0) { - if (st == stapi->get_current(stapi)) { - if (st->thread_finish) - st->thread_finish(st); - - /* Record HUD queries for the duration the context was "current". */ - if (ctx->hud) - hud_record_only(ctx->hud, st->pipe); - - stapi->make_current(stapi, NULL, NULL, NULL); - } - } - - return GL_TRUE; -} - -GLboolean -dri_make_current(__DRIcontext * cPriv, - __DRIdrawable * driDrawPriv, - __DRIdrawable * driReadPriv) -{ - /* dri_util.c ensures cPriv is not null */ - struct dri_context *ctx = dri_context(cPriv); - struct dri_drawable *draw = dri_drawable(driDrawPriv); - struct dri_drawable *read = dri_drawable(driReadPriv); - - ++ctx->bind_count; - - if (!draw && !read) - return ctx->stapi->make_current(ctx->stapi, ctx->st, NULL, NULL); - else if (!draw || !read) - return GL_FALSE; - - if (ctx->dPriv != driDrawPriv) { - ctx->dPriv = driDrawPriv; - draw->texture_stamp = driDrawPriv->lastStamp - 1; - } - if (ctx->rPriv != driReadPriv) { - ctx->rPriv = driReadPriv; - read->texture_stamp = driReadPriv->lastStamp - 1; - } - - ctx->stapi->make_current(ctx->stapi, ctx->st, &draw->base, &read->base); - - /* This is ok to call here. If they are already init, it's a no-op. */ - if (ctx->pp && draw->textures[ST_ATTACHMENT_BACK_LEFT]) - pp_init_fbos(ctx->pp, draw->textures[ST_ATTACHMENT_BACK_LEFT]->width0, - draw->textures[ST_ATTACHMENT_BACK_LEFT]->height0); - - return GL_TRUE; -} - -struct dri_context * -dri_get_current(__DRIscreen *sPriv) -{ - struct dri_screen *screen = dri_screen(sPriv); - struct st_api *stapi = screen->st_api; - struct st_context_iface *st; - - st = stapi->get_current(stapi); - - return (struct dri_context *) st ? st->st_manager_private : NULL; -} - -/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/dri_context.h b/src/gallium/state_trackers/dri/dri_context.h deleted file mode 100644 index 96e21e0695c..00000000000 --- a/src/gallium/state_trackers/dri/dri_context.h +++ /dev/null @@ -1,95 +0,0 @@ -/************************************************************************** - * - * Copyright (C) 2009 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ -/* - * Author: Keith Whitwell - * Author: Jakob Bornecrantz - */ - -#ifndef DRI_CONTEXT_H -#define DRI_CONTEXT_H - -#include "dri_util.h" -#include "pipe/p_compiler.h" -#include "hud/hud_context.h" - -struct pipe_context; -struct pipe_fence; -struct st_api; -struct st_context_iface; -struct dri_drawable; - -struct dri_context -{ - /* dri */ - __DRIscreen *sPriv; - __DRIcontext *cPriv; - __DRIdrawable *dPriv; - __DRIdrawable *rPriv; - - unsigned int bind_count; - - /* gallium */ - struct st_api *stapi; - struct st_context_iface *st; - struct pp_queue_t *pp; - struct hud_context *hud; -}; - -static inline struct dri_context * -dri_context(__DRIcontext * driContextPriv) -{ - if (!driContextPriv) - return NULL; - return (struct dri_context *)driContextPriv->driverPrivate; -} - -/*********************************************************************** - * dri_context.c - */ -void dri_destroy_context(__DRIcontext * driContextPriv); - -boolean dri_unbind_context(__DRIcontext * driContextPriv); - -boolean -dri_make_current(__DRIcontext * driContextPriv, - __DRIdrawable * driDrawPriv, - __DRIdrawable * driReadPriv); - -struct dri_context * -dri_get_current(__DRIscreen * driScreenPriv); - -boolean -dri_create_context(gl_api api, - const struct gl_config * visual, - __DRIcontext * driContextPriv, - const struct __DriverContextConfig *ctx_config, - unsigned *error, - void *sharedContextPrivate); - -#endif - -/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/dri_drawable.c b/src/gallium/state_trackers/dri/dri_drawable.c deleted file mode 100644 index 2ee4f185537..00000000000 --- a/src/gallium/state_trackers/dri/dri_drawable.c +++ /dev/null @@ -1,580 +0,0 @@ -/************************************************************************** - * - * Copyright 2009, VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ -/* - * Author: Keith Whitwell - * Author: Jakob Bornecrantz - */ - -#include "dri_screen.h" -#include "dri_context.h" -#include "dri_drawable.h" - -#include "pipe/p_screen.h" -#include "util/format/u_format.h" -#include "util/u_memory.h" -#include "util/u_inlines.h" - -static uint32_t drifb_ID = 0; - -static bool -dri_st_framebuffer_validate(struct st_context_iface *stctx, - struct st_framebuffer_iface *stfbi, - const enum st_attachment_type *statts, - unsigned count, - struct pipe_resource **out) -{ - struct dri_context *ctx = (struct dri_context *)stctx->st_manager_private; - struct dri_drawable *drawable = - (struct dri_drawable *) stfbi->st_manager_private; - struct dri_screen *screen = dri_screen(drawable->sPriv); - unsigned statt_mask, new_mask; - bool new_stamp; - int i; - unsigned int lastStamp; - struct pipe_resource **textures = - drawable->stvis.samples > 1 ? drawable->msaa_textures - : drawable->textures; - - statt_mask = 0x0; - for (i = 0; i < count; i++) - statt_mask |= (1 << statts[i]); - - /* record newly allocated textures */ - new_mask = (statt_mask & ~drawable->texture_mask); - - /* - * dPriv->dri2.stamp is the server stamp. dPriv->lastStamp is the - * client stamp. It has the value of the server stamp when last - * checked. - */ - do { - lastStamp = drawable->dPriv->lastStamp; - new_stamp = (drawable->texture_stamp != lastStamp); - - if (new_stamp || new_mask || screen->broken_invalidate) { - if (new_stamp && drawable->update_drawable_info) - drawable->update_drawable_info(drawable); - - drawable->allocate_textures(ctx, drawable, statts, count); - - /* add existing textures */ - for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { - if (textures[i]) - statt_mask |= (1 << i); - } - - drawable->texture_stamp = lastStamp; - drawable->texture_mask = statt_mask; - } - } while (lastStamp != drawable->dPriv->lastStamp); - - /* Flush the pending set_damage_region request. */ - struct pipe_screen *pscreen = screen->base.screen; - - if (new_mask & (1 << ST_ATTACHMENT_BACK_LEFT) && - pscreen->set_damage_region) { - struct pipe_resource *resource = textures[ST_ATTACHMENT_BACK_LEFT]; - - pscreen->set_damage_region(pscreen, resource, - drawable->num_damage_rects, - drawable->damage_rects); - } - - if (!out) - return true; - - /* Set the window-system buffers for the state tracker. */ - for (i = 0; i < count; i++) - pipe_resource_reference(&out[i], textures[statts[i]]); - - return true; -} - -static bool -dri_st_framebuffer_flush_front(struct st_context_iface *stctx, - struct st_framebuffer_iface *stfbi, - enum st_attachment_type statt) -{ - struct dri_context *ctx = (struct dri_context *)stctx->st_manager_private; - struct dri_drawable *drawable = - (struct dri_drawable *) stfbi->st_manager_private; - - /* XXX remove this and just set the correct one on the framebuffer */ - drawable->flush_frontbuffer(ctx, drawable, statt); - - return true; -} - -/** - * The state tracker framebuffer interface flush_swapbuffers callback - */ -static bool -dri_st_framebuffer_flush_swapbuffers(struct st_context_iface *stctx, - struct st_framebuffer_iface *stfbi) -{ - struct dri_context *ctx = (struct dri_context *)stctx->st_manager_private; - struct dri_drawable *drawable = - (struct dri_drawable *) stfbi->st_manager_private; - - if (drawable->flush_swapbuffers) - drawable->flush_swapbuffers(ctx, drawable); - - return true; -} - -/** - * This is called when we need to set up GL rendering to a new X window. - */ -bool -dri_create_buffer(__DRIscreen * sPriv, - __DRIdrawable * dPriv, - const struct gl_config * visual, bool isPixmap) -{ - struct dri_screen *screen = sPriv->driverPrivate; - struct dri_drawable *drawable = NULL; - - if (isPixmap) - goto fail; /* not implemented */ - - drawable = CALLOC_STRUCT(dri_drawable); - if (drawable == NULL) - goto fail; - - dri_fill_st_visual(&drawable->stvis, screen, visual); - - /* setup the st_framebuffer_iface */ - drawable->base.visual = &drawable->stvis; - drawable->base.flush_front = dri_st_framebuffer_flush_front; - drawable->base.validate = dri_st_framebuffer_validate; - drawable->base.flush_swapbuffers = dri_st_framebuffer_flush_swapbuffers; - drawable->base.st_manager_private = (void *) drawable; - - drawable->screen = screen; - drawable->sPriv = sPriv; - drawable->dPriv = dPriv; - - dPriv->driverPrivate = (void *)drawable; - p_atomic_set(&drawable->base.stamp, 1); - drawable->base.ID = p_atomic_inc_return(&drifb_ID); - drawable->base.state_manager = &screen->base; - - return true; -fail: - FREE(drawable); - return false; -} - -void -dri_destroy_buffer(__DRIdrawable * dPriv) -{ - struct dri_drawable *drawable = dri_drawable(dPriv); - struct dri_screen *screen = drawable->screen; - struct st_api *stapi = screen->st_api; - int i; - - pipe_surface_reference(&drawable->drisw_surface, NULL); - - for (i = 0; i < ST_ATTACHMENT_COUNT; i++) - pipe_resource_reference(&drawable->textures[i], NULL); - for (i = 0; i < ST_ATTACHMENT_COUNT; i++) - pipe_resource_reference(&drawable->msaa_textures[i], NULL); - - screen->base.screen->fence_reference(screen->base.screen, - &drawable->throttle_fence, NULL); - - /* Notify the st manager that this drawable is no longer valid */ - stapi->destroy_drawable(stapi, &drawable->base); - - FREE(drawable->damage_rects); - FREE(drawable); -} - -/** - * Validate the texture at an attachment. Allocate the texture if it does not - * exist. Used by the TFP extension. - */ -static void -dri_drawable_validate_att(struct dri_context *ctx, - struct dri_drawable *drawable, - enum st_attachment_type statt) -{ - enum st_attachment_type statts[ST_ATTACHMENT_COUNT]; - unsigned i, count = 0; - - /* check if buffer already exists */ - if (drawable->texture_mask & (1 << statt)) - return; - - /* make sure DRI2 does not destroy existing buffers */ - for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { - if (drawable->texture_mask & (1 << i)) { - statts[count++] = i; - } - } - statts[count++] = statt; - - drawable->texture_stamp = drawable->dPriv->lastStamp - 1; - - drawable->base.validate(ctx->st, &drawable->base, statts, count, NULL); -} - -/** - * These are used for GLX_EXT_texture_from_pixmap - */ -static void -dri_set_tex_buffer2(__DRIcontext *pDRICtx, GLint target, - GLint format, __DRIdrawable *dPriv) -{ - struct dri_context *ctx = dri_context(pDRICtx); - struct st_context_iface *st = ctx->st; - struct dri_drawable *drawable = dri_drawable(dPriv); - struct pipe_resource *pt; - - if (st->thread_finish) - st->thread_finish(st); - - dri_drawable_validate_att(ctx, drawable, ST_ATTACHMENT_FRONT_LEFT); - - /* Use the pipe resource associated with the X drawable */ - pt = drawable->textures[ST_ATTACHMENT_FRONT_LEFT]; - - if (pt) { - enum pipe_format internal_format = pt->format; - - if (format == __DRI_TEXTURE_FORMAT_RGB) { - /* only need to cover the formats recognized by dri_fill_st_visual */ - switch (internal_format) { - case PIPE_FORMAT_R16G16B16A16_FLOAT: - internal_format = PIPE_FORMAT_R16G16B16X16_FLOAT; - break; - case PIPE_FORMAT_B10G10R10A2_UNORM: - internal_format = PIPE_FORMAT_B10G10R10X2_UNORM; - break; - case PIPE_FORMAT_R10G10B10A2_UNORM: - internal_format = PIPE_FORMAT_R10G10B10X2_UNORM; - break; - case PIPE_FORMAT_BGRA8888_UNORM: - internal_format = PIPE_FORMAT_BGRX8888_UNORM; - break; - case PIPE_FORMAT_ARGB8888_UNORM: - internal_format = PIPE_FORMAT_XRGB8888_UNORM; - break; - default: - break; - } - } - - drawable->update_tex_buffer(drawable, ctx, pt); - - ctx->st->teximage(ctx->st, - (target == GL_TEXTURE_2D) ? ST_TEXTURE_2D : ST_TEXTURE_RECT, - 0, internal_format, pt, false); - } -} - -static void -dri_set_tex_buffer(__DRIcontext *pDRICtx, GLint target, - __DRIdrawable *dPriv) -{ - dri_set_tex_buffer2(pDRICtx, target, __DRI_TEXTURE_FORMAT_RGBA, dPriv); -} - -const __DRItexBufferExtension driTexBufferExtension = { - .base = { __DRI_TEX_BUFFER, 2 }, - - .setTexBuffer = dri_set_tex_buffer, - .setTexBuffer2 = dri_set_tex_buffer2, - .releaseTexBuffer = NULL, -}; - -/** - * Get the format and binding of an attachment. - */ -void -dri_drawable_get_format(struct dri_drawable *drawable, - enum st_attachment_type statt, - enum pipe_format *format, - unsigned *bind) -{ - switch (statt) { - case ST_ATTACHMENT_FRONT_LEFT: - case ST_ATTACHMENT_BACK_LEFT: - case ST_ATTACHMENT_FRONT_RIGHT: - case ST_ATTACHMENT_BACK_RIGHT: - /* Other pieces of the driver stack get confused and behave incorrectly - * when they get an sRGB drawable. st/mesa receives "drawable->stvis" - * though other means and handles it correctly, so we don't really need - * to use an sRGB format here. - */ - *format = util_format_linear(drawable->stvis.color_format); - *bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; - break; - case ST_ATTACHMENT_DEPTH_STENCIL: - *format = drawable->stvis.depth_stencil_format; - *bind = PIPE_BIND_DEPTH_STENCIL; /* XXX sampler? */ - break; - default: - *format = PIPE_FORMAT_NONE; - *bind = 0; - break; - } -} - -void -dri_pipe_blit(struct pipe_context *pipe, - struct pipe_resource *dst, - struct pipe_resource *src) -{ - struct pipe_blit_info blit; - - if (!dst || !src) - return; - - /* From the GL spec, version 4.2, section 4.1.11 (Additional Multisample - * Fragment Operations): - * - * If a framebuffer object is not bound, after all operations have - * been completed on the multisample buffer, the sample values for - * each color in the multisample buffer are combined to produce a - * single color value, and that value is written into the - * corresponding color buffers selected by DrawBuffer or - * DrawBuffers. An implementation may defer the writing of the color - * buffers until a later time, but the state of the framebuffer must - * behave as if the color buffers were updated as each fragment was - * processed. The method of combination is not specified. If the - * framebuffer contains sRGB values, then it is recommended that the - * an average of sample values is computed in a linearized space, as - * for blending (see section 4.1.7). - * - * In other words, to do a resolve operation in a linear space, we have - * to set sRGB formats if the original resources were sRGB, so don't use - * util_format_linear. - */ - - memset(&blit, 0, sizeof(blit)); - blit.dst.resource = dst; - blit.dst.box.width = dst->width0; - blit.dst.box.height = dst->height0; - blit.dst.box.depth = 1; - blit.dst.format = dst->format; - blit.src.resource = src; - blit.src.box.width = src->width0; - blit.src.box.height = src->height0; - blit.src.box.depth = 1; - blit.src.format = src->format; - blit.mask = PIPE_MASK_RGBA; - blit.filter = PIPE_TEX_FILTER_NEAREST; - - pipe->blit(pipe, &blit); -} - -static void -dri_postprocessing(struct dri_context *ctx, - struct dri_drawable *drawable, - enum st_attachment_type att) -{ - struct pipe_resource *src = drawable->textures[att]; - struct pipe_resource *zsbuf = drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]; - - if (ctx->pp && src) - pp_run(ctx->pp, src, src, zsbuf); -} - -struct notify_before_flush_cb_args { - struct dri_context *ctx; - struct dri_drawable *drawable; - unsigned flags; - enum __DRI2throttleReason reason; - bool swap_msaa_buffers; -}; - -static void -notify_before_flush_cb(void* _args) -{ - struct notify_before_flush_cb_args *args = (struct notify_before_flush_cb_args *) _args; - struct st_context_iface *st = args->ctx->st; - struct pipe_context *pipe = st->pipe; - - if (args->drawable->stvis.samples > 1 && - (args->reason == __DRI2_THROTTLE_SWAPBUFFER || - args->reason == __DRI2_THROTTLE_COPYSUBBUFFER)) { - /* Resolve the MSAA back buffer. */ - dri_pipe_blit(st->pipe, - args->drawable->textures[ST_ATTACHMENT_BACK_LEFT], - args->drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT]); - - if (args->reason == __DRI2_THROTTLE_SWAPBUFFER && - args->drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT] && - args->drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT]) { - args->swap_msaa_buffers = true; - } - - /* FRONT_LEFT is resolved in drawable->flush_frontbuffer. */ - } - - dri_postprocessing(args->ctx, args->drawable, ST_ATTACHMENT_BACK_LEFT); - - if (pipe->invalidate_resource && - (args->flags & __DRI2_FLUSH_INVALIDATE_ANCILLARY)) { - if (args->drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]) - pipe->invalidate_resource(pipe, args->drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]); - if (args->drawable->msaa_textures[ST_ATTACHMENT_DEPTH_STENCIL]) - pipe->invalidate_resource(pipe, args->drawable->msaa_textures[ST_ATTACHMENT_DEPTH_STENCIL]); - } - - if (args->ctx->hud) { - hud_run(args->ctx->hud, args->ctx->st->cso_context, - args->drawable->textures[ST_ATTACHMENT_BACK_LEFT]); - } - - pipe->flush_resource(pipe, args->drawable->textures[ST_ATTACHMENT_BACK_LEFT]); -} - -/** - * DRI2 flush extension, the flush_with_flags function. - * - * \param context the context - * \param drawable the drawable to flush - * \param flags a combination of _DRI2_FLUSH_xxx flags - * \param throttle_reason the reason for throttling, 0 = no throttling - */ -void -dri_flush(__DRIcontext *cPriv, - __DRIdrawable *dPriv, - unsigned flags, - enum __DRI2throttleReason reason) -{ - struct dri_context *ctx = dri_context(cPriv); - struct dri_drawable *drawable = dri_drawable(dPriv); - struct st_context_iface *st; - unsigned flush_flags; - struct notify_before_flush_cb_args args = { 0 }; - - if (!ctx) { - assert(0); - return; - } - - st = ctx->st; - if (st->thread_finish) - st->thread_finish(st); - - if (drawable) { - /* prevent recursion */ - if (drawable->flushing) - return; - - drawable->flushing = true; - } - else { - flags &= ~__DRI2_FLUSH_DRAWABLE; - } - - if ((flags & __DRI2_FLUSH_DRAWABLE) && - drawable->textures[ST_ATTACHMENT_BACK_LEFT]) { - /* We can't do operations on the back buffer here, because there - * may be some pending operations that will get flushed by the - * call to st->flush (eg: FLUSH_VERTICES). - * Instead we register a callback to be notified when all operations - * have been submitted but before the call to st_flush. - */ - args.ctx = ctx; - args.drawable = drawable; - args.flags = flags; - args.reason = reason; - } - - flush_flags = 0; - if (flags & __DRI2_FLUSH_CONTEXT) - flush_flags |= ST_FLUSH_FRONT; - if (reason == __DRI2_THROTTLE_SWAPBUFFER) - flush_flags |= ST_FLUSH_END_OF_FRAME; - - /* Flush the context and throttle if needed. */ - if (dri_screen(ctx->sPriv)->throttle && - drawable && - (reason == __DRI2_THROTTLE_SWAPBUFFER || - reason == __DRI2_THROTTLE_FLUSHFRONT)) { - - struct pipe_screen *screen = drawable->screen->base.screen; - struct pipe_fence_handle *new_fence = NULL; - - st->flush(st, flush_flags, &new_fence, args.ctx ? notify_before_flush_cb : NULL, &args); - - /* throttle on the previous fence */ - if (drawable->throttle_fence) { - screen->fence_finish(screen, NULL, drawable->throttle_fence, PIPE_TIMEOUT_INFINITE); - screen->fence_reference(screen, &drawable->throttle_fence, NULL); - } - drawable->throttle_fence = new_fence; - } - else if (flags & (__DRI2_FLUSH_DRAWABLE | __DRI2_FLUSH_CONTEXT)) { - st->flush(st, flush_flags, NULL, args.ctx ? notify_before_flush_cb : NULL, &args); - } - - if (drawable) { - drawable->flushing = false; - } - - /* Swap the MSAA front and back buffers, so that reading - * from the front buffer after SwapBuffers returns what was - * in the back buffer. - */ - if (args.swap_msaa_buffers) { - struct pipe_resource *tmp = - drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT]; - - drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT] = - drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT]; - drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT] = tmp; - - /* Now that we have swapped the buffers, this tells the state - * tracker to revalidate the framebuffer. - */ - p_atomic_inc(&drawable->base.stamp); - } -} - -/** - * dri_throttle - A DRI2ThrottleExtension throttling function. - */ -static void -dri_throttle(__DRIcontext *cPriv, __DRIdrawable *dPriv, - enum __DRI2throttleReason reason) -{ - dri_flush(cPriv, dPriv, 0, reason); -} - - -const __DRI2throttleExtension dri2ThrottleExtension = { - .base = { __DRI2_THROTTLE, 1 }, - - .throttle = dri_throttle, -}; - - -/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/dri_drawable.h b/src/gallium/state_trackers/dri/dri_drawable.h deleted file mode 100644 index d57ff1d84e0..00000000000 --- a/src/gallium/state_trackers/dri/dri_drawable.h +++ /dev/null @@ -1,125 +0,0 @@ -/************************************************************************** - * - * Copyright 2009, VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#ifndef DRI_DRAWABLE_H -#define DRI_DRAWABLE_H - -#include "pipe/p_compiler.h" -#include "pipe/p_format.h" -#include "state_tracker/st_api.h" - -struct pipe_surface; -struct st_framebuffer; -struct dri_context; - -struct dri_drawable -{ - struct st_framebuffer_iface base; - struct st_visual stvis; - - struct dri_screen *screen; - - /* dri */ - __DRIdrawable *dPriv; - __DRIscreen *sPriv; - - __DRIbuffer old[8]; - unsigned old_num; - unsigned old_w; - unsigned old_h; - - struct pipe_box *damage_rects; - unsigned int num_damage_rects; - - struct pipe_resource *textures[ST_ATTACHMENT_COUNT]; - struct pipe_resource *msaa_textures[ST_ATTACHMENT_COUNT]; - unsigned int texture_mask, texture_stamp; - - struct pipe_fence_handle *throttle_fence; - bool flushing; /* prevents recursion in dri_flush */ - - /* used only by DRISW */ - struct pipe_surface *drisw_surface; - - /* hooks filled in by dri2 & drisw */ - void (*allocate_textures)(struct dri_context *ctx, - struct dri_drawable *drawable, - const enum st_attachment_type *statts, - unsigned count); - - void (*update_drawable_info)(struct dri_drawable *drawable); - - void (*flush_frontbuffer)(struct dri_context *ctx, - struct dri_drawable *drawable, - enum st_attachment_type statt); - - void (*update_tex_buffer)(struct dri_drawable *drawable, - struct dri_context *ctx, - struct pipe_resource *res); - void (*flush_swapbuffers)(struct dri_context *ctx, - struct dri_drawable *drawable); -}; - -static inline struct dri_drawable * -dri_drawable(__DRIdrawable * driDrawPriv) -{ - return (struct dri_drawable *) (driDrawPriv) - ? driDrawPriv->driverPrivate : NULL; -} - -/*********************************************************************** - * dri_drawable.c - */ -bool -dri_create_buffer(__DRIscreen * sPriv, - __DRIdrawable * dPriv, - const struct gl_config * visual, bool isPixmap); - -void dri_destroy_buffer(__DRIdrawable * dPriv); - -void -dri_drawable_get_format(struct dri_drawable *drawable, - enum st_attachment_type statt, - enum pipe_format *format, - unsigned *bind); - -void -dri_pipe_blit(struct pipe_context *pipe, - struct pipe_resource *dst, - struct pipe_resource *src); - -void -dri_flush(__DRIcontext *cPriv, - __DRIdrawable *dPriv, - unsigned flags, - enum __DRI2throttleReason reason); - -extern const __DRItexBufferExtension driTexBufferExtension; -extern const __DRI2throttleExtension dri2ThrottleExtension; -#endif - -/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/dri_helpers.c b/src/gallium/state_trackers/dri/dri_helpers.c deleted file mode 100644 index 90a8a392fad..00000000000 --- a/src/gallium/state_trackers/dri/dri_helpers.c +++ /dev/null @@ -1,618 +0,0 @@ -/* - * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#include -#include "drm-uapi/drm_fourcc.h" -#include "util/u_memory.h" -#include "pipe/p_screen.h" -#include "state_tracker/st_texture.h" -#include "state_tracker/st_context.h" -#include "state_tracker/st_cb_fbo.h" -#include "main/texobj.h" - -#include "dri_helpers.h" - -static bool -dri2_is_opencl_interop_loaded_locked(struct dri_screen *screen) -{ - return screen->opencl_dri_event_add_ref && - screen->opencl_dri_event_release && - screen->opencl_dri_event_wait && - screen->opencl_dri_event_get_fence; -} - -static bool -dri2_load_opencl_interop(struct dri_screen *screen) -{ -#if defined(RTLD_DEFAULT) - bool success; - - mtx_lock(&screen->opencl_func_mutex); - - if (dri2_is_opencl_interop_loaded_locked(screen)) { - mtx_unlock(&screen->opencl_func_mutex); - return true; - } - - screen->opencl_dri_event_add_ref = - dlsym(RTLD_DEFAULT, "opencl_dri_event_add_ref"); - screen->opencl_dri_event_release = - dlsym(RTLD_DEFAULT, "opencl_dri_event_release"); - screen->opencl_dri_event_wait = - dlsym(RTLD_DEFAULT, "opencl_dri_event_wait"); - screen->opencl_dri_event_get_fence = - dlsym(RTLD_DEFAULT, "opencl_dri_event_get_fence"); - - success = dri2_is_opencl_interop_loaded_locked(screen); - mtx_unlock(&screen->opencl_func_mutex); - return success; -#else - return false; -#endif -} - -struct dri2_fence { - struct dri_screen *driscreen; - struct pipe_fence_handle *pipe_fence; - void *cl_event; -}; - -static unsigned dri2_fence_get_caps(__DRIscreen *_screen) -{ - struct dri_screen *driscreen = dri_screen(_screen); - struct pipe_screen *screen = driscreen->base.screen; - unsigned caps = 0; - - if (screen->get_param(screen, PIPE_CAP_NATIVE_FENCE_FD)) - caps |= __DRI_FENCE_CAP_NATIVE_FD; - - return caps; -} - -static void * -dri2_create_fence(__DRIcontext *_ctx) -{ - struct st_context_iface *stapi = dri_context(_ctx)->st; - struct dri2_fence *fence = CALLOC_STRUCT(dri2_fence); - - if (!fence) - return NULL; - - stapi->flush(stapi, 0, &fence->pipe_fence, NULL, NULL); - - if (!fence->pipe_fence) { - FREE(fence); - return NULL; - } - - fence->driscreen = dri_screen(_ctx->driScreenPriv); - return fence; -} - -static void * -dri2_create_fence_fd(__DRIcontext *_ctx, int fd) -{ - struct st_context_iface *stapi = dri_context(_ctx)->st; - struct pipe_context *ctx = stapi->pipe; - struct dri2_fence *fence = CALLOC_STRUCT(dri2_fence); - - if (fd == -1) { - /* exporting driver created fence, flush: */ - stapi->flush(stapi, ST_FLUSH_FENCE_FD, &fence->pipe_fence, NULL, NULL); - } else { - /* importing a foreign fence fd: */ - ctx->create_fence_fd(ctx, &fence->pipe_fence, fd, PIPE_FD_TYPE_NATIVE_SYNC); - } - if (!fence->pipe_fence) { - FREE(fence); - return NULL; - } - - fence->driscreen = dri_screen(_ctx->driScreenPriv); - return fence; -} - -static int -dri2_get_fence_fd(__DRIscreen *_screen, void *_fence) -{ - struct dri_screen *driscreen = dri_screen(_screen); - struct pipe_screen *screen = driscreen->base.screen; - struct dri2_fence *fence = (struct dri2_fence*)_fence; - - return screen->fence_get_fd(screen, fence->pipe_fence); -} - -static void * -dri2_get_fence_from_cl_event(__DRIscreen *_screen, intptr_t cl_event) -{ - struct dri_screen *driscreen = dri_screen(_screen); - struct dri2_fence *fence; - - if (!dri2_load_opencl_interop(driscreen)) - return NULL; - - fence = CALLOC_STRUCT(dri2_fence); - if (!fence) - return NULL; - - fence->cl_event = (void*)cl_event; - - if (!driscreen->opencl_dri_event_add_ref(fence->cl_event)) { - free(fence); - return NULL; - } - - fence->driscreen = driscreen; - return fence; -} - -static void -dri2_destroy_fence(__DRIscreen *_screen, void *_fence) -{ - struct dri_screen *driscreen = dri_screen(_screen); - struct pipe_screen *screen = driscreen->base.screen; - struct dri2_fence *fence = (struct dri2_fence*)_fence; - - if (fence->pipe_fence) - screen->fence_reference(screen, &fence->pipe_fence, NULL); - else if (fence->cl_event) - driscreen->opencl_dri_event_release(fence->cl_event); - else - assert(0); - - FREE(fence); -} - -static GLboolean -dri2_client_wait_sync(__DRIcontext *_ctx, void *_fence, unsigned flags, - uint64_t timeout) -{ - struct dri2_fence *fence = (struct dri2_fence*)_fence; - struct dri_screen *driscreen = fence->driscreen; - struct pipe_screen *screen = driscreen->base.screen; - - /* No need to flush. The context was flushed when the fence was created. */ - - if (fence->pipe_fence) - return screen->fence_finish(screen, NULL, fence->pipe_fence, timeout); - else if (fence->cl_event) { - struct pipe_fence_handle *pipe_fence = - driscreen->opencl_dri_event_get_fence(fence->cl_event); - - if (pipe_fence) - return screen->fence_finish(screen, NULL, pipe_fence, timeout); - else - return driscreen->opencl_dri_event_wait(fence->cl_event, timeout); - } - else { - assert(0); - return false; - } -} - -static void -dri2_server_wait_sync(__DRIcontext *_ctx, void *_fence, unsigned flags) -{ - struct pipe_context *ctx = dri_context(_ctx)->st->pipe; - struct dri2_fence *fence = (struct dri2_fence*)_fence; - - /* We might be called here with a NULL fence as a result of WaitSyncKHR - * on a EGL_KHR_reusable_sync fence. Nothing to do here in such case. - */ - if (!fence) - return; - - if (ctx->fence_server_sync) - ctx->fence_server_sync(ctx, fence->pipe_fence); -} - -const __DRI2fenceExtension dri2FenceExtension = { - .base = { __DRI2_FENCE, 2 }, - - .create_fence = dri2_create_fence, - .get_fence_from_cl_event = dri2_get_fence_from_cl_event, - .destroy_fence = dri2_destroy_fence, - .client_wait_sync = dri2_client_wait_sync, - .server_wait_sync = dri2_server_wait_sync, - .get_capabilities = dri2_fence_get_caps, - .create_fence_fd = dri2_create_fence_fd, - .get_fence_fd = dri2_get_fence_fd, -}; - -__DRIimage * -dri2_lookup_egl_image(struct dri_screen *screen, void *handle) -{ - const __DRIimageLookupExtension *loader = screen->sPriv->dri2.image; - __DRIimage *img; - - if (!loader->lookupEGLImage) - return NULL; - - img = loader->lookupEGLImage(screen->sPriv, - handle, screen->sPriv->loaderPrivate); - - return img; -} - -__DRIimage * -dri2_create_image_from_renderbuffer2(__DRIcontext *context, - int renderbuffer, void *loaderPrivate, - unsigned *error) -{ - struct gl_context *ctx = ((struct st_context *)dri_context(context)->st)->ctx; - struct gl_renderbuffer *rb; - struct pipe_resource *tex; - __DRIimage *img; - - /* Section 3.9 (EGLImage Specification and Management) of the EGL 1.5 - * specification says: - * - * "If target is EGL_GL_RENDERBUFFER and buffer is not the name of a - * renderbuffer object, or if buffer is the name of a multisampled - * renderbuffer object, the error EGL_BAD_PARAMETER is generated." - * - * "If target is EGL_GL_TEXTURE_2D , EGL_GL_TEXTURE_CUBE_MAP_*, - * EGL_GL_RENDERBUFFER or EGL_GL_TEXTURE_3D and buffer refers to the - * default GL texture object (0) for the corresponding GL target, the - * error EGL_BAD_PARAMETER is generated." - * (rely on _mesa_lookup_renderbuffer returning NULL in this case) - */ - rb = _mesa_lookup_renderbuffer(ctx, renderbuffer); - if (!rb || rb->NumSamples > 0) { - *error = __DRI_IMAGE_ERROR_BAD_PARAMETER; - return NULL; - } - - tex = st_get_renderbuffer_resource(rb); - if (!tex) { - *error = __DRI_IMAGE_ERROR_BAD_PARAMETER; - return NULL; - } - - img = CALLOC_STRUCT(__DRIimageRec); - if (!img) { - *error = __DRI_IMAGE_ERROR_BAD_ALLOC; - return NULL; - } - - img->dri_format = driGLFormatToImageFormat(rb->Format); - img->loader_private = loaderPrivate; - - pipe_resource_reference(&img->texture, tex); - - *error = __DRI_IMAGE_ERROR_SUCCESS; - return img; -} - -__DRIimage * -dri2_create_image_from_renderbuffer(__DRIcontext *context, - int renderbuffer, void *loaderPrivate) -{ - unsigned error; - return dri2_create_image_from_renderbuffer2(context, renderbuffer, - loaderPrivate, &error); -} - -void -dri2_destroy_image(__DRIimage *img) -{ - pipe_resource_reference(&img->texture, NULL); - FREE(img); -} - - -__DRIimage * -dri2_create_from_texture(__DRIcontext *context, int target, unsigned texture, - int depth, int level, unsigned *error, - void *loaderPrivate) -{ - __DRIimage *img; - struct gl_context *ctx = ((struct st_context *)dri_context(context)->st)->ctx; - struct gl_texture_object *obj; - struct pipe_resource *tex; - GLuint face = 0; - - obj = _mesa_lookup_texture(ctx, texture); - if (!obj || obj->Target != target) { - *error = __DRI_IMAGE_ERROR_BAD_PARAMETER; - return NULL; - } - - tex = st_get_texobj_resource(obj); - if (!tex) { - *error = __DRI_IMAGE_ERROR_BAD_PARAMETER; - return NULL; - } - - if (target == GL_TEXTURE_CUBE_MAP) - face = depth; - - _mesa_test_texobj_completeness(ctx, obj); - if (!obj->_BaseComplete || (level > 0 && !obj->_MipmapComplete)) { - *error = __DRI_IMAGE_ERROR_BAD_PARAMETER; - return NULL; - } - - if (level < obj->BaseLevel || level > obj->_MaxLevel) { - *error = __DRI_IMAGE_ERROR_BAD_MATCH; - return NULL; - } - - if (target == GL_TEXTURE_3D && obj->Image[face][level]->Depth < depth) { - *error = __DRI_IMAGE_ERROR_BAD_MATCH; - return NULL; - } - - img = CALLOC_STRUCT(__DRIimageRec); - if (!img) { - *error = __DRI_IMAGE_ERROR_BAD_ALLOC; - return NULL; - } - - img->level = level; - img->layer = depth; - img->dri_format = driGLFormatToImageFormat(obj->Image[face][level]->TexFormat); - - img->loader_private = loaderPrivate; - - pipe_resource_reference(&img->texture, tex); - - *error = __DRI_IMAGE_ERROR_SUCCESS; - return img; -} - -static const struct dri2_format_mapping dri2_format_table[] = { - { DRM_FORMAT_ABGR16161616F, __DRI_IMAGE_FORMAT_ABGR16161616F, - __DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_R16G16B16A16_FLOAT, 1, - { { 0, 0, 0, __DRI_IMAGE_FORMAT_ABGR16161616F, 4 } } }, - { DRM_FORMAT_XBGR16161616F, __DRI_IMAGE_FORMAT_XBGR16161616F, - __DRI_IMAGE_COMPONENTS_RGB, PIPE_FORMAT_R16G16B16X16_FLOAT, 1, - { { 0, 0, 0, __DRI_IMAGE_FORMAT_XBGR16161616F, 4 } } }, - { DRM_FORMAT_ARGB2101010, __DRI_IMAGE_FORMAT_ARGB2101010, - __DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_B10G10R10A2_UNORM, 1, - { { 0, 0, 0, __DRI_IMAGE_FORMAT_ARGB2101010, 4 } } }, - { DRM_FORMAT_XRGB2101010, __DRI_IMAGE_FORMAT_XRGB2101010, - __DRI_IMAGE_COMPONENTS_RGB, PIPE_FORMAT_B10G10R10X2_UNORM, 1, - { { 0, 0, 0, __DRI_IMAGE_FORMAT_XRGB2101010, 4 } } }, - { DRM_FORMAT_ABGR2101010, __DRI_IMAGE_FORMAT_ABGR2101010, - __DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_R10G10B10A2_UNORM, 1, - { { 0, 0, 0, __DRI_IMAGE_FORMAT_ABGR2101010, 4 } } }, - { DRM_FORMAT_XBGR2101010, __DRI_IMAGE_FORMAT_XBGR2101010, - __DRI_IMAGE_COMPONENTS_RGB, PIPE_FORMAT_R10G10B10X2_UNORM, 1, - { { 0, 0, 0, __DRI_IMAGE_FORMAT_XBGR2101010, 4 } } }, - { DRM_FORMAT_ARGB8888, __DRI_IMAGE_FORMAT_ARGB8888, - __DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_BGRA8888_UNORM, 1, - { { 0, 0, 0, __DRI_IMAGE_FORMAT_ARGB8888, 4 } } }, - { DRM_FORMAT_ABGR8888, __DRI_IMAGE_FORMAT_ABGR8888, - __DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_RGBA8888_UNORM, 1, - { { 0, 0, 0, __DRI_IMAGE_FORMAT_ABGR8888, 4 } } }, - { __DRI_IMAGE_FOURCC_SARGB8888, __DRI_IMAGE_FORMAT_SARGB8, - __DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_BGRA8888_SRGB, 1, - { { 0, 0, 0, __DRI_IMAGE_FORMAT_SARGB8, 4 } } }, - { DRM_FORMAT_XRGB8888, __DRI_IMAGE_FORMAT_XRGB8888, - __DRI_IMAGE_COMPONENTS_RGB, PIPE_FORMAT_BGRX8888_UNORM, 1, - { { 0, 0, 0, __DRI_IMAGE_FORMAT_XRGB8888, 4 }, } }, - { DRM_FORMAT_XBGR8888, __DRI_IMAGE_FORMAT_XBGR8888, - __DRI_IMAGE_COMPONENTS_RGB, PIPE_FORMAT_RGBX8888_UNORM, 1, - { { 0, 0, 0, __DRI_IMAGE_FORMAT_XBGR8888, 4 }, } }, - { DRM_FORMAT_ARGB1555, __DRI_IMAGE_FORMAT_ARGB1555, - __DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_B5G5R5A1_UNORM, 1, - { { 0, 0, 0, __DRI_IMAGE_FORMAT_ARGB1555, 2 } } }, - { DRM_FORMAT_RGB565, __DRI_IMAGE_FORMAT_RGB565, - __DRI_IMAGE_COMPONENTS_RGB, PIPE_FORMAT_B5G6R5_UNORM, 1, - { { 0, 0, 0, __DRI_IMAGE_FORMAT_RGB565, 2 } } }, - { DRM_FORMAT_R8, __DRI_IMAGE_FORMAT_R8, - __DRI_IMAGE_COMPONENTS_R, PIPE_FORMAT_R8_UNORM, 1, - { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, } }, - { DRM_FORMAT_R16, __DRI_IMAGE_FORMAT_R16, - __DRI_IMAGE_COMPONENTS_R, PIPE_FORMAT_R16_UNORM, 1, - { { 0, 0, 0, __DRI_IMAGE_FORMAT_R16, 1 }, } }, - { DRM_FORMAT_GR88, __DRI_IMAGE_FORMAT_GR88, - __DRI_IMAGE_COMPONENTS_RG, PIPE_FORMAT_RG88_UNORM, 1, - { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88, 2 }, } }, - { DRM_FORMAT_GR1616, __DRI_IMAGE_FORMAT_GR1616, - __DRI_IMAGE_COMPONENTS_RG, PIPE_FORMAT_RG1616_UNORM, 1, - { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR1616, 2 }, } }, - - { DRM_FORMAT_YUV410, __DRI_IMAGE_FORMAT_NONE, - __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3, - { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, - { 1, 2, 2, __DRI_IMAGE_FORMAT_R8, 1 }, - { 2, 2, 2, __DRI_IMAGE_FORMAT_R8, 1 } } }, - { DRM_FORMAT_YUV411, __DRI_IMAGE_FORMAT_NONE, - __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3, - { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, - { 1, 2, 0, __DRI_IMAGE_FORMAT_R8, 1 }, - { 2, 2, 0, __DRI_IMAGE_FORMAT_R8, 1 } } }, - { DRM_FORMAT_YUV420, __DRI_IMAGE_FORMAT_NONE, - __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3, - { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, - { 1, 1, 1, __DRI_IMAGE_FORMAT_R8, 1 }, - { 2, 1, 1, __DRI_IMAGE_FORMAT_R8, 1 } } }, - { DRM_FORMAT_YUV422, __DRI_IMAGE_FORMAT_NONE, - __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3, - { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, - { 1, 1, 0, __DRI_IMAGE_FORMAT_R8, 1 }, - { 2, 1, 0, __DRI_IMAGE_FORMAT_R8, 1 } } }, - { DRM_FORMAT_YUV444, __DRI_IMAGE_FORMAT_NONE, - __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3, - { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, - { 1, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, - { 2, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 } } }, - - { DRM_FORMAT_YVU410, __DRI_IMAGE_FORMAT_NONE, - __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3, - { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, - { 2, 2, 2, __DRI_IMAGE_FORMAT_R8, 1 }, - { 1, 2, 2, __DRI_IMAGE_FORMAT_R8, 1 } } }, - { DRM_FORMAT_YVU411, __DRI_IMAGE_FORMAT_NONE, - __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3, - { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, - { 2, 2, 0, __DRI_IMAGE_FORMAT_R8, 1 }, - { 1, 2, 0, __DRI_IMAGE_FORMAT_R8, 1 } } }, - { DRM_FORMAT_YVU420, __DRI_IMAGE_FORMAT_NONE, - __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3, - { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, - { 2, 1, 1, __DRI_IMAGE_FORMAT_R8, 1 }, - { 1, 1, 1, __DRI_IMAGE_FORMAT_R8, 1 } } }, - { DRM_FORMAT_YVU422, __DRI_IMAGE_FORMAT_NONE, - __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3, - { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, - { 2, 1, 0, __DRI_IMAGE_FORMAT_R8, 1 }, - { 1, 1, 0, __DRI_IMAGE_FORMAT_R8, 1 } } }, - { DRM_FORMAT_YVU444, __DRI_IMAGE_FORMAT_NONE, - __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3, - { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, - { 2, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, - { 1, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 } } }, - - { DRM_FORMAT_NV12, __DRI_IMAGE_FORMAT_NONE, - __DRI_IMAGE_COMPONENTS_Y_UV, PIPE_FORMAT_NV12, 2, - { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, - { 1, 1, 1, __DRI_IMAGE_FORMAT_GR88, 2 } } }, - - { DRM_FORMAT_P010, __DRI_IMAGE_FORMAT_NONE, - __DRI_IMAGE_COMPONENTS_Y_UV, PIPE_FORMAT_P016, 2, - { { 0, 0, 0, __DRI_IMAGE_FORMAT_R16, 2 }, - { 1, 1, 1, __DRI_IMAGE_FORMAT_GR1616, 4 } } }, - { DRM_FORMAT_P012, __DRI_IMAGE_FORMAT_NONE, - __DRI_IMAGE_COMPONENTS_Y_UV, PIPE_FORMAT_P016, 2, - { { 0, 0, 0, __DRI_IMAGE_FORMAT_R16, 2 }, - { 1, 1, 1, __DRI_IMAGE_FORMAT_GR1616, 4 } } }, - { DRM_FORMAT_P016, __DRI_IMAGE_FORMAT_NONE, - __DRI_IMAGE_COMPONENTS_Y_UV, PIPE_FORMAT_P016, 2, - { { 0, 0, 0, __DRI_IMAGE_FORMAT_R16, 2 }, - { 1, 1, 1, __DRI_IMAGE_FORMAT_GR1616, 4 } } }, - - { DRM_FORMAT_NV16, __DRI_IMAGE_FORMAT_NONE, - __DRI_IMAGE_COMPONENTS_Y_UV, PIPE_FORMAT_NV12, 2, - { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, - { 1, 1, 0, __DRI_IMAGE_FORMAT_GR88, 2 } } }, - - { DRM_FORMAT_AYUV, __DRI_IMAGE_FORMAT_ABGR8888, - __DRI_IMAGE_COMPONENTS_AYUV, PIPE_FORMAT_AYUV, 1, - { { 0, 0, 0, __DRI_IMAGE_FORMAT_ABGR8888, 4 } } }, - { DRM_FORMAT_XYUV8888, __DRI_IMAGE_FORMAT_XBGR8888, - __DRI_IMAGE_COMPONENTS_XYUV, PIPE_FORMAT_XYUV, 1, - { { 0, 0, 0, __DRI_IMAGE_FORMAT_XBGR8888, 4 } } }, - - /* For YUYV and UYVY buffers, we set up two overlapping DRI images - * and treat them as planar buffers in the compositors. - * Plane 0 is GR88 and samples YU or YV pairs and places Y into - * the R component, while plane 1 is ARGB/ABGR and samples YUYV/UYVY - * clusters and places pairs and places U into the G component and - * V into A. This lets the texture sampler interpolate the Y - * components correctly when sampling from plane 0, and interpolate - * U and V correctly when sampling from plane 1. */ - { DRM_FORMAT_YUYV, __DRI_IMAGE_FORMAT_NONE, - __DRI_IMAGE_COMPONENTS_Y_XUXV, PIPE_FORMAT_YUYV, 2, - { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88, 2 }, - { 0, 1, 0, __DRI_IMAGE_FORMAT_ARGB8888, 4 } } }, - { DRM_FORMAT_UYVY, __DRI_IMAGE_FORMAT_NONE, - __DRI_IMAGE_COMPONENTS_Y_UXVX, PIPE_FORMAT_UYVY, 2, - { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88, 2 }, - { 0, 1, 0, __DRI_IMAGE_FORMAT_ABGR8888, 4 } } } -}; - -const struct dri2_format_mapping * -dri2_get_mapping_by_fourcc(int fourcc) -{ - for (unsigned i = 0; i < ARRAY_SIZE(dri2_format_table); i++) { - if (dri2_format_table[i].dri_fourcc == fourcc) - return &dri2_format_table[i]; - } - - return NULL; -} - -const struct dri2_format_mapping * -dri2_get_mapping_by_format(int format) -{ - for (unsigned i = 0; i < ARRAY_SIZE(dri2_format_table); i++) { - if (dri2_format_table[i].dri_format == format) - return &dri2_format_table[i]; - } - - return NULL; -} - -enum pipe_format -dri2_get_pipe_format_for_dri_format(int format) -{ - for (unsigned i = 0; i < ARRAY_SIZE(dri2_format_table); i++) { - if (dri2_format_table[i].dri_format == format) - return dri2_format_table[i].pipe_format; - } - - return PIPE_FORMAT_NONE; -} - -boolean -dri2_yuv_dma_buf_supported(struct dri_screen *screen, - const struct dri2_format_mapping *map) -{ - struct pipe_screen *pscreen = screen->base.screen; - - for (unsigned i = 0; i < map->nplanes; i++) { - if (!pscreen->is_format_supported(pscreen, - dri2_get_pipe_format_for_dri_format(map->planes[i].dri_format), - screen->target, 0, 0, PIPE_BIND_SAMPLER_VIEW)) - return false; - } - return true; -} - -boolean -dri2_query_dma_buf_formats(__DRIscreen *_screen, int max, int *formats, - int *count) -{ - struct dri_screen *screen = dri_screen(_screen); - struct pipe_screen *pscreen = screen->base.screen; - int i, j; - - for (i = 0, j = 0; (i < ARRAY_SIZE(dri2_format_table)) && - (j < max || max == 0); i++) { - const struct dri2_format_mapping *map = &dri2_format_table[i]; - - /* The sRGB format is not a real FourCC as defined by drm_fourcc.h, so we - * must not leak it out to clients. - */ - if (dri2_format_table[i].dri_fourcc == __DRI_IMAGE_FOURCC_SARGB8888) - continue; - - if (pscreen->is_format_supported(pscreen, map->pipe_format, - screen->target, 0, 0, - PIPE_BIND_RENDER_TARGET) || - pscreen->is_format_supported(pscreen, map->pipe_format, - screen->target, 0, 0, - PIPE_BIND_SAMPLER_VIEW) || - dri2_yuv_dma_buf_supported(screen, map)) { - if (j < max) - formats[j] = map->dri_fourcc; - j++; - } - } - *count = j; - return true; -} - -/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/dri_helpers.h b/src/gallium/state_trackers/dri/dri_helpers.h deleted file mode 100644 index 0393a48a8ee..00000000000 --- a/src/gallium/state_trackers/dri/dri_helpers.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef DRI_HELPERS_H -#define DRI_HELPERS_H - -#include "dri_context.h" -#include "dri_screen.h" - - -struct dri2_format_mapping { - int dri_fourcc; - int dri_format; /* image format */ - int dri_components; - enum pipe_format pipe_format; - int nplanes; - struct { - int buffer_index; - int width_shift; - int height_shift; - uint32_t dri_format; /* plane format */ - int cpp; - } planes[3]; -}; - -extern const __DRI2fenceExtension dri2FenceExtension; - -const struct dri2_format_mapping * -dri2_get_mapping_by_fourcc(int fourcc); - -const struct dri2_format_mapping * -dri2_get_mapping_by_format(int format); - -enum pipe_format -dri2_get_pipe_format_for_dri_format(int format); - -boolean -dri2_query_dma_buf_formats(__DRIscreen *_screen, int max, int *formats, - int *count); -boolean -dri2_yuv_dma_buf_supported(struct dri_screen *screen, - const struct dri2_format_mapping *map); - -__DRIimage * -dri2_lookup_egl_image(struct dri_screen *screen, void *handle); - -__DRIimage * -dri2_create_image_from_renderbuffer(__DRIcontext *context, - int renderbuffer, void *loaderPrivate); - -__DRIimage * -dri2_create_image_from_renderbuffer2(__DRIcontext *context, - int renderbuffer, void *loaderPrivate, - unsigned *error); - -void -dri2_destroy_image(__DRIimage *img); - -__DRIimage * -dri2_create_from_texture(__DRIcontext *context, int target, unsigned texture, - int depth, int level, unsigned *error, - void *loaderPrivate); -#endif - -/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/dri_query_renderer.c b/src/gallium/state_trackers/dri/dri_query_renderer.c deleted file mode 100644 index 2417f40a6ad..00000000000 --- a/src/gallium/state_trackers/dri/dri_query_renderer.c +++ /dev/null @@ -1,93 +0,0 @@ -#include "dri_query_renderer.h" - -#include "util/u_inlines.h" -#include "state_tracker/drm_driver.h" - -#include "utils.h" -#include "dri_screen.h" -#include "dri_query_renderer.h" - -static int -dri2_query_renderer_integer(__DRIscreen *_screen, int param, - unsigned int *value) -{ - struct dri_screen *screen = dri_screen(_screen); - - switch (param) { - case __DRI2_RENDERER_VENDOR_ID: - value[0] = - (unsigned int)screen->base.screen->get_param(screen->base.screen, - PIPE_CAP_VENDOR_ID); - return 0; - case __DRI2_RENDERER_DEVICE_ID: - value[0] = - (unsigned int)screen->base.screen->get_param(screen->base.screen, - PIPE_CAP_DEVICE_ID); - return 0; - case __DRI2_RENDERER_ACCELERATED: - value[0] = - (unsigned int)screen->base.screen->get_param(screen->base.screen, - PIPE_CAP_ACCELERATED); - return 0; - - case __DRI2_RENDERER_VIDEO_MEMORY: - value[0] = - (unsigned int)screen->base.screen->get_param(screen->base.screen, - PIPE_CAP_VIDEO_MEMORY); - return 0; - - case __DRI2_RENDERER_UNIFIED_MEMORY_ARCHITECTURE: - value[0] = - (unsigned int)screen->base.screen->get_param(screen->base.screen, - PIPE_CAP_UMA); - return 0; - - case __DRI2_RENDERER_HAS_TEXTURE_3D: - value[0] = - screen->base.screen->get_param(screen->base.screen, - PIPE_CAP_MAX_TEXTURE_3D_LEVELS) != 0; - return 0; - - case __DRI2_RENDERER_HAS_FRAMEBUFFER_SRGB: - value[0] = - screen->base.screen->is_format_supported(screen->base.screen, - PIPE_FORMAT_B8G8R8A8_SRGB, - PIPE_TEXTURE_2D, 0, 0, - PIPE_BIND_RENDER_TARGET); - return 0; - case __DRI2_RENDERER_HAS_CONTEXT_PRIORITY: - value[0] = - screen->base.screen->get_param(screen->base.screen, - PIPE_CAP_CONTEXT_PRIORITY_MASK); - if (!value[0]) - return -1; - return 0; - default: - return driQueryRendererIntegerCommon(_screen, param, value); - } -} - -static int -dri2_query_renderer_string(__DRIscreen *_screen, int param, - const char **value) -{ - struct dri_screen *screen = dri_screen(_screen); - - switch (param) { - case __DRI2_RENDERER_VENDOR_ID: - value[0] = screen->base.screen->get_vendor(screen->base.screen); - return 0; - case __DRI2_RENDERER_DEVICE_ID: - value[0] = screen->base.screen->get_name(screen->base.screen); - return 0; - default: - return -1; - } -} - -const __DRI2rendererQueryExtension dri2RendererQueryExtension = { - .base = { __DRI2_RENDERER_QUERY, 1 }, - - .queryInteger = dri2_query_renderer_integer, - .queryString = dri2_query_renderer_string -}; diff --git a/src/gallium/state_trackers/dri/dri_query_renderer.h b/src/gallium/state_trackers/dri/dri_query_renderer.h deleted file mode 100644 index 59b3ff8e5b3..00000000000 --- a/src/gallium/state_trackers/dri/dri_query_renderer.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef DRI_QUERY_RENDERER_H -#define DRI_QUERY_RENDERER_H - -#include "dri_util.h" - -extern const -__DRI2rendererQueryExtension dri2RendererQueryExtension; - -#endif diff --git a/src/gallium/state_trackers/dri/dri_screen.c b/src/gallium/state_trackers/dri/dri_screen.c deleted file mode 100644 index 4f1bf166125..00000000000 --- a/src/gallium/state_trackers/dri/dri_screen.c +++ /dev/null @@ -1,605 +0,0 @@ -/************************************************************************** - * - * Copyright 2009, VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ -/* - * Author: Keith Whitwell - * Author: Jakob Bornecrantz - */ - -#include "utils.h" - -#include "dri_screen.h" -#include "dri_context.h" -#include "dri_helpers.h" - -#include "util/u_inlines.h" -#include "pipe/p_screen.h" -#include "pipe/p_format.h" -#include "pipe-loader/pipe_loader.h" -#include "state_tracker/st_gl_api.h" /* for st_gl_api_create */ -#include "state_tracker/drm_driver.h" - -#include "util/u_debug.h" -#include "util/format/u_format_s3tc.h" - -#define MSAA_VISUAL_MAX_SAMPLES 32 - -#undef false - -const __DRIconfigOptionsExtension gallium_config_options = { - .base = { __DRI_CONFIG_OPTIONS, 2 }, - .xml = gallium_driinfo_xml, - .getXml = pipe_loader_get_driinfo_xml -}; - -#define false 0 - -static void -dri_fill_st_options(struct dri_screen *screen) -{ - struct st_config_options *options = &screen->options; - const struct driOptionCache *optionCache = &screen->dev->option_cache; - - options->disable_blend_func_extended = - driQueryOptionb(optionCache, "disable_blend_func_extended"); - options->disable_arb_gpu_shader5 = - driQueryOptionb(optionCache, "disable_arb_gpu_shader5"); - options->disable_glsl_line_continuations = - driQueryOptionb(optionCache, "disable_glsl_line_continuations"); - options->force_glsl_extensions_warn = - driQueryOptionb(optionCache, "force_glsl_extensions_warn"); - options->force_glsl_version = - driQueryOptioni(optionCache, "force_glsl_version"); - options->allow_glsl_extension_directive_midshader = - driQueryOptionb(optionCache, "allow_glsl_extension_directive_midshader"); - options->allow_glsl_builtin_const_expression = - driQueryOptionb(optionCache, "allow_glsl_builtin_const_expression"); - options->allow_glsl_relaxed_es = - driQueryOptionb(optionCache, "allow_glsl_relaxed_es"); - options->allow_glsl_builtin_variable_redeclaration = - driQueryOptionb(optionCache, "allow_glsl_builtin_variable_redeclaration"); - options->allow_higher_compat_version = - driQueryOptionb(optionCache, "allow_higher_compat_version"); - options->glsl_zero_init = driQueryOptionb(optionCache, "glsl_zero_init"); - options->force_integer_tex_nearest = - driQueryOptionb(optionCache, "force_integer_tex_nearest"); - options->vs_position_always_invariant = - driQueryOptionb(optionCache, "vs_position_always_invariant"); - options->force_glsl_abs_sqrt = - driQueryOptionb(optionCache, "force_glsl_abs_sqrt"); - options->allow_glsl_cross_stage_interpolation_mismatch = - driQueryOptionb(optionCache, "allow_glsl_cross_stage_interpolation_mismatch"); - options->allow_glsl_layout_qualifier_on_function_parameters = - driQueryOptionb(optionCache, "allow_glsl_layout_qualifier_on_function_parameters"); - options->allow_draw_out_of_order = - driQueryOptionb(optionCache, "allow_draw_out_of_order"); - - char *vendor_str = driQueryOptionstr(optionCache, "force_gl_vendor"); - /* not an empty string */ - if (*vendor_str) - options->force_gl_vendor = strdup(vendor_str); - - driComputeOptionsSha1(optionCache, options->config_options_sha1); -} - -static unsigned -dri_loader_get_cap(struct dri_screen *screen, enum dri_loader_cap cap) -{ - const __DRIdri2LoaderExtension *dri2_loader = screen->sPriv->dri2.loader; - const __DRIimageLoaderExtension *image_loader = screen->sPriv->image.loader; - - if (dri2_loader && dri2_loader->base.version >= 4 && - dri2_loader->getCapability) - return dri2_loader->getCapability(screen->sPriv->loaderPrivate, cap); - - if (image_loader && image_loader->base.version >= 2 && - image_loader->getCapability) - return image_loader->getCapability(screen->sPriv->loaderPrivate, cap); - - return 0; -} - -static const __DRIconfig ** -dri_fill_in_modes(struct dri_screen *screen) -{ - static const mesa_format mesa_formats[] = { - MESA_FORMAT_B10G10R10A2_UNORM, - MESA_FORMAT_B10G10R10X2_UNORM, - MESA_FORMAT_R10G10B10A2_UNORM, - MESA_FORMAT_R10G10B10X2_UNORM, - MESA_FORMAT_B8G8R8A8_UNORM, - MESA_FORMAT_B8G8R8X8_UNORM, - MESA_FORMAT_B8G8R8A8_SRGB, - MESA_FORMAT_B8G8R8X8_SRGB, - MESA_FORMAT_B5G6R5_UNORM, - MESA_FORMAT_RGBA_FLOAT16, - MESA_FORMAT_RGBX_FLOAT16, - - /* The 32-bit RGBA format must not precede the 32-bit BGRA format. - * Likewise for RGBX and BGRX. Otherwise, the GLX client and the GLX - * server may disagree on which format the GLXFBConfig represents, - * resulting in swapped color channels. - * - * The problem, as of 2017-05-30: - * When matching a GLXFBConfig to a __DRIconfig, GLX ignores the channel - * order and chooses the first __DRIconfig with the expected channel - * sizes. Specifically, GLX compares the GLXFBConfig's and __DRIconfig's - * __DRI_ATTRIB_{CHANNEL}_SIZE but ignores __DRI_ATTRIB_{CHANNEL}_MASK. - * - * EGL does not suffer from this problem. It correctly compares the - * channel masks when matching EGLConfig to __DRIconfig. - */ - - /* Required by Android, for HAL_PIXEL_FORMAT_RGBA_8888. */ - MESA_FORMAT_R8G8B8A8_UNORM, - - /* Required by Android, for HAL_PIXEL_FORMAT_RGBX_8888. */ - MESA_FORMAT_R8G8B8X8_UNORM, - }; - static const enum pipe_format pipe_formats[] = { - PIPE_FORMAT_B10G10R10A2_UNORM, - PIPE_FORMAT_B10G10R10X2_UNORM, - PIPE_FORMAT_R10G10B10A2_UNORM, - PIPE_FORMAT_R10G10B10X2_UNORM, - PIPE_FORMAT_BGRA8888_UNORM, - PIPE_FORMAT_BGRX8888_UNORM, - PIPE_FORMAT_BGRA8888_SRGB, - PIPE_FORMAT_BGRX8888_SRGB, - PIPE_FORMAT_B5G6R5_UNORM, - PIPE_FORMAT_R16G16B16A16_FLOAT, - PIPE_FORMAT_R16G16B16X16_FLOAT, - PIPE_FORMAT_RGBA8888_UNORM, - PIPE_FORMAT_RGBX8888_UNORM, - }; - mesa_format format; - __DRIconfig **configs = NULL; - uint8_t depth_bits_array[5]; - uint8_t stencil_bits_array[5]; - unsigned depth_buffer_factor; - unsigned msaa_samples_max; - unsigned i; - struct pipe_screen *p_screen = screen->base.screen; - bool pf_z16, pf_x8z24, pf_z24x8, pf_s8z24, pf_z24s8, pf_z32; - bool mixed_color_depth; - bool allow_rgba_ordering; - bool allow_rgb10; - bool allow_fp16; - - static const GLenum back_buffer_modes[] = { - __DRI_ATTRIB_SWAP_NONE, __DRI_ATTRIB_SWAP_UNDEFINED, - __DRI_ATTRIB_SWAP_COPY - }; - - if (driQueryOptionb(&screen->dev->option_cache, "always_have_depth_buffer")) { - /* all visuals will have a depth buffer */ - depth_buffer_factor = 0; - } - else { - depth_bits_array[0] = 0; - stencil_bits_array[0] = 0; - depth_buffer_factor = 1; - } - - allow_rgba_ordering = dri_loader_get_cap(screen, DRI_LOADER_CAP_RGBA_ORDERING); - allow_rgb10 = driQueryOptionb(&screen->dev->option_cache, "allow_rgb10_configs"); - allow_fp16 = driQueryOptionb(&screen->dev->option_cache, "allow_fp16_configs"); - allow_fp16 &= dri_loader_get_cap(screen, DRI_LOADER_CAP_FP16); - - msaa_samples_max = (screen->st_api->feature_mask & ST_API_FEATURE_MS_VISUALS_MASK) - ? MSAA_VISUAL_MAX_SAMPLES : 1; - - pf_x8z24 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z24X8_UNORM, - PIPE_TEXTURE_2D, 0, 0, - PIPE_BIND_DEPTH_STENCIL); - pf_z24x8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_X8Z24_UNORM, - PIPE_TEXTURE_2D, 0, 0, - PIPE_BIND_DEPTH_STENCIL); - pf_s8z24 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z24_UNORM_S8_UINT, - PIPE_TEXTURE_2D, 0, 0, - PIPE_BIND_DEPTH_STENCIL); - pf_z24s8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_S8_UINT_Z24_UNORM, - PIPE_TEXTURE_2D, 0, 0, - PIPE_BIND_DEPTH_STENCIL); - pf_z16 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z16_UNORM, - PIPE_TEXTURE_2D, 0, 0, - PIPE_BIND_DEPTH_STENCIL); - pf_z32 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z32_UNORM, - PIPE_TEXTURE_2D, 0, 0, - PIPE_BIND_DEPTH_STENCIL); - - if (pf_z16) { - depth_bits_array[depth_buffer_factor] = 16; - stencil_bits_array[depth_buffer_factor++] = 0; - } - if (pf_x8z24 || pf_z24x8) { - depth_bits_array[depth_buffer_factor] = 24; - stencil_bits_array[depth_buffer_factor++] = 0; - screen->d_depth_bits_last = pf_x8z24; - } - if (pf_s8z24 || pf_z24s8) { - depth_bits_array[depth_buffer_factor] = 24; - stencil_bits_array[depth_buffer_factor++] = 8; - screen->sd_depth_bits_last = pf_s8z24; - } - if (pf_z32) { - depth_bits_array[depth_buffer_factor] = 32; - stencil_bits_array[depth_buffer_factor++] = 0; - } - - mixed_color_depth = - p_screen->get_param(p_screen, PIPE_CAP_MIXED_COLOR_DEPTH_BITS); - - assert(ARRAY_SIZE(mesa_formats) == ARRAY_SIZE(pipe_formats)); - - /* Add configs. */ - for (format = 0; format < ARRAY_SIZE(mesa_formats); format++) { - __DRIconfig **new_configs = NULL; - unsigned num_msaa_modes = 0; /* includes a single-sample mode */ - uint8_t msaa_modes[MSAA_VISUAL_MAX_SAMPLES]; - - /* Expose only BGRA ordering if the loader doesn't support RGBA ordering. */ - if (!allow_rgba_ordering && - (mesa_formats[format] == MESA_FORMAT_R8G8B8A8_UNORM || - mesa_formats[format] == MESA_FORMAT_R8G8B8X8_UNORM)) - continue; - - if (!allow_rgb10 && - (mesa_formats[format] == MESA_FORMAT_B10G10R10A2_UNORM || - mesa_formats[format] == MESA_FORMAT_B10G10R10X2_UNORM || - mesa_formats[format] == MESA_FORMAT_R10G10B10A2_UNORM || - mesa_formats[format] == MESA_FORMAT_R10G10B10X2_UNORM)) - continue; - - if (!allow_fp16 && - (mesa_formats[format] == MESA_FORMAT_RGBA_FLOAT16 || - mesa_formats[format] == MESA_FORMAT_RGBX_FLOAT16)) - continue; - - if (!p_screen->is_format_supported(p_screen, pipe_formats[format], - PIPE_TEXTURE_2D, 0, 0, - PIPE_BIND_RENDER_TARGET | - PIPE_BIND_DISPLAY_TARGET)) - continue; - - for (i = 1; i <= msaa_samples_max; i++) { - int samples = i > 1 ? i : 0; - - if (p_screen->is_format_supported(p_screen, pipe_formats[format], - PIPE_TEXTURE_2D, samples, samples, - PIPE_BIND_RENDER_TARGET)) { - msaa_modes[num_msaa_modes++] = samples; - } - } - - if (num_msaa_modes) { - /* Single-sample configs with an accumulation buffer. */ - new_configs = driCreateConfigs(mesa_formats[format], - depth_bits_array, stencil_bits_array, - depth_buffer_factor, back_buffer_modes, - ARRAY_SIZE(back_buffer_modes), - msaa_modes, 1, - GL_TRUE, !mixed_color_depth, GL_FALSE); - configs = driConcatConfigs(configs, new_configs); - - /* Multi-sample configs without an accumulation buffer. */ - if (num_msaa_modes > 1) { - new_configs = driCreateConfigs(mesa_formats[format], - depth_bits_array, stencil_bits_array, - depth_buffer_factor, back_buffer_modes, - ARRAY_SIZE(back_buffer_modes), - msaa_modes+1, num_msaa_modes-1, - GL_FALSE, !mixed_color_depth, GL_FALSE); - configs = driConcatConfigs(configs, new_configs); - } - } - } - - if (configs == NULL) { - debug_printf("%s: driCreateConfigs failed\n", __FUNCTION__); - return NULL; - } - - return (const __DRIconfig **)configs; -} - -/** - * Roughly the converse of dri_fill_in_modes. - */ -void -dri_fill_st_visual(struct st_visual *stvis, - const struct dri_screen *screen, - const struct gl_config *mode) -{ - memset(stvis, 0, sizeof(*stvis)); - - if (!mode) { - stvis->no_config = true; - return; - } - - /* Deduce the color format. */ - switch (mode->redMask) { - case 0: - /* Formats > 32 bpp */ - assert(mode->floatMode); - if (mode->alphaShift > -1) { - assert(mode->alphaShift == 48); - stvis->color_format = PIPE_FORMAT_R16G16B16A16_FLOAT; - } else { - stvis->color_format = PIPE_FORMAT_R16G16B16X16_FLOAT; - } - break; - - case 0x3FF00000: - if (mode->alphaMask) { - assert(mode->alphaMask == 0xC0000000); - stvis->color_format = PIPE_FORMAT_B10G10R10A2_UNORM; - } else { - stvis->color_format = PIPE_FORMAT_B10G10R10X2_UNORM; - } - break; - - case 0x000003FF: - if (mode->alphaMask) { - assert(mode->alphaMask == 0xC0000000); - stvis->color_format = PIPE_FORMAT_R10G10B10A2_UNORM; - } else { - stvis->color_format = PIPE_FORMAT_R10G10B10X2_UNORM; - } - break; - - case 0x00FF0000: - if (mode->alphaMask) { - assert(mode->alphaMask == 0xFF000000); - stvis->color_format = mode->sRGBCapable ? - PIPE_FORMAT_BGRA8888_SRGB : - PIPE_FORMAT_BGRA8888_UNORM; - } else { - stvis->color_format = mode->sRGBCapable ? - PIPE_FORMAT_BGRX8888_SRGB : - PIPE_FORMAT_BGRX8888_UNORM; - } - break; - - case 0x000000FF: - if (mode->alphaMask) { - assert(mode->alphaMask == 0xFF000000); - stvis->color_format = mode->sRGBCapable ? - PIPE_FORMAT_RGBA8888_SRGB : - PIPE_FORMAT_RGBA8888_UNORM; - } else { - stvis->color_format = mode->sRGBCapable ? - PIPE_FORMAT_RGBX8888_SRGB : - PIPE_FORMAT_RGBX8888_UNORM; - } - break; - - case 0x0000F800: - stvis->color_format = PIPE_FORMAT_B5G6R5_UNORM; - break; - - default: - assert(!"unsupported visual: invalid red mask"); - return; - } - - if (mode->sampleBuffers) { - stvis->samples = mode->samples; - } - - switch (mode->depthBits) { - default: - case 0: - stvis->depth_stencil_format = PIPE_FORMAT_NONE; - break; - case 16: - stvis->depth_stencil_format = PIPE_FORMAT_Z16_UNORM; - break; - case 24: - if (mode->stencilBits == 0) { - stvis->depth_stencil_format = (screen->d_depth_bits_last) ? - PIPE_FORMAT_Z24X8_UNORM: - PIPE_FORMAT_X8Z24_UNORM; - } else { - stvis->depth_stencil_format = (screen->sd_depth_bits_last) ? - PIPE_FORMAT_Z24_UNORM_S8_UINT: - PIPE_FORMAT_S8_UINT_Z24_UNORM; - } - break; - case 32: - stvis->depth_stencil_format = PIPE_FORMAT_Z32_UNORM; - break; - } - - stvis->accum_format = (mode->accumRedBits > 0) ? - PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE; - - stvis->buffer_mask |= ST_ATTACHMENT_FRONT_LEFT_MASK; - stvis->render_buffer = ST_ATTACHMENT_FRONT_LEFT; - if (mode->doubleBufferMode) { - stvis->buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK; - stvis->render_buffer = ST_ATTACHMENT_BACK_LEFT; - } - if (mode->stereoMode) { - stvis->buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK; - if (mode->doubleBufferMode) - stvis->buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK; - } - - if (mode->depthBits > 0 || mode->stencilBits > 0) - stvis->buffer_mask |= ST_ATTACHMENT_DEPTH_STENCIL_MASK; - /* let the state tracker allocate the accum buffer */ -} - -static bool -dri_get_egl_image(struct st_manager *smapi, - void *egl_image, - struct st_egl_image *stimg) -{ - struct dri_screen *screen = (struct dri_screen *)smapi; - __DRIimage *img = NULL; - const struct dri2_format_mapping *map; - - if (screen->lookup_egl_image) { - img = screen->lookup_egl_image(screen, egl_image); - } - - if (!img) - return FALSE; - - stimg->texture = NULL; - pipe_resource_reference(&stimg->texture, img->texture); - map = dri2_get_mapping_by_fourcc(img->dri_fourcc); - stimg->format = map ? map->pipe_format : img->texture->format; - stimg->level = img->level; - stimg->layer = img->layer; - - if (img->imported_dmabuf && map) { - /* Guess sized internal format for dma-bufs. Could be used - * by EXT_EGL_image_storage. - */ - mesa_format mesa_format = driImageFormatToGLFormat(map->dri_format); - stimg->internalformat = driGLFormatToSizedInternalGLFormat(mesa_format); - } - - return TRUE; -} - -static int -dri_get_param(struct st_manager *smapi, - enum st_manager_param param) -{ - struct dri_screen *screen = (struct dri_screen *)smapi; - - switch(param) { - case ST_MANAGER_BROKEN_INVALIDATE: - return screen->broken_invalidate; - default: - return 0; - } -} - -void -dri_destroy_screen_helper(struct dri_screen * screen) -{ - if (screen->base.destroy) - screen->base.destroy(&screen->base); - - if (screen->st_api && screen->st_api->destroy) - screen->st_api->destroy(screen->st_api); - - if (screen->base.screen) - screen->base.screen->destroy(screen->base.screen); - - mtx_destroy(&screen->opencl_func_mutex); -} - -void -dri_destroy_screen(__DRIscreen * sPriv) -{ - struct dri_screen *screen = dri_screen(sPriv); - - dri_destroy_screen_helper(screen); - - pipe_loader_release(&screen->dev, 1); - - free(screen->options.force_gl_vendor); - - /* The caller in dri_util preserves the fd ownership */ - free(screen); - sPriv->driverPrivate = NULL; - sPriv->extensions = NULL; -} - -static void -dri_postprocessing_init(struct dri_screen *screen) -{ - unsigned i; - - for (i = 0; i < PP_FILTERS; i++) { - screen->pp_enabled[i] = driQueryOptioni(&screen->dev->option_cache, - pp_filters[i].name); - } -} - -static void -dri_set_background_context(struct st_context_iface *st, - struct util_queue_monitoring *queue_info) -{ - struct dri_context *ctx = (struct dri_context *)st->st_manager_private; - const __DRIbackgroundCallableExtension *backgroundCallable = - ctx->sPriv->dri2.backgroundCallable; - - /* Note: Mesa will only call this function if GL multithreading is enabled - * We only do that if the loader exposed the __DRI_BACKGROUND_CALLABLE - * extension. So we know that backgroundCallable is not NULL. - */ - assert(backgroundCallable); - backgroundCallable->setBackgroundContext(ctx->cPriv->loaderPrivate); - - if (ctx->hud) - hud_add_queue_for_monitoring(ctx->hud, queue_info); -} - -void -dri_init_options(struct dri_screen *screen) -{ - pipe_loader_load_options(screen->dev); - - dri_fill_st_options(screen); -} - -const __DRIconfig ** -dri_init_screen_helper(struct dri_screen *screen, - struct pipe_screen *pscreen) -{ - screen->base.screen = pscreen; - screen->base.get_egl_image = dri_get_egl_image; - screen->base.get_param = dri_get_param; - screen->base.set_background_context = dri_set_background_context; - - screen->st_api = st_gl_api_create(); - if (!screen->st_api) - return NULL; - - if(pscreen->get_param(pscreen, PIPE_CAP_NPOT_TEXTURES)) - screen->target = PIPE_TEXTURE_2D; - else - screen->target = PIPE_TEXTURE_RECT; - - dri_postprocessing_init(screen); - - screen->st_api->query_versions(screen->st_api, &screen->base, - &screen->options, - &screen->sPriv->max_gl_core_version, - &screen->sPriv->max_gl_compat_version, - &screen->sPriv->max_gl_es1_version, - &screen->sPriv->max_gl_es2_version); - - return dri_fill_in_modes(screen); -} - -/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/dri_screen.h b/src/gallium/state_trackers/dri/dri_screen.h deleted file mode 100644 index 1586439bba3..00000000000 --- a/src/gallium/state_trackers/dri/dri_screen.h +++ /dev/null @@ -1,161 +0,0 @@ -/************************************************************************** - * - * Copyright 2009, VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ -/* - * Author: Keith Whitwell - * Author: Jakob Bornecrantz - */ - -#ifndef DRI_SCREEN_H -#define DRI_SCREEN_H - -#include "dri_util.h" - -#include "pipe/p_compiler.h" -#include "pipe/p_context.h" -#include "pipe/p_state.h" -#include "state_tracker/st_api.h" -#include "state_tracker/opencl_interop.h" -#include "os/os_thread.h" -#include "postprocess/filters.h" - -struct dri_context; -struct dri_drawable; -struct pipe_loader_device; - -struct dri_screen -{ - /* st_api */ - struct st_manager base; - struct st_api *st_api; - - /* on old libGL's invalidate doesn't get called as it should */ - boolean broken_invalidate; - - /* dri */ - __DRIscreen *sPriv; - boolean throttle; - - struct st_config_options options; - - /* Which postprocessing filters are enabled. */ - unsigned pp_enabled[PP_FILTERS]; - - /* drm */ - int fd; - boolean can_share_buffer; - - struct pipe_loader_device *dev; - - /* gallium */ - boolean d_depth_bits_last; - boolean sd_depth_bits_last; - boolean auto_fake_front; - boolean has_reset_status_query; - enum pipe_texture_target target; - - boolean swrast_no_present; - - /* hooks filled in by dri2 & drisw */ - __DRIimage * (*lookup_egl_image)(struct dri_screen *ctx, void *handle); - - /* OpenCL interop */ - mtx_t opencl_func_mutex; - opencl_dri_event_add_ref_t opencl_dri_event_add_ref; - opencl_dri_event_release_t opencl_dri_event_release; - opencl_dri_event_wait_t opencl_dri_event_wait; - opencl_dri_event_get_fence_t opencl_dri_event_get_fence; -}; - -/** cast wrapper */ -static inline struct dri_screen * -dri_screen(__DRIscreen * sPriv) -{ - return (struct dri_screen *)sPriv->driverPrivate; -} - -struct __DRIimageRec { - struct pipe_resource *texture; - unsigned level; - unsigned layer; - uint32_t dri_format; - uint32_t dri_fourcc; - uint32_t dri_components; - unsigned use; - unsigned plane; - - void *loader_private; - - boolean imported_dmabuf; - /** - * Provided by EGL_EXT_image_dma_buf_import. - */ - enum __DRIYUVColorSpace yuv_color_space; - enum __DRISampleRange sample_range; - enum __DRIChromaSiting horizontal_siting; - enum __DRIChromaSiting vertical_siting; - -}; - -static inline boolean -dri_with_format(__DRIscreen * sPriv) -{ - const __DRIdri2LoaderExtension *loader = sPriv->dri2.loader; - - return loader - && (loader->base.version >= 3) - && (loader->getBuffersWithFormat != NULL); -} - -void -dri_fill_st_visual(struct st_visual *stvis, - const struct dri_screen *screen, - const struct gl_config *mode); - -void -dri_init_options(struct dri_screen *screen); - -const __DRIconfig ** -dri_init_screen_helper(struct dri_screen *screen, - struct pipe_screen *pscreen); - -void -dri_destroy_screen_helper(struct dri_screen * screen); - -void -dri_destroy_screen(__DRIscreen * sPriv); - -extern const struct __DriverAPIRec dri_kms_driver_api; - -extern const struct __DriverAPIRec galliumdrm_driver_api; -extern const __DRIextension *galliumdrm_driver_extensions[]; -extern const struct __DriverAPIRec galliumsw_driver_api; -extern const __DRIextension *galliumsw_driver_extensions[]; -extern const __DRIconfigOptionsExtension gallium_config_options; - -#endif - -/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/drisw.c b/src/gallium/state_trackers/dri/drisw.c deleted file mode 100644 index 4afa69f891d..00000000000 --- a/src/gallium/state_trackers/dri/drisw.c +++ /dev/null @@ -1,576 +0,0 @@ -/************************************************************************** - * - * Copyright 2009, VMware, Inc. - * All Rights Reserved. - * Copyright 2010 George Sapountzis - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include "util/format/u_format.h" -#include "util/u_memory.h" -#include "util/u_inlines.h" -#include "util/u_box.h" -#include "pipe/p_context.h" -#include "pipe-loader/pipe_loader.h" -#include "state_tracker/drisw_api.h" -#include "state_tracker/st_context.h" - -#include "dri_screen.h" -#include "dri_context.h" -#include "dri_drawable.h" -#include "dri_helpers.h" -#include "dri_query_renderer.h" - -DEBUG_GET_ONCE_BOOL_OPTION(swrast_no_present, "SWRAST_NO_PRESENT", FALSE); - -static inline void -get_drawable_info(__DRIdrawable *dPriv, int *x, int *y, int *w, int *h) -{ - __DRIscreen *sPriv = dPriv->driScreenPriv; - const __DRIswrastLoaderExtension *loader = sPriv->swrast_loader; - - loader->getDrawableInfo(dPriv, - x, y, w, h, - dPriv->loaderPrivate); -} - -static inline void -put_image(__DRIdrawable *dPriv, void *data, unsigned width, unsigned height) -{ - __DRIscreen *sPriv = dPriv->driScreenPriv; - const __DRIswrastLoaderExtension *loader = sPriv->swrast_loader; - - loader->putImage(dPriv, __DRI_SWRAST_IMAGE_OP_SWAP, - 0, 0, width, height, - data, dPriv->loaderPrivate); -} - -static inline void -put_image2(__DRIdrawable *dPriv, void *data, int x, int y, - unsigned width, unsigned height, unsigned stride) -{ - __DRIscreen *sPriv = dPriv->driScreenPriv; - const __DRIswrastLoaderExtension *loader = sPriv->swrast_loader; - - loader->putImage2(dPriv, __DRI_SWRAST_IMAGE_OP_SWAP, - x, y, width, height, stride, - data, dPriv->loaderPrivate); -} - -static inline void -put_image_shm(__DRIdrawable *dPriv, int shmid, char *shmaddr, - unsigned offset, unsigned offset_x, int x, int y, - unsigned width, unsigned height, unsigned stride) -{ - __DRIscreen *sPriv = dPriv->driScreenPriv; - const __DRIswrastLoaderExtension *loader = sPriv->swrast_loader; - - /* if we have the newer interface, don't have to add the offset_x here. */ - if (loader->base.version > 4 && loader->putImageShm2) - loader->putImageShm2(dPriv, __DRI_SWRAST_IMAGE_OP_SWAP, - x, y, width, height, stride, - shmid, shmaddr, offset, dPriv->loaderPrivate); - else - loader->putImageShm(dPriv, __DRI_SWRAST_IMAGE_OP_SWAP, - x, y, width, height, stride, - shmid, shmaddr, offset + offset_x, dPriv->loaderPrivate); -} - -static inline void -get_image(__DRIdrawable *dPriv, int x, int y, int width, int height, void *data) -{ - __DRIscreen *sPriv = dPriv->driScreenPriv; - const __DRIswrastLoaderExtension *loader = sPriv->swrast_loader; - - loader->getImage(dPriv, - x, y, width, height, - data, dPriv->loaderPrivate); -} - -static inline void -get_image2(__DRIdrawable *dPriv, int x, int y, int width, int height, int stride, void *data) -{ - __DRIscreen *sPriv = dPriv->driScreenPriv; - const __DRIswrastLoaderExtension *loader = sPriv->swrast_loader; - - /* getImage2 support is only in version 3 or newer */ - if (loader->base.version < 3) - return; - - loader->getImage2(dPriv, - x, y, width, height, stride, - data, dPriv->loaderPrivate); -} - -static inline bool -get_image_shm(__DRIdrawable *dPriv, int x, int y, int width, int height, - struct pipe_resource *res) -{ - __DRIscreen *sPriv = dPriv->driScreenPriv; - const __DRIswrastLoaderExtension *loader = sPriv->swrast_loader; - struct winsys_handle whandle; - - whandle.type = WINSYS_HANDLE_TYPE_SHMID; - - if (loader->base.version < 4 || !loader->getImageShm) - return FALSE; - - if (!res->screen->resource_get_handle(res->screen, NULL, res, &whandle, PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE)) - return FALSE; - - if (loader->base.version > 5 && loader->getImageShm2) - return loader->getImageShm2(dPriv, x, y, width, height, whandle.handle, dPriv->loaderPrivate); - - loader->getImageShm(dPriv, x, y, width, height, whandle.handle, dPriv->loaderPrivate); - return TRUE; -} - -static void -drisw_update_drawable_info(struct dri_drawable *drawable) -{ - __DRIdrawable *dPriv = drawable->dPriv; - int x, y; - - get_drawable_info(dPriv, &x, &y, &dPriv->w, &dPriv->h); -} - -static void -drisw_get_image(struct dri_drawable *drawable, - int x, int y, unsigned width, unsigned height, unsigned stride, - void *data) -{ - __DRIdrawable *dPriv = drawable->dPriv; - int draw_x, draw_y, draw_w, draw_h; - - get_drawable_info(dPriv, &draw_x, &draw_y, &draw_w, &draw_h); - get_image2(dPriv, x, y, draw_w, draw_h, stride, data); -} - -static void -drisw_put_image(struct dri_drawable *drawable, - void *data, unsigned width, unsigned height) -{ - __DRIdrawable *dPriv = drawable->dPriv; - - put_image(dPriv, data, width, height); -} - -static void -drisw_put_image2(struct dri_drawable *drawable, - void *data, int x, int y, unsigned width, unsigned height, - unsigned stride) -{ - __DRIdrawable *dPriv = drawable->dPriv; - - put_image2(dPriv, data, x, y, width, height, stride); -} - -static inline void -drisw_put_image_shm(struct dri_drawable *drawable, - int shmid, char *shmaddr, unsigned offset, - unsigned offset_x, - int x, int y, unsigned width, unsigned height, - unsigned stride) -{ - __DRIdrawable *dPriv = drawable->dPriv; - - put_image_shm(dPriv, shmid, shmaddr, offset, offset_x, x, y, width, height, stride); -} - -static inline void -drisw_present_texture(__DRIdrawable *dPriv, - struct pipe_resource *ptex, struct pipe_box *sub_box) -{ - struct dri_drawable *drawable = dri_drawable(dPriv); - struct dri_screen *screen = dri_screen(drawable->sPriv); - - if (screen->swrast_no_present) - return; - - screen->base.screen->flush_frontbuffer(screen->base.screen, ptex, 0, 0, drawable, sub_box); -} - -static inline void -drisw_invalidate_drawable(__DRIdrawable *dPriv) -{ - struct dri_drawable *drawable = dri_drawable(dPriv); - - drawable->texture_stamp = dPriv->lastStamp - 1; - - p_atomic_inc(&drawable->base.stamp); -} - -static inline void -drisw_copy_to_front(__DRIdrawable * dPriv, - struct pipe_resource *ptex) -{ - drisw_present_texture(dPriv, ptex, NULL); - - drisw_invalidate_drawable(dPriv); -} - -/* - * Backend functions for st_framebuffer interface and swap_buffers. - */ - -static void -drisw_swap_buffers(__DRIdrawable *dPriv) -{ - struct dri_context *ctx = dri_get_current(dPriv->driScreenPriv); - struct dri_drawable *drawable = dri_drawable(dPriv); - struct pipe_resource *ptex; - - if (!ctx) - return; - - ptex = drawable->textures[ST_ATTACHMENT_BACK_LEFT]; - - if (ptex) { - if (ctx->pp) - pp_run(ctx->pp, ptex, ptex, drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]); - - if (ctx->hud) - hud_run(ctx->hud, ctx->st->cso_context, ptex); - - ctx->st->flush(ctx->st, ST_FLUSH_FRONT, NULL, NULL, NULL); - - if (drawable->stvis.samples > 1) { - /* Resolve the back buffer. */ - dri_pipe_blit(ctx->st->pipe, - drawable->textures[ST_ATTACHMENT_BACK_LEFT], - drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT]); - } - - drisw_copy_to_front(dPriv, ptex); - } -} - -static void -drisw_copy_sub_buffer(__DRIdrawable *dPriv, int x, int y, - int w, int h) -{ - struct dri_context *ctx = dri_get_current(dPriv->driScreenPriv); - struct dri_drawable *drawable = dri_drawable(dPriv); - struct pipe_resource *ptex; - struct pipe_box box; - if (!ctx) - return; - - ptex = drawable->textures[ST_ATTACHMENT_BACK_LEFT]; - - if (ptex) { - if (ctx->pp && drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]) - pp_run(ctx->pp, ptex, ptex, drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]); - - ctx->st->flush(ctx->st, ST_FLUSH_FRONT, NULL, NULL, NULL); - - u_box_2d(x, dPriv->h - y - h, w, h, &box); - drisw_present_texture(dPriv, ptex, &box); - } -} - -static void -drisw_flush_frontbuffer(struct dri_context *ctx, - struct dri_drawable *drawable, - enum st_attachment_type statt) -{ - struct pipe_resource *ptex; - - if (!ctx) - return; - - if (drawable->stvis.samples > 1) { - /* Resolve the front buffer. */ - dri_pipe_blit(ctx->st->pipe, - drawable->textures[ST_ATTACHMENT_FRONT_LEFT], - drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT]); - } - ptex = drawable->textures[statt]; - - if (ptex) { - drisw_copy_to_front(ctx->dPriv, ptex); - } -} - -/** - * Allocate framebuffer attachments. - * - * During fixed-size operation, the function keeps allocating new attachments - * as they are requested. Unused attachments are not removed, not until the - * framebuffer is resized or destroyed. - */ -static void -drisw_allocate_textures(struct dri_context *stctx, - struct dri_drawable *drawable, - const enum st_attachment_type *statts, - unsigned count) -{ - struct dri_screen *screen = dri_screen(drawable->sPriv); - const __DRIswrastLoaderExtension *loader = drawable->dPriv->driScreenPriv->swrast_loader; - struct pipe_resource templ; - unsigned width, height; - boolean resized; - unsigned i; - - width = drawable->dPriv->w; - height = drawable->dPriv->h; - - resized = (drawable->old_w != width || - drawable->old_h != height); - - /* remove outdated textures */ - if (resized) { - for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { - pipe_resource_reference(&drawable->textures[i], NULL); - pipe_resource_reference(&drawable->msaa_textures[i], NULL); - } - } - - memset(&templ, 0, sizeof(templ)); - templ.target = screen->target; - templ.width0 = width; - templ.height0 = height; - templ.depth0 = 1; - templ.array_size = 1; - templ.last_level = 0; - - for (i = 0; i < count; i++) { - enum pipe_format format; - unsigned bind; - - /* the texture already exists or not requested */ - if (drawable->textures[statts[i]]) - continue; - - dri_drawable_get_format(drawable, statts[i], &format, &bind); - - /* if we don't do any present, no need for display targets */ - if (statts[i] != ST_ATTACHMENT_DEPTH_STENCIL && !screen->swrast_no_present) - bind |= PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_LINEAR; - - if (format == PIPE_FORMAT_NONE) - continue; - - templ.format = format; - templ.bind = bind; - templ.nr_samples = 0; - templ.nr_storage_samples = 0; - - if (statts[i] == ST_ATTACHMENT_FRONT_LEFT && - screen->base.screen->resource_create_front && - loader->base.version >= 3) { - drawable->textures[statts[i]] = - screen->base.screen->resource_create_front(screen->base.screen, &templ, (const void *)drawable); - } else - drawable->textures[statts[i]] = - screen->base.screen->resource_create(screen->base.screen, &templ); - - if (drawable->stvis.samples > 1) { - templ.bind = templ.bind & - ~(PIPE_BIND_SCANOUT | PIPE_BIND_SHARED | PIPE_BIND_DISPLAY_TARGET); - templ.nr_samples = drawable->stvis.samples; - templ.nr_storage_samples = drawable->stvis.samples; - drawable->msaa_textures[statts[i]] = - screen->base.screen->resource_create(screen->base.screen, &templ); - - dri_pipe_blit(stctx->st->pipe, - drawable->msaa_textures[statts[i]], - drawable->textures[statts[i]]); - } - } - - drawable->old_w = width; - drawable->old_h = height; -} - -static void -drisw_update_tex_buffer(struct dri_drawable *drawable, - struct dri_context *ctx, - struct pipe_resource *res) -{ - __DRIdrawable *dPriv = drawable->dPriv; - - struct st_context *st_ctx = (struct st_context *)ctx->st; - struct pipe_context *pipe = st_ctx->pipe; - struct pipe_transfer *transfer; - char *map; - int x, y, w, h; - int ximage_stride, line; - int cpp = util_format_get_blocksize(res->format); - - get_drawable_info(dPriv, &x, &y, &w, &h); - - map = pipe_transfer_map(pipe, res, - 0, 0, // level, layer, - PIPE_TRANSFER_WRITE, - x, y, w, h, &transfer); - - /* Copy the Drawable content to the mapped texture buffer */ - if (!get_image_shm(dPriv, x, y, w, h, res)) - get_image(dPriv, x, y, w, h, map); - - /* The pipe transfer has a pitch rounded up to the nearest 64 pixels. - get_image() has a pitch rounded up to 4 bytes. */ - ximage_stride = ((w * cpp) + 3) & -4; - for (line = h-1; line; --line) { - memmove(&map[line * transfer->stride], - &map[line * ximage_stride], - ximage_stride); - } - - pipe_transfer_unmap(pipe, transfer); -} - -static __DRIimageExtension driSWImageExtension = { - .base = { __DRI_IMAGE, 6 }, - - .createImageFromRenderbuffer = dri2_create_image_from_renderbuffer, - .createImageFromTexture = dri2_create_from_texture, - .destroyImage = dri2_destroy_image, -}; - -/* - * Backend function for init_screen. - */ - -static const __DRIextension *drisw_screen_extensions[] = { - &driTexBufferExtension.base, - &dri2RendererQueryExtension.base, - &dri2ConfigQueryExtension.base, - &dri2FenceExtension.base, - &dri2NoErrorExtension.base, - &driSWImageExtension.base, - &dri2FlushControlExtension.base, - NULL -}; - -static const struct drisw_loader_funcs drisw_lf = { - .get_image = drisw_get_image, - .put_image = drisw_put_image, - .put_image2 = drisw_put_image2 -}; - -static const struct drisw_loader_funcs drisw_shm_lf = { - .get_image = drisw_get_image, - .put_image = drisw_put_image, - .put_image2 = drisw_put_image2, - .put_image_shm = drisw_put_image_shm -}; - -static const __DRIconfig ** -drisw_init_screen(__DRIscreen * sPriv) -{ - const __DRIswrastLoaderExtension *loader = sPriv->swrast_loader; - const __DRIconfig **configs; - struct dri_screen *screen; - struct pipe_screen *pscreen = NULL; - const struct drisw_loader_funcs *lf = &drisw_lf; - - screen = CALLOC_STRUCT(dri_screen); - if (!screen) - return NULL; - - screen->sPriv = sPriv; - screen->fd = -1; - - screen->swrast_no_present = debug_get_option_swrast_no_present(); - - sPriv->driverPrivate = (void *)screen; - sPriv->extensions = drisw_screen_extensions; - if (loader->base.version >= 4) { - if (loader->putImageShm) - lf = &drisw_shm_lf; - } - - if (pipe_loader_sw_probe_dri(&screen->dev, lf)) { - dri_init_options(screen); - - pscreen = pipe_loader_create_screen(screen->dev); - } - - if (!pscreen) - goto fail; - - configs = dri_init_screen_helper(screen, pscreen); - if (!configs) - goto fail; - - screen->lookup_egl_image = dri2_lookup_egl_image; - - return configs; -fail: - dri_destroy_screen_helper(screen); - if (screen->dev) - pipe_loader_release(&screen->dev, 1); - FREE(screen); - return NULL; -} - -static boolean -drisw_create_buffer(__DRIscreen * sPriv, - __DRIdrawable * dPriv, - const struct gl_config * visual, boolean isPixmap) -{ - struct dri_drawable *drawable = NULL; - - if (!dri_create_buffer(sPriv, dPriv, visual, isPixmap)) - return FALSE; - - drawable = dPriv->driverPrivate; - - drawable->allocate_textures = drisw_allocate_textures; - drawable->update_drawable_info = drisw_update_drawable_info; - drawable->flush_frontbuffer = drisw_flush_frontbuffer; - drawable->update_tex_buffer = drisw_update_tex_buffer; - - return TRUE; -} - -/** - * DRI driver virtual function table. - * - * DRI versions differ in their implementation of init_screen and swap_buffers. - */ -const struct __DriverAPIRec galliumsw_driver_api = { - .InitScreen = drisw_init_screen, - .DestroyScreen = dri_destroy_screen, - .CreateContext = dri_create_context, - .DestroyContext = dri_destroy_context, - .CreateBuffer = drisw_create_buffer, - .DestroyBuffer = dri_destroy_buffer, - .SwapBuffers = drisw_swap_buffers, - .MakeCurrent = dri_make_current, - .UnbindContext = dri_unbind_context, - .CopySubBuffer = drisw_copy_sub_buffer, -}; - -/* This is the table of extensions that the loader will dlsym() for. */ -const __DRIextension *galliumsw_driver_extensions[] = { - &driCoreExtension.base, - &driSWRastExtension.base, - &driCopySubBufferExtension.base, - &gallium_config_options.base, - NULL -}; - -/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/meson.build b/src/gallium/state_trackers/dri/meson.build deleted file mode 100644 index 4bb41157e42..00000000000 --- a/src/gallium/state_trackers/dri/meson.build +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright © 2017 Dylan Baker - -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: - -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. - -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -inc_st_dri = include_directories('.') - -files_libdri = files( - 'dri_context.c', - 'dri_context.h', - 'dri_drawable.c', - 'dri_drawable.h', - 'dri_helpers.c', - 'dri_helpers.h', - 'dri_query_renderer.c', - 'dri_query_renderer.h', - 'dri_screen.c', - 'dri_screen.h', -) - -if with_dri - files_libdri += files('drisw.c') -endif - -if with_dri2 - files_libdri += files('dri2.c') -endif - -libdri_c_args = [] -if with_gallium_softpipe - libdri_c_args += '-DGALLIUM_SOFTPIPE' -endif - -libdri = static_library( - 'dri', - files_libdri, - include_directories : [ - inc_include, inc_util, inc_mesa, inc_mapi, inc_src, inc_gallium, - inc_gallium_aux, inc_dri_common, - ], - c_args : [c_vis_args, libdri_c_args], - dependencies : dep_libdrm, -) diff --git a/src/gallium/state_trackers/glx/xlib/Makefile.sources b/src/gallium/state_trackers/glx/xlib/Makefile.sources deleted file mode 100644 index 9e31a70eb3e..00000000000 --- a/src/gallium/state_trackers/glx/xlib/Makefile.sources +++ /dev/null @@ -1,9 +0,0 @@ -C_SOURCES := \ - glx_api.c \ - glx_getproc.c \ - glx_usefont.c \ - xm_api.c \ - xm_api.h \ - xm_public.h \ - xm_st.c \ - xm_st.h diff --git a/src/gallium/state_trackers/glx/xlib/SConscript b/src/gallium/state_trackers/glx/xlib/SConscript deleted file mode 100644 index 1d5dd1df4fd..00000000000 --- a/src/gallium/state_trackers/glx/xlib/SConscript +++ /dev/null @@ -1,18 +0,0 @@ -####################################################################### -# SConscript for xlib state_tracker - -Import('*') - -env = env.Clone() - -env.Append(CPPPATH = [ - '#/src', - '#/src/mapi', - '#/src/mesa', -]) - -st_xlib = env.ConvenienceLibrary( - target = 'st_xlib', - source = env.ParseSourceList('Makefile.sources', 'C_SOURCES') -) -Export('st_xlib') diff --git a/src/gallium/state_trackers/glx/xlib/glx_api.c b/src/gallium/state_trackers/glx/xlib/glx_api.c deleted file mode 100644 index 281111bdfb0..00000000000 --- a/src/gallium/state_trackers/glx/xlib/glx_api.c +++ /dev/null @@ -1,2777 +0,0 @@ -/* - * Mesa 3-D graphics library - * - * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. - * Copyright (C) 2009 VMware, Inc. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - - -/** - * "Fake" GLX API implemented in terms of the XMesa*() functions. - */ - - - -#define GLX_GLXEXT_PROTOTYPES -#include "GL/glx.h" - -#include -#include -#include -#include - -#include "xm_api.h" -#include "main/errors.h" -#include "util/u_math.h" -#include "util/u_memory.h" - -/* An "Atrribs/Attribs" typo was fixed in glxproto.h in Nov 2014. - * This is in case we don't have the updated header. - */ -#if !defined(X_GLXCreateContextAttribsARB) && \ - defined(X_GLXCreateContextAtrribsARB) -#define X_GLXCreateContextAttribsARB X_GLXCreateContextAtrribsARB -#endif - -/* This indicates the client-side GLX API and GLX encoder version. */ -#define CLIENT_MAJOR_VERSION 1 -#define CLIENT_MINOR_VERSION 4 /* but don't have 1.3's pbuffers, etc yet */ - -/* This indicates the server-side GLX decoder version. - * GLX 1.4 indicates OpenGL 1.3 support - */ -#define SERVER_MAJOR_VERSION 1 -#define SERVER_MINOR_VERSION 4 - -/* Who implemented this GLX? */ -#define VENDOR "Brian Paul" - -#define EXTENSIONS \ - "GLX_MESA_copy_sub_buffer " \ - "GLX_MESA_pixmap_colormap " \ - "GLX_MESA_release_buffers " \ - "GLX_ARB_create_context " \ - "GLX_ARB_create_context_profile " \ - "GLX_ARB_get_proc_address " \ - "GLX_EXT_create_context_es_profile " \ - "GLX_EXT_create_context_es2_profile " \ - "GLX_EXT_texture_from_pixmap " \ - "GLX_EXT_visual_info " \ - "GLX_EXT_visual_rating " \ - /*"GLX_SGI_video_sync "*/ \ - "GLX_SGIX_fbconfig " \ - "GLX_SGIX_pbuffer " - -#define DEFAULT_DIRECT GL_TRUE - - -/** XXX this could be based on gallium's max texture size */ -#define PBUFFER_MAX_SIZE 16384 - - -/** - * The GLXContext typedef is defined as a pointer to this structure. - */ -struct __GLXcontextRec -{ - Display *currentDpy; - GLboolean isDirect; - GLXDrawable currentDrawable; - GLXDrawable currentReadable; - XID xid; - - XMesaContext xmesaContext; -}; - - - -static pipe_tsd ContextTSD; - -/** Set current context for calling thread */ -static void -SetCurrentContext(GLXContext c) -{ - pipe_tsd_set(&ContextTSD, c); -} - -/** Get current context for calling thread */ -static GLXContext -GetCurrentContext(void) -{ - return pipe_tsd_get(&ContextTSD); -} - - - -/**********************************************************************/ -/*** GLX Visual Code ***/ -/**********************************************************************/ - -#define DONT_CARE -1 - - -static XMesaVisual *VisualTable = NULL; -static int NumVisuals = 0; - - - -/* Macro to handle c_class vs class field name in XVisualInfo struct */ -#if defined(__cplusplus) || defined(c_plusplus) -#define CLASS c_class -#else -#define CLASS class -#endif - - - -/* - * Test if the given XVisualInfo is usable for Mesa rendering. - */ -static GLboolean -is_usable_visual( XVisualInfo *vinfo ) -{ - switch (vinfo->CLASS) { - case StaticGray: - case GrayScale: - /* Any StaticGray/GrayScale visual works in RGB or CI mode */ - return GL_TRUE; - case StaticColor: - case PseudoColor: - /* Any StaticColor/PseudoColor visual of at least 4 bits */ - if (vinfo->depth>=4) { - return GL_TRUE; - } - else { - return GL_FALSE; - } - case TrueColor: - case DirectColor: - /* Any depth of TrueColor or DirectColor works in RGB mode */ - return GL_TRUE; - default: - /* This should never happen */ - return GL_FALSE; - } -} - - -/* - * Given an XVisualInfo and RGB, Double, and Depth buffer flags, save the - * configuration in our list of GLX visuals. - */ -static XMesaVisual -save_glx_visual( Display *dpy, XVisualInfo *vinfo, - GLboolean rgbFlag, GLboolean alphaFlag, GLboolean dbFlag, - GLboolean stereoFlag, - GLint depth_size, GLint stencil_size, - GLint accumRedSize, GLint accumGreenSize, - GLint accumBlueSize, GLint accumAlphaSize, - GLint level, GLint numAuxBuffers, GLuint num_samples ) -{ - GLboolean ximageFlag = GL_TRUE; - XMesaVisual xmvis; - GLint i; - GLboolean comparePointers; - - if (!rgbFlag) - return NULL; - - if (dbFlag) { - /* Check if the MESA_BACK_BUFFER env var is set */ - char *backbuffer = getenv("MESA_BACK_BUFFER"); - if (backbuffer) { - if (backbuffer[0]=='p' || backbuffer[0]=='P') { - ximageFlag = GL_FALSE; - } - else if (backbuffer[0]=='x' || backbuffer[0]=='X') { - ximageFlag = GL_TRUE; - } - else { - _mesa_warning(NULL, "Mesa: invalid value for MESA_BACK_BUFFER environment variable, using an XImage."); - } - } - } - - if (stereoFlag) { - /* stereo not supported */ - return NULL; - } - - if (stencil_size > 0 && depth_size > 0) - depth_size = 24; - - /* Comparing IDs uses less memory but sometimes fails. */ - /* XXX revisit this after 3.0 is finished. */ - if (getenv("MESA_GLX_VISUAL_HACK")) - comparePointers = GL_TRUE; - else - comparePointers = GL_FALSE; - - /* Force the visual to have an alpha channel */ - if (rgbFlag && getenv("MESA_GLX_FORCE_ALPHA")) - alphaFlag = GL_TRUE; - - /* First check if a matching visual is already in the list */ - for (i=0; idisplay == dpy - && v->mesa_visual.level == level - && v->mesa_visual.numAuxBuffers == numAuxBuffers - && v->mesa_visual.samples == num_samples - && v->ximage_flag == ximageFlag - && v->mesa_visual.doubleBufferMode == dbFlag - && v->mesa_visual.stereoMode == stereoFlag - && (v->mesa_visual.alphaBits > 0) == alphaFlag - && (v->mesa_visual.depthBits >= depth_size || depth_size == 0) - && (v->mesa_visual.stencilBits >= stencil_size || stencil_size == 0) - && (v->mesa_visual.accumRedBits >= accumRedSize || accumRedSize == 0) - && (v->mesa_visual.accumGreenBits >= accumGreenSize || accumGreenSize == 0) - && (v->mesa_visual.accumBlueBits >= accumBlueSize || accumBlueSize == 0) - && (v->mesa_visual.accumAlphaBits >= accumAlphaSize || accumAlphaSize == 0)) { - /* now either compare XVisualInfo pointers or visual IDs */ - if ((!comparePointers && v->visinfo->visualid == vinfo->visualid) - || (comparePointers && v->vishandle == vinfo)) { - return v; - } - } - } - - /* Create a new visual and add it to the list. */ - - xmvis = XMesaCreateVisual( dpy, vinfo, rgbFlag, alphaFlag, dbFlag, - stereoFlag, ximageFlag, - depth_size, stencil_size, - accumRedSize, accumBlueSize, - accumBlueSize, accumAlphaSize, num_samples, level, - GLX_NONE_EXT ); - if (xmvis) { - /* Save a copy of the pointer now so we can find this visual again - * if we need to search for it in find_glx_visual(). - */ - xmvis->vishandle = vinfo; - /* Allocate more space for additional visual */ - VisualTable = realloc(VisualTable, sizeof(XMesaVisual) * (NumVisuals + 1)); - /* add xmvis to the list */ - VisualTable[NumVisuals] = xmvis; - NumVisuals++; - /* XXX minor hack, because XMesaCreateVisual doesn't support an - * aux buffers parameter. - */ - xmvis->mesa_visual.numAuxBuffers = numAuxBuffers; - } - return xmvis; -} - - -/** - * Return the default number of bits for the Z buffer. - * If defined, use the MESA_GLX_DEPTH_BITS env var value. - * Otherwise, use the DEFAULT_SOFTWARE_DEPTH_BITS constant. - * XXX probably do the same thing for stencil, accum, etc. - */ -static GLint -default_depth_bits(void) -{ - int zBits; - const char *zEnv = getenv("MESA_GLX_DEPTH_BITS"); - if (zEnv) - zBits = atoi(zEnv); - else - zBits = 24; - return zBits; -} - -static GLint -default_alpha_bits(void) -{ - int aBits; - const char *aEnv = getenv("MESA_GLX_ALPHA_BITS"); - if (aEnv) - aBits = atoi(aEnv); - else - aBits = 0; - return aBits; -} - -static GLint -default_accum_bits(void) -{ - return 16; -} - - - -/* - * Create a GLX visual from a regular XVisualInfo. - * This is called when Fake GLX is given an XVisualInfo which wasn't - * returned by glXChooseVisual. Since this is the first time we're - * considering this visual we'll take a guess at reasonable values - * for depth buffer size, stencil size, accum size, etc. - * This is the best we can do with a client-side emulation of GLX. - */ -static XMesaVisual -create_glx_visual( Display *dpy, XVisualInfo *visinfo ) -{ - GLint zBits = default_depth_bits(); - GLint accBits = default_accum_bits(); - GLboolean alphaFlag = default_alpha_bits() > 0; - - if (is_usable_visual( visinfo )) { - /* Configure this visual as RGB, double-buffered, depth-buffered. */ - /* This is surely wrong for some people's needs but what else */ - /* can be done? They should use glXChooseVisual(). */ - return save_glx_visual( dpy, visinfo, - GL_TRUE, /* rgb */ - alphaFlag, /* alpha */ - GL_TRUE, /* double */ - GL_FALSE, /* stereo */ - zBits, - 8, /* stencil bits */ - accBits, /* r */ - accBits, /* g */ - accBits, /* b */ - accBits, /* a */ - 0, /* level */ - 0, /* numAux */ - 0 /* numSamples */ - ); - } - else { - _mesa_warning(NULL, "Mesa: error in glXCreateContext: bad visual\n"); - return NULL; - } -} - - - -/* - * Find the GLX visual associated with an XVisualInfo. - */ -static XMesaVisual -find_glx_visual( Display *dpy, XVisualInfo *vinfo ) -{ - int i; - - /* try to match visual id */ - for (i=0;idisplay==dpy - && VisualTable[i]->visinfo->visualid == vinfo->visualid) { - return VisualTable[i]; - } - } - - /* if that fails, try to match pointers */ - for (i=0;idisplay==dpy && VisualTable[i]->vishandle==vinfo) { - return VisualTable[i]; - } - } - - return NULL; -} - - -/** - * Try to get an X visual which matches the given arguments. - */ -static XVisualInfo * -get_visual( Display *dpy, int scr, unsigned int depth, int xclass ) -{ - XVisualInfo temp, *vis; - long mask; - int n; - unsigned int default_depth; - int default_class; - - mask = VisualScreenMask | VisualDepthMask | VisualClassMask; - temp.screen = scr; - temp.depth = depth; - temp.CLASS = xclass; - - default_depth = DefaultDepth(dpy,scr); - default_class = DefaultVisual(dpy,scr)->CLASS; - - if (depth==default_depth && xclass==default_class) { - /* try to get root window's visual */ - temp.visualid = DefaultVisual(dpy,scr)->visualid; - mask |= VisualIDMask; - } - - vis = XGetVisualInfo( dpy, mask, &temp, &n ); - - /* In case bits/pixel > 24, make sure color channels are still <=8 bits. - * An SGI Infinite Reality system, for example, can have 30bpp pixels: - * 10 bits per color channel. Mesa's limited to a max of 8 bits/channel. - */ - if (vis && depth > 24 && (xclass==TrueColor || xclass==DirectColor)) { - if (util_bitcount((GLuint) vis->red_mask ) <= 8 && - util_bitcount((GLuint) vis->green_mask) <= 8 && - util_bitcount((GLuint) vis->blue_mask ) <= 8) { - return vis; - } - else { - free((void *) vis); - return NULL; - } - } - - return vis; -} - - -/* - * Retrieve the value of the given environment variable and find - * the X visual which matches it. - * Input: dpy - the display - * screen - the screen number - * varname - the name of the environment variable - * Return: an XVisualInfo pointer to NULL if error. - */ -static XVisualInfo * -get_env_visual(Display *dpy, int scr, const char *varname) -{ - char value[100], type[100]; - int depth, xclass = -1; - XVisualInfo *vis; - - if (!getenv( varname )) { - return NULL; - } - - strncpy( value, getenv(varname), 100 ); - value[99] = 0; - - sscanf( value, "%s %d", type, &depth ); - - if (strcmp(type,"TrueColor")==0) xclass = TrueColor; - else if (strcmp(type,"DirectColor")==0) xclass = DirectColor; - else if (strcmp(type,"PseudoColor")==0) xclass = PseudoColor; - else if (strcmp(type,"StaticColor")==0) xclass = StaticColor; - else if (strcmp(type,"GrayScale")==0) xclass = GrayScale; - else if (strcmp(type,"StaticGray")==0) xclass = StaticGray; - - if (xclass>-1 && depth>0) { - vis = get_visual( dpy, scr, depth, xclass ); - if (vis) { - return vis; - } - } - - _mesa_warning(NULL, "GLX unable to find visual class=%s, depth=%d.", - type, depth); - - return NULL; -} - - - -/* - * Select an X visual which satisfies the RGBA flag and minimum depth. - * Input: dpy, - * screen - X display and screen number - * min_depth - minimum visual depth - * preferred_class - preferred GLX visual class or DONT_CARE - * Return: pointer to an XVisualInfo or NULL. - */ -static XVisualInfo * -choose_x_visual( Display *dpy, int screen, int min_depth, - int preferred_class ) -{ - XVisualInfo *vis; - int xclass, visclass = 0; - int depth; - - /* First see if the MESA_RGB_VISUAL env var is defined */ - vis = get_env_visual( dpy, screen, "MESA_RGB_VISUAL" ); - if (vis) { - return vis; - } - /* Otherwise, search for a suitable visual */ - if (preferred_class==DONT_CARE) { - for (xclass=0;xclass<6;xclass++) { - switch (xclass) { - case 0: visclass = TrueColor; break; - case 1: visclass = DirectColor; break; - case 2: visclass = PseudoColor; break; - case 3: visclass = StaticColor; break; - case 4: visclass = GrayScale; break; - case 5: visclass = StaticGray; break; - } - if (min_depth==0) { - /* start with shallowest */ - for (depth=0;depth<=32;depth++) { - if (visclass==TrueColor && depth==8) { - /* Special case: try to get 8-bit PseudoColor before */ - /* 8-bit TrueColor */ - vis = get_visual( dpy, screen, 8, PseudoColor ); - if (vis) { - return vis; - } - } - vis = get_visual( dpy, screen, depth, visclass ); - if (vis) { - return vis; - } - } - } - else { - /* start with deepest */ - for (depth=32;depth>=min_depth;depth--) { - if (visclass==TrueColor && depth==8) { - /* Special case: try to get 8-bit PseudoColor before */ - /* 8-bit TrueColor */ - vis = get_visual( dpy, screen, 8, PseudoColor ); - if (vis) { - return vis; - } - } - vis = get_visual( dpy, screen, depth, visclass ); - if (vis) { - return vis; - } - } - } - } - } - else { - /* search for a specific visual class */ - switch (preferred_class) { - case GLX_TRUE_COLOR_EXT: visclass = TrueColor; break; - case GLX_DIRECT_COLOR_EXT: visclass = DirectColor; break; - case GLX_PSEUDO_COLOR_EXT: visclass = PseudoColor; break; - case GLX_STATIC_COLOR_EXT: visclass = StaticColor; break; - case GLX_GRAY_SCALE_EXT: visclass = GrayScale; break; - case GLX_STATIC_GRAY_EXT: visclass = StaticGray; break; - default: return NULL; - } - if (min_depth==0) { - /* start with shallowest */ - for (depth=0;depth<=32;depth++) { - vis = get_visual( dpy, screen, depth, visclass ); - if (vis) { - return vis; - } - } - } - else { - /* start with deepest */ - for (depth=32;depth>=min_depth;depth--) { - vis = get_visual( dpy, screen, depth, visclass ); - if (vis) { - return vis; - } - } - } - } - - /* didn't find a visual */ - return NULL; -} - - - - -/**********************************************************************/ -/*** Display-related functions ***/ -/**********************************************************************/ - - -/** - * Free all XMesaVisuals which are associated with the given display. - */ -static void -destroy_visuals_on_display(Display *dpy) -{ - int i; - for (i = 0; i < NumVisuals; i++) { - if (VisualTable[i]->display == dpy) { - /* remove this visual */ - int j; - free(VisualTable[i]); - for (j = i; j < NumVisuals - 1; j++) - VisualTable[j] = VisualTable[j + 1]; - NumVisuals--; - } - } -} - - -/** - * Called from XCloseDisplay() to let us free our display-related data. - */ -static int -close_display_callback(Display *dpy, XExtCodes *codes) -{ - xmesa_destroy_buffers_on_display(dpy); - destroy_visuals_on_display(dpy); - xmesa_close_display(dpy); - return 0; -} - - -/** - * Look for the named extension on given display and return a pointer - * to the _XExtension data, or NULL if extension not found. - */ -static _XExtension * -lookup_extension(Display *dpy, const char *extName) -{ - _XExtension *ext; - for (ext = dpy->ext_procs; ext; ext = ext->next) { - if (ext->name && strcmp(ext->name, extName) == 0) { - return ext; - } - } - return NULL; -} - - -/** - * Whenever we're given a new Display pointer, call this function to - * register our close_display_callback function. - */ -static void -register_with_display(Display *dpy) -{ - const char *extName = "MesaGLX"; - _XExtension *ext; - - ext = lookup_extension(dpy, extName); - if (!ext) { - XExtCodes *c = XAddExtension(dpy); - ext = dpy->ext_procs; /* new extension is at head of list */ - assert(c->extension == ext->codes.extension); - (void) c; - ext->name = strdup(extName); - ext->close_display = close_display_callback; - } -} - - -/** - * Fake an error. - */ -static int -generate_error(Display *dpy, - unsigned char error_code, - XID resourceid, - unsigned char minor_code, - Bool core) -{ - XErrorHandler handler; - int major_opcode; - int first_event; - int first_error; - XEvent event; - - handler = XSetErrorHandler(NULL); - XSetErrorHandler(handler); - if (!handler) { - return 0; - } - - if (!XQueryExtension(dpy, GLX_EXTENSION_NAME, &major_opcode, &first_event, &first_error)) { - major_opcode = 0; - first_event = 0; - first_error = 0; - } - - if (!core) { - error_code += first_error; - } - - memset(&event, 0, sizeof event); - - event.xerror.type = X_Error; - event.xerror.display = dpy; - event.xerror.resourceid = resourceid; - event.xerror.serial = NextRequest(dpy) - 1; - event.xerror.error_code = error_code; - event.xerror.request_code = major_opcode; - event.xerror.minor_code = minor_code; - - return handler(dpy, &event.xerror); -} - - -/**********************************************************************/ -/*** Begin Fake GLX API Functions ***/ -/**********************************************************************/ - - -/** - * Helper used by glXChooseVisual and glXChooseFBConfig. - * The fbConfig parameter must be GL_FALSE for the former and GL_TRUE for - * the later. - * In either case, the attribute list is terminated with the value 'None'. - */ -static XMesaVisual -choose_visual( Display *dpy, int screen, const int *list, GLboolean fbConfig ) -{ - const GLboolean rgbModeDefault = fbConfig; - const int *parselist; - XVisualInfo *vis; - int min_red=0, min_green=0, min_blue=0; - GLboolean rgb_flag = rgbModeDefault; - GLboolean alpha_flag = GL_FALSE; - GLboolean double_flag = GL_FALSE; - GLboolean stereo_flag = GL_FALSE; - GLint depth_size = 0; - GLint stencil_size = 0; - GLint accumRedSize = 0; - GLint accumGreenSize = 0; - GLint accumBlueSize = 0; - GLint accumAlphaSize = 0; - int level = 0; - int visual_type = DONT_CARE; - GLint caveat = DONT_CARE; - XMesaVisual xmvis = NULL; - int desiredVisualID = -1; - int numAux = 0; - GLint num_samples = 0; - - if (xmesa_init( dpy ) != 0) { - _mesa_warning(NULL, "Failed to initialize display"); - return NULL; - } - - parselist = list; - - while (*parselist) { - - if (fbConfig && - parselist[1] == GLX_DONT_CARE && - parselist[0] != GLX_LEVEL) { - /* For glXChooseFBConfig(), skip attributes whose value is - * GLX_DONT_CARE, unless it's GLX_LEVEL (which can legitimately be - * a negative value). - * - * From page 17 (23 of the pdf) of the GLX 1.4 spec: - * GLX DONT CARE may be specified for all attributes except GLX LEVEL. - */ - parselist += 2; - continue; - } - - switch (*parselist) { - case GLX_USE_GL: - if (fbConfig) { - /* invalid token */ - return NULL; - } - else { - /* skip */ - parselist++; - } - break; - case GLX_BUFFER_SIZE: - parselist++; - parselist++; - break; - case GLX_LEVEL: - parselist++; - level = *parselist++; - break; - case GLX_RGBA: - if (fbConfig) { - /* invalid token */ - return NULL; - } - else { - rgb_flag = GL_TRUE; - parselist++; - } - break; - case GLX_DOUBLEBUFFER: - parselist++; - if (fbConfig) { - double_flag = *parselist++; - } - else { - double_flag = GL_TRUE; - } - break; - case GLX_STEREO: - parselist++; - if (fbConfig) { - stereo_flag = *parselist++; - } - else { - stereo_flag = GL_TRUE; - } - break; - case GLX_AUX_BUFFERS: - parselist++; - numAux = *parselist++; - if (numAux > MAX_AUX_BUFFERS) - return NULL; - break; - case GLX_RED_SIZE: - parselist++; - min_red = *parselist++; - break; - case GLX_GREEN_SIZE: - parselist++; - min_green = *parselist++; - break; - case GLX_BLUE_SIZE: - parselist++; - min_blue = *parselist++; - break; - case GLX_ALPHA_SIZE: - parselist++; - { - GLint size = *parselist++; - alpha_flag = size ? GL_TRUE : GL_FALSE; - } - break; - case GLX_DEPTH_SIZE: - parselist++; - depth_size = *parselist++; - break; - case GLX_STENCIL_SIZE: - parselist++; - stencil_size = *parselist++; - break; - case GLX_ACCUM_RED_SIZE: - parselist++; - { - GLint size = *parselist++; - accumRedSize = MAX2( accumRedSize, size ); - } - break; - case GLX_ACCUM_GREEN_SIZE: - parselist++; - { - GLint size = *parselist++; - accumGreenSize = MAX2( accumGreenSize, size ); - } - break; - case GLX_ACCUM_BLUE_SIZE: - parselist++; - { - GLint size = *parselist++; - accumBlueSize = MAX2( accumBlueSize, size ); - } - break; - case GLX_ACCUM_ALPHA_SIZE: - parselist++; - { - GLint size = *parselist++; - accumAlphaSize = MAX2( accumAlphaSize, size ); - } - break; - - /* - * GLX_EXT_visual_info extension - */ - case GLX_X_VISUAL_TYPE_EXT: - parselist++; - visual_type = *parselist++; - break; - case GLX_TRANSPARENT_TYPE_EXT: - parselist++; - parselist++; - break; - case GLX_TRANSPARENT_INDEX_VALUE_EXT: - parselist++; - parselist++; - break; - case GLX_TRANSPARENT_RED_VALUE_EXT: - case GLX_TRANSPARENT_GREEN_VALUE_EXT: - case GLX_TRANSPARENT_BLUE_VALUE_EXT: - case GLX_TRANSPARENT_ALPHA_VALUE_EXT: - /* ignore */ - parselist++; - parselist++; - break; - - /* - * GLX_EXT_visual_info extension - */ - case GLX_VISUAL_CAVEAT_EXT: - parselist++; - caveat = *parselist++; /* ignored for now */ - break; - - /* - * GLX_ARB_multisample - */ - case GLX_SAMPLE_BUFFERS_ARB: - /* ignore */ - parselist++; - parselist++; - break; - case GLX_SAMPLES_ARB: - parselist++; - num_samples = *parselist++; - break; - - /* - * FBConfig attribs. - */ - case GLX_RENDER_TYPE: - if (!fbConfig) - return NULL; - parselist++; - if (*parselist & GLX_RGBA_BIT) { - rgb_flag = GL_TRUE; - } - else if (*parselist & GLX_COLOR_INDEX_BIT) { - rgb_flag = GL_FALSE; - } - else if (*parselist == 0) { - rgb_flag = GL_TRUE; - } - parselist++; - break; - case GLX_DRAWABLE_TYPE: - if (!fbConfig) - return NULL; - parselist++; - if (*parselist & ~(GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT)) { - return NULL; /* bad bit */ - } - parselist++; - break; - case GLX_FBCONFIG_ID: - case GLX_VISUAL_ID: - if (!fbConfig) - return NULL; - parselist++; - desiredVisualID = *parselist++; - break; - case GLX_X_RENDERABLE: - case GLX_MAX_PBUFFER_WIDTH: - case GLX_MAX_PBUFFER_HEIGHT: - case GLX_MAX_PBUFFER_PIXELS: - if (!fbConfig) - return NULL; /* invalid config option */ - parselist += 2; /* ignore the parameter */ - break; - - case GLX_BIND_TO_TEXTURE_RGB_EXT: - parselist++; /*skip*/ - break; - case GLX_BIND_TO_TEXTURE_RGBA_EXT: - parselist++; /*skip*/ - break; - case GLX_BIND_TO_MIPMAP_TEXTURE_EXT: - parselist++; /*skip*/ - break; - case GLX_BIND_TO_TEXTURE_TARGETS_EXT: - parselist++; - if (*parselist & ~(GLX_TEXTURE_1D_BIT_EXT | - GLX_TEXTURE_2D_BIT_EXT | - GLX_TEXTURE_RECTANGLE_BIT_EXT)) { - /* invalid bit */ - return NULL; - } - break; - case GLX_Y_INVERTED_EXT: - parselist++; /*skip*/ - break; - - case None: - /* end of list */ - break; - - default: - /* undefined attribute */ - _mesa_warning(NULL, "unexpected attrib 0x%x in choose_visual()", - *parselist); - return NULL; - } - } - - (void) caveat; - - if (num_samples < 0) { - _mesa_warning(NULL, "GLX_SAMPLES_ARB: number of samples must not be negative"); - return NULL; - } - - /* - * Since we're only simulating the GLX extension this function will never - * find any real GL visuals. Instead, all we can do is try to find an RGB - * or CI visual of appropriate depth. Other requested attributes such as - * double buffering, depth buffer, etc. will be associated with the X - * visual and stored in the VisualTable[]. - */ - if (desiredVisualID != -1) { - /* try to get a specific visual, by visualID */ - XVisualInfo temp; - int n; - temp.visualid = desiredVisualID; - temp.screen = screen; - vis = XGetVisualInfo(dpy, VisualIDMask | VisualScreenMask, &temp, &n); - if (vis) { - /* give the visual some useful GLX attributes */ - double_flag = GL_TRUE; - rgb_flag = GL_TRUE; - } - } - else if (level==0) { - /* normal color planes */ - /* Get an RGB visual */ - int min_rgb = min_red + min_green + min_blue; - if (min_rgb>1 && min_rgb<8) { - /* a special case to be sure we can get a monochrome visual */ - min_rgb = 1; - } - vis = choose_x_visual( dpy, screen, min_rgb, visual_type ); - } - else { - _mesa_warning(NULL, "overlay not supported"); - return NULL; - } - - if (vis) { - /* Note: we're not exactly obeying the glXChooseVisual rules here. - * When GLX_DEPTH_SIZE = 1 is specified we're supposed to choose the - * largest depth buffer size, which is 32bits/value. Instead, we - * return 16 to maintain performance with earlier versions of Mesa. - */ - if (stencil_size > 0) - depth_size = 24; /* if Z and stencil, always use 24+8 format */ - else if (depth_size > 24) - depth_size = 32; - else if (depth_size > 16) - depth_size = 24; - else if (depth_size > 0) { - depth_size = default_depth_bits(); - } - - if (!alpha_flag) { - alpha_flag = default_alpha_bits() > 0; - } - - /* we only support one size of stencil and accum buffers. */ - if (stencil_size > 0) - stencil_size = 8; - - if (accumRedSize > 0 || - accumGreenSize > 0 || - accumBlueSize > 0 || - accumAlphaSize > 0) { - - accumRedSize = - accumGreenSize = - accumBlueSize = default_accum_bits(); - - accumAlphaSize = alpha_flag ? accumRedSize : 0; - } - - xmvis = save_glx_visual( dpy, vis, rgb_flag, alpha_flag, double_flag, - stereo_flag, depth_size, stencil_size, - accumRedSize, accumGreenSize, - accumBlueSize, accumAlphaSize, level, numAux, - num_samples ); - } - - return xmvis; -} - - -PUBLIC XVisualInfo * -glXChooseVisual( Display *dpy, int screen, int *list ) -{ - XMesaVisual xmvis; - - /* register ourselves as an extension on this display */ - register_with_display(dpy); - - xmvis = choose_visual(dpy, screen, list, GL_FALSE); - if (xmvis) { - /* create a new vishandle - the cached one may be stale */ - xmvis->vishandle = malloc(sizeof(XVisualInfo)); - if (xmvis->vishandle) { - memcpy(xmvis->vishandle, xmvis->visinfo, sizeof(XVisualInfo)); - } - return xmvis->vishandle; - } - else - return NULL; -} - - -/** - * Helper function used by other glXCreateContext functions. - */ -static GLXContext -create_context(Display *dpy, XMesaVisual xmvis, - XMesaContext shareCtx, Bool direct, - unsigned major, unsigned minor, - unsigned profileMask, unsigned contextFlags) -{ - GLXContext glxCtx; - - if (!dpy || !xmvis) - return 0; - - glxCtx = CALLOC_STRUCT(__GLXcontextRec); - if (!glxCtx) - return 0; - - /* deallocate unused windows/buffers */ -#if 0 - XMesaGarbageCollect(); -#endif - - glxCtx->xmesaContext = XMesaCreateContext(xmvis, shareCtx, major, minor, - profileMask, contextFlags); - if (!glxCtx->xmesaContext) { - free(glxCtx); - return NULL; - } - - glxCtx->isDirect = DEFAULT_DIRECT; - glxCtx->currentDpy = dpy; - glxCtx->xid = (XID) glxCtx; /* self pointer */ - - return glxCtx; -} - - -PUBLIC GLXContext -glXCreateContext( Display *dpy, XVisualInfo *visinfo, - GLXContext shareCtx, Bool direct ) -{ - XMesaVisual xmvis; - - xmvis = find_glx_visual( dpy, visinfo ); - if (!xmvis) { - /* This visual wasn't found with glXChooseVisual() */ - xmvis = create_glx_visual( dpy, visinfo ); - if (!xmvis) { - /* unusable visual */ - return NULL; - } - } - - return create_context(dpy, xmvis, - shareCtx ? shareCtx->xmesaContext : NULL, - direct, - 1, 0, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, 0x0); -} - - -/* GLX 1.3 and later */ -PUBLIC Bool -glXMakeContextCurrent( Display *dpy, GLXDrawable draw, - GLXDrawable read, GLXContext ctx ) -{ - GLXContext glxCtx = ctx; - GLXContext current = GetCurrentContext(); - static boolean firsttime = 1, no_rast = 0; - - if (firsttime) { - no_rast = getenv("SP_NO_RAST") != NULL; - firsttime = 0; - } - - if (ctx) { - XMesaBuffer drawBuffer = NULL, readBuffer = NULL; - XMesaContext xmctx = glxCtx->xmesaContext; - - /* either both must be null, or both must be non-null */ - if (!draw != !read) - return False; - - if (draw) { - /* Find the XMesaBuffer which corresponds to 'draw' */ - drawBuffer = XMesaFindBuffer( dpy, draw ); - if (!drawBuffer) { - /* drawable must be a new window! */ - drawBuffer = XMesaCreateWindowBuffer( xmctx->xm_visual, draw ); - if (!drawBuffer) { - /* Out of memory, or context/drawable depth mismatch */ - return False; - } - } - } - - if (read) { - /* Find the XMesaBuffer which corresponds to 'read' */ - readBuffer = XMesaFindBuffer( dpy, read ); - if (!readBuffer) { - /* drawable must be a new window! */ - readBuffer = XMesaCreateWindowBuffer( xmctx->xm_visual, read ); - if (!readBuffer) { - /* Out of memory, or context/drawable depth mismatch */ - return False; - } - } - } - - if (no_rast && current == ctx) - return True; - - /* Now make current! */ - if (XMesaMakeCurrent2(xmctx, drawBuffer, readBuffer)) { - ctx->currentDpy = dpy; - ctx->currentDrawable = draw; - ctx->currentReadable = read; - SetCurrentContext(ctx); - return True; - } - else { - return False; - } - } - else if (!ctx && !draw && !read) { - /* release current context w/out assigning new one. */ - XMesaMakeCurrent2( NULL, NULL, NULL ); - SetCurrentContext(NULL); - return True; - } - else { - /* We were given an invalid set of arguments */ - return False; - } -} - - -PUBLIC Bool -glXMakeCurrent( Display *dpy, GLXDrawable drawable, GLXContext ctx ) -{ - return glXMakeContextCurrent( dpy, drawable, drawable, ctx ); -} - - -PUBLIC GLXContext -glXGetCurrentContext(void) -{ - return GetCurrentContext(); -} - - -PUBLIC Display * -glXGetCurrentDisplay(void) -{ - GLXContext glxCtx = glXGetCurrentContext(); - - return glxCtx ? glxCtx->currentDpy : NULL; -} - - -PUBLIC Display * -glXGetCurrentDisplayEXT(void) -{ - return glXGetCurrentDisplay(); -} - - -PUBLIC GLXDrawable -glXGetCurrentDrawable(void) -{ - GLXContext gc = glXGetCurrentContext(); - return gc ? gc->currentDrawable : 0; -} - - -PUBLIC GLXDrawable -glXGetCurrentReadDrawable(void) -{ - GLXContext gc = glXGetCurrentContext(); - return gc ? gc->currentReadable : 0; -} - - -PUBLIC GLXDrawable -glXGetCurrentReadDrawableSGI(void) -{ - return glXGetCurrentReadDrawable(); -} - - -PUBLIC GLXPixmap -glXCreateGLXPixmap( Display *dpy, XVisualInfo *visinfo, Pixmap pixmap ) -{ - XMesaVisual v; - XMesaBuffer b; - - v = find_glx_visual( dpy, visinfo ); - if (!v) { - v = create_glx_visual( dpy, visinfo ); - if (!v) { - /* unusable visual */ - return 0; - } - } - - b = XMesaCreatePixmapBuffer( v, pixmap, 0 ); - if (!b) { - return 0; - } - return b->ws.drawable; -} - - -/*** GLX_MESA_pixmap_colormap ***/ - -PUBLIC GLXPixmap -glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visinfo, - Pixmap pixmap, Colormap cmap ) -{ - XMesaVisual v; - XMesaBuffer b; - - v = find_glx_visual( dpy, visinfo ); - if (!v) { - v = create_glx_visual( dpy, visinfo ); - if (!v) { - /* unusable visual */ - return 0; - } - } - - b = XMesaCreatePixmapBuffer( v, pixmap, cmap ); - if (!b) { - return 0; - } - return b->ws.drawable; -} - - -PUBLIC void -glXDestroyGLXPixmap( Display *dpy, GLXPixmap pixmap ) -{ - XMesaBuffer b = XMesaFindBuffer(dpy, pixmap); - if (b) { - XMesaDestroyBuffer(b); - } - else if (getenv("MESA_DEBUG")) { - _mesa_warning(NULL, "Mesa: glXDestroyGLXPixmap: invalid pixmap\n"); - } -} - - -PUBLIC void -glXCopyContext( Display *dpy, GLXContext src, GLXContext dst, - unsigned long mask ) -{ - XMesaContext xm_src = src->xmesaContext; - XMesaContext xm_dst = dst->xmesaContext; - (void) dpy; - if (GetCurrentContext() == src) { - glFlush(); - } - XMesaCopyContext(xm_src, xm_dst, mask); -} - - -PUBLIC Bool -glXQueryExtension( Display *dpy, int *errorBase, int *eventBase ) -{ - int op, ev, err; - /* Mesa's GLX isn't really an X extension but we try to act like one. */ - if (!XQueryExtension(dpy, GLX_EXTENSION_NAME, &op, &ev, &err)) - ev = err = 0; - if (errorBase) - *errorBase = err; - if (eventBase) - *eventBase = ev; - return True; /* we're faking GLX so always return success */ -} - - -PUBLIC void -glXDestroyContext( Display *dpy, GLXContext ctx ) -{ - if (ctx) { - GLXContext glxCtx = ctx; - (void) dpy; - XMesaDestroyContext( glxCtx->xmesaContext ); - XMesaGarbageCollect(); - free(glxCtx); - } -} - - -PUBLIC Bool -glXIsDirect( Display *dpy, GLXContext ctx ) -{ - return ctx ? ctx->isDirect : False; -} - - - -PUBLIC void -glXSwapBuffers( Display *dpy, GLXDrawable drawable ) -{ - XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable ); - static boolean firsttime = 1, no_rast = 0; - - if (firsttime) { - no_rast = getenv("SP_NO_RAST") != NULL; - firsttime = 0; - } - - if (no_rast) - return; - - if (buffer) { - XMesaSwapBuffers(buffer); - } - else if (getenv("MESA_DEBUG")) { - _mesa_warning(NULL, "glXSwapBuffers: invalid drawable 0x%x\n", - (int) drawable); - } -} - - - -/*** GLX_MESA_copy_sub_buffer ***/ - -PUBLIC void -glXCopySubBufferMESA(Display *dpy, GLXDrawable drawable, - int x, int y, int width, int height) -{ - XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable ); - if (buffer) { - XMesaCopySubBuffer(buffer, x, y, width, height); - } - else if (getenv("MESA_DEBUG")) { - _mesa_warning(NULL, "Mesa: glXCopySubBufferMESA: invalid drawable\n"); - } -} - - -PUBLIC Bool -glXQueryVersion( Display *dpy, int *maj, int *min ) -{ - (void) dpy; - /* Return GLX version, not Mesa version */ - assert(CLIENT_MAJOR_VERSION == SERVER_MAJOR_VERSION); - *maj = CLIENT_MAJOR_VERSION; - *min = MIN2( CLIENT_MINOR_VERSION, SERVER_MINOR_VERSION ); - return True; -} - - -/* - * Query the GLX attributes of the given XVisualInfo. - */ -static int -get_config( XMesaVisual xmvis, int attrib, int *value, GLboolean fbconfig ) -{ - assert(xmvis); - switch(attrib) { - case GLX_USE_GL: - if (fbconfig) - return GLX_BAD_ATTRIBUTE; - *value = (int) True; - return 0; - case GLX_BUFFER_SIZE: - *value = xmvis->visinfo->depth; - return 0; - case GLX_LEVEL: - *value = xmvis->mesa_visual.level; - return 0; - case GLX_RGBA: - if (fbconfig) - return GLX_BAD_ATTRIBUTE; - *value = True; - return 0; - case GLX_DOUBLEBUFFER: - *value = (int) xmvis->mesa_visual.doubleBufferMode; - return 0; - case GLX_STEREO: - *value = (int) xmvis->mesa_visual.stereoMode; - return 0; - case GLX_AUX_BUFFERS: - *value = xmvis->mesa_visual.numAuxBuffers; - return 0; - case GLX_RED_SIZE: - *value = xmvis->mesa_visual.redBits; - return 0; - case GLX_GREEN_SIZE: - *value = xmvis->mesa_visual.greenBits; - return 0; - case GLX_BLUE_SIZE: - *value = xmvis->mesa_visual.blueBits; - return 0; - case GLX_ALPHA_SIZE: - *value = xmvis->mesa_visual.alphaBits; - return 0; - case GLX_DEPTH_SIZE: - *value = xmvis->mesa_visual.depthBits; - return 0; - case GLX_STENCIL_SIZE: - *value = xmvis->mesa_visual.stencilBits; - return 0; - case GLX_ACCUM_RED_SIZE: - *value = xmvis->mesa_visual.accumRedBits; - return 0; - case GLX_ACCUM_GREEN_SIZE: - *value = xmvis->mesa_visual.accumGreenBits; - return 0; - case GLX_ACCUM_BLUE_SIZE: - *value = xmvis->mesa_visual.accumBlueBits; - return 0; - case GLX_ACCUM_ALPHA_SIZE: - *value = xmvis->mesa_visual.accumAlphaBits; - return 0; - - /* - * GLX_EXT_visual_info extension - */ - case GLX_X_VISUAL_TYPE_EXT: - switch (xmvis->visinfo->CLASS) { - case StaticGray: *value = GLX_STATIC_GRAY_EXT; return 0; - case GrayScale: *value = GLX_GRAY_SCALE_EXT; return 0; - case StaticColor: *value = GLX_STATIC_GRAY_EXT; return 0; - case PseudoColor: *value = GLX_PSEUDO_COLOR_EXT; return 0; - case TrueColor: *value = GLX_TRUE_COLOR_EXT; return 0; - case DirectColor: *value = GLX_DIRECT_COLOR_EXT; return 0; - } - return 0; - case GLX_TRANSPARENT_TYPE_EXT: - /* normal planes */ - *value = GLX_NONE_EXT; - return 0; - case GLX_TRANSPARENT_INDEX_VALUE_EXT: - /* undefined */ - return 0; - case GLX_TRANSPARENT_RED_VALUE_EXT: - /* undefined */ - return 0; - case GLX_TRANSPARENT_GREEN_VALUE_EXT: - /* undefined */ - return 0; - case GLX_TRANSPARENT_BLUE_VALUE_EXT: - /* undefined */ - return 0; - case GLX_TRANSPARENT_ALPHA_VALUE_EXT: - /* undefined */ - return 0; - - /* - * GLX_EXT_visual_info extension - */ - case GLX_VISUAL_CAVEAT_EXT: - /* test for zero, just in case */ - if (xmvis->mesa_visual.visualRating > 0) - *value = xmvis->mesa_visual.visualRating; - else - *value = GLX_NONE_EXT; - return 0; - - /* - * GLX_ARB_multisample - */ - case GLX_SAMPLE_BUFFERS_ARB: - *value = xmvis->mesa_visual.sampleBuffers; - return 0; - case GLX_SAMPLES_ARB: - *value = xmvis->mesa_visual.samples; - return 0; - - /* - * For FBConfigs: - */ - case GLX_SCREEN_EXT: - if (!fbconfig) - return GLX_BAD_ATTRIBUTE; - *value = xmvis->visinfo->screen; - break; - case GLX_DRAWABLE_TYPE: /*SGIX too */ - if (!fbconfig) - return GLX_BAD_ATTRIBUTE; - *value = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT; - break; - case GLX_RENDER_TYPE_SGIX: - if (!fbconfig) - return GLX_BAD_ATTRIBUTE; - *value = GLX_RGBA_BIT; - break; - case GLX_X_RENDERABLE_SGIX: - if (!fbconfig) - return GLX_BAD_ATTRIBUTE; - *value = True; /* XXX really? */ - break; - case GLX_FBCONFIG_ID_SGIX: - if (!fbconfig) - return GLX_BAD_ATTRIBUTE; - *value = xmvis->visinfo->visualid; - break; - case GLX_MAX_PBUFFER_WIDTH: - if (!fbconfig) - return GLX_BAD_ATTRIBUTE; - /* XXX should be same as ctx->Const.MaxRenderbufferSize */ - *value = DisplayWidth(xmvis->display, xmvis->visinfo->screen); - break; - case GLX_MAX_PBUFFER_HEIGHT: - if (!fbconfig) - return GLX_BAD_ATTRIBUTE; - *value = DisplayHeight(xmvis->display, xmvis->visinfo->screen); - break; - case GLX_MAX_PBUFFER_PIXELS: - if (!fbconfig) - return GLX_BAD_ATTRIBUTE; - *value = DisplayWidth(xmvis->display, xmvis->visinfo->screen) * - DisplayHeight(xmvis->display, xmvis->visinfo->screen); - break; - case GLX_VISUAL_ID: - if (!fbconfig) - return GLX_BAD_ATTRIBUTE; - *value = xmvis->visinfo->visualid; - break; - - case GLX_BIND_TO_TEXTURE_RGB_EXT: - *value = True; /*XXX*/ - break; - case GLX_BIND_TO_TEXTURE_RGBA_EXT: - /* XXX review */ - *value = xmvis->mesa_visual.alphaBits > 0 ? True : False; - break; - case GLX_BIND_TO_MIPMAP_TEXTURE_EXT: - *value = True; /*XXX*/ - break; - case GLX_BIND_TO_TEXTURE_TARGETS_EXT: - *value = (GLX_TEXTURE_1D_BIT_EXT | - GLX_TEXTURE_2D_BIT_EXT | - GLX_TEXTURE_RECTANGLE_BIT_EXT); /*XXX*/ - break; - case GLX_Y_INVERTED_EXT: - *value = True; /*XXX*/ - break; - - default: - return GLX_BAD_ATTRIBUTE; - } - return Success; -} - - -PUBLIC int -glXGetConfig( Display *dpy, XVisualInfo *visinfo, - int attrib, int *value ) -{ - XMesaVisual xmvis; - int k; - if (!dpy || !visinfo) - return GLX_BAD_ATTRIBUTE; - - xmvis = find_glx_visual( dpy, visinfo ); - if (!xmvis) { - /* this visual wasn't obtained with glXChooseVisual */ - xmvis = create_glx_visual( dpy, visinfo ); - if (!xmvis) { - /* this visual can't be used for GL rendering */ - if (attrib==GLX_USE_GL) { - *value = (int) False; - return 0; - } - else { - return GLX_BAD_VISUAL; - } - } - } - - k = get_config(xmvis, attrib, value, GL_FALSE); - return k; -} - - -PUBLIC void -glXWaitGL( void ) -{ - XMesaContext xmesa = XMesaGetCurrentContext(); - XMesaFlush( xmesa ); -} - - - -PUBLIC void -glXWaitX( void ) -{ - XMesaContext xmesa = XMesaGetCurrentContext(); - XMesaFlush( xmesa ); -} - - -static const char * -get_extensions( void ) -{ - return EXTENSIONS; -} - - - -/* GLX 1.1 and later */ -PUBLIC const char * -glXQueryExtensionsString( Display *dpy, int screen ) -{ - (void) dpy; - (void) screen; - return get_extensions(); -} - - - -/* GLX 1.1 and later */ -PUBLIC const char * -glXQueryServerString( Display *dpy, int screen, int name ) -{ - static char version[1000]; - sprintf(version, "%d.%d %s", - SERVER_MAJOR_VERSION, SERVER_MINOR_VERSION, xmesa_get_name()); - - (void) dpy; - (void) screen; - - switch (name) { - case GLX_EXTENSIONS: - return get_extensions(); - case GLX_VENDOR: - return VENDOR; - case GLX_VERSION: - return version; - default: - return NULL; - } -} - - - -/* GLX 1.1 and later */ -PUBLIC const char * -glXGetClientString( Display *dpy, int name ) -{ - static char version[1000]; - sprintf(version, "%d.%d %s", CLIENT_MAJOR_VERSION, - CLIENT_MINOR_VERSION, xmesa_get_name()); - - (void) dpy; - - switch (name) { - case GLX_EXTENSIONS: - return get_extensions(); - case GLX_VENDOR: - return VENDOR; - case GLX_VERSION: - return version; - default: - return NULL; - } -} - - - -/* - * GLX 1.3 and later - */ - - -PUBLIC int -glXGetFBConfigAttrib(Display *dpy, GLXFBConfig config, - int attribute, int *value) -{ - XMesaVisual v = (XMesaVisual) config; - (void) dpy; - (void) config; - - if (!dpy || !config || !value) - return -1; - - return get_config(v, attribute, value, GL_TRUE); -} - - -PUBLIC GLXFBConfig * -glXGetFBConfigs( Display *dpy, int screen, int *nelements ) -{ - XVisualInfo *visuals, visTemplate; - const long visMask = VisualScreenMask; - int i; - - /* Get list of all X visuals */ - visTemplate.screen = screen; - visuals = XGetVisualInfo(dpy, visMask, &visTemplate, nelements); - if (*nelements > 0) { - XMesaVisual *results = malloc(*nelements * sizeof(XMesaVisual)); - if (!results) { - *nelements = 0; - return NULL; - } - for (i = 0; i < *nelements; i++) { - results[i] = create_glx_visual(dpy, visuals + i); - if (!results[i]) { - *nelements = i; - break; - } - } - return (GLXFBConfig *) results; - } - return NULL; -} - - -PUBLIC GLXFBConfig * -glXChooseFBConfig(Display *dpy, int screen, - const int *attribList, int *nitems) -{ - XMesaVisual xmvis; - - /* register ourselves as an extension on this display */ - register_with_display(dpy); - - if (!attribList || !attribList[0]) { - /* return list of all configs (per GLX_SGIX_fbconfig spec) */ - return glXGetFBConfigs(dpy, screen, nitems); - } - - xmvis = choose_visual(dpy, screen, attribList, GL_TRUE); - if (xmvis) { - GLXFBConfig *config = malloc(sizeof(XMesaVisual)); - if (!config) { - *nitems = 0; - return NULL; - } - *nitems = 1; - config[0] = (GLXFBConfig) xmvis; - return (GLXFBConfig *) config; - } - else { - *nitems = 0; - return NULL; - } -} - - -PUBLIC XVisualInfo * -glXGetVisualFromFBConfig( Display *dpy, GLXFBConfig config ) -{ - if (dpy && config) { - XMesaVisual xmvis = (XMesaVisual) config; -#if 0 - return xmvis->vishandle; -#else - /* create a new vishandle - the cached one may be stale */ - xmvis->vishandle = malloc(sizeof(XVisualInfo)); - if (xmvis->vishandle) { - memcpy(xmvis->vishandle, xmvis->visinfo, sizeof(XVisualInfo)); - } - return xmvis->vishandle; -#endif - } - else { - return NULL; - } -} - - -PUBLIC GLXWindow -glXCreateWindow(Display *dpy, GLXFBConfig config, Window win, - const int *attribList) -{ - XMesaVisual xmvis = (XMesaVisual) config; - XMesaBuffer xmbuf; - if (!xmvis) - return 0; - - xmbuf = XMesaCreateWindowBuffer(xmvis, win); - if (!xmbuf) - return 0; - - (void) dpy; - (void) attribList; /* Ignored in GLX 1.3 */ - - return win; /* A hack for now */ -} - - -PUBLIC void -glXDestroyWindow( Display *dpy, GLXWindow window ) -{ - XMesaBuffer b = XMesaFindBuffer(dpy, (Drawable) window); - if (b) - XMesaDestroyBuffer(b); - /* don't destroy X window */ -} - - -/* XXX untested */ -PUBLIC GLXPixmap -glXCreatePixmap(Display *dpy, GLXFBConfig config, Pixmap pixmap, - const int *attribList) -{ - XMesaVisual v = (XMesaVisual) config; - XMesaBuffer b; - const int *attr; - int target = 0, format = 0, mipmap = 0; - int value; - - if (!dpy || !config || !pixmap) - return 0; - - for (attr = attribList; attr && *attr; attr++) { - switch (*attr) { - case GLX_TEXTURE_FORMAT_EXT: - attr++; - switch (*attr) { - case GLX_TEXTURE_FORMAT_NONE_EXT: - case GLX_TEXTURE_FORMAT_RGB_EXT: - case GLX_TEXTURE_FORMAT_RGBA_EXT: - format = *attr; - break; - default: - /* error */ - return 0; - } - break; - case GLX_TEXTURE_TARGET_EXT: - attr++; - switch (*attr) { - case GLX_TEXTURE_1D_EXT: - case GLX_TEXTURE_2D_EXT: - case GLX_TEXTURE_RECTANGLE_EXT: - target = *attr; - break; - default: - /* error */ - return 0; - } - break; - case GLX_MIPMAP_TEXTURE_EXT: - attr++; - if (*attr) - mipmap = 1; - break; - default: - /* error */ - return 0; - } - } - - if (format == GLX_TEXTURE_FORMAT_RGB_EXT) { - if (get_config(v, GLX_BIND_TO_TEXTURE_RGB_EXT, - &value, GL_TRUE) != Success - || !value) { - return 0; /* error! */ - } - } - else if (format == GLX_TEXTURE_FORMAT_RGBA_EXT) { - if (get_config(v, GLX_BIND_TO_TEXTURE_RGBA_EXT, - &value, GL_TRUE) != Success - || !value) { - return 0; /* error! */ - } - } - if (mipmap) { - if (get_config(v, GLX_BIND_TO_MIPMAP_TEXTURE_EXT, - &value, GL_TRUE) != Success - || !value) { - return 0; /* error! */ - } - } - if (target == GLX_TEXTURE_1D_EXT) { - if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT, - &value, GL_TRUE) != Success - || (value & GLX_TEXTURE_1D_BIT_EXT) == 0) { - return 0; /* error! */ - } - } - else if (target == GLX_TEXTURE_2D_EXT) { - if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT, - &value, GL_TRUE) != Success - || (value & GLX_TEXTURE_2D_BIT_EXT) == 0) { - return 0; /* error! */ - } - } - if (target == GLX_TEXTURE_RECTANGLE_EXT) { - if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT, - &value, GL_TRUE) != Success - || (value & GLX_TEXTURE_RECTANGLE_BIT_EXT) == 0) { - return 0; /* error! */ - } - } - - if (format || target || mipmap) { - /* texture from pixmap */ - b = XMesaCreatePixmapTextureBuffer(v, pixmap, 0, format, target, mipmap); - } - else { - b = XMesaCreatePixmapBuffer( v, pixmap, 0 ); - } - if (!b) { - return 0; - } - - return pixmap; -} - - -PUBLIC void -glXDestroyPixmap( Display *dpy, GLXPixmap pixmap ) -{ - XMesaBuffer b = XMesaFindBuffer(dpy, (Drawable)pixmap); - if (b) - XMesaDestroyBuffer(b); - /* don't destroy X pixmap */ -} - - -PUBLIC GLXPbuffer -glXCreatePbuffer(Display *dpy, GLXFBConfig config, const int *attribList) -{ - XMesaVisual xmvis = (XMesaVisual) config; - XMesaBuffer xmbuf; - const int *attrib; - int width = 0, height = 0; - GLboolean useLargest = GL_FALSE, preserveContents = GL_FALSE; - - (void) dpy; - - for (attrib = attribList; *attrib; attrib++) { - switch (*attrib) { - case GLX_PBUFFER_WIDTH: - attrib++; - width = *attrib; - break; - case GLX_PBUFFER_HEIGHT: - attrib++; - height = *attrib; - break; - case GLX_PRESERVED_CONTENTS: - attrib++; - preserveContents = *attrib; - break; - case GLX_LARGEST_PBUFFER: - attrib++; - useLargest = *attrib; - break; - default: - return 0; - } - } - - if (width == 0 || height == 0) - return 0; - - if (width > PBUFFER_MAX_SIZE || height > PBUFFER_MAX_SIZE) { - /* If allocation would have failed and GLX_LARGEST_PBUFFER is set, - * allocate the largest possible buffer. - */ - if (useLargest) { - width = PBUFFER_MAX_SIZE; - height = PBUFFER_MAX_SIZE; - } - } - - xmbuf = XMesaCreatePBuffer( xmvis, 0, width, height); - /* A GLXPbuffer handle must be an X Drawable because that's what - * glXMakeCurrent takes. - */ - if (xmbuf) { - xmbuf->largestPbuffer = useLargest; - xmbuf->preservedContents = preserveContents; - return (GLXPbuffer) xmbuf->ws.drawable; - } - else { - return 0; - } -} - - -PUBLIC void -glXDestroyPbuffer( Display *dpy, GLXPbuffer pbuf ) -{ - XMesaBuffer b = XMesaFindBuffer(dpy, pbuf); - if (b) { - XMesaDestroyBuffer(b); - } -} - - -PUBLIC void -glXQueryDrawable(Display *dpy, GLXDrawable draw, int attribute, - unsigned int *value) -{ - GLuint width, height; - XMesaBuffer xmbuf = XMesaFindBuffer(dpy, draw); - if (!xmbuf) { - generate_error(dpy, GLXBadDrawable, draw, X_GLXGetDrawableAttributes, False); - return; - } - - /* make sure buffer's dimensions are up to date */ - xmesa_get_window_size(dpy, xmbuf, &width, &height); - - switch (attribute) { - case GLX_WIDTH: - *value = width; - break; - case GLX_HEIGHT: - *value = height; - break; - case GLX_PRESERVED_CONTENTS: - *value = xmbuf->preservedContents; - break; - case GLX_LARGEST_PBUFFER: - *value = xmbuf->largestPbuffer; - break; - case GLX_FBCONFIG_ID: - *value = xmbuf->xm_visual->visinfo->visualid; - return; - case GLX_TEXTURE_FORMAT_EXT: - *value = xmbuf->TextureFormat; - break; - case GLX_TEXTURE_TARGET_EXT: - *value = xmbuf->TextureTarget; - break; - case GLX_MIPMAP_TEXTURE_EXT: - *value = xmbuf->TextureMipmap; - break; - - default: - generate_error(dpy, BadValue, 0, X_GLXCreateContextAttribsARB, true); - return; - } -} - - -PUBLIC GLXContext -glXCreateNewContext( Display *dpy, GLXFBConfig config, - int renderType, GLXContext shareCtx, Bool direct ) -{ - XMesaVisual xmvis = (XMesaVisual) config; - - if (!dpy || !config || - (renderType != GLX_RGBA_TYPE && renderType != GLX_COLOR_INDEX_TYPE)) - return 0; - - return create_context(dpy, xmvis, - shareCtx ? shareCtx->xmesaContext : NULL, - direct, - 1, 0, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, 0x0); -} - - -PUBLIC int -glXQueryContext( Display *dpy, GLXContext ctx, int attribute, int *value ) -{ - GLXContext glxCtx = ctx; - XMesaContext xmctx = glxCtx->xmesaContext; - - (void) dpy; - (void) ctx; - - switch (attribute) { - case GLX_FBCONFIG_ID: - *value = xmctx->xm_visual->visinfo->visualid; - break; - case GLX_RENDER_TYPE: - *value = GLX_RGBA_TYPE; - break; - case GLX_SCREEN: - *value = 0; - return Success; - default: - return GLX_BAD_ATTRIBUTE; - } - return 0; -} - - -PUBLIC void -glXSelectEvent( Display *dpy, GLXDrawable drawable, unsigned long mask ) -{ - XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable); - if (xmbuf) - xmbuf->selectedEvents = mask; -} - - -PUBLIC void -glXGetSelectedEvent(Display *dpy, GLXDrawable drawable, unsigned long *mask) -{ - XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable); - if (xmbuf) - *mask = xmbuf->selectedEvents; - else - *mask = 0; -} - - - -/*** GLX_SGI_swap_control ***/ - -PUBLIC int -glXSwapIntervalSGI(int interval) -{ - (void) interval; - return 0; -} - - - -/*** GLX_SGI_video_sync ***/ - -static unsigned int FrameCounter = 0; - -PUBLIC int -glXGetVideoSyncSGI(unsigned int *count) -{ - /* this is a bogus implementation */ - *count = FrameCounter++; - return 0; -} - -PUBLIC int -glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count) -{ - if (divisor <= 0 || remainder < 0) - return GLX_BAD_VALUE; - /* this is a bogus implementation */ - FrameCounter++; - while (FrameCounter % divisor != remainder) - FrameCounter++; - *count = FrameCounter; - return 0; -} - - - -/*** GLX_SGI_make_current_read ***/ - -PUBLIC Bool -glXMakeCurrentReadSGI(Display *dpy, GLXDrawable draw, GLXDrawable read, - GLXContext ctx) -{ - return glXMakeContextCurrent( dpy, draw, read, ctx ); -} - -/* not used -static GLXDrawable -glXGetCurrentReadDrawableSGI(void) -{ - return 0; -} -*/ - - -/*** GLX_SGIX_video_source ***/ -#if defined(_VL_H) - -PUBLIC GLXVideoSourceSGIX -glXCreateGLXVideoSourceSGIX(Display *dpy, int screen, VLServer server, - VLPath path, int nodeClass, VLNode drainNode) -{ - (void) dpy; - (void) screen; - (void) server; - (void) path; - (void) nodeClass; - (void) drainNode; - return 0; -} - -PUBLIC void -glXDestroyGLXVideoSourceSGIX(Display *dpy, GLXVideoSourceSGIX src) -{ - (void) dpy; - (void) src; -} - -#endif - - -/*** GLX_EXT_import_context ***/ - -PUBLIC void -glXFreeContextEXT(Display *dpy, GLXContext context) -{ - (void) dpy; - (void) context; -} - -PUBLIC GLXContextID -glXGetContextIDEXT(const GLXContext context) -{ - (void) context; - return 0; -} - -PUBLIC GLXContext -glXImportContextEXT(Display *dpy, GLXContextID contextID) -{ - (void) dpy; - (void) contextID; - return 0; -} - -PUBLIC int -glXQueryContextInfoEXT(Display *dpy, GLXContext context, int attribute, - int *value) -{ - (void) dpy; - (void) context; - (void) attribute; - (void) value; - return 0; -} - - - -/*** GLX_SGIX_fbconfig ***/ - -PUBLIC int -glXGetFBConfigAttribSGIX(Display *dpy, GLXFBConfigSGIX config, - int attribute, int *value) -{ - return glXGetFBConfigAttrib(dpy, config, attribute, value); -} - -PUBLIC GLXFBConfigSGIX * -glXChooseFBConfigSGIX(Display *dpy, int screen, int *attrib_list, - int *nelements) -{ - return (GLXFBConfig *) glXChooseFBConfig(dpy, screen, - attrib_list, nelements); -} - - -PUBLIC GLXPixmap -glXCreateGLXPixmapWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, - Pixmap pixmap) -{ - XMesaVisual xmvis = (XMesaVisual) config; - XMesaBuffer xmbuf = XMesaCreatePixmapBuffer(xmvis, pixmap, 0); - return xmbuf->ws.drawable; /* need to return an X ID */ -} - - -PUBLIC GLXContext -glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, - int renderType, GLXContext shareCtx, - Bool direct) -{ - XMesaVisual xmvis = (XMesaVisual) config; - - if (!dpy || !config || - (renderType != GLX_RGBA_TYPE && renderType != GLX_COLOR_INDEX_TYPE)) - return 0; - - return create_context(dpy, xmvis, - shareCtx ? shareCtx->xmesaContext : NULL, - direct, - 1, 0, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, 0x0); -} - - -PUBLIC XVisualInfo * -glXGetVisualFromFBConfigSGIX(Display *dpy, GLXFBConfigSGIX config) -{ - return glXGetVisualFromFBConfig(dpy, config); -} - - -PUBLIC GLXFBConfigSGIX -glXGetFBConfigFromVisualSGIX(Display *dpy, XVisualInfo *vis) -{ - XMesaVisual xmvis = find_glx_visual(dpy, vis); - if (!xmvis) { - /* This visual wasn't found with glXChooseVisual() */ - xmvis = create_glx_visual(dpy, vis); - } - - return (GLXFBConfigSGIX) xmvis; -} - - - -/*** GLX_SGIX_pbuffer ***/ - -PUBLIC GLXPbufferSGIX -glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfigSGIX config, - unsigned int width, unsigned int height, - int *attribList) -{ - XMesaVisual xmvis = (XMesaVisual) config; - XMesaBuffer xmbuf; - const int *attrib; - GLboolean useLargest = GL_FALSE, preserveContents = GL_FALSE; - - (void) dpy; - - for (attrib = attribList; attrib && *attrib; attrib++) { - switch (*attrib) { - case GLX_PRESERVED_CONTENTS_SGIX: - attrib++; - preserveContents = *attrib; /* ignored */ - break; - case GLX_LARGEST_PBUFFER_SGIX: - attrib++; - useLargest = *attrib; /* ignored */ - break; - default: - return 0; - } - } - - /* not used at this time */ - (void) useLargest; - (void) preserveContents; - - xmbuf = XMesaCreatePBuffer( xmvis, 0, width, height); - /* A GLXPbuffer handle must be an X Drawable because that's what - * glXMakeCurrent takes. - */ - return (GLXPbuffer) xmbuf->ws.drawable; -} - - -PUBLIC void -glXDestroyGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf) -{ - XMesaBuffer xmbuf = XMesaFindBuffer(dpy, pbuf); - if (xmbuf) { - XMesaDestroyBuffer(xmbuf); - } -} - - -PUBLIC void -glXQueryGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf, int attribute, - unsigned int *value) -{ - const XMesaBuffer xmbuf = XMesaFindBuffer(dpy, pbuf); - - if (!xmbuf) { - /* Generate GLXBadPbufferSGIX for bad pbuffer */ - return; - } - - switch (attribute) { - case GLX_PRESERVED_CONTENTS_SGIX: - *value = True; - break; - case GLX_LARGEST_PBUFFER_SGIX: - *value = xmesa_buffer_width(xmbuf) * xmesa_buffer_height(xmbuf); - break; - case GLX_WIDTH_SGIX: - *value = xmesa_buffer_width(xmbuf); - break; - case GLX_HEIGHT_SGIX: - *value = xmesa_buffer_height(xmbuf); - break; - case GLX_EVENT_MASK_SGIX: - *value = 0; /* XXX might be wrong */ - break; - default: - *value = 0; - } -} - - -PUBLIC void -glXSelectEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long mask) -{ - XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable); - if (xmbuf) { - /* Note: we'll never generate clobber events */ - xmbuf->selectedEvents = mask; - } -} - - -PUBLIC void -glXGetSelectedEventSGIX(Display *dpy, GLXDrawable drawable, - unsigned long *mask) -{ - XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable); - if (xmbuf) { - *mask = xmbuf->selectedEvents; - } - else { - *mask = 0; - } -} - - - -/*** GLX_SGI_cushion ***/ - -PUBLIC void -glXCushionSGI(Display *dpy, Window win, float cushion) -{ - (void) dpy; - (void) win; - (void) cushion; -} - - - -/*** GLX_SGIX_video_resize ***/ - -PUBLIC int -glXBindChannelToWindowSGIX(Display *dpy, int screen, int channel, - Window window) -{ - (void) dpy; - (void) screen; - (void) channel; - (void) window; - return 0; -} - -PUBLIC int -glXChannelRectSGIX(Display *dpy, int screen, int channel, - int x, int y, int w, int h) -{ - (void) dpy; - (void) screen; - (void) channel; - (void) x; - (void) y; - (void) w; - (void) h; - return 0; -} - -PUBLIC int -glXQueryChannelRectSGIX(Display *dpy, int screen, int channel, - int *x, int *y, int *w, int *h) -{ - (void) dpy; - (void) screen; - (void) channel; - (void) x; - (void) y; - (void) w; - (void) h; - return 0; -} - -PUBLIC int -glXQueryChannelDeltasSGIX(Display *dpy, int screen, int channel, - int *dx, int *dy, int *dw, int *dh) -{ - (void) dpy; - (void) screen; - (void) channel; - (void) dx; - (void) dy; - (void) dw; - (void) dh; - return 0; -} - -PUBLIC int -glXChannelRectSyncSGIX(Display *dpy, int screen, int channel, GLenum synctype) -{ - (void) dpy; - (void) screen; - (void) channel; - (void) synctype; - return 0; -} - - - -/*** GLX_SGIX_dmbuffer **/ - -#if defined(_DM_BUFFER_H_) -PUBLIC Bool -glXAssociateDMPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuffer, - DMparams *params, DMbuffer dmbuffer) -{ - (void) dpy; - (void) pbuffer; - (void) params; - (void) dmbuffer; - return False; -} -#endif - - -/*** GLX_SUN_get_transparent_index ***/ - -PUBLIC Status -glXGetTransparentIndexSUN(Display *dpy, Window overlay, Window underlay, - unsigned long *pTransparent) -{ - (void) dpy; - (void) overlay; - (void) underlay; - (void) pTransparent; - return 0; -} - - - -/*** GLX_MESA_release_buffers ***/ - -/* - * Release the depth, stencil, accum buffers attached to a GLXDrawable - * (a window or pixmap) prior to destroying the GLXDrawable. - */ -PUBLIC Bool -glXReleaseBuffersMESA( Display *dpy, GLXDrawable d ) -{ - XMesaBuffer b = XMesaFindBuffer(dpy, d); - if (b) { - XMesaDestroyBuffer(b); - return True; - } - return False; -} - -/*** GLX_EXT_texture_from_pixmap ***/ - -PUBLIC void -glXBindTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer, - const int *attrib_list) -{ - XMesaBuffer b = XMesaFindBuffer(dpy, drawable); - if (b) - XMesaBindTexImage(dpy, b, buffer, attrib_list); -} - -PUBLIC void -glXReleaseTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer) -{ - XMesaBuffer b = XMesaFindBuffer(dpy, drawable); - if (b) - XMesaReleaseTexImage(dpy, b, buffer); -} - - - -/*** GLX_ARB_create_context ***/ - - -GLXContext -glXCreateContextAttribsARB(Display *dpy, GLXFBConfig config, - GLXContext shareCtx, Bool direct, - const int *attrib_list) -{ - XMesaVisual xmvis = (XMesaVisual) config; - int majorVersion = 1, minorVersion = 0; - int contextFlags = 0x0; - int profileMask = GLX_CONTEXT_CORE_PROFILE_BIT_ARB; - int renderType = GLX_RGBA_TYPE; - unsigned i; - Bool done = False; - const int contextFlagsAll = (GLX_CONTEXT_DEBUG_BIT_ARB | - GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB); - GLXContext ctx; - - /* parse attrib_list */ - for (i = 0; !done && attrib_list && attrib_list[i]; i++) { - switch (attrib_list[i]) { - case GLX_CONTEXT_MAJOR_VERSION_ARB: - majorVersion = attrib_list[++i]; - break; - case GLX_CONTEXT_MINOR_VERSION_ARB: - minorVersion = attrib_list[++i]; - break; - case GLX_CONTEXT_FLAGS_ARB: - contextFlags = attrib_list[++i]; - break; - case GLX_CONTEXT_PROFILE_MASK_ARB: - profileMask = attrib_list[++i]; - break; - case GLX_RENDER_TYPE: - renderType = attrib_list[++i]; - break; - case 0: - /* end of list */ - done = True; - break; - default: - /* bad attribute */ - generate_error(dpy, BadValue, 0, X_GLXCreateContextAttribsARB, True); - return NULL; - } - } - - /* check contextFlags */ - if (contextFlags & ~contextFlagsAll) { - generate_error(dpy, BadValue, 0, X_GLXCreateContextAttribsARB, True); - return NULL; - } - - /* check profileMask */ - if (profileMask != GLX_CONTEXT_CORE_PROFILE_BIT_ARB && - profileMask != GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB && - profileMask != GLX_CONTEXT_ES_PROFILE_BIT_EXT) { - generate_error(dpy, GLXBadProfileARB, 0, X_GLXCreateContextAttribsARB, False); - return NULL; - } - - /* check renderType */ - if (renderType != GLX_RGBA_TYPE && - renderType != GLX_COLOR_INDEX_TYPE) { - generate_error(dpy, BadValue, 0, X_GLXCreateContextAttribsARB, True); - return NULL; - } - - /* check version */ - if (majorVersion <= 0 || - minorVersion < 0 || - (profileMask != GLX_CONTEXT_ES_PROFILE_BIT_EXT && - ((majorVersion == 1 && minorVersion > 5) || - (majorVersion == 2 && minorVersion > 1) || - (majorVersion == 3 && minorVersion > 3) || - (majorVersion == 4 && minorVersion > 5) || - majorVersion > 4))) { - generate_error(dpy, BadMatch, 0, X_GLXCreateContextAttribsARB, True); - return NULL; - } - if (profileMask == GLX_CONTEXT_ES_PROFILE_BIT_EXT && - ((majorVersion == 1 && minorVersion > 1) || - (majorVersion == 2 && minorVersion > 0) || - (majorVersion == 3 && minorVersion > 1) || - majorVersion > 3)) { - /* GLX_EXT_create_context_es2_profile says nothing to justifying a - * different error code for invalid ES versions, but this is what NVIDIA - * does and piglit expects. - */ - generate_error(dpy, GLXBadProfileARB, 0, X_GLXCreateContextAttribsARB, False); - return NULL; - } - - if ((contextFlags & GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB) && - majorVersion < 3) { - generate_error(dpy, BadMatch, 0, X_GLXCreateContextAttribsARB, True); - return NULL; - } - - if (renderType == GLX_COLOR_INDEX_TYPE && majorVersion >= 3) { - generate_error(dpy, BadMatch, 0, X_GLXCreateContextAttribsARB, True); - return NULL; - } - - ctx = create_context(dpy, xmvis, - shareCtx ? shareCtx->xmesaContext : NULL, - direct, - majorVersion, minorVersion, - profileMask, contextFlags); - if (!ctx) { - generate_error(dpy, GLXBadFBConfig, 0, X_GLXCreateContextAttribsARB, False); - } - - return ctx; -} diff --git a/src/gallium/state_trackers/glx/xlib/glx_getproc.c b/src/gallium/state_trackers/glx/xlib/glx_getproc.c deleted file mode 100644 index 6b94f2c1960..00000000000 --- a/src/gallium/state_trackers/glx/xlib/glx_getproc.c +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Mesa 3-D graphics library - * - * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. - * Copyright (C) 2009 VMware, Inc. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - - -/** - * glXGetProcAddress() - */ - - -#define GLX_GLXEXT_PROTOTYPES - -#include -#include "pipe/p_compiler.h" -#include "GL/glx.h" -#include "glapi/glapi.h" - - -struct name_address_pair { - const char *Name; - __GLXextFuncPtr Address; -}; - - -static const struct name_address_pair GLX_functions[] = { - /*** GLX_VERSION_1_0 ***/ - { "glXChooseVisual", (__GLXextFuncPtr) glXChooseVisual }, - { "glXCopyContext", (__GLXextFuncPtr) glXCopyContext }, - { "glXCreateContext", (__GLXextFuncPtr) glXCreateContext }, - { "glXCreateGLXPixmap", (__GLXextFuncPtr) glXCreateGLXPixmap }, - { "glXDestroyContext", (__GLXextFuncPtr) glXDestroyContext }, - { "glXDestroyGLXPixmap", (__GLXextFuncPtr) glXDestroyGLXPixmap }, - { "glXGetConfig", (__GLXextFuncPtr) glXGetConfig }, - { "glXGetCurrentContext", (__GLXextFuncPtr) glXGetCurrentContext }, - { "glXGetCurrentDrawable", (__GLXextFuncPtr) glXGetCurrentDrawable }, - { "glXIsDirect", (__GLXextFuncPtr) glXIsDirect }, - { "glXMakeCurrent", (__GLXextFuncPtr) glXMakeCurrent }, - { "glXQueryExtension", (__GLXextFuncPtr) glXQueryExtension }, - { "glXQueryVersion", (__GLXextFuncPtr) glXQueryVersion }, - { "glXSwapBuffers", (__GLXextFuncPtr) glXSwapBuffers }, - { "glXUseXFont", (__GLXextFuncPtr) glXUseXFont }, - { "glXWaitGL", (__GLXextFuncPtr) glXWaitGL }, - { "glXWaitX", (__GLXextFuncPtr) glXWaitX }, - - /*** GLX_VERSION_1_1 ***/ - { "glXGetClientString", (__GLXextFuncPtr) glXGetClientString }, - { "glXQueryExtensionsString", (__GLXextFuncPtr) glXQueryExtensionsString }, - { "glXQueryServerString", (__GLXextFuncPtr) glXQueryServerString }, - - /*** GLX_VERSION_1_2 ***/ - { "glXGetCurrentDisplay", (__GLXextFuncPtr) glXGetCurrentDisplay }, - - /*** GLX_VERSION_1_3 ***/ - { "glXChooseFBConfig", (__GLXextFuncPtr) glXChooseFBConfig }, - { "glXCreateNewContext", (__GLXextFuncPtr) glXCreateNewContext }, - { "glXCreatePbuffer", (__GLXextFuncPtr) glXCreatePbuffer }, - { "glXCreatePixmap", (__GLXextFuncPtr) glXCreatePixmap }, - { "glXCreateWindow", (__GLXextFuncPtr) glXCreateWindow }, - { "glXDestroyPbuffer", (__GLXextFuncPtr) glXDestroyPbuffer }, - { "glXDestroyPixmap", (__GLXextFuncPtr) glXDestroyPixmap }, - { "glXDestroyWindow", (__GLXextFuncPtr) glXDestroyWindow }, - { "glXGetCurrentReadDrawable", (__GLXextFuncPtr) glXGetCurrentReadDrawable }, - { "glXGetFBConfigAttrib", (__GLXextFuncPtr) glXGetFBConfigAttrib }, - { "glXGetFBConfigs", (__GLXextFuncPtr) glXGetFBConfigs }, - { "glXGetSelectedEvent", (__GLXextFuncPtr) glXGetSelectedEvent }, - { "glXGetVisualFromFBConfig", (__GLXextFuncPtr) glXGetVisualFromFBConfig }, - { "glXMakeContextCurrent", (__GLXextFuncPtr) glXMakeContextCurrent }, - { "glXQueryContext", (__GLXextFuncPtr) glXQueryContext }, - { "glXQueryDrawable", (__GLXextFuncPtr) glXQueryDrawable }, - { "glXSelectEvent", (__GLXextFuncPtr) glXSelectEvent }, - - /*** GLX_VERSION_1_4 ***/ - { "glXGetProcAddress", (__GLXextFuncPtr) glXGetProcAddress }, - - /*** GLX_SGI_swap_control ***/ - { "glXSwapIntervalSGI", (__GLXextFuncPtr) glXSwapIntervalSGI }, - - /*** GLX_SGI_video_sync ***/ - { "glXGetVideoSyncSGI", (__GLXextFuncPtr) glXGetVideoSyncSGI }, - { "glXWaitVideoSyncSGI", (__GLXextFuncPtr) glXWaitVideoSyncSGI }, - - /*** GLX_SGI_make_current_read ***/ - { "glXMakeCurrentReadSGI", (__GLXextFuncPtr) glXMakeCurrentReadSGI }, - { "glXGetCurrentReadDrawableSGI", (__GLXextFuncPtr) glXGetCurrentReadDrawableSGI }, - - /*** GLX_SGIX_video_source ***/ -#if defined(_VL_H) - { "glXCreateGLXVideoSourceSGIX", (__GLXextFuncPtr) glXCreateGLXVideoSourceSGIX }, - { "glXDestroyGLXVideoSourceSGIX", (__GLXextFuncPtr) glXDestroyGLXVideoSourceSGIX }, -#endif - - /*** GLX_EXT_import_context ***/ - { "glXFreeContextEXT", (__GLXextFuncPtr) glXFreeContextEXT }, - { "glXGetContextIDEXT", (__GLXextFuncPtr) glXGetContextIDEXT }, - { "glXGetCurrentDisplayEXT", (__GLXextFuncPtr) glXGetCurrentDisplayEXT }, - { "glXImportContextEXT", (__GLXextFuncPtr) glXImportContextEXT }, - { "glXQueryContextInfoEXT", (__GLXextFuncPtr) glXQueryContextInfoEXT }, - - /*** GLX_SGIX_fbconfig ***/ - { "glXGetFBConfigAttribSGIX", (__GLXextFuncPtr) glXGetFBConfigAttribSGIX }, - { "glXChooseFBConfigSGIX", (__GLXextFuncPtr) glXChooseFBConfigSGIX }, - { "glXCreateGLXPixmapWithConfigSGIX", (__GLXextFuncPtr) glXCreateGLXPixmapWithConfigSGIX }, - { "glXCreateContextWithConfigSGIX", (__GLXextFuncPtr) glXCreateContextWithConfigSGIX }, - { "glXGetVisualFromFBConfigSGIX", (__GLXextFuncPtr) glXGetVisualFromFBConfigSGIX }, - { "glXGetFBConfigFromVisualSGIX", (__GLXextFuncPtr) glXGetFBConfigFromVisualSGIX }, - - /*** GLX_SGIX_pbuffer ***/ - { "glXCreateGLXPbufferSGIX", (__GLXextFuncPtr) glXCreateGLXPbufferSGIX }, - { "glXDestroyGLXPbufferSGIX", (__GLXextFuncPtr) glXDestroyGLXPbufferSGIX }, - { "glXQueryGLXPbufferSGIX", (__GLXextFuncPtr) glXQueryGLXPbufferSGIX }, - { "glXSelectEventSGIX", (__GLXextFuncPtr) glXSelectEventSGIX }, - { "glXGetSelectedEventSGIX", (__GLXextFuncPtr) glXGetSelectedEventSGIX }, - - /*** GLX_SGI_cushion ***/ - { "glXCushionSGI", (__GLXextFuncPtr) glXCushionSGI }, - - /*** GLX_SGIX_video_resize ***/ - { "glXBindChannelToWindowSGIX", (__GLXextFuncPtr) glXBindChannelToWindowSGIX }, - { "glXChannelRectSGIX", (__GLXextFuncPtr) glXChannelRectSGIX }, - { "glXQueryChannelRectSGIX", (__GLXextFuncPtr) glXQueryChannelRectSGIX }, - { "glXQueryChannelDeltasSGIX", (__GLXextFuncPtr) glXQueryChannelDeltasSGIX }, - { "glXChannelRectSyncSGIX", (__GLXextFuncPtr) glXChannelRectSyncSGIX }, - - /*** GLX_SGIX_dmbuffer **/ -#if defined(_DM_BUFFER_H_) - { "glXAssociateDMPbufferSGIX", (__GLXextFuncPtr) glXAssociateDMPbufferSGIX }, -#endif - - /*** GLX_SUN_get_transparent_index ***/ - { "glXGetTransparentIndexSUN", (__GLXextFuncPtr) glXGetTransparentIndexSUN }, - - /*** GLX_MESA_copy_sub_buffer ***/ - { "glXCopySubBufferMESA", (__GLXextFuncPtr) glXCopySubBufferMESA }, - - /*** GLX_MESA_pixmap_colormap ***/ - { "glXCreateGLXPixmapMESA", (__GLXextFuncPtr) glXCreateGLXPixmapMESA }, - - /*** GLX_MESA_release_buffers ***/ - { "glXReleaseBuffersMESA", (__GLXextFuncPtr) glXReleaseBuffersMESA }, - - /*** GLX_ARB_get_proc_address ***/ - { "glXGetProcAddressARB", (__GLXextFuncPtr) glXGetProcAddressARB }, - - /*** GLX_ARB_create_context ***/ - { "glXCreateContextAttribsARB", (__GLXextFuncPtr) glXCreateContextAttribsARB }, - - /*** GLX_EXT_texture_from_pixmap ***/ - { "glXBindTexImageEXT", (__GLXextFuncPtr) glXBindTexImageEXT }, - { "glXReleaseTexImageEXT", (__GLXextFuncPtr) glXReleaseTexImageEXT }, - - { NULL, NULL } /* end of list */ -}; - - - -/** - * Return address of named glX function, or NULL if not found. - */ -static __GLXextFuncPtr -_glxapi_get_proc_address(const char *funcName) -{ - GLuint i; - for (i = 0; GLX_functions[i].Name; i++) { - if (strcmp(GLX_functions[i].Name, funcName) == 0) - return GLX_functions[i].Address; - } - return NULL; -} - - -PUBLIC __GLXextFuncPtr -glXGetProcAddressARB(const GLubyte *procName) -{ - __GLXextFuncPtr f; - - f = _glxapi_get_proc_address((const char *) procName); - if (f) { - return f; - } - - f = (__GLXextFuncPtr) _glapi_get_proc_address((const char *) procName); - return f; -} - - -/* GLX 1.4 */ -PUBLIC -void (*glXGetProcAddress(const GLubyte *procName))() -{ - return glXGetProcAddressARB(procName); -} diff --git a/src/gallium/state_trackers/glx/xlib/glx_usefont.c b/src/gallium/state_trackers/glx/xlib/glx_usefont.c deleted file mode 100644 index 9d35054b44d..00000000000 --- a/src/gallium/state_trackers/glx/xlib/glx_usefont.c +++ /dev/null @@ -1,373 +0,0 @@ -/* - * Mesa 3-D graphics library - * - * Copyright (C) 1995 Thorsten.Ohl @ Physik.TH-Darmstadt.de - * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. - * Copyright (C) 2009 VMware, Inc. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - - -/** - * Fake implementation of glXUseXFont(). - */ - -#include -#include -#include -#include -#include "main/errors.h" - - -/* Some debugging info. */ - -#ifdef DEBUG -#include - -int debug_xfonts = 0; - -static void -dump_char_struct(XCharStruct * ch, char *prefix) -{ - printf("%slbearing = %d, rbearing = %d, width = %d\n", - prefix, ch->lbearing, ch->rbearing, ch->width); - printf("%sascent = %d, descent = %d, attributes = %u\n", - prefix, ch->ascent, ch->descent, (unsigned int) ch->attributes); -} - -static void -dump_font_struct(XFontStruct * font) -{ - printf("ascent = %d, descent = %d\n", font->ascent, font->descent); - printf("char_or_byte2 = (%u,%u)\n", - font->min_char_or_byte2, font->max_char_or_byte2); - printf("byte1 = (%u,%u)\n", font->min_byte1, font->max_byte1); - printf("all_chars_exist = %s\n", font->all_chars_exist ? "True" : "False"); - printf("default_char = %c (\\%03o)\n", - (char) (isprint(font->default_char) ? font->default_char : ' '), - font->default_char); - dump_char_struct(&font->min_bounds, "min> "); - dump_char_struct(&font->max_bounds, "max> "); -#if 0 - for (c = font->min_char_or_byte2; c <= font->max_char_or_byte2; c++) { - char prefix[8]; - sprintf(prefix, "%d> ", c); - dump_char_struct(&font->per_char[c], prefix); - } -#endif -} - -static void -dump_bitmap(unsigned int width, unsigned int height, GLubyte * bitmap) -{ - unsigned int x, y; - - printf(" "); - for (x = 0; x < 8 * width; x++) - printf("%o", 7 - (x % 8)); - putchar('\n'); - for (y = 0; y < height; y++) { - printf("%3o:", y); - for (x = 0; x < 8 * width; x++) - putchar((bitmap[width * (height - y - 1) + x / 8] & (1 << (7 - (x % - 8)))) - ? '*' : '.'); - printf(" "); - for (x = 0; x < width; x++) - printf("0x%02x, ", bitmap[width * (height - y - 1) + x]); - putchar('\n'); - } -} -#endif /* DEBUG */ - - -/* Implementation. */ - -/* Fill a BITMAP with a character C from thew current font - in the graphics context GC. WIDTH is the width in bytes - and HEIGHT is the height in bits. - - Note that the generated bitmaps must be used with - - glPixelStorei (GL_UNPACK_SWAP_BYTES, GL_FALSE); - glPixelStorei (GL_UNPACK_LSB_FIRST, GL_FALSE); - glPixelStorei (GL_UNPACK_ROW_LENGTH, 0); - glPixelStorei (GL_UNPACK_SKIP_ROWS, 0); - glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0); - glPixelStorei (GL_UNPACK_ALIGNMENT, 1); - - Possible optimizations: - - * use only one reusable pixmap with the maximum dimensions. - * draw the entire font into a single pixmap (careful with - proportional fonts!). -*/ - - -/* - * Generate OpenGL-compatible bitmap. - */ -static void -fill_bitmap(Display * dpy, Window win, GC gc, - unsigned int width, unsigned int height, - int x0, int y0, unsigned int c, GLubyte * bitmap) -{ - XImage *image; - unsigned int x, y; - Pixmap pixmap; - XChar2b char2b; - - pixmap = XCreatePixmap(dpy, win, 8 * width, height, 1); - XSetForeground(dpy, gc, 0); - XFillRectangle(dpy, pixmap, gc, 0, 0, 8 * width, height); - XSetForeground(dpy, gc, 1); - - char2b.byte1 = (c >> 8) & 0xff; - char2b.byte2 = (c & 0xff); - - XDrawString16(dpy, pixmap, gc, x0, y0, &char2b, 1); - - image = XGetImage(dpy, pixmap, 0, 0, 8 * width, height, 1, XYPixmap); - if (image) { - /* Fill the bitmap (X11 and OpenGL are upside down wrt each other). */ - for (y = 0; y < height; y++) - for (x = 0; x < 8 * width; x++) - if (XGetPixel(image, x, y)) - bitmap[width * (height - y - 1) + x / 8] |= - (1 << (7 - (x % 8))); - XDestroyImage(image); - } - - XFreePixmap(dpy, pixmap); -} - -/* - * determine if a given glyph is valid and return the - * corresponding XCharStruct. - */ -static XCharStruct * -isvalid(XFontStruct * fs, unsigned int which) -{ - unsigned int rows, pages; - unsigned int byte1 = 0, byte2 = 0; - int i, valid = 1; - - rows = fs->max_byte1 - fs->min_byte1 + 1; - pages = fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1; - - if (rows == 1) { - /* "linear" fonts */ - if ((fs->min_char_or_byte2 > which) || (fs->max_char_or_byte2 < which)) - valid = 0; - } - else { - /* "matrix" fonts */ - byte2 = which & 0xff; - byte1 = which >> 8; - if ((fs->min_char_or_byte2 > byte2) || - (fs->max_char_or_byte2 < byte2) || - (fs->min_byte1 > byte1) || (fs->max_byte1 < byte1)) - valid = 0; - } - - if (valid) { - if (fs->per_char) { - if (rows == 1) { - /* "linear" fonts */ - return (fs->per_char + (which - fs->min_char_or_byte2)); - } - else { - /* "matrix" fonts */ - i = ((byte1 - fs->min_byte1) * pages) + - (byte2 - fs->min_char_or_byte2); - return (fs->per_char + i); - } - } - else { - return (&fs->min_bounds); - } - } - return (NULL); -} - - -PUBLIC void -glXUseXFont(Font font, int first, int count, int listbase) -{ - Display *dpy; - Window win; - Pixmap pixmap; - GC gc; - XGCValues values; - unsigned long valuemask; - XFontStruct *fs; - GLint swapbytes, lsbfirst, rowlength; - GLint skiprows, skippixels, alignment; - unsigned int max_width, max_height, max_bm_width, max_bm_height; - GLubyte *bm; - int i; - - dpy = glXGetCurrentDisplay(); - if (!dpy) - return; /* I guess glXMakeCurrent wasn't called */ - i = DefaultScreen(dpy); - win = RootWindow(dpy, i); - - fs = XQueryFont(dpy, font); - if (!fs) { - _mesa_error(NULL, GL_INVALID_VALUE, - "Couldn't get font structure information"); - return; - } - - /* Allocate a bitmap that can fit all characters. */ - max_width = fs->max_bounds.rbearing - fs->min_bounds.lbearing; - max_height = fs->max_bounds.ascent + fs->max_bounds.descent; - max_bm_width = (max_width + 7) / 8; - max_bm_height = max_height; - - bm = malloc((max_bm_width * max_bm_height) * sizeof(GLubyte)); - if (!bm) { - XFreeFontInfo(NULL, fs, 1); - _mesa_error(NULL, GL_OUT_OF_MEMORY, - "Couldn't allocate bitmap in glXUseXFont()"); - return; - } - -#if 0 - /* get the page info */ - pages = fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1; - firstchar = (fs->min_byte1 << 8) + fs->min_char_or_byte2; - lastchar = (fs->max_byte1 << 8) + fs->max_char_or_byte2; - rows = fs->max_byte1 - fs->min_byte1 + 1; - unsigned int first_char, last_char, pages, rows; -#endif - - /* Save the current packing mode for bitmaps. */ - glGetIntegerv(GL_UNPACK_SWAP_BYTES, &swapbytes); - glGetIntegerv(GL_UNPACK_LSB_FIRST, &lsbfirst); - glGetIntegerv(GL_UNPACK_ROW_LENGTH, &rowlength); - glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skiprows); - glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skippixels); - glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment); - - /* Enforce a standard packing mode which is compatible with - fill_bitmap() from above. This is actually the default mode, - except for the (non)alignment. */ - glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); - glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE); - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); - glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - - pixmap = XCreatePixmap(dpy, win, 10, 10, 1); - values.foreground = BlackPixel(dpy, DefaultScreen(dpy)); - values.background = WhitePixel(dpy, DefaultScreen(dpy)); - values.font = fs->fid; - valuemask = GCForeground | GCBackground | GCFont; - gc = XCreateGC(dpy, pixmap, valuemask, &values); - XFreePixmap(dpy, pixmap); - -#ifdef DEBUG - if (debug_xfonts) - dump_font_struct(fs); -#endif - - for (i = 0; i < count; i++) { - unsigned int width, height, bm_width, bm_height; - GLfloat x0, y0, dx, dy; - XCharStruct *ch; - int x, y; - unsigned int c = first + i; - int list = listbase + i; - int valid; - - /* check on index validity and get the bounds */ - ch = isvalid(fs, c); - if (!ch) { - ch = &fs->max_bounds; - valid = 0; - } - else { - valid = 1; - } - -#ifdef DEBUG - if (debug_xfonts) { - char s[7]; - sprintf(s, isprint(c) ? "%c> " : "\\%03o> ", c); - dump_char_struct(ch, s); - } -#endif - - /* glBitmap()' parameters: - straight from the glXUseXFont(3) manpage. */ - width = ch->rbearing - ch->lbearing; - height = ch->ascent + ch->descent; - x0 = -ch->lbearing; - y0 = ch->descent - 0; /* XXX used to subtract 1 here */ - /* but that caused a conformace failure */ - dx = ch->width; - dy = 0; - - /* X11's starting point. */ - x = -ch->lbearing; - y = ch->ascent; - - /* Round the width to a multiple of eight. We will use this also - for the pixmap for capturing the X11 font. This is slightly - inefficient, but it makes the OpenGL part real easy. */ - bm_width = (width + 7) / 8; - bm_height = height; - - glNewList(list, GL_COMPILE); - if (valid && (bm_width > 0) && (bm_height > 0)) { - - memset(bm, '\0', bm_width * bm_height); - fill_bitmap(dpy, win, gc, bm_width, bm_height, x, y, c, bm); - - glBitmap(width, height, x0, y0, dx, dy, bm); -#ifdef DEBUG - if (debug_xfonts) { - printf("width/height = %u/%u\n", width, height); - printf("bm_width/bm_height = %u/%u\n", bm_width, bm_height); - dump_bitmap(bm_width, bm_height, bm); - } -#endif - } - else { - glBitmap(0, 0, 0.0, 0.0, dx, dy, NULL); - } - glEndList(); - } - - free(bm); - XFreeFontInfo(NULL, fs, 1); - XFreeGC(dpy, gc); - - /* Restore saved packing modes. */ - glPixelStorei(GL_UNPACK_SWAP_BYTES, swapbytes); - glPixelStorei(GL_UNPACK_LSB_FIRST, lsbfirst); - glPixelStorei(GL_UNPACK_ROW_LENGTH, rowlength); - glPixelStorei(GL_UNPACK_SKIP_ROWS, skiprows); - glPixelStorei(GL_UNPACK_SKIP_PIXELS, skippixels); - glPixelStorei(GL_UNPACK_ALIGNMENT, alignment); -} diff --git a/src/gallium/state_trackers/glx/xlib/meson.build b/src/gallium/state_trackers/glx/xlib/meson.build deleted file mode 100644 index 7b1fdb34ffe..00000000000 --- a/src/gallium/state_trackers/glx/xlib/meson.build +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright © 2017 Intel Corporation - -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: - -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. - -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -libxlib = static_library( - 'xlib', - files('glx_api.c', 'glx_getproc.c', 'glx_usefont.c', 'xm_api.c', 'xm_st.c'), - c_args : c_vis_args, - include_directories : [inc_include, inc_src, inc_gallium, inc_gallium_aux, inc_mapi, inc_mesa], - dependencies : [dep_x11, dep_xext, dep_xcb, dep_glproto], -) diff --git a/src/gallium/state_trackers/glx/xlib/xm_api.c b/src/gallium/state_trackers/glx/xlib/xm_api.c deleted file mode 100644 index 94a787b422a..00000000000 --- a/src/gallium/state_trackers/glx/xlib/xm_api.c +++ /dev/null @@ -1,1561 +0,0 @@ -/* - * Mesa 3-D graphics library - * - * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -/** - * \file xm_api.c - * - * All the XMesa* API functions. - * - * - * NOTES: - * - * The window coordinate system origin (0,0) is in the lower-left corner - * of the window. X11's window coordinate origin is in the upper-left - * corner of the window. Therefore, most drawing functions in this - * file have to flip Y coordinates. - * - * - * Byte swapping: If the Mesa host and the X display use a different - * byte order then there's some trickiness to be aware of when using - * XImages. The byte ordering used for the XImage is that of the X - * display, not the Mesa host. - * The color-to-pixel encoding for True/DirectColor must be done - * according to the display's visual red_mask, green_mask, and blue_mask. - * If XPutPixel is used to put a pixel into an XImage then XPutPixel will - * do byte swapping if needed. If one wants to directly "poke" the pixel - * into the XImage's buffer then the pixel must be byte swapped first. - * - */ - -#ifdef __CYGWIN__ -#undef WIN32 -#undef __WIN32__ -#endif - -#include -#include "xm_api.h" -#include "xm_st.h" - -#include "pipe/p_context.h" -#include "pipe/p_defines.h" -#include "pipe/p_screen.h" -#include "pipe/p_state.h" -#include "state_tracker/st_api.h" - -#include "util/u_atomic.h" -#include "util/u_inlines.h" -#include "util/u_math.h" -#include "util/u_memory.h" - -#include "hud/hud_context.h" - -#include "main/errors.h" - -#include "xm_public.h" -#include - - -/* Driver interface routines, set up by xlib backend on library - * _init(). These are global in the same way that function names are - * global. - */ -static struct xm_driver driver; -static struct st_api *stapi; - -/* Default strict invalidate to false. This means we will not call - * XGetGeometry after every swapbuffers, which allows swapbuffers to - * remain asynchronous. For apps running at 100fps with synchronous - * swapping, a 10% boost is typical. For gears, I see closer to 20% - * speedup. - * - * Note that the work of copying data on swapbuffers doesn't disappear - * - this change just allows the X server to execute the PutImage - * asynchronously without us effectively blocked until its completion. - * - * This speeds up even llvmpipe's threaded rasterization as the - * swapbuffers operation was a large part of the serial component of - * an llvmpipe frame. - * - * The downside of this is correctness - applications which don't call - * glViewport on window resizes will get incorrect rendering. A - * better solution would be to have per-frame but asynchronous - * invalidation. Xcb almost looks as if it could provide this, but - * the API doesn't seem to quite be there. - */ -boolean xmesa_strict_invalidate = FALSE; - -void xmesa_set_driver( const struct xm_driver *templ ) -{ - driver = *templ; - stapi = driver.create_st_api(); - - xmesa_strict_invalidate = - debug_get_bool_option("XMESA_STRICT_INVALIDATE", FALSE); -} - - -static int -xmesa_get_param(struct st_manager *smapi, - enum st_manager_param param) -{ - switch(param) { - case ST_MANAGER_BROKEN_INVALIDATE: - return !xmesa_strict_invalidate; - default: - return 0; - } -} - -/* linked list of XMesaDisplay hooks per display */ -typedef struct _XMesaExtDisplayInfo { - struct _XMesaExtDisplayInfo *next; - Display *display; - struct xmesa_display mesaDisplay; -} XMesaExtDisplayInfo; - -typedef struct _XMesaExtInfo { - XMesaExtDisplayInfo *head; - int ndisplays; -} XMesaExtInfo; - -static XMesaExtInfo MesaExtInfo; - -/* hook to delete XMesaDisplay on XDestroyDisplay */ -extern void -xmesa_close_display(Display *display) -{ - XMesaExtDisplayInfo *info, *prev; - - /* These assertions are not valid since screen creation can fail and result - * in an empty list - assert(MesaExtInfo.ndisplays > 0); - assert(MesaExtInfo.head); - */ - - _XLockMutex(_Xglobal_lock); - /* first find display */ - prev = NULL; - for (info = MesaExtInfo.head; info; info = info->next) { - if (info->display == display) { - prev = info; - break; - } - } - - if (info == NULL) { - /* no display found */ - _XUnlockMutex(_Xglobal_lock); - return; - } - - /* remove display entry from list */ - if (prev != MesaExtInfo.head) { - prev->next = info->next; - } else { - MesaExtInfo.head = info->next; - } - MesaExtInfo.ndisplays--; - - _XUnlockMutex(_Xglobal_lock); - - /* don't forget to clean up mesaDisplay */ - XMesaDisplay xmdpy = &info->mesaDisplay; - - /** - * XXX: Don't destroy the screens here, since there may still - * be some dangling screen pointers that are used after this point - * if (xmdpy->screen) { - * xmdpy->screen->destroy(xmdpy->screen); - * } - */ - - if (xmdpy->smapi->destroy) - xmdpy->smapi->destroy(xmdpy->smapi); - free(xmdpy->smapi); - - XFree((char *) info); -} - -static XMesaDisplay -xmesa_init_display( Display *display ) -{ - static mtx_t init_mutex = _MTX_INITIALIZER_NP; - XMesaDisplay xmdpy; - XMesaExtDisplayInfo *info; - - if (display == NULL) { - return NULL; - } - - mtx_lock(&init_mutex); - - /* Look for XMesaDisplay which corresponds to this display */ - info = MesaExtInfo.head; - while(info) { - if (info->display == display) { - /* Found it */ - mtx_unlock(&init_mutex); - return &info->mesaDisplay; - } - info = info->next; - } - - /* Not found. Create new XMesaDisplay */ - /* first allocate X-related resources and hook destroy callback */ - - /* allocate mesa display info */ - info = (XMesaExtDisplayInfo *) Xmalloc(sizeof(XMesaExtDisplayInfo)); - if (info == NULL) { - mtx_unlock(&init_mutex); - return NULL; - } - info->display = display; - - xmdpy = &info->mesaDisplay; /* to be filled out below */ - xmdpy->display = display; - xmdpy->pipe = NULL; - - xmdpy->smapi = CALLOC_STRUCT(st_manager); - if (!xmdpy->smapi) { - Xfree(info); - mtx_unlock(&init_mutex); - return NULL; - } - - xmdpy->screen = driver.create_pipe_screen(display); - if (!xmdpy->screen) { - free(xmdpy->smapi); - Xfree(info); - mtx_unlock(&init_mutex); - return NULL; - } - - /* At this point, both smapi and screen are known to be valid */ - xmdpy->smapi->screen = xmdpy->screen; - xmdpy->smapi->get_param = xmesa_get_param; - (void) mtx_init(&xmdpy->mutex, mtx_plain); - - /* chain to the list of displays */ - _XLockMutex(_Xglobal_lock); - info->next = MesaExtInfo.head; - MesaExtInfo.head = info; - MesaExtInfo.ndisplays++; - _XUnlockMutex(_Xglobal_lock); - - mtx_unlock(&init_mutex); - - return xmdpy; -} - - -/**********************************************************************/ -/***** X Utility Functions *****/ -/**********************************************************************/ - - -/** - * Return the host's byte order as LSBFirst or MSBFirst ala X. - */ -static int host_byte_order( void ) -{ - int i = 1; - char *cptr = (char *) &i; - return (*cptr==1) ? LSBFirst : MSBFirst; -} - - - - -/** - * Return the true number of bits per pixel for XImages. - * For example, if we request a 24-bit deep visual we may actually need/get - * 32bpp XImages. This function returns the appropriate bpp. - * Input: dpy - the X display - * visinfo - desribes the visual to be used for XImages - * Return: true number of bits per pixel for XImages - */ -static int -bits_per_pixel( XMesaVisual xmv ) -{ - Display *dpy = xmv->display; - XVisualInfo * visinfo = xmv->visinfo; - XImage *img; - int bitsPerPixel; - /* Create a temporary XImage */ - img = XCreateImage( dpy, visinfo->visual, visinfo->depth, - ZPixmap, 0, /*format, offset*/ - malloc(8), /*data*/ - 1, 1, /*width, height*/ - 32, /*bitmap_pad*/ - 0 /*bytes_per_line*/ - ); - assert(img); - /* grab the bits/pixel value */ - bitsPerPixel = img->bits_per_pixel; - /* free the XImage */ - free( img->data ); - img->data = NULL; - XDestroyImage( img ); - return bitsPerPixel; -} - - - -/* - * Determine if a given X window ID is valid (window exists). - * Do this by calling XGetWindowAttributes() for the window and - * checking if we catch an X error. - * Input: dpy - the display - * win - the window to check for existence - * Return: GL_TRUE - window exists - * GL_FALSE - window doesn't exist - */ -static GLboolean WindowExistsFlag; - -static int window_exists_err_handler( Display* dpy, XErrorEvent* xerr ) -{ - (void) dpy; - if (xerr->error_code == BadWindow) { - WindowExistsFlag = GL_FALSE; - } - return 0; -} - -static GLboolean window_exists( Display *dpy, Window win ) -{ - XWindowAttributes wa; - int (*old_handler)( Display*, XErrorEvent* ); - WindowExistsFlag = GL_TRUE; - old_handler = XSetErrorHandler(window_exists_err_handler); - XGetWindowAttributes( dpy, win, &wa ); /* dummy request */ - XSetErrorHandler(old_handler); - return WindowExistsFlag; -} - -static Status -get_drawable_size( Display *dpy, Drawable d, uint *width, uint *height ) -{ - Window root; - Status stat; - int xpos, ypos; - unsigned int w, h, bw, depth; - stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth); - *width = w; - *height = h; - return stat; -} - - -/** - * Return the size of the window (or pixmap) that corresponds to the - * given XMesaBuffer. - * \param width returns width in pixels - * \param height returns height in pixels - */ -void -xmesa_get_window_size(Display *dpy, XMesaBuffer b, - GLuint *width, GLuint *height) -{ - XMesaDisplay xmdpy = xmesa_init_display(dpy); - Status stat; - - mtx_lock(&xmdpy->mutex); - stat = get_drawable_size(dpy, b->ws.drawable, width, height); - mtx_unlock(&xmdpy->mutex); - - if (!stat) { - /* probably querying a window that's recently been destroyed */ - _mesa_warning(NULL, "XGetGeometry failed!\n"); - *width = *height = 1; - } -} - -#define GET_REDMASK(__v) __v->mesa_visual.redMask -#define GET_GREENMASK(__v) __v->mesa_visual.greenMask -#define GET_BLUEMASK(__v) __v->mesa_visual.blueMask - - -/** - * Choose the pixel format for the given visual. - * This will tell the gallium driver how to pack pixel data into - * drawing surfaces. - */ -static GLuint -choose_pixel_format(XMesaVisual v) -{ - boolean native_byte_order = (host_byte_order() == - ImageByteOrder(v->display)); - - if ( GET_REDMASK(v) == 0x0000ff - && GET_GREENMASK(v) == 0x00ff00 - && GET_BLUEMASK(v) == 0xff0000 - && v->BitsPerPixel == 32) { - if (native_byte_order) { - /* no byteswapping needed */ - return PIPE_FORMAT_RGBA8888_UNORM; - } - else { - return PIPE_FORMAT_ABGR8888_UNORM; - } - } - else if ( GET_REDMASK(v) == 0xff0000 - && GET_GREENMASK(v) == 0x00ff00 - && GET_BLUEMASK(v) == 0x0000ff - && v->BitsPerPixel == 32) { - if (native_byte_order) { - /* no byteswapping needed */ - return PIPE_FORMAT_BGRA8888_UNORM; - } - else { - return PIPE_FORMAT_ARGB8888_UNORM; - } - } - else if ( GET_REDMASK(v) == 0x0000ff00 - && GET_GREENMASK(v) == 0x00ff0000 - && GET_BLUEMASK(v) == 0xff000000 - && v->BitsPerPixel == 32) { - if (native_byte_order) { - /* no byteswapping needed */ - return PIPE_FORMAT_ARGB8888_UNORM; - } - else { - return PIPE_FORMAT_BGRA8888_UNORM; - } - } - else if ( GET_REDMASK(v) == 0xf800 - && GET_GREENMASK(v) == 0x07e0 - && GET_BLUEMASK(v) == 0x001f - && native_byte_order - && v->BitsPerPixel == 16) { - /* 5-6-5 RGB */ - return PIPE_FORMAT_B5G6R5_UNORM; - } - - return PIPE_FORMAT_NONE; -} - - -/** - * Choose a depth/stencil format that satisfies the given depth and - * stencil sizes. - */ -static enum pipe_format -choose_depth_stencil_format(XMesaDisplay xmdpy, int depth, int stencil, - int sample_count) -{ - const enum pipe_texture_target target = PIPE_TEXTURE_2D; - const unsigned tex_usage = PIPE_BIND_DEPTH_STENCIL; - enum pipe_format formats[8], fmt; - int count, i; - - count = 0; - - if (depth <= 16 && stencil == 0) { - formats[count++] = PIPE_FORMAT_Z16_UNORM; - } - if (depth <= 24 && stencil == 0) { - formats[count++] = PIPE_FORMAT_X8Z24_UNORM; - formats[count++] = PIPE_FORMAT_Z24X8_UNORM; - } - if (depth <= 24 && stencil <= 8) { - formats[count++] = PIPE_FORMAT_S8_UINT_Z24_UNORM; - formats[count++] = PIPE_FORMAT_Z24_UNORM_S8_UINT; - } - if (depth <= 32 && stencil == 0) { - formats[count++] = PIPE_FORMAT_Z32_UNORM; - } - - fmt = PIPE_FORMAT_NONE; - for (i = 0; i < count; i++) { - if (xmdpy->screen->is_format_supported(xmdpy->screen, formats[i], - target, sample_count, - sample_count, tex_usage)) { - fmt = formats[i]; - break; - } - } - - return fmt; -} - - - -/**********************************************************************/ -/***** Linked list of XMesaBuffers *****/ -/**********************************************************************/ - -static XMesaBuffer XMesaBufferList = NULL; - - -/** - * Allocate a new XMesaBuffer object which corresponds to the given drawable. - * Note that XMesaBuffer is derived from struct gl_framebuffer. - * The new XMesaBuffer will not have any size (Width=Height=0). - * - * \param d the corresponding X drawable (window or pixmap) - * \param type either WINDOW, PIXMAP or PBUFFER, describing d - * \param vis the buffer's visual - * \param cmap the window's colormap, if known. - * \return new XMesaBuffer or NULL if any problem - */ -static XMesaBuffer -create_xmesa_buffer(Drawable d, BufferType type, - XMesaVisual vis, Colormap cmap) -{ - XMesaDisplay xmdpy = xmesa_init_display(vis->display); - XMesaBuffer b; - - assert(type == WINDOW || type == PIXMAP || type == PBUFFER); - - if (!xmdpy) - return NULL; - - b = (XMesaBuffer) CALLOC_STRUCT(xmesa_buffer); - if (!b) - return NULL; - - b->ws.drawable = d; - b->ws.visual = vis->visinfo->visual; - b->ws.depth = vis->visinfo->depth; - - b->xm_visual = vis; - b->type = type; - b->cmap = cmap; - - get_drawable_size(vis->display, d, &b->width, &b->height); - - /* - * Create framebuffer, but we'll plug in our own renderbuffers below. - */ - b->stfb = xmesa_create_st_framebuffer(xmdpy, b); - - /* GLX_EXT_texture_from_pixmap */ - b->TextureTarget = 0; - b->TextureFormat = GLX_TEXTURE_FORMAT_NONE_EXT; - b->TextureMipmap = 0; - - /* insert buffer into linked list */ - b->Next = XMesaBufferList; - XMesaBufferList = b; - - return b; -} - - -/** - * Find an XMesaBuffer by matching X display and colormap but NOT matching - * the notThis buffer. - */ -XMesaBuffer -xmesa_find_buffer(Display *dpy, Colormap cmap, XMesaBuffer notThis) -{ - XMesaBuffer b; - for (b = XMesaBufferList; b; b = b->Next) { - if (b->xm_visual->display == dpy && - b->cmap == cmap && - b != notThis) { - return b; - } - } - return NULL; -} - - -/** - * Remove buffer from linked list, delete if no longer referenced. - */ -static void -xmesa_free_buffer(XMesaBuffer buffer) -{ - XMesaBuffer prev = NULL, b; - - for (b = XMesaBufferList; b; b = b->Next) { - if (b == buffer) { - /* unlink buffer from list */ - if (prev) - prev->Next = buffer->Next; - else - XMesaBufferList = buffer->Next; - - /* Since the X window for the XMesaBuffer is going away, we don't - * want to dereference this pointer in the future. - */ - b->ws.drawable = 0; - - /* Notify the st manager that the associated framebuffer interface - * object is no longer valid. - */ - stapi->destroy_drawable(stapi, buffer->stfb); - - /* XXX we should move the buffer to a delete-pending list and destroy - * the buffer until it is no longer current. - */ - xmesa_destroy_st_framebuffer(buffer->stfb); - - free(buffer); - - return; - } - /* continue search */ - prev = b; - } - /* buffer not found in XMesaBufferList */ - _mesa_problem(NULL,"xmesa_free_buffer() - buffer not found\n"); -} - - - -/**********************************************************************/ -/***** Misc Private Functions *****/ -/**********************************************************************/ - - -/** - * When a context is bound for the first time, we can finally finish - * initializing the context's visual and buffer information. - * \param v the XMesaVisual to initialize - * \param b the XMesaBuffer to initialize (may be NULL) - * \param window the window/pixmap we're rendering into - * \param cmap the colormap associated with the window/pixmap - * \return GL_TRUE=success, GL_FALSE=failure - */ -static GLboolean -initialize_visual_and_buffer(XMesaVisual v, XMesaBuffer b, - Drawable window, Colormap cmap) -{ - assert(!b || b->xm_visual == v); - - /* Save true bits/pixel */ - v->BitsPerPixel = bits_per_pixel(v); - assert(v->BitsPerPixel > 0); - - /* RGB WINDOW: - * We support RGB rendering into almost any kind of visual. - */ - const int xclass = v->visualType; - if (xclass != GLX_TRUE_COLOR && xclass != GLX_DIRECT_COLOR) { - _mesa_warning(NULL, - "XMesa: RGB mode rendering not supported in given visual.\n"); - return GL_FALSE; - } - - if (v->BitsPerPixel == 32) { - /* We use XImages for all front/back buffers. If an X Window or - * X Pixmap is 32bpp, there's no guarantee that the alpha channel - * will be preserved. For XImages we're in luck. - */ - v->mesa_visual.alphaBits = 8; - } - - /* - * If MESA_INFO env var is set print out some debugging info - * which can help Brian figure out what's going on when a user - * reports bugs. - */ - if (getenv("MESA_INFO")) { - printf("X/Mesa visual = %p\n", (void *) v); - printf("X/Mesa level = %d\n", v->mesa_visual.level); - printf("X/Mesa depth = %d\n", v->visinfo->depth); - printf("X/Mesa bits per pixel = %d\n", v->BitsPerPixel); - } - - return GL_TRUE; -} - - - -#define NUM_VISUAL_TYPES 6 - -/** - * Convert an X visual type to a GLX visual type. - * - * \param visualType X visual type (i.e., \c TrueColor, \c StaticGray, etc.) - * to be converted. - * \return If \c visualType is a valid X visual type, a GLX visual type will - * be returned. Otherwise \c GLX_NONE will be returned. - * - * \note - * This code was lifted directly from lib/GL/glx/glcontextmodes.c in the - * DRI CVS tree. - */ -static GLint -xmesa_convert_from_x_visual_type( int visualType ) -{ - static const int glx_visual_types[ NUM_VISUAL_TYPES ] = { - GLX_STATIC_GRAY, GLX_GRAY_SCALE, - GLX_STATIC_COLOR, GLX_PSEUDO_COLOR, - GLX_TRUE_COLOR, GLX_DIRECT_COLOR - }; - - return ( (unsigned) visualType < NUM_VISUAL_TYPES ) - ? glx_visual_types[ visualType ] : GLX_NONE; -} - - -/**********************************************************************/ -/***** Public Functions *****/ -/**********************************************************************/ - - -/* - * Create a new X/Mesa visual. - * Input: display - X11 display - * visinfo - an XVisualInfo pointer - * rgb_flag - GL_TRUE = RGB mode, - * GL_FALSE = color index mode - * alpha_flag - alpha buffer requested? - * db_flag - GL_TRUE = double-buffered, - * GL_FALSE = single buffered - * stereo_flag - stereo visual? - * ximage_flag - GL_TRUE = use an XImage for back buffer, - * GL_FALSE = use an off-screen pixmap for back buffer - * depth_size - requested bits/depth values, or zero - * stencil_size - requested bits/stencil values, or zero - * accum_red_size - requested bits/red accum values, or zero - * accum_green_size - requested bits/green accum values, or zero - * accum_blue_size - requested bits/blue accum values, or zero - * accum_alpha_size - requested bits/alpha accum values, or zero - * num_samples - number of samples/pixel if multisampling, or zero - * level - visual level, usually 0 - * visualCaveat - ala the GLX extension, usually GLX_NONE - * Return; a new XMesaVisual or 0 if error. - */ -PUBLIC -XMesaVisual XMesaCreateVisual( Display *display, - XVisualInfo * visinfo, - GLboolean rgb_flag, - GLboolean alpha_flag, - GLboolean db_flag, - GLboolean stereo_flag, - GLboolean ximage_flag, - GLint depth_size, - GLint stencil_size, - GLint accum_red_size, - GLint accum_green_size, - GLint accum_blue_size, - GLint accum_alpha_size, - GLint num_samples, - GLint level, - GLint visualCaveat ) -{ - XMesaDisplay xmdpy = xmesa_init_display(display); - XMesaVisual v; - GLint red_bits, green_bits, blue_bits, alpha_bits; - - if (!xmdpy) - return NULL; - - if (!rgb_flag) - return NULL; - - /* For debugging only */ - if (getenv("MESA_XSYNC")) { - /* This makes debugging X easier. - * In your debugger, set a breakpoint on _XError to stop when an - * X protocol error is generated. - */ - XSynchronize( display, 1 ); - } - - v = (XMesaVisual) CALLOC_STRUCT(xmesa_visual); - if (!v) { - return NULL; - } - - v->display = display; - - /* Save a copy of the XVisualInfo struct because the user may Xfree() - * the struct but we may need some of the information contained in it - * at a later time. - */ - v->visinfo = malloc(sizeof(*visinfo)); - if (!v->visinfo) { - free(v); - return NULL; - } - memcpy(v->visinfo, visinfo, sizeof(*visinfo)); - - v->ximage_flag = ximage_flag; - - v->mesa_visual.redMask = visinfo->red_mask; - v->mesa_visual.greenMask = visinfo->green_mask; - v->mesa_visual.blueMask = visinfo->blue_mask; - v->visualID = visinfo->visualid; - v->screen = visinfo->screen; - -#if !(defined(__cplusplus) || defined(c_plusplus)) - v->visualType = xmesa_convert_from_x_visual_type(visinfo->class); -#else - v->visualType = xmesa_convert_from_x_visual_type(visinfo->c_class); -#endif - - v->mesa_visual.visualRating = visualCaveat; - - if (alpha_flag) - v->mesa_visual.alphaBits = 8; - - (void) initialize_visual_and_buffer( v, NULL, 0, 0 ); - - { - const int xclass = v->visualType; - if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) { - red_bits = util_bitcount(GET_REDMASK(v)); - green_bits = util_bitcount(GET_GREENMASK(v)); - blue_bits = util_bitcount(GET_BLUEMASK(v)); - } - else { - /* this is an approximation */ - int depth; - depth = v->visinfo->depth; - red_bits = depth / 3; - depth -= red_bits; - green_bits = depth / 2; - depth -= green_bits; - blue_bits = depth; - alpha_bits = 0; - assert( red_bits + green_bits + blue_bits == v->visinfo->depth ); - } - alpha_bits = v->mesa_visual.alphaBits; - } - - /* initialize visual */ - { - struct gl_config *vis = &v->mesa_visual; - - vis->doubleBufferMode = db_flag; - vis->stereoMode = stereo_flag; - - vis->redBits = red_bits; - vis->greenBits = green_bits; - vis->blueBits = blue_bits; - vis->alphaBits = alpha_bits; - vis->rgbBits = red_bits + green_bits + blue_bits; - - vis->depthBits = depth_size; - vis->stencilBits = stencil_size; - - vis->accumRedBits = accum_red_size; - vis->accumGreenBits = accum_green_size; - vis->accumBlueBits = accum_blue_size; - vis->accumAlphaBits = accum_alpha_size; - - vis->numAuxBuffers = 0; - vis->level = 0; - vis->sampleBuffers = num_samples > 1; - vis->samples = num_samples; - } - - v->stvis.buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK; - if (db_flag) - v->stvis.buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK; - if (stereo_flag) { - v->stvis.buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK; - if (db_flag) - v->stvis.buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK; - } - - v->stvis.color_format = choose_pixel_format(v); - - /* Check format support at requested num_samples (for multisample) */ - if (!xmdpy->screen->is_format_supported(xmdpy->screen, - v->stvis.color_format, - PIPE_TEXTURE_2D, num_samples, - num_samples, - PIPE_BIND_RENDER_TARGET)) - v->stvis.color_format = PIPE_FORMAT_NONE; - - if (v->stvis.color_format == PIPE_FORMAT_NONE) { - free(v->visinfo); - free(v); - return NULL; - } - - v->stvis.depth_stencil_format = - choose_depth_stencil_format(xmdpy, depth_size, stencil_size, - num_samples); - - v->stvis.accum_format = (accum_red_size + - accum_green_size + accum_blue_size + accum_alpha_size) ? - PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE; - - v->stvis.samples = num_samples; - v->stvis.render_buffer = ST_ATTACHMENT_INVALID; - - /* XXX minor hack */ - v->mesa_visual.level = level; - return v; -} - - -PUBLIC -void XMesaDestroyVisual( XMesaVisual v ) -{ - free(v->visinfo); - free(v); -} - - -/** - * Return the informative name. - */ -const char * -xmesa_get_name(void) -{ - return stapi->name; -} - - -/** - * Do per-display initializations. - */ -int -xmesa_init( Display *display ) -{ - return xmesa_init_display(display) ? 0 : 1; -} - - -/** - * Create a new XMesaContext. - * \param v the XMesaVisual - * \param share_list another XMesaContext with which to share display - * lists or NULL if no sharing is wanted. - * \return an XMesaContext or NULL if error. - */ -PUBLIC -XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list, - GLuint major, GLuint minor, - GLuint profileMask, GLuint contextFlags) -{ - XMesaDisplay xmdpy = xmesa_init_display(v->display); - struct st_context_attribs attribs; - enum st_context_error ctx_err = 0; - XMesaContext c; - - if (!xmdpy) - goto no_xmesa_context; - - /* Note: the XMesaContext contains a Mesa struct gl_context struct (inheritance) */ - c = (XMesaContext) CALLOC_STRUCT(xmesa_context); - if (!c) - goto no_xmesa_context; - - c->xm_visual = v; - c->xm_buffer = NULL; /* set later by XMesaMakeCurrent */ - c->xm_read_buffer = NULL; - - memset(&attribs, 0, sizeof(attribs)); - attribs.visual = v->stvis; - attribs.major = major; - attribs.minor = minor; - if (contextFlags & GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB) - attribs.flags |= ST_CONTEXT_FLAG_FORWARD_COMPATIBLE; - if (contextFlags & GLX_CONTEXT_DEBUG_BIT_ARB) - attribs.flags |= ST_CONTEXT_FLAG_DEBUG; - if (contextFlags & GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB) - attribs.flags |= ST_CONTEXT_FLAG_ROBUST_ACCESS; - - switch (profileMask) { - case GLX_CONTEXT_CORE_PROFILE_BIT_ARB: - /* There are no profiles before OpenGL 3.2. The - * GLX_ARB_create_context_profile spec says: - * - * "If the requested OpenGL version is less than 3.2, - * GLX_CONTEXT_PROFILE_MASK_ARB is ignored and the functionality - * of the context is determined solely by the requested version." - */ - if (major > 3 || (major == 3 && minor >= 2)) { - attribs.profile = ST_PROFILE_OPENGL_CORE; - break; - } - /* fall-through */ - case GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB: - /* - * The spec also says: - * - * "If version 3.1 is requested, the context returned may implement - * any of the following versions: - * - * * Version 3.1. The GL_ARB_compatibility extension may or may not - * be implemented, as determined by the implementation. - * * The core profile of version 3.2 or greater." - * - * and because Mesa doesn't support GL_ARB_compatibility, the only chance to - * honour a 3.1 context is through core profile. - */ - if (major == 3 && minor == 1) { - attribs.profile = ST_PROFILE_OPENGL_CORE; - } else { - attribs.profile = ST_PROFILE_DEFAULT; - } - break; - case GLX_CONTEXT_ES_PROFILE_BIT_EXT: - if (major >= 2) { - attribs.profile = ST_PROFILE_OPENGL_ES2; - } else { - attribs.profile = ST_PROFILE_OPENGL_ES1; - } - break; - default: - assert(0); - goto no_st; - } - - c->st = stapi->create_context(stapi, xmdpy->smapi, &attribs, - &ctx_err, (share_list) ? share_list->st : NULL); - if (c->st == NULL) - goto no_st; - - c->st->st_manager_private = (void *) c; - - c->hud = hud_create(c->st->cso_context, NULL); - - return c; - -no_st: - free(c); -no_xmesa_context: - return NULL; -} - - - -PUBLIC -void XMesaDestroyContext( XMesaContext c ) -{ - if (c->hud) { - hud_destroy(c->hud, NULL); - } - - c->st->destroy(c->st); - - /* FIXME: We should destroy the screen here, but if we do so, surfaces may - * outlive it, causing segfaults - struct pipe_screen *screen = c->st->pipe->screen; - screen->destroy(screen); - */ - - free(c); -} - - - -/** - * Private function for creating an XMesaBuffer which corresponds to an - * X window or pixmap. - * \param v the window's XMesaVisual - * \param w the window we're wrapping - * \return new XMesaBuffer or NULL if error - */ -PUBLIC XMesaBuffer -XMesaCreateWindowBuffer(XMesaVisual v, Window w) -{ - XWindowAttributes attr; - XMesaBuffer b; - Colormap cmap; - int depth; - - assert(v); - assert(w); - - /* Check that window depth matches visual depth */ - XGetWindowAttributes( v->display, w, &attr ); - depth = attr.depth; - if (v->visinfo->depth != depth) { - _mesa_warning(NULL, "XMesaCreateWindowBuffer: depth mismatch between visual (%d) and window (%d)!\n", - v->visinfo->depth, depth); - return NULL; - } - - /* Find colormap */ - if (attr.colormap) { - cmap = attr.colormap; - } - else { - _mesa_warning(NULL, "Window %u has no colormap!\n", (unsigned int) w); - /* this is weird, a window w/out a colormap!? */ - /* OK, let's just allocate a new one and hope for the best */ - cmap = XCreateColormap(v->display, w, attr.visual, AllocNone); - } - - b = create_xmesa_buffer((Drawable) w, WINDOW, v, cmap); - if (!b) - return NULL; - - if (!initialize_visual_and_buffer( v, b, (Drawable) w, cmap )) { - xmesa_free_buffer(b); - return NULL; - } - - return b; -} - - - -/** - * Create a new XMesaBuffer from an X pixmap. - * - * \param v the XMesaVisual - * \param p the pixmap - * \param cmap the colormap, may be 0 if using a \c GLX_TRUE_COLOR or - * \c GLX_DIRECT_COLOR visual for the pixmap - * \returns new XMesaBuffer or NULL if error - */ -PUBLIC XMesaBuffer -XMesaCreatePixmapBuffer(XMesaVisual v, Pixmap p, Colormap cmap) -{ - XMesaBuffer b; - - assert(v); - - b = create_xmesa_buffer((Drawable) p, PIXMAP, v, cmap); - if (!b) - return NULL; - - if (!initialize_visual_and_buffer(v, b, (Drawable) p, cmap)) { - xmesa_free_buffer(b); - return NULL; - } - - return b; -} - - -/** - * For GLX_EXT_texture_from_pixmap - */ -XMesaBuffer -XMesaCreatePixmapTextureBuffer(XMesaVisual v, Pixmap p, - Colormap cmap, - int format, int target, int mipmap) -{ - GET_CURRENT_CONTEXT(ctx); - XMesaBuffer b; - - assert(v); - - b = create_xmesa_buffer((Drawable) p, PIXMAP, v, cmap); - if (!b) - return NULL; - - /* get pixmap size */ - xmesa_get_window_size(v->display, b, &b->width, &b->height); - - if (target == 0) { - /* examine dims */ - if (ctx->Extensions.ARB_texture_non_power_of_two) { - target = GLX_TEXTURE_2D_EXT; - } - else if ( util_bitcount(b->width) == 1 - && util_bitcount(b->height) == 1) { - /* power of two size */ - if (b->height == 1) { - target = GLX_TEXTURE_1D_EXT; - } - else { - target = GLX_TEXTURE_2D_EXT; - } - } - else if (ctx->Extensions.NV_texture_rectangle) { - target = GLX_TEXTURE_RECTANGLE_EXT; - } - else { - /* non power of two textures not supported */ - XMesaDestroyBuffer(b); - return 0; - } - } - - b->TextureTarget = target; - b->TextureFormat = format; - b->TextureMipmap = mipmap; - - if (!initialize_visual_and_buffer(v, b, (Drawable) p, cmap)) { - xmesa_free_buffer(b); - return NULL; - } - - return b; -} - - - -XMesaBuffer -XMesaCreatePBuffer(XMesaVisual v, Colormap cmap, - unsigned int width, unsigned int height) -{ - Window root; - Drawable drawable; /* X Pixmap Drawable */ - XMesaBuffer b; - - /* allocate pixmap for front buffer */ - root = RootWindow( v->display, v->visinfo->screen ); - drawable = XCreatePixmap(v->display, root, width, height, - v->visinfo->depth); - if (!drawable) - return NULL; - - b = create_xmesa_buffer(drawable, PBUFFER, v, cmap); - if (!b) - return NULL; - - if (!initialize_visual_and_buffer(v, b, drawable, cmap)) { - xmesa_free_buffer(b); - return NULL; - } - - return b; -} - - - -/* - * Deallocate an XMesaBuffer structure and all related info. - */ -PUBLIC void -XMesaDestroyBuffer(XMesaBuffer b) -{ - xmesa_free_buffer(b); -} - - -/** - * Notify the binding context to validate the buffer. - */ -void -xmesa_notify_invalid_buffer(XMesaBuffer b) -{ - p_atomic_inc(&b->stfb->stamp); -} - - -/** - * Query the current drawable size and notify the binding context. - */ -void -xmesa_check_buffer_size(XMesaBuffer b) -{ - GLuint old_width, old_height; - - if (!b) - return; - - if (b->type == PBUFFER) - return; - - old_width = b->width; - old_height = b->height; - - xmesa_get_window_size(b->xm_visual->display, b, &b->width, &b->height); - - if (b->width != old_width || b->height != old_height) - xmesa_notify_invalid_buffer(b); -} - - -/* - * Bind buffer b to context c and make c the current rendering context. - */ -PUBLIC -GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer, - XMesaBuffer readBuffer ) -{ - XMesaContext old_ctx = XMesaGetCurrentContext(); - - if (old_ctx && old_ctx != c) { - XMesaFlush(old_ctx); - old_ctx->xm_buffer = NULL; - old_ctx->xm_read_buffer = NULL; - } - - if (c) { - if (!drawBuffer != !readBuffer) { - return GL_FALSE; /* must specify zero or two buffers! */ - } - - if (c == old_ctx && - c->xm_buffer == drawBuffer && - c->xm_read_buffer == readBuffer) - return GL_TRUE; - - xmesa_check_buffer_size(drawBuffer); - if (readBuffer != drawBuffer) - xmesa_check_buffer_size(readBuffer); - - c->xm_buffer = drawBuffer; - c->xm_read_buffer = readBuffer; - - stapi->make_current(stapi, c->st, - drawBuffer ? drawBuffer->stfb : NULL, - readBuffer ? readBuffer->stfb : NULL); - - /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */ - if (drawBuffer) - drawBuffer->wasCurrent = GL_TRUE; - } - else { - /* Detach */ - stapi->make_current(stapi, NULL, NULL, NULL); - - } - return GL_TRUE; -} - - -/* - * Unbind the context c from its buffer. - */ -GLboolean XMesaUnbindContext( XMesaContext c ) -{ - /* A no-op for XFree86 integration purposes */ - return GL_TRUE; -} - - -XMesaContext XMesaGetCurrentContext( void ) -{ - struct st_context_iface *st = stapi->get_current(stapi); - return (XMesaContext) (st) ? st->st_manager_private : NULL; -} - - - -/** - * Swap front and back color buffers and have winsys display front buffer. - * If there's no front color buffer no swap actually occurs. - */ -PUBLIC -void XMesaSwapBuffers( XMesaBuffer b ) -{ - XMesaContext xmctx = XMesaGetCurrentContext(); - - /* Need to draw HUD before flushing */ - if (xmctx && xmctx->hud) { - struct pipe_resource *back = - xmesa_get_framebuffer_resource(b->stfb, ST_ATTACHMENT_BACK_LEFT); - hud_run(xmctx->hud, NULL, back); - } - - if (xmctx && xmctx->xm_buffer == b) { - xmctx->st->flush( xmctx->st, ST_FLUSH_FRONT, NULL, NULL, NULL); - } - - xmesa_swap_st_framebuffer(b->stfb); -} - - - -/* - * Copy sub-region of back buffer to front buffer - */ -void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height ) -{ - XMesaContext xmctx = XMesaGetCurrentContext(); - - xmctx->st->flush( xmctx->st, ST_FLUSH_FRONT, NULL, NULL, NULL); - - xmesa_copy_st_framebuffer(b->stfb, - ST_ATTACHMENT_BACK_LEFT, ST_ATTACHMENT_FRONT_LEFT, - x, b->height - y - height, width, height); -} - - - -void XMesaFlush( XMesaContext c ) -{ - if (c && c->xm_visual->display) { - XMesaDisplay xmdpy = xmesa_init_display(c->xm_visual->display); - struct pipe_fence_handle *fence = NULL; - - c->st->flush(c->st, ST_FLUSH_FRONT, &fence, NULL, NULL); - if (fence) { - xmdpy->screen->fence_finish(xmdpy->screen, NULL, fence, - PIPE_TIMEOUT_INFINITE); - xmdpy->screen->fence_reference(xmdpy->screen, &fence, NULL); - } - XFlush( c->xm_visual->display ); - } -} - - - - - -XMesaBuffer XMesaFindBuffer( Display *dpy, Drawable d ) -{ - XMesaBuffer b; - for (b = XMesaBufferList; b; b = b->Next) { - if (b->ws.drawable == d && b->xm_visual->display == dpy) { - return b; - } - } - return NULL; -} - - -/** - * Free/destroy all XMesaBuffers associated with given display. - */ -void xmesa_destroy_buffers_on_display(Display *dpy) -{ - XMesaBuffer b, next; - for (b = XMesaBufferList; b; b = next) { - next = b->Next; - if (b->xm_visual->display == dpy) { - xmesa_free_buffer(b); - /* delete head of list? */ - if (XMesaBufferList == b) { - XMesaBufferList = next; - } - } - } -} - - -/* - * Look for XMesaBuffers whose X window has been destroyed. - * Deallocate any such XMesaBuffers. - */ -void XMesaGarbageCollect( void ) -{ - XMesaBuffer b, next; - for (b=XMesaBufferList; b; b=next) { - next = b->Next; - if (b->xm_visual && - b->xm_visual->display && - b->ws.drawable && - b->type == WINDOW) { - XSync(b->xm_visual->display, False); - if (!window_exists( b->xm_visual->display, b->ws.drawable )) { - /* found a dead window, free the ancillary info */ - XMesaDestroyBuffer( b ); - } - } - } -} - - -static enum st_attachment_type xmesa_attachment_type(int glx_attachment) -{ - switch(glx_attachment) { - case GLX_FRONT_LEFT_EXT: - return ST_ATTACHMENT_FRONT_LEFT; - case GLX_FRONT_RIGHT_EXT: - return ST_ATTACHMENT_FRONT_RIGHT; - case GLX_BACK_LEFT_EXT: - return ST_ATTACHMENT_BACK_LEFT; - case GLX_BACK_RIGHT_EXT: - return ST_ATTACHMENT_BACK_RIGHT; - default: - assert(0); - return ST_ATTACHMENT_FRONT_LEFT; - } -} - - -PUBLIC void -XMesaBindTexImage(Display *dpy, XMesaBuffer drawable, int buffer, - const int *attrib_list) -{ - struct st_context_iface *st = stapi->get_current(stapi); - struct st_framebuffer_iface* stfbi = drawable->stfb; - struct pipe_resource *res; - int x, y, w, h; - enum st_attachment_type st_attachment = xmesa_attachment_type(buffer); - - x = 0; - y = 0; - w = drawable->width; - h = drawable->height; - - /* We need to validate our attachments before using them, - * in case the texture doesn't exist yet. */ - xmesa_st_framebuffer_validate_textures(stfbi, w, h, 1 << st_attachment); - res = xmesa_get_attachment(stfbi, st_attachment); - - if (res) { - struct pipe_context* pipe = xmesa_get_context(stfbi); - enum pipe_format internal_format = res->format; - struct pipe_transfer *tex_xfer; - char *map; - int line, byte_width; - XImage *img; - - internal_format = choose_pixel_format(drawable->xm_visual); - - map = pipe_transfer_map(pipe, res, - 0, 0, /* level, layer */ - PIPE_TRANSFER_WRITE, - x, y, - w, h, &tex_xfer); - if (!map) - return; - - /* Grab the XImage that we want to turn into a texture. */ - img = XGetImage(dpy, - drawable->ws.drawable, - x, y, - w, h, - AllPlanes, - ZPixmap); - - if (!img) { - pipe_transfer_unmap(pipe, tex_xfer); - return; - } - - /* The pipe transfer has a pitch rounded up to the nearest 64 pixels. */ - byte_width = w * ((img->bits_per_pixel + 7) / 8); - - for (line = 0; line < h; line++) - memcpy(&map[line * tex_xfer->stride], - &img->data[line * img->bytes_per_line], - byte_width); - - pipe_transfer_unmap(pipe, tex_xfer); - - st->teximage(st, - ST_TEXTURE_2D, - 0, /* level */ - internal_format, - res, - FALSE /* no mipmap */); - - } -} - - - -PUBLIC void -XMesaReleaseTexImage(Display *dpy, XMesaBuffer drawable, int buffer) -{ -} - - -void -XMesaCopyContext(XMesaContext src, XMesaContext dst, unsigned long mask) -{ - if (dst->st->copy) - dst->st->copy(dst->st, src->st, mask); -} diff --git a/src/gallium/state_trackers/glx/xlib/xm_api.h b/src/gallium/state_trackers/glx/xlib/xm_api.h deleted file mode 100644 index 9684b5a17e1..00000000000 --- a/src/gallium/state_trackers/glx/xlib/xm_api.h +++ /dev/null @@ -1,398 +0,0 @@ -/* - * Mesa 3-D graphics library - * - * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - - - -/* Sample Usage: - -In addition to the usual X calls to select a visual, create a colormap -and create a window, you must do the following to use the X/Mesa interface: - -1. Call XMesaCreateVisual() to make an XMesaVisual from an XVisualInfo. - -2. Call XMesaCreateContext() to create an X/Mesa rendering context, given - the XMesaVisual. - -3. Call XMesaCreateWindowBuffer() to create an XMesaBuffer from an X window - and XMesaVisual. - -4. Call XMesaMakeCurrent() to bind the XMesaBuffer to an XMesaContext and - to make the context the current one. - -5. Make gl* calls to render your graphics. - -6. Use XMesaSwapBuffers() when double buffering to swap front/back buffers. - -7. Before the X window is destroyed, call XMesaDestroyBuffer(). - -8. Before exiting, call XMesaDestroyVisual and XMesaDestroyContext. - -*/ - - - - -#ifndef XM_API_H -#define XM_API_H - - -#include "main/mtypes.h" /* for gl_config */ -#include "state_tracker/st_api.h" -#include "os/os_thread.h" - -#include "state_tracker/xlibsw_api.h" - -# include -# include -# include - -struct hud_context; - -typedef struct xmesa_display *XMesaDisplay; -typedef struct xmesa_buffer *XMesaBuffer; -typedef struct xmesa_context *XMesaContext; -typedef struct xmesa_visual *XMesaVisual; - - -struct xmesa_display { - mtx_t mutex; - - Display *display; - struct pipe_screen *screen; - struct st_manager *smapi; - - struct pipe_context *pipe; -}; - - -/* - * Create a new X/Mesa visual. - * Input: display - X11 display - * visinfo - an XVisualInfo pointer - * rgb_flag - GL_TRUE = RGB mode, - * GL_FALSE = color index mode - * alpha_flag - alpha buffer requested? - * db_flag - GL_TRUE = double-buffered, - * GL_FALSE = single buffered - * stereo_flag - stereo visual? - * ximage_flag - GL_TRUE = use an XImage for back buffer, - * GL_FALSE = use an off-screen pixmap for back buffer - * depth_size - requested bits/depth values, or zero - * stencil_size - requested bits/stencil values, or zero - * accum_red_size - requested bits/red accum values, or zero - * accum_green_size - requested bits/green accum values, or zero - * accum_blue_size - requested bits/blue accum values, or zero - * accum_alpha_size - requested bits/alpha accum values, or zero - * num_samples - number of samples/pixel if multisampling, or zero - * level - visual level, usually 0 - * visualCaveat - ala the GLX extension, usually GLX_NONE_EXT - * Return; a new XMesaVisual or 0 if error. - */ -extern XMesaVisual XMesaCreateVisual( Display *display, - XVisualInfo * visinfo, - GLboolean rgb_flag, - GLboolean alpha_flag, - GLboolean db_flag, - GLboolean stereo_flag, - GLboolean ximage_flag, - GLint depth_size, - GLint stencil_size, - GLint accum_red_size, - GLint accum_green_size, - GLint accum_blue_size, - GLint accum_alpha_size, - GLint num_samples, - GLint level, - GLint visualCaveat ); - -/* - * Destroy an XMesaVisual, but not the associated XVisualInfo. - */ -extern void XMesaDestroyVisual( XMesaVisual v ); - - - -/* - * Create a new XMesaContext for rendering into an X11 window. - * - * Input: visual - an XMesaVisual - * share_list - another XMesaContext with which to share display - * lists or NULL if no sharing is wanted. - * Return: an XMesaContext or NULL if error. - */ -extern XMesaContext XMesaCreateContext( XMesaVisual v, - XMesaContext share_list, - GLuint major, GLuint minor, - GLuint profileMask, - GLuint contextFlags); - - -/* - * Destroy a rendering context as returned by XMesaCreateContext() - */ -extern void XMesaDestroyContext( XMesaContext c ); - - - -/* - * Create an XMesaBuffer from an X window. - */ -extern XMesaBuffer XMesaCreateWindowBuffer( XMesaVisual v, Window w ); - - -/* - * Create an XMesaBuffer from an X pixmap. - */ -extern XMesaBuffer XMesaCreatePixmapBuffer( XMesaVisual v, - Pixmap p, - Colormap cmap ); - - -/* - * Destroy an XMesaBuffer, but not the corresponding window or pixmap. - */ -extern void XMesaDestroyBuffer( XMesaBuffer b ); - - -/* - * Return the XMesaBuffer handle which corresponds to an X drawable, if any. - * - * New in Mesa 2.3. - */ -extern XMesaBuffer XMesaFindBuffer( Display *dpy, - Drawable d ); - - - -/* - * Bind two buffers (read and draw) to a context and make the - * context the current one. - * New in Mesa 3.3 - */ -extern GLboolean XMesaMakeCurrent2( XMesaContext c, - XMesaBuffer drawBuffer, - XMesaBuffer readBuffer ); - - -/* - * Unbind the current context from its buffer. - */ -extern GLboolean XMesaUnbindContext( XMesaContext c ); - - -/* - * Return a handle to the current context. - */ -extern XMesaContext XMesaGetCurrentContext( void ); - - -/* - * Swap the front and back buffers for the given buffer. No action is - * taken if the buffer is not double buffered. - */ -extern void XMesaSwapBuffers( XMesaBuffer b ); - - -/* - * Copy a sub-region of the back buffer to the front buffer. - * - * New in Mesa 2.6 - */ -extern void XMesaCopySubBuffer( XMesaBuffer b, - int x, - int y, - int width, - int height ); - - - - - -/* - * Flush/sync a context - */ -extern void XMesaFlush( XMesaContext c ); - - - -/* - * Scan for XMesaBuffers whose window/pixmap has been destroyed, then free - * any memory used by that buffer. - * - * New in Mesa 2.3. - */ -extern void XMesaGarbageCollect( void ); - - - -/* - * Create a pbuffer. - * New in Mesa 4.1 - */ -extern XMesaBuffer XMesaCreatePBuffer(XMesaVisual v, Colormap cmap, - unsigned int width, unsigned int height); - - - -/* - * Texture from Pixmap - * New in Mesa 7.1 - */ -extern void -XMesaBindTexImage(Display *dpy, XMesaBuffer drawable, int buffer, - const int *attrib_list); - -extern void -XMesaReleaseTexImage(Display *dpy, XMesaBuffer drawable, int buffer); - - -extern XMesaBuffer -XMesaCreatePixmapTextureBuffer(XMesaVisual v, Pixmap p, - Colormap cmap, - int format, int target, int mipmap); - - -extern void -XMesaCopyContext(XMesaContext src, XMesaContext dst, unsigned long mask); - - -/*********************************************************************** - */ - -/** - * Visual inforation, derived from GLvisual. - * Basically corresponds to an XVisualInfo. - */ -struct xmesa_visual { - struct gl_config mesa_visual;/* Device independent visual parameters */ - int screen, visualID, visualType; - Display *display; /* The X11 display */ - XVisualInfo * visinfo; /* X's visual info (pointer to private copy) */ - XVisualInfo *vishandle; /* Only used in fakeglx.c */ - GLint BitsPerPixel; /* True bits per pixel for XImages */ - - GLboolean ximage_flag; /* Use XImage for back buffer (not pixmap)? */ - - struct st_visual stvis; -}; - - -/** - * Context info, derived from st_context. - * Basically corresponds to a GLXContext. - */ -struct xmesa_context { - struct st_context_iface *st; - XMesaVisual xm_visual; /** pixel format info */ - XMesaBuffer xm_buffer; /** current drawbuffer */ - XMesaBuffer xm_read_buffer; /** current readbuffer */ - struct hud_context *hud; -}; - - -/** - * Types of X/GLX drawables we might render into. - */ -typedef enum { - WINDOW, /* An X window */ - GLXWINDOW, /* GLX window */ - PIXMAP, /* GLX pixmap */ - PBUFFER /* GLX Pbuffer */ -} BufferType; - - -/** - * Framebuffer information, derived from. - * Basically corresponds to a GLXDrawable. - */ -struct xmesa_buffer { - struct st_framebuffer_iface *stfb; - struct xlib_drawable ws; - - GLboolean wasCurrent; /* was ever the current buffer? */ - XMesaVisual xm_visual; /* the X/Mesa visual */ - Colormap cmap; /* the X colormap */ - BufferType type; /* window, pixmap, pbuffer or glxwindow */ - - GLboolean largestPbuffer; /**< for pbuffers */ - GLboolean preservedContents; /**< for pbuffers */ - - XImage *tempImage; - unsigned long selectedEvents;/* for pbuffers only */ - - - GC gc; /* scratch GC for span, line, tri drawing */ - - /* GLX_EXT_texture_from_pixmap */ - GLint TextureTarget; /** GLX_TEXTURE_1D_EXT, for example */ - GLint TextureFormat; /** GLX_TEXTURE_FORMAT_RGB_EXT, for example */ - GLint TextureMipmap; /** 0 or 1 */ - - struct xmesa_buffer *Next; /* Linked list pointer: */ - - unsigned width, height; -}; - - - -extern const char * -xmesa_get_name(void); - -extern int -xmesa_init(Display *dpy); - -extern XMesaBuffer -xmesa_find_buffer(Display *dpy, Colormap cmap, XMesaBuffer notThis); - -extern void -xmesa_get_window_size(Display *dpy, XMesaBuffer b, - GLuint *width, GLuint *height); - -extern void -xmesa_notify_invalid_buffer(XMesaBuffer b); - -extern void -xmesa_check_buffer_size(XMesaBuffer b); - -extern void -xmesa_destroy_buffers_on_display(Display *dpy); - -extern void -xmesa_close_display(Display *dpy); - -static inline GLuint -xmesa_buffer_width(XMesaBuffer b) -{ - return b->width; -} - -static inline GLuint -xmesa_buffer_height(XMesaBuffer b) -{ - return b->height; -} - -extern boolean xmesa_strict_invalidate; - -#endif diff --git a/src/gallium/state_trackers/glx/xlib/xm_public.h b/src/gallium/state_trackers/glx/xlib/xm_public.h deleted file mode 100644 index 9afc5f5d7cf..00000000000 --- a/src/gallium/state_trackers/glx/xlib/xm_public.h +++ /dev/null @@ -1,48 +0,0 @@ - -/************************************************************************** - * - * Copyright 2006 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#ifndef XM_PUBLIC_H -#define XM_PUBLIC_H - -#include - -struct pipe_screen; -struct st_api; - -/* This is the driver interface required by the glx/xlib state tracker. - */ -struct xm_driver { - struct pipe_screen *(*create_pipe_screen)( Display *display ); - struct st_api *(*create_st_api)( void ); -}; - -extern void -xmesa_set_driver( const struct xm_driver *driver ); - - -#endif /* XM_PUBLIC_H */ diff --git a/src/gallium/state_trackers/glx/xlib/xm_st.c b/src/gallium/state_trackers/glx/xlib/xm_st.c deleted file mode 100644 index 4fe7b57f24c..00000000000 --- a/src/gallium/state_trackers/glx/xlib/xm_st.c +++ /dev/null @@ -1,411 +0,0 @@ -/* - * Mesa 3-D graphics library - * - * Copyright (C) 2010 LunarG Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * Chia-I Wu - */ - -#include "xm_api.h" -#include "xm_st.h" - -#include "util/u_inlines.h" -#include "util/u_atomic.h" -#include "util/u_memory.h" - -struct xmesa_st_framebuffer { - XMesaDisplay display; - XMesaBuffer buffer; - struct pipe_screen *screen; - - struct st_visual stvis; - enum pipe_texture_target target; - - unsigned texture_width, texture_height, texture_mask; - struct pipe_resource *textures[ST_ATTACHMENT_COUNT]; - - struct pipe_resource *display_resource; -}; - - -static inline struct xmesa_st_framebuffer * -xmesa_st_framebuffer(struct st_framebuffer_iface *stfbi) -{ - return (struct xmesa_st_framebuffer *) stfbi->st_manager_private; -} - - -/** - * Display (present) an attachment to the xlib_drawable of the framebuffer. - */ -static bool -xmesa_st_framebuffer_display(struct st_framebuffer_iface *stfbi, - enum st_attachment_type statt) -{ - struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); - struct pipe_resource *ptex = xstfb->textures[statt]; - struct pipe_resource *pres; - - if (!ptex) - return true; - - pres = xstfb->display_resource; - /* (re)allocate the surface for the texture to be displayed */ - if (!pres || pres != ptex) { - pipe_resource_reference(&xstfb->display_resource, ptex); - pres = xstfb->display_resource; - } - - xstfb->screen->flush_frontbuffer(xstfb->screen, pres, 0, 0, &xstfb->buffer->ws, NULL); - return true; -} - - -/** - * Copy the contents between the attachments. - */ -static void -xmesa_st_framebuffer_copy_textures(struct st_framebuffer_iface *stfbi, - enum st_attachment_type src_statt, - enum st_attachment_type dst_statt, - unsigned x, unsigned y, - unsigned width, unsigned height) -{ - struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); - struct pipe_resource *src_ptex = xstfb->textures[src_statt]; - struct pipe_resource *dst_ptex = xstfb->textures[dst_statt]; - struct pipe_box src_box; - struct pipe_context *pipe; - - if (!src_ptex || !dst_ptex) - return; - - pipe = xmesa_get_context(stfbi); - - u_box_2d(x, y, width, height, &src_box); - - if (src_ptex && dst_ptex) - pipe->resource_copy_region(pipe, dst_ptex, 0, x, y, 0, - src_ptex, 0, &src_box); -} - - -/** - * Remove outdated textures and create the requested ones. - * This is a helper used during framebuffer validation. - */ -bool -xmesa_st_framebuffer_validate_textures(struct st_framebuffer_iface *stfbi, - unsigned width, unsigned height, - unsigned mask) -{ - struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); - struct pipe_resource templ; - enum st_attachment_type i; - - /* remove outdated textures */ - if (xstfb->texture_width != width || xstfb->texture_height != height) { - for (i = 0; i < ST_ATTACHMENT_COUNT; i++) - pipe_resource_reference(&xstfb->textures[i], NULL); - } - - memset(&templ, 0, sizeof(templ)); - templ.target = xstfb->target; - templ.width0 = width; - templ.height0 = height; - templ.depth0 = 1; - templ.array_size = 1; - templ.last_level = 0; - templ.nr_samples = xstfb->stvis.samples; - templ.nr_storage_samples = xstfb->stvis.samples; - - for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { - enum pipe_format format; - unsigned bind; - - /* the texture already exists or not requested */ - if (xstfb->textures[i] || !(mask & (1 << i))) { - /* remember the texture */ - if (xstfb->textures[i]) - mask |= (1 << i); - continue; - } - - switch (i) { - case ST_ATTACHMENT_FRONT_LEFT: - case ST_ATTACHMENT_BACK_LEFT: - case ST_ATTACHMENT_FRONT_RIGHT: - case ST_ATTACHMENT_BACK_RIGHT: - format = xstfb->stvis.color_format; - bind = PIPE_BIND_DISPLAY_TARGET | - PIPE_BIND_RENDER_TARGET; - break; - case ST_ATTACHMENT_DEPTH_STENCIL: - format = xstfb->stvis.depth_stencil_format; - bind = PIPE_BIND_DEPTH_STENCIL; - break; - default: - format = PIPE_FORMAT_NONE; - break; - } - - if (format != PIPE_FORMAT_NONE) { - templ.format = format; - templ.bind = bind; - - xstfb->textures[i] = - xstfb->screen->resource_create(xstfb->screen, &templ); - if (!xstfb->textures[i]) - return FALSE; - } - } - - xstfb->texture_width = width; - xstfb->texture_height = height; - xstfb->texture_mask = mask; - - return true; -} - - -/** - * Check that a framebuffer's attachments match the window's size. - * - * Called via st_framebuffer_iface::validate() - * - * \param statts array of framebuffer attachments - * \param count number of framebuffer attachments in statts[] - * \param out returns resources for each of the attachments - */ -static bool -xmesa_st_framebuffer_validate(struct st_context_iface *stctx, - struct st_framebuffer_iface *stfbi, - const enum st_attachment_type *statts, - unsigned count, - struct pipe_resource **out) -{ - struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); - unsigned statt_mask, new_mask, i; - bool resized; - bool ret; - - /* build mask of ST_ATTACHMENT bits */ - statt_mask = 0x0; - for (i = 0; i < count; i++) - statt_mask |= 1 << statts[i]; - - /* record newly allocated textures */ - new_mask = statt_mask & ~xstfb->texture_mask; - - /* If xmesa_strict_invalidate is not set, we will not yet have - * called XGetGeometry(). Do so here: - */ - if (!xmesa_strict_invalidate) - xmesa_check_buffer_size(xstfb->buffer); - - resized = (xstfb->buffer->width != xstfb->texture_width || - xstfb->buffer->height != xstfb->texture_height); - - /* revalidate textures */ - if (resized || new_mask) { - ret = xmesa_st_framebuffer_validate_textures(stfbi, - xstfb->buffer->width, xstfb->buffer->height, statt_mask); - if (!ret) - return ret; - - if (!resized) { - enum st_attachment_type back, front; - - back = ST_ATTACHMENT_BACK_LEFT; - front = ST_ATTACHMENT_FRONT_LEFT; - /* copy the contents if front is newly allocated and back is not */ - if ((statt_mask & (1 << back)) && - (new_mask & (1 << front)) && - !(new_mask & (1 << back))) { - xmesa_st_framebuffer_copy_textures(stfbi, back, front, - 0, 0, xstfb->texture_width, xstfb->texture_height); - } - } - } - - for (i = 0; i < count; i++) - pipe_resource_reference(&out[i], xstfb->textures[statts[i]]); - - return true; -} - - -/** - * Called via st_framebuffer_iface::flush_front() - */ -static bool -xmesa_st_framebuffer_flush_front(struct st_context_iface *stctx, - struct st_framebuffer_iface *stfbi, - enum st_attachment_type statt) -{ - struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); - bool ret; - - ret = xmesa_st_framebuffer_display(stfbi, statt); - - if (ret && xmesa_strict_invalidate) - xmesa_check_buffer_size(xstfb->buffer); - - return ret; -} - -static uint32_t xmesa_stfbi_ID = 0; - -struct st_framebuffer_iface * -xmesa_create_st_framebuffer(XMesaDisplay xmdpy, XMesaBuffer b) -{ - struct st_framebuffer_iface *stfbi; - struct xmesa_st_framebuffer *xstfb; - - assert(xmdpy->display == b->xm_visual->display); - - stfbi = CALLOC_STRUCT(st_framebuffer_iface); - xstfb = CALLOC_STRUCT(xmesa_st_framebuffer); - if (!stfbi || !xstfb) { - free(stfbi); - free(xstfb); - return NULL; - } - - xstfb->display = xmdpy; - xstfb->buffer = b; - xstfb->screen = xmdpy->screen; - xstfb->stvis = b->xm_visual->stvis; - if (xstfb->screen->get_param(xstfb->screen, PIPE_CAP_NPOT_TEXTURES)) - xstfb->target = PIPE_TEXTURE_2D; - else - xstfb->target = PIPE_TEXTURE_RECT; - - stfbi->visual = &xstfb->stvis; - stfbi->flush_front = xmesa_st_framebuffer_flush_front; - stfbi->validate = xmesa_st_framebuffer_validate; - stfbi->ID = p_atomic_inc_return(&xmesa_stfbi_ID); - stfbi->state_manager = xmdpy->smapi; - p_atomic_set(&stfbi->stamp, 1); - stfbi->st_manager_private = (void *) xstfb; - - return stfbi; -} - - -void -xmesa_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi) -{ - struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); - int i; - - pipe_resource_reference(&xstfb->display_resource, NULL); - - for (i = 0; i < ST_ATTACHMENT_COUNT; i++) - pipe_resource_reference(&xstfb->textures[i], NULL); - - free(xstfb); - free(stfbi); -} - - -/** - * Return the pipe_surface which corresponds to the given - * framebuffer attachment. - */ -struct pipe_resource * -xmesa_get_framebuffer_resource(struct st_framebuffer_iface *stfbi, - enum st_attachment_type att) -{ - struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); - return xstfb->textures[att]; -} - - -void -xmesa_swap_st_framebuffer(struct st_framebuffer_iface *stfbi) -{ - struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); - bool ret; - - ret = xmesa_st_framebuffer_display(stfbi, ST_ATTACHMENT_BACK_LEFT); - if (ret) { - struct pipe_resource **front, **back, *tmp; - - front = &xstfb->textures[ST_ATTACHMENT_FRONT_LEFT]; - back = &xstfb->textures[ST_ATTACHMENT_BACK_LEFT]; - /* swap textures only if the front texture has been allocated */ - if (*front) { - tmp = *front; - *front = *back; - *back = tmp; - - /* the current context should validate the buffer after swapping */ - if (!xmesa_strict_invalidate) - xmesa_notify_invalid_buffer(xstfb->buffer); - } - - if (xmesa_strict_invalidate) - xmesa_check_buffer_size(xstfb->buffer); - } -} - - -void -xmesa_copy_st_framebuffer(struct st_framebuffer_iface *stfbi, - enum st_attachment_type src, - enum st_attachment_type dst, - int x, int y, int w, int h) -{ - xmesa_st_framebuffer_copy_textures(stfbi, src, dst, x, y, w, h); - if (dst == ST_ATTACHMENT_FRONT_LEFT) - xmesa_st_framebuffer_display(stfbi, dst); -} - - -struct pipe_resource* -xmesa_get_attachment(struct st_framebuffer_iface *stfbi, - enum st_attachment_type st_attachment) -{ - struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); - struct pipe_resource *res; - - res = xstfb->textures[st_attachment]; - return res; -} - - -struct pipe_context* -xmesa_get_context(struct st_framebuffer_iface *stfbi) -{ - struct pipe_context *pipe; - struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); - - pipe = xstfb->display->pipe; - if (!pipe) { - pipe = xstfb->screen->context_create(xstfb->screen, NULL, 0); - if (!pipe) - return NULL; - xstfb->display->pipe = pipe; - } - return pipe; -} diff --git a/src/gallium/state_trackers/glx/xlib/xm_st.h b/src/gallium/state_trackers/glx/xlib/xm_st.h deleted file mode 100644 index 0a15afcd77c..00000000000 --- a/src/gallium/state_trackers/glx/xlib/xm_st.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Mesa 3-D graphics library - * - * Copyright (C) 2010 LunarG Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * Chia-I Wu - */ - -#ifndef _XM_ST_H_ -#define _XM_ST_H_ - -#include "pipe/p_compiler.h" -#include "state_tracker/st_api.h" - -#include "xm_api.h" - -struct st_framebuffer_iface * -xmesa_create_st_framebuffer(XMesaDisplay xmdpy, XMesaBuffer b); - -void -xmesa_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi); - -struct pipe_resource * -xmesa_get_framebuffer_resource(struct st_framebuffer_iface *stfbi, - enum st_attachment_type att); - -void -xmesa_swap_st_framebuffer(struct st_framebuffer_iface *stfbi); - -void -xmesa_copy_st_framebuffer(struct st_framebuffer_iface *stfbi, - enum st_attachment_type src, - enum st_attachment_type dst, - int x, int y, int w, int h); - -struct pipe_resource* -xmesa_get_attachment(struct st_framebuffer_iface *stfbi, - enum st_attachment_type st_attachment); - -struct pipe_context* -xmesa_get_context(struct st_framebuffer_iface* stfbi); - -bool -xmesa_st_framebuffer_validate_textures(struct st_framebuffer_iface *stfbi, - unsigned width, unsigned height, - unsigned mask); -#endif /* _XM_ST_H_ */ diff --git a/src/gallium/state_trackers/hgl/.editorconfig b/src/gallium/state_trackers/hgl/.editorconfig deleted file mode 100644 index f391def61c9..00000000000 --- a/src/gallium/state_trackers/hgl/.editorconfig +++ /dev/null @@ -1,2 +0,0 @@ -[*.{c,h,cpp,hpp}] -indent_style = tab diff --git a/src/gallium/state_trackers/hgl/bitmap_wrapper.cpp b/src/gallium/state_trackers/hgl/bitmap_wrapper.cpp deleted file mode 100644 index ef81edc8a57..00000000000 --- a/src/gallium/state_trackers/hgl/bitmap_wrapper.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 Artur Wyszynski - * Copyright 2013 Alexander von Gluck IV - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - **************************************************************************/ - - -#include -#include -#include -#include -#include -#include - -#include "bitmap_wrapper.h" - - -extern "C" { -static int frameNo = 0; - - -Bitmap* -create_bitmap(int32 width, int32 height, color_space colorSpace) -{ - BBitmap *bb = new BBitmap(BRect(0, 0, width, height), colorSpace); - if (bb) - return (Bitmap*)bb; - return NULL; -} - - -void -get_bitmap_size(const Bitmap* bitmap, int32* width, int32* height) -{ - BBitmap *bb = (BBitmap*)bitmap; - if (bb && width && height) { - uint32 w = bb->Bounds().IntegerWidth() + 1; - uint32 h = bb->Bounds().IntegerHeight() + 1; - *width = w; - *height = h; - } -} - - -color_space -get_bitmap_color_space(const Bitmap* bitmap) -{ - BBitmap *bb = (BBitmap*)bitmap; - if (bb) - return bb->ColorSpace(); - return B_NO_COLOR_SPACE; -} - - -void -copy_bitmap_bits(const Bitmap* bitmap, void* data, int32 length) -{ - BBitmap *bb = (BBitmap*)bitmap; - - // We assume the data is 1:1 the format of the bitmap - if (bb) - bb->ImportBits(data, length, bb->BytesPerRow(), 0, bb->ColorSpace()); -} - - -void -import_bitmap_bits(const Bitmap* bitmap, void* data, int32 length, - unsigned srcStride, color_space srcColorSpace) -{ - BBitmap *bb = (BBitmap*)bitmap; - - // Import image and adjust image format from source to dest - if (bb) - bb->ImportBits(data, length, srcStride, 0, srcColorSpace); -} - - -void -delete_bitmap(Bitmap* bitmap) -{ - BBitmap *bb = (BBitmap*)bitmap; - delete bb; -} - - -int32 -get_bitmap_bytes_per_row(const Bitmap* bitmap) -{ - BBitmap *bb = (BBitmap*)bitmap; - if (bb) - return bb->BytesPerRow(); - return 0; -} - - -int32 -get_bitmap_bits_length(const Bitmap* bitmap) -{ - BBitmap *bb = (BBitmap*)bitmap; - if (bb) - return bb->BitsLength(); - return 0; -} - - -void -dump_bitmap(const Bitmap* bitmap) -{ - BBitmap *bb = (BBitmap*)bitmap; - if (!bb) - return; - - BString filename("/boot/home/frame_"); - filename << (int32)frameNo << ".png"; - - BTranslatorRoster *roster = BTranslatorRoster::Default(); - BBitmapStream stream(bb); - BFile dump(filename, B_CREATE_FILE | B_WRITE_ONLY); - - roster->Translate(&stream, NULL, NULL, &dump, 0); - - frameNo++; -} - -} diff --git a/src/gallium/state_trackers/hgl/bitmap_wrapper.h b/src/gallium/state_trackers/hgl/bitmap_wrapper.h deleted file mode 100644 index 65ba14044d8..00000000000 --- a/src/gallium/state_trackers/hgl/bitmap_wrapper.h +++ /dev/null @@ -1,62 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 Artur Wyszynski - * Copyright 2013 Alexander von Gluck IV - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - **************************************************************************/ -#ifndef __BBITMAP_WRAPPER_H__ -#define __BBITMAP_WRAPPER_H__ - - -#include -#include - - -typedef void Bitmap; - -#ifdef __cplusplus -extern "C" { -#endif - - -Bitmap* create_bitmap(int32 width, int32 height, color_space colorSpace); -void delete_bitmap(Bitmap* bitmap); - -void copy_bitmap_bits(const Bitmap* bitmap, void* data, int32 length); -void import_bitmap_bits(const Bitmap* bitmap, void* data, int32 length, - unsigned srcStride, color_space srcColorSpace); - -void get_bitmap_size(const Bitmap* bitmap, int32* width, int32* height); -color_space get_bitmap_color_space(const Bitmap* bitmap); -int32 get_bitmap_bytes_per_row(const Bitmap* bitmap); -int32 get_bitmap_bits_length(const Bitmap* bitmap); - -void dump_bitmap(const Bitmap* bitmap); - - -#ifdef __cplusplus -} -#endif - - -#endif /* __BBITMAP_WRAPPER_H__ */ diff --git a/src/gallium/state_trackers/hgl/hgl.c b/src/gallium/state_trackers/hgl/hgl.c deleted file mode 100644 index f7dc7a6d3db..00000000000 --- a/src/gallium/state_trackers/hgl/hgl.c +++ /dev/null @@ -1,362 +0,0 @@ -/* - * Copyright 2012-2014, Haiku, Inc. All Rights Reserved. - * Distributed under the terms of the MIT License. - * - * Authors: - * Artur Wyszynski, harakash@gmail.com - * Alexander von Gluck IV, kallisti5@unixzen.com - */ - -#include "hgl_context.h" - -#include - -#include "pipe/p_format.h" -#include "util/u_atomic.h" -#include "util/format/u_format.h" -#include "util/u_memory.h" -#include "util/u_inlines.h" -#include "state_tracker/st_gl_api.h" /* for st_gl_api_create */ - -#include "GLView.h" - - -#ifdef DEBUG -# define TRACE(x...) printf("hgl:state_tracker: " x) -# define CALLED() TRACE("CALLED: %s\n", __PRETTY_FUNCTION__) -#else -# define TRACE(x...) -# define CALLED() -#endif -#define ERROR(x...) printf("hgl:state_tracker: " x) - - -// Perform a safe void to hgl_context cast -static inline struct hgl_context* -hgl_st_context(struct st_context_iface *stctxi) -{ - struct hgl_context* context; - assert(stctxi); - context = (struct hgl_context*)stctxi->st_manager_private; - assert(context); - return context; -} - - -// Perform a safe void to hgl_buffer cast -//static inline struct hgl_buffer* -struct hgl_buffer* -hgl_st_framebuffer(struct st_framebuffer_iface *stfbi) -{ - struct hgl_buffer* buffer; - assert(stfbi); - buffer = (struct hgl_buffer*)stfbi->st_manager_private; - assert(buffer); - return buffer; -} - - -static bool -hgl_st_framebuffer_flush_front(struct st_context_iface *stctxi, - struct st_framebuffer_iface* stfbi, enum st_attachment_type statt) -{ - CALLED(); - - //struct hgl_context* context = hgl_st_context(stctxi); - // struct hgl_buffer* buffer = hgl_st_context(stfbi); - struct hgl_buffer* buffer = hgl_st_framebuffer(stfbi); - //buffer->surface - - #if 0 - struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb); - mtx_lock(&stwfb->fb->mutex); - - struct pipe_resource* resource = textures[statt]; - if (resource) - stw_framebuffer_present_locked(...); - #endif - - return true; -} - - -static bool -hgl_st_framebuffer_validate_textures(struct st_framebuffer_iface *stfbi, - unsigned width, unsigned height, unsigned mask) -{ - struct hgl_buffer* buffer; - enum st_attachment_type i; - struct pipe_resource templat; - - CALLED(); - - buffer = hgl_st_framebuffer(stfbi); - - if (buffer->width != width || buffer->height != height) { - for (i = 0; i < ST_ATTACHMENT_COUNT; i++) - pipe_resource_reference(&buffer->textures[i], NULL); - } - - memset(&templat, 0, sizeof(templat)); - templat.target = buffer->target; - templat.width0 = width; - templat.height0 = height; - templat.depth0 = 1; - templat.array_size = 1; - templat.last_level = 0; - - for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { - enum pipe_format format; - unsigned bind; - - switch (i) { - case ST_ATTACHMENT_FRONT_LEFT: - case ST_ATTACHMENT_BACK_LEFT: - case ST_ATTACHMENT_FRONT_RIGHT: - case ST_ATTACHMENT_BACK_RIGHT: - format = buffer->visual->color_format; - bind = PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_RENDER_TARGET; - break; - case ST_ATTACHMENT_DEPTH_STENCIL: - format = buffer->visual->depth_stencil_format; - bind = PIPE_BIND_DEPTH_STENCIL; - break; - default: - format = PIPE_FORMAT_NONE; - bind = 0; - break; - } - - if (format != PIPE_FORMAT_NONE) { - templat.format = format; - templat.bind = bind; - buffer->textures[i] = buffer->screen->resource_create(buffer->screen, - &templat); - if (!buffer->textures[i]) - return FALSE; - } - } - - buffer->width = width; - buffer->height = height; - buffer->mask = mask; - - return true; -} - - -/** - * Called by the st manager to validate the framebuffer (allocate - * its resources). - */ -static bool -hgl_st_framebuffer_validate(struct st_context_iface *stctxi, - struct st_framebuffer_iface *stfbi, const enum st_attachment_type *statts, - unsigned count, struct pipe_resource **out) -{ - struct hgl_context* context; - struct hgl_buffer* buffer; - unsigned stAttachmentMask, newMask; - unsigned i; - bool resized; - - CALLED(); - - context = hgl_st_context(stctxi); - buffer = hgl_st_framebuffer(stfbi); - - //int32 width = 0; - //int32 height = 0; - //get_bitmap_size(context->bitmap, &width, &height); - - // Build mask of current attachments - stAttachmentMask = 0; - for (i = 0; i < count; i++) - stAttachmentMask |= 1 << statts[i]; - - newMask = stAttachmentMask & ~buffer->mask; - - resized = (buffer->width != context->width) - || (buffer->height != context->height); - - if (resized || newMask) { - boolean ret; - TRACE("%s: resize event. old: %d x %d; new: %d x %d\n", __func__, - buffer->width, buffer->height, context->width, context->height); - - ret = hgl_st_framebuffer_validate_textures(stfbi, - context->width, context->height, stAttachmentMask); - - if (!ret) - return ret; - - // TODO: Simply update attachments - //if (!resized) { - - //} - } - - for (i = 0; i < count; i++) - pipe_resource_reference(&out[i], buffer->textures[statts[i]]); - - return true; -} - - -static int -hgl_st_manager_get_param(struct st_manager *smapi, enum st_manager_param param) -{ - CALLED(); - - switch (param) { - case ST_MANAGER_BROKEN_INVALIDATE: - return 1; - } - - return 0; -} - - -/** - * Create new framebuffer - */ -struct hgl_buffer * -hgl_create_st_framebuffer(struct hgl_context* context) -{ - struct hgl_buffer *buffer; - CALLED(); - - // Our requires before creating a framebuffer - assert(context); - assert(context->screen); - assert(context->stVisual); - - buffer = CALLOC_STRUCT(hgl_buffer); - assert(buffer); - - // calloc and configure our st_framebuffer interface - buffer->stfbi = CALLOC_STRUCT(st_framebuffer_iface); - assert(buffer->stfbi); - - // Prepare our buffer - buffer->visual = context->stVisual; - buffer->screen = context->screen; - - if (context->screen->get_param(buffer->screen, PIPE_CAP_NPOT_TEXTURES)) - buffer->target = PIPE_TEXTURE_2D; - else - buffer->target = PIPE_TEXTURE_RECT; - - // Prepare our state_tracker interface - buffer->stfbi->flush_front = hgl_st_framebuffer_flush_front; - buffer->stfbi->validate = hgl_st_framebuffer_validate; - buffer->stfbi->visual = context->stVisual; - - p_atomic_set(&buffer->stfbi->stamp, 1); - buffer->stfbi->st_manager_private = (void*)buffer; - - return buffer; -} - - -struct st_api* -hgl_create_st_api() -{ - CALLED(); - return st_gl_api_create(); -} - - -struct st_manager * -hgl_create_st_manager(struct hgl_context* context) -{ - struct st_manager* manager; - - CALLED(); - - // Required things - assert(context); - assert(context->screen); - - manager = CALLOC_STRUCT(st_manager); - assert(manager); - - //manager->display = dpy; - manager->screen = context->screen; - manager->get_param = hgl_st_manager_get_param; - manager->st_manager_private = (void *)context; - - return manager; -} - - -void -hgl_destroy_st_manager(struct st_manager *manager) -{ - CALLED(); - - FREE(manager); -} - - -struct st_visual* -hgl_create_st_visual(ulong options) -{ - struct st_visual* visual; - - CALLED(); - - visual = CALLOC_STRUCT(st_visual); - assert(visual); - - // Determine color format - if ((options & BGL_INDEX) != 0) { - // Index color - visual->color_format = PIPE_FORMAT_B5G6R5_UNORM; - // TODO: Indexed color depth buffer? - visual->depth_stencil_format = PIPE_FORMAT_NONE; - } else { - // RGB color - visual->color_format = (options & BGL_ALPHA) - ? PIPE_FORMAT_BGRA8888_UNORM : PIPE_FORMAT_BGRX8888_UNORM; - // TODO: Determine additional stencil formats - visual->depth_stencil_format = (options & BGL_DEPTH) - ? PIPE_FORMAT_Z24_UNORM_S8_UINT : PIPE_FORMAT_NONE; - } - - visual->accum_format = (options & BGL_ACCUM) - ? PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE; - - visual->buffer_mask |= ST_ATTACHMENT_FRONT_LEFT_MASK; - visual->render_buffer = ST_ATTACHMENT_FRONT_LEFT; - - if ((options & BGL_DOUBLE) != 0) { - visual->buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK; - visual->render_buffer = ST_ATTACHMENT_BACK_LEFT; - } - - #if 0 - if ((options & BGL_STEREO) != 0) { - visual->buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK; - if ((options & BGL_DOUBLE) != 0) - visual->buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK; - } - #endif - - if ((options & BGL_DEPTH) || (options & BGL_STENCIL)) - visual->buffer_mask |= ST_ATTACHMENT_DEPTH_STENCIL_MASK; - - TRACE("%s: Visual color format: %s\n", __func__, - util_format_name(visual->color_format)); - - return visual; -} - - -void -hgl_destroy_st_visual(struct st_visual* visual) -{ - CALLED(); - - FREE(visual); -} diff --git a/src/gallium/state_trackers/hgl/hgl_context.h b/src/gallium/state_trackers/hgl/hgl_context.h deleted file mode 100644 index e2ebfbad4bc..00000000000 --- a/src/gallium/state_trackers/hgl/hgl_context.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright 2009-2014, Haiku, Inc. All Rights Reserved. - * Distributed under the terms of the MIT License. - * - * Authors: - * Alexander von Gluck IV, kallisti5@unixzen.com - */ -#ifndef HGL_CONTEXT_H -#define HGL_CONTEXT_H - - -#include "pipe/p_format.h" -#include "pipe/p_compiler.h" -#include "pipe/p_screen.h" -#include "postprocess/filters.h" - -#include "state_tracker/st_api.h" -#include "state_tracker/st_manager.h" -#include "os/os_thread.h" - -#include "bitmap_wrapper.h" - - -#ifdef __cplusplus -extern "C" { -#endif - - -#define CONTEXT_MAX 32 - -typedef int64 context_id; - - -struct hgl_buffer -{ - struct st_framebuffer_iface *stfbi; - struct st_visual* visual; - - unsigned width; - unsigned height; - unsigned mask; - - struct pipe_screen* screen; - struct pipe_surface* surface; - - enum pipe_texture_target target; - struct pipe_resource* textures[ST_ATTACHMENT_COUNT]; - - void *map; - - //struct hgl_buffer *next; /**< next in linked list */ -}; - - -struct hgl_context -{ - struct st_api* api; - // State Tracker API - struct st_manager* manager; - // State Tracker Manager - struct st_context_iface* st; - // State Tracker Interface Object - struct st_visual* stVisual; - // State Tracker Visual - - struct pipe_screen* screen; - - //struct pipe_resource* textures[ST_ATTACHMENT_COUNT]; - - // Post processing - struct pp_queue_t* postProcess; - unsigned int postProcessEnable[PP_FILTERS]; - - // Desired viewport size - unsigned width; - unsigned height; - - Bitmap* bitmap; - color_space colorSpace; - - mtx_t fbMutex; - - struct hgl_buffer* draw; - struct hgl_buffer* read; -}; - -// hgl_buffer from statetracker interface -struct hgl_buffer* hgl_st_framebuffer(struct st_framebuffer_iface *stfbi); - -// hgl state_tracker api -struct st_api* hgl_create_st_api(void); - -// hgl state_tracker framebuffer -struct hgl_buffer* hgl_create_st_framebuffer(struct hgl_context* context); - -// hgl state_tracker manager -struct st_manager* hgl_create_st_manager(struct hgl_context* screen); -void hgl_destroy_st_manager(struct st_manager *manager); - -// hgl state_tracker visual -struct st_visual* hgl_create_st_visual(ulong options); -void hgl_destroy_st_visual(struct st_visual* visual); - - -#ifdef __cplusplus -} -#endif - -#endif /* HGL_CONTEXT_H */ diff --git a/src/gallium/state_trackers/hgl/meson.build b/src/gallium/state_trackers/hgl/meson.build deleted file mode 100644 index 3c5870fe101..00000000000 --- a/src/gallium/state_trackers/hgl/meson.build +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright © 2017 Dylan Baker - -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: - -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. - -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -files_libsthgl = files( - 'bitmap_wrapper.cpp', - 'bitmap_wrapper.h', - 'hgl_context.h', - 'hgl.c', -) - -libsthgl_c_args = [] -if with_gallium_softpipe - libsthgl_c_args += '-DGALLIUM_SOFTPIPE' -endif - -libsthgl = static_library( - 'sthgl', - files_libsthgl, - include_directories : [ - inc_include, inc_haikugl, inc_util, inc_mesa, inc_mapi, inc_src, - inc_gallium, inc_gallium_aux - ], - c_args : [c_vis_args, libsthgl_c_args], -) diff --git a/src/gallium/state_trackers/nine/.editorconfig b/src/gallium/state_trackers/nine/.editorconfig deleted file mode 100644 index 7b12a40ca00..00000000000 --- a/src/gallium/state_trackers/nine/.editorconfig +++ /dev/null @@ -1,3 +0,0 @@ -[*.{c,h}] -indent_style = space -indent_size = 4 diff --git a/src/gallium/state_trackers/nine/Makefile.sources b/src/gallium/state_trackers/nine/Makefile.sources deleted file mode 100644 index 56698a19f10..00000000000 --- a/src/gallium/state_trackers/nine/Makefile.sources +++ /dev/null @@ -1,82 +0,0 @@ -C_SOURCES := \ - adapter9.c \ - adapter9.h \ - authenticatedchannel9.c \ - authenticatedchannel9.h \ - basetexture9.c \ - basetexture9.h \ - buffer9.c \ - buffer9.h \ - cryptosession9.c \ - cryptosession9.h \ - cubetexture9.c \ - cubetexture9.h \ - device9.c \ - device9.h \ - device9ex.c \ - device9ex.h \ - device9video.c \ - device9video.h \ - guid.c \ - guid.h \ - indexbuffer9.c \ - indexbuffer9.h \ - iunknown.c \ - iunknown.h \ - nine_buffer_upload.c \ - nine_buffer_upload.h \ - nine_csmt_helper.h \ - nine_debug.c \ - nine_debug.h \ - nine_defines.h \ - nine_dump.c \ - nine_dump.h \ - nineexoverlayextension.c \ - nineexoverlayextension.h \ - nine_ff.c \ - nine_ff.h \ - nine_flags.h \ - nine_helpers.c \ - nine_helpers.h \ - nine_limits.h \ - nine_lock.c \ - nine_lock.h \ - nine_pdata.h \ - nine_pipe.c \ - nine_pipe.h \ - nine_quirk.c \ - nine_quirk.h \ - nine_queue.c \ - nine_queue.h \ - nine_shader.c \ - nine_shader.h \ - nine_state.c \ - nine_state.h \ - pixelshader9.c \ - pixelshader9.h \ - query9.c \ - query9.h \ - resource9.c \ - resource9.h \ - stateblock9.c \ - stateblock9.h \ - surface9.c \ - surface9.h \ - swapchain9.c \ - swapchain9ex.c \ - swapchain9ex.h \ - swapchain9.h \ - texture9.c \ - texture9.h \ - threadpool.c \ - threadpool.h \ - vertexbuffer9.c \ - vertexbuffer9.h \ - vertexdeclaration9.c \ - vertexdeclaration9.h \ - vertexshader9.c \ - vertexshader9.h \ - volume9.c \ - volume9.h \ - volumetexture9.c \ - volumetexture9.h diff --git a/src/gallium/state_trackers/nine/README b/src/gallium/state_trackers/nine/README deleted file mode 100644 index 34e928d4da3..00000000000 --- a/src/gallium/state_trackers/nine/README +++ /dev/null @@ -1,77 +0,0 @@ -Quickstart Guide - -*** Configure and build mesa -CFLAGS="-m32" CXXFLAGS="-m32" ./autogen.sh --prefix=/usr \ - --with-gallium-drivers=nouveau,r600,swrast --enable-nine \ - --enable-debug --enable-texture-float --with-dri-drivers= --disable-dri \ - --disable-opengl --disable-egl --disable-vdpau --disable-xvmc --disable-gbm \ - --disable-llvm -make - -*** Then we create some symlinks to mesa: -ln -s "`pwd`/lib/gallium/libd3dadapter9.so.0.0.0" /usr/lib/ -ln -s "`pwd`/lib/gallium/libd3dadapter9.so.0" /usr/lib/ -ln -s "`pwd`/lib/gallium/libd3dadapter9.so" /usr/lib/ -ln -s "`pwd`/include/d3dadapter" /usr/include/ - -*** Clone and build a patched wine -git clone git@github.com:iXit/wine.git -./configure -make - -*** And finally we create some symlinks to our patched wine files: -for f in d3d9.dll gdi32.dll user32.dll wineps.drv winex11.drv; -do - mv /usr/lib/wine/$f.so /usr/lib/wine/$f.so.old - ln -s "`pwd`/dlls/`basename -s .dll $f`/$f.so" /usr/lib/wine/ -done - -*** Activating it within wine -regedit -Navigate to HKCU\Software\Wine\Direct3D -If it's not there, create it -Create a new DWORD value called UseNative -Set its value to 1 - -Every Direct3D9 program will now try using nine before wined3d - -If you want to selectively enable it per-exe instead, use the key: -HKCU\Software\Wine\AppDefaults\app.exe\Direct3D\UseNative -where app.exe is the name of your .exe file - - -*** HOW IT WORKS *** - -Nine implements the full IDirect3DDevice9 COM interface and a custom COM -interface called ID3DAdapter9 which is used to implement a final IDirect3D9Ex -COM interface. -ID3DAdapter9 is completely devoid of window system code, meaning this can be -provided by wine, Xlib, Wayland, etc. It's inadvisible to write a non-Windows -backend though, as we don't want to encourage linux developers to use this API. - -The state tracker is compiled, along with pipe-loader, into a library called -libd3dadapter9.so. This library loads pipe_[driver].so drivers on demand and -exports a single symbol for getting a subsystem driver. Currently only DRM is -supported. -This library is then linked to the library implementing the IDirect3D9[Ex] -interface and the actual Direct3D9 entry points (Direct3DCreate9[Ex]) - -The implementation of IDirect3D9[Ex] lies within wine and coexists with -wined3d. It's loaded on demand and so if it's not there, it doesn't have any -drivers or something else is wrong, d3d9.dll will automatically revert to using -wined3d. -Whether or not it's even tried is determined by 2 DWORD registry keys. -> HKCU\Software\Wine\Direct3D\UseNative -> HKCU\Software\Wine\AppDefaults\app.exe\Direct3D\UseNative -The former is the global on-switch. The latter is per-exe. - -The driver search path can be set at configure time with ---with-gallium-driver-dir and overridden at runtime with D3D9_DRIVERS_PATH. -Debugging information can be gotten with the WINEDEBUG channels d3d9 and -d3dadapter, and state_tracker debug information can be gotten with NINE_DEBUG. -Help on NINE_DEBUG is shown through NINE_DEBUG=help - -Finally, the ID3DPresent[Group] and ID3DAdapter9 interfaces are not set in -stone, so feel free to hack on those as well as st/nine. - -Happy Hacking! diff --git a/src/gallium/state_trackers/nine/adapter9.c b/src/gallium/state_trackers/nine/adapter9.c deleted file mode 100644 index e8d4697986c..00000000000 --- a/src/gallium/state_trackers/nine/adapter9.c +++ /dev/null @@ -1,1128 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "adapter9.h" -#include "device9ex.h" -#include "nine_helpers.h" -#include "nine_defines.h" -#include "nine_pipe.h" -#include "nine_dump.h" -#include "util/u_math.h" -#include "util/format/u_format.h" -#include "util/u_dump.h" - -#include "pipe/p_screen.h" - -#define DBG_CHANNEL DBG_ADAPTER - -static bool -has_sm3(struct pipe_screen *hal) -{ - return hal->get_param(hal, PIPE_CAP_FRAGMENT_SHADER_TEXTURE_LOD) && - hal->get_param(hal, PIPE_CAP_FRAGMENT_SHADER_DERIVATIVES) && - hal->get_param(hal, PIPE_CAP_VERTEX_SHADER_SATURATE); -} - -HRESULT -NineAdapter9_ctor( struct NineAdapter9 *This, - struct NineUnknownParams *pParams, - struct d3dadapter9_context *pCTX ) -{ - struct pipe_screen *hal = pCTX->hal; - HRESULT hr = NineUnknown_ctor(&This->base, pParams); - if (FAILED(hr)) { return hr; } - - DBG("This=%p pParams=%p pCTX=%p\n", This, pParams, pCTX); - nine_dump_D3DADAPTER_IDENTIFIER9(DBG_CHANNEL, &pCTX->identifier); - - This->ctx = pCTX; - if (!hal->get_param(hal, PIPE_CAP_CLIP_HALFZ)) { - ERR("Driver doesn't support d3d9 coordinates\n"); - return D3DERR_DRIVERINTERNALERROR; - } - if (This->ctx->ref && - !This->ctx->ref->get_param(This->ctx->ref, PIPE_CAP_CLIP_HALFZ)) { - ERR("Warning: Sotware rendering driver doesn't support d3d9 coordinates\n"); - } - /* Old cards had tricks to bypass some restrictions to implement - * everything and fit tight the requirements: number of constants, - * number of temp registers, special behaviours, etc. Since we don't - * have access to all this, we need a bit more than what dx9 required. - * For example we have to use more than 32 temp registers to emulate - * behaviours, while some dx9 hw don't have more. As for sm2 hardware, - * we could support vs2 / ps2 for them but it needs some more care, and - * as these are very old, we choose to drop support for them */ - - /* checks minimum requirements, most are vs3/ps3 strict requirements */ - if (!has_sm3(hal) || - hal->get_shader_param(hal, PIPE_SHADER_VERTEX, - PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE) < 256 * sizeof(float[4]) || - hal->get_shader_param(hal, PIPE_SHADER_FRAGMENT, - PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE) < 244 * sizeof(float[4]) || - hal->get_shader_param(hal, PIPE_SHADER_VERTEX, - PIPE_SHADER_CAP_MAX_TEMPS) < 32 || - hal->get_shader_param(hal, PIPE_SHADER_FRAGMENT, - PIPE_SHADER_CAP_MAX_TEMPS) < 32 || - hal->get_shader_param(hal, PIPE_SHADER_VERTEX, - PIPE_SHADER_CAP_MAX_INPUTS) < 16 || - hal->get_shader_param(hal, PIPE_SHADER_FRAGMENT, - PIPE_SHADER_CAP_MAX_INPUTS) < 10 || - hal->get_shader_param(hal, PIPE_SHADER_FRAGMENT, - PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS) < 16) { - ERR("Your card is not supported by Gallium Nine. Minimum requirement " - "is >= r500, >= nv50, >= i965\n"); - return D3DERR_DRIVERINTERNALERROR; - } - /* for r500 */ - if (hal->get_shader_param(hal, PIPE_SHADER_VERTEX, - PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE) < 276 * sizeof(float[4]) || /* we put bool and int constants with float constants */ - hal->get_shader_param(hal, PIPE_SHADER_VERTEX, - PIPE_SHADER_CAP_MAX_TEMPS) < 40 || /* we use some more temp registers */ - hal->get_shader_param(hal, PIPE_SHADER_FRAGMENT, - PIPE_SHADER_CAP_MAX_TEMPS) < 40 || - hal->get_shader_param(hal, PIPE_SHADER_FRAGMENT, - PIPE_SHADER_CAP_MAX_INPUTS) < 20) /* we don't pack inputs as much as we could */ - ERR("Your card is at the limit of Gallium Nine requirements. Some games " - "may run into issues because requirements are too tight\n"); - return D3D_OK; -} - -void -NineAdapter9_dtor( struct NineAdapter9 *This ) -{ - struct d3dadapter9_context *ctx = This->ctx; - - DBG("This=%p\n", This); - - NineUnknown_dtor(&This->base); - - /* special case, call backend-specific dtor AFTER destroying this object - * completely. */ - if (ctx) { - if (ctx->destroy) { ctx->destroy(ctx); } - } -} - -static HRESULT -NineAdapter9_GetScreen( struct NineAdapter9 *This, - D3DDEVTYPE DevType, - struct pipe_screen **ppScreen ) -{ - const char *force_sw = getenv("D3D_ALWAYS_SOFTWARE"); - switch (DevType) { - case D3DDEVTYPE_HAL: - if (force_sw && !strcmp(force_sw, "1") && This->ctx->ref) { - *ppScreen = This->ctx->ref; - break; - } - *ppScreen = This->ctx->hal; - break; - - case D3DDEVTYPE_REF: - case D3DDEVTYPE_NULLREF: - case D3DDEVTYPE_SW: - if (force_sw && !strcmp(force_sw, "0")) { - *ppScreen = This->ctx->hal; - break; - } - *ppScreen = This->ctx->ref; - break; - - default: - user_assert(!"Invalid device type", D3DERR_INVALIDCALL); - } - - if (!*ppScreen) { return D3DERR_NOTAVAILABLE; } - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineAdapter9_GetAdapterIdentifier( struct NineAdapter9 *This, - DWORD Flags, - D3DADAPTER_IDENTIFIER9 *pIdentifier ) -{ - DBG("This=%p Flags=%x pIdentifier=%p\n", This, Flags, pIdentifier); - - /* regarding flags, MSDN has this to say: - * Flags sets the WHQLLevel member of D3DADAPTER_IDENTIFIER9. Flags can be - * set to either 0 or D3DENUM_WHQL_LEVEL. If D3DENUM_WHQL_LEVEL is - * specified, this call can connect to the Internet to download new - * Microsoft Windows Hardware Quality Labs (WHQL) certificates. - * so let's just ignore it. */ - *pIdentifier = This->ctx->identifier; - return D3D_OK; -} - -static inline boolean -backbuffer_format( D3DFORMAT dfmt, - D3DFORMAT bfmt, - boolean win ) -{ - if (dfmt == D3DFMT_A2R10G10B10 && win) { return FALSE; } - - if ((dfmt == D3DFMT_A2R10G10B10 && bfmt == dfmt) || - (dfmt == D3DFMT_X8R8G8B8 && (bfmt == dfmt || - bfmt == D3DFMT_A8R8G8B8)) || - (dfmt == D3DFMT_X1R5G5B5 && (bfmt == dfmt || - bfmt == D3DFMT_A1R5G5B5)) || - (dfmt == D3DFMT_R5G6B5 && bfmt == dfmt)) { - return TRUE; - } - - return FALSE; -} - -HRESULT NINE_WINAPI -NineAdapter9_CheckDeviceType( struct NineAdapter9 *This, - D3DDEVTYPE DevType, - D3DFORMAT AdapterFormat, - D3DFORMAT BackBufferFormat, - BOOL bWindowed ) -{ - struct pipe_screen *screen; - enum pipe_format dfmt, bfmt; - HRESULT hr; - - DBG("This=%p DevType=%s AdapterFormat=%s BackBufferFormat=%s " - "bWindowed=%i\n", This, nine_D3DDEVTYPE_to_str(DevType), - d3dformat_to_string(AdapterFormat), - d3dformat_to_string(BackBufferFormat), bWindowed); - - user_assert(backbuffer_format(AdapterFormat, BackBufferFormat, bWindowed), - D3DERR_NOTAVAILABLE); - - hr = NineAdapter9_GetScreen(This, DevType, &screen); - if (FAILED(hr)) { return hr; } - - /* The display format is not handled in Nine. We always present an XRGB8888 - * buffer (and the display server will eventually do the conversion). We probably - * don't need to check for anything for the adapter format support, since if the - * display server advertise support, it will likely be able to do the conversion. - * We do the approximation that a format is available in the display server if - * the format passes with NINE_BIND_BACKBUFFER_FLAGS */ - dfmt = d3d9_to_pipe_format_checked(screen, AdapterFormat, PIPE_TEXTURE_2D, - 1, - NINE_BIND_BACKBUFFER_FLAGS, FALSE, FALSE); - bfmt = d3d9_to_pipe_format_checked(screen, BackBufferFormat, PIPE_TEXTURE_2D, - 1, - NINE_BIND_BACKBUFFER_FLAGS, FALSE, FALSE); - if (dfmt == PIPE_FORMAT_NONE || bfmt == PIPE_FORMAT_NONE) { - DBG("Unsupported Adapter/BackBufferFormat.\n"); - return D3DERR_NOTAVAILABLE; - } - - return D3D_OK; -} - -static inline boolean -display_format( D3DFORMAT fmt, - boolean win ) -{ - /* http://msdn.microsoft.com/en-us/library/bb172558(v=VS.85).aspx#BackBuffer_or_Display_Formats */ - static const D3DFORMAT allowed[] = { - D3DFMT_A2R10G10B10, - D3DFMT_X8R8G8B8, - D3DFMT_X1R5G5B5, - D3DFMT_R5G6B5, - }; - unsigned i; - - if (fmt == D3DFMT_A2R10G10B10 && win) { return FALSE; } - - for (i = 0; i < sizeof(allowed)/sizeof(D3DFORMAT); i++) { - if (fmt == allowed[i]) { return TRUE; } - } - return FALSE; -} - -HRESULT NINE_WINAPI -NineAdapter9_CheckDeviceFormat( struct NineAdapter9 *This, - D3DDEVTYPE DeviceType, - D3DFORMAT AdapterFormat, - DWORD Usage, - D3DRESOURCETYPE RType, - D3DFORMAT CheckFormat ) -{ - struct pipe_screen *screen; - HRESULT hr; - enum pipe_format pf; - enum pipe_texture_target target; - unsigned bind = 0; - boolean srgb; - - /* Check adapter format. */ - - DBG("This=%p DeviceType=%s AdapterFormat=%s\n", This, - nine_D3DDEVTYPE_to_str(DeviceType), d3dformat_to_string(AdapterFormat)); - DBG("Usage=%x RType=%u CheckFormat=%s\n", Usage, RType, - d3dformat_to_string(CheckFormat)); - - user_assert(display_format(AdapterFormat, FALSE), D3DERR_INVALIDCALL); - - hr = NineAdapter9_GetScreen(This, DeviceType, &screen); - if (FAILED(hr)) - return hr; - pf = d3d9_to_pipe_format_checked(screen, AdapterFormat, PIPE_TEXTURE_2D, 0, - PIPE_BIND_DISPLAY_TARGET | - PIPE_BIND_SHARED, FALSE, FALSE); - if (pf == PIPE_FORMAT_NONE) { - DBG("AdapterFormat %s not available.\n", - d3dformat_to_string(AdapterFormat)); - return D3DERR_NOTAVAILABLE; - } - - /* Check actual format. */ - - switch (RType) { - case D3DRTYPE_SURFACE: target = PIPE_TEXTURE_2D; break; - case D3DRTYPE_TEXTURE: target = PIPE_TEXTURE_2D; break; - case D3DRTYPE_CUBETEXTURE: target = PIPE_TEXTURE_CUBE; break; - case D3DRTYPE_VOLUME: target = PIPE_TEXTURE_3D; break; - case D3DRTYPE_VOLUMETEXTURE: target = PIPE_TEXTURE_3D; break; - case D3DRTYPE_VERTEXBUFFER: target = PIPE_BUFFER; break; - case D3DRTYPE_INDEXBUFFER: target = PIPE_BUFFER; break; - default: - user_assert(0, D3DERR_INVALIDCALL); - } - - bind = 0; - if (Usage & D3DUSAGE_RENDERTARGET) bind |= PIPE_BIND_RENDER_TARGET; - if (Usage & D3DUSAGE_DEPTHSTENCIL) { - if (!depth_stencil_format(CheckFormat)) - return D3DERR_NOTAVAILABLE; - bind |= d3d9_get_pipe_depth_format_bindings(CheckFormat); - } - - /* API hack because setting RT[0] to NULL is forbidden */ - if (CheckFormat == D3DFMT_NULL && bind == PIPE_BIND_RENDER_TARGET && - (RType == D3DRTYPE_SURFACE || - RType == D3DRTYPE_TEXTURE)) - return D3D_OK; - - /* RESZ hack */ - if (CheckFormat == D3DFMT_RESZ && bind == PIPE_BIND_RENDER_TARGET && - RType == D3DRTYPE_SURFACE) - return screen->get_param(screen, PIPE_CAP_MULTISAMPLE_Z_RESOLVE) ? - D3D_OK : D3DERR_NOTAVAILABLE; - - /* ATOC hack */ - if (CheckFormat == D3DFMT_ATOC && RType == D3DRTYPE_SURFACE) - return D3D_OK; - - if ((Usage & D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) && - (Usage & D3DUSAGE_RENDERTARGET)) - bind |= PIPE_BIND_BLENDABLE; - - if (Usage & D3DUSAGE_DMAP) { - DBG("D3DUSAGE_DMAP not available\n"); - return D3DERR_NOTAVAILABLE; /* TODO: displacement mapping */ - } - - switch (RType) { - case D3DRTYPE_TEXTURE: bind |= PIPE_BIND_SAMPLER_VIEW; break; - case D3DRTYPE_CUBETEXTURE: bind |= PIPE_BIND_SAMPLER_VIEW; break; - case D3DRTYPE_VOLUMETEXTURE: bind |= PIPE_BIND_SAMPLER_VIEW; break; - case D3DRTYPE_VERTEXBUFFER: bind |= PIPE_BIND_VERTEX_BUFFER; break; - case D3DRTYPE_INDEXBUFFER: bind |= PIPE_BIND_INDEX_BUFFER; break; - case D3DRTYPE_SURFACE: - if (!(Usage & D3DUSAGE_DEPTHSTENCIL)) - bind |= PIPE_BIND_SAMPLER_VIEW; /* StretchRect */ - /* Offscreen surface support: Usage = 0. - * In practice drivers are very restrictive on the formats supported. - * Basically a few common formats + YUV and compressed formats. The - * reason is that offscreen surface are useful only for directdraw - * compatibility (a WONTIMPL of nine) + format conversion (useful in - * particular for YUV because the format was not advertised for textures - * on NV chips). */ - if (Usage == 0) - bind |= PIPE_BIND_RENDER_TARGET; /* A current requirement of our impl, which we should get rid of. */ - default: - break; - } - - - srgb = (Usage & (D3DUSAGE_QUERY_SRGBREAD | D3DUSAGE_QUERY_SRGBWRITE)) != 0; - pf = d3d9_to_pipe_format_checked(screen, CheckFormat, target, - 0, bind, srgb, FALSE); - if (pf == PIPE_FORMAT_NONE) { - DBG("NOT AVAILABLE\n"); - return D3DERR_NOTAVAILABLE; - } - - /* we support ATI1 and ATI2 hack only for 2D and Cube textures */ - if (RType != D3DRTYPE_TEXTURE && RType != D3DRTYPE_CUBETEXTURE && - (CheckFormat == D3DFMT_ATI1 || CheckFormat == D3DFMT_ATI2)) - return D3DERR_NOTAVAILABLE; - /* if (Usage & D3DUSAGE_NONSECURE) { don't know the implications of this } */ - /* if (Usage & D3DUSAGE_SOFTWAREPROCESSING) { we can always support this } */ - - if ((Usage & D3DUSAGE_AUTOGENMIPMAP) && !(bind & PIPE_BIND_SAMPLER_VIEW)) - return D3DOK_NOAUTOGEN; - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineAdapter9_CheckDeviceMultiSampleType( struct NineAdapter9 *This, - D3DDEVTYPE DeviceType, - D3DFORMAT SurfaceFormat, - BOOL Windowed, - D3DMULTISAMPLE_TYPE MultiSampleType, - DWORD *pQualityLevels ) -{ - struct pipe_screen *screen; - HRESULT hr; - enum pipe_format pf; - unsigned bind; - - DBG("This=%p DeviceType=%s SurfaceFormat=%s Windowed=%i MultiSampleType=%u " - "pQualityLevels=%p\n", This, nine_D3DDEVTYPE_to_str(DeviceType), - d3dformat_to_string(SurfaceFormat), Windowed, MultiSampleType, - pQualityLevels); - - if (pQualityLevels) { - /* In error cases return only 1 quality level supported */ - *pQualityLevels = 1; - } - user_assert(MultiSampleType <= D3DMULTISAMPLE_16_SAMPLES, D3DERR_INVALIDCALL); - - hr = NineAdapter9_GetScreen(This, DeviceType, &screen); - if (FAILED(hr)) - return hr; - - if (depth_stencil_format(SurfaceFormat)) - bind = d3d9_get_pipe_depth_format_bindings(SurfaceFormat); - else /* render-target */ - bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; - - pf = d3d9_to_pipe_format_checked(screen, SurfaceFormat, PIPE_TEXTURE_2D, - 0, PIPE_BIND_SAMPLER_VIEW, FALSE, FALSE); - - if (pf == PIPE_FORMAT_NONE && SurfaceFormat != D3DFMT_NULL) { - DBG("%s not available.\n", d3dformat_to_string(SurfaceFormat)); - return D3DERR_INVALIDCALL; - } - - pf = d3d9_to_pipe_format_checked(screen, SurfaceFormat, PIPE_TEXTURE_2D, - MultiSampleType, bind, FALSE, FALSE); - - if (pf == PIPE_FORMAT_NONE && SurfaceFormat != D3DFMT_NULL) { - DBG("%s with %u samples not available.\n", - d3dformat_to_string(SurfaceFormat), MultiSampleType); - return D3DERR_NOTAVAILABLE; - } - - if (pQualityLevels) { - /* NONMASKABLE MultiSampleType might have more than one quality level, - * while MASKABLE MultiSampleTypes have only one level. - * Advertise quality levels and map each level to a sample count. */ - (void ) d3dmultisample_type_check(screen, SurfaceFormat, - &MultiSampleType, D3DMULTISAMPLE_16_SAMPLES, pQualityLevels); - DBG("advertising %u quality levels\n", *pQualityLevels); - } - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineAdapter9_CheckDepthStencilMatch( struct NineAdapter9 *This, - D3DDEVTYPE DeviceType, - D3DFORMAT AdapterFormat, - D3DFORMAT RenderTargetFormat, - D3DFORMAT DepthStencilFormat ) -{ - struct pipe_screen *screen; - enum pipe_format dfmt, bfmt, zsfmt; - HRESULT hr; - - DBG("This=%p DeviceType=%s AdapterFormat=%s " - "RenderTargetFormat=%s DepthStencilFormat=%s\n", This, - nine_D3DDEVTYPE_to_str(DeviceType), d3dformat_to_string(AdapterFormat), - d3dformat_to_string(RenderTargetFormat), - d3dformat_to_string(DepthStencilFormat)); - - user_assert(display_format(AdapterFormat, FALSE), D3DERR_NOTAVAILABLE); - user_assert(depth_stencil_format(DepthStencilFormat), D3DERR_NOTAVAILABLE); - - hr = NineAdapter9_GetScreen(This, DeviceType, &screen); - if (FAILED(hr)) { return hr; } - - dfmt = d3d9_to_pipe_format_checked(screen, AdapterFormat, PIPE_TEXTURE_2D, 0, - NINE_BIND_BACKBUFFER_FLAGS, FALSE, FALSE); - bfmt = d3d9_to_pipe_format_checked(screen, RenderTargetFormat, - PIPE_TEXTURE_2D, 0, - NINE_BIND_BACKBUFFER_FLAGS, FALSE, FALSE); - if (RenderTargetFormat == D3DFMT_NULL) - bfmt = dfmt; - zsfmt = d3d9_to_pipe_format_checked(screen, DepthStencilFormat, - PIPE_TEXTURE_2D, 0, - d3d9_get_pipe_depth_format_bindings(DepthStencilFormat), - FALSE, FALSE); - if (dfmt == PIPE_FORMAT_NONE || - bfmt == PIPE_FORMAT_NONE || - zsfmt == PIPE_FORMAT_NONE) { - return D3DERR_NOTAVAILABLE; - } - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineAdapter9_CheckDeviceFormatConversion( struct NineAdapter9 *This, - D3DDEVTYPE DeviceType, - D3DFORMAT SourceFormat, - D3DFORMAT TargetFormat ) -{ - /* MSDN says this tests whether a certain backbuffer format can be used in - * conjunction with a certain front buffer format. It's a little confusing - * but some one wiser might be able to figure this one out. XXX */ - struct pipe_screen *screen; - enum pipe_format dfmt, bfmt; - HRESULT hr; - - DBG("This=%p DeviceType=%s SourceFormat=%s TargetFormat=%s\n", This, - nine_D3DDEVTYPE_to_str(DeviceType), - d3dformat_to_string(SourceFormat), d3dformat_to_string(TargetFormat)); - - user_assert(backbuffer_format(TargetFormat, SourceFormat, FALSE), - D3DERR_NOTAVAILABLE); - - hr = NineAdapter9_GetScreen(This, DeviceType, &screen); - if (FAILED(hr)) { return hr; } - - dfmt = d3d9_to_pipe_format_checked(screen, TargetFormat, PIPE_TEXTURE_2D, 1, - NINE_BIND_BACKBUFFER_FLAGS, FALSE, FALSE); - bfmt = d3d9_to_pipe_format_checked(screen, SourceFormat, PIPE_TEXTURE_2D, 1, - NINE_BIND_BACKBUFFER_FLAGS, FALSE, FALSE); - - if (dfmt == PIPE_FORMAT_NONE || bfmt == PIPE_FORMAT_NONE) { - DBG("%s to %s not supported.\n", - d3dformat_to_string(SourceFormat), - d3dformat_to_string(TargetFormat)); - return D3DERR_NOTAVAILABLE; - } - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineAdapter9_GetDeviceCaps( struct NineAdapter9 *This, - D3DDEVTYPE DeviceType, - D3DCAPS9 *pCaps ) -{ - struct pipe_screen *screen; - HRESULT hr; - - DBG("This=%p DeviceType=%s pCaps=%p\n", This, - nine_D3DDEVTYPE_to_str(DeviceType), pCaps); - - user_assert(pCaps, D3DERR_INVALIDCALL); - - hr = NineAdapter9_GetScreen(This, DeviceType, &screen); - if (FAILED(hr)) { - DBG("Failed to get pipe_screen.\n"); - return hr; - } - -#define D3DPIPECAP(pcap, d3dcap) \ - (screen->get_param(screen, PIPE_CAP_##pcap) ? (d3dcap) : 0) - -#define D3DNPIPECAP(pcap, d3dcap) \ - (screen->get_param(screen, PIPE_CAP_##pcap) ? 0 : (d3dcap)) - - pCaps->DeviceType = DeviceType; - - pCaps->AdapterOrdinal = 0; - - pCaps->Caps = D3DCAPS_READ_SCANLINE; - - pCaps->Caps2 = /* D3DCAPS2_CANMANAGERESOURCE | */ - /* D3DCAPS2_CANSHARERESOURCE | */ - /* D3DCAPS2_CANCALIBRATEGAMMA | */ - D3DCAPS2_DYNAMICTEXTURES | - D3DCAPS2_FULLSCREENGAMMA | - D3DCAPS2_CANAUTOGENMIPMAP; - - /* Note: D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD just means the - * backbuffer can be ARGB (instead of only XRGB) when we are fullscreen - * and in discard mode. */ - pCaps->Caps3 = D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD | - D3DCAPS3_COPY_TO_VIDMEM | - D3DCAPS3_COPY_TO_SYSTEMMEM | - D3DCAPS3_LINEAR_TO_SRGB_PRESENTATION; - - pCaps->PresentationIntervals = D3DPRESENT_INTERVAL_DEFAULT | - D3DPRESENT_INTERVAL_ONE | - D3DPRESENT_INTERVAL_TWO | - D3DPRESENT_INTERVAL_THREE | - D3DPRESENT_INTERVAL_FOUR | - D3DPRESENT_INTERVAL_IMMEDIATE; - pCaps->CursorCaps = D3DCURSORCAPS_COLOR /* | D3DCURSORCAPS_LOWRES*/; - - pCaps->DevCaps = D3DDEVCAPS_CANBLTSYSTONONLOCAL | - D3DDEVCAPS_CANRENDERAFTERFLIP | - D3DDEVCAPS_DRAWPRIMITIVES2 | - D3DDEVCAPS_DRAWPRIMITIVES2EX | - D3DDEVCAPS_DRAWPRIMTLVERTEX | - D3DDEVCAPS_EXECUTESYSTEMMEMORY | - D3DDEVCAPS_EXECUTEVIDEOMEMORY | - D3DDEVCAPS_HWRASTERIZATION | - D3DDEVCAPS_HWTRANSFORMANDLIGHT | - /*D3DDEVCAPS_NPATCHES |*/ - D3DDEVCAPS_PUREDEVICE | - /*D3DDEVCAPS_QUINTICRTPATCHES |*/ - /*D3DDEVCAPS_RTPATCHES |*/ - /*D3DDEVCAPS_RTPATCHHANDLEZERO |*/ - /*D3DDEVCAPS_SEPARATETEXTUREMEMORIES |*/ - D3DDEVCAPS_TEXTURENONLOCALVIDMEM | - /* D3DDEVCAPS_TEXTURESYSTEMMEMORY |*/ - D3DDEVCAPS_TEXTUREVIDEOMEMORY | - D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | - D3DDEVCAPS_TLVERTEXVIDEOMEMORY; - - pCaps->PrimitiveMiscCaps = D3DPMISCCAPS_MASKZ | - D3DPMISCCAPS_CULLNONE | /* XXX */ - D3DPMISCCAPS_CULLCW | - D3DPMISCCAPS_CULLCCW | - D3DPMISCCAPS_COLORWRITEENABLE | - D3DPMISCCAPS_CLIPPLANESCALEDPOINTS | - /*D3DPMISCCAPS_CLIPTLVERTS |*/ - D3DPMISCCAPS_TSSARGTEMP | - D3DPMISCCAPS_BLENDOP | - D3DPIPECAP(INDEP_BLEND_ENABLE, D3DPMISCCAPS_INDEPENDENTWRITEMASKS) | - D3DPMISCCAPS_PERSTAGECONSTANT | - /*D3DPMISCCAPS_POSTBLENDSRGBCONVERT |*/ /* TODO: advertise if Ex and dx10 able card */ - D3DPMISCCAPS_FOGANDSPECULARALPHA | /* Note: documentation of the flag is wrong */ - D3DPIPECAP(BLEND_EQUATION_SEPARATE, D3DPMISCCAPS_SEPARATEALPHABLEND) | - D3DPIPECAP(MIXED_COLORBUFFER_FORMATS, D3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS) | - D3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING | - D3DPMISCCAPS_FOGVERTEXCLAMPED; - if (!screen->get_param(screen, PIPE_CAP_TGSI_VS_WINDOW_SPACE_POSITION)) - pCaps->PrimitiveMiscCaps |= D3DPMISCCAPS_CLIPTLVERTS; - - pCaps->RasterCaps = - D3DPIPECAP(ANISOTROPIC_FILTER, D3DPRASTERCAPS_ANISOTROPY) | - D3DPRASTERCAPS_COLORPERSPECTIVE | - D3DPRASTERCAPS_DITHER | - D3DPRASTERCAPS_DEPTHBIAS | - D3DPRASTERCAPS_FOGRANGE | - D3DPRASTERCAPS_FOGTABLE | - D3DPRASTERCAPS_FOGVERTEX | - D3DPRASTERCAPS_MIPMAPLODBIAS | - D3DPRASTERCAPS_MULTISAMPLE_TOGGLE | - D3DPRASTERCAPS_SCISSORTEST | - D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS | - /*D3DPRASTERCAPS_WBUFFER |*/ - D3DPRASTERCAPS_WFOG | - /*D3DPRASTERCAPS_ZBUFFERLESSHSR |*/ - D3DPRASTERCAPS_ZFOG | - D3DPRASTERCAPS_ZTEST; - - pCaps->ZCmpCaps = D3DPCMPCAPS_NEVER | - D3DPCMPCAPS_LESS | - D3DPCMPCAPS_EQUAL | - D3DPCMPCAPS_LESSEQUAL | - D3DPCMPCAPS_GREATER | - D3DPCMPCAPS_NOTEQUAL | - D3DPCMPCAPS_GREATEREQUAL | - D3DPCMPCAPS_ALWAYS; - - pCaps->SrcBlendCaps = D3DPBLENDCAPS_ZERO | - D3DPBLENDCAPS_ONE | - D3DPBLENDCAPS_SRCCOLOR | - D3DPBLENDCAPS_INVSRCCOLOR | - D3DPBLENDCAPS_SRCALPHA | - D3DPBLENDCAPS_INVSRCALPHA | - D3DPBLENDCAPS_DESTALPHA | - D3DPBLENDCAPS_INVDESTALPHA | - D3DPBLENDCAPS_DESTCOLOR | - D3DPBLENDCAPS_INVDESTCOLOR | - D3DPBLENDCAPS_SRCALPHASAT | - D3DPBLENDCAPS_BOTHSRCALPHA | - D3DPBLENDCAPS_BOTHINVSRCALPHA | - D3DPBLENDCAPS_BLENDFACTOR | - D3DPIPECAP(MAX_DUAL_SOURCE_RENDER_TARGETS, - D3DPBLENDCAPS_INVSRCCOLOR2 | - D3DPBLENDCAPS_SRCCOLOR2); - - pCaps->DestBlendCaps = pCaps->SrcBlendCaps; - - pCaps->AlphaCmpCaps = D3DPCMPCAPS_NEVER | - D3DPCMPCAPS_LESS | - D3DPCMPCAPS_EQUAL | - D3DPCMPCAPS_LESSEQUAL | - D3DPCMPCAPS_GREATER | - D3DPCMPCAPS_NOTEQUAL | - D3DPCMPCAPS_GREATEREQUAL | - D3DPCMPCAPS_ALWAYS; - - /* FLAT caps not legal for D3D9. */ - pCaps->ShadeCaps = D3DPSHADECAPS_COLORGOURAUDRGB | - D3DPSHADECAPS_SPECULARGOURAUDRGB | - D3DPSHADECAPS_ALPHAGOURAUDBLEND | - D3DPSHADECAPS_FOGGOURAUD; - - pCaps->TextureCaps = - D3DPTEXTURECAPS_ALPHA | - D3DPTEXTURECAPS_ALPHAPALETTE | - D3DPTEXTURECAPS_PERSPECTIVE | - D3DPTEXTURECAPS_PROJECTED | - D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE | - D3DPTEXTURECAPS_CUBEMAP | - D3DPTEXTURECAPS_VOLUMEMAP | - D3DNPIPECAP(NPOT_TEXTURES, D3DPTEXTURECAPS_POW2) | - D3DNPIPECAP(NPOT_TEXTURES, D3DPTEXTURECAPS_NONPOW2CONDITIONAL) | - D3DNPIPECAP(NPOT_TEXTURES, D3DPTEXTURECAPS_CUBEMAP_POW2) | - D3DNPIPECAP(NPOT_TEXTURES, D3DPTEXTURECAPS_VOLUMEMAP_POW2) | - D3DPIPECAP(MAX_TEXTURE_2D_SIZE, D3DPTEXTURECAPS_MIPMAP) | - D3DPIPECAP(MAX_TEXTURE_3D_LEVELS, D3DPTEXTURECAPS_MIPVOLUMEMAP) | - D3DPIPECAP(MAX_TEXTURE_CUBE_LEVELS, D3DPTEXTURECAPS_MIPCUBEMAP); - - pCaps->TextureFilterCaps = - D3DPTFILTERCAPS_MINFPOINT | - D3DPTFILTERCAPS_MINFLINEAR | - D3DPIPECAP(ANISOTROPIC_FILTER, D3DPTFILTERCAPS_MINFANISOTROPIC) | - /*D3DPTFILTERCAPS_MINFPYRAMIDALQUAD |*/ - /*D3DPTFILTERCAPS_MINFGAUSSIANQUAD |*/ - D3DPTFILTERCAPS_MIPFPOINT | - D3DPTFILTERCAPS_MIPFLINEAR | - D3DPTFILTERCAPS_MAGFPOINT | - D3DPTFILTERCAPS_MAGFLINEAR | - D3DPIPECAP(ANISOTROPIC_FILTER, D3DPTFILTERCAPS_MAGFANISOTROPIC) | - /*D3DPTFILTERCAPS_MAGFPYRAMIDALQUAD |*/ - /*D3DPTFILTERCAPS_MAGFGAUSSIANQUAD*/0; - - pCaps->CubeTextureFilterCaps = pCaps->TextureFilterCaps; - pCaps->VolumeTextureFilterCaps = pCaps->TextureFilterCaps; - - pCaps->TextureAddressCaps = - D3DPTADDRESSCAPS_BORDER | - D3DPTADDRESSCAPS_INDEPENDENTUV | - D3DPTADDRESSCAPS_WRAP | - D3DPTADDRESSCAPS_MIRROR | - D3DPTADDRESSCAPS_CLAMP | - D3DPIPECAP(TEXTURE_MIRROR_CLAMP, D3DPTADDRESSCAPS_MIRRORONCE); - - pCaps->VolumeTextureAddressCaps = pCaps->TextureAddressCaps; - - pCaps->LineCaps = - D3DLINECAPS_ALPHACMP | - D3DLINECAPS_BLEND | - D3DLINECAPS_TEXTURE | - D3DLINECAPS_ZTEST | - D3DLINECAPS_FOG; - if (screen->get_paramf(screen, PIPE_CAPF_MAX_LINE_WIDTH_AA) > 0.0) { - pCaps->LineCaps |= D3DLINECAPS_ANTIALIAS; - } - - pCaps->MaxTextureWidth =screen->get_param(screen, - PIPE_CAP_MAX_TEXTURE_2D_SIZE); - pCaps->MaxTextureHeight = pCaps->MaxTextureWidth; - pCaps->MaxVolumeExtent = - 1 << (screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_3D_LEVELS) - 1); - /* XXX values from wine */ - pCaps->MaxTextureRepeat = 32768; - pCaps->MaxTextureAspectRatio = pCaps->MaxTextureWidth; - - pCaps->MaxAnisotropy = - (DWORD)screen->get_paramf(screen, PIPE_CAPF_MAX_TEXTURE_ANISOTROPY); - - /* Values for GeForce 9600 GT */ - pCaps->MaxVertexW = 1e10f; - pCaps->GuardBandLeft = -1e9f; - pCaps->GuardBandTop = -1e9f; - pCaps->GuardBandRight = 1e9f; - pCaps->GuardBandBottom = 1e9f; - pCaps->ExtentsAdjust = 0.0f; - - pCaps->StencilCaps = - D3DSTENCILCAPS_KEEP | - D3DSTENCILCAPS_ZERO | - D3DSTENCILCAPS_REPLACE | - D3DSTENCILCAPS_INCRSAT | - D3DSTENCILCAPS_DECRSAT | - D3DSTENCILCAPS_INVERT | - D3DSTENCILCAPS_INCR | - D3DSTENCILCAPS_DECR | - D3DSTENCILCAPS_TWOSIDED; - - pCaps->FVFCaps = - 8 | /* 8 textures max */ - /*D3DFVFCAPS_DONOTSTRIPELEMENTS |*/ - D3DFVFCAPS_PSIZE; - - pCaps->TextureOpCaps = D3DTEXOPCAPS_DISABLE | - D3DTEXOPCAPS_SELECTARG1 | - D3DTEXOPCAPS_SELECTARG2 | - D3DTEXOPCAPS_MODULATE | - D3DTEXOPCAPS_MODULATE2X | - D3DTEXOPCAPS_MODULATE4X | - D3DTEXOPCAPS_ADD | - D3DTEXOPCAPS_ADDSIGNED | - D3DTEXOPCAPS_ADDSIGNED2X | - D3DTEXOPCAPS_SUBTRACT | - D3DTEXOPCAPS_ADDSMOOTH | - D3DTEXOPCAPS_BLENDDIFFUSEALPHA | - D3DTEXOPCAPS_BLENDTEXTUREALPHA | - D3DTEXOPCAPS_BLENDFACTORALPHA | - D3DTEXOPCAPS_BLENDTEXTUREALPHAPM | - D3DTEXOPCAPS_BLENDCURRENTALPHA | - D3DTEXOPCAPS_PREMODULATE | - D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR | - D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA | - D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR | - D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA | - D3DTEXOPCAPS_BUMPENVMAP | - D3DTEXOPCAPS_BUMPENVMAPLUMINANCE | - D3DTEXOPCAPS_DOTPRODUCT3 | - D3DTEXOPCAPS_MULTIPLYADD | - D3DTEXOPCAPS_LERP; - - pCaps->MaxTextureBlendStages = 8; /* XXX wine */ - (DWORD)screen->get_param(screen, PIPE_CAP_BLEND_EQUATION_SEPARATE); - pCaps->MaxSimultaneousTextures = 8; - - pCaps->VertexProcessingCaps = D3DVTXPCAPS_TEXGEN | - D3DVTXPCAPS_TEXGEN_SPHEREMAP | - D3DVTXPCAPS_MATERIALSOURCE7 | - D3DVTXPCAPS_DIRECTIONALLIGHTS | - D3DVTXPCAPS_POSITIONALLIGHTS | - D3DVTXPCAPS_LOCALVIEWER | - D3DVTXPCAPS_TWEENING | - /*D3DVTXPCAPS_NO_TEXGEN_NONLOCALVIEWER*/0; - - pCaps->MaxActiveLights = NINE_MAX_LIGHTS_ACTIVE; /* like GL_LIGHTi */ - pCaps->MaxUserClipPlanes = PIPE_MAX_CLIP_PLANES; - pCaps->MaxVertexBlendMatrices = 4; /* 1 vec4 BLENDWEIGHT/INDICES input */ - pCaps->MaxVertexBlendMatrixIndex = 8; /* D3DTS_WORLDMATRIX(0..8) */ - - pCaps->MaxPointSize = screen->get_paramf(screen, PIPE_CAPF_MAX_POINT_WIDTH); - - pCaps->MaxPrimitiveCount = 0x555555; /* <- wine, really 0xFFFFFFFF; */ - pCaps->MaxVertexIndex = 0xFFFFFF; /* <- wine, really 0xFFFFFFFF */ - pCaps->MaxStreams = - _min(screen->get_shader_param(screen, - PIPE_SHADER_VERTEX, PIPE_SHADER_CAP_MAX_INPUTS), - 16); - - pCaps->MaxStreamStride = screen->get_param(screen, - PIPE_CAP_MAX_VERTEX_ATTRIB_STRIDE); - - pCaps->VertexShaderVersion = D3DVS_VERSION(3,0); - - /* VS 2 as well as 3.0 supports a minimum of 256 consts. - * Wine and d3d9 drivers for dx1x hw advertise 256. Just as them, - * advertise 256. Problem is with hw that can only do 256, because - * we need take a few slots for boolean and integer constants. For these - * we'll have to fail later if they use complex shaders. */ - pCaps->MaxVertexShaderConst = NINE_MAX_CONST_F; - - pCaps->PixelShaderVersion = D3DPS_VERSION(3,0); - /* Value for GeForce 9600 GT */ - pCaps->PixelShader1xMaxValue = 65504.f; - - pCaps->DevCaps2 = D3DDEVCAPS2_STREAMOFFSET | - D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET | - D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES | - /*D3DDEVCAPS2_DMAPNPATCH |*/ - /*D3DDEVCAPS2_ADAPTIVETESSRTPATCH |*/ - /*D3DDEVCAPS2_ADAPTIVETESSNPATCH |*/ - /*D3DDEVCAPS2_PRESAMPLEDDMAPNPATCH*/0; - - pCaps->MasterAdapterOrdinal = 0; - pCaps->AdapterOrdinalInGroup = 0; - pCaps->NumberOfAdaptersInGroup = 1; - - /* Undocumented ? */ - pCaps->MaxNpatchTessellationLevel = 0.0f; - pCaps->Reserved5 = 0; - - /* XXX: use is_format_supported */ - pCaps->DeclTypes = D3DDTCAPS_UBYTE4 | - D3DDTCAPS_UBYTE4N | - D3DDTCAPS_SHORT2N | - D3DDTCAPS_SHORT4N | - D3DDTCAPS_USHORT2N | - D3DDTCAPS_USHORT4N | - D3DDTCAPS_UDEC3 | - D3DDTCAPS_DEC3N | - D3DDTCAPS_FLOAT16_2 | - D3DDTCAPS_FLOAT16_4; - - pCaps->NumSimultaneousRTs = - screen->get_param(screen, PIPE_CAP_MAX_RENDER_TARGETS); - if (pCaps->NumSimultaneousRTs > NINE_MAX_SIMULTANEOUS_RENDERTARGETS) - pCaps->NumSimultaneousRTs = NINE_MAX_SIMULTANEOUS_RENDERTARGETS; - - pCaps->StretchRectFilterCaps = D3DPTFILTERCAPS_MINFPOINT | - D3DPTFILTERCAPS_MINFLINEAR | - D3DPTFILTERCAPS_MAGFPOINT | - D3DPTFILTERCAPS_MAGFLINEAR; - - - pCaps->VS20Caps.Caps = D3DVS20CAPS_PREDICATION; - pCaps->VS20Caps.DynamicFlowControlDepth = /* XXX is this dynamic ? */ - screen->get_shader_param(screen, PIPE_SHADER_VERTEX, - PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH); - pCaps->VS20Caps.NumTemps = - screen->get_shader_param(screen, PIPE_SHADER_VERTEX, - PIPE_SHADER_CAP_MAX_TEMPS); - pCaps->VS20Caps.StaticFlowControlDepth = /* XXX is this static ? */ - screen->get_shader_param(screen, PIPE_SHADER_VERTEX, - PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH); - - /* also check for values < 0, because get_shader_param may return unsigned */ - if (pCaps->VS20Caps.DynamicFlowControlDepth > D3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH - || pCaps->VS20Caps.DynamicFlowControlDepth < 0) - pCaps->VS20Caps.DynamicFlowControlDepth = D3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; - if (pCaps->VS20Caps.StaticFlowControlDepth > D3DVS20_MAX_STATICFLOWCONTROLDEPTH - || pCaps->VS20Caps.StaticFlowControlDepth < 0) - pCaps->VS20Caps.StaticFlowControlDepth = D3DVS20_MAX_STATICFLOWCONTROLDEPTH; - if (pCaps->VS20Caps.NumTemps > D3DVS20_MAX_NUMTEMPS) - pCaps->VS20Caps.NumTemps = D3DVS20_MAX_NUMTEMPS; - assert(pCaps->VS20Caps.DynamicFlowControlDepth >= D3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH); - assert(pCaps->VS20Caps.StaticFlowControlDepth >= D3DVS20_MIN_STATICFLOWCONTROLDEPTH); - assert(pCaps->VS20Caps.NumTemps >= D3DVS20_MIN_NUMTEMPS); - - - pCaps->PS20Caps.Caps = D3DPS20CAPS_ARBITRARYSWIZZLE | - D3DPS20CAPS_GRADIENTINSTRUCTIONS | - D3DPS20CAPS_PREDICATION; - if (screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT, - PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS) == - screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT, - PIPE_SHADER_CAP_MAX_INSTRUCTIONS)) - pCaps->PS20Caps.Caps |= D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT; - if (screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT, - PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS) == - screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT, - PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS)) - pCaps->PS20Caps.Caps |= D3DPS20CAPS_NODEPENDENTREADLIMIT; - pCaps->PS20Caps.DynamicFlowControlDepth = /* XXX is this dynamic ? */ - screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT, - PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH); - pCaps->PS20Caps.NumTemps = - screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT, - PIPE_SHADER_CAP_MAX_TEMPS); - pCaps->PS20Caps.StaticFlowControlDepth = /* XXX is this static ? */ - screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT, - PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH); - pCaps->PS20Caps.NumInstructionSlots = - screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT, - PIPE_SHADER_CAP_MAX_INSTRUCTIONS); - - if (pCaps->PS20Caps.DynamicFlowControlDepth > D3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH - || pCaps->PS20Caps.DynamicFlowControlDepth < 0) - pCaps->PS20Caps.DynamicFlowControlDepth = D3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; - if (pCaps->PS20Caps.StaticFlowControlDepth > D3DPS20_MAX_STATICFLOWCONTROLDEPTH - || pCaps->PS20Caps.StaticFlowControlDepth < 0) - pCaps->PS20Caps.StaticFlowControlDepth = D3DPS20_MAX_STATICFLOWCONTROLDEPTH; - if (pCaps->PS20Caps.NumTemps > D3DPS20_MAX_NUMTEMPS) - pCaps->PS20Caps.NumTemps = D3DPS20_MAX_NUMTEMPS; - if (pCaps->PS20Caps.NumInstructionSlots > D3DPS20_MAX_NUMINSTRUCTIONSLOTS) - pCaps->PS20Caps.NumInstructionSlots = D3DPS20_MAX_NUMINSTRUCTIONSLOTS; - assert(pCaps->PS20Caps.DynamicFlowControlDepth >= D3DPS20_MIN_DYNAMICFLOWCONTROLDEPTH); - assert(pCaps->PS20Caps.StaticFlowControlDepth >= D3DPS20_MIN_STATICFLOWCONTROLDEPTH); - assert(pCaps->PS20Caps.NumTemps >= D3DPS20_MIN_NUMTEMPS); - assert(pCaps->PS20Caps.NumInstructionSlots >= D3DPS20_MIN_NUMINSTRUCTIONSLOTS); - - - if (screen->get_shader_param(screen, PIPE_SHADER_VERTEX, - PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS)) - pCaps->VertexTextureFilterCaps = pCaps->TextureFilterCaps & - ~(D3DPTFILTERCAPS_MIPFPOINT | - D3DPTFILTERCAPS_MIPFPOINT); /* XXX */ - else - pCaps->VertexTextureFilterCaps = 0; - - pCaps->MaxVertexShader30InstructionSlots = - screen->get_shader_param(screen, PIPE_SHADER_VERTEX, - PIPE_SHADER_CAP_MAX_INSTRUCTIONS); - pCaps->MaxPixelShader30InstructionSlots = - screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT, - PIPE_SHADER_CAP_MAX_INSTRUCTIONS); - if (pCaps->MaxVertexShader30InstructionSlots > D3DMAX30SHADERINSTRUCTIONS) - pCaps->MaxVertexShader30InstructionSlots = D3DMAX30SHADERINSTRUCTIONS; - if (pCaps->MaxPixelShader30InstructionSlots > D3DMAX30SHADERINSTRUCTIONS) - pCaps->MaxPixelShader30InstructionSlots = D3DMAX30SHADERINSTRUCTIONS; - assert(pCaps->MaxVertexShader30InstructionSlots >= D3DMIN30SHADERINSTRUCTIONS); - assert(pCaps->MaxPixelShader30InstructionSlots >= D3DMIN30SHADERINSTRUCTIONS); - - /* 65535 is required, advertise more for GPUs with >= 2048 instruction slots */ - pCaps->MaxVShaderInstructionsExecuted = MAX2(65535, pCaps->MaxVertexShader30InstructionSlots * 32); - pCaps->MaxPShaderInstructionsExecuted = MAX2(65535, pCaps->MaxPixelShader30InstructionSlots * 32); - - if (debug_get_bool_option("NINE_DUMP_CAPS", FALSE)) - nine_dump_D3DCAPS9(DBG_CHANNEL, pCaps); - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineAdapter9_CreateDevice( struct NineAdapter9 *This, - UINT RealAdapter, - D3DDEVTYPE DeviceType, - HWND hFocusWindow, - DWORD BehaviorFlags, - D3DPRESENT_PARAMETERS *pPresentationParameters, - IDirect3D9 *pD3D9, - ID3DPresentGroup *pPresentationGroup, - IDirect3DDevice9 **ppReturnedDeviceInterface ) -{ - struct pipe_screen *screen; - D3DDEVICE_CREATION_PARAMETERS params; - D3DCAPS9 caps; - int major, minor; - HRESULT hr; - - DBG("This=%p RealAdapter=%u DeviceType=%s hFocusWindow=%p " - "BehaviourFlags=%x " "pD3D9=%p pPresentationGroup=%p " - "ppReturnedDeviceInterface=%p\n", This, - RealAdapter, nine_D3DDEVTYPE_to_str(DeviceType), hFocusWindow, - BehaviorFlags, pD3D9, pPresentationGroup, ppReturnedDeviceInterface); - - ID3DPresentGroup_GetVersion(pPresentationGroup, &major, &minor); - if (major != 1) { - ERR("Doesn't support the ID3DPresentGroup version %d %d. Expected 1\n", - major, minor); - return D3DERR_NOTAVAILABLE; - } - - hr = NineAdapter9_GetScreen(This, DeviceType, &screen); - if (FAILED(hr)) { - DBG("Failed to get pipe_screen.\n"); - return hr; - } - - hr = NineAdapter9_GetDeviceCaps(This, DeviceType, &caps); - if (FAILED(hr)) { - DBG("Failed to get device caps.\n"); - return hr; - } - - params.AdapterOrdinal = RealAdapter; - params.DeviceType = DeviceType; - params.hFocusWindow = hFocusWindow; - params.BehaviorFlags = BehaviorFlags; - - hr = NineDevice9_new(screen, ¶ms, &caps, pPresentationParameters, - pD3D9, pPresentationGroup, This->ctx, FALSE, NULL, - (struct NineDevice9 **)ppReturnedDeviceInterface, - minor); - if (FAILED(hr)) { - DBG("Failed to create device.\n"); - return hr; - } - DBG("NineDevice9 created successfully.\n"); - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineAdapter9_CreateDeviceEx( struct NineAdapter9 *This, - UINT RealAdapter, - D3DDEVTYPE DeviceType, - HWND hFocusWindow, - DWORD BehaviorFlags, - D3DPRESENT_PARAMETERS *pPresentationParameters, - D3DDISPLAYMODEEX *pFullscreenDisplayMode, - IDirect3D9Ex *pD3D9Ex, - ID3DPresentGroup *pPresentationGroup, - IDirect3DDevice9Ex **ppReturnedDeviceInterface ) -{ - struct pipe_screen *screen; - D3DDEVICE_CREATION_PARAMETERS params; - D3DCAPS9 caps; - int major, minor; - HRESULT hr; - - DBG("This=%p RealAdapter=%u DeviceType=%s hFocusWindow=%p " - "BehaviourFlags=%x " "pD3D9Ex=%p pPresentationGroup=%p " - "ppReturnedDeviceInterface=%p\n", This, - RealAdapter, nine_D3DDEVTYPE_to_str(DeviceType), hFocusWindow, - BehaviorFlags, pD3D9Ex, pPresentationGroup, ppReturnedDeviceInterface); - - ID3DPresentGroup_GetVersion(pPresentationGroup, &major, &minor); - if (major != 1) { - ERR("Doesn't support the ID3DPresentGroup version %d %d. Expected 1\n", - major, minor); - return D3DERR_NOTAVAILABLE; - } - - hr = NineAdapter9_GetScreen(This, DeviceType, &screen); - if (FAILED(hr)) { - DBG("Failed to get pipe_screen.\n"); - return hr; - } - - hr = NineAdapter9_GetDeviceCaps(This, DeviceType, &caps); - if (FAILED(hr)) { - DBG("Failed to get device caps.\n"); - return hr; - } - - params.AdapterOrdinal = RealAdapter; - params.DeviceType = DeviceType; - params.hFocusWindow = hFocusWindow; - params.BehaviorFlags = BehaviorFlags; - - hr = NineDevice9Ex_new(screen, ¶ms, &caps, pPresentationParameters, - pFullscreenDisplayMode, - pD3D9Ex, pPresentationGroup, This->ctx, - (struct NineDevice9Ex **)ppReturnedDeviceInterface, - minor); - if (FAILED(hr)) { - DBG("Failed to create device.\n"); - return hr; - } - DBG("NineDevice9Ex created successfully.\n"); - - return D3D_OK; -} - -ID3DAdapter9Vtbl NineAdapter9_vtable = { - (void *)NineUnknown_QueryInterface, - (void *)NineUnknown_AddRef, - (void *)NineUnknown_Release, - (void *)NineAdapter9_GetAdapterIdentifier, - (void *)NineAdapter9_CheckDeviceType, - (void *)NineAdapter9_CheckDeviceFormat, - (void *)NineAdapter9_CheckDeviceMultiSampleType, - (void *)NineAdapter9_CheckDepthStencilMatch, - (void *)NineAdapter9_CheckDeviceFormatConversion, - (void *)NineAdapter9_GetDeviceCaps, - (void *)NineAdapter9_CreateDevice, - (void *)NineAdapter9_CreateDeviceEx -}; - -static const GUID *NineAdapter9_IIDs[] = { - &IID_ID3D9Adapter, - &IID_IUnknown, - NULL -}; - -HRESULT -NineAdapter9_new( struct d3dadapter9_context *pCTX, - struct NineAdapter9 **ppOut ) -{ - NINE_NEW(Adapter9, ppOut, FALSE, /* args */ pCTX); -} diff --git a/src/gallium/state_trackers/nine/adapter9.h b/src/gallium/state_trackers/nine/adapter9.h deleted file mode 100644 index 605444cbc8d..00000000000 --- a/src/gallium/state_trackers/nine/adapter9.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef _NINE_ADAPTER9_H_ -#define _NINE_ADAPTER9_H_ - -#include "iunknown.h" - -#include "d3dadapter/d3dadapter9.h" - -struct pipe_screen; -struct pipe_resource; - -struct d3dadapter9_context -{ - struct pipe_screen *hal, *ref; - D3DADAPTER_IDENTIFIER9 identifier; - BOOL linear_framebuffer; - BOOL throttling; - int throttling_value; - int vblank_mode; - BOOL thread_submit; - BOOL discard_delayed_release; - BOOL tearfree_discard; - int csmt_force; - BOOL dynamic_texture_workaround; - BOOL shader_inline_constants; - - void (*destroy)( struct d3dadapter9_context *ctx ); -}; - -struct NineAdapter9 -{ - struct NineUnknown base; - - struct d3dadapter9_context *ctx; -}; -static inline struct NineAdapter9 * -NineAdapter9( void *data ) -{ - return (struct NineAdapter9 *)data; -} - -HRESULT -NineAdapter9_new( struct d3dadapter9_context *pCTX, - struct NineAdapter9 **ppOut ); - -HRESULT -NineAdapter9_ctor( struct NineAdapter9 *This, - struct NineUnknownParams *pParams, - struct d3dadapter9_context *pCTX ); - -void -NineAdapter9_dtor( struct NineAdapter9 *This ); - -HRESULT NINE_WINAPI -NineAdapter9_GetAdapterIdentifier( struct NineAdapter9 *This, - DWORD Flags, - D3DADAPTER_IDENTIFIER9 *pIdentifier ); - -HRESULT NINE_WINAPI -NineAdapter9_CheckDeviceType( struct NineAdapter9 *This, - D3DDEVTYPE DevType, - D3DFORMAT AdapterFormat, - D3DFORMAT BackBufferFormat, - BOOL bWindowed ); - -HRESULT NINE_WINAPI -NineAdapter9_CheckDeviceFormat( struct NineAdapter9 *This, - D3DDEVTYPE DeviceType, - D3DFORMAT AdapterFormat, - DWORD Usage, - D3DRESOURCETYPE RType, - D3DFORMAT CheckFormat ); - -HRESULT NINE_WINAPI -NineAdapter9_CheckDeviceMultiSampleType( struct NineAdapter9 *This, - D3DDEVTYPE DeviceType, - D3DFORMAT SurfaceFormat, - BOOL Windowed, - D3DMULTISAMPLE_TYPE MultiSampleType, - DWORD *pQualityLevels ); - -HRESULT NINE_WINAPI -NineAdapter9_CheckDepthStencilMatch( struct NineAdapter9 *This, - D3DDEVTYPE DeviceType, - D3DFORMAT AdapterFormat, - D3DFORMAT RenderTargetFormat, - D3DFORMAT DepthStencilFormat ); - -HRESULT NINE_WINAPI -NineAdapter9_CheckDeviceFormatConversion( struct NineAdapter9 *This, - D3DDEVTYPE DeviceType, - D3DFORMAT SourceFormat, - D3DFORMAT TargetFormat ); - -HRESULT NINE_WINAPI -NineAdapter9_GetDeviceCaps( struct NineAdapter9 *This, - D3DDEVTYPE DeviceType, - D3DCAPS9 *pCaps ); - -HRESULT NINE_WINAPI -NineAdapter9_CreateDevice( struct NineAdapter9 *This, - UINT RealAdapter, - D3DDEVTYPE DeviceType, - HWND hFocusWindow, - DWORD BehaviorFlags, - D3DPRESENT_PARAMETERS *pPresentationParameters, - IDirect3D9 *pD3D9, - ID3DPresentGroup *pPresentationGroup, - IDirect3DDevice9 **ppReturnedDeviceInterface ); - -HRESULT NINE_WINAPI -NineAdapter9_CreateDeviceEx( struct NineAdapter9 *This, - UINT RealAdapter, - D3DDEVTYPE DeviceType, - HWND hFocusWindow, - DWORD BehaviorFlags, - D3DPRESENT_PARAMETERS *pPresentationParameters, - D3DDISPLAYMODEEX *pFullscreenDisplayMode, - IDirect3D9Ex *pD3D9Ex, - ID3DPresentGroup *pPresentationGroup, - IDirect3DDevice9Ex **ppReturnedDeviceInterface ); - -#endif /* _NINE_ADAPTER9_H_ */ diff --git a/src/gallium/state_trackers/nine/authenticatedchannel9.c b/src/gallium/state_trackers/nine/authenticatedchannel9.c deleted file mode 100644 index 45fca3a2975..00000000000 --- a/src/gallium/state_trackers/nine/authenticatedchannel9.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "authenticatedchannel9.h" - -#define DBG_CHANNEL DBG_AUTHENTICATEDCHANNEL - -HRESULT NINE_WINAPI -NineAuthenticatedChannel9_GetCertificateSize( struct NineAuthenticatedChannel9 *This, - UINT *pCertificateSize ) -{ - STUB(D3DERR_INVALIDCALL); -} - -HRESULT NINE_WINAPI -NineAuthenticatedChannel9_GetCertificate( struct NineAuthenticatedChannel9 *This, - UINT CertifacteSize, - BYTE *ppCertificate ) -{ - STUB(D3DERR_INVALIDCALL); -} - -HRESULT NINE_WINAPI -NineAuthenticatedChannel9_NegotiateKeyExchange( struct NineAuthenticatedChannel9 *This, - UINT DataSize, - void *pData ) -{ - STUB(D3DERR_INVALIDCALL); -} - -HRESULT NINE_WINAPI -NineAuthenticatedChannel9_Query( struct NineAuthenticatedChannel9 *This, - UINT InputSize, - const void *pInput, - UINT OutputSize, - void *pOutput ) -{ - STUB(D3DERR_INVALIDCALL); -} - -HRESULT NINE_WINAPI -NineAuthenticatedChannel9_Configure( struct NineAuthenticatedChannel9 *This, - UINT InputSize, - const void *pInput, - D3DAUTHENTICATEDCHANNEL_CONFIGURE_OUTPUT *pOutput ) -{ - STUB(D3DERR_INVALIDCALL); -} - -IDirect3DAuthenticatedChannel9Vtbl NineAuthenticatedChannel9_vtable = { - (void *)NineUnknown_QueryInterface, - (void *)NineUnknown_AddRef, - (void *)NineUnknown_Release, - (void *)NineAuthenticatedChannel9_GetCertificateSize, - (void *)NineAuthenticatedChannel9_GetCertificate, - (void *)NineAuthenticatedChannel9_NegotiateKeyExchange, - (void *)NineAuthenticatedChannel9_Query, - (void *)NineAuthenticatedChannel9_Configure -}; diff --git a/src/gallium/state_trackers/nine/authenticatedchannel9.h b/src/gallium/state_trackers/nine/authenticatedchannel9.h deleted file mode 100644 index b18848235c8..00000000000 --- a/src/gallium/state_trackers/nine/authenticatedchannel9.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef _NINE_AUTHENTICATEDCHANNEL9_H_ -#define _NINE_AUTHENTICATEDCHANNEL9_H_ - -#include "iunknown.h" - -struct NineAuthenticatedChannel9 -{ - struct NineUnknown base; -}; -static inline struct NineAuthenticatedChannel9 * -NineAuthenticatedChannel9( void *data ) -{ - return (struct NineAuthenticatedChannel9 *)data; -} - -HRESULT NINE_WINAPI -NineAuthenticatedChannel9_GetCertificateSize( struct NineAuthenticatedChannel9 *This, - UINT *pCertificateSize ); - -HRESULT NINE_WINAPI -NineAuthenticatedChannel9_GetCertificate( struct NineAuthenticatedChannel9 *This, - UINT CertifacteSize, - BYTE *ppCertificate ); - -HRESULT NINE_WINAPI -NineAuthenticatedChannel9_NegotiateKeyExchange( struct NineAuthenticatedChannel9 *This, - UINT DataSize, - void *pData ); - -HRESULT NINE_WINAPI -NineAuthenticatedChannel9_Query( struct NineAuthenticatedChannel9 *This, - UINT InputSize, - const void *pInput, - UINT OutputSize, - void *pOutput ); - -HRESULT NINE_WINAPI -NineAuthenticatedChannel9_Configure( struct NineAuthenticatedChannel9 *This, - UINT InputSize, - const void *pInput, - D3DAUTHENTICATEDCHANNEL_CONFIGURE_OUTPUT *pOutput ); - -#endif /* _NINE_AUTHENTICATEDCHANNEL9_H_ */ diff --git a/src/gallium/state_trackers/nine/basetexture9.c b/src/gallium/state_trackers/nine/basetexture9.c deleted file mode 100644 index c59bda5d295..00000000000 --- a/src/gallium/state_trackers/nine/basetexture9.c +++ /dev/null @@ -1,623 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "basetexture9.h" -#include "device9.h" - -/* For UploadSelf: */ -#include "texture9.h" -#include "cubetexture9.h" -#include "volumetexture9.h" - -#if defined(DEBUG) || !defined(NDEBUG) -#include "nine_pipe.h" -#include "nine_dump.h" -#endif - -#include "util/format/u_format.h" - -#define DBG_CHANNEL DBG_BASETEXTURE - -HRESULT -NineBaseTexture9_ctor( struct NineBaseTexture9 *This, - struct NineUnknownParams *pParams, - struct pipe_resource *initResource, - D3DRESOURCETYPE Type, - D3DFORMAT format, - D3DPOOL Pool, - DWORD Usage) -{ - BOOL alloc = (Pool == D3DPOOL_DEFAULT) && !initResource && - (format != D3DFMT_NULL); - HRESULT hr; - - DBG("This=%p, pParams=%p initResource=%p Type=%d format=%d Pool=%d Usage=%d\n", - This, pParams, initResource, Type, format, Pool, Usage); - - user_assert(!(Usage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL)) || - Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); - user_assert(!(Usage & D3DUSAGE_DYNAMIC) || - !(Pool == D3DPOOL_MANAGED || - Pool == D3DPOOL_SCRATCH), D3DERR_INVALIDCALL); - - hr = NineResource9_ctor(&This->base, pParams, initResource, alloc, Type, Pool, Usage); - if (FAILED(hr)) - return hr; - - This->format = format; - This->mipfilter = (Usage & D3DUSAGE_AUTOGENMIPMAP) ? - D3DTEXF_LINEAR : D3DTEXF_NONE; - This->managed.lod = 0; - This->managed.lod_resident = -1; - /* Mark the texture as dirty to trigger first upload when we need the texture, - * even if it wasn't set by the application */ - if (Pool == D3DPOOL_MANAGED) - This->managed.dirty = TRUE; - /* When a depth buffer is sampled, it is for shadow mapping, except for - * D3DFMT_INTZ, D3DFMT_DF16 and D3DFMT_DF24. - * In addition D3DFMT_INTZ can be used for both texturing and depth buffering - * if z write is disabled. This particular feature may not work for us in - * practice because OGL doesn't have that. However apparently it is known - * some cards have performance issues with this feature, so real apps - * shouldn't use it. */ - This->shadow = (This->format != D3DFMT_INTZ && This->format != D3DFMT_DF16 && - This->format != D3DFMT_DF24) && - util_format_has_depth(util_format_description(This->base.info.format)); - - list_inithead(&This->list); - list_inithead(&This->list2); - if (Pool == D3DPOOL_MANAGED) - list_add(&This->list2, &This->base.base.device->managed_textures); - - return D3D_OK; -} - -void -NineBaseTexture9_dtor( struct NineBaseTexture9 *This ) -{ - DBG("This=%p\n", This); - - pipe_sampler_view_reference(&This->view[0], NULL); - pipe_sampler_view_reference(&This->view[1], NULL); - - if (This->list.prev != NULL && This->list.next != NULL) - list_del(&This->list); - if (This->list2.prev != NULL && This->list2.next != NULL) - list_del(&This->list2); - - NineResource9_dtor(&This->base); -} - -DWORD NINE_WINAPI -NineBaseTexture9_SetLOD( struct NineBaseTexture9 *This, - DWORD LODNew ) -{ - DWORD old = This->managed.lod; - DWORD max_level; - - DBG("This=%p LODNew=%d\n", This, LODNew); - - user_assert(This->base.pool == D3DPOOL_MANAGED, 0); - - max_level = (This->base.usage & D3DUSAGE_AUTOGENMIPMAP) ? - 0 : This->base.info.last_level; - This->managed.lod = MIN2(LODNew, max_level); - - if (This->managed.lod != old && This->bind_count && list_is_empty(&This->list)) - list_add(&This->list, &This->base.base.device->update_textures); - - return old; -} - -DWORD NINE_WINAPI -NineBaseTexture9_GetLOD( struct NineBaseTexture9 *This ) -{ - DBG("This=%p\n", This); - - return This->managed.lod; -} - -DWORD NINE_WINAPI -NineBaseTexture9_GetLevelCount( struct NineBaseTexture9 *This ) -{ - DBG("This=%p\n", This); - - if (This->base.usage & D3DUSAGE_AUTOGENMIPMAP) - return 1; - return This->base.info.last_level + 1; -} - -HRESULT NINE_WINAPI -NineBaseTexture9_SetAutoGenFilterType( struct NineBaseTexture9 *This, - D3DTEXTUREFILTERTYPE FilterType ) -{ - DBG("This=%p FilterType=%d\n", This, FilterType); - - if (!(This->base.usage & D3DUSAGE_AUTOGENMIPMAP)) - return D3D_OK; - user_assert(FilterType != D3DTEXF_NONE, D3DERR_INVALIDCALL); - - This->mipfilter = FilterType; - This->dirty_mip = TRUE; - NineBaseTexture9_GenerateMipSubLevels(This); - - return D3D_OK; -} - -D3DTEXTUREFILTERTYPE NINE_WINAPI -NineBaseTexture9_GetAutoGenFilterType( struct NineBaseTexture9 *This ) -{ - DBG("This=%p\n", This); - - return This->mipfilter; -} - -HRESULT -NineBaseTexture9_UploadSelf( struct NineBaseTexture9 *This ) -{ - HRESULT hr; - unsigned last_level = This->base.info.last_level; - unsigned l, min_level_dirty = This->managed.lod; - BOOL update_lod; - - DBG("This=%p dirty=%i type=%s\n", This, This->managed.dirty, - nine_D3DRTYPE_to_str(This->base.type)); - - assert(This->base.pool == D3DPOOL_MANAGED); - - if (This->base.usage & D3DUSAGE_AUTOGENMIPMAP) - last_level = 0; - - update_lod = This->managed.lod_resident != This->managed.lod; - if (!update_lod && !This->managed.dirty) - return D3D_OK; - - /* Allocate a new resource with the correct number of levels, - * Mark states for update, and tell the nine surfaces/volumes - * their new resource. */ - if (update_lod) { - struct pipe_resource *res; - - DBG("updating LOD from %u to %u ...\n", This->managed.lod_resident, This->managed.lod); - - pipe_sampler_view_reference(&This->view[0], NULL); - pipe_sampler_view_reference(&This->view[1], NULL); - - /* Allocate a new resource */ - hr = NineBaseTexture9_CreatePipeResource(This, This->managed.lod_resident != -1); - if (FAILED(hr)) - return hr; - res = This->base.resource; - - if (This->managed.lod_resident == -1) {/* no levels were resident */ - This->managed.dirty = FALSE; /* We are going to upload everything. */ - This->managed.lod_resident = This->base.info.last_level + 1; - } - - if (This->base.type == D3DRTYPE_TEXTURE) { - struct NineTexture9 *tex = NineTexture9(This); - - /* last content (if apply) has been copied to the new resource. - * Note: We cannot render to surfaces of managed textures. - * Note2: the level argument passed is to get the level offset - * right when the texture is uploaded (the texture first level - * corresponds to This->managed.lod). - * Note3: We don't care about the value passed for the surfaces - * before This->managed.lod, negative with this implementation. */ - for (l = 0; l <= This->base.info.last_level; ++l) - NineSurface9_SetResource(tex->surfaces[l], res, l - This->managed.lod); - } else - if (This->base.type == D3DRTYPE_CUBETEXTURE) { - struct NineCubeTexture9 *tex = NineCubeTexture9(This); - unsigned z; - - for (l = 0; l <= This->base.info.last_level; ++l) { - for (z = 0; z < 6; ++z) - NineSurface9_SetResource(tex->surfaces[l * 6 + z], - res, l - This->managed.lod); - } - } else - if (This->base.type == D3DRTYPE_VOLUMETEXTURE) { - struct NineVolumeTexture9 *tex = NineVolumeTexture9(This); - - for (l = 0; l <= This->base.info.last_level; ++l) - NineVolume9_SetResource(tex->volumes[l], res, l - This->managed.lod); - } else { - assert(!"invalid texture type"); - } - - /* We are going to fully upload the new levels, - * no need to update dirty parts of the texture for these */ - min_level_dirty = MAX2(This->managed.lod, This->managed.lod_resident); - } - - /* Update dirty parts of the texture */ - if (This->managed.dirty) { - if (This->base.type == D3DRTYPE_TEXTURE) { - struct NineTexture9 *tex = NineTexture9(This); - struct pipe_box box; - box.z = 0; - box.depth = 1; - - DBG("TEXTURE: dirty rect=(%u,%u) (%ux%u)\n", - tex->dirty_rect.x, tex->dirty_rect.y, - tex->dirty_rect.width, tex->dirty_rect.height); - - /* Note: for l < min_level_dirty, the resource is - * either non-existing (and thus will be entirely re-uploaded - * if the lod changes) or going to have a full upload */ - if (tex->dirty_rect.width) { - for (l = min_level_dirty; l <= last_level; ++l) { - u_box_minify_2d(&box, &tex->dirty_rect, l); - NineSurface9_UploadSelf(tex->surfaces[l], &box); - } - memset(&tex->dirty_rect, 0, sizeof(tex->dirty_rect)); - tex->dirty_rect.depth = 1; - } - } else - if (This->base.type == D3DRTYPE_CUBETEXTURE) { - struct NineCubeTexture9 *tex = NineCubeTexture9(This); - unsigned z; - struct pipe_box box; - box.z = 0; - box.depth = 1; - - for (z = 0; z < 6; ++z) { - DBG("FACE[%u]: dirty rect=(%u,%u) (%ux%u)\n", z, - tex->dirty_rect[z].x, tex->dirty_rect[z].y, - tex->dirty_rect[z].width, tex->dirty_rect[z].height); - - if (tex->dirty_rect[z].width) { - for (l = min_level_dirty; l <= last_level; ++l) { - u_box_minify_2d(&box, &tex->dirty_rect[z], l); - NineSurface9_UploadSelf(tex->surfaces[l * 6 + z], &box); - } - memset(&tex->dirty_rect[z], 0, sizeof(tex->dirty_rect[z])); - tex->dirty_rect[z].depth = 1; - } - } - } else - if (This->base.type == D3DRTYPE_VOLUMETEXTURE) { - struct NineVolumeTexture9 *tex = NineVolumeTexture9(This); - struct pipe_box box; - - DBG("VOLUME: dirty_box=(%u,%u,%u) (%ux%ux%u)\n", - tex->dirty_box.x, tex->dirty_box.y, tex->dirty_box.y, - tex->dirty_box.width, tex->dirty_box.height, tex->dirty_box.depth); - - if (tex->dirty_box.width) { - for (l = min_level_dirty; l <= last_level; ++l) { - u_box_minify_3d(&box, &tex->dirty_box, l); - NineVolume9_UploadSelf(tex->volumes[l], &box); - } - memset(&tex->dirty_box, 0, sizeof(tex->dirty_box)); - } - } else { - assert(!"invalid texture type"); - } - This->managed.dirty = FALSE; - } - - /* Upload the new levels */ - if (update_lod) { - if (This->base.type == D3DRTYPE_TEXTURE) { - struct NineTexture9 *tex = NineTexture9(This); - struct pipe_box box; - - box.x = box.y = box.z = 0; - box.depth = 1; - for (l = This->managed.lod; l < This->managed.lod_resident; ++l) { - box.width = u_minify(This->base.info.width0, l); - box.height = u_minify(This->base.info.height0, l); - NineSurface9_UploadSelf(tex->surfaces[l], &box); - } - } else - if (This->base.type == D3DRTYPE_CUBETEXTURE) { - struct NineCubeTexture9 *tex = NineCubeTexture9(This); - struct pipe_box box; - unsigned z; - - box.x = box.y = box.z = 0; - box.depth = 1; - for (l = This->managed.lod; l < This->managed.lod_resident; ++l) { - box.width = u_minify(This->base.info.width0, l); - box.height = u_minify(This->base.info.height0, l); - for (z = 0; z < 6; ++z) - NineSurface9_UploadSelf(tex->surfaces[l * 6 + z], &box); - } - } else - if (This->base.type == D3DRTYPE_VOLUMETEXTURE) { - struct NineVolumeTexture9 *tex = NineVolumeTexture9(This); - struct pipe_box box; - - box.x = box.y = box.z = 0; - for (l = This->managed.lod; l < This->managed.lod_resident; ++l) { - box.width = u_minify(This->base.info.width0, l); - box.height = u_minify(This->base.info.height0, l); - box.depth = u_minify(This->base.info.depth0, l); - NineVolume9_UploadSelf(tex->volumes[l], &box); - } - } else { - assert(!"invalid texture type"); - } - - This->managed.lod_resident = This->managed.lod; - } - - if (This->base.usage & D3DUSAGE_AUTOGENMIPMAP) - This->dirty_mip = TRUE; - - /* Set again the textures currently bound to update the texture data */ - if (This->bind_count) { - struct nine_state *state = &This->base.base.device->state; - unsigned s; - for (s = 0; s < NINE_MAX_SAMPLERS; ++s) - /* Dirty tracking is done in device9 state, not nine_context. */ - if (state->texture[s] == This) - nine_context_set_texture(This->base.base.device, s, This); - } - - DBG("DONE, generate mip maps = %i\n", This->dirty_mip); - return D3D_OK; -} - -void NINE_WINAPI -NineBaseTexture9_GenerateMipSubLevels( struct NineBaseTexture9 *This ) -{ - unsigned base_level = 0; - unsigned last_level = This->base.info.last_level - This->managed.lod; - unsigned first_layer = 0; - unsigned last_layer; - unsigned filter = This->mipfilter == D3DTEXF_POINT ? PIPE_TEX_FILTER_NEAREST - : PIPE_TEX_FILTER_LINEAR; - DBG("This=%p\n", This); - - if (This->base.pool == D3DPOOL_MANAGED) - NineBaseTexture9_UploadSelf(This); - if (!This->dirty_mip) - return; - if (This->managed.lod) { - ERR("AUTOGENMIPMAP if level 0 is not resident not supported yet !\n"); - return; - } - - if (!This->view[0]) - NineBaseTexture9_UpdateSamplerView(This, 0); - - last_layer = util_max_layer(This->view[0]->texture, base_level); - - nine_context_gen_mipmap(This->base.base.device, (struct NineUnknown *)This, - This->base.resource, - base_level, last_level, - first_layer, last_layer, filter); - - This->dirty_mip = FALSE; -} - -HRESULT -NineBaseTexture9_CreatePipeResource( struct NineBaseTexture9 *This, - BOOL CopyData ) -{ - struct pipe_context *pipe; - struct pipe_screen *screen = This->base.info.screen; - struct pipe_resource templ; - unsigned l, m; - struct pipe_resource *res; - struct pipe_resource *old = This->base.resource; - - DBG("This=%p lod=%u last_level=%u\n", This, - This->managed.lod, This->base.info.last_level); - - assert(This->base.pool == D3DPOOL_MANAGED); - - templ = This->base.info; - - if (This->managed.lod) { - templ.width0 = u_minify(templ.width0, This->managed.lod); - templ.height0 = u_minify(templ.height0, This->managed.lod); - templ.depth0 = u_minify(templ.depth0, This->managed.lod); - } - templ.last_level = This->base.info.last_level - This->managed.lod; - - if (old) { - /* LOD might have changed. */ - if (old->width0 == templ.width0 && - old->height0 == templ.height0 && - old->depth0 == templ.depth0) - return D3D_OK; - } - - res = screen->resource_create(screen, &templ); - if (!res) - return D3DERR_OUTOFVIDEOMEMORY; - This->base.resource = res; - - if (old && CopyData) { /* Don't return without releasing old ! */ - struct pipe_box box; - box.x = 0; - box.y = 0; - box.z = 0; - - l = (This->managed.lod < This->managed.lod_resident) ? This->managed.lod_resident - This->managed.lod : 0; - m = (This->managed.lod < This->managed.lod_resident) ? 0 : This->managed.lod - This->managed.lod_resident; - - box.width = u_minify(templ.width0, l); - box.height = u_minify(templ.height0, l); - box.depth = u_minify(templ.depth0, l); - - pipe = nine_context_get_pipe_acquire(This->base.base.device); - - for (; l <= templ.last_level; ++l, ++m) { - pipe->resource_copy_region(pipe, - res, l, 0, 0, 0, - old, m, &box); - box.width = u_minify(box.width, 1); - box.height = u_minify(box.height, 1); - box.depth = u_minify(box.depth, 1); - } - - nine_context_get_pipe_release(This->base.base.device); - } - pipe_resource_reference(&old, NULL); - - return D3D_OK; -} - -#define SWIZZLE_TO_REPLACE(s) (s == PIPE_SWIZZLE_0 || \ - s == PIPE_SWIZZLE_1 || \ - s == PIPE_SWIZZLE_NONE) - -HRESULT -NineBaseTexture9_UpdateSamplerView( struct NineBaseTexture9 *This, - const int sRGB ) -{ - const struct util_format_description *desc; - struct pipe_context *pipe; - struct pipe_screen *screen = NineDevice9_GetScreen(This->base.base.device); - struct pipe_resource *resource = This->base.resource; - struct pipe_sampler_view templ; - enum pipe_format srgb_format; - unsigned i; - uint8_t swizzle[4]; - - DBG("This=%p sRGB=%d\n", This, sRGB); - - if (unlikely(!resource)) { - if (unlikely(This->format == D3DFMT_NULL)) - return D3D_OK; - NineBaseTexture9_Dump(This); - } - assert(resource); - - pipe_sampler_view_reference(&This->view[sRGB], NULL); - - swizzle[0] = PIPE_SWIZZLE_X; - swizzle[1] = PIPE_SWIZZLE_Y; - swizzle[2] = PIPE_SWIZZLE_Z; - swizzle[3] = PIPE_SWIZZLE_W; - desc = util_format_description(resource->format); - if (desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) { - /* msdn doc is incomplete here and wrong. - * The only formats that can be read directly here - * are DF16, DF24 and INTZ. - * Tested on win the swizzle is - * R = depth, G = B = 0, A = 1 for DF16 and DF24 - * R = G = B = A = depth for INTZ - * For the other ZS formats that can't be read directly - * but can be used as shadow map, the result is duplicated on - * all channel */ - if (This->format == D3DFMT_DF16 || - This->format == D3DFMT_DF24) { - swizzle[1] = PIPE_SWIZZLE_0; - swizzle[2] = PIPE_SWIZZLE_0; - swizzle[3] = PIPE_SWIZZLE_1; - } else { - swizzle[1] = PIPE_SWIZZLE_X; - swizzle[2] = PIPE_SWIZZLE_X; - swizzle[3] = PIPE_SWIZZLE_X; - } - } else if (resource->format == PIPE_FORMAT_RGTC2_UNORM) { - swizzle[0] = PIPE_SWIZZLE_Y; - swizzle[1] = PIPE_SWIZZLE_X; - swizzle[2] = PIPE_SWIZZLE_1; - swizzle[3] = PIPE_SWIZZLE_1; - } else if (resource->format != PIPE_FORMAT_A8_UNORM && - resource->format != PIPE_FORMAT_RGTC1_UNORM) { - /* exceptions: - * A8 should have 0.0 as default values for RGB. - * ATI1/RGTC1 should be r 0 0 1 (tested on windows). - * It is already what gallium does. All the other ones - * should have 1.0 for non-defined values */ - for (i = 0; i < 4; i++) { - if (SWIZZLE_TO_REPLACE(desc->swizzle[i])) - swizzle[i] = PIPE_SWIZZLE_1; - } - } - - /* if requested and supported, convert to the sRGB format */ - srgb_format = util_format_srgb(resource->format); - if (sRGB && srgb_format != PIPE_FORMAT_NONE && - screen->is_format_supported(screen, srgb_format, - resource->target, 0, 0, resource->bind)) - templ.format = srgb_format; - else - templ.format = resource->format; - templ.u.tex.first_layer = 0; - templ.u.tex.last_layer = resource->target == PIPE_TEXTURE_3D ? - resource->depth0 - 1 : resource->array_size - 1; - templ.u.tex.first_level = 0; - templ.u.tex.last_level = resource->last_level; - templ.swizzle_r = swizzle[0]; - templ.swizzle_g = swizzle[1]; - templ.swizzle_b = swizzle[2]; - templ.swizzle_a = swizzle[3]; - templ.target = resource->target; - - pipe = nine_context_get_pipe_acquire(This->base.base.device); - This->view[sRGB] = pipe->create_sampler_view(pipe, resource, &templ); - nine_context_get_pipe_release(This->base.base.device); - - DBG("sampler view = %p(resource = %p)\n", This->view[sRGB], resource); - - return This->view ? D3D_OK : D3DERR_DRIVERINTERNALERROR; -} - -void NINE_WINAPI -NineBaseTexture9_PreLoad( struct NineBaseTexture9 *This ) -{ - DBG("This=%p\n", This); - - if (This->base.pool == D3DPOOL_MANAGED) - NineBaseTexture9_UploadSelf(This); -} - -void -NineBaseTexture9_UnLoad( struct NineBaseTexture9 *This ) -{ - if (This->base.pool != D3DPOOL_MANAGED || - This->managed.lod_resident == -1) - return; - - pipe_resource_reference(&This->base.resource, NULL); - This->managed.lod_resident = -1; - This->managed.dirty = TRUE; - - /* If the texture is bound, we have to re-upload it */ - BASETEX_REGISTER_UPDATE(This); -} - -#if defined(DEBUG) || !defined(NDEBUG) -void -NineBaseTexture9_Dump( struct NineBaseTexture9 *This ) -{ - DBG("\nNineBaseTexture9(%p->NULL/%p): Pool=%s Type=%s Usage=%s\n" - "Format=%s Dims=%ux%ux%u/%u LastLevel=%u Lod=%u(%u)\n", This, - This->base.resource, - nine_D3DPOOL_to_str(This->base.pool), - nine_D3DRTYPE_to_str(This->base.type), - nine_D3DUSAGE_to_str(This->base.usage), - d3dformat_to_string(This->format), - This->base.info.width0, This->base.info.height0, This->base.info.depth0, - This->base.info.array_size, This->base.info.last_level, - This->managed.lod, This->managed.lod_resident); -} -#endif /* DEBUG || !NDEBUG */ diff --git a/src/gallium/state_trackers/nine/basetexture9.h b/src/gallium/state_trackers/nine/basetexture9.h deleted file mode 100644 index 70e8b934f56..00000000000 --- a/src/gallium/state_trackers/nine/basetexture9.h +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef _NINE_BASETEXTURE9_H_ -#define _NINE_BASETEXTURE9_H_ - -#include "device9.h" -#include "resource9.h" -#include "util/u_inlines.h" -#include "util/list.h" - -struct NineBaseTexture9 -{ - struct NineResource9 base; - struct list_head list; /* for update_textures */ - struct list_head list2; /* for managed_textures */ - - /* g3d */ - struct pipe_sampler_view *view[2]; /* linear and sRGB */ - - D3DFORMAT format; - - int16_t bind_count; /* to Device9->state.texture */ - - boolean shadow; - uint8_t pstype; /* 0: 2D, 1: 1D, 2: CUBE, 3: 3D */ - - boolean dirty_mip; - D3DTEXTUREFILTERTYPE mipfilter; - - /* Specific to managed textures */ - struct { - boolean dirty; - DWORD lod; - DWORD lod_resident; - } managed; -}; -static inline struct NineBaseTexture9 * -NineBaseTexture9( void *data ) -{ - return (struct NineBaseTexture9 *)data; -} - -HRESULT -NineBaseTexture9_ctor( struct NineBaseTexture9 *This, - struct NineUnknownParams *pParams, - struct pipe_resource *initResource, - D3DRESOURCETYPE Type, - D3DFORMAT format, - D3DPOOL Pool, - DWORD Usage); - -void -NineBaseTexture9_dtor( struct NineBaseTexture9 *This ); - -DWORD NINE_WINAPI -NineBaseTexture9_SetLOD( struct NineBaseTexture9 *This, - DWORD LODNew ); - -DWORD NINE_WINAPI -NineBaseTexture9_GetLOD( struct NineBaseTexture9 *This ); - -DWORD NINE_WINAPI -NineBaseTexture9_GetLevelCount( struct NineBaseTexture9 *This ); - -HRESULT NINE_WINAPI -NineBaseTexture9_SetAutoGenFilterType( struct NineBaseTexture9 *This, - D3DTEXTUREFILTERTYPE FilterType ); - -D3DTEXTUREFILTERTYPE NINE_WINAPI -NineBaseTexture9_GetAutoGenFilterType( struct NineBaseTexture9 *This ); - -void NINE_WINAPI -NineBaseTexture9_GenerateMipSubLevels( struct NineBaseTexture9 *This ); - -void NINE_WINAPI -NineBaseTexture9_PreLoad( struct NineBaseTexture9 *This ); - -void -NineBaseTexture9_UnLoad( struct NineBaseTexture9 *This ); - -/* For D3DPOOL_MANAGED only (after SetLOD change): */ -HRESULT -NineBaseTexture9_CreatePipeResource( struct NineBaseTexture9 *This, - BOOL CopyData ); - -/* For D3DPOOL_MANAGED only: */ -HRESULT -NineBaseTexture9_UploadSelf( struct NineBaseTexture9 *This ); - -HRESULT -NineBaseTexture9_UpdateSamplerView( struct NineBaseTexture9 *This, - const int sRGB ); - -static inline void -NineBaseTexture9_Validate( struct NineBaseTexture9 *This ) -{ - DBG_FLAG(DBG_BASETEXTURE, "This=%p dirty=%i dirty_mip=%i lod=%u/%u\n", - This, This->managed.dirty, This->dirty_mip, This->managed.lod, This->managed.lod_resident); - if ((This->base.pool == D3DPOOL_MANAGED) && - (This->managed.dirty || This->managed.lod != This->managed.lod_resident)) - NineBaseTexture9_UploadSelf(This); - if (This->dirty_mip) - NineBaseTexture9_GenerateMipSubLevels(This); -} - -static inline struct pipe_sampler_view * -NineBaseTexture9_GetSamplerView( struct NineBaseTexture9 *This, const int sRGB ) -{ - if (!This->view[sRGB]) - NineBaseTexture9_UpdateSamplerView(This, sRGB); - return This->view[sRGB]; -} - -static void inline -NineBindTextureToDevice( struct NineDevice9 *device, - struct NineBaseTexture9 **slot, - struct NineBaseTexture9 *tex ) -{ - struct NineBaseTexture9 *old = *slot; - - if (tex) { - if ((tex->managed.dirty | tex->dirty_mip) && list_is_empty(&tex->list)) - list_add(&tex->list, &device->update_textures); - - tex->bind_count++; - } - if (old) { - old->bind_count--; - if (!old->bind_count) - list_delinit(&old->list); - } - - nine_bind(slot, tex); -} - -#if defined(DEBUG) || !defined(NDEBUG) -void -NineBaseTexture9_Dump( struct NineBaseTexture9 *This ); -#else -static inline void -NineBaseTexture9_Dump( struct NineBaseTexture9 *This ) { } -#endif - -#define BASETEX_REGISTER_UPDATE(t) do { \ - if (((t)->managed.dirty | ((t)->dirty_mip)) && (t)->bind_count) \ - if (list_is_empty(&(t)->list)) \ - list_add(&(t)->list, &(t)->base.base.device->update_textures); \ - } while(0) - -#endif /* _NINE_BASETEXTURE9_H_ */ diff --git a/src/gallium/state_trackers/nine/buffer9.c b/src/gallium/state_trackers/nine/buffer9.c deleted file mode 100644 index 629f33731ce..00000000000 --- a/src/gallium/state_trackers/nine/buffer9.c +++ /dev/null @@ -1,461 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * Copyright 2015 Patrick Rudolph - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "buffer9.h" -#include "device9.h" -#include "nine_buffer_upload.h" -#include "nine_helpers.h" -#include "nine_pipe.h" - -#include "pipe/p_screen.h" -#include "pipe/p_context.h" -#include "pipe/p_state.h" -#include "pipe/p_defines.h" -#include "pipe/p_format.h" -#include "util/u_box.h" -#include "util/u_inlines.h" - -#define DBG_CHANNEL (DBG_INDEXBUFFER|DBG_VERTEXBUFFER) - -HRESULT -NineBuffer9_ctor( struct NineBuffer9 *This, - struct NineUnknownParams *pParams, - D3DRESOURCETYPE Type, - DWORD Usage, - UINT Size, - D3DPOOL Pool ) -{ - struct pipe_resource *info = &This->base.info; - HRESULT hr; - - DBG("This=%p Size=0x%x Usage=%x Pool=%u\n", This, Size, Usage, Pool); - - user_assert(Pool != D3DPOOL_SCRATCH, D3DERR_INVALIDCALL); - - This->maps = MALLOC(sizeof(struct NineTransfer)); - if (!This->maps) - return E_OUTOFMEMORY; - This->nmaps = 0; - This->maxmaps = 1; - This->size = Size; - - info->screen = pParams->device->screen; - info->target = PIPE_BUFFER; - info->format = PIPE_FORMAT_R8_UNORM; - info->width0 = Size; - info->flags = 0; - - /* Note: WRITEONLY is just tip for resource placement, the resource - * can still be read (but slower). */ - info->bind = PIPE_BIND_VERTEX_BUFFER; - - /* It is hard to find clear information on where to place the buffer in - * memory depending on the flag. - * MSDN: resources are static, except for those with DYNAMIC, thus why you - * can only use DISCARD on them. - * ATI doc: The driver has the liberty it wants for having things static - * or not. - * MANAGED: Ram + uploads to Vram copy at unlock (msdn and nvidia doc say - * at first draw call using the buffer) - * DEFAULT + Usage = 0 => System memory backing for easy read access - * (That doc is very unclear on the details, like whether some copies to - * vram copy are involved or not). - * DEFAULT + WRITEONLY => Vram - * DEFAULT + WRITEONLY + DYNAMIC => Either Vram buffer or GTT_WC, depending on what the driver wants. - */ - if (Pool == D3DPOOL_SYSTEMMEM) - info->usage = PIPE_USAGE_STAGING; - else if (Pool == D3DPOOL_MANAGED) - info->usage = PIPE_USAGE_DEFAULT; - else if (Usage & D3DUSAGE_DYNAMIC && Usage & D3DUSAGE_WRITEONLY) - info->usage = PIPE_USAGE_STREAM; - else if (Usage & D3DUSAGE_WRITEONLY) - info->usage = PIPE_USAGE_DEFAULT; - /* For the remaining two, PIPE_USAGE_STAGING would probably be - * a good fit according to the doc. However it seems rather a mistake - * from apps to use these (mistakes that do really happen). Try - * to put the flags that are the best compromise between the real - * behaviour and what buggy apps should get for better performance. */ - else if (Usage & D3DUSAGE_DYNAMIC) - info->usage = PIPE_USAGE_STREAM; - else - info->usage = PIPE_USAGE_DYNAMIC; - - /* When Writeonly is not set, we don't want to enable the - * optimizations */ - This->discard_nooverwrite_only = !!(Usage & D3DUSAGE_WRITEONLY) && - pParams->device->buffer_upload; - /* if (pDesc->Usage & D3DUSAGE_DONOTCLIP) { } */ - /* if (pDesc->Usage & D3DUSAGE_NONSECURE) { } */ - /* if (pDesc->Usage & D3DUSAGE_NPATCHES) { } */ - /* if (pDesc->Usage & D3DUSAGE_POINTS) { } */ - /* if (pDesc->Usage & D3DUSAGE_RTPATCHES) { } */ - /* The buffer must be usable with both sw and hw - * vertex processing. It is expected to be slower with hw. */ - if (Usage & D3DUSAGE_SOFTWAREPROCESSING) - info->usage = PIPE_USAGE_STAGING; - /* if (pDesc->Usage & D3DUSAGE_TEXTAPI) { } */ - - info->height0 = 1; - info->depth0 = 1; - info->array_size = 1; - info->last_level = 0; - info->nr_samples = 0; - info->nr_storage_samples = 0; - - hr = NineResource9_ctor(&This->base, pParams, NULL, TRUE, - Type, Pool, Usage); - - if (FAILED(hr)) - return hr; - - if (Pool == D3DPOOL_MANAGED) { - This->managed.data = align_calloc( - nine_format_get_level_alloc_size(This->base.info.format, - Size, 1, 0), 32); - if (!This->managed.data) - return E_OUTOFMEMORY; - memset(This->managed.data, 0, Size); - This->managed.dirty = TRUE; - u_box_1d(0, Size, &This->managed.dirty_box); - list_inithead(&This->managed.list); - list_inithead(&This->managed.list2); - list_add(&This->managed.list2, &pParams->device->managed_buffers); - } - - return D3D_OK; -} - -void -NineBuffer9_dtor( struct NineBuffer9 *This ) -{ - DBG("This=%p\n", This); - - if (This->maps) { - while (This->nmaps) { - NineBuffer9_Unlock(This); - } - FREE(This->maps); - } - - if (This->base.pool == D3DPOOL_MANAGED) { - if (This->managed.data) - align_free(This->managed.data); - if (This->managed.list.prev != NULL && This->managed.list.next != NULL) - list_del(&This->managed.list); - if (This->managed.list2.prev != NULL && This->managed.list2.next != NULL) - list_del(&This->managed.list2); - } - - if (This->buf) - nine_upload_release_buffer(This->base.base.device->buffer_upload, This->buf); - - NineResource9_dtor(&This->base); -} - -struct pipe_resource * -NineBuffer9_GetResource( struct NineBuffer9 *This, unsigned *offset ) -{ - if (This->buf) - return nine_upload_buffer_resource_and_offset(This->buf, offset); - *offset = 0; - return NineResource9_GetResource(&This->base); -} - -static void -NineBuffer9_RebindIfRequired( struct NineBuffer9 *This, - struct NineDevice9 *device ) -{ - int i; - - if (!This->bind_count) - return; - for (i = 0; i < device->caps.MaxStreams; i++) { - if (device->state.stream[i] == (struct NineVertexBuffer9 *)This) - nine_context_set_stream_source(device, i, - (struct NineVertexBuffer9 *)This, - device->state.vtxbuf[i].buffer_offset, - device->state.vtxbuf[i].stride); - } - if (device->state.idxbuf == (struct NineIndexBuffer9 *)This) - nine_context_set_indices(device, (struct NineIndexBuffer9 *)This); -} - -HRESULT NINE_WINAPI -NineBuffer9_Lock( struct NineBuffer9 *This, - UINT OffsetToLock, - UINT SizeToLock, - void **ppbData, - DWORD Flags ) -{ - struct NineDevice9 *device = This->base.base.device; - struct pipe_box box; - struct pipe_context *pipe; - void *data; - unsigned usage; - - DBG("This=%p(pipe=%p) OffsetToLock=0x%x, SizeToLock=0x%x, Flags=0x%x\n", - This, This->base.resource, - OffsetToLock, SizeToLock, Flags); - - user_assert(ppbData, E_POINTER); - user_assert(!(Flags & ~(D3DLOCK_DISCARD | - D3DLOCK_DONOTWAIT | - D3DLOCK_NO_DIRTY_UPDATE | - D3DLOCK_NOSYSLOCK | - D3DLOCK_READONLY | - D3DLOCK_NOOVERWRITE)), D3DERR_INVALIDCALL); - - if (SizeToLock == 0) { - SizeToLock = This->size - OffsetToLock; - user_warn(OffsetToLock != 0); - } - - /* Write out of bound seems to have to be taken into account for these. - * TODO: Do more tests (is it only at buffer first lock ? etc). - * Since these buffers are supposed to be locked once and never - * writen again (MANAGED or DYNAMIC is used for the other uses cases), - * performance should be unaffected. */ - if (!(This->base.usage & D3DUSAGE_DYNAMIC) && This->base.pool != D3DPOOL_MANAGED) - SizeToLock = This->size - OffsetToLock; - - u_box_1d(OffsetToLock, SizeToLock, &box); - - if (This->base.pool == D3DPOOL_MANAGED) { - /* READONLY doesn't dirty the buffer */ - /* Tests on Win: READONLY doesn't wait for the upload */ - if (!(Flags & D3DLOCK_READONLY)) { - if (!This->managed.dirty) { - assert(list_is_empty(&This->managed.list)); - This->managed.dirty = TRUE; - This->managed.dirty_box = box; - if (p_atomic_read(&This->managed.pending_upload)) - nine_csmt_process(This->base.base.device); - } else - u_box_union_2d(&This->managed.dirty_box, &This->managed.dirty_box, &box); - /* Tests trying to draw while the buffer is locked show that - * MANAGED buffers are made dirty at Lock time */ - BASEBUF_REGISTER_UPDATE(This); - } - *ppbData = (char *)This->managed.data + OffsetToLock; - DBG("returning pointer %p\n", *ppbData); - This->nmaps++; - return D3D_OK; - } - - /* Driver ddi doc: READONLY is never passed to the device. So it can only - * have effect on things handled by the driver (MANAGED pool for example). - * Msdn doc: DISCARD and NOOVERWRITE are only for DYNAMIC. - * ATI doc: You can use DISCARD and NOOVERWRITE without DYNAMIC. - * Msdn doc: D3DLOCK_DONOTWAIT is not among the valid flags for buffers. - * Our tests: On win 7 nvidia, D3DLOCK_DONOTWAIT does return - * D3DERR_WASSTILLDRAWING if the resource is in use, except for DYNAMIC. - * Our tests: some apps do use both DISCARD and NOOVERWRITE at the same - * time. On windows it seems to return different pointer, thus indicating - * DISCARD is taken into account. - * Our tests: SYSTEMMEM doesn't DISCARD */ - - if (This->base.pool == D3DPOOL_SYSTEMMEM) - Flags &= ~(D3DLOCK_DISCARD | D3DLOCK_NOOVERWRITE); - - if (Flags & D3DLOCK_DISCARD) - usage = PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE; - else if (Flags & D3DLOCK_NOOVERWRITE) - usage = PIPE_TRANSFER_WRITE | PIPE_TRANSFER_UNSYNCHRONIZED; - else - /* Do not ask for READ if writeonly and default pool (should be safe enough, - * as the doc says app shouldn't expect reading to work with writeonly). - * Ignore for Systemmem as it has special behaviours. */ - usage = ((This->base.usage & D3DUSAGE_WRITEONLY) && This->base.pool == D3DPOOL_DEFAULT) ? - PIPE_TRANSFER_WRITE : - PIPE_TRANSFER_READ_WRITE; - if (Flags & D3DLOCK_DONOTWAIT && !(This->base.usage & D3DUSAGE_DYNAMIC)) - usage |= PIPE_TRANSFER_DONTBLOCK; - - This->discard_nooverwrite_only &= !!(Flags & (D3DLOCK_DISCARD | D3DLOCK_NOOVERWRITE)); - - if (This->nmaps == This->maxmaps) { - struct NineTransfer *newmaps = - REALLOC(This->maps, sizeof(struct NineTransfer)*This->maxmaps, - sizeof(struct NineTransfer)*(This->maxmaps << 1)); - if (newmaps == NULL) - return E_OUTOFMEMORY; - - This->maxmaps <<= 1; - This->maps = newmaps; - } - - if (This->buf && !This->discard_nooverwrite_only) { - struct pipe_box src_box; - unsigned offset; - struct pipe_resource *src_res; - DBG("Disabling nine_subbuffer for a buffer having" - "used a nine_subbuffer buffer\n"); - /* Copy buffer content to the buffer resource, which - * we will now use. - * Note: The behaviour may be different from what is expected - * with double lock. However applications can't really make expectations - * about double locks, and don't really use them, so that's ok. */ - src_res = nine_upload_buffer_resource_and_offset(This->buf, &offset); - u_box_1d(offset, This->size, &src_box); - - pipe = NineDevice9_GetPipe(device); - pipe->resource_copy_region(pipe, This->base.resource, 0, 0, 0, 0, - src_res, 0, &src_box); - /* Release previous resource */ - if (This->nmaps >= 1) - This->maps[This->nmaps-1].should_destroy_buf = true; - else - nine_upload_release_buffer(device->buffer_upload, This->buf); - This->buf = NULL; - /* Rebind buffer */ - NineBuffer9_RebindIfRequired(This, device); - } - - This->maps[This->nmaps].transfer = NULL; - This->maps[This->nmaps].is_pipe_secondary = false; - This->maps[This->nmaps].buf = NULL; - This->maps[This->nmaps].should_destroy_buf = false; - - if (This->discard_nooverwrite_only) { - if (This->buf && (Flags & D3DLOCK_DISCARD)) { - /* Release previous buffer */ - if (This->nmaps >= 1) - This->maps[This->nmaps-1].should_destroy_buf = true; - else - nine_upload_release_buffer(device->buffer_upload, This->buf); - This->buf = NULL; - } - - if (!This->buf) { - This->buf = nine_upload_create_buffer(device->buffer_upload, This->base.info.width0); - NineBuffer9_RebindIfRequired(This, device); - } - - if (This->buf) { - This->maps[This->nmaps].buf = This->buf; - This->nmaps++; - *ppbData = nine_upload_buffer_get_map(This->buf) + OffsetToLock; - return D3D_OK; - } else { - /* Fallback to normal path, and don't try again */ - This->discard_nooverwrite_only = false; - } - } - - /* Previous mappings may need pending commands to write to the - * buffer (staging buffer for example). Before a NOOVERWRITE, - * we thus need a finish, to guarantee any upload is finished. - * Note for discard_nooverwrite_only we don't need to do this - * check as neither discard nor nooverwrite have issues there */ - if (This->need_sync_if_nooverwrite && !(Flags & D3DLOCK_DISCARD) && - (Flags & D3DLOCK_NOOVERWRITE)) { - struct pipe_screen *screen = NineDevice9_GetScreen(device); - struct pipe_fence_handle *fence = NULL; - - pipe = NineDevice9_GetPipe(device); - pipe->flush(pipe, &fence, 0); - (void) screen->fence_finish(screen, NULL, fence, PIPE_TIMEOUT_INFINITE); - screen->fence_reference(screen, &fence, NULL); - } - This->need_sync_if_nooverwrite = !(Flags & (D3DLOCK_DISCARD | D3DLOCK_NOOVERWRITE)); - - /* When csmt is active, we want to avoid stalls as much as possible, - * and thus we want to create a new resource on discard and map it - * with the secondary pipe, instead of waiting on the main pipe. */ - if (Flags & D3DLOCK_DISCARD && device->csmt_active) { - struct pipe_screen *screen = NineDevice9_GetScreen(device); - struct pipe_resource *new_res = screen->resource_create(screen, &This->base.info); - if (new_res) { - /* Use the new resource */ - pipe_resource_reference(&This->base.resource, new_res); - pipe_resource_reference(&new_res, NULL); - usage = PIPE_TRANSFER_WRITE | PIPE_TRANSFER_UNSYNCHRONIZED; - NineBuffer9_RebindIfRequired(This, device); - This->maps[This->nmaps].is_pipe_secondary = TRUE; - } - } else if (Flags & D3DLOCK_NOOVERWRITE && device->csmt_active) - This->maps[This->nmaps].is_pipe_secondary = TRUE; - - if (This->maps[This->nmaps].is_pipe_secondary) - pipe = device->pipe_secondary; - else - pipe = NineDevice9_GetPipe(device); - - data = pipe->transfer_map(pipe, This->base.resource, 0, - usage, &box, &This->maps[This->nmaps].transfer); - - if (!data) { - DBG("pipe::transfer_map failed\n" - " usage = %x\n" - " box.x = %u\n" - " box.width = %u\n", - usage, box.x, box.width); - - if (Flags & D3DLOCK_DONOTWAIT) - return D3DERR_WASSTILLDRAWING; - return D3DERR_INVALIDCALL; - } - - DBG("returning pointer %p\n", data); - This->nmaps++; - *ppbData = data; - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineBuffer9_Unlock( struct NineBuffer9 *This ) -{ - struct NineDevice9 *device = This->base.base.device; - struct pipe_context *pipe; - DBG("This=%p\n", This); - - user_assert(This->nmaps > 0, D3DERR_INVALIDCALL); - This->nmaps--; - if (This->base.pool != D3DPOOL_MANAGED) { - if (!This->maps[This->nmaps].buf) { - pipe = This->maps[This->nmaps].is_pipe_secondary ? - device->pipe_secondary : - nine_context_get_pipe_acquire(device); - pipe->transfer_unmap(pipe, This->maps[This->nmaps].transfer); - /* We need to flush in case the driver does implicit copies */ - if (This->maps[This->nmaps].is_pipe_secondary) - pipe->flush(pipe, NULL, 0); - else - nine_context_get_pipe_release(device); - } else if (This->maps[This->nmaps].should_destroy_buf) - nine_upload_release_buffer(device->buffer_upload, This->maps[This->nmaps].buf); - } - return D3D_OK; -} - -void -NineBuffer9_SetDirty( struct NineBuffer9 *This ) -{ - assert(This->base.pool == D3DPOOL_MANAGED); - - This->managed.dirty = TRUE; - u_box_1d(0, This->size, &This->managed.dirty_box); - BASEBUF_REGISTER_UPDATE(This); -} diff --git a/src/gallium/state_trackers/nine/buffer9.h b/src/gallium/state_trackers/nine/buffer9.h deleted file mode 100644 index 1c142fcf64a..00000000000 --- a/src/gallium/state_trackers/nine/buffer9.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * Copyright 2015 Patrick Rudolph - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef _NINE_BUFFER9_H_ -#define _NINE_BUFFER9_H_ - -#include "device9.h" -#include "nine_buffer_upload.h" -#include "nine_state.h" -#include "resource9.h" -#include "pipe/p_context.h" -#include "pipe/p_state.h" -#include "util/list.h" - -struct pipe_screen; -struct pipe_context; -struct pipe_transfer; - -struct NineTransfer { - struct pipe_transfer *transfer; - bool is_pipe_secondary; - struct nine_subbuffer *buf; /* NULL unless subbuffer are used */ - bool should_destroy_buf; /* If the subbuffer should be destroyed */ -}; - -struct NineBuffer9 -{ - struct NineResource9 base; - - /* G3D */ - struct NineTransfer *maps; - int nmaps, maxmaps; - UINT size; - - int16_t bind_count; /* to Device9->state.stream */ - /* Whether only discard and nooverwrite were used so far - * for this buffer. Allows some optimization. */ - boolean discard_nooverwrite_only; - boolean need_sync_if_nooverwrite; - struct nine_subbuffer *buf; - - /* Specific to managed buffers */ - struct { - void *data; - boolean dirty; - struct pipe_box dirty_box; - struct list_head list; /* for update_buffers */ - struct list_head list2; /* for managed_buffers */ - unsigned pending_upload; /* for uploads */ - } managed; -}; -static inline struct NineBuffer9 * -NineBuffer9( void *data ) -{ - return (struct NineBuffer9 *)data; -} - -HRESULT -NineBuffer9_ctor( struct NineBuffer9 *This, - struct NineUnknownParams *pParams, - D3DRESOURCETYPE Type, - DWORD Usage, - UINT Size, - D3DPOOL Pool ); - -void -NineBuffer9_dtor( struct NineBuffer9 *This ); - -struct pipe_resource * -NineBuffer9_GetResource( struct NineBuffer9 *This, unsigned *offset ); - -HRESULT NINE_WINAPI -NineBuffer9_Lock( struct NineBuffer9 *This, - UINT OffsetToLock, - UINT SizeToLock, - void **ppbData, - DWORD Flags ); - -HRESULT NINE_WINAPI -NineBuffer9_Unlock( struct NineBuffer9 *This ); - -static inline void -NineBuffer9_Upload( struct NineBuffer9 *This ) -{ - struct NineDevice9 *device = This->base.base.device; - - assert(This->base.pool == D3DPOOL_MANAGED && This->managed.dirty); - nine_context_range_upload(device, &This->managed.pending_upload, - (struct NineUnknown *)This, - This->base.resource, - This->managed.dirty_box.x, - This->managed.dirty_box.width, - (char *)This->managed.data + This->managed.dirty_box.x); - This->managed.dirty = FALSE; -} - -static void inline -NineBindBufferToDevice( struct NineDevice9 *device, - struct NineBuffer9 **slot, - struct NineBuffer9 *buf ) -{ - struct NineBuffer9 *old = *slot; - - if (buf) { - if ((buf->managed.dirty) && list_is_empty(&buf->managed.list)) - list_add(&buf->managed.list, &device->update_buffers); - buf->bind_count++; - } - if (old) { - old->bind_count--; - if (!old->bind_count && old->managed.dirty) - list_delinit(&old->managed.list); - } - - nine_bind(slot, buf); -} - -void -NineBuffer9_SetDirty( struct NineBuffer9 *This ); - -#define BASEBUF_REGISTER_UPDATE(b) { \ - if ((b)->managed.dirty && (b)->bind_count) \ - if (list_is_empty(&(b)->managed.list)) \ - list_add(&(b)->managed.list, &(b)->base.base.device->update_buffers); \ - } - -#endif /* _NINE_BUFFER9_H_ */ diff --git a/src/gallium/state_trackers/nine/cryptosession9.c b/src/gallium/state_trackers/nine/cryptosession9.c deleted file mode 100644 index c656f72a215..00000000000 --- a/src/gallium/state_trackers/nine/cryptosession9.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "cryptosession9.h" - -#define DBG_CHANNEL DBG_CRYPTOSESSION - -HRESULT NINE_WINAPI -NineCryptoSession9_GetCertificateSize( struct NineCryptoSession9 *This, - UINT *pCertificateSize ) -{ - STUB(D3DERR_INVALIDCALL); -} - -HRESULT NINE_WINAPI -NineCryptoSession9_GetCertificate( struct NineCryptoSession9 *This, - UINT CertifacteSize, - BYTE *ppCertificate ) -{ - STUB(D3DERR_INVALIDCALL); -} - -HRESULT NINE_WINAPI -NineCryptoSession9_NegotiateKeyExchange( struct NineCryptoSession9 *This, - UINT DataSize, - void *pData ) -{ - STUB(D3DERR_INVALIDCALL); -} - -HRESULT NINE_WINAPI -NineCryptoSession9_EncryptionBlt( struct NineCryptoSession9 *This, - IDirect3DSurface9 *pSrcSurface, - IDirect3DSurface9 *pDstSurface, - UINT DstSurfaceSize, - void *pIV ) -{ - STUB(D3DERR_INVALIDCALL); -} - -HRESULT NINE_WINAPI -NineCryptoSession9_DecryptionBlt( struct NineCryptoSession9 *This, - IDirect3DSurface9 *pSrcSurface, - IDirect3DSurface9 *pDstSurface, - UINT SrcSurfaceSize, - D3DENCRYPTED_BLOCK_INFO *pEncryptedBlockInfo, - void *pContentKey, - void *pIV ) -{ - STUB(D3DERR_INVALIDCALL); -} - -HRESULT NINE_WINAPI -NineCryptoSession9_GetSurfacePitch( struct NineCryptoSession9 *This, - IDirect3DSurface9 *pSrcSurface, - UINT *pSurfacePitch ) -{ - STUB(D3DERR_INVALIDCALL); -} - -HRESULT NINE_WINAPI -NineCryptoSession9_StartSessionKeyRefresh( struct NineCryptoSession9 *This, - void *pRandomNumber, - UINT RandomNumberSize ) -{ - STUB(D3DERR_INVALIDCALL); -} - -HRESULT NINE_WINAPI -NineCryptoSession9_FinishSessionKeyRefresh( struct NineCryptoSession9 *This ) -{ - STUB(D3DERR_INVALIDCALL); -} - -HRESULT NINE_WINAPI -NineCryptoSession9_GetEncryptionBltKey( struct NineCryptoSession9 *This, - void *pReadbackKey, - UINT KeySize ) -{ - STUB(D3DERR_INVALIDCALL); -} - -IDirect3DCryptoSession9Vtbl NineCryptoSession9_vtable = { - (void *)NineUnknown_QueryInterface, - (void *)NineUnknown_AddRef, - (void *)NineUnknown_Release, - (void *)NineCryptoSession9_GetCertificateSize, - (void *)NineCryptoSession9_GetCertificate, - (void *)NineCryptoSession9_NegotiateKeyExchange, - (void *)NineCryptoSession9_EncryptionBlt, - (void *)NineCryptoSession9_DecryptionBlt, - (void *)NineCryptoSession9_GetSurfacePitch, - (void *)NineCryptoSession9_StartSessionKeyRefresh, - (void *)NineCryptoSession9_FinishSessionKeyRefresh, - (void *)NineCryptoSession9_GetEncryptionBltKey -}; diff --git a/src/gallium/state_trackers/nine/cryptosession9.h b/src/gallium/state_trackers/nine/cryptosession9.h deleted file mode 100644 index 9904455a000..00000000000 --- a/src/gallium/state_trackers/nine/cryptosession9.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef _NINE_CRYPTOSESSION9_H_ -#define _NINE_CRYPTOSESSION9_H_ - -#include "iunknown.h" - -struct NineCryptoSession9 -{ - struct NineUnknown base; -}; -static inline struct NineCryptoSession9 * -NineCryptoSession9( void *data ) -{ - return (struct NineCryptoSession9 *)data; -} - -HRESULT NINE_WINAPI -NineCryptoSession9_GetCertificateSize( struct NineCryptoSession9 *This, - UINT *pCertificateSize ); - -HRESULT NINE_WINAPI -NineCryptoSession9_GetCertificate( struct NineCryptoSession9 *This, - UINT CertifacteSize, - BYTE *ppCertificate ); - -HRESULT NINE_WINAPI -NineCryptoSession9_NegotiateKeyExchange( struct NineCryptoSession9 *This, - UINT DataSize, - void *pData ); - -HRESULT NINE_WINAPI -NineCryptoSession9_EncryptionBlt( struct NineCryptoSession9 *This, - IDirect3DSurface9 *pSrcSurface, - IDirect3DSurface9 *pDstSurface, - UINT DstSurfaceSize, - void *pIV ); - -HRESULT NINE_WINAPI -NineCryptoSession9_DecryptionBlt( struct NineCryptoSession9 *This, - IDirect3DSurface9 *pSrcSurface, - IDirect3DSurface9 *pDstSurface, - UINT SrcSurfaceSize, - D3DENCRYPTED_BLOCK_INFO *pEncryptedBlockInfo, - void *pContentKey, - void *pIV ); - -HRESULT NINE_WINAPI -NineCryptoSession9_GetSurfacePitch( struct NineCryptoSession9 *This, - IDirect3DSurface9 *pSrcSurface, - UINT *pSurfacePitch ); - -HRESULT NINE_WINAPI -NineCryptoSession9_StartSessionKeyRefresh( struct NineCryptoSession9 *This, - void *pRandomNumber, - UINT RandomNumberSize ); - -HRESULT NINE_WINAPI -NineCryptoSession9_FinishSessionKeyRefresh( struct NineCryptoSession9 *This ); - -HRESULT NINE_WINAPI -NineCryptoSession9_GetEncryptionBltKey( struct NineCryptoSession9 *This, - void *pReadbackKey, - UINT KeySize ); - -#endif /* _NINE_CRYPTOSESSION9_H_ */ diff --git a/src/gallium/state_trackers/nine/cubetexture9.c b/src/gallium/state_trackers/nine/cubetexture9.c deleted file mode 100644 index 89821682f8f..00000000000 --- a/src/gallium/state_trackers/nine/cubetexture9.c +++ /dev/null @@ -1,350 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "c99_alloca.h" - -#include "device9.h" -#include "cubetexture9.h" -#include "nine_helpers.h" -#include "nine_pipe.h" - -#define DBG_CHANNEL DBG_CUBETEXTURE - - -static HRESULT -NineCubeTexture9_ctor( struct NineCubeTexture9 *This, - struct NineUnknownParams *pParams, - UINT EdgeLength, UINT Levels, - DWORD Usage, - D3DFORMAT Format, - D3DPOOL Pool, - HANDLE *pSharedHandle ) -{ - struct pipe_resource *info = &This->base.base.info; - struct pipe_screen *screen = pParams->device->screen; - enum pipe_format pf; - unsigned i, l, f, offset, face_size = 0; - unsigned *level_offsets = NULL; - D3DSURFACE_DESC sfdesc; - void *p; - HRESULT hr; - - DBG("This=%p pParams=%p EdgeLength=%u Levels=%u Usage=%d " - "Format=%d Pool=%d pSharedHandle=%p\n", - This, pParams, EdgeLength, Levels, Usage, - Format, Pool, pSharedHandle); - - user_assert(EdgeLength, D3DERR_INVALIDCALL); - - /* user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); */ - user_assert(!pSharedHandle, D3DERR_INVALIDCALL); /* TODO */ - - user_assert(!(Usage & D3DUSAGE_AUTOGENMIPMAP) || - (Pool != D3DPOOL_SYSTEMMEM && Levels <= 1), D3DERR_INVALIDCALL); - - if (Usage & D3DUSAGE_AUTOGENMIPMAP) - Levels = 0; - - pf = d3d9_to_pipe_format_checked(screen, Format, PIPE_TEXTURE_CUBE, 0, - PIPE_BIND_SAMPLER_VIEW, FALSE, - Pool == D3DPOOL_SCRATCH); - - if (pf == PIPE_FORMAT_NONE) - return D3DERR_INVALIDCALL; - - if (compressed_format(Format)) { - const unsigned w = util_format_get_blockwidth(pf); - const unsigned h = util_format_get_blockheight(pf); - - user_assert(!(EdgeLength % w) && !(EdgeLength % h), D3DERR_INVALIDCALL); - } - - info->screen = pParams->device->screen; - info->target = PIPE_TEXTURE_CUBE; - info->format = pf; - info->width0 = EdgeLength; - info->height0 = EdgeLength; - info->depth0 = 1; - if (Levels) - info->last_level = Levels - 1; - else - info->last_level = util_logbase2(EdgeLength); - info->array_size = 6; - info->nr_samples = 0; - info->nr_storage_samples = 0; - info->bind = PIPE_BIND_SAMPLER_VIEW; - info->usage = PIPE_USAGE_DEFAULT; - info->flags = 0; - - if (Usage & D3DUSAGE_RENDERTARGET) - info->bind |= PIPE_BIND_RENDER_TARGET; - if (Usage & D3DUSAGE_DEPTHSTENCIL) - info->bind |= PIPE_BIND_DEPTH_STENCIL; - - if (Usage & D3DUSAGE_DYNAMIC) { - info->usage = PIPE_USAGE_DYNAMIC; - } - if (Usage & D3DUSAGE_SOFTWAREPROCESSING) - DBG("Application asked for Software Vertex Processing, " - "but this is unimplemented\n"); - - if (Pool != D3DPOOL_DEFAULT) { - level_offsets = alloca(sizeof(unsigned) * (info->last_level + 1)); - face_size = nine_format_get_size_and_offsets(pf, level_offsets, - EdgeLength, EdgeLength, - info->last_level); - This->managed_buffer = align_calloc(6 * face_size, 32); - if (!This->managed_buffer) - return E_OUTOFMEMORY; - } - - This->surfaces = CALLOC(6 * (info->last_level + 1), sizeof(*This->surfaces)); - if (!This->surfaces) - return E_OUTOFMEMORY; - - hr = NineBaseTexture9_ctor(&This->base, pParams, NULL, D3DRTYPE_CUBETEXTURE, - Format, Pool, Usage); - if (FAILED(hr)) - return hr; - This->base.pstype = 2; - - /* Create all the surfaces right away. - * They manage backing storage, and transfers (LockRect) are deferred - * to them. - */ - sfdesc.Format = Format; - sfdesc.Type = D3DRTYPE_SURFACE; - sfdesc.Usage = Usage; - sfdesc.Pool = Pool; - sfdesc.MultiSampleType = D3DMULTISAMPLE_NONE; - sfdesc.MultiSampleQuality = 0; - /* We allocate the memory for the surfaces as continous blocks. - * This is the expected behaviour, however we haven't tested for - * cube textures in which order the faces/levels should be in memory - */ - for (f = 0; f < 6; f++) { - offset = f * face_size; - for (l = 0; l <= info->last_level; l++) { - sfdesc.Width = sfdesc.Height = u_minify(EdgeLength, l); - p = This->managed_buffer ? This->managed_buffer + offset + - level_offsets[l] : NULL; - - hr = NineSurface9_new(This->base.base.base.device, NineUnknown(This), - This->base.base.resource, p, D3DRTYPE_CUBETEXTURE, - l, f, &sfdesc, &This->surfaces[f + 6 * l]); - if (FAILED(hr)) - return hr; - } - } - - for (i = 0; i < 6; ++i) { - /* Textures start initially dirty */ - This->dirty_rect[i].width = EdgeLength; - This->dirty_rect[i].height = EdgeLength; - This->dirty_rect[i].depth = 1; - } - - return D3D_OK; -} - -static void -NineCubeTexture9_dtor( struct NineCubeTexture9 *This ) -{ - unsigned i; - - DBG("This=%p\n", This); - - if (This->surfaces) { - for (i = 0; i < (This->base.base.info.last_level + 1) * 6; ++i) - NineUnknown_Destroy(&This->surfaces[i]->base.base); - FREE(This->surfaces); - } - - if (This->managed_buffer) - align_free(This->managed_buffer); - - NineBaseTexture9_dtor(&This->base); -} - -HRESULT NINE_WINAPI -NineCubeTexture9_GetLevelDesc( struct NineCubeTexture9 *This, - UINT Level, - D3DSURFACE_DESC *pDesc ) -{ - DBG("This=%p Level=%u pDesc=%p\n", This, Level, pDesc); - - user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); - user_assert(Level == 0 || !(This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP), - D3DERR_INVALIDCALL); - - *pDesc = This->surfaces[Level * 6]->desc; - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineCubeTexture9_GetCubeMapSurface( struct NineCubeTexture9 *This, - D3DCUBEMAP_FACES FaceType, - UINT Level, - IDirect3DSurface9 **ppCubeMapSurface ) -{ - const unsigned s = Level * 6 + FaceType; - - DBG("This=%p FaceType=%d Level=%u ppCubeMapSurface=%p\n", - This, FaceType, Level, ppCubeMapSurface); - - user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); - user_assert(Level == 0 || !(This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP), - D3DERR_INVALIDCALL); - user_assert(FaceType < 6, D3DERR_INVALIDCALL); - - NineUnknown_AddRef(NineUnknown(This->surfaces[s])); - *ppCubeMapSurface = (IDirect3DSurface9 *)This->surfaces[s]; - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineCubeTexture9_LockRect( struct NineCubeTexture9 *This, - D3DCUBEMAP_FACES FaceType, - UINT Level, - D3DLOCKED_RECT *pLockedRect, - const RECT *pRect, - DWORD Flags ) -{ - const unsigned s = Level * 6 + FaceType; - - DBG("This=%p FaceType=%d Level=%u pLockedRect=%p pRect=%p Flags=%d\n", - This, FaceType, Level, pLockedRect, pRect, Flags); - - user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); - user_assert(Level == 0 || !(This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP), - D3DERR_INVALIDCALL); - user_assert(FaceType < 6, D3DERR_INVALIDCALL); - - return NineSurface9_LockRect(This->surfaces[s], pLockedRect, pRect, Flags); -} - -HRESULT NINE_WINAPI -NineCubeTexture9_UnlockRect( struct NineCubeTexture9 *This, - D3DCUBEMAP_FACES FaceType, - UINT Level ) -{ - const unsigned s = Level * 6 + FaceType; - - DBG("This=%p FaceType=%d Level=%u\n", This, FaceType, Level); - - user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); - user_assert(FaceType < 6, D3DERR_INVALIDCALL); - - return NineSurface9_UnlockRect(This->surfaces[s]); -} - -HRESULT NINE_WINAPI -NineCubeTexture9_AddDirtyRect( struct NineCubeTexture9 *This, - D3DCUBEMAP_FACES FaceType, - const RECT *pDirtyRect ) -{ - DBG("This=%p FaceType=%d pDirtyRect=%p\n", This, FaceType, pDirtyRect); - - user_assert(FaceType < 6, D3DERR_INVALIDCALL); - - if (This->base.base.pool != D3DPOOL_MANAGED) { - if (This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP) { - This->base.dirty_mip = TRUE; - BASETEX_REGISTER_UPDATE(&This->base); - } - return D3D_OK; - } - - if (This->base.base.pool == D3DPOOL_MANAGED) { - This->base.managed.dirty = TRUE; - BASETEX_REGISTER_UPDATE(&This->base); - } - - if (!pDirtyRect) { - u_box_origin_2d(This->base.base.info.width0, - This->base.base.info.height0, - &This->dirty_rect[FaceType]); - } else { - if (This->dirty_rect[FaceType].width == 0) { - rect_to_pipe_box_clamp(&This->dirty_rect[FaceType], pDirtyRect); - } else { - struct pipe_box box; - rect_to_pipe_box_clamp(&box, pDirtyRect); - u_box_union_2d(&This->dirty_rect[FaceType], &This->dirty_rect[FaceType], - &box); - } - (void) u_box_clip_2d(&This->dirty_rect[FaceType], - &This->dirty_rect[FaceType], - This->base.base.info.width0, - This->base.base.info.height0); - } - return D3D_OK; -} - -IDirect3DCubeTexture9Vtbl NineCubeTexture9_vtable = { - (void *)NineUnknown_QueryInterface, - (void *)NineUnknown_AddRef, - (void *)NineUnknown_Release, - (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */ - (void *)NineUnknown_SetPrivateData, - (void *)NineUnknown_GetPrivateData, - (void *)NineUnknown_FreePrivateData, - (void *)NineResource9_SetPriority, - (void *)NineResource9_GetPriority, - (void *)NineBaseTexture9_PreLoad, - (void *)NineResource9_GetType, - (void *)NineBaseTexture9_SetLOD, - (void *)NineBaseTexture9_GetLOD, - (void *)NineBaseTexture9_GetLevelCount, - (void *)NineBaseTexture9_SetAutoGenFilterType, - (void *)NineBaseTexture9_GetAutoGenFilterType, - (void *)NineBaseTexture9_GenerateMipSubLevels, - (void *)NineCubeTexture9_GetLevelDesc, - (void *)NineCubeTexture9_GetCubeMapSurface, - (void *)NineCubeTexture9_LockRect, - (void *)NineCubeTexture9_UnlockRect, - (void *)NineCubeTexture9_AddDirtyRect -}; - -static const GUID *NineCubeTexture9_IIDs[] = { - &IID_IDirect3DCubeTexture9, - &IID_IDirect3DBaseTexture9, - &IID_IDirect3DResource9, - &IID_IUnknown, - NULL -}; - -HRESULT -NineCubeTexture9_new( struct NineDevice9 *pDevice, - UINT EdgeLength, UINT Levels, - DWORD Usage, - D3DFORMAT Format, - D3DPOOL Pool, - struct NineCubeTexture9 **ppOut, - HANDLE *pSharedHandle ) -{ - NINE_DEVICE_CHILD_NEW(CubeTexture9, ppOut, pDevice, - EdgeLength, Levels, - Usage, Format, Pool, pSharedHandle); -} diff --git a/src/gallium/state_trackers/nine/cubetexture9.h b/src/gallium/state_trackers/nine/cubetexture9.h deleted file mode 100644 index 129789d0d69..00000000000 --- a/src/gallium/state_trackers/nine/cubetexture9.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef _NINE_CUBETEXTURE9_H_ -#define _NINE_CUBETEXTURE9_H_ - -#include "basetexture9.h" -#include "surface9.h" - -struct NineCubeTexture9 -{ - struct NineBaseTexture9 base; - struct NineSurface9 **surfaces; - struct pipe_box dirty_rect[6]; /* covers all mip levels */ - uint8_t *managed_buffer; -}; -static inline struct NineCubeTexture9 * -NineCubeTexture9( void *data ) -{ - return (struct NineCubeTexture9 *)data; -} - -HRESULT -NineCubeTexture9_new( struct NineDevice9 *pDevice, - UINT EdgeLength, UINT Levels, - DWORD Usage, - D3DFORMAT Format, - D3DPOOL Pool, - struct NineCubeTexture9 **ppOut, - HANDLE *pSharedHandle ); - -HRESULT NINE_WINAPI -NineCubeTexture9_GetLevelDesc( struct NineCubeTexture9 *This, - UINT Level, - D3DSURFACE_DESC *pDesc ); - -HRESULT NINE_WINAPI -NineCubeTexture9_GetCubeMapSurface( struct NineCubeTexture9 *This, - D3DCUBEMAP_FACES FaceType, - UINT Level, - IDirect3DSurface9 **ppCubeMapSurface ); - -HRESULT NINE_WINAPI -NineCubeTexture9_LockRect( struct NineCubeTexture9 *This, - D3DCUBEMAP_FACES FaceType, - UINT Level, - D3DLOCKED_RECT *pLockedRect, - const RECT *pRect, - DWORD Flags ); - -HRESULT NINE_WINAPI -NineCubeTexture9_UnlockRect( struct NineCubeTexture9 *This, - D3DCUBEMAP_FACES FaceType, - UINT Level ); - -HRESULT NINE_WINAPI -NineCubeTexture9_AddDirtyRect( struct NineCubeTexture9 *This, - D3DCUBEMAP_FACES FaceType, - const RECT *pDirtyRect ); - -#endif /* _NINE_CUBETEXTURE9_H_ */ diff --git a/src/gallium/state_trackers/nine/device9.c b/src/gallium/state_trackers/nine/device9.c deleted file mode 100644 index c5b5eff128e..00000000000 --- a/src/gallium/state_trackers/nine/device9.c +++ /dev/null @@ -1,4053 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "device9.h" -#include "stateblock9.h" -#include "surface9.h" -#include "swapchain9.h" -#include "swapchain9ex.h" -#include "indexbuffer9.h" -#include "vertexbuffer9.h" -#include "vertexdeclaration9.h" -#include "vertexshader9.h" -#include "pixelshader9.h" -#include "query9.h" -#include "texture9.h" -#include "cubetexture9.h" -#include "volumetexture9.h" -#include "nine_buffer_upload.h" -#include "nine_helpers.h" -#include "nine_pipe.h" -#include "nine_ff.h" -#include "nine_dump.h" -#include "nine_limits.h" - -#include "pipe/p_screen.h" -#include "pipe/p_context.h" -#include "pipe/p_config.h" -#include "util/u_math.h" -#include "util/u_inlines.h" -#include "util/u_hash_table.h" -#include "util/format/u_format.h" -#include "util/u_surface.h" -#include "util/u_upload_mgr.h" -#include "hud/hud_context.h" -#include "compiler/glsl_types.h" - -#include "cso_cache/cso_context.h" - -#define DBG_CHANNEL DBG_DEVICE - -#if defined(PIPE_CC_GCC) && (defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)) - -static void nine_setup_fpu() -{ - uint16_t c; - - __asm__ __volatile__ ("fnstcw %0" : "=m" (*&c)); - - /* clear the control word */ - c &= 0xF0C0; - /* d3d9 doc/wine tests: mask all exceptions, use single-precision - * and round to nearest */ - c |= 0x003F; - - __asm__ __volatile__ ("fldcw %0" : : "m" (*&c)); -} - -#else - -static void nine_setup_fpu(void) -{ - WARN_ONCE("FPU setup not supported on non-x86 platforms\n"); -} - -#endif - -void -NineDevice9_SetDefaultState( struct NineDevice9 *This, boolean is_reset ) -{ - struct NineSurface9 *refSurf = NULL; - - DBG("This=%p is_reset=%d\n", This, (int) is_reset); - - assert(!This->is_recording); - - nine_state_set_defaults(This, &This->caps, is_reset); - - refSurf = This->swapchains[0]->buffers[0]; - assert(refSurf); - - This->state.viewport.X = 0; - This->state.viewport.Y = 0; - This->state.viewport.Width = refSurf->desc.Width; - This->state.viewport.Height = refSurf->desc.Height; - - nine_context_set_viewport(This, &This->state.viewport); - - This->state.scissor.minx = 0; - This->state.scissor.miny = 0; - This->state.scissor.maxx = refSurf->desc.Width; - This->state.scissor.maxy = refSurf->desc.Height; - - nine_context_set_scissor(This, &This->state.scissor); - - if (This->nswapchains && This->swapchains[0]->params.EnableAutoDepthStencil) { - nine_context_set_render_state(This, D3DRS_ZENABLE, TRUE); - This->state.rs_advertised[D3DRS_ZENABLE] = TRUE; - } - if (This->state.rs_advertised[D3DRS_ZENABLE]) - NineDevice9_SetDepthStencilSurface( - This, (IDirect3DSurface9 *)This->swapchains[0]->zsbuf); -} - -#define GET_PCAP(n) pScreen->get_param(pScreen, PIPE_CAP_##n) -HRESULT -NineDevice9_ctor( struct NineDevice9 *This, - struct NineUnknownParams *pParams, - struct pipe_screen *pScreen, - D3DDEVICE_CREATION_PARAMETERS *pCreationParameters, - D3DCAPS9 *pCaps, - D3DPRESENT_PARAMETERS *pPresentationParameters, - IDirect3D9 *pD3D9, - ID3DPresentGroup *pPresentationGroup, - struct d3dadapter9_context *pCTX, - boolean ex, - D3DDISPLAYMODEEX *pFullscreenDisplayMode, - int minorVersionNum ) -{ - unsigned i; - HRESULT hr = NineUnknown_ctor(&This->base, pParams); - - DBG("This=%p pParams=%p pScreen=%p pCreationParameters=%p pCaps=%p pPresentationParameters=%p " - "pD3D9=%p pPresentationGroup=%p pCTX=%p ex=%d pFullscreenDisplayMode=%p\n", - This, pParams, pScreen, pCreationParameters, pCaps, pPresentationParameters, pD3D9, - pPresentationGroup, pCTX, (int) ex, pFullscreenDisplayMode); - - if (FAILED(hr)) { return hr; } - - /* NIR shaders need to use GLSL types so let's initialize them here */ - glsl_type_singleton_init_or_ref(); - - list_inithead(&This->update_buffers); - list_inithead(&This->update_textures); - list_inithead(&This->managed_buffers); - list_inithead(&This->managed_textures); - - This->screen = pScreen; - This->screen_sw = pCTX->ref; - This->caps = *pCaps; - This->d3d9 = pD3D9; - This->params = *pCreationParameters; - This->ex = ex; - This->present = pPresentationGroup; - This->minor_version_num = minorVersionNum; - - IDirect3D9_AddRef(This->d3d9); - ID3DPresentGroup_AddRef(This->present); - - if (!(This->params.BehaviorFlags & D3DCREATE_FPU_PRESERVE)) - nine_setup_fpu(); - - if (This->params.BehaviorFlags & D3DCREATE_SOFTWARE_VERTEXPROCESSING) { - DBG("Application asked full Software Vertex Processing.\n"); - This->swvp = true; - This->may_swvp = true; - } else - This->swvp = false; - if (This->params.BehaviorFlags & D3DCREATE_MIXED_VERTEXPROCESSING) { - DBG("Application asked mixed Software Vertex Processing.\n"); - This->may_swvp = true; - } - This->context.swvp = This->swvp; - /* TODO: check if swvp is resetted by device Resets */ - - if (This->may_swvp && - (This->screen->get_shader_param(This->screen, PIPE_SHADER_VERTEX, - PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE) - < (NINE_MAX_CONST_F_SWVP/2) * sizeof(float[4]) || - This->screen->get_shader_param(This->screen, PIPE_SHADER_VERTEX, - PIPE_SHADER_CAP_MAX_CONST_BUFFERS) < 5)) { - /* Note: We just go on, some apps never use the abilities of - * swvp, and just set more constants than allowed at init. - * Only cards we support that are affected are the r500 */ - WARN("Card unable to handle Software Vertex Processing. Game may fail\n"); - } - - /* When may_swvp, SetConstant* limits are different */ - if (This->may_swvp) - This->caps.MaxVertexShaderConst = NINE_MAX_CONST_F_SWVP; - - This->context.pipe = This->screen->context_create(This->screen, NULL, 0); - This->pipe_secondary = This->screen->context_create(This->screen, NULL, 0); - if (!This->context.pipe || !This->pipe_secondary) { return E_OUTOFMEMORY; } /* guess */ - This->pipe_sw = This->screen_sw->context_create(This->screen_sw, NULL, 0); - if (!This->pipe_sw) { return E_OUTOFMEMORY; } - - This->context.cso = cso_create_context(This->context.pipe, 0); - if (!This->context.cso) { return E_OUTOFMEMORY; } /* also a guess */ - This->cso_sw = cso_create_context(This->pipe_sw, 0); - if (!This->cso_sw) { return E_OUTOFMEMORY; } - - /* Create first, it messes up our state. */ - This->hud = hud_create(This->context.cso, NULL); /* NULL result is fine */ - - /* Available memory counter. Updated only for allocations with this device - * instance. This is the Win 7 behavior. - * Win XP shares this counter across multiple devices. */ - This->available_texture_mem = This->screen->get_param(This->screen, PIPE_CAP_VIDEO_MEMORY); - if (This->available_texture_mem < 4096) - This->available_texture_mem <<= 20; - else - This->available_texture_mem = UINT_MAX; - /* We cap texture memory usage to 80% of what is reported free initially - * This helps get closer Win behaviour. For example VertexBuffer allocation - * still succeeds when texture allocation fails. */ - This->available_texture_limit = This->available_texture_mem * 20LL / 100LL; - - /* create implicit swapchains */ - This->nswapchains = ID3DPresentGroup_GetMultiheadCount(This->present); - This->swapchains = CALLOC(This->nswapchains, - sizeof(struct NineSwapChain9 *)); - if (!This->swapchains) { return E_OUTOFMEMORY; } - - for (i = 0; i < This->nswapchains; ++i) { - ID3DPresent *present; - - hr = ID3DPresentGroup_GetPresent(This->present, i, &present); - if (FAILED(hr)) - return hr; - - if (ex) { - D3DDISPLAYMODEEX *mode = NULL; - struct NineSwapChain9Ex **ret = - (struct NineSwapChain9Ex **)&This->swapchains[i]; - - if (pFullscreenDisplayMode) mode = &(pFullscreenDisplayMode[i]); - /* when this is a Device9Ex, it should create SwapChain9Exs */ - hr = NineSwapChain9Ex_new(This, TRUE, present, - &pPresentationParameters[i], pCTX, - This->params.hFocusWindow, mode, ret); - } else { - hr = NineSwapChain9_new(This, TRUE, present, - &pPresentationParameters[i], pCTX, - This->params.hFocusWindow, - &This->swapchains[i]); - } - - ID3DPresent_Release(present); - if (FAILED(hr)) - return hr; - NineUnknown_ConvertRefToBind(NineUnknown(This->swapchains[i])); - - hr = NineSwapChain9_GetBackBuffer(This->swapchains[i], 0, - D3DBACKBUFFER_TYPE_MONO, - (IDirect3DSurface9 **) - &This->state.rt[i]); - if (FAILED(hr)) - return hr; - NineUnknown_ConvertRefToBind(NineUnknown(This->state.rt[i])); - nine_bind(&This->context.rt[i], This->state.rt[i]); - } - - /* Initialize CSMT */ - /* r600, radeonsi and iris are thread safe. */ - if (pCTX->csmt_force == 1) - This->csmt_active = true; - else if (pCTX->csmt_force == 0) - This->csmt_active = false; - else if (strstr(pScreen->get_name(pScreen), "AMD") != NULL) - This->csmt_active = true; - else if (strstr(pScreen->get_name(pScreen), "Intel") != NULL) - This->csmt_active = true; - - /* We rely on u_upload_mgr using persistent coherent buffers (which don't - * require flush to work in multi-pipe_context scenario) for vertex and - * index buffers */ - if (!GET_PCAP(BUFFER_MAP_PERSISTENT_COHERENT)) - This->csmt_active = false; - - if (This->csmt_active) { - This->csmt_ctx = nine_csmt_create(This); - if (!This->csmt_ctx) - return E_OUTOFMEMORY; - } - - if (This->csmt_active) - DBG("\033[1;32mCSMT is active\033[0m\n"); - - This->workarounds.dynamic_texture_workaround = pCTX->dynamic_texture_workaround; - - This->buffer_upload = nine_upload_create(This->pipe_secondary, 4 * 1024 * 1024, 4); - - /* Initialize a dummy VBO to be used when a vertex declaration does not - * specify all the inputs needed by vertex shader, on win default behavior - * is to pass 0,0,0,0 to the shader */ - { - struct pipe_transfer *transfer; - struct pipe_resource tmpl; - struct pipe_box box; - unsigned char *data; - - memset(&tmpl, 0, sizeof(tmpl)); - tmpl.target = PIPE_BUFFER; - tmpl.format = PIPE_FORMAT_R8_UNORM; - tmpl.width0 = 16; /* 4 floats */ - tmpl.height0 = 1; - tmpl.depth0 = 1; - tmpl.array_size = 1; - tmpl.last_level = 0; - tmpl.nr_samples = 0; - tmpl.usage = PIPE_USAGE_DEFAULT; - tmpl.bind = PIPE_BIND_VERTEX_BUFFER; - tmpl.flags = 0; - This->dummy_vbo = pScreen->resource_create(pScreen, &tmpl); - - if (!This->dummy_vbo) - return D3DERR_OUTOFVIDEOMEMORY; - - u_box_1d(0, 16, &box); - data = This->context.pipe->transfer_map(This->context.pipe, This->dummy_vbo, 0, - PIPE_TRANSFER_WRITE | - PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE, - &box, &transfer); - assert(data); - assert(transfer); - memset(data, 0, 16); - This->context.pipe->transfer_unmap(This->context.pipe, transfer); - } - - This->cursor.software = FALSE; - This->cursor.hotspot.x = -1; - This->cursor.hotspot.y = -1; - This->cursor.w = This->cursor.h = 0; - This->cursor.visible = FALSE; - if (ID3DPresent_GetCursorPos(This->swapchains[0]->present, &This->cursor.pos) != S_OK) { - This->cursor.pos.x = 0; - This->cursor.pos.y = 0; - } - - { - struct pipe_resource tmpl; - memset(&tmpl, 0, sizeof(tmpl)); - tmpl.target = PIPE_TEXTURE_2D; - tmpl.format = PIPE_FORMAT_R8G8B8A8_UNORM; - tmpl.width0 = 64; - tmpl.height0 = 64; - tmpl.depth0 = 1; - tmpl.array_size = 1; - tmpl.last_level = 0; - tmpl.nr_samples = 0; - tmpl.usage = PIPE_USAGE_DEFAULT; - tmpl.bind = PIPE_BIND_CURSOR | PIPE_BIND_SAMPLER_VIEW; - tmpl.flags = 0; - - This->cursor.image = pScreen->resource_create(pScreen, &tmpl); - if (!This->cursor.image) - return D3DERR_OUTOFVIDEOMEMORY; - - /* For uploading 32x32 (argb) cursor */ - This->cursor.hw_upload_temp = MALLOC(32 * 4 * 32); - if (!This->cursor.hw_upload_temp) - return D3DERR_OUTOFVIDEOMEMORY; - } - - /* Create constant buffers. */ - { - unsigned max_const_vs, max_const_ps; - - /* vs 3.0: >= 256 float constants, but for cards with exactly 256 slots, - * we have to take in some more slots for int and bool*/ - max_const_vs = _min(pScreen->get_shader_param(pScreen, PIPE_SHADER_VERTEX, - PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE) / - sizeof(float[4]), - NINE_MAX_CONST_ALL); - /* ps 3.0: 224 float constants. All cards supported support at least - * 256 constants for ps */ - max_const_ps = NINE_MAX_CONST_F_PS3 + (NINE_MAX_CONST_I + NINE_MAX_CONST_B / 4); - - This->max_vs_const_f = max_const_vs - - (NINE_MAX_CONST_I + NINE_MAX_CONST_B / 4); - This->max_ps_const_f = max_const_ps - - (NINE_MAX_CONST_I + NINE_MAX_CONST_B / 4); - - This->vs_const_size = max_const_vs * sizeof(float[4]); - This->ps_const_size = max_const_ps * sizeof(float[4]); - /* Include space for I,B constants for user constbuf. */ - if (This->may_swvp) { - This->state.vs_const_f = CALLOC(NINE_MAX_CONST_F_SWVP * sizeof(float[4]),1); - This->context.vs_const_f_swvp = CALLOC(NINE_MAX_CONST_F_SWVP * sizeof(float[4]),1); - if (!This->context.vs_const_f_swvp) - return E_OUTOFMEMORY; - This->state.vs_lconstf_temp = CALLOC(NINE_MAX_CONST_F_SWVP * sizeof(float[4]),1); - This->context.vs_lconstf_temp = CALLOC(NINE_MAX_CONST_F_SWVP * sizeof(float[4]),1); - This->state.vs_const_i = CALLOC(NINE_MAX_CONST_I_SWVP * sizeof(int[4]), 1); - This->context.vs_const_i = CALLOC(NINE_MAX_CONST_I_SWVP * sizeof(int[4]), 1); - This->state.vs_const_b = CALLOC(NINE_MAX_CONST_B_SWVP * sizeof(BOOL), 1); - This->context.vs_const_b = CALLOC(NINE_MAX_CONST_B_SWVP * sizeof(BOOL), 1); - } else { - This->state.vs_const_f = CALLOC(NINE_MAX_CONST_F * sizeof(float[4]), 1); - This->context.vs_const_f_swvp = NULL; - This->state.vs_lconstf_temp = CALLOC(This->vs_const_size,1); - This->context.vs_lconstf_temp = CALLOC(This->vs_const_size,1); - This->state.vs_const_i = CALLOC(NINE_MAX_CONST_I * sizeof(int[4]), 1); - This->context.vs_const_i = CALLOC(NINE_MAX_CONST_I * sizeof(int[4]), 1); - This->state.vs_const_b = CALLOC(NINE_MAX_CONST_B * sizeof(BOOL), 1); - This->context.vs_const_b = CALLOC(NINE_MAX_CONST_B * sizeof(BOOL), 1); - } - This->context.vs_const_f = CALLOC(This->vs_const_size, 1); - This->state.ps_const_f = CALLOC(This->ps_const_size, 1); - This->context.ps_const_f = CALLOC(This->ps_const_size, 1); - This->context.ps_lconstf_temp = CALLOC(This->ps_const_size,1); - if (!This->state.vs_const_f || !This->context.vs_const_f || - !This->state.ps_const_f || !This->context.ps_const_f || - !This->state.vs_lconstf_temp || !This->context.vs_lconstf_temp || - !This->context.ps_lconstf_temp || - !This->state.vs_const_i || !This->context.vs_const_i || - !This->state.vs_const_b || !This->context.vs_const_b) - return E_OUTOFMEMORY; - - if (strstr(pScreen->get_name(pScreen), "AMD") || - strstr(pScreen->get_name(pScreen), "ATI")) { - This->driver_bugs.buggy_barycentrics = TRUE; - } - } - - /* allocate dummy texture/sampler for when there are missing ones bound */ - { - struct pipe_resource tmplt; - struct pipe_sampler_view templ; - struct pipe_sampler_state samp; - memset(&tmplt, 0, sizeof(tmplt)); - memset(&samp, 0, sizeof(samp)); - - tmplt.target = PIPE_TEXTURE_2D; - tmplt.width0 = 1; - tmplt.height0 = 1; - tmplt.depth0 = 1; - tmplt.last_level = 0; - tmplt.array_size = 1; - tmplt.usage = PIPE_USAGE_DEFAULT; - tmplt.flags = 0; - tmplt.format = PIPE_FORMAT_B8G8R8A8_UNORM; - tmplt.bind = PIPE_BIND_SAMPLER_VIEW; - tmplt.nr_samples = 0; - - This->dummy_texture = This->screen->resource_create(This->screen, &tmplt); - if (!This->dummy_texture) - return D3DERR_DRIVERINTERNALERROR; - - templ.format = PIPE_FORMAT_B8G8R8A8_UNORM; - templ.u.tex.first_layer = 0; - templ.u.tex.last_layer = 0; - templ.u.tex.first_level = 0; - templ.u.tex.last_level = 0; - templ.swizzle_r = PIPE_SWIZZLE_0; - templ.swizzle_g = PIPE_SWIZZLE_0; - templ.swizzle_b = PIPE_SWIZZLE_0; - templ.swizzle_a = PIPE_SWIZZLE_1; - templ.target = This->dummy_texture->target; - - This->dummy_sampler_view = This->context.pipe->create_sampler_view(This->context.pipe, This->dummy_texture, &templ); - if (!This->dummy_sampler_view) - return D3DERR_DRIVERINTERNALERROR; - - samp.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; - samp.max_lod = 15.0f; - samp.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; - samp.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; - samp.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; - samp.min_img_filter = PIPE_TEX_FILTER_NEAREST; - samp.mag_img_filter = PIPE_TEX_FILTER_NEAREST; - samp.compare_mode = PIPE_TEX_COMPARE_NONE; - samp.compare_func = PIPE_FUNC_LEQUAL; - samp.normalized_coords = 1; - samp.seamless_cube_map = 0; - This->dummy_sampler_state = samp; - } - - /* Allocate upload helper for drivers that suck (from st pov ;). */ - - This->driver_caps.user_vbufs = GET_PCAP(USER_VERTEX_BUFFERS) && !This->csmt_active; - This->driver_caps.user_sw_vbufs = This->screen_sw->get_param(This->screen_sw, PIPE_CAP_USER_VERTEX_BUFFERS); - This->vertex_uploader = This->csmt_active ? This->pipe_secondary->stream_uploader : This->context.pipe->stream_uploader; - This->driver_caps.window_space_position_support = GET_PCAP(TGSI_VS_WINDOW_SPACE_POSITION); - This->driver_caps.vs_integer = pScreen->get_shader_param(pScreen, PIPE_SHADER_VERTEX, PIPE_SHADER_CAP_INTEGERS); - This->driver_caps.ps_integer = pScreen->get_shader_param(pScreen, PIPE_SHADER_FRAGMENT, PIPE_SHADER_CAP_INTEGERS); - This->driver_caps.offset_units_unscaled = GET_PCAP(POLYGON_OFFSET_UNITS_UNSCALED); - - This->context.inline_constants = pCTX->shader_inline_constants; - /* Code would be needed when integers are not available to correctly - * handle the conversion of integer constants */ - This->context.inline_constants &= This->driver_caps.vs_integer && This->driver_caps.ps_integer; - - nine_ff_init(This); /* initialize fixed function code */ - - NineDevice9_SetDefaultState(This, FALSE); - - { - struct pipe_poly_stipple stipple; - memset(&stipple, ~0, sizeof(stipple)); - This->context.pipe->set_polygon_stipple(This->context.pipe, &stipple); - } - - This->update = &This->state; - - nine_state_init_sw(This); - - ID3DPresentGroup_Release(This->present); - nine_csmt_process(This); - - return D3D_OK; -} -#undef GET_PCAP - -void -NineDevice9_dtor( struct NineDevice9 *This ) -{ - unsigned i; - - DBG("This=%p\n", This); - - /* Flush all pending commands to get refcount right, - * and properly release bound objects. It is ok to still - * execute commands while we are in device dtor, because - * we haven't released anything yet. Note that no pending - * command can increase the device refcount. */ - if (This->csmt_active && This->csmt_ctx) { - nine_csmt_process(This); - nine_csmt_destroy(This, This->csmt_ctx); - This->csmt_active = FALSE; - This->csmt_ctx = NULL; - } - - nine_ff_fini(This); - nine_state_destroy_sw(This); - nine_device_state_clear(This); - nine_context_clear(This); - - nine_bind(&This->record, NULL); - - pipe_sampler_view_reference(&This->dummy_sampler_view, NULL); - pipe_resource_reference(&This->dummy_texture, NULL); - pipe_resource_reference(&This->dummy_vbo, NULL); - FREE(This->state.vs_const_f); - FREE(This->context.vs_const_f); - FREE(This->state.ps_const_f); - FREE(This->context.ps_const_f); - FREE(This->state.vs_lconstf_temp); - FREE(This->context.vs_lconstf_temp); - FREE(This->context.ps_lconstf_temp); - FREE(This->state.vs_const_i); - FREE(This->context.vs_const_i); - FREE(This->state.vs_const_b); - FREE(This->context.vs_const_b); - FREE(This->context.vs_const_f_swvp); - - pipe_resource_reference(&This->cursor.image, NULL); - FREE(This->cursor.hw_upload_temp); - - if (This->swapchains) { - for (i = 0; i < This->nswapchains; ++i) - if (This->swapchains[i]) - NineUnknown_Unbind(NineUnknown(This->swapchains[i])); - FREE(This->swapchains); - } - - if (This->buffer_upload) - nine_upload_destroy(This->buffer_upload); - - /* Destroy cso first */ - if (This->context.cso) { cso_destroy_context(This->context.cso); } - if (This->cso_sw) { cso_destroy_context(This->cso_sw); } - if (This->context.pipe && This->context.pipe->destroy) { This->context.pipe->destroy(This->context.pipe); } - if (This->pipe_secondary && This->pipe_secondary->destroy) { This->pipe_secondary->destroy(This->pipe_secondary); } - if (This->pipe_sw && This->pipe_sw->destroy) { This->pipe_sw->destroy(This->pipe_sw); } - - if (This->present) { ID3DPresentGroup_Release(This->present); } - if (This->d3d9) { IDirect3D9_Release(This->d3d9); } - - NineUnknown_dtor(&This->base); - glsl_type_singleton_decref(); -} - -struct pipe_screen * -NineDevice9_GetScreen( struct NineDevice9 *This ) -{ - return This->screen; -} - -struct pipe_context * -NineDevice9_GetPipe( struct NineDevice9 *This ) -{ - return nine_context_get_pipe(This); -} - -const D3DCAPS9 * -NineDevice9_GetCaps( struct NineDevice9 *This ) -{ - return &This->caps; -} - -static inline void -NineDevice9_PauseRecording( struct NineDevice9 *This ) -{ - if (This->record) { - This->update = &This->state; - This->is_recording = FALSE; - } -} - -static inline void -NineDevice9_ResumeRecording( struct NineDevice9 *This ) -{ - if (This->record) { - This->update = &This->record->state; - This->is_recording = TRUE; - } -} - -HRESULT NINE_WINAPI -NineDevice9_TestCooperativeLevel( struct NineDevice9 *This ) -{ - if (NineSwapChain9_GetOccluded(This->swapchains[0])) { - This->device_needs_reset = TRUE; - return D3DERR_DEVICELOST; - } else if (NineSwapChain9_ResolutionMismatch(This->swapchains[0])) { - This->device_needs_reset = TRUE; - return D3DERR_DEVICENOTRESET; - } else if (This->device_needs_reset) { - return D3DERR_DEVICENOTRESET; - } - - return D3D_OK; -} - -UINT NINE_WINAPI -NineDevice9_GetAvailableTextureMem( struct NineDevice9 *This ) -{ - return This->available_texture_mem; -} - -HRESULT NINE_WINAPI -NineDevice9_EvictManagedResources( struct NineDevice9 *This ) -{ - struct NineBaseTexture9 *tex; - struct NineBuffer9 *buf; - - DBG("This=%p\n", This); - LIST_FOR_EACH_ENTRY(tex, &This->managed_textures, list2) { - NineBaseTexture9_UnLoad(tex); - } - /* Vertex/index buffers don't take a lot of space and aren't accounted - * for d3d memory usage. Instead of actually freeing from memory, - * just mark the buffer dirty to trigger a re-upload later. We - * could just ignore, but some bad behaving apps could rely on it (if - * they write outside the locked regions typically). */ - LIST_FOR_EACH_ENTRY(buf, &This->managed_buffers, managed.list2) { - NineBuffer9_SetDirty(buf); - } - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_GetDirect3D( struct NineDevice9 *This, - IDirect3D9 **ppD3D9 ) -{ - user_assert(ppD3D9 != NULL, E_POINTER); - IDirect3D9_AddRef(This->d3d9); - *ppD3D9 = This->d3d9; - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_GetDeviceCaps( struct NineDevice9 *This, - D3DCAPS9 *pCaps ) -{ - user_assert(pCaps != NULL, D3DERR_INVALIDCALL); - *pCaps = This->caps; - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_GetDisplayMode( struct NineDevice9 *This, - UINT iSwapChain, - D3DDISPLAYMODE *pMode ) -{ - DBG("This=%p iSwapChain=%u pMode=%p\n", This, iSwapChain, pMode); - - user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL); - - return NineSwapChain9_GetDisplayMode(This->swapchains[iSwapChain], pMode); -} - -HRESULT NINE_WINAPI -NineDevice9_GetCreationParameters( struct NineDevice9 *This, - D3DDEVICE_CREATION_PARAMETERS *pParameters ) -{ - user_assert(pParameters != NULL, D3DERR_INVALIDCALL); - *pParameters = This->params; - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_SetCursorProperties( struct NineDevice9 *This, - UINT XHotSpot, - UINT YHotSpot, - IDirect3DSurface9 *pCursorBitmap ) -{ - struct NineSurface9 *surf = NineSurface9(pCursorBitmap); - struct pipe_context *pipe = NineDevice9_GetPipe(This); - struct pipe_box box; - struct pipe_transfer *transfer; - BOOL hw_cursor; - void *ptr; - - DBG_FLAG(DBG_SWAPCHAIN, "This=%p XHotSpot=%u YHotSpot=%u " - "pCursorBitmap=%p\n", This, XHotSpot, YHotSpot, pCursorBitmap); - - user_assert(pCursorBitmap, D3DERR_INVALIDCALL); - user_assert(surf->desc.Format == D3DFMT_A8R8G8B8, D3DERR_INVALIDCALL); - - if (This->swapchains[0]->params.Windowed) { - This->cursor.w = MIN2(surf->desc.Width, 32); - This->cursor.h = MIN2(surf->desc.Height, 32); - hw_cursor = 1; /* always use hw cursor for windowed mode */ - } else { - This->cursor.w = MIN2(surf->desc.Width, This->cursor.image->width0); - This->cursor.h = MIN2(surf->desc.Height, This->cursor.image->height0); - hw_cursor = This->cursor.w == 32 && This->cursor.h == 32; - } - - u_box_origin_2d(This->cursor.w, This->cursor.h, &box); - - ptr = pipe->transfer_map(pipe, This->cursor.image, 0, - PIPE_TRANSFER_WRITE | - PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE, - &box, &transfer); - if (!ptr) - ret_err("Failed to update cursor image.\n", D3DERR_DRIVERINTERNALERROR); - - This->cursor.hotspot.x = XHotSpot; - This->cursor.hotspot.y = YHotSpot; - - /* Copy cursor image to internal storage. */ - { - D3DLOCKED_RECT lock; - HRESULT hr; - const struct util_format_description *sfmt = - util_format_description(surf->base.info.format); - assert(sfmt); - - hr = NineSurface9_LockRect(surf, &lock, NULL, D3DLOCK_READONLY); - if (FAILED(hr)) - ret_err("Failed to map cursor source image.\n", - D3DERR_DRIVERINTERNALERROR); - - sfmt->unpack_rgba_8unorm(ptr, transfer->stride, - lock.pBits, lock.Pitch, - This->cursor.w, This->cursor.h); - - if (hw_cursor) { - void *data = lock.pBits; - /* SetCursor assumes 32x32 argb with pitch 128 */ - if (lock.Pitch != 128) { - sfmt->unpack_rgba_8unorm(This->cursor.hw_upload_temp, 128, - lock.pBits, lock.Pitch, - 32, 32); - data = This->cursor.hw_upload_temp; - } - hw_cursor = ID3DPresent_SetCursor(This->swapchains[0]->present, - data, - &This->cursor.hotspot, - This->cursor.visible) == D3D_OK; - } - - NineSurface9_UnlockRect(surf); - } - pipe->transfer_unmap(pipe, transfer); - - /* hide cursor if we emulate it */ - if (!hw_cursor) - ID3DPresent_SetCursor(This->swapchains[0]->present, NULL, NULL, FALSE); - This->cursor.software = !hw_cursor; - - return D3D_OK; -} - -void NINE_WINAPI -NineDevice9_SetCursorPosition( struct NineDevice9 *This, - int X, - int Y, - DWORD Flags ) -{ - struct NineSwapChain9 *swap = This->swapchains[0]; - - DBG("This=%p X=%d Y=%d Flags=%d\n", This, X, Y, Flags); - - /* present >= v1.4 handles this itself */ - if (This->minor_version_num < 4) { - if (This->cursor.pos.x == X && This->cursor.pos.y == Y) - return; - } - - This->cursor.pos.x = X; - This->cursor.pos.y = Y; - - if (!This->cursor.software) - This->cursor.software = ID3DPresent_SetCursorPos(swap->present, &This->cursor.pos) != D3D_OK; -} - -BOOL NINE_WINAPI -NineDevice9_ShowCursor( struct NineDevice9 *This, - BOOL bShow ) -{ - BOOL old = This->cursor.visible; - - DBG("This=%p bShow=%d\n", This, (int) bShow); - - /* No-op until a cursor is set in d3d */ - if (This->cursor.hotspot.x == -1) - return old; - - This->cursor.visible = bShow; - /* Note: Don't optimize by avoiding the call if This->cursor.visible - * hasn't changed. One has to keep in mind the app may do SetCursor - * calls outside d3d, thus such an optimization affects behaviour. */ - if (!This->cursor.software) - This->cursor.software = ID3DPresent_SetCursor(This->swapchains[0]->present, NULL, NULL, bShow) != D3D_OK; - - return old; -} - -HRESULT NINE_WINAPI -NineDevice9_CreateAdditionalSwapChain( struct NineDevice9 *This, - D3DPRESENT_PARAMETERS *pPresentationParameters, - IDirect3DSwapChain9 **pSwapChain ) -{ - struct NineSwapChain9 *swapchain, *tmplt = This->swapchains[0]; - ID3DPresent *present; - HRESULT hr; - - DBG("This=%p pPresentationParameters=%p pSwapChain=%p\n", - This, pPresentationParameters, pSwapChain); - - user_assert(pPresentationParameters, D3DERR_INVALIDCALL); - user_assert(tmplt->params.Windowed && pPresentationParameters->Windowed, D3DERR_INVALIDCALL); - - /* TODO: this deserves more tests */ - if (!pPresentationParameters->hDeviceWindow) - pPresentationParameters->hDeviceWindow = This->params.hFocusWindow; - - hr = ID3DPresentGroup_CreateAdditionalPresent(This->present, pPresentationParameters, &present); - - if (FAILED(hr)) - return hr; - - hr = NineSwapChain9_new(This, FALSE, present, pPresentationParameters, - tmplt->actx, - tmplt->params.hDeviceWindow, - &swapchain); - if (FAILED(hr)) - return hr; - - *pSwapChain = (IDirect3DSwapChain9 *)swapchain; - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_GetSwapChain( struct NineDevice9 *This, - UINT iSwapChain, - IDirect3DSwapChain9 **pSwapChain ) -{ - user_assert(pSwapChain != NULL, D3DERR_INVALIDCALL); - - *pSwapChain = NULL; - user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL); - - NineUnknown_AddRef(NineUnknown(This->swapchains[iSwapChain])); - *pSwapChain = (IDirect3DSwapChain9 *)This->swapchains[iSwapChain]; - - return D3D_OK; -} - -UINT NINE_WINAPI -NineDevice9_GetNumberOfSwapChains( struct NineDevice9 *This ) -{ - return This->nswapchains; -} - -HRESULT NINE_WINAPI -NineDevice9_Reset( struct NineDevice9 *This, - D3DPRESENT_PARAMETERS *pPresentationParameters ) -{ - HRESULT hr = D3D_OK; - unsigned i; - - DBG("This=%p pPresentationParameters=%p\n", This, pPresentationParameters); - - if (NineSwapChain9_GetOccluded(This->swapchains[0])) { - This->device_needs_reset = TRUE; - return D3DERR_DEVICELOST; - } - - for (i = 0; i < This->nswapchains; ++i) { - D3DPRESENT_PARAMETERS *params = &pPresentationParameters[i]; - hr = NineSwapChain9_Resize(This->swapchains[i], params, NULL); - if (hr != D3D_OK) - break; - } - - nine_csmt_process(This); - nine_device_state_clear(This); - nine_context_clear(This); - - NineDevice9_SetDefaultState(This, TRUE); - NineDevice9_SetRenderTarget( - This, 0, (IDirect3DSurface9 *)This->swapchains[0]->buffers[0]); - /* XXX: better use GetBackBuffer here ? */ - - This->device_needs_reset = (hr != D3D_OK); - return hr; -} - -HRESULT NINE_WINAPI -NineDevice9_Present( struct NineDevice9 *This, - const RECT *pSourceRect, - const RECT *pDestRect, - HWND hDestWindowOverride, - const RGNDATA *pDirtyRegion ) -{ - unsigned i; - HRESULT hr; - - DBG("This=%p pSourceRect=%p pDestRect=%p hDestWindowOverride=%p pDirtyRegion=%p\n", - This, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion); - - /* XXX is this right? */ - for (i = 0; i < This->nswapchains; ++i) { - hr = NineSwapChain9_Present(This->swapchains[i], pSourceRect, pDestRect, - hDestWindowOverride, pDirtyRegion, 0); - if (FAILED(hr)) { return hr; } - } - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_GetBackBuffer( struct NineDevice9 *This, - UINT iSwapChain, - UINT iBackBuffer, - D3DBACKBUFFER_TYPE Type, - IDirect3DSurface9 **ppBackBuffer ) -{ - user_assert(ppBackBuffer != NULL, D3DERR_INVALIDCALL); - /* return NULL on error */ - *ppBackBuffer = NULL; - user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL); - - return NineSwapChain9_GetBackBuffer(This->swapchains[iSwapChain], - iBackBuffer, Type, ppBackBuffer); -} - -HRESULT NINE_WINAPI -NineDevice9_GetRasterStatus( struct NineDevice9 *This, - UINT iSwapChain, - D3DRASTER_STATUS *pRasterStatus ) -{ - user_assert(pRasterStatus != NULL, D3DERR_INVALIDCALL); - user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL); - - return NineSwapChain9_GetRasterStatus(This->swapchains[iSwapChain], - pRasterStatus); -} - -HRESULT NINE_WINAPI -NineDevice9_SetDialogBoxMode( struct NineDevice9 *This, - BOOL bEnableDialogs ) -{ - STUB(D3DERR_INVALIDCALL); -} - -void NINE_WINAPI -NineDevice9_SetGammaRamp( struct NineDevice9 *This, - UINT iSwapChain, - DWORD Flags, - const D3DGAMMARAMP *pRamp ) -{ - DBG("This=%p iSwapChain=%u Flags=%x pRamp=%p\n", This, - iSwapChain, Flags, pRamp); - - user_warn(iSwapChain >= This->nswapchains); - user_warn(!pRamp); - - if (pRamp && (iSwapChain < This->nswapchains)) { - struct NineSwapChain9 *swap = This->swapchains[iSwapChain]; - swap->gamma = *pRamp; - ID3DPresent_SetGammaRamp(swap->present, pRamp, swap->params.hDeviceWindow); - } -} - -void NINE_WINAPI -NineDevice9_GetGammaRamp( struct NineDevice9 *This, - UINT iSwapChain, - D3DGAMMARAMP *pRamp ) -{ - DBG("This=%p iSwapChain=%u pRamp=%p\n", This, iSwapChain, pRamp); - - user_warn(iSwapChain >= This->nswapchains); - user_warn(!pRamp); - - if (pRamp && (iSwapChain < This->nswapchains)) - *pRamp = This->swapchains[iSwapChain]->gamma; -} - -HRESULT NINE_WINAPI -NineDevice9_CreateTexture( struct NineDevice9 *This, - UINT Width, - UINT Height, - UINT Levels, - DWORD Usage, - D3DFORMAT Format, - D3DPOOL Pool, - IDirect3DTexture9 **ppTexture, - HANDLE *pSharedHandle ) -{ - struct NineTexture9 *tex; - HRESULT hr; - - DBG("This=%p Width=%u Height=%u Levels=%u Usage=%s Format=%s Pool=%s " - "ppOut=%p pSharedHandle=%p\n", This, Width, Height, Levels, - nine_D3DUSAGE_to_str(Usage), d3dformat_to_string(Format), - nine_D3DPOOL_to_str(Pool), ppTexture, pSharedHandle); - - Usage &= D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_DMAP | - D3DUSAGE_DYNAMIC | D3DUSAGE_NONSECURE | D3DUSAGE_RENDERTARGET | - D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_TEXTAPI; - - *ppTexture = NULL; - - hr = NineTexture9_new(This, Width, Height, Levels, Usage, Format, Pool, - &tex, pSharedHandle); - if (SUCCEEDED(hr)) - *ppTexture = (IDirect3DTexture9 *)tex; - - return hr; -} - -HRESULT NINE_WINAPI -NineDevice9_CreateVolumeTexture( struct NineDevice9 *This, - UINT Width, - UINT Height, - UINT Depth, - UINT Levels, - DWORD Usage, - D3DFORMAT Format, - D3DPOOL Pool, - IDirect3DVolumeTexture9 **ppVolumeTexture, - HANDLE *pSharedHandle ) -{ - struct NineVolumeTexture9 *tex; - HRESULT hr; - - DBG("This=%p Width=%u Height=%u Depth=%u Levels=%u Usage=%s Format=%s Pool=%s " - "ppOut=%p pSharedHandle=%p\n", This, Width, Height, Depth, Levels, - nine_D3DUSAGE_to_str(Usage), d3dformat_to_string(Format), - nine_D3DPOOL_to_str(Pool), ppVolumeTexture, pSharedHandle); - - Usage &= D3DUSAGE_DYNAMIC | D3DUSAGE_NONSECURE | - D3DUSAGE_SOFTWAREPROCESSING; - - *ppVolumeTexture = NULL; - - hr = NineVolumeTexture9_new(This, Width, Height, Depth, Levels, - Usage, Format, Pool, &tex, pSharedHandle); - if (SUCCEEDED(hr)) - *ppVolumeTexture = (IDirect3DVolumeTexture9 *)tex; - - return hr; -} - -HRESULT NINE_WINAPI -NineDevice9_CreateCubeTexture( struct NineDevice9 *This, - UINT EdgeLength, - UINT Levels, - DWORD Usage, - D3DFORMAT Format, - D3DPOOL Pool, - IDirect3DCubeTexture9 **ppCubeTexture, - HANDLE *pSharedHandle ) -{ - struct NineCubeTexture9 *tex; - HRESULT hr; - - DBG("This=%p EdgeLength=%u Levels=%u Usage=%s Format=%s Pool=%s ppOut=%p " - "pSharedHandle=%p\n", This, EdgeLength, Levels, - nine_D3DUSAGE_to_str(Usage), d3dformat_to_string(Format), - nine_D3DPOOL_to_str(Pool), ppCubeTexture, pSharedHandle); - - Usage &= D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_DYNAMIC | - D3DUSAGE_NONSECURE | D3DUSAGE_RENDERTARGET | - D3DUSAGE_SOFTWAREPROCESSING; - - *ppCubeTexture = NULL; - - hr = NineCubeTexture9_new(This, EdgeLength, Levels, Usage, Format, Pool, - &tex, pSharedHandle); - if (SUCCEEDED(hr)) - *ppCubeTexture = (IDirect3DCubeTexture9 *)tex; - - return hr; -} - -HRESULT NINE_WINAPI -NineDevice9_CreateVertexBuffer( struct NineDevice9 *This, - UINT Length, - DWORD Usage, - DWORD FVF, - D3DPOOL Pool, - IDirect3DVertexBuffer9 **ppVertexBuffer, - HANDLE *pSharedHandle ) -{ - struct NineVertexBuffer9 *buf; - HRESULT hr; - D3DVERTEXBUFFER_DESC desc; - - DBG("This=%p Length=%u Usage=%x FVF=%x Pool=%u ppOut=%p pSharedHandle=%p\n", - This, Length, Usage, FVF, Pool, ppVertexBuffer, pSharedHandle); - - user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_NOTAVAILABLE); - - desc.Format = D3DFMT_VERTEXDATA; - desc.Type = D3DRTYPE_VERTEXBUFFER; - desc.Usage = Usage & - (D3DUSAGE_DONOTCLIP | D3DUSAGE_DYNAMIC | D3DUSAGE_NONSECURE | - D3DUSAGE_NPATCHES | D3DUSAGE_POINTS | D3DUSAGE_RTPATCHES | - D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_TEXTAPI | - D3DUSAGE_WRITEONLY); - desc.Pool = Pool; - desc.Size = Length; - desc.FVF = FVF; - - user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); - user_assert(desc.Usage == Usage, D3DERR_INVALIDCALL); - - hr = NineVertexBuffer9_new(This, &desc, &buf); - if (SUCCEEDED(hr)) - *ppVertexBuffer = (IDirect3DVertexBuffer9 *)buf; - return hr; -} - -HRESULT NINE_WINAPI -NineDevice9_CreateIndexBuffer( struct NineDevice9 *This, - UINT Length, - DWORD Usage, - D3DFORMAT Format, - D3DPOOL Pool, - IDirect3DIndexBuffer9 **ppIndexBuffer, - HANDLE *pSharedHandle ) -{ - struct NineIndexBuffer9 *buf; - HRESULT hr; - D3DINDEXBUFFER_DESC desc; - - DBG("This=%p Length=%u Usage=%x Format=%s Pool=%u ppOut=%p " - "pSharedHandle=%p\n", This, Length, Usage, - d3dformat_to_string(Format), Pool, ppIndexBuffer, pSharedHandle); - - user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_NOTAVAILABLE); - - desc.Format = Format; - desc.Type = D3DRTYPE_INDEXBUFFER; - desc.Usage = Usage & - (D3DUSAGE_DONOTCLIP | D3DUSAGE_DYNAMIC | D3DUSAGE_NONSECURE | - D3DUSAGE_NPATCHES | D3DUSAGE_POINTS | D3DUSAGE_RTPATCHES | - D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_WRITEONLY); - desc.Pool = Pool; - desc.Size = Length; - - user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); - user_assert(desc.Usage == Usage, D3DERR_INVALIDCALL); - - hr = NineIndexBuffer9_new(This, &desc, &buf); - if (SUCCEEDED(hr)) - *ppIndexBuffer = (IDirect3DIndexBuffer9 *)buf; - return hr; -} - -static HRESULT -create_zs_or_rt_surface(struct NineDevice9 *This, - unsigned type, /* 0 = RT, 1 = ZS, 2 = plain */ - D3DPOOL Pool, - UINT Width, UINT Height, - D3DFORMAT Format, - D3DMULTISAMPLE_TYPE MultiSample, - DWORD MultisampleQuality, - BOOL Discard_or_Lockable, - IDirect3DSurface9 **ppSurface, - HANDLE *pSharedHandle) -{ - struct NineSurface9 *surface; - HRESULT hr; - D3DSURFACE_DESC desc; - - DBG("This=%p type=%u Pool=%s Width=%u Height=%u Format=%s MS=%u Quality=%u " - "Discard_or_Lockable=%i ppSurface=%p pSharedHandle=%p\n", - This, type, nine_D3DPOOL_to_str(Pool), Width, Height, - d3dformat_to_string(Format), MultiSample, MultisampleQuality, - Discard_or_Lockable, ppSurface, pSharedHandle); - - if (pSharedHandle) - DBG("FIXME Used shared handle! This option isn't probably handled correctly!\n"); - - user_assert(Width && Height, D3DERR_INVALIDCALL); - user_assert(Pool != D3DPOOL_MANAGED, D3DERR_INVALIDCALL); - - desc.Format = Format; - desc.Type = D3DRTYPE_SURFACE; - desc.Usage = 0; - desc.Pool = Pool; - desc.MultiSampleType = MultiSample; - desc.MultiSampleQuality = MultisampleQuality; - desc.Width = Width; - desc.Height = Height; - switch (type) { - case 0: desc.Usage = D3DUSAGE_RENDERTARGET; break; - case 1: desc.Usage = D3DUSAGE_DEPTHSTENCIL; break; - default: assert(type == 2); break; - } - - hr = NineSurface9_new(This, NULL, NULL, NULL, 0, 0, 0, &desc, &surface); - if (SUCCEEDED(hr)) { - *ppSurface = (IDirect3DSurface9 *)surface; - - if (surface->base.resource && Discard_or_Lockable && (type != 1)) - surface->base.resource->flags |= NINE_RESOURCE_FLAG_LOCKABLE; - } - - return hr; -} - -HRESULT NINE_WINAPI -NineDevice9_CreateRenderTarget( struct NineDevice9 *This, - UINT Width, - UINT Height, - D3DFORMAT Format, - D3DMULTISAMPLE_TYPE MultiSample, - DWORD MultisampleQuality, - BOOL Lockable, - IDirect3DSurface9 **ppSurface, - HANDLE *pSharedHandle ) -{ - *ppSurface = NULL; - return create_zs_or_rt_surface(This, 0, D3DPOOL_DEFAULT, - Width, Height, Format, - MultiSample, MultisampleQuality, - Lockable, ppSurface, pSharedHandle); -} - -HRESULT NINE_WINAPI -NineDevice9_CreateDepthStencilSurface( struct NineDevice9 *This, - UINT Width, - UINT Height, - D3DFORMAT Format, - D3DMULTISAMPLE_TYPE MultiSample, - DWORD MultisampleQuality, - BOOL Discard, - IDirect3DSurface9 **ppSurface, - HANDLE *pSharedHandle ) -{ - *ppSurface = NULL; - if (!depth_stencil_format(Format)) - return D3DERR_NOTAVAILABLE; - return create_zs_or_rt_surface(This, 1, D3DPOOL_DEFAULT, - Width, Height, Format, - MultiSample, MultisampleQuality, - Discard, ppSurface, pSharedHandle); -} - -HRESULT NINE_WINAPI -NineDevice9_UpdateSurface( struct NineDevice9 *This, - IDirect3DSurface9 *pSourceSurface, - const RECT *pSourceRect, - IDirect3DSurface9 *pDestinationSurface, - const POINT *pDestPoint ) -{ - struct NineSurface9 *dst = NineSurface9(pDestinationSurface); - struct NineSurface9 *src = NineSurface9(pSourceSurface); - int copy_width, copy_height; - RECT destRect; - - DBG("This=%p pSourceSurface=%p pDestinationSurface=%p " - "pSourceRect=%p pDestPoint=%p\n", This, - pSourceSurface, pDestinationSurface, pSourceRect, pDestPoint); - if (pSourceRect) - DBG("pSourceRect = (%u,%u)-(%u,%u)\n", - pSourceRect->left, pSourceRect->top, - pSourceRect->right, pSourceRect->bottom); - if (pDestPoint) - DBG("pDestPoint = (%u,%u)\n", pDestPoint->x, pDestPoint->y); - - user_assert(dst && src, D3DERR_INVALIDCALL); - - user_assert(dst->base.pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); - user_assert(src->base.pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL); - - user_assert(dst->desc.MultiSampleType == D3DMULTISAMPLE_NONE, D3DERR_INVALIDCALL); - user_assert(src->desc.MultiSampleType == D3DMULTISAMPLE_NONE, D3DERR_INVALIDCALL); - - user_assert(!src->lock_count, D3DERR_INVALIDCALL); - user_assert(!dst->lock_count, D3DERR_INVALIDCALL); - - user_assert(dst->desc.Format == src->desc.Format, D3DERR_INVALIDCALL); - user_assert(!depth_stencil_format(dst->desc.Format), D3DERR_INVALIDCALL); - - if (pSourceRect) { - copy_width = pSourceRect->right - pSourceRect->left; - copy_height = pSourceRect->bottom - pSourceRect->top; - - user_assert(pSourceRect->left >= 0 && - copy_width > 0 && - pSourceRect->right <= src->desc.Width && - pSourceRect->top >= 0 && - copy_height > 0 && - pSourceRect->bottom <= src->desc.Height, - D3DERR_INVALIDCALL); - } else { - copy_width = src->desc.Width; - copy_height = src->desc.Height; - } - - destRect.right = copy_width; - destRect.bottom = copy_height; - - if (pDestPoint) { - user_assert(pDestPoint->x >= 0 && pDestPoint->y >= 0, - D3DERR_INVALIDCALL); - destRect.right += pDestPoint->x; - destRect.bottom += pDestPoint->y; - } - - user_assert(destRect.right <= dst->desc.Width && - destRect.bottom <= dst->desc.Height, - D3DERR_INVALIDCALL); - - if (compressed_format(dst->desc.Format)) { - const unsigned w = util_format_get_blockwidth(dst->base.info.format); - const unsigned h = util_format_get_blockheight(dst->base.info.format); - - if (pDestPoint) { - user_assert(!(pDestPoint->x % w) && !(pDestPoint->y % h), - D3DERR_INVALIDCALL); - } - - if (pSourceRect) { - user_assert(!(pSourceRect->left % w) && !(pSourceRect->top % h), - D3DERR_INVALIDCALL); - } - if (!(copy_width == src->desc.Width && - copy_width == dst->desc.Width && - copy_height == src->desc.Height && - copy_height == dst->desc.Height)) { - user_assert(!(copy_width % w) && !(copy_height % h), - D3DERR_INVALIDCALL); - } - } - - NineSurface9_CopyMemToDefault(dst, src, pDestPoint, pSourceRect); - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_UpdateTexture( struct NineDevice9 *This, - IDirect3DBaseTexture9 *pSourceTexture, - IDirect3DBaseTexture9 *pDestinationTexture ) -{ - struct NineBaseTexture9 *dstb = NineBaseTexture9(pDestinationTexture); - struct NineBaseTexture9 *srcb = NineBaseTexture9(pSourceTexture); - unsigned l, m; - unsigned last_src_level, last_dst_level; - RECT rect; - - DBG("This=%p pSourceTexture=%p pDestinationTexture=%p\n", This, - pSourceTexture, pDestinationTexture); - - user_assert(pSourceTexture && pDestinationTexture, D3DERR_INVALIDCALL); - user_assert(pSourceTexture != pDestinationTexture, D3DERR_INVALIDCALL); - - user_assert(dstb->base.pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); - user_assert(srcb->base.pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL); - user_assert(dstb->base.type == srcb->base.type, D3DERR_INVALIDCALL); - user_assert(!(srcb->base.usage & D3DUSAGE_AUTOGENMIPMAP) || - dstb->base.usage & D3DUSAGE_AUTOGENMIPMAP, D3DERR_INVALIDCALL); - - /* Spec: Failure if - * . Different formats - * . Fewer src levels than dst levels (if the opposite, only matching levels - * are supposed to be copied) - * . Levels do not match - * DDI: Actually the above should pass because of legacy applications - * Do what you want about these, but you shouldn't crash. - * However driver can expect that the top dimension is greater for src than dst. - * Wine tests: Every combination that passes the initial checks should pass. - * . Different formats => conversion driver and format dependent. - * . 1 level, but size not matching => copy is done (and even crash if src bigger - * than dst. For the case where dst bigger, wine doesn't test if a stretch is applied - * or if a subrect is copied). - * . 8x8 4 sublevels -> 7x7 2 sublevels => driver dependent, On NV seems to be 4x4 subrect - * copied to 7x7. - * - * From these, the proposal is: - * . Different formats -> use util_format_translate to translate if possible for surfaces. - * Accept ARGB/XRGB for Volumes. Do nothing for the other combinations - * . First level copied -> the first level such that src is smaller or equal to dst first level - * . number of levels copied -> as long as it fits and textures have levels - * That should satisfy the constraints (and instead of crashing for some cases we return D3D_OK) - */ - - last_src_level = (srcb->base.usage & D3DUSAGE_AUTOGENMIPMAP) ? 0 : srcb->base.info.last_level; - last_dst_level = (dstb->base.usage & D3DUSAGE_AUTOGENMIPMAP) ? 0 : dstb->base.info.last_level; - - for (m = 0; m <= last_src_level; ++m) { - unsigned w = u_minify(srcb->base.info.width0, m); - unsigned h = u_minify(srcb->base.info.height0, m); - unsigned d = u_minify(srcb->base.info.depth0, m); - - if (w <= dstb->base.info.width0 && - h <= dstb->base.info.height0 && - d <= dstb->base.info.depth0) - break; - } - user_assert(m <= last_src_level, D3D_OK); - - last_dst_level = MIN2(srcb->base.info.last_level - m, last_dst_level); - - if (dstb->base.type == D3DRTYPE_TEXTURE) { - struct NineTexture9 *dst = NineTexture9(dstb); - struct NineTexture9 *src = NineTexture9(srcb); - - if (src->dirty_rect.width == 0) - return D3D_OK; - - pipe_box_to_rect(&rect, &src->dirty_rect); - for (l = 0; l < m; ++l) - rect_minify_inclusive(&rect); - - for (l = 0; l <= last_dst_level; ++l, ++m) { - fit_rect_format_inclusive(dst->base.base.info.format, - &rect, - dst->surfaces[l]->desc.Width, - dst->surfaces[l]->desc.Height); - NineSurface9_CopyMemToDefault(dst->surfaces[l], - src->surfaces[m], - (POINT *)&rect, - &rect); - rect_minify_inclusive(&rect); - } - u_box_origin_2d(0, 0, &src->dirty_rect); - } else - if (dstb->base.type == D3DRTYPE_CUBETEXTURE) { - struct NineCubeTexture9 *dst = NineCubeTexture9(dstb); - struct NineCubeTexture9 *src = NineCubeTexture9(srcb); - unsigned z; - - /* GPUs usually have them stored as arrays of mip-mapped 2D textures. */ - for (z = 0; z < 6; ++z) { - if (src->dirty_rect[z].width == 0) - continue; - - pipe_box_to_rect(&rect, &src->dirty_rect[z]); - for (l = 0; l < m; ++l) - rect_minify_inclusive(&rect); - - for (l = 0; l <= last_dst_level; ++l, ++m) { - fit_rect_format_inclusive(dst->base.base.info.format, - &rect, - dst->surfaces[l * 6 + z]->desc.Width, - dst->surfaces[l * 6 + z]->desc.Height); - NineSurface9_CopyMemToDefault(dst->surfaces[l * 6 + z], - src->surfaces[m * 6 + z], - (POINT *)&rect, - &rect); - rect_minify_inclusive(&rect); - } - u_box_origin_2d(0, 0, &src->dirty_rect[z]); - m -= l; - } - } else - if (dstb->base.type == D3DRTYPE_VOLUMETEXTURE) { - struct NineVolumeTexture9 *dst = NineVolumeTexture9(dstb); - struct NineVolumeTexture9 *src = NineVolumeTexture9(srcb); - - if (src->dirty_box.width == 0) - return D3D_OK; - for (l = 0; l <= last_dst_level; ++l, ++m) - NineVolume9_CopyMemToDefault(dst->volumes[l], - src->volumes[m], 0, 0, 0, NULL); - u_box_3d(0, 0, 0, 0, 0, 0, &src->dirty_box); - } else{ - assert(!"invalid texture type"); - } - - if (dstb->base.usage & D3DUSAGE_AUTOGENMIPMAP) { - dstb->dirty_mip = TRUE; - NineBaseTexture9_GenerateMipSubLevels(dstb); - } - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_GetRenderTargetData( struct NineDevice9 *This, - IDirect3DSurface9 *pRenderTarget, - IDirect3DSurface9 *pDestSurface ) -{ - struct NineSurface9 *dst = NineSurface9(pDestSurface); - struct NineSurface9 *src = NineSurface9(pRenderTarget); - - DBG("This=%p pRenderTarget=%p pDestSurface=%p\n", - This, pRenderTarget, pDestSurface); - - user_assert(pRenderTarget && pDestSurface, D3DERR_INVALIDCALL); - - user_assert(dst->desc.Pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL); - user_assert(src->desc.Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); - - user_assert(dst->desc.MultiSampleType < 2, D3DERR_INVALIDCALL); - user_assert(src->desc.MultiSampleType < 2, D3DERR_INVALIDCALL); - - user_assert(src->desc.Width == dst->desc.Width, D3DERR_INVALIDCALL); - user_assert(src->desc.Height == dst->desc.Height, D3DERR_INVALIDCALL); - - user_assert(src->desc.Format != D3DFMT_NULL, D3DERR_INVALIDCALL); - - NineSurface9_CopyDefaultToMem(dst, src); - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_GetFrontBufferData( struct NineDevice9 *This, - UINT iSwapChain, - IDirect3DSurface9 *pDestSurface ) -{ - DBG("This=%p iSwapChain=%u pDestSurface=%p\n", This, - iSwapChain, pDestSurface); - - user_assert(pDestSurface != NULL, D3DERR_INVALIDCALL); - user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL); - - return NineSwapChain9_GetFrontBufferData(This->swapchains[iSwapChain], - pDestSurface); -} - -HRESULT NINE_WINAPI -NineDevice9_StretchRect( struct NineDevice9 *This, - IDirect3DSurface9 *pSourceSurface, - const RECT *pSourceRect, - IDirect3DSurface9 *pDestSurface, - const RECT *pDestRect, - D3DTEXTUREFILTERTYPE Filter ) -{ - struct pipe_screen *screen = This->screen; - struct NineSurface9 *dst = NineSurface9(pDestSurface); - struct NineSurface9 *src = NineSurface9(pSourceSurface); - struct pipe_resource *dst_res = NineSurface9_GetResource(dst); - struct pipe_resource *src_res = NineSurface9_GetResource(src); - boolean zs; - struct pipe_blit_info blit; - boolean scaled, clamped, ms, flip_x = FALSE, flip_y = FALSE; - - DBG("This=%p pSourceSurface=%p pSourceRect=%p pDestSurface=%p " - "pDestRect=%p Filter=%u\n", - This, pSourceSurface, pSourceRect, pDestSurface, pDestRect, Filter); - if (pSourceRect) - DBG("pSourceRect=(%u,%u)-(%u,%u)\n", - pSourceRect->left, pSourceRect->top, - pSourceRect->right, pSourceRect->bottom); - if (pDestRect) - DBG("pDestRect=(%u,%u)-(%u,%u)\n", pDestRect->left, pDestRect->top, - pDestRect->right, pDestRect->bottom); - - user_assert(dst->base.pool == D3DPOOL_DEFAULT && - src->base.pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); - zs = util_format_is_depth_or_stencil(dst_res->format); - user_assert(!zs || !This->in_scene, D3DERR_INVALIDCALL); - user_assert(!zs || !pSourceRect || - (pSourceRect->left == 0 && - pSourceRect->top == 0 && - pSourceRect->right == src->desc.Width && - pSourceRect->bottom == src->desc.Height), D3DERR_INVALIDCALL); - user_assert(!zs || !pDestRect || - (pDestRect->left == 0 && - pDestRect->top == 0 && - pDestRect->right == dst->desc.Width && - pDestRect->bottom == dst->desc.Height), D3DERR_INVALIDCALL); - user_assert(!zs || - (dst->desc.Width == src->desc.Width && - dst->desc.Height == src->desc.Height), D3DERR_INVALIDCALL); - user_assert(zs || !util_format_is_depth_or_stencil(src_res->format), - D3DERR_INVALIDCALL); - user_assert(!zs || dst->desc.Format == src->desc.Format, - D3DERR_INVALIDCALL); - user_assert(screen->is_format_supported(screen, src_res->format, - src_res->target, - src_res->nr_samples, - src_res->nr_storage_samples, - PIPE_BIND_SAMPLER_VIEW), - D3DERR_INVALIDCALL); - - /* We might want to permit these, but wine thinks we shouldn't. */ - user_assert(!pDestRect || - (pDestRect->left <= pDestRect->right && - pDestRect->top <= pDestRect->bottom), D3DERR_INVALIDCALL); - user_assert(!pSourceRect || - (pSourceRect->left <= pSourceRect->right && - pSourceRect->top <= pSourceRect->bottom), D3DERR_INVALIDCALL); - - memset(&blit, 0, sizeof(blit)); - blit.dst.resource = dst_res; - blit.dst.level = dst->level; - blit.dst.box.z = dst->layer; - blit.dst.box.depth = 1; - blit.dst.format = dst_res->format; - if (pDestRect) { - flip_x = pDestRect->left > pDestRect->right; - if (flip_x) { - blit.dst.box.x = pDestRect->right; - blit.dst.box.width = pDestRect->left - pDestRect->right; - } else { - blit.dst.box.x = pDestRect->left; - blit.dst.box.width = pDestRect->right - pDestRect->left; - } - flip_y = pDestRect->top > pDestRect->bottom; - if (flip_y) { - blit.dst.box.y = pDestRect->bottom; - blit.dst.box.height = pDestRect->top - pDestRect->bottom; - } else { - blit.dst.box.y = pDestRect->top; - blit.dst.box.height = pDestRect->bottom - pDestRect->top; - } - } else { - blit.dst.box.x = 0; - blit.dst.box.y = 0; - blit.dst.box.width = dst->desc.Width; - blit.dst.box.height = dst->desc.Height; - } - blit.src.resource = src_res; - blit.src.level = src->level; - blit.src.box.z = src->layer; - blit.src.box.depth = 1; - blit.src.format = src_res->format; - if (pSourceRect) { - if (flip_x ^ (pSourceRect->left > pSourceRect->right)) { - blit.src.box.x = pSourceRect->right; - blit.src.box.width = pSourceRect->left - pSourceRect->right; - } else { - blit.src.box.x = pSourceRect->left; - blit.src.box.width = pSourceRect->right - pSourceRect->left; - } - if (flip_y ^ (pSourceRect->top > pSourceRect->bottom)) { - blit.src.box.y = pSourceRect->bottom; - blit.src.box.height = pSourceRect->top - pSourceRect->bottom; - } else { - blit.src.box.y = pSourceRect->top; - blit.src.box.height = pSourceRect->bottom - pSourceRect->top; - } - } else { - blit.src.box.x = flip_x ? src->desc.Width : 0; - blit.src.box.y = flip_y ? src->desc.Height : 0; - blit.src.box.width = flip_x ? -src->desc.Width : src->desc.Width; - blit.src.box.height = flip_y ? -src->desc.Height : src->desc.Height; - } - blit.mask = zs ? PIPE_MASK_ZS : PIPE_MASK_RGBA; - blit.filter = Filter == D3DTEXF_LINEAR ? - PIPE_TEX_FILTER_LINEAR : PIPE_TEX_FILTER_NEAREST; - blit.scissor_enable = FALSE; - blit.alpha_blend = FALSE; - - /* If both of a src and dst dimension are negative, flip them. */ - if (blit.dst.box.width < 0 && blit.src.box.width < 0) { - blit.dst.box.width = -blit.dst.box.width; - blit.src.box.width = -blit.src.box.width; - } - if (blit.dst.box.height < 0 && blit.src.box.height < 0) { - blit.dst.box.height = -blit.dst.box.height; - blit.src.box.height = -blit.src.box.height; - } - scaled = - blit.dst.box.width != blit.src.box.width || - blit.dst.box.height != blit.src.box.height; - - user_assert(!scaled || dst != src, D3DERR_INVALIDCALL); - user_assert(!scaled || - !NineSurface9_IsOffscreenPlain(dst), D3DERR_INVALIDCALL); - user_assert(!NineSurface9_IsOffscreenPlain(dst) || - NineSurface9_IsOffscreenPlain(src), D3DERR_INVALIDCALL); - user_assert(NineSurface9_IsOffscreenPlain(dst) || - dst->desc.Usage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL), - D3DERR_INVALIDCALL); - user_assert(!scaled || - (!util_format_is_compressed(dst->base.info.format) && - !util_format_is_compressed(src->base.info.format)), - D3DERR_INVALIDCALL); - - user_warn(src == dst && - u_box_test_intersection_2d(&blit.src.box, &blit.dst.box)); - - /* Check for clipping/clamping: */ - { - struct pipe_box box; - int xy; - - xy = u_box_clip_2d(&box, &blit.dst.box, - dst->desc.Width, dst->desc.Height); - if (xy < 0) - return D3D_OK; - if (xy == 0) - xy = u_box_clip_2d(&box, &blit.src.box, - src->desc.Width, src->desc.Height); - clamped = !!xy; - } - - ms = (dst->desc.MultiSampleType != src->desc.MultiSampleType) || - (dst->desc.MultiSampleQuality != src->desc.MultiSampleQuality); - - if (clamped || scaled || (blit.dst.format != blit.src.format) || ms) { - DBG("using pipe->blit()\n"); - /* TODO: software scaling */ - user_assert(screen->is_format_supported(screen, dst_res->format, - dst_res->target, - dst_res->nr_samples, - dst_res->nr_storage_samples, - zs ? PIPE_BIND_DEPTH_STENCIL : - PIPE_BIND_RENDER_TARGET), - D3DERR_INVALIDCALL); - - nine_context_blit(This, (struct NineUnknown *)dst, - (struct NineUnknown *)src, &blit); - } else { - assert(blit.dst.box.x >= 0 && blit.dst.box.y >= 0 && - blit.src.box.x >= 0 && blit.src.box.y >= 0 && - blit.dst.box.x + blit.dst.box.width <= dst->desc.Width && - blit.src.box.x + blit.src.box.width <= src->desc.Width && - blit.dst.box.y + blit.dst.box.height <= dst->desc.Height && - blit.src.box.y + blit.src.box.height <= src->desc.Height); - /* Or drivers might crash ... */ - DBG("Using resource_copy_region.\n"); - nine_context_resource_copy_region(This, (struct NineUnknown *)dst, - (struct NineUnknown *)src, - blit.dst.resource, blit.dst.level, - &blit.dst.box, - blit.src.resource, blit.src.level, - &blit.src.box); - } - - /* Communicate the container it needs to update sublevels - if apply */ - NineSurface9_MarkContainerDirty(dst); - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_ColorFill( struct NineDevice9 *This, - IDirect3DSurface9 *pSurface, - const RECT *pRect, - D3DCOLOR color ) -{ - struct NineSurface9 *surf = NineSurface9(pSurface); - unsigned x, y, w, h; - - DBG("This=%p pSurface=%p pRect=%p color=%08x\n", This, - pSurface, pRect, color); - if (pRect) - DBG("pRect=(%u,%u)-(%u,%u)\n", pRect->left, pRect->top, - pRect->right, pRect->bottom); - - user_assert(surf->base.pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); - - user_assert((surf->base.usage & D3DUSAGE_RENDERTARGET) || - NineSurface9_IsOffscreenPlain(surf), D3DERR_INVALIDCALL); - - user_assert(surf->desc.Format != D3DFMT_NULL, D3D_OK); - - if (pRect) { - x = pRect->left; - y = pRect->top; - w = pRect->right - pRect->left; - h = pRect->bottom - pRect->top; - /* Wine tests: */ - if (compressed_format(surf->desc.Format)) { - const unsigned bw = util_format_get_blockwidth(surf->base.info.format); - const unsigned bh = util_format_get_blockheight(surf->base.info.format); - - user_assert(!(x % bw) && !(y % bh) && !(w % bw) && !(h % bh), - D3DERR_INVALIDCALL); - } - } else{ - x = 0; - y = 0; - w = surf->desc.Width; - h = surf->desc.Height; - } - - if (surf->base.info.bind & PIPE_BIND_RENDER_TARGET) { - nine_context_clear_render_target(This, surf, color, x, y, w, h); - } else { - D3DLOCKED_RECT lock; - union util_color uc; - HRESULT hr; - /* XXX: lock pRect and fix util_fill_rect */ - hr = NineSurface9_LockRect(surf, &lock, NULL, pRect ? 0 : D3DLOCK_DISCARD); - if (FAILED(hr)) - return hr; - util_pack_color_ub(color >> 16, color >> 8, color >> 0, color >> 24, - surf->base.info.format, &uc); - util_fill_rect(lock.pBits, surf->base.info.format,lock.Pitch, - x, y, w, h, &uc); - NineSurface9_UnlockRect(surf); - } - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_CreateOffscreenPlainSurface( struct NineDevice9 *This, - UINT Width, - UINT Height, - D3DFORMAT Format, - D3DPOOL Pool, - IDirect3DSurface9 **ppSurface, - HANDLE *pSharedHandle ) -{ - HRESULT hr; - - DBG("This=%p Width=%u Height=%u Format=%s(0x%x) Pool=%u " - "ppSurface=%p pSharedHandle=%p\n", This, - Width, Height, d3dformat_to_string(Format), Format, Pool, - ppSurface, pSharedHandle); - - *ppSurface = NULL; - user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT - || Pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL); - user_assert(Pool != D3DPOOL_MANAGED, D3DERR_INVALIDCALL); - - /* Can be used with StretchRect and ColorFill. It's also always lockable. - */ - hr = create_zs_or_rt_surface(This, 2, Pool, Width, Height, - Format, - D3DMULTISAMPLE_NONE, 0, - TRUE, - ppSurface, pSharedHandle); - if (FAILED(hr)) - DBG("Failed to create surface.\n"); - return hr; -} - -HRESULT NINE_WINAPI -NineDevice9_SetRenderTarget( struct NineDevice9 *This, - DWORD RenderTargetIndex, - IDirect3DSurface9 *pRenderTarget ) -{ - struct NineSurface9 *rt = NineSurface9(pRenderTarget); - const unsigned i = RenderTargetIndex; - - DBG("This=%p RenderTargetIndex=%u pRenderTarget=%p\n", This, - RenderTargetIndex, pRenderTarget); - - user_assert(i < This->caps.NumSimultaneousRTs, D3DERR_INVALIDCALL); - user_assert(i != 0 || pRenderTarget, D3DERR_INVALIDCALL); - user_assert(!pRenderTarget || - rt->desc.Usage & D3DUSAGE_RENDERTARGET, D3DERR_INVALIDCALL); - - if (i == 0) { - This->state.viewport.X = 0; - This->state.viewport.Y = 0; - This->state.viewport.Width = rt->desc.Width; - This->state.viewport.Height = rt->desc.Height; - This->state.viewport.MinZ = 0.0f; - This->state.viewport.MaxZ = 1.0f; - - This->state.scissor.minx = 0; - This->state.scissor.miny = 0; - This->state.scissor.maxx = rt->desc.Width; - This->state.scissor.maxy = rt->desc.Height; - } - - if (This->state.rt[i] != NineSurface9(pRenderTarget)) - nine_bind(&This->state.rt[i], pRenderTarget); - - nine_context_set_render_target(This, i, rt); - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_GetRenderTarget( struct NineDevice9 *This, - DWORD RenderTargetIndex, - IDirect3DSurface9 **ppRenderTarget ) -{ - const unsigned i = RenderTargetIndex; - - user_assert(i < This->caps.NumSimultaneousRTs, D3DERR_INVALIDCALL); - user_assert(ppRenderTarget, D3DERR_INVALIDCALL); - - *ppRenderTarget = (IDirect3DSurface9 *)This->state.rt[i]; - if (!This->state.rt[i]) - return D3DERR_NOTFOUND; - - NineUnknown_AddRef(NineUnknown(This->state.rt[i])); - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_SetDepthStencilSurface( struct NineDevice9 *This, - IDirect3DSurface9 *pNewZStencil ) -{ - struct NineSurface9 *ds = NineSurface9(pNewZStencil); - DBG("This=%p pNewZStencil=%p\n", This, pNewZStencil); - - if (This->state.ds != ds) { - nine_bind(&This->state.ds, ds); - nine_context_set_depth_stencil(This, ds); - } - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_GetDepthStencilSurface( struct NineDevice9 *This, - IDirect3DSurface9 **ppZStencilSurface ) -{ - user_assert(ppZStencilSurface, D3DERR_INVALIDCALL); - - *ppZStencilSurface = (IDirect3DSurface9 *)This->state.ds; - if (!This->state.ds) - return D3DERR_NOTFOUND; - - NineUnknown_AddRef(NineUnknown(This->state.ds)); - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_BeginScene( struct NineDevice9 *This ) -{ - DBG("This=%p\n", This); - user_assert(!This->in_scene, D3DERR_INVALIDCALL); - This->in_scene = TRUE; - /* Do we want to do anything else here ? */ - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_EndScene( struct NineDevice9 *This ) -{ - DBG("This=%p\n", This); - user_assert(This->in_scene, D3DERR_INVALIDCALL); - This->in_scene = FALSE; - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_Clear( struct NineDevice9 *This, - DWORD Count, - const D3DRECT *pRects, - DWORD Flags, - D3DCOLOR Color, - float Z, - DWORD Stencil ) -{ - struct NineSurface9 *zsbuf_surf = This->state.ds; - - DBG("This=%p Count=%u pRects=%p Flags=%x Color=%08x Z=%f Stencil=%x\n", - This, Count, pRects, Flags, Color, Z, Stencil); - - user_assert(This->state.ds || !(Flags & NINED3DCLEAR_DEPTHSTENCIL), - D3DERR_INVALIDCALL); - user_assert(!(Flags & D3DCLEAR_STENCIL) || - (zsbuf_surf && - util_format_is_depth_and_stencil(zsbuf_surf->base.info.format)), - D3DERR_INVALIDCALL); -#ifdef NINE_STRICT - user_assert((Count && pRects) || (!Count && !pRects), D3DERR_INVALIDCALL); -#else - user_warn((pRects && !Count) || (!pRects && Count)); - if (pRects && !Count) - return D3D_OK; - if (!pRects) - Count = 0; -#endif - - nine_context_clear_fb(This, Count, pRects, Flags, Color, Z, Stencil); - return D3D_OK; -} - -static void -nine_D3DMATRIX_print(const D3DMATRIX *M) -{ - DBG("\n(%f %f %f %f)\n" - "(%f %f %f %f)\n" - "(%f %f %f %f)\n" - "(%f %f %f %f)\n", - M->m[0][0], M->m[0][1], M->m[0][2], M->m[0][3], - M->m[1][0], M->m[1][1], M->m[1][2], M->m[1][3], - M->m[2][0], M->m[2][1], M->m[2][2], M->m[2][3], - M->m[3][0], M->m[3][1], M->m[3][2], M->m[3][3]); -} - -HRESULT NINE_WINAPI -NineDevice9_SetTransform( struct NineDevice9 *This, - D3DTRANSFORMSTATETYPE State, - const D3DMATRIX *pMatrix ) -{ - struct nine_state *state = This->update; - D3DMATRIX *M = nine_state_access_transform(&state->ff, State, TRUE); - - DBG("This=%p State=%d pMatrix=%p\n", This, State, pMatrix); - - user_assert(M, D3DERR_INVALIDCALL); - nine_D3DMATRIX_print(pMatrix); - - *M = *pMatrix; - if (unlikely(This->is_recording)) { - state->ff.changed.transform[State / 32] |= 1 << (State % 32); - state->changed.group |= NINE_STATE_FF_VSTRANSF; - } else - nine_context_set_transform(This, State, pMatrix); - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_GetTransform( struct NineDevice9 *This, - D3DTRANSFORMSTATETYPE State, - D3DMATRIX *pMatrix ) -{ - D3DMATRIX *M = nine_state_access_transform(&This->state.ff, State, FALSE); - user_assert(M, D3DERR_INVALIDCALL); - *pMatrix = *M; - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_MultiplyTransform( struct NineDevice9 *This, - D3DTRANSFORMSTATETYPE State, - const D3DMATRIX *pMatrix ) -{ - struct nine_state *state = This->update; - D3DMATRIX T; - D3DMATRIX *M = nine_state_access_transform(&state->ff, State, TRUE); - - DBG("This=%p State=%d pMatrix=%p\n", This, State, pMatrix); - - user_assert(M, D3DERR_INVALIDCALL); - - nine_d3d_matrix_matrix_mul(&T, pMatrix, M); - return NineDevice9_SetTransform(This, State, &T); -} - -HRESULT NINE_WINAPI -NineDevice9_SetViewport( struct NineDevice9 *This, - const D3DVIEWPORT9 *pViewport ) -{ - struct nine_state *state = This->update; - - DBG("X=%u Y=%u W=%u H=%u MinZ=%f MaxZ=%f\n", - pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, - pViewport->MinZ, pViewport->MaxZ); - - state->viewport = *pViewport; - nine_context_set_viewport(This, pViewport); - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_GetViewport( struct NineDevice9 *This, - D3DVIEWPORT9 *pViewport ) -{ - *pViewport = This->state.viewport; - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_SetMaterial( struct NineDevice9 *This, - const D3DMATERIAL9 *pMaterial ) -{ - struct nine_state *state = This->update; - - DBG("This=%p pMaterial=%p\n", This, pMaterial); - if (pMaterial) - nine_dump_D3DMATERIAL9(DBG_FF, pMaterial); - - user_assert(pMaterial, E_POINTER); - - state->ff.material = *pMaterial; - if (unlikely(This->is_recording)) - state->changed.group |= NINE_STATE_FF_MATERIAL; - else - nine_context_set_material(This, pMaterial); - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_GetMaterial( struct NineDevice9 *This, - D3DMATERIAL9 *pMaterial ) -{ - user_assert(pMaterial, E_POINTER); - *pMaterial = This->state.ff.material; - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_SetLight( struct NineDevice9 *This, - DWORD Index, - const D3DLIGHT9 *pLight ) -{ - struct nine_state *state = This->update; - HRESULT hr; - - DBG("This=%p Index=%u pLight=%p\n", This, Index, pLight); - if (pLight) - nine_dump_D3DLIGHT9(DBG_FF, pLight); - - user_assert(pLight, D3DERR_INVALIDCALL); - user_assert(pLight->Type < NINED3DLIGHT_INVALID, D3DERR_INVALIDCALL); - - user_assert(Index < NINE_MAX_LIGHTS, D3DERR_INVALIDCALL); /* sanity */ - - hr = nine_state_set_light(&state->ff, Index, pLight); - if (hr != D3D_OK) - return hr; - - if (pLight->Type != D3DLIGHT_DIRECTIONAL && - pLight->Attenuation0 == 0.0f && - pLight->Attenuation1 == 0.0f && - pLight->Attenuation2 == 0.0f) { - DBG("Warning: all D3DLIGHT9.Attenuation[i] are 0\n"); - } - - if (unlikely(This->is_recording)) - state->changed.group |= NINE_STATE_FF_LIGHTING; - else - nine_context_set_light(This, Index, pLight); - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_GetLight( struct NineDevice9 *This, - DWORD Index, - D3DLIGHT9 *pLight ) -{ - const struct nine_state *state = &This->state; - - user_assert(pLight, D3DERR_INVALIDCALL); - user_assert(Index < state->ff.num_lights, D3DERR_INVALIDCALL); - user_assert(state->ff.light[Index].Type < NINED3DLIGHT_INVALID, - D3DERR_INVALIDCALL); - - *pLight = state->ff.light[Index]; - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_LightEnable( struct NineDevice9 *This, - DWORD Index, - BOOL Enable ) -{ - struct nine_state *state = This->update; - - DBG("This=%p Index=%u Enable=%i\n", This, Index, Enable); - - if (Index >= state->ff.num_lights || - state->ff.light[Index].Type == NINED3DLIGHT_INVALID) { - /* This should create a default light. */ - D3DLIGHT9 light; - memset(&light, 0, sizeof(light)); - light.Type = D3DLIGHT_DIRECTIONAL; - light.Diffuse.r = 1.0f; - light.Diffuse.g = 1.0f; - light.Diffuse.b = 1.0f; - light.Direction.z = 1.0f; - NineDevice9_SetLight(This, Index, &light); - } - - nine_state_light_enable(&state->ff, Index, Enable); - if (likely(!This->is_recording)) - nine_context_light_enable(This, Index, Enable); - else - state->changed.group |= NINE_STATE_FF_LIGHTING; - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_GetLightEnable( struct NineDevice9 *This, - DWORD Index, - BOOL *pEnable ) -{ - const struct nine_state *state = &This->state; - unsigned i; - - user_assert(Index < state->ff.num_lights, D3DERR_INVALIDCALL); - user_assert(state->ff.light[Index].Type < NINED3DLIGHT_INVALID, - D3DERR_INVALIDCALL); - - for (i = 0; i < state->ff.num_lights_active; ++i) - if (state->ff.active_light[i] == Index) - break; - - *pEnable = i != state->ff.num_lights_active ? 128 : 0; // Taken from wine - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_SetClipPlane( struct NineDevice9 *This, - DWORD Index, - const float *pPlane ) -{ - struct nine_state *state = This->update; - - user_assert(pPlane, D3DERR_INVALIDCALL); - - DBG("This=%p Index=%u pPlane=%f %f %f %f\n", This, Index, - pPlane[0], pPlane[1], - pPlane[2], pPlane[3]); - - user_assert(Index < PIPE_MAX_CLIP_PLANES, D3DERR_INVALIDCALL); - - memcpy(&state->clip.ucp[Index][0], pPlane, sizeof(state->clip.ucp[0])); - if (unlikely(This->is_recording)) - state->changed.ucp |= 1 << Index; - else - nine_context_set_clip_plane(This, Index, (struct nine_clipplane *)pPlane); - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_GetClipPlane( struct NineDevice9 *This, - DWORD Index, - float *pPlane ) -{ - const struct nine_state *state = &This->state; - - user_assert(Index < PIPE_MAX_CLIP_PLANES, D3DERR_INVALIDCALL); - - memcpy(pPlane, &state->clip.ucp[Index][0], sizeof(state->clip.ucp[0])); - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_SetRenderState( struct NineDevice9 *This, - D3DRENDERSTATETYPE State, - DWORD Value ) -{ - struct nine_state *state = This->update; - - DBG("This=%p State=%u(%s) Value=%08x\n", This, - State, nine_d3drs_to_string(State), Value); - - user_assert(State < D3DRS_COUNT, D3DERR_INVALIDCALL); - - if (unlikely(This->is_recording)) { - state->rs_advertised[State] = Value; - /* only need to record changed render states for stateblocks */ - state->changed.rs[State / 32] |= 1 << (State % 32); - return D3D_OK; - } - - if (state->rs_advertised[State] == Value) - return D3D_OK; - - state->rs_advertised[State] = Value; - nine_context_set_render_state(This, State, Value); - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_GetRenderState( struct NineDevice9 *This, - D3DRENDERSTATETYPE State, - DWORD *pValue ) -{ - user_assert(State < D3DRS_COUNT, D3DERR_INVALIDCALL); - - *pValue = This->state.rs_advertised[State]; - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_CreateStateBlock( struct NineDevice9 *This, - D3DSTATEBLOCKTYPE Type, - IDirect3DStateBlock9 **ppSB ) -{ - struct NineStateBlock9 *nsb; - struct nine_state *dst; - HRESULT hr; - enum nine_stateblock_type type; - unsigned s; - - DBG("This=%p Type=%u ppSB=%p\n", This, Type, ppSB); - - user_assert(Type == D3DSBT_ALL || - Type == D3DSBT_VERTEXSTATE || - Type == D3DSBT_PIXELSTATE, D3DERR_INVALIDCALL); - - switch (Type) { - case D3DSBT_VERTEXSTATE: type = NINESBT_VERTEXSTATE; break; - case D3DSBT_PIXELSTATE: type = NINESBT_PIXELSTATE; break; - default: - type = NINESBT_ALL; - break; - } - - hr = NineStateBlock9_new(This, &nsb, type); - if (FAILED(hr)) - return hr; - *ppSB = (IDirect3DStateBlock9 *)nsb; - dst = &nsb->state; - - dst->changed.group = NINE_STATE_SAMPLER; - - if (Type == D3DSBT_ALL || Type == D3DSBT_VERTEXSTATE) { - dst->changed.group |= - NINE_STATE_FF_LIGHTING | - NINE_STATE_VS | NINE_STATE_VS_CONST | - NINE_STATE_VDECL; - /* TODO: texture/sampler state */ - memcpy(dst->changed.rs, - nine_render_states_vertex, sizeof(dst->changed.rs)); - nine_ranges_insert(&dst->changed.vs_const_f, 0, This->may_swvp ? NINE_MAX_CONST_F_SWVP : This->max_vs_const_f, - &This->range_pool); - nine_ranges_insert(&dst->changed.vs_const_i, 0, This->may_swvp ? NINE_MAX_CONST_I_SWVP : NINE_MAX_CONST_I, - &This->range_pool); - nine_ranges_insert(&dst->changed.vs_const_b, 0, This->may_swvp ? NINE_MAX_CONST_B_SWVP : NINE_MAX_CONST_B, - &This->range_pool); - for (s = 0; s < NINE_MAX_SAMPLERS; ++s) - dst->changed.sampler[s] |= 1 << D3DSAMP_DMAPOFFSET; - if (This->state.ff.num_lights) { - dst->ff.num_lights = This->state.ff.num_lights; - /* zero'd -> light type won't be NINED3DLIGHT_INVALID, so - * all currently existing lights will be captured - */ - dst->ff.light = CALLOC(This->state.ff.num_lights, - sizeof(D3DLIGHT9)); - if (!dst->ff.light) { - nine_bind(ppSB, NULL); - return E_OUTOFMEMORY; - } - } - } - if (Type == D3DSBT_ALL || Type == D3DSBT_PIXELSTATE) { - dst->changed.group |= - NINE_STATE_PS | NINE_STATE_PS_CONST | NINE_STATE_FF_PS_CONSTS; - memcpy(dst->changed.rs, - nine_render_states_pixel, sizeof(dst->changed.rs)); - nine_ranges_insert(&dst->changed.ps_const_f, 0, This->max_ps_const_f, - &This->range_pool); - dst->changed.ps_const_i = 0xffff; - dst->changed.ps_const_b = 0xffff; - for (s = 0; s < NINE_MAX_SAMPLERS; ++s) - dst->changed.sampler[s] |= 0x1ffe; - for (s = 0; s < NINE_MAX_TEXTURE_STAGES; ++s) { - dst->ff.changed.tex_stage[s][0] |= 0xffffffff; - dst->ff.changed.tex_stage[s][1] |= 0xffffffff; - } - } - if (Type == D3DSBT_ALL) { - dst->changed.group |= - NINE_STATE_VIEWPORT | - NINE_STATE_SCISSOR | - NINE_STATE_IDXBUF | - NINE_STATE_FF_MATERIAL | - NINE_STATE_FF_VSTRANSF; - memset(dst->changed.rs, ~0, (D3DRS_COUNT / 32) * sizeof(uint32_t)); - dst->changed.rs[D3DRS_LAST / 32] |= (1 << (D3DRS_COUNT % 32)) - 1; - dst->changed.vtxbuf = (1ULL << This->caps.MaxStreams) - 1; - dst->changed.stream_freq = dst->changed.vtxbuf; - dst->changed.ucp = (1 << PIPE_MAX_CLIP_PLANES) - 1; - dst->changed.texture = (1 << NINE_MAX_SAMPLERS) - 1; - /* The doc says the projection, world, view and texture matrices - * are saved, which would translate to: - * dst->ff.changed.transform[0] = 0x00FF000C; - * dst->ff.changed.transform[D3DTS_WORLD / 32] |= 1 << (D3DTS_WORLD % 32); - * However we assume they meant save everything (which is basically just the - * above plus the other world matrices). - */ - dst->ff.changed.transform[0] = 0x00FF000C; - for (s = 0; s < 8; s++) - dst->ff.changed.transform[8+s] = ~0; - } - NineStateBlock9_Capture(NineStateBlock9(*ppSB)); - - /* TODO: fixed function state */ - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_BeginStateBlock( struct NineDevice9 *This ) -{ - HRESULT hr; - - DBG("This=%p\n", This); - - user_assert(!This->record, D3DERR_INVALIDCALL); - - hr = NineStateBlock9_new(This, &This->record, NINESBT_CUSTOM); - if (FAILED(hr)) - return hr; - NineUnknown_ConvertRefToBind(NineUnknown(This->record)); - - This->update = &This->record->state; - This->is_recording = TRUE; - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_EndStateBlock( struct NineDevice9 *This, - IDirect3DStateBlock9 **ppSB ) -{ - DBG("This=%p ppSB=%p\n", This, ppSB); - - user_assert(This->record, D3DERR_INVALIDCALL); - - This->update = &This->state; - This->is_recording = FALSE; - - NineUnknown_AddRef(NineUnknown(This->record)); - *ppSB = (IDirect3DStateBlock9 *)This->record; - NineUnknown_Unbind(NineUnknown(This->record)); - This->record = NULL; - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_SetClipStatus( struct NineDevice9 *This, - const D3DCLIPSTATUS9 *pClipStatus ) -{ - STUB(D3DERR_INVALIDCALL); -} - -HRESULT NINE_WINAPI -NineDevice9_GetClipStatus( struct NineDevice9 *This, - D3DCLIPSTATUS9 *pClipStatus ) -{ - STUB(D3DERR_INVALIDCALL); -} - -HRESULT NINE_WINAPI -NineDevice9_GetTexture( struct NineDevice9 *This, - DWORD Stage, - IDirect3DBaseTexture9 **ppTexture ) -{ - user_assert(Stage < NINE_MAX_SAMPLERS_PS || - Stage == D3DDMAPSAMPLER || - (Stage >= D3DVERTEXTEXTURESAMPLER0 && - Stage <= D3DVERTEXTEXTURESAMPLER3), D3DERR_INVALIDCALL); - user_assert(ppTexture, D3DERR_INVALIDCALL); - - if (Stage >= D3DDMAPSAMPLER) - Stage = Stage - D3DDMAPSAMPLER + NINE_MAX_SAMPLERS_PS; - - *ppTexture = (IDirect3DBaseTexture9 *)This->state.texture[Stage]; - - if (This->state.texture[Stage]) - NineUnknown_AddRef(NineUnknown(This->state.texture[Stage])); - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_SetTexture( struct NineDevice9 *This, - DWORD Stage, - IDirect3DBaseTexture9 *pTexture ) -{ - struct nine_state *state = This->update; - struct NineBaseTexture9 *tex = NineBaseTexture9(pTexture); - struct NineBaseTexture9 *old; - - DBG("This=%p Stage=%u pTexture=%p\n", This, Stage, pTexture); - - user_assert(Stage < NINE_MAX_SAMPLERS_PS || - Stage == D3DDMAPSAMPLER || - (Stage >= D3DVERTEXTEXTURESAMPLER0 && - Stage <= D3DVERTEXTEXTURESAMPLER3), D3DERR_INVALIDCALL); - user_assert(!tex || (tex->base.pool != D3DPOOL_SCRATCH && - tex->base.pool != D3DPOOL_SYSTEMMEM), D3DERR_INVALIDCALL); - - if (Stage >= D3DDMAPSAMPLER) - Stage = Stage - D3DDMAPSAMPLER + NINE_MAX_SAMPLERS_PS; - - if (This->is_recording) { - state->changed.texture |= 1 << Stage; - nine_bind(&state->texture[Stage], pTexture); - return D3D_OK; - } - - old = state->texture[Stage]; - if (old == tex) - return D3D_OK; - - NineBindTextureToDevice(This, &state->texture[Stage], tex); - - nine_context_set_texture(This, Stage, tex); - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_GetTextureStageState( struct NineDevice9 *This, - DWORD Stage, - D3DTEXTURESTAGESTATETYPE Type, - DWORD *pValue ) -{ - const struct nine_state *state = &This->state; - - user_assert(Stage < ARRAY_SIZE(state->ff.tex_stage), D3DERR_INVALIDCALL); - user_assert(Type < ARRAY_SIZE(state->ff.tex_stage[0]), D3DERR_INVALIDCALL); - - *pValue = state->ff.tex_stage[Stage][Type]; - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_SetTextureStageState( struct NineDevice9 *This, - DWORD Stage, - D3DTEXTURESTAGESTATETYPE Type, - DWORD Value ) -{ - struct nine_state *state = This->update; - - DBG("Stage=%u Type=%u Value=%08x\n", Stage, Type, Value); - nine_dump_D3DTSS_value(DBG_FF, Type, Value); - - user_assert(Stage < ARRAY_SIZE(state->ff.tex_stage), D3DERR_INVALIDCALL); - user_assert(Type < ARRAY_SIZE(state->ff.tex_stage[0]), D3DERR_INVALIDCALL); - - state->ff.tex_stage[Stage][Type] = Value; - - if (unlikely(This->is_recording)) { - state->changed.group |= NINE_STATE_FF_PS_CONSTS; - state->ff.changed.tex_stage[Stage][Type / 32] |= 1 << (Type % 32); - } else - nine_context_set_texture_stage_state(This, Stage, Type, Value); - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_GetSamplerState( struct NineDevice9 *This, - DWORD Sampler, - D3DSAMPLERSTATETYPE Type, - DWORD *pValue ) -{ - user_assert(Sampler < NINE_MAX_SAMPLERS_PS || - Sampler == D3DDMAPSAMPLER || - (Sampler >= D3DVERTEXTEXTURESAMPLER0 && - Sampler <= D3DVERTEXTEXTURESAMPLER3), D3DERR_INVALIDCALL); - - if (Sampler >= D3DDMAPSAMPLER) - Sampler = Sampler - D3DDMAPSAMPLER + NINE_MAX_SAMPLERS_PS; - - *pValue = This->state.samp_advertised[Sampler][Type]; - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_SetSamplerState( struct NineDevice9 *This, - DWORD Sampler, - D3DSAMPLERSTATETYPE Type, - DWORD Value ) -{ - struct nine_state *state = This->update; - - DBG("This=%p Sampler=%u Type=%s Value=%08x\n", This, - Sampler, nine_D3DSAMP_to_str(Type), Value); - - user_assert(Sampler < NINE_MAX_SAMPLERS_PS || - Sampler == D3DDMAPSAMPLER || - (Sampler >= D3DVERTEXTEXTURESAMPLER0 && - Sampler <= D3DVERTEXTEXTURESAMPLER3), D3DERR_INVALIDCALL); - - if (Sampler >= D3DDMAPSAMPLER) - Sampler = Sampler - D3DDMAPSAMPLER + NINE_MAX_SAMPLERS_PS; - - if (unlikely(This->is_recording)) { - state->samp_advertised[Sampler][Type] = Value; - state->changed.group |= NINE_STATE_SAMPLER; - state->changed.sampler[Sampler] |= 1 << Type; - return D3D_OK; - } - - if (state->samp_advertised[Sampler][Type] == Value) - return D3D_OK; - - state->samp_advertised[Sampler][Type] = Value; - nine_context_set_sampler_state(This, Sampler, Type, Value); - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_ValidateDevice( struct NineDevice9 *This, - DWORD *pNumPasses ) -{ - const struct nine_state *state = &This->state; - unsigned i; - unsigned w = 0, h = 0; - - DBG("This=%p pNumPasses=%p\n", This, pNumPasses); - - for (i = 0; i < ARRAY_SIZE(state->samp_advertised); ++i) { - if (state->samp_advertised[i][D3DSAMP_MINFILTER] == D3DTEXF_NONE || - state->samp_advertised[i][D3DSAMP_MAGFILTER] == D3DTEXF_NONE) - return D3DERR_UNSUPPORTEDTEXTUREFILTER; - } - - for (i = 0; i < This->caps.NumSimultaneousRTs; ++i) { - if (!state->rt[i]) - continue; - if (w == 0) { - w = state->rt[i]->desc.Width; - h = state->rt[i]->desc.Height; - } else - if (state->rt[i]->desc.Width != w || state->rt[i]->desc.Height != h) { - return D3DERR_CONFLICTINGRENDERSTATE; - } - } - if (state->ds && - (state->rs_advertised[D3DRS_ZENABLE] || state->rs_advertised[D3DRS_STENCILENABLE])) { - if (w != 0 && - (state->ds->desc.Width != w || state->ds->desc.Height != h)) - return D3DERR_CONFLICTINGRENDERSTATE; - } - - if (pNumPasses) - *pNumPasses = 1; - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_SetPaletteEntries( struct NineDevice9 *This, - UINT PaletteNumber, - const PALETTEENTRY *pEntries ) -{ - STUB(D3D_OK); /* like wine */ -} - -HRESULT NINE_WINAPI -NineDevice9_GetPaletteEntries( struct NineDevice9 *This, - UINT PaletteNumber, - PALETTEENTRY *pEntries ) -{ - STUB(D3DERR_INVALIDCALL); -} - -HRESULT NINE_WINAPI -NineDevice9_SetCurrentTexturePalette( struct NineDevice9 *This, - UINT PaletteNumber ) -{ - STUB(D3D_OK); /* like wine */ -} - -HRESULT NINE_WINAPI -NineDevice9_GetCurrentTexturePalette( struct NineDevice9 *This, - UINT *PaletteNumber ) -{ - STUB(D3DERR_INVALIDCALL); -} - -HRESULT NINE_WINAPI -NineDevice9_SetScissorRect( struct NineDevice9 *This, - const RECT *pRect ) -{ - struct nine_state *state = This->update; - - DBG("x=(%u..%u) y=(%u..%u)\n", - pRect->left, pRect->top, pRect->right, pRect->bottom); - - state->scissor.minx = pRect->left; - state->scissor.miny = pRect->top; - state->scissor.maxx = pRect->right; - state->scissor.maxy = pRect->bottom; - - if (unlikely(This->is_recording)) - state->changed.group |= NINE_STATE_SCISSOR; - else - nine_context_set_scissor(This, &state->scissor); - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_GetScissorRect( struct NineDevice9 *This, - RECT *pRect ) -{ - pRect->left = This->state.scissor.minx; - pRect->top = This->state.scissor.miny; - pRect->right = This->state.scissor.maxx; - pRect->bottom = This->state.scissor.maxy; - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_SetSoftwareVertexProcessing( struct NineDevice9 *This, - BOOL bSoftware ) -{ - if (This->params.BehaviorFlags & D3DCREATE_MIXED_VERTEXPROCESSING) { - This->swvp = bSoftware; - nine_context_set_swvp(This, bSoftware); - return D3D_OK; - } else - return D3D_OK; /* msdn seems to indicate INVALIDCALL, but at least Halo expects OK */ -} - -BOOL NINE_WINAPI -NineDevice9_GetSoftwareVertexProcessing( struct NineDevice9 *This ) -{ - return This->swvp; -} - -HRESULT NINE_WINAPI -NineDevice9_SetNPatchMode( struct NineDevice9 *This, - float nSegments ) -{ - return D3D_OK; /* Nothing to do because we don't advertise NPatch support */ -} - -float NINE_WINAPI -NineDevice9_GetNPatchMode( struct NineDevice9 *This ) -{ - STUB(0); -} - -/* TODO: only go through dirty textures */ -static void -validate_textures(struct NineDevice9 *device) -{ - struct NineBaseTexture9 *tex, *ptr; - LIST_FOR_EACH_ENTRY_SAFE(tex, ptr, &device->update_textures, list) { - list_delinit(&tex->list); - NineBaseTexture9_Validate(tex); - } -} - -static void -update_managed_buffers(struct NineDevice9 *device) -{ - struct NineBuffer9 *buf, *ptr; - LIST_FOR_EACH_ENTRY_SAFE(buf, ptr, &device->update_buffers, managed.list) { - list_delinit(&buf->managed.list); - NineBuffer9_Upload(buf); - } -} - -static void -NineBeforeDraw( struct NineDevice9 *This ) -{ - /* Upload Managed dirty content */ - validate_textures(This); /* may clobber state */ - update_managed_buffers(This); -} - -static void -NineAfterDraw( struct NineDevice9 *This ) -{ - unsigned i; - struct nine_state *state = &This->state; - unsigned ps_mask = state->ps ? state->ps->rt_mask : 1; - - /* Flag render-targets with autogenmipmap for mipmap regeneration */ - for (i = 0; i < This->caps.NumSimultaneousRTs; ++i) { - struct NineSurface9 *rt = state->rt[i]; - - if (rt && rt->desc.Format != D3DFMT_NULL && (ps_mask & (1 << i)) && - rt->desc.Usage & D3DUSAGE_AUTOGENMIPMAP) { - assert(rt->texture == D3DRTYPE_TEXTURE || - rt->texture == D3DRTYPE_CUBETEXTURE); - NineBaseTexture9(rt->base.base.container)->dirty_mip = TRUE; - } - } -} - -HRESULT NINE_WINAPI -NineDevice9_DrawPrimitive( struct NineDevice9 *This, - D3DPRIMITIVETYPE PrimitiveType, - UINT StartVertex, - UINT PrimitiveCount ) -{ - DBG("iface %p, PrimitiveType %u, StartVertex %u, PrimitiveCount %u\n", - This, PrimitiveType, StartVertex, PrimitiveCount); - - NineBeforeDraw(This); - nine_context_draw_primitive(This, PrimitiveType, StartVertex, PrimitiveCount); - NineAfterDraw(This); - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_DrawIndexedPrimitive( struct NineDevice9 *This, - D3DPRIMITIVETYPE PrimitiveType, - INT BaseVertexIndex, - UINT MinVertexIndex, - UINT NumVertices, - UINT StartIndex, - UINT PrimitiveCount ) -{ - DBG("iface %p, PrimitiveType %u, BaseVertexIndex %u, MinVertexIndex %u " - "NumVertices %u, StartIndex %u, PrimitiveCount %u\n", - This, PrimitiveType, BaseVertexIndex, MinVertexIndex, NumVertices, - StartIndex, PrimitiveCount); - - user_assert(This->state.idxbuf, D3DERR_INVALIDCALL); - user_assert(This->state.vdecl, D3DERR_INVALIDCALL); - - NineBeforeDraw(This); - nine_context_draw_indexed_primitive(This, PrimitiveType, BaseVertexIndex, - MinVertexIndex, NumVertices, StartIndex, - PrimitiveCount); - NineAfterDraw(This); - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_DrawPrimitiveUP( struct NineDevice9 *This, - D3DPRIMITIVETYPE PrimitiveType, - UINT PrimitiveCount, - const void *pVertexStreamZeroData, - UINT VertexStreamZeroStride ) -{ - struct pipe_vertex_buffer vtxbuf; - - DBG("iface %p, PrimitiveType %u, PrimitiveCount %u, data %p, stride %u\n", - This, PrimitiveType, PrimitiveCount, - pVertexStreamZeroData, VertexStreamZeroStride); - - user_assert(pVertexStreamZeroData && VertexStreamZeroStride, - D3DERR_INVALIDCALL); - user_assert(PrimitiveCount, D3D_OK); - - vtxbuf.stride = VertexStreamZeroStride; - vtxbuf.buffer_offset = 0; - vtxbuf.is_user_buffer = true; - vtxbuf.buffer.user = pVertexStreamZeroData; - - if (!This->driver_caps.user_vbufs) { - vtxbuf.is_user_buffer = false; - vtxbuf.buffer.resource = NULL; - u_upload_data(This->vertex_uploader, - 0, - (prim_count_to_vertex_count(PrimitiveType, PrimitiveCount)) * VertexStreamZeroStride, /* XXX */ - 4, - pVertexStreamZeroData, - &vtxbuf.buffer_offset, - &vtxbuf.buffer.resource); - u_upload_unmap(This->vertex_uploader); - } - - NineBeforeDraw(This); - nine_context_draw_primitive_from_vtxbuf(This, PrimitiveType, PrimitiveCount, &vtxbuf); - NineAfterDraw(This); - - pipe_vertex_buffer_unreference(&vtxbuf); - - NineDevice9_PauseRecording(This); - NineDevice9_SetStreamSource(This, 0, NULL, 0, 0); - NineDevice9_ResumeRecording(This); - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_DrawIndexedPrimitiveUP( struct NineDevice9 *This, - D3DPRIMITIVETYPE PrimitiveType, - UINT MinVertexIndex, - UINT NumVertices, - UINT PrimitiveCount, - const void *pIndexData, - D3DFORMAT IndexDataFormat, - const void *pVertexStreamZeroData, - UINT VertexStreamZeroStride ) -{ - struct pipe_vertex_buffer vbuf; - - DBG("iface %p, PrimitiveType %u, MinVertexIndex %u, NumVertices %u " - "PrimitiveCount %u, pIndexData %p, IndexDataFormat %u " - "pVertexStreamZeroData %p, VertexStreamZeroStride %u\n", - This, PrimitiveType, MinVertexIndex, NumVertices, PrimitiveCount, - pIndexData, IndexDataFormat, - pVertexStreamZeroData, VertexStreamZeroStride); - - user_assert(pIndexData && pVertexStreamZeroData, D3DERR_INVALIDCALL); - user_assert(VertexStreamZeroStride, D3DERR_INVALIDCALL); - user_assert(IndexDataFormat == D3DFMT_INDEX16 || - IndexDataFormat == D3DFMT_INDEX32, D3DERR_INVALIDCALL); - user_assert(PrimitiveCount, D3D_OK); - - vbuf.stride = VertexStreamZeroStride; - vbuf.buffer_offset = 0; - vbuf.is_user_buffer = true; - vbuf.buffer.user = pVertexStreamZeroData; - - unsigned index_size = (IndexDataFormat == D3DFMT_INDEX16) ? 2 : 4; - struct pipe_resource *ibuf = NULL; - - if (!This->driver_caps.user_vbufs) { - const unsigned base = MinVertexIndex * VertexStreamZeroStride; - vbuf.is_user_buffer = false; - vbuf.buffer.resource = NULL; - u_upload_data(This->vertex_uploader, - base, - NumVertices * VertexStreamZeroStride, /* XXX */ - 4, - (const uint8_t *)pVertexStreamZeroData + base, - &vbuf.buffer_offset, - &vbuf.buffer.resource); - u_upload_unmap(This->vertex_uploader); - /* Won't be used: */ - vbuf.buffer_offset -= base; - } - - unsigned index_offset = 0; - if (This->csmt_active) { - u_upload_data(This->pipe_secondary->stream_uploader, - 0, - (prim_count_to_vertex_count(PrimitiveType, PrimitiveCount)) * index_size, - 4, - pIndexData, - &index_offset, - &ibuf); - u_upload_unmap(This->pipe_secondary->stream_uploader); - } - - NineBeforeDraw(This); - nine_context_draw_indexed_primitive_from_vtxbuf_idxbuf(This, PrimitiveType, - MinVertexIndex, - NumVertices, - PrimitiveCount, - &vbuf, - ibuf, - ibuf ? NULL : (void*)pIndexData, - index_offset, - index_size); - NineAfterDraw(This); - - pipe_vertex_buffer_unreference(&vbuf); - pipe_resource_reference(&ibuf, NULL); - - NineDevice9_PauseRecording(This); - NineDevice9_SetIndices(This, NULL); - NineDevice9_SetStreamSource(This, 0, NULL, 0, 0); - NineDevice9_ResumeRecording(This); - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_ProcessVertices( struct NineDevice9 *This, - UINT SrcStartIndex, - UINT DestIndex, - UINT VertexCount, - IDirect3DVertexBuffer9 *pDestBuffer, - IDirect3DVertexDeclaration9 *pVertexDecl, - DWORD Flags ) -{ - struct pipe_screen *screen_sw = This->screen_sw; - struct pipe_context *pipe_sw = This->pipe_sw; - struct NineVertexDeclaration9 *vdecl = NineVertexDeclaration9(pVertexDecl); - struct NineVertexBuffer9 *dst = NineVertexBuffer9(pDestBuffer); - struct NineVertexShader9 *vs; - struct pipe_resource *resource; - struct pipe_transfer *transfer = NULL; - struct pipe_stream_output_info so; - struct pipe_stream_output_target *target; - struct pipe_draw_info draw; - struct pipe_box box; - bool programmable_vs = This->state.vs && !(This->state.vdecl && This->state.vdecl->position_t); - unsigned offsets[1] = {0}; - HRESULT hr; - unsigned buffer_size; - void *map; - - DBG("This=%p SrcStartIndex=%u DestIndex=%u VertexCount=%u " - "pDestBuffer=%p pVertexDecl=%p Flags=%d\n", - This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, - pVertexDecl, Flags); - - if (!screen_sw->get_param(screen_sw, PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS)) { - DBG("ProcessVertices not supported\n"); - return D3DERR_INVALIDCALL; - } - - - vs = programmable_vs ? This->state.vs : This->ff.vs; - /* Note: version is 0 for ff */ - user_assert(vdecl || (vs->byte_code.version < 0x30 && dst->desc.FVF), - D3DERR_INVALIDCALL); - if (!vdecl) { - DWORD FVF = dst->desc.FVF; - vdecl = util_hash_table_get(This->ff.ht_fvf, &FVF); - if (!vdecl) { - hr = NineVertexDeclaration9_new_from_fvf(This, FVF, &vdecl); - if (FAILED(hr)) - return hr; - vdecl->fvf = FVF; - _mesa_hash_table_insert(This->ff.ht_fvf, &vdecl->fvf, vdecl); - NineUnknown_ConvertRefToBind(NineUnknown(vdecl)); - } - } - - /* Flags: Can be 0 or D3DPV_DONOTCOPYDATA, and/or lock flags - * D3DPV_DONOTCOPYDATA -> Has effect only for ff. In particular - * if not set, everything from src will be used, and dst - * must match exactly the ff vs outputs. - * TODO: Handle all the checks, etc for ff */ - user_assert(vdecl->position_t || programmable_vs, - D3DERR_INVALIDCALL); - - /* TODO: Support vs < 3 and ff */ - user_assert(vs->byte_code.version == 0x30, - D3DERR_INVALIDCALL); - /* TODO: Not hardcode the constant buffers for swvp */ - user_assert(This->may_swvp, - D3DERR_INVALIDCALL); - - nine_state_prepare_draw_sw(This, vdecl, SrcStartIndex, VertexCount, &so); - - buffer_size = VertexCount * so.stride[0] * 4; - { - struct pipe_resource templ; - - memset(&templ, 0, sizeof(templ)); - templ.target = PIPE_BUFFER; - templ.format = PIPE_FORMAT_R8_UNORM; - templ.width0 = buffer_size; - templ.flags = 0; - templ.bind = PIPE_BIND_STREAM_OUTPUT; - templ.usage = PIPE_USAGE_STREAM; - templ.height0 = templ.depth0 = templ.array_size = 1; - templ.last_level = templ.nr_samples = templ.nr_storage_samples = 0; - - resource = screen_sw->resource_create(screen_sw, &templ); - if (!resource) - return E_OUTOFMEMORY; - } - target = pipe_sw->create_stream_output_target(pipe_sw, resource, - 0, buffer_size); - if (!target) { - pipe_resource_reference(&resource, NULL); - return D3DERR_DRIVERINTERNALERROR; - } - - draw.mode = PIPE_PRIM_POINTS; - draw.count = VertexCount; - draw.start_instance = 0; - draw.primitive_restart = FALSE; - draw.restart_index = 0; - draw.count_from_stream_output = NULL; - draw.indirect = NULL; - draw.instance_count = 1; - draw.index_size = 0; - draw.start = 0; - draw.index_bias = 0; - draw.min_index = 0; - draw.max_index = VertexCount - 1; - - - pipe_sw->set_stream_output_targets(pipe_sw, 1, &target, offsets); - - pipe_sw->draw_vbo(pipe_sw, &draw); - - pipe_sw->set_stream_output_targets(pipe_sw, 0, NULL, 0); - pipe_sw->stream_output_target_destroy(pipe_sw, target); - - u_box_1d(0, VertexCount * so.stride[0] * 4, &box); - map = pipe_sw->transfer_map(pipe_sw, resource, 0, PIPE_TRANSFER_READ, &box, - &transfer); - if (!map) { - hr = D3DERR_DRIVERINTERNALERROR; - goto out; - } - - hr = NineVertexDeclaration9_ConvertStreamOutput(vdecl, - dst, DestIndex, VertexCount, - map, &so); - if (transfer) - pipe_sw->transfer_unmap(pipe_sw, transfer); - -out: - nine_state_after_draw_sw(This); - pipe_resource_reference(&resource, NULL); - return hr; -} - -HRESULT NINE_WINAPI -NineDevice9_CreateVertexDeclaration( struct NineDevice9 *This, - const D3DVERTEXELEMENT9 *pVertexElements, - IDirect3DVertexDeclaration9 **ppDecl ) -{ - struct NineVertexDeclaration9 *vdecl; - - DBG("This=%p pVertexElements=%p ppDecl=%p\n", - This, pVertexElements, ppDecl); - - HRESULT hr = NineVertexDeclaration9_new(This, pVertexElements, &vdecl); - if (SUCCEEDED(hr)) - *ppDecl = (IDirect3DVertexDeclaration9 *)vdecl; - - return hr; -} - -HRESULT NINE_WINAPI -NineDevice9_SetVertexDeclaration( struct NineDevice9 *This, - IDirect3DVertexDeclaration9 *pDecl ) -{ - struct nine_state *state = This->update; - struct NineVertexDeclaration9 *vdecl = NineVertexDeclaration9(pDecl); - - DBG("This=%p pDecl=%p\n", This, pDecl); - - if (unlikely(This->is_recording)) { - nine_bind(&state->vdecl, vdecl); - state->changed.group |= NINE_STATE_VDECL; - return D3D_OK; - } - - if (state->vdecl == vdecl) - return D3D_OK; - - nine_bind(&state->vdecl, vdecl); - - nine_context_set_vertex_declaration(This, vdecl); - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_GetVertexDeclaration( struct NineDevice9 *This, - IDirect3DVertexDeclaration9 **ppDecl ) -{ - user_assert(ppDecl, D3DERR_INVALIDCALL); - - *ppDecl = (IDirect3DVertexDeclaration9 *)This->state.vdecl; - if (*ppDecl) - NineUnknown_AddRef(NineUnknown(*ppDecl)); - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_SetFVF( struct NineDevice9 *This, - DWORD FVF ) -{ - struct NineVertexDeclaration9 *vdecl; - HRESULT hr; - - DBG("FVF = %08x\n", FVF); - if (!FVF) - return D3D_OK; /* like wine */ - - vdecl = util_hash_table_get(This->ff.ht_fvf, &FVF); - if (!vdecl) { - hr = NineVertexDeclaration9_new_from_fvf(This, FVF, &vdecl); - if (FAILED(hr)) - return hr; - vdecl->fvf = FVF; - _mesa_hash_table_insert(This->ff.ht_fvf, &vdecl->fvf, vdecl); - NineUnknown_ConvertRefToBind(NineUnknown(vdecl)); - } - return NineDevice9_SetVertexDeclaration( - This, (IDirect3DVertexDeclaration9 *)vdecl); -} - -HRESULT NINE_WINAPI -NineDevice9_GetFVF( struct NineDevice9 *This, - DWORD *pFVF ) -{ - *pFVF = This->state.vdecl ? This->state.vdecl->fvf : 0; - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_CreateVertexShader( struct NineDevice9 *This, - const DWORD *pFunction, - IDirect3DVertexShader9 **ppShader ) -{ - struct NineVertexShader9 *vs; - HRESULT hr; - - DBG("This=%p pFunction=%p ppShader=%p\n", This, pFunction, ppShader); - - hr = NineVertexShader9_new(This, &vs, pFunction, NULL); - if (FAILED(hr)) - return hr; - *ppShader = (IDirect3DVertexShader9 *)vs; - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_SetVertexShader( struct NineDevice9 *This, - IDirect3DVertexShader9 *pShader ) -{ - struct nine_state *state = This->update; - struct NineVertexShader9 *vs_shader = (struct NineVertexShader9*)pShader; - - DBG("This=%p pShader=%p\n", This, pShader); - - if (unlikely(This->is_recording)) { - nine_bind(&state->vs, vs_shader); - state->changed.group |= NINE_STATE_VS; - return D3D_OK; - } - - if (state->vs == vs_shader) - return D3D_OK; - - nine_bind(&state->vs, vs_shader); - - nine_context_set_vertex_shader(This, vs_shader); - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_GetVertexShader( struct NineDevice9 *This, - IDirect3DVertexShader9 **ppShader ) -{ - user_assert(ppShader, D3DERR_INVALIDCALL); - nine_reference_set(ppShader, This->state.vs); - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_SetVertexShaderConstantF( struct NineDevice9 *This, - UINT StartRegister, - const float *pConstantData, - UINT Vector4fCount ) -{ - struct nine_state *state = This->update; - float *vs_const_f = state->vs_const_f; - - DBG("This=%p StartRegister=%u pConstantData=%p Vector4fCount=%u\n", - This, StartRegister, pConstantData, Vector4fCount); - - user_assert(StartRegister < This->caps.MaxVertexShaderConst, D3DERR_INVALIDCALL); - user_assert(StartRegister + Vector4fCount <= This->caps.MaxVertexShaderConst, D3DERR_INVALIDCALL); - - if (!Vector4fCount) - return D3D_OK; - user_assert(pConstantData, D3DERR_INVALIDCALL); - - if (unlikely(This->is_recording)) { - memcpy(&vs_const_f[StartRegister * 4], - pConstantData, - Vector4fCount * 4 * sizeof(state->vs_const_f[0])); - - nine_ranges_insert(&state->changed.vs_const_f, - StartRegister, StartRegister + Vector4fCount, - &This->range_pool); - - state->changed.group |= NINE_STATE_VS_CONST; - - return D3D_OK; - } - - if (!memcmp(&vs_const_f[StartRegister * 4], pConstantData, - Vector4fCount * 4 * sizeof(state->vs_const_f[0]))) - return D3D_OK; - - memcpy(&vs_const_f[StartRegister * 4], - pConstantData, - Vector4fCount * 4 * sizeof(state->vs_const_f[0])); - - nine_context_set_vertex_shader_constant_f(This, StartRegister, pConstantData, - Vector4fCount * 4 * sizeof(state->vs_const_f[0]), - Vector4fCount); - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_GetVertexShaderConstantF( struct NineDevice9 *This, - UINT StartRegister, - float *pConstantData, - UINT Vector4fCount ) -{ - const struct nine_state *state = &This->state; - - user_assert(StartRegister < This->caps.MaxVertexShaderConst, D3DERR_INVALIDCALL); - user_assert(StartRegister + Vector4fCount <= This->caps.MaxVertexShaderConst, D3DERR_INVALIDCALL); - user_assert(pConstantData, D3DERR_INVALIDCALL); - - memcpy(pConstantData, - &state->vs_const_f[StartRegister * 4], - Vector4fCount * 4 * sizeof(state->vs_const_f[0])); - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_SetVertexShaderConstantI( struct NineDevice9 *This, - UINT StartRegister, - const int *pConstantData, - UINT Vector4iCount ) -{ - struct nine_state *state = This->update; - int i; - - DBG("This=%p StartRegister=%u pConstantData=%p Vector4iCount=%u\n", - This, StartRegister, pConstantData, Vector4iCount); - - user_assert(StartRegister < (This->may_swvp ? NINE_MAX_CONST_I_SWVP : NINE_MAX_CONST_I), - D3DERR_INVALIDCALL); - user_assert(StartRegister + Vector4iCount <= (This->may_swvp ? NINE_MAX_CONST_I_SWVP : NINE_MAX_CONST_I), - D3DERR_INVALIDCALL); - user_assert(pConstantData, D3DERR_INVALIDCALL); - - if (This->driver_caps.vs_integer) { - if (!This->is_recording) { - if (!memcmp(&state->vs_const_i[4 * StartRegister], pConstantData, - Vector4iCount * sizeof(int[4]))) - return D3D_OK; - } - memcpy(&state->vs_const_i[4 * StartRegister], - pConstantData, - Vector4iCount * sizeof(int[4])); - } else { - for (i = 0; i < Vector4iCount; i++) { - state->vs_const_i[4 * (StartRegister + i)] = fui((float)(pConstantData[4 * i])); - state->vs_const_i[4 * (StartRegister + i) + 1] = fui((float)(pConstantData[4 * i + 1])); - state->vs_const_i[4 * (StartRegister + i) + 2] = fui((float)(pConstantData[4 * i + 2])); - state->vs_const_i[4 * (StartRegister + i) + 3] = fui((float)(pConstantData[4 * i + 3])); - } - } - - if (unlikely(This->is_recording)) { - nine_ranges_insert(&state->changed.vs_const_i, - StartRegister, StartRegister + Vector4iCount, - &This->range_pool); - state->changed.group |= NINE_STATE_VS_CONST; - } else - nine_context_set_vertex_shader_constant_i(This, StartRegister, pConstantData, - Vector4iCount * sizeof(int[4]), Vector4iCount); - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_GetVertexShaderConstantI( struct NineDevice9 *This, - UINT StartRegister, - int *pConstantData, - UINT Vector4iCount ) -{ - const struct nine_state *state = &This->state; - int i; - - user_assert(StartRegister < (This->may_swvp ? NINE_MAX_CONST_I_SWVP : NINE_MAX_CONST_I), - D3DERR_INVALIDCALL); - user_assert(StartRegister + Vector4iCount <= (This->may_swvp ? NINE_MAX_CONST_I_SWVP : NINE_MAX_CONST_I), - D3DERR_INVALIDCALL); - user_assert(pConstantData, D3DERR_INVALIDCALL); - - if (This->driver_caps.vs_integer) { - memcpy(pConstantData, - &state->vs_const_i[4 * StartRegister], - Vector4iCount * sizeof(int[4])); - } else { - for (i = 0; i < Vector4iCount; i++) { - pConstantData[4 * i] = (int32_t) uif(state->vs_const_i[4 * (StartRegister + i)]); - pConstantData[4 * i + 1] = (int32_t) uif(state->vs_const_i[4 * (StartRegister + i) + 1]); - pConstantData[4 * i + 2] = (int32_t) uif(state->vs_const_i[4 * (StartRegister + i) + 2]); - pConstantData[4 * i + 3] = (int32_t) uif(state->vs_const_i[4 * (StartRegister + i) + 3]); - } - } - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_SetVertexShaderConstantB( struct NineDevice9 *This, - UINT StartRegister, - const BOOL *pConstantData, - UINT BoolCount ) -{ - struct nine_state *state = This->update; - int i; - uint32_t bool_true = This->driver_caps.vs_integer ? 0xFFFFFFFF : fui(1.0f); - - DBG("This=%p StartRegister=%u pConstantData=%p BoolCount=%u\n", - This, StartRegister, pConstantData, BoolCount); - - user_assert(StartRegister < (This->may_swvp ? NINE_MAX_CONST_B_SWVP : NINE_MAX_CONST_B), - D3DERR_INVALIDCALL); - user_assert(StartRegister + BoolCount <= (This->may_swvp ? NINE_MAX_CONST_B_SWVP : NINE_MAX_CONST_B), - D3DERR_INVALIDCALL); - user_assert(pConstantData, D3DERR_INVALIDCALL); - - if (!This->is_recording) { - bool noChange = true; - for (i = 0; i < BoolCount; i++) { - if (!!state->vs_const_b[StartRegister + i] != !!pConstantData[i]) - noChange = false; - } - if (noChange) - return D3D_OK; - } - - for (i = 0; i < BoolCount; i++) - state->vs_const_b[StartRegister + i] = pConstantData[i] ? bool_true : 0; - - if (unlikely(This->is_recording)) { - nine_ranges_insert(&state->changed.vs_const_b, - StartRegister, StartRegister + BoolCount, - &This->range_pool); - state->changed.group |= NINE_STATE_VS_CONST; - } else - nine_context_set_vertex_shader_constant_b(This, StartRegister, pConstantData, - sizeof(BOOL) * BoolCount, BoolCount); - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_GetVertexShaderConstantB( struct NineDevice9 *This, - UINT StartRegister, - BOOL *pConstantData, - UINT BoolCount ) -{ - const struct nine_state *state = &This->state; - int i; - - user_assert(StartRegister < (This->may_swvp ? NINE_MAX_CONST_B_SWVP : NINE_MAX_CONST_B), - D3DERR_INVALIDCALL); - user_assert(StartRegister + BoolCount <= (This->may_swvp ? NINE_MAX_CONST_B_SWVP : NINE_MAX_CONST_B), - D3DERR_INVALIDCALL); - user_assert(pConstantData, D3DERR_INVALIDCALL); - - for (i = 0; i < BoolCount; i++) - pConstantData[i] = state->vs_const_b[StartRegister + i] != 0 ? TRUE : FALSE; - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_SetStreamSource( struct NineDevice9 *This, - UINT StreamNumber, - IDirect3DVertexBuffer9 *pStreamData, - UINT OffsetInBytes, - UINT Stride ) -{ - struct nine_state *state = This->update; - struct NineVertexBuffer9 *pVBuf9 = NineVertexBuffer9(pStreamData); - const unsigned i = StreamNumber; - - DBG("This=%p StreamNumber=%u pStreamData=%p OffsetInBytes=%u Stride=%u\n", - This, StreamNumber, pStreamData, OffsetInBytes, Stride); - - user_assert(StreamNumber < This->caps.MaxStreams, D3DERR_INVALIDCALL); - user_assert(Stride <= This->caps.MaxStreamStride, D3DERR_INVALIDCALL); - - if (unlikely(This->is_recording)) { - nine_bind(&state->stream[i], pStreamData); - state->changed.vtxbuf |= 1 << StreamNumber; - state->vtxbuf[i].stride = Stride; - state->vtxbuf[i].buffer_offset = OffsetInBytes; - return D3D_OK; - } - - if (state->stream[i] == NineVertexBuffer9(pStreamData) && - state->vtxbuf[i].stride == Stride && - state->vtxbuf[i].buffer_offset == OffsetInBytes) - return D3D_OK; - - state->vtxbuf[i].stride = Stride; - state->vtxbuf[i].buffer_offset = OffsetInBytes; - - NineBindBufferToDevice(This, - (struct NineBuffer9 **)&state->stream[i], - (struct NineBuffer9 *)pVBuf9); - - nine_context_set_stream_source(This, - StreamNumber, - pVBuf9, - OffsetInBytes, - Stride); - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_GetStreamSource( struct NineDevice9 *This, - UINT StreamNumber, - IDirect3DVertexBuffer9 **ppStreamData, - UINT *pOffsetInBytes, - UINT *pStride ) -{ - const struct nine_state *state = &This->state; - const unsigned i = StreamNumber; - - user_assert(StreamNumber < This->caps.MaxStreams, D3DERR_INVALIDCALL); - user_assert(ppStreamData, D3DERR_INVALIDCALL); - - nine_reference_set(ppStreamData, state->stream[i]); - *pStride = state->vtxbuf[i].stride; - *pOffsetInBytes = state->vtxbuf[i].buffer_offset; - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_SetStreamSourceFreq( struct NineDevice9 *This, - UINT StreamNumber, - UINT Setting ) -{ - struct nine_state *state = This->update; - /* const UINT freq = Setting & 0x7FFFFF; */ - - DBG("This=%p StreamNumber=%u FrequencyParameter=0x%x\n", This, - StreamNumber, Setting); - - user_assert(StreamNumber < This->caps.MaxStreams, D3DERR_INVALIDCALL); - user_assert(StreamNumber != 0 || !(Setting & D3DSTREAMSOURCE_INSTANCEDATA), - D3DERR_INVALIDCALL); - user_assert(!((Setting & D3DSTREAMSOURCE_INSTANCEDATA) && - (Setting & D3DSTREAMSOURCE_INDEXEDDATA)), D3DERR_INVALIDCALL); - user_assert(Setting, D3DERR_INVALIDCALL); - - if (unlikely(This->is_recording)) { - state->stream_freq[StreamNumber] = Setting; - state->changed.stream_freq |= 1 << StreamNumber; - return D3D_OK; - } - - if (state->stream_freq[StreamNumber] == Setting) - return D3D_OK; - - state->stream_freq[StreamNumber] = Setting; - - nine_context_set_stream_source_freq(This, StreamNumber, Setting); - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_GetStreamSourceFreq( struct NineDevice9 *This, - UINT StreamNumber, - UINT *pSetting ) -{ - user_assert(StreamNumber < This->caps.MaxStreams, D3DERR_INVALIDCALL); - *pSetting = This->state.stream_freq[StreamNumber]; - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_SetIndices( struct NineDevice9 *This, - IDirect3DIndexBuffer9 *pIndexData ) -{ - struct nine_state *state = This->update; - struct NineIndexBuffer9 *idxbuf = NineIndexBuffer9(pIndexData); - - DBG("This=%p pIndexData=%p\n", This, pIndexData); - - if (unlikely(This->is_recording)) { - nine_bind(&state->idxbuf, idxbuf); - state->changed.group |= NINE_STATE_IDXBUF; - return D3D_OK; - } - - if (state->idxbuf == idxbuf) - return D3D_OK; - - NineBindBufferToDevice(This, - (struct NineBuffer9 **)&state->idxbuf, - (struct NineBuffer9 *)idxbuf); - - nine_context_set_indices(This, idxbuf); - - return D3D_OK; -} - -/* XXX: wine/d3d9 doesn't have pBaseVertexIndex, and it doesn't make sense - * here because it's an argument passed to the Draw calls. - */ -HRESULT NINE_WINAPI -NineDevice9_GetIndices( struct NineDevice9 *This, - IDirect3DIndexBuffer9 **ppIndexData) -{ - user_assert(ppIndexData, D3DERR_INVALIDCALL); - nine_reference_set(ppIndexData, This->state.idxbuf); - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_CreatePixelShader( struct NineDevice9 *This, - const DWORD *pFunction, - IDirect3DPixelShader9 **ppShader ) -{ - struct NinePixelShader9 *ps; - HRESULT hr; - - DBG("This=%p pFunction=%p ppShader=%p\n", This, pFunction, ppShader); - - hr = NinePixelShader9_new(This, &ps, pFunction, NULL); - if (FAILED(hr)) - return hr; - *ppShader = (IDirect3DPixelShader9 *)ps; - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_SetPixelShader( struct NineDevice9 *This, - IDirect3DPixelShader9 *pShader ) -{ - struct nine_state *state = This->update; - struct NinePixelShader9 *ps = (struct NinePixelShader9*)pShader; - - DBG("This=%p pShader=%p\n", This, pShader); - - if (unlikely(This->is_recording)) { - nine_bind(&state->ps, pShader); - state->changed.group |= NINE_STATE_PS; - return D3D_OK; - } - - if (state->ps == ps) - return D3D_OK; - - nine_bind(&state->ps, ps); - - nine_context_set_pixel_shader(This, ps); - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_GetPixelShader( struct NineDevice9 *This, - IDirect3DPixelShader9 **ppShader ) -{ - user_assert(ppShader, D3DERR_INVALIDCALL); - nine_reference_set(ppShader, This->state.ps); - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_SetPixelShaderConstantF( struct NineDevice9 *This, - UINT StartRegister, - const float *pConstantData, - UINT Vector4fCount ) -{ - struct nine_state *state = This->update; - - DBG("This=%p StartRegister=%u pConstantData=%p Vector4fCount=%u\n", - This, StartRegister, pConstantData, Vector4fCount); - - user_assert(StartRegister < NINE_MAX_CONST_F_PS3, D3DERR_INVALIDCALL); - user_assert(StartRegister + Vector4fCount <= NINE_MAX_CONST_F_PS3, D3DERR_INVALIDCALL); - - if (!Vector4fCount) - return D3D_OK; - user_assert(pConstantData, D3DERR_INVALIDCALL); - - if (unlikely(This->is_recording)) { - memcpy(&state->ps_const_f[StartRegister * 4], - pConstantData, - Vector4fCount * 4 * sizeof(state->ps_const_f[0])); - - nine_ranges_insert(&state->changed.ps_const_f, - StartRegister, StartRegister + Vector4fCount, - &This->range_pool); - - state->changed.group |= NINE_STATE_PS_CONST; - return D3D_OK; - } - - if (!memcmp(&state->ps_const_f[StartRegister * 4], pConstantData, - Vector4fCount * 4 * sizeof(state->ps_const_f[0]))) - return D3D_OK; - - memcpy(&state->ps_const_f[StartRegister * 4], - pConstantData, - Vector4fCount * 4 * sizeof(state->ps_const_f[0])); - - nine_context_set_pixel_shader_constant_f(This, StartRegister, pConstantData, - Vector4fCount * 4 * sizeof(state->ps_const_f[0]), - Vector4fCount); - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_GetPixelShaderConstantF( struct NineDevice9 *This, - UINT StartRegister, - float *pConstantData, - UINT Vector4fCount ) -{ - const struct nine_state *state = &This->state; - - user_assert(StartRegister < NINE_MAX_CONST_F_PS3, D3DERR_INVALIDCALL); - user_assert(StartRegister + Vector4fCount <= NINE_MAX_CONST_F_PS3, D3DERR_INVALIDCALL); - user_assert(pConstantData, D3DERR_INVALIDCALL); - - memcpy(pConstantData, - &state->ps_const_f[StartRegister * 4], - Vector4fCount * 4 * sizeof(state->ps_const_f[0])); - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_SetPixelShaderConstantI( struct NineDevice9 *This, - UINT StartRegister, - const int *pConstantData, - UINT Vector4iCount ) -{ - struct nine_state *state = This->update; - int i; - - DBG("This=%p StartRegister=%u pConstantData=%p Vector4iCount=%u\n", - This, StartRegister, pConstantData, Vector4iCount); - - user_assert(StartRegister < NINE_MAX_CONST_I, D3DERR_INVALIDCALL); - user_assert(StartRegister + Vector4iCount <= NINE_MAX_CONST_I, D3DERR_INVALIDCALL); - user_assert(pConstantData, D3DERR_INVALIDCALL); - - if (This->driver_caps.ps_integer) { - if (!This->is_recording) { - if (!memcmp(&state->ps_const_i[StartRegister][0], pConstantData, - Vector4iCount * sizeof(state->ps_const_i[0]))) - return D3D_OK; - } - memcpy(&state->ps_const_i[StartRegister][0], - pConstantData, - Vector4iCount * sizeof(state->ps_const_i[0])); - } else { - for (i = 0; i < Vector4iCount; i++) { - state->ps_const_i[StartRegister+i][0] = fui((float)(pConstantData[4*i])); - state->ps_const_i[StartRegister+i][1] = fui((float)(pConstantData[4*i+1])); - state->ps_const_i[StartRegister+i][2] = fui((float)(pConstantData[4*i+2])); - state->ps_const_i[StartRegister+i][3] = fui((float)(pConstantData[4*i+3])); - } - } - - if (unlikely(This->is_recording)) { - state->changed.ps_const_i |= ((1 << Vector4iCount) - 1) << StartRegister; - state->changed.group |= NINE_STATE_PS_CONST; - } else - nine_context_set_pixel_shader_constant_i(This, StartRegister, pConstantData, - sizeof(state->ps_const_i[0]) * Vector4iCount, Vector4iCount); - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_GetPixelShaderConstantI( struct NineDevice9 *This, - UINT StartRegister, - int *pConstantData, - UINT Vector4iCount ) -{ - const struct nine_state *state = &This->state; - int i; - - user_assert(StartRegister < NINE_MAX_CONST_I, D3DERR_INVALIDCALL); - user_assert(StartRegister + Vector4iCount <= NINE_MAX_CONST_I, D3DERR_INVALIDCALL); - user_assert(pConstantData, D3DERR_INVALIDCALL); - - if (This->driver_caps.ps_integer) { - memcpy(pConstantData, - &state->ps_const_i[StartRegister][0], - Vector4iCount * sizeof(state->ps_const_i[0])); - } else { - for (i = 0; i < Vector4iCount; i++) { - pConstantData[4*i] = (int32_t) uif(state->ps_const_i[StartRegister+i][0]); - pConstantData[4*i+1] = (int32_t) uif(state->ps_const_i[StartRegister+i][1]); - pConstantData[4*i+2] = (int32_t) uif(state->ps_const_i[StartRegister+i][2]); - pConstantData[4*i+3] = (int32_t) uif(state->ps_const_i[StartRegister+i][3]); - } - } - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_SetPixelShaderConstantB( struct NineDevice9 *This, - UINT StartRegister, - const BOOL *pConstantData, - UINT BoolCount ) -{ - struct nine_state *state = This->update; - int i; - uint32_t bool_true = This->driver_caps.ps_integer ? 0xFFFFFFFF : fui(1.0f); - - DBG("This=%p StartRegister=%u pConstantData=%p BoolCount=%u\n", - This, StartRegister, pConstantData, BoolCount); - - user_assert(StartRegister < NINE_MAX_CONST_B, D3DERR_INVALIDCALL); - user_assert(StartRegister + BoolCount <= NINE_MAX_CONST_B, D3DERR_INVALIDCALL); - user_assert(pConstantData, D3DERR_INVALIDCALL); - - if (!This->is_recording) { - bool noChange = true; - for (i = 0; i < BoolCount; i++) { - if (!!state->ps_const_b[StartRegister + i] != !!pConstantData[i]) - noChange = false; - } - if (noChange) - return D3D_OK; - } - - for (i = 0; i < BoolCount; i++) - state->ps_const_b[StartRegister + i] = pConstantData[i] ? bool_true : 0; - - if (unlikely(This->is_recording)) { - state->changed.ps_const_b |= ((1 << BoolCount) - 1) << StartRegister; - state->changed.group |= NINE_STATE_PS_CONST; - } else - nine_context_set_pixel_shader_constant_b(This, StartRegister, pConstantData, - sizeof(BOOL) * BoolCount, BoolCount); - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_GetPixelShaderConstantB( struct NineDevice9 *This, - UINT StartRegister, - BOOL *pConstantData, - UINT BoolCount ) -{ - const struct nine_state *state = &This->state; - int i; - - user_assert(StartRegister < NINE_MAX_CONST_B, D3DERR_INVALIDCALL); - user_assert(StartRegister + BoolCount <= NINE_MAX_CONST_B, D3DERR_INVALIDCALL); - user_assert(pConstantData, D3DERR_INVALIDCALL); - - for (i = 0; i < BoolCount; i++) - pConstantData[i] = state->ps_const_b[StartRegister + i] ? TRUE : FALSE; - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9_DrawRectPatch( struct NineDevice9 *This, - UINT Handle, - const float *pNumSegs, - const D3DRECTPATCH_INFO *pRectPatchInfo ) -{ - STUB(D3DERR_INVALIDCALL); -} - -HRESULT NINE_WINAPI -NineDevice9_DrawTriPatch( struct NineDevice9 *This, - UINT Handle, - const float *pNumSegs, - const D3DTRIPATCH_INFO *pTriPatchInfo ) -{ - STUB(D3DERR_INVALIDCALL); -} - -HRESULT NINE_WINAPI -NineDevice9_DeletePatch( struct NineDevice9 *This, - UINT Handle ) -{ - STUB(D3DERR_INVALIDCALL); -} - -HRESULT NINE_WINAPI -NineDevice9_CreateQuery( struct NineDevice9 *This, - D3DQUERYTYPE Type, - IDirect3DQuery9 **ppQuery ) -{ - struct NineQuery9 *query; - HRESULT hr; - - DBG("This=%p Type=%d ppQuery=%p\n", This, Type, ppQuery); - - hr = nine_is_query_supported(This->screen, Type); - if (!ppQuery || hr != D3D_OK) - return hr; - - hr = NineQuery9_new(This, &query, Type); - if (FAILED(hr)) - return hr; - *ppQuery = (IDirect3DQuery9 *)query; - return D3D_OK; -} - -IDirect3DDevice9Vtbl NineDevice9_vtable = { - (void *)NineUnknown_QueryInterface, - (void *)NineUnknown_AddRef, - (void *)NineUnknown_Release, - (void *)NineDevice9_TestCooperativeLevel, - (void *)NineDevice9_GetAvailableTextureMem, - (void *)NineDevice9_EvictManagedResources, - (void *)NineDevice9_GetDirect3D, - (void *)NineDevice9_GetDeviceCaps, - (void *)NineDevice9_GetDisplayMode, - (void *)NineDevice9_GetCreationParameters, - (void *)NineDevice9_SetCursorProperties, - (void *)NineDevice9_SetCursorPosition, - (void *)NineDevice9_ShowCursor, - (void *)NineDevice9_CreateAdditionalSwapChain, - (void *)NineDevice9_GetSwapChain, - (void *)NineDevice9_GetNumberOfSwapChains, - (void *)NineDevice9_Reset, - (void *)NineDevice9_Present, - (void *)NineDevice9_GetBackBuffer, - (void *)NineDevice9_GetRasterStatus, - (void *)NineDevice9_SetDialogBoxMode, - (void *)NineDevice9_SetGammaRamp, - (void *)NineDevice9_GetGammaRamp, - (void *)NineDevice9_CreateTexture, - (void *)NineDevice9_CreateVolumeTexture, - (void *)NineDevice9_CreateCubeTexture, - (void *)NineDevice9_CreateVertexBuffer, - (void *)NineDevice9_CreateIndexBuffer, - (void *)NineDevice9_CreateRenderTarget, - (void *)NineDevice9_CreateDepthStencilSurface, - (void *)NineDevice9_UpdateSurface, - (void *)NineDevice9_UpdateTexture, - (void *)NineDevice9_GetRenderTargetData, - (void *)NineDevice9_GetFrontBufferData, - (void *)NineDevice9_StretchRect, - (void *)NineDevice9_ColorFill, - (void *)NineDevice9_CreateOffscreenPlainSurface, - (void *)NineDevice9_SetRenderTarget, - (void *)NineDevice9_GetRenderTarget, - (void *)NineDevice9_SetDepthStencilSurface, - (void *)NineDevice9_GetDepthStencilSurface, - (void *)NineDevice9_BeginScene, - (void *)NineDevice9_EndScene, - (void *)NineDevice9_Clear, - (void *)NineDevice9_SetTransform, - (void *)NineDevice9_GetTransform, - (void *)NineDevice9_MultiplyTransform, - (void *)NineDevice9_SetViewport, - (void *)NineDevice9_GetViewport, - (void *)NineDevice9_SetMaterial, - (void *)NineDevice9_GetMaterial, - (void *)NineDevice9_SetLight, - (void *)NineDevice9_GetLight, - (void *)NineDevice9_LightEnable, - (void *)NineDevice9_GetLightEnable, - (void *)NineDevice9_SetClipPlane, - (void *)NineDevice9_GetClipPlane, - (void *)NineDevice9_SetRenderState, - (void *)NineDevice9_GetRenderState, - (void *)NineDevice9_CreateStateBlock, - (void *)NineDevice9_BeginStateBlock, - (void *)NineDevice9_EndStateBlock, - (void *)NineDevice9_SetClipStatus, - (void *)NineDevice9_GetClipStatus, - (void *)NineDevice9_GetTexture, - (void *)NineDevice9_SetTexture, - (void *)NineDevice9_GetTextureStageState, - (void *)NineDevice9_SetTextureStageState, - (void *)NineDevice9_GetSamplerState, - (void *)NineDevice9_SetSamplerState, - (void *)NineDevice9_ValidateDevice, - (void *)NineDevice9_SetPaletteEntries, - (void *)NineDevice9_GetPaletteEntries, - (void *)NineDevice9_SetCurrentTexturePalette, - (void *)NineDevice9_GetCurrentTexturePalette, - (void *)NineDevice9_SetScissorRect, - (void *)NineDevice9_GetScissorRect, - (void *)NineDevice9_SetSoftwareVertexProcessing, - (void *)NineDevice9_GetSoftwareVertexProcessing, - (void *)NineDevice9_SetNPatchMode, - (void *)NineDevice9_GetNPatchMode, - (void *)NineDevice9_DrawPrimitive, - (void *)NineDevice9_DrawIndexedPrimitive, - (void *)NineDevice9_DrawPrimitiveUP, - (void *)NineDevice9_DrawIndexedPrimitiveUP, - (void *)NineDevice9_ProcessVertices, - (void *)NineDevice9_CreateVertexDeclaration, - (void *)NineDevice9_SetVertexDeclaration, - (void *)NineDevice9_GetVertexDeclaration, - (void *)NineDevice9_SetFVF, - (void *)NineDevice9_GetFVF, - (void *)NineDevice9_CreateVertexShader, - (void *)NineDevice9_SetVertexShader, - (void *)NineDevice9_GetVertexShader, - (void *)NineDevice9_SetVertexShaderConstantF, - (void *)NineDevice9_GetVertexShaderConstantF, - (void *)NineDevice9_SetVertexShaderConstantI, - (void *)NineDevice9_GetVertexShaderConstantI, - (void *)NineDevice9_SetVertexShaderConstantB, - (void *)NineDevice9_GetVertexShaderConstantB, - (void *)NineDevice9_SetStreamSource, - (void *)NineDevice9_GetStreamSource, - (void *)NineDevice9_SetStreamSourceFreq, - (void *)NineDevice9_GetStreamSourceFreq, - (void *)NineDevice9_SetIndices, - (void *)NineDevice9_GetIndices, - (void *)NineDevice9_CreatePixelShader, - (void *)NineDevice9_SetPixelShader, - (void *)NineDevice9_GetPixelShader, - (void *)NineDevice9_SetPixelShaderConstantF, - (void *)NineDevice9_GetPixelShaderConstantF, - (void *)NineDevice9_SetPixelShaderConstantI, - (void *)NineDevice9_GetPixelShaderConstantI, - (void *)NineDevice9_SetPixelShaderConstantB, - (void *)NineDevice9_GetPixelShaderConstantB, - (void *)NineDevice9_DrawRectPatch, - (void *)NineDevice9_DrawTriPatch, - (void *)NineDevice9_DeletePatch, - (void *)NineDevice9_CreateQuery -}; - -static const GUID *NineDevice9_IIDs[] = { - &IID_IDirect3DDevice9, - &IID_IUnknown, - NULL -}; - -HRESULT -NineDevice9_new( struct pipe_screen *pScreen, - D3DDEVICE_CREATION_PARAMETERS *pCreationParameters, - D3DCAPS9 *pCaps, - D3DPRESENT_PARAMETERS *pPresentationParameters, - IDirect3D9 *pD3D9, - ID3DPresentGroup *pPresentationGroup, - struct d3dadapter9_context *pCTX, - boolean ex, - D3DDISPLAYMODEEX *pFullscreenDisplayMode, - struct NineDevice9 **ppOut, - int minorVersionNum ) -{ - BOOL lock; - lock = !!(pCreationParameters->BehaviorFlags & D3DCREATE_MULTITHREADED); - - NINE_NEW(Device9, ppOut, lock, /* args */ - pScreen, pCreationParameters, pCaps, - pPresentationParameters, pD3D9, pPresentationGroup, pCTX, - ex, pFullscreenDisplayMode, minorVersionNum ); -} diff --git a/src/gallium/state_trackers/nine/device9.h b/src/gallium/state_trackers/nine/device9.h deleted file mode 100644 index f24d79295ad..00000000000 --- a/src/gallium/state_trackers/nine/device9.h +++ /dev/null @@ -1,841 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef _NINE_DEVICE9_H_ -#define _NINE_DEVICE9_H_ - -#include "d3dadapter/d3dadapter9.h" - -#include "iunknown.h" -#include "adapter9.h" - -#include "nine_helpers.h" -#include "nine_state.h" - -struct gen_mipmap_state; -struct hash_table; -struct pipe_screen; -struct pipe_context; -struct cso_context; -struct hud_context; -struct u_upload_mgr; -struct csmt_context; - -struct NineSwapChain9; -struct NineStateBlock9; - -#include "util/list.h" - -struct NineDevice9 -{ - struct NineUnknown base; - boolean ex; - boolean may_swvp; - - /* G3D context */ - struct pipe_screen *screen; - /* For first time upload. No Sync with rendering thread */ - struct pipe_context *pipe_secondary; - struct pipe_screen *screen_sw; - struct pipe_context *pipe_sw; - struct cso_context *cso_sw; - - /* CSMT context */ - struct csmt_context *csmt_ctx; - BOOL csmt_active; - - /* For DISCARD/NOOVERWRITE */ - struct nine_buffer_upload *buffer_upload; - - /* creation parameters */ - D3DCAPS9 caps; - D3DDEVICE_CREATION_PARAMETERS params; - IDirect3D9 *d3d9; - - /* swapchain stuff */ - ID3DPresentGroup *present; - struct NineSwapChain9 **swapchains; - unsigned nswapchains; - - struct NineStateBlock9 *record; - struct nine_state *update; /* state to update (&state / &record->state) */ - struct nine_state state; /* device state */ - struct nine_context context; - struct nine_state_sw_internal state_sw_internal; - - struct list_head update_buffers; - struct list_head update_textures; - struct list_head managed_buffers; - struct list_head managed_textures; - - boolean is_recording; - boolean in_scene; - - uint16_t vs_const_size; - uint16_t ps_const_size; - uint16_t max_vs_const_f; - uint16_t max_ps_const_f; - - struct pipe_resource *dummy_texture; - struct pipe_sampler_view *dummy_sampler_view; - struct pipe_sampler_state dummy_sampler_state; - - struct gen_mipmap_state *gen_mipmap; - - struct { - struct hash_table *ht_vs; - struct hash_table *ht_ps; - struct NineVertexShader9 *vs; - struct NinePixelShader9 *ps; - unsigned num_vs; - unsigned num_ps; - float *vs_const; - float *ps_const; - - struct hash_table *ht_fvf; - } ff; - - struct { - struct pipe_resource *image; - unsigned w; - unsigned h; - POINT hotspot; /* -1, -1 if no cursor image set */ - POINT pos; - BOOL visible; - boolean software; - void *hw_upload_temp; - } cursor; - - struct { - boolean user_vbufs; - boolean user_sw_vbufs; - boolean window_space_position_support; - boolean vs_integer; - boolean ps_integer; - boolean offset_units_unscaled; - } driver_caps; - - struct { - boolean buggy_barycentrics; - } driver_bugs; - - struct { - boolean dynamic_texture_workaround; - } workarounds; - - struct u_upload_mgr *vertex_uploader; - - struct nine_range_pool range_pool; - - struct hud_context *hud; /* NULL if hud is disabled */ - - /* dummy vbo (containing 0 0 0 0) to bind if vertex shader input - * is not bound to anything by the vertex declaration */ - struct pipe_resource *dummy_vbo; - BOOL device_needs_reset; - int minor_version_num; - long long available_texture_mem; - long long available_texture_limit; - - /* software vertex processing */ - boolean swvp; -}; -static inline struct NineDevice9 * -NineDevice9( void *data ) -{ - return (struct NineDevice9 *)data; -} - -HRESULT -NineDevice9_new( struct pipe_screen *pScreen, - D3DDEVICE_CREATION_PARAMETERS *pCreationParameters, - D3DCAPS9 *pCaps, - D3DPRESENT_PARAMETERS *pPresentationParameters, - IDirect3D9 *pD3D9, - ID3DPresentGroup *pPresentationGroup, - struct d3dadapter9_context *pCTX, - boolean ex, - D3DDISPLAYMODEEX *pFullscreenDisplayMode, - struct NineDevice9 **ppOut, - int minorVersionNum ); - -HRESULT -NineDevice9_ctor( struct NineDevice9 *This, - struct NineUnknownParams *pParams, - struct pipe_screen *pScreen, - D3DDEVICE_CREATION_PARAMETERS *pCreationParameters, - D3DCAPS9 *pCaps, - D3DPRESENT_PARAMETERS *pPresentationParameters, - IDirect3D9 *pD3D9, - ID3DPresentGroup *pPresentationGroup, - struct d3dadapter9_context *pCTX, - boolean ex, - D3DDISPLAYMODEEX *pFullscreenDisplayMode, - int minorVersionNum ); - -void -NineDevice9_dtor( struct NineDevice9 *This ); - -/*** Nine private ***/ -void -NineDevice9_SetDefaultState( struct NineDevice9 *This, boolean is_reset ); - -struct pipe_screen * -NineDevice9_GetScreen( struct NineDevice9 *This ); - -struct pipe_context * -NineDevice9_GetPipe( struct NineDevice9 *This ); - -const D3DCAPS9 * -NineDevice9_GetCaps( struct NineDevice9 *This ); - -/*** Direct3D public ***/ - -HRESULT NINE_WINAPI -NineDevice9_TestCooperativeLevel( struct NineDevice9 *This ); - -UINT NINE_WINAPI -NineDevice9_GetAvailableTextureMem( struct NineDevice9 *This ); - -HRESULT NINE_WINAPI -NineDevice9_EvictManagedResources( struct NineDevice9 *This ); - -HRESULT NINE_WINAPI -NineDevice9_GetDirect3D( struct NineDevice9 *This, - IDirect3D9 **ppD3D9 ); - -HRESULT NINE_WINAPI -NineDevice9_GetDeviceCaps( struct NineDevice9 *This, - D3DCAPS9 *pCaps ); - -HRESULT NINE_WINAPI -NineDevice9_GetDisplayMode( struct NineDevice9 *This, - UINT iSwapChain, - D3DDISPLAYMODE *pMode ); - -HRESULT NINE_WINAPI -NineDevice9_GetCreationParameters( struct NineDevice9 *This, - D3DDEVICE_CREATION_PARAMETERS *pParameters ); - -HRESULT NINE_WINAPI -NineDevice9_SetCursorProperties( struct NineDevice9 *This, - UINT XHotSpot, - UINT YHotSpot, - IDirect3DSurface9 *pCursorBitmap ); - -void NINE_WINAPI -NineDevice9_SetCursorPosition( struct NineDevice9 *This, - int X, - int Y, - DWORD Flags ); - -BOOL NINE_WINAPI -NineDevice9_ShowCursor( struct NineDevice9 *This, - BOOL bShow ); - -HRESULT NINE_WINAPI -NineDevice9_CreateAdditionalSwapChain( struct NineDevice9 *This, - D3DPRESENT_PARAMETERS *pPresentationParameters, - IDirect3DSwapChain9 **pSwapChain ); - -HRESULT NINE_WINAPI -NineDevice9_GetSwapChain( struct NineDevice9 *This, - UINT iSwapChain, - IDirect3DSwapChain9 **pSwapChain ); - -UINT NINE_WINAPI -NineDevice9_GetNumberOfSwapChains( struct NineDevice9 *This ); - -HRESULT NINE_WINAPI -NineDevice9_Reset( struct NineDevice9 *This, - D3DPRESENT_PARAMETERS *pPresentationParameters ); - -HRESULT NINE_WINAPI -NineDevice9_Present( struct NineDevice9 *This, - const RECT *pSourceRect, - const RECT *pDestRect, - HWND hDestWindowOverride, - const RGNDATA *pDirtyRegion ); - -HRESULT NINE_WINAPI -NineDevice9_GetBackBuffer( struct NineDevice9 *This, - UINT iSwapChain, - UINT iBackBuffer, - D3DBACKBUFFER_TYPE Type, - IDirect3DSurface9 **ppBackBuffer ); - -HRESULT NINE_WINAPI -NineDevice9_GetRasterStatus( struct NineDevice9 *This, - UINT iSwapChain, - D3DRASTER_STATUS *pRasterStatus ); - -HRESULT NINE_WINAPI -NineDevice9_SetDialogBoxMode( struct NineDevice9 *This, - BOOL bEnableDialogs ); - -void NINE_WINAPI -NineDevice9_SetGammaRamp( struct NineDevice9 *This, - UINT iSwapChain, - DWORD Flags, - const D3DGAMMARAMP *pRamp ); - -void NINE_WINAPI -NineDevice9_GetGammaRamp( struct NineDevice9 *This, - UINT iSwapChain, - D3DGAMMARAMP *pRamp ); - -HRESULT NINE_WINAPI -NineDevice9_CreateTexture( struct NineDevice9 *This, - UINT Width, - UINT Height, - UINT Levels, - DWORD Usage, - D3DFORMAT Format, - D3DPOOL Pool, - IDirect3DTexture9 **ppTexture, - HANDLE *pSharedHandle ); - -HRESULT NINE_WINAPI -NineDevice9_CreateVolumeTexture( struct NineDevice9 *This, - UINT Width, - UINT Height, - UINT Depth, - UINT Levels, - DWORD Usage, - D3DFORMAT Format, - D3DPOOL Pool, - IDirect3DVolumeTexture9 **ppVolumeTexture, - HANDLE *pSharedHandle ); - -HRESULT NINE_WINAPI -NineDevice9_CreateCubeTexture( struct NineDevice9 *This, - UINT EdgeLength, - UINT Levels, - DWORD Usage, - D3DFORMAT Format, - D3DPOOL Pool, - IDirect3DCubeTexture9 **ppCubeTexture, - HANDLE *pSharedHandle ); - -HRESULT NINE_WINAPI -NineDevice9_CreateVertexBuffer( struct NineDevice9 *This, - UINT Length, - DWORD Usage, - DWORD FVF, - D3DPOOL Pool, - IDirect3DVertexBuffer9 **ppVertexBuffer, - HANDLE *pSharedHandle ); - -HRESULT NINE_WINAPI -NineDevice9_CreateIndexBuffer( struct NineDevice9 *This, - UINT Length, - DWORD Usage, - D3DFORMAT Format, - D3DPOOL Pool, - IDirect3DIndexBuffer9 **ppIndexBuffer, - HANDLE *pSharedHandle ); - -HRESULT NINE_WINAPI -NineDevice9_CreateRenderTarget( struct NineDevice9 *This, - UINT Width, - UINT Height, - D3DFORMAT Format, - D3DMULTISAMPLE_TYPE MultiSample, - DWORD MultisampleQuality, - BOOL Lockable, - IDirect3DSurface9 **ppSurface, - HANDLE *pSharedHandle ); - -HRESULT NINE_WINAPI -NineDevice9_CreateDepthStencilSurface( struct NineDevice9 *This, - UINT Width, - UINT Height, - D3DFORMAT Format, - D3DMULTISAMPLE_TYPE MultiSample, - DWORD MultisampleQuality, - BOOL Discard, - IDirect3DSurface9 **ppSurface, - HANDLE *pSharedHandle ); - -HRESULT NINE_WINAPI -NineDevice9_UpdateSurface( struct NineDevice9 *This, - IDirect3DSurface9 *pSourceSurface, - const RECT *pSourceRect, - IDirect3DSurface9 *pDestinationSurface, - const POINT *pDestPoint ); - -HRESULT NINE_WINAPI -NineDevice9_UpdateTexture( struct NineDevice9 *This, - IDirect3DBaseTexture9 *pSourceTexture, - IDirect3DBaseTexture9 *pDestinationTexture ); - -HRESULT NINE_WINAPI -NineDevice9_GetRenderTargetData( struct NineDevice9 *This, - IDirect3DSurface9 *pRenderTarget, - IDirect3DSurface9 *pDestSurface ); - -HRESULT NINE_WINAPI -NineDevice9_GetFrontBufferData( struct NineDevice9 *This, - UINT iSwapChain, - IDirect3DSurface9 *pDestSurface ); - -HRESULT NINE_WINAPI -NineDevice9_StretchRect( struct NineDevice9 *This, - IDirect3DSurface9 *pSourceSurface, - const RECT *pSourceRect, - IDirect3DSurface9 *pDestSurface, - const RECT *pDestRect, - D3DTEXTUREFILTERTYPE Filter ); - -HRESULT NINE_WINAPI -NineDevice9_ColorFill( struct NineDevice9 *This, - IDirect3DSurface9 *pSurface, - const RECT *pRect, - D3DCOLOR color ); - -HRESULT NINE_WINAPI -NineDevice9_CreateOffscreenPlainSurface( struct NineDevice9 *This, - UINT Width, - UINT Height, - D3DFORMAT Format, - D3DPOOL Pool, - IDirect3DSurface9 **ppSurface, - HANDLE *pSharedHandle ); - -HRESULT NINE_WINAPI -NineDevice9_SetRenderTarget( struct NineDevice9 *This, - DWORD RenderTargetIndex, - IDirect3DSurface9 *pRenderTarget ); - -HRESULT NINE_WINAPI -NineDevice9_GetRenderTarget( struct NineDevice9 *This, - DWORD RenderTargetIndex, - IDirect3DSurface9 **ppRenderTarget ); - -HRESULT NINE_WINAPI -NineDevice9_SetDepthStencilSurface( struct NineDevice9 *This, - IDirect3DSurface9 *pNewZStencil ); - -HRESULT NINE_WINAPI -NineDevice9_GetDepthStencilSurface( struct NineDevice9 *This, - IDirect3DSurface9 **ppZStencilSurface ); - -HRESULT NINE_WINAPI -NineDevice9_BeginScene( struct NineDevice9 *This ); - -HRESULT NINE_WINAPI -NineDevice9_EndScene( struct NineDevice9 *This ); - -HRESULT NINE_WINAPI -NineDevice9_Clear( struct NineDevice9 *This, - DWORD Count, - const D3DRECT *pRects, - DWORD Flags, - D3DCOLOR Color, - float Z, - DWORD Stencil ); - -HRESULT NINE_WINAPI -NineDevice9_SetTransform( struct NineDevice9 *This, - D3DTRANSFORMSTATETYPE State, - const D3DMATRIX *pMatrix ); - -HRESULT NINE_WINAPI -NineDevice9_GetTransform( struct NineDevice9 *This, - D3DTRANSFORMSTATETYPE State, - D3DMATRIX *pMatrix ); - -HRESULT NINE_WINAPI -NineDevice9_MultiplyTransform( struct NineDevice9 *This, - D3DTRANSFORMSTATETYPE State, - const D3DMATRIX *pMatrix ); - -HRESULT NINE_WINAPI -NineDevice9_SetViewport( struct NineDevice9 *This, - const D3DVIEWPORT9 *pViewport ); - -HRESULT NINE_WINAPI -NineDevice9_GetViewport( struct NineDevice9 *This, - D3DVIEWPORT9 *pViewport ); - -HRESULT NINE_WINAPI -NineDevice9_SetMaterial( struct NineDevice9 *This, - const D3DMATERIAL9 *pMaterial ); - -HRESULT NINE_WINAPI -NineDevice9_GetMaterial( struct NineDevice9 *This, - D3DMATERIAL9 *pMaterial ); - -HRESULT NINE_WINAPI -NineDevice9_SetLight( struct NineDevice9 *This, - DWORD Index, - const D3DLIGHT9 *pLight ); - -HRESULT NINE_WINAPI -NineDevice9_GetLight( struct NineDevice9 *This, - DWORD Index, - D3DLIGHT9 *pLight ); - -HRESULT NINE_WINAPI -NineDevice9_LightEnable( struct NineDevice9 *This, - DWORD Index, - BOOL Enable ); - -HRESULT NINE_WINAPI -NineDevice9_GetLightEnable( struct NineDevice9 *This, - DWORD Index, - BOOL *pEnable ); - -HRESULT NINE_WINAPI -NineDevice9_SetClipPlane( struct NineDevice9 *This, - DWORD Index, - const float *pPlane ); - -HRESULT NINE_WINAPI -NineDevice9_GetClipPlane( struct NineDevice9 *This, - DWORD Index, - float *pPlane ); - -HRESULT NINE_WINAPI -NineDevice9_SetRenderState( struct NineDevice9 *This, - D3DRENDERSTATETYPE State, - DWORD Value ); - -HRESULT NINE_WINAPI -NineDevice9_GetRenderState( struct NineDevice9 *This, - D3DRENDERSTATETYPE State, - DWORD *pValue ); - -HRESULT NINE_WINAPI -NineDevice9_CreateStateBlock( struct NineDevice9 *This, - D3DSTATEBLOCKTYPE Type, - IDirect3DStateBlock9 **ppSB ); - -HRESULT NINE_WINAPI -NineDevice9_BeginStateBlock( struct NineDevice9 *This ); - -HRESULT NINE_WINAPI -NineDevice9_EndStateBlock( struct NineDevice9 *This, - IDirect3DStateBlock9 **ppSB ); - -HRESULT NINE_WINAPI -NineDevice9_SetClipStatus( struct NineDevice9 *This, - const D3DCLIPSTATUS9 *pClipStatus ); - -HRESULT NINE_WINAPI -NineDevice9_GetClipStatus( struct NineDevice9 *This, - D3DCLIPSTATUS9 *pClipStatus ); - -HRESULT NINE_WINAPI -NineDevice9_GetTexture( struct NineDevice9 *This, - DWORD Stage, - IDirect3DBaseTexture9 **ppTexture ); - -HRESULT NINE_WINAPI -NineDevice9_SetTexture( struct NineDevice9 *This, - DWORD Stage, - IDirect3DBaseTexture9 *pTexture ); - -HRESULT NINE_WINAPI -NineDevice9_GetTextureStageState( struct NineDevice9 *This, - DWORD Stage, - D3DTEXTURESTAGESTATETYPE Type, - DWORD *pValue ); - -HRESULT NINE_WINAPI -NineDevice9_SetTextureStageState( struct NineDevice9 *This, - DWORD Stage, - D3DTEXTURESTAGESTATETYPE Type, - DWORD Value ); - -HRESULT NINE_WINAPI -NineDevice9_GetSamplerState( struct NineDevice9 *This, - DWORD Sampler, - D3DSAMPLERSTATETYPE Type, - DWORD *pValue ); - -HRESULT NINE_WINAPI -NineDevice9_SetSamplerState( struct NineDevice9 *This, - DWORD Sampler, - D3DSAMPLERSTATETYPE Type, - DWORD Value ); - -HRESULT NINE_WINAPI -NineDevice9_ValidateDevice( struct NineDevice9 *This, - DWORD *pNumPasses ); - -HRESULT NINE_WINAPI -NineDevice9_SetPaletteEntries( struct NineDevice9 *This, - UINT PaletteNumber, - const PALETTEENTRY *pEntries ); - -HRESULT NINE_WINAPI -NineDevice9_GetPaletteEntries( struct NineDevice9 *This, - UINT PaletteNumber, - PALETTEENTRY *pEntries ); - -HRESULT NINE_WINAPI -NineDevice9_SetCurrentTexturePalette( struct NineDevice9 *This, - UINT PaletteNumber ); - -HRESULT NINE_WINAPI -NineDevice9_GetCurrentTexturePalette( struct NineDevice9 *This, - UINT *PaletteNumber ); - -HRESULT NINE_WINAPI -NineDevice9_SetScissorRect( struct NineDevice9 *This, - const RECT *pRect ); - -HRESULT NINE_WINAPI -NineDevice9_GetScissorRect( struct NineDevice9 *This, - RECT *pRect ); - -HRESULT NINE_WINAPI -NineDevice9_SetSoftwareVertexProcessing( struct NineDevice9 *This, - BOOL bSoftware ); - -BOOL NINE_WINAPI -NineDevice9_GetSoftwareVertexProcessing( struct NineDevice9 *This ); - -HRESULT NINE_WINAPI -NineDevice9_SetNPatchMode( struct NineDevice9 *This, - float nSegments ); - -float NINE_WINAPI -NineDevice9_GetNPatchMode( struct NineDevice9 *This ); - -HRESULT NINE_WINAPI -NineDevice9_DrawPrimitive( struct NineDevice9 *This, - D3DPRIMITIVETYPE PrimitiveType, - UINT StartVertex, - UINT PrimitiveCount ); - -HRESULT NINE_WINAPI -NineDevice9_DrawIndexedPrimitive( struct NineDevice9 *This, - D3DPRIMITIVETYPE PrimitiveType, - INT BaseVertexIndex, - UINT MinVertexIndex, - UINT NumVertices, - UINT startIndex, - UINT primCount ); - -HRESULT NINE_WINAPI -NineDevice9_DrawPrimitiveUP( struct NineDevice9 *This, - D3DPRIMITIVETYPE PrimitiveType, - UINT PrimitiveCount, - const void *pVertexStreamZeroData, - UINT VertexStreamZeroStride ); - -HRESULT NINE_WINAPI -NineDevice9_DrawIndexedPrimitiveUP( struct NineDevice9 *This, - D3DPRIMITIVETYPE PrimitiveType, - UINT MinVertexIndex, - UINT NumVertices, - UINT PrimitiveCount, - const void *pIndexData, - D3DFORMAT IndexDataFormat, - const void *pVertexStreamZeroData, - UINT VertexStreamZeroStride ); - -HRESULT NINE_WINAPI -NineDevice9_ProcessVertices( struct NineDevice9 *This, - UINT SrcStartIndex, - UINT DestIndex, - UINT VertexCount, - IDirect3DVertexBuffer9 *pDestBuffer, - IDirect3DVertexDeclaration9 *pVertexDecl, - DWORD Flags ); - -HRESULT NINE_WINAPI -NineDevice9_CreateVertexDeclaration( struct NineDevice9 *This, - const D3DVERTEXELEMENT9 *pVertexElements, - IDirect3DVertexDeclaration9 **ppDecl ); - -HRESULT NINE_WINAPI -NineDevice9_SetVertexDeclaration( struct NineDevice9 *This, - IDirect3DVertexDeclaration9 *pDecl ); - -HRESULT NINE_WINAPI -NineDevice9_GetVertexDeclaration( struct NineDevice9 *This, - IDirect3DVertexDeclaration9 **ppDecl ); - -HRESULT NINE_WINAPI -NineDevice9_SetFVF( struct NineDevice9 *This, - DWORD FVF ); - -HRESULT NINE_WINAPI -NineDevice9_GetFVF( struct NineDevice9 *This, - DWORD *pFVF ); - -HRESULT NINE_WINAPI -NineDevice9_CreateVertexShader( struct NineDevice9 *This, - const DWORD *pFunction, - IDirect3DVertexShader9 **ppShader ); - -HRESULT NINE_WINAPI -NineDevice9_SetVertexShader( struct NineDevice9 *This, - IDirect3DVertexShader9 *pShader ); - -HRESULT NINE_WINAPI -NineDevice9_GetVertexShader( struct NineDevice9 *This, - IDirect3DVertexShader9 **ppShader ); - -HRESULT NINE_WINAPI -NineDevice9_SetVertexShaderConstantF( struct NineDevice9 *This, - UINT StartRegister, - const float *pConstantData, - UINT Vector4fCount ); - -HRESULT NINE_WINAPI -NineDevice9_GetVertexShaderConstantF( struct NineDevice9 *This, - UINT StartRegister, - float *pConstantData, - UINT Vector4fCount ); - -HRESULT NINE_WINAPI -NineDevice9_SetVertexShaderConstantI( struct NineDevice9 *This, - UINT StartRegister, - const int *pConstantData, - UINT Vector4iCount ); - -HRESULT NINE_WINAPI -NineDevice9_GetVertexShaderConstantI( struct NineDevice9 *This, - UINT StartRegister, - int *pConstantData, - UINT Vector4iCount ); - -HRESULT NINE_WINAPI -NineDevice9_SetVertexShaderConstantB( struct NineDevice9 *This, - UINT StartRegister, - const BOOL *pConstantData, - UINT BoolCount ); - -HRESULT NINE_WINAPI -NineDevice9_GetVertexShaderConstantB( struct NineDevice9 *This, - UINT StartRegister, - BOOL *pConstantData, - UINT BoolCount ); - -HRESULT NINE_WINAPI -NineDevice9_SetStreamSource( struct NineDevice9 *This, - UINT StreamNumber, - IDirect3DVertexBuffer9 *pStreamData, - UINT OffsetInBytes, - UINT Stride ); - -HRESULT NINE_WINAPI -NineDevice9_GetStreamSource( struct NineDevice9 *This, - UINT StreamNumber, - IDirect3DVertexBuffer9 **ppStreamData, - UINT *pOffsetInBytes, - UINT *pStride ); - -HRESULT NINE_WINAPI -NineDevice9_SetStreamSourceFreq( struct NineDevice9 *This, - UINT StreamNumber, - UINT Setting ); - -HRESULT NINE_WINAPI -NineDevice9_GetStreamSourceFreq( struct NineDevice9 *This, - UINT StreamNumber, - UINT *pSetting ); - -HRESULT NINE_WINAPI -NineDevice9_SetIndices( struct NineDevice9 *This, - IDirect3DIndexBuffer9 *pIndexData ); - -HRESULT NINE_WINAPI -NineDevice9_GetIndices( struct NineDevice9 *This, - IDirect3DIndexBuffer9 **ppIndexData /*, - UINT *pBaseVertexIndex */ ); - -HRESULT NINE_WINAPI -NineDevice9_CreatePixelShader( struct NineDevice9 *This, - const DWORD *pFunction, - IDirect3DPixelShader9 **ppShader ); - -HRESULT NINE_WINAPI -NineDevice9_SetPixelShader( struct NineDevice9 *This, - IDirect3DPixelShader9 *pShader ); - -HRESULT NINE_WINAPI -NineDevice9_GetPixelShader( struct NineDevice9 *This, - IDirect3DPixelShader9 **ppShader ); - -HRESULT NINE_WINAPI -NineDevice9_SetPixelShaderConstantF( struct NineDevice9 *This, - UINT StartRegister, - const float *pConstantData, - UINT Vector4fCount ); - -HRESULT NINE_WINAPI -NineDevice9_GetPixelShaderConstantF( struct NineDevice9 *This, - UINT StartRegister, - float *pConstantData, - UINT Vector4fCount ); - -HRESULT NINE_WINAPI -NineDevice9_SetPixelShaderConstantI( struct NineDevice9 *This, - UINT StartRegister, - const int *pConstantData, - UINT Vector4iCount ); - -HRESULT NINE_WINAPI -NineDevice9_GetPixelShaderConstantI( struct NineDevice9 *This, - UINT StartRegister, - int *pConstantData, - UINT Vector4iCount ); - -HRESULT NINE_WINAPI -NineDevice9_SetPixelShaderConstantB( struct NineDevice9 *This, - UINT StartRegister, - const BOOL *pConstantData, - UINT BoolCount ); - -HRESULT NINE_WINAPI -NineDevice9_GetPixelShaderConstantB( struct NineDevice9 *This, - UINT StartRegister, - BOOL *pConstantData, - UINT BoolCount ); - -HRESULT NINE_WINAPI -NineDevice9_DrawRectPatch( struct NineDevice9 *This, - UINT Handle, - const float *pNumSegs, - const D3DRECTPATCH_INFO *pRectPatchInfo ); - -HRESULT NINE_WINAPI -NineDevice9_DrawTriPatch( struct NineDevice9 *This, - UINT Handle, - const float *pNumSegs, - const D3DTRIPATCH_INFO *pTriPatchInfo ); - -HRESULT NINE_WINAPI -NineDevice9_DeletePatch( struct NineDevice9 *This, - UINT Handle ); - -HRESULT NINE_WINAPI -NineDevice9_CreateQuery( struct NineDevice9 *This, - D3DQUERYTYPE Type, - IDirect3DQuery9 **ppQuery ); - -#endif /* _NINE_DEVICE9_H_ */ diff --git a/src/gallium/state_trackers/nine/device9ex.c b/src/gallium/state_trackers/nine/device9ex.c deleted file mode 100644 index 3047657e95f..00000000000 --- a/src/gallium/state_trackers/nine/device9ex.c +++ /dev/null @@ -1,458 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "device9.h" -#include "device9ex.h" -#include "nine_pipe.h" -#include "swapchain9ex.h" - -#include "nine_helpers.h" - -#define DBG_CHANNEL DBG_DEVICE - -static HRESULT -NineDevice9Ex_ctor( struct NineDevice9Ex *This, - struct NineUnknownParams *pParams, - struct pipe_screen *pScreen, - D3DDEVICE_CREATION_PARAMETERS *pCreationParameters, - D3DCAPS9 *pCaps, - D3DPRESENT_PARAMETERS *pPresentationParameters, - D3DDISPLAYMODEEX *pFullscreenDisplayMode, - IDirect3D9Ex *pD3D9Ex, - ID3DPresentGroup *pPresentationGroup, - struct d3dadapter9_context *pCTX, - int minorVersionNum ) -{ - DBG("This=%p pParams=%p pScreen=%p pCreationParameters=%p pCaps=%p " - "pPresentationParameters=%p pFullscreenDisplayMode=%p " - "pD3D9Ex=%p pPresentationGroup=%p pCTX=%p\n", - This, pParams, pScreen, pCreationParameters, pCaps, - pPresentationParameters, pFullscreenDisplayMode, - pD3D9Ex, pPresentationGroup, pCTX); - - return NineDevice9_ctor(&This->base, pParams, - pScreen, pCreationParameters, pCaps, - pPresentationParameters, - (IDirect3D9 *)pD3D9Ex, pPresentationGroup, pCTX, - TRUE, pFullscreenDisplayMode, minorVersionNum); -} - -static void -NineDevice9Ex_dtor( struct NineDevice9Ex *This ) -{ - NineDevice9_dtor(&This->base); -} - -HRESULT NINE_WINAPI -NineDevice9Ex_SetConvolutionMonoKernel( struct NineDevice9Ex *This, - UINT width, - UINT height, - float *rows, - float *columns ) -{ - STUB(D3DERR_INVALIDCALL); -} - -HRESULT NINE_WINAPI -NineDevice9Ex_ComposeRects( struct NineDevice9Ex *This, - IDirect3DSurface9 *pSrc, - IDirect3DSurface9 *pDst, - IDirect3DVertexBuffer9 *pSrcRectDescs, - UINT NumRects, - IDirect3DVertexBuffer9 *pDstRectDescs, - D3DCOMPOSERECTSOP Operation, - int Xoffset, - int Yoffset ) -{ - STUB(D3DERR_INVALIDCALL); -} - -HRESULT NINE_WINAPI -NineDevice9Ex_PresentEx( struct NineDevice9Ex *This, - const RECT *pSourceRect, - const RECT *pDestRect, - HWND hDestWindowOverride, - const RGNDATA *pDirtyRegion, - DWORD dwFlags ) -{ - unsigned i; - HRESULT hr; - - DBG("This=%p pSourceRect=%p pDestRect=%p hDestWindowOverride=%p " - "pDirtyRegion=%p dwFlags=%d\n", - This, pSourceRect, pDestRect, hDestWindowOverride, - pDirtyRegion, dwFlags); - - for (i = 0; i < This->base.nswapchains; i++) { - hr = NineSwapChain9_Present(This->base.swapchains[i], pSourceRect, pDestRect, - hDestWindowOverride, pDirtyRegion, dwFlags); - if (FAILED(hr)) { return hr; } - } - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9Ex_GetGPUThreadPriority( struct NineDevice9Ex *This, - INT *pPriority ) -{ - STUB(D3DERR_INVALIDCALL); -} - -HRESULT NINE_WINAPI -NineDevice9Ex_SetGPUThreadPriority( struct NineDevice9Ex *This, - INT Priority ) -{ - STUB(D3DERR_INVALIDCALL); -} - -HRESULT NINE_WINAPI -NineDevice9Ex_WaitForVBlank( struct NineDevice9Ex *This, - UINT iSwapChain ) -{ - STUB(D3DERR_INVALIDCALL); -} - -HRESULT NINE_WINAPI -NineDevice9Ex_CheckResourceResidency( struct NineDevice9Ex *This, - IDirect3DResource9 **pResourceArray, - UINT32 NumResources ) -{ - STUB(D3DERR_INVALIDCALL); -} - -HRESULT NINE_WINAPI -NineDevice9Ex_SetMaximumFrameLatency( struct NineDevice9Ex *This, - UINT MaxLatency ) -{ - STUB(D3DERR_INVALIDCALL); -} - -HRESULT NINE_WINAPI -NineDevice9Ex_GetMaximumFrameLatency( struct NineDevice9Ex *This, - UINT *pMaxLatency ) -{ - STUB(D3DERR_INVALIDCALL); -} - -HRESULT NINE_WINAPI -NineDevice9Ex_CheckDeviceState( struct NineDevice9Ex *This, - HWND hDestinationWindow ) -{ - DBG("This=%p hDestinationWindow=%p\n", - This, hDestinationWindow); - - user_assert(!This->base.swapchains[0]->params.Windowed, D3D_OK); - - if (This->base.params.hFocusWindow == hDestinationWindow) { - if (NineSwapChain9_GetOccluded(This->base.swapchains[0])) - return S_PRESENT_OCCLUDED; - } else if(!NineSwapChain9_GetOccluded(This->base.swapchains[0])) { - return S_PRESENT_OCCLUDED; - } - /* TODO: handle the other return values */ - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineDevice9Ex_CreateRenderTargetEx( struct NineDevice9Ex *This, - UINT Width, - UINT Height, - D3DFORMAT Format, - D3DMULTISAMPLE_TYPE MultiSample, - DWORD MultisampleQuality, - BOOL Lockable, - IDirect3DSurface9 **ppSurface, - HANDLE *pSharedHandle, - DWORD Usage ) -{ - STUB(D3DERR_INVALIDCALL); -} - -HRESULT NINE_WINAPI -NineDevice9Ex_CreateOffscreenPlainSurfaceEx( struct NineDevice9Ex *This, - UINT Width, - UINT Height, - D3DFORMAT Format, - D3DPOOL Pool, - IDirect3DSurface9 **ppSurface, - HANDLE *pSharedHandle, - DWORD Usage ) -{ - STUB(D3DERR_INVALIDCALL); -} - -HRESULT NINE_WINAPI -NineDevice9Ex_CreateDepthStencilSurfaceEx( struct NineDevice9Ex *This, - UINT Width, - UINT Height, - D3DFORMAT Format, - D3DMULTISAMPLE_TYPE MultiSample, - DWORD MultisampleQuality, - BOOL Discard, - IDirect3DSurface9 **ppSurface, - HANDLE *pSharedHandle, - DWORD Usage ) -{ - STUB(D3DERR_INVALIDCALL); -} - -HRESULT NINE_WINAPI -NineDevice9Ex_ResetEx( struct NineDevice9Ex *This, - D3DPRESENT_PARAMETERS *pPresentationParameters, - D3DDISPLAYMODEEX *pFullscreenDisplayMode ) -{ - HRESULT hr = D3D_OK; - unsigned i; - - DBG("This=%p pPresentationParameters=%p pFullscreenDisplayMode=%p\n", This, pPresentationParameters, pFullscreenDisplayMode); - - for (i = 0; i < This->base.nswapchains; ++i) { - D3DDISPLAYMODEEX *mode = NULL; - D3DPRESENT_PARAMETERS *params = &pPresentationParameters[i]; - if (pFullscreenDisplayMode) mode = &(pFullscreenDisplayMode[i]); - hr = NineSwapChain9_Resize(This->base.swapchains[i], params, mode); - if (FAILED(hr)) - break; - } - - NineDevice9_SetRenderTarget( - (struct NineDevice9 *)This, 0, (IDirect3DSurface9 *)This->base.swapchains[0]->buffers[0]); - - return hr; -} - -HRESULT NINE_WINAPI -NineDevice9Ex_Reset( struct NineDevice9Ex *This, - D3DPRESENT_PARAMETERS *pPresentationParameters ) -{ - HRESULT hr = D3D_OK; - unsigned i; - - DBG("This=%p pPresentationParameters=%p\n", This, pPresentationParameters); - - for (i = 0; i < This->base.nswapchains; ++i) { - D3DPRESENT_PARAMETERS *params = &pPresentationParameters[i]; - hr = NineSwapChain9_Resize(This->base.swapchains[i], params, NULL); - if (FAILED(hr)) - break; - } - - nine_csmt_process(&This->base); - nine_device_state_clear((struct NineDevice9 *)This); - nine_context_clear(&This->base); - - NineDevice9_SetDefaultState((struct NineDevice9 *)This, TRUE); - NineDevice9_SetRenderTarget( - (struct NineDevice9 *)This, 0, (IDirect3DSurface9 *)This->base.swapchains[0]->buffers[0]); - - return hr; -} - -HRESULT NINE_WINAPI -NineDevice9Ex_GetDisplayModeEx( struct NineDevice9Ex *This, - UINT iSwapChain, - D3DDISPLAYMODEEX *pMode, - D3DDISPLAYROTATION *pRotation ) -{ - struct NineSwapChain9Ex *swapchain; - - DBG("This=%p iSwapChain=%u pMode=%p pRotation=%p\n", - This, iSwapChain, pMode, pRotation); - - user_assert(iSwapChain < This->base.nswapchains, D3DERR_INVALIDCALL); - - swapchain = NineSwapChain9Ex(This->base.swapchains[iSwapChain]); - return NineSwapChain9Ex_GetDisplayModeEx(swapchain, pMode, pRotation); -} - -HRESULT NINE_WINAPI -NineDevice9Ex_TestCooperativeLevel( struct NineDevice9Ex *This ) -{ - return D3D_OK; -} - - -IDirect3DDevice9ExVtbl NineDevice9Ex_vtable = { - (void *)NineUnknown_QueryInterface, - (void *)NineUnknown_AddRef, - (void *)NineUnknown_Release, - (void *)NineDevice9Ex_TestCooperativeLevel, - (void *)NineDevice9_GetAvailableTextureMem, - (void *)NineDevice9_EvictManagedResources, - (void *)NineDevice9_GetDirect3D, - (void *)NineDevice9_GetDeviceCaps, - (void *)NineDevice9_GetDisplayMode, - (void *)NineDevice9_GetCreationParameters, - (void *)NineDevice9_SetCursorProperties, - (void *)NineDevice9_SetCursorPosition, - (void *)NineDevice9_ShowCursor, - (void *)NineDevice9_CreateAdditionalSwapChain, - (void *)NineDevice9_GetSwapChain, - (void *)NineDevice9_GetNumberOfSwapChains, - (void *)NineDevice9Ex_Reset, - (void *)NineDevice9_Present, - (void *)NineDevice9_GetBackBuffer, - (void *)NineDevice9_GetRasterStatus, - (void *)NineDevice9_SetDialogBoxMode, - (void *)NineDevice9_SetGammaRamp, - (void *)NineDevice9_GetGammaRamp, - (void *)NineDevice9_CreateTexture, - (void *)NineDevice9_CreateVolumeTexture, - (void *)NineDevice9_CreateCubeTexture, - (void *)NineDevice9_CreateVertexBuffer, - (void *)NineDevice9_CreateIndexBuffer, - (void *)NineDevice9_CreateRenderTarget, - (void *)NineDevice9_CreateDepthStencilSurface, - (void *)NineDevice9_UpdateSurface, - (void *)NineDevice9_UpdateTexture, - (void *)NineDevice9_GetRenderTargetData, - (void *)NineDevice9_GetFrontBufferData, - (void *)NineDevice9_StretchRect, - (void *)NineDevice9_ColorFill, - (void *)NineDevice9_CreateOffscreenPlainSurface, - (void *)NineDevice9_SetRenderTarget, - (void *)NineDevice9_GetRenderTarget, - (void *)NineDevice9_SetDepthStencilSurface, - (void *)NineDevice9_GetDepthStencilSurface, - (void *)NineDevice9_BeginScene, - (void *)NineDevice9_EndScene, - (void *)NineDevice9_Clear, - (void *)NineDevice9_SetTransform, - (void *)NineDevice9_GetTransform, - (void *)NineDevice9_MultiplyTransform, - (void *)NineDevice9_SetViewport, - (void *)NineDevice9_GetViewport, - (void *)NineDevice9_SetMaterial, - (void *)NineDevice9_GetMaterial, - (void *)NineDevice9_SetLight, - (void *)NineDevice9_GetLight, - (void *)NineDevice9_LightEnable, - (void *)NineDevice9_GetLightEnable, - (void *)NineDevice9_SetClipPlane, - (void *)NineDevice9_GetClipPlane, - (void *)NineDevice9_SetRenderState, - (void *)NineDevice9_GetRenderState, - (void *)NineDevice9_CreateStateBlock, - (void *)NineDevice9_BeginStateBlock, - (void *)NineDevice9_EndStateBlock, - (void *)NineDevice9_SetClipStatus, - (void *)NineDevice9_GetClipStatus, - (void *)NineDevice9_GetTexture, - (void *)NineDevice9_SetTexture, - (void *)NineDevice9_GetTextureStageState, - (void *)NineDevice9_SetTextureStageState, - (void *)NineDevice9_GetSamplerState, - (void *)NineDevice9_SetSamplerState, - (void *)NineDevice9_ValidateDevice, - (void *)NineDevice9_SetPaletteEntries, - (void *)NineDevice9_GetPaletteEntries, - (void *)NineDevice9_SetCurrentTexturePalette, - (void *)NineDevice9_GetCurrentTexturePalette, - (void *)NineDevice9_SetScissorRect, - (void *)NineDevice9_GetScissorRect, - (void *)NineDevice9_SetSoftwareVertexProcessing, - (void *)NineDevice9_GetSoftwareVertexProcessing, - (void *)NineDevice9_SetNPatchMode, - (void *)NineDevice9_GetNPatchMode, - (void *)NineDevice9_DrawPrimitive, - (void *)NineDevice9_DrawIndexedPrimitive, - (void *)NineDevice9_DrawPrimitiveUP, - (void *)NineDevice9_DrawIndexedPrimitiveUP, - (void *)NineDevice9_ProcessVertices, - (void *)NineDevice9_CreateVertexDeclaration, - (void *)NineDevice9_SetVertexDeclaration, - (void *)NineDevice9_GetVertexDeclaration, - (void *)NineDevice9_SetFVF, - (void *)NineDevice9_GetFVF, - (void *)NineDevice9_CreateVertexShader, - (void *)NineDevice9_SetVertexShader, - (void *)NineDevice9_GetVertexShader, - (void *)NineDevice9_SetVertexShaderConstantF, - (void *)NineDevice9_GetVertexShaderConstantF, - (void *)NineDevice9_SetVertexShaderConstantI, - (void *)NineDevice9_GetVertexShaderConstantI, - (void *)NineDevice9_SetVertexShaderConstantB, - (void *)NineDevice9_GetVertexShaderConstantB, - (void *)NineDevice9_SetStreamSource, - (void *)NineDevice9_GetStreamSource, - (void *)NineDevice9_SetStreamSourceFreq, - (void *)NineDevice9_GetStreamSourceFreq, - (void *)NineDevice9_SetIndices, - (void *)NineDevice9_GetIndices, - (void *)NineDevice9_CreatePixelShader, - (void *)NineDevice9_SetPixelShader, - (void *)NineDevice9_GetPixelShader, - (void *)NineDevice9_SetPixelShaderConstantF, - (void *)NineDevice9_GetPixelShaderConstantF, - (void *)NineDevice9_SetPixelShaderConstantI, - (void *)NineDevice9_GetPixelShaderConstantI, - (void *)NineDevice9_SetPixelShaderConstantB, - (void *)NineDevice9_GetPixelShaderConstantB, - (void *)NineDevice9_DrawRectPatch, - (void *)NineDevice9_DrawTriPatch, - (void *)NineDevice9_DeletePatch, - (void *)NineDevice9_CreateQuery, - (void *)NineDevice9Ex_SetConvolutionMonoKernel, - (void *)NineDevice9Ex_ComposeRects, - (void *)NineDevice9Ex_PresentEx, - (void *)NineDevice9Ex_GetGPUThreadPriority, - (void *)NineDevice9Ex_SetGPUThreadPriority, - (void *)NineDevice9Ex_WaitForVBlank, - (void *)NineDevice9Ex_CheckResourceResidency, - (void *)NineDevice9Ex_SetMaximumFrameLatency, - (void *)NineDevice9Ex_GetMaximumFrameLatency, - (void *)NineDevice9Ex_CheckDeviceState, - (void *)NineDevice9Ex_CreateRenderTargetEx, - (void *)NineDevice9Ex_CreateOffscreenPlainSurfaceEx, - (void *)NineDevice9Ex_CreateDepthStencilSurfaceEx, - (void *)NineDevice9Ex_ResetEx, - (void *)NineDevice9Ex_GetDisplayModeEx -}; - -static const GUID *NineDevice9Ex_IIDs[] = { - &IID_IDirect3DDevice9Ex, - &IID_IDirect3DDevice9, - &IID_IUnknown, - NULL -}; - -HRESULT -NineDevice9Ex_new( struct pipe_screen *pScreen, - D3DDEVICE_CREATION_PARAMETERS *pCreationParameters, - D3DCAPS9 *pCaps, - D3DPRESENT_PARAMETERS *pPresentationParameters, - D3DDISPLAYMODEEX *pFullscreenDisplayMode, - IDirect3D9Ex *pD3D9Ex, - ID3DPresentGroup *pPresentationGroup, - struct d3dadapter9_context *pCTX, - struct NineDevice9Ex **ppOut, - int minorVersionNum ) -{ - BOOL lock; - lock = !!(pCreationParameters->BehaviorFlags & D3DCREATE_MULTITHREADED); - - NINE_NEW(Device9Ex, ppOut, lock, - pScreen, pCreationParameters, pCaps, pPresentationParameters, - pFullscreenDisplayMode, pD3D9Ex, pPresentationGroup, pCTX, minorVersionNum ); -} - diff --git a/src/gallium/state_trackers/nine/device9ex.h b/src/gallium/state_trackers/nine/device9ex.h deleted file mode 100644 index 3306f238b59..00000000000 --- a/src/gallium/state_trackers/nine/device9ex.h +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef _NINE_DEVICE9EX_H_ -#define _NINE_DEVICE9EX_H_ - -#include "device9.h" - -struct NineDevice9Ex -{ - struct NineDevice9 base; -}; -static inline struct NineDevice9Ex * -NineDevice9Ex( void *data ) -{ - return (struct NineDevice9Ex *)data; -} - -HRESULT -NineDevice9Ex_new( struct pipe_screen *pScreen, - D3DDEVICE_CREATION_PARAMETERS *pCreationParameters, - D3DCAPS9 *pCaps, - D3DPRESENT_PARAMETERS *pPresentationParameters, - D3DDISPLAYMODEEX *pFullscreenDisplayMode, - IDirect3D9Ex *pD3D9Ex, - ID3DPresentGroup *pPresentationGroup, - struct d3dadapter9_context *pCTX, - struct NineDevice9Ex **ppOut, - int minorVersionNum ); - -HRESULT NINE_WINAPI -NineDevice9Ex_SetConvolutionMonoKernel( struct NineDevice9Ex *This, - UINT width, - UINT height, - float *rows, - float *columns ); - -HRESULT NINE_WINAPI -NineDevice9Ex_ComposeRects( struct NineDevice9Ex *This, - IDirect3DSurface9 *pSrc, - IDirect3DSurface9 *pDst, - IDirect3DVertexBuffer9 *pSrcRectDescs, - UINT NumRects, - IDirect3DVertexBuffer9 *pDstRectDescs, - D3DCOMPOSERECTSOP Operation, - int Xoffset, - int Yoffset ); - -HRESULT NINE_WINAPI -NineDevice9Ex_PresentEx( struct NineDevice9Ex *This, - const RECT *pSourceRect, - const RECT *pDestRect, - HWND hDestWindowOverride, - const RGNDATA *pDirtyRegion, - DWORD dwFlags ); - -HRESULT NINE_WINAPI -NineDevice9Ex_Present( struct NineDevice9Ex *This, - const RECT *pSourceRect, - const RECT *pDestRect, - HWND hDestWindowOverride, - const RGNDATA *pDirtyRegion ); - -HRESULT NINE_WINAPI -NineDevice9Ex_GetGPUThreadPriority( struct NineDevice9Ex *This, - INT *pPriority ); - -HRESULT NINE_WINAPI -NineDevice9Ex_SetGPUThreadPriority( struct NineDevice9Ex *This, - INT Priority ); - -HRESULT NINE_WINAPI -NineDevice9Ex_WaitForVBlank( struct NineDevice9Ex *This, - UINT iSwapChain ); - -HRESULT NINE_WINAPI -NineDevice9Ex_CheckResourceResidency( struct NineDevice9Ex *This, - IDirect3DResource9 **pResourceArray, - UINT32 NumResources ); - -HRESULT NINE_WINAPI -NineDevice9Ex_SetMaximumFrameLatency( struct NineDevice9Ex *This, - UINT MaxLatency ); - -HRESULT NINE_WINAPI -NineDevice9Ex_GetMaximumFrameLatency( struct NineDevice9Ex *This, - UINT *pMaxLatency ); - -HRESULT NINE_WINAPI -NineDevice9Ex_CheckDeviceState( struct NineDevice9Ex *This, - HWND hDestinationWindow ); - -HRESULT NINE_WINAPI -NineDevice9Ex_CreateRenderTargetEx( struct NineDevice9Ex *This, - UINT Width, - UINT Height, - D3DFORMAT Format, - D3DMULTISAMPLE_TYPE MultiSample, - DWORD MultisampleQuality, - BOOL Lockable, - IDirect3DSurface9 **ppSurface, - HANDLE *pSharedHandle, - DWORD Usage ); - -HRESULT NINE_WINAPI -NineDevice9Ex_CreateOffscreenPlainSurfaceEx( struct NineDevice9Ex *This, - UINT Width, - UINT Height, - D3DFORMAT Format, - D3DPOOL Pool, - IDirect3DSurface9 **ppSurface, - HANDLE *pSharedHandle, - DWORD Usage ); - -HRESULT NINE_WINAPI -NineDevice9Ex_CreateDepthStencilSurfaceEx( struct NineDevice9Ex *This, - UINT Width, - UINT Height, - D3DFORMAT Format, - D3DMULTISAMPLE_TYPE MultiSample, - DWORD MultisampleQuality, - BOOL Discard, - IDirect3DSurface9 **ppSurface, - HANDLE *pSharedHandle, - DWORD Usage ); - -HRESULT NINE_WINAPI -NineDevice9Ex_ResetEx( struct NineDevice9Ex *This, - D3DPRESENT_PARAMETERS *pPresentationParameters, - D3DDISPLAYMODEEX *pFullscreenDisplayMode ); - -HRESULT NINE_WINAPI -NineDevice9Ex_Reset( struct NineDevice9Ex *This, - D3DPRESENT_PARAMETERS *pPresentationParameters ); - -HRESULT NINE_WINAPI -NineDevice9Ex_GetDisplayModeEx( struct NineDevice9Ex *This, - UINT iSwapChain, - D3DDISPLAYMODEEX *pMode, - D3DDISPLAYROTATION *pRotation ); - -HRESULT NINE_WINAPI -NineDevice9Ex_TestCooperativeLevel( struct NineDevice9Ex *This ); - -#endif /* _NINE_DEVICE9EX_H_ */ diff --git a/src/gallium/state_trackers/nine/device9video.c b/src/gallium/state_trackers/nine/device9video.c deleted file mode 100644 index 2e8e94a26e7..00000000000 --- a/src/gallium/state_trackers/nine/device9video.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "device9video.h" - -#define DBG_CHANNEL DBG_DEVICEVIDEO - -HRESULT NINE_WINAPI -NineDevice9Video_GetContentProtectionCaps( struct NineDevice9Video *This, - const GUID *pCryptoType, - const GUID *pDecodeProfile, - D3DCONTENTPROTECTIONCAPS *pCaps ) -{ - STUB(D3DERR_INVALIDCALL); -} - -HRESULT NINE_WINAPI -NineDevice9Video_CreateAuthenticatedChannel( struct NineDevice9Video *This, - D3DAUTHENTICATEDCHANNELTYPE ChannelType, - IDirect3DAuthenticatedChannel9 **ppAuthenticatedChannel, - HANDLE *pChannelHandle ) -{ - STUB(D3DERR_INVALIDCALL); -} - -HRESULT NINE_WINAPI -NineDevice9Video_CreateCryptoSession( struct NineDevice9Video *This, - const GUID *pCryptoType, - const GUID *pDecodeProfile, - IDirect3DCryptoSession9 **ppCryptoSession, - HANDLE *pCryptoHandle ) -{ - STUB(D3DERR_INVALIDCALL); -} - -IDirect3DDevice9VideoVtbl NineDevice9Video_vtable = { - (void *)NineUnknown_QueryInterface, - (void *)NineUnknown_AddRef, - (void *)NineUnknown_Release, - (void *)NineDevice9Video_GetContentProtectionCaps, - (void *)NineDevice9Video_CreateAuthenticatedChannel, - (void *)NineDevice9Video_CreateCryptoSession -}; diff --git a/src/gallium/state_trackers/nine/device9video.h b/src/gallium/state_trackers/nine/device9video.h deleted file mode 100644 index d77fd5ec57a..00000000000 --- a/src/gallium/state_trackers/nine/device9video.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef _NINE_DEVICE9VIDEO_H_ -#define _NINE_DEVICE9VIDEO_H_ - -#include "iunknown.h" - -struct NineDevice9Video -{ - struct NineUnknown base; -}; -static inline struct NineDevice9Video * -NineDevice9Video( void *data ) -{ - return (struct NineDevice9Video *)data; -} - -HRESULT NINE_WINAPI -NineDevice9Video_GetContentProtectionCaps( struct NineDevice9Video *This, - const GUID *pCryptoType, - const GUID *pDecodeProfile, - D3DCONTENTPROTECTIONCAPS *pCaps ); - -HRESULT NINE_WINAPI -NineDevice9Video_CreateAuthenticatedChannel( struct NineDevice9Video *This, - D3DAUTHENTICATEDCHANNELTYPE ChannelType, - IDirect3DAuthenticatedChannel9 **ppAuthenticatedChannel, - HANDLE *pChannelHandle ); - -HRESULT NINE_WINAPI -NineDevice9Video_CreateCryptoSession( struct NineDevice9Video *This, - const GUID *pCryptoType, - const GUID *pDecodeProfile, - IDirect3DCryptoSession9 **ppCryptoSession, - HANDLE *pCryptoHandle ); - -#endif /* _NINE_DEVICE9VIDEO_H_ */ diff --git a/src/gallium/state_trackers/nine/guid.c b/src/gallium/state_trackers/nine/guid.c deleted file mode 100644 index 5e63d2f6629..00000000000 --- a/src/gallium/state_trackers/nine/guid.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include -#include "guid.h" - -const GUID IID_IUnknown = { 0x00000000, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } }; -const GUID IID_ID3D9Adapter = { 0xBF6C7B9A, 0xF0BE, 0x11DF, { 0x81, 0xE3, 0x7F, 0x57, 0xDF, 0xD7, 0x20, 0x85 } }; -const GUID IID_IDirect3D9ExOverlayExtension = { 0x187AEB13, 0xAAF5, 0x4C59, { 0x87, 0x6D, 0xE0, 0x59, 0x08, 0x8C, 0x0D, 0xF8 } }; -const GUID IID_IDirect3DAuthenticatedChannel9 = { 0xFF24BEEE, 0xDA21, 0x4BEB, { 0x98, 0xB5, 0xD2, 0xF8, 0x99, 0xF9, 0x8A, 0xF9 } }; -const GUID IID_IDirect3DBaseTexture9 = { 0x580CA87E, 0x1D3C, 0x4D54, { 0x99, 0x1D, 0xB7, 0xD3, 0xE3, 0xC2, 0x98, 0xCE } }; -const GUID IID_IDirect3DCryptoSession9 = { 0xFA0AB799, 0x7A9C, 0x48CA, { 0x8C, 0x5B, 0x23, 0x7E, 0x71, 0xA5, 0x44, 0x34 } }; -const GUID IID_IDirect3DCubeTexture9 = { 0xFFF32F81, 0xD953, 0x473A, { 0x92, 0x23, 0x93, 0xD6, 0x52, 0xAB, 0xA9, 0x3F } }; -const GUID IID_IDirect3DDevice9 = { 0xD0223B96, 0xBF7A, 0x43FD, { 0x92, 0xBD, 0xA4, 0x3B, 0x0D, 0x82, 0xB9, 0xEB } }; -const GUID IID_IDirect3DDevice9Ex = { 0xB18B10CE, 0x2649, 0x405A, { 0x87, 0x0F, 0x95, 0xF7, 0x77, 0xD4, 0x31, 0x3A } }; -const GUID IID_IDirect3DDevice9Video = { 0x26DC4561, 0xA1EE, 0x4AE7, { 0x96, 0xDA, 0x11, 0x8A, 0x36, 0xC0, 0xEC, 0x95 } }; -const GUID IID_IDirect3DIndexBuffer9 = { 0x7C9DD65E, 0xD3F7, 0x4529, { 0xAC, 0xEE, 0x78, 0x58, 0x30, 0xAC, 0xDE, 0x35 } }; -const GUID IID_IDirect3DPixelShader9 = { 0x6D3BDBDC, 0x5B02, 0x4415, { 0xB8, 0x52, 0xCE, 0x5E, 0x8B, 0xCC, 0xB2, 0x89 } }; -const GUID IID_IDirect3DQuery9 = { 0xD9771460, 0xA695, 0x4F26, { 0xBB, 0xD3, 0x27, 0xB8, 0x40, 0xB5, 0x41, 0xCC } }; -const GUID IID_IDirect3DResource9 = { 0x05EEC05D, 0x8F7D, 0x4362, { 0xB9, 0x99, 0xD1, 0xBA, 0xF3, 0x57, 0xC7, 0x4 } }; -const GUID IID_IDirect3DStateBlock9 = { 0xB07C4FE5, 0x310D, 0x4BA8, { 0xA2, 0x3C, 0x4F, 0x0F, 0x20, 0x6F, 0x21, 0x8B } }; -const GUID IID_IDirect3DSurface9 = { 0x0CFBAF3A, 0x9FF6, 0x429A, { 0x99, 0xB3, 0xA2, 0x79, 0x6A, 0xF8, 0xB8, 0x9B } }; -const GUID IID_IDirect3DSwapChain9 = { 0x794950F2, 0xADFC, 0x458A, { 0x90, 0x5E, 0x10, 0xA1, 0x0B, 0x0B, 0x50, 0x3B } }; -const GUID IID_IDirect3DSwapChain9Ex = { 0x91886CAF, 0x1C3D, 0x4D2E, { 0xA0, 0xAB, 0x3E, 0x4C, 0x7D, 0x8D, 0x33, 0x3 } }; -const GUID IID_IDirect3DTexture9 = { 0x85C31227, 0x3DE5, 0x4F00, { 0x9B, 0x3A, 0xF1, 0x1A, 0xC3, 0x8C, 0x18, 0xB5 } }; -const GUID IID_IDirect3DVertexBuffer9 = { 0xB64BB1B5, 0xFD70, 0x4DF6, { 0xBF, 0x91, 0x19, 0xD0, 0xA1, 0x24, 0x55, 0xE3 } }; -const GUID IID_IDirect3DVertexDeclaration9 = { 0xDD13C59C, 0x36FA, 0x4098, { 0xA8, 0xFB, 0xC7, 0xED, 0x39, 0xDC, 0x85, 0x46 } }; -const GUID IID_IDirect3DVertexShader9 = { 0xEFC5557E, 0x6265, 0x4613, { 0x8A, 0x94, 0x43, 0x85, 0x78, 0x89, 0xEB, 0x36 } }; -const GUID IID_IDirect3DVolume9 = { 0x24F416E6, 0x1F67, 0x4AA7, { 0xB8, 0x8E, 0xD3, 0x3F, 0x6F, 0x31, 0x28, 0xA1 } }; -const GUID IID_IDirect3DVolumeTexture9 = { 0x2518526C, 0xE789, 0x4111, { 0xA7, 0xB9, 0x47, 0xEF, 0x32, 0x8D, 0x13, 0xE6 } }; - -boolean -GUID_equal( const GUID *a, - const GUID *b ) -{ - unsigned i; - - if (!a || !b) - return FALSE; - - if (a->Data1 != b->Data1 || - a->Data2 != b->Data2 || - a->Data3 != b->Data3) { return FALSE; } - for (i = 0; i < 8; i++) { - if (a->Data4[i] != b->Data4[i]) { return FALSE; } - } - return TRUE; -} - -char* GUID_sprintf(char *guid_str, REFGUID id) { - sprintf( guid_str, - "{%08X,%04X,%04X,%02X%02X%02X%02X%02X%02X%02X%02X}", - id->Data1, - id->Data2, - id->Data3, - id->Data4[0], - id->Data4[1], - id->Data4[2], - id->Data4[3], - id->Data4[4], - id->Data4[5], - id->Data4[6], - id->Data4[7]); - return guid_str; -} diff --git a/src/gallium/state_trackers/nine/guid.h b/src/gallium/state_trackers/nine/guid.h deleted file mode 100644 index af8f081bfb5..00000000000 --- a/src/gallium/state_trackers/nine/guid.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef _NINE_GUID_H_ -#define _NINE_GUID_H_ - -#include "pipe/p_compiler.h" - -#include "d3d9types.h" - -extern const GUID IID_ID3D9Adapter; - -boolean -GUID_equal( const GUID *a, - const GUID *b ); - -char* -GUID_sprintf( char *guid_str, - REFGUID id ); - -#endif /* _NINE_GUID_H_ */ diff --git a/src/gallium/state_trackers/nine/indexbuffer9.c b/src/gallium/state_trackers/nine/indexbuffer9.c deleted file mode 100644 index e73d29b5bd3..00000000000 --- a/src/gallium/state_trackers/nine/indexbuffer9.c +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "indexbuffer9.h" -#include "device9.h" -#include "nine_helpers.h" -#include "nine_pipe.h" -#include "nine_dump.h" - -#include "pipe/p_screen.h" -#include "pipe/p_context.h" -#include "pipe/p_state.h" -#include "pipe/p_defines.h" -#include "pipe/p_format.h" -#include "util/u_box.h" - -#define DBG_CHANNEL DBG_INDEXBUFFER - -HRESULT -NineIndexBuffer9_ctor( struct NineIndexBuffer9 *This, - struct NineUnknownParams *pParams, - D3DINDEXBUFFER_DESC *pDesc ) -{ - HRESULT hr; - DBG("This=%p pParams=%p pDesc=%p Usage=%s\n", - This, pParams, pDesc, nine_D3DUSAGE_to_str(pDesc->Usage)); - - hr = NineBuffer9_ctor(&This->base, pParams, D3DRTYPE_INDEXBUFFER, - pDesc->Usage, pDesc->Size, pDesc->Pool); - if (FAILED(hr)) - return hr; - - switch (pDesc->Format) { - case D3DFMT_INDEX16: This->index_size = 2; break; - case D3DFMT_INDEX32: This->index_size = 4; break; - default: - user_assert(!"Invalid index format.", D3DERR_INVALIDCALL); - break; - } - - pDesc->Type = D3DRTYPE_INDEXBUFFER; - This->desc = *pDesc; - - return D3D_OK; -} - -void -NineIndexBuffer9_dtor( struct NineIndexBuffer9 *This ) -{ - NineBuffer9_dtor(&This->base); -} - -struct pipe_resource * -NineIndexBuffer9_GetBuffer( struct NineIndexBuffer9 *This, unsigned *offset ) -{ - /* The resource may change */ - return NineBuffer9_GetResource(&This->base, offset); -} - -HRESULT NINE_WINAPI -NineIndexBuffer9_Lock( struct NineIndexBuffer9 *This, - UINT OffsetToLock, - UINT SizeToLock, - void **ppbData, - DWORD Flags ) -{ - return NineBuffer9_Lock(&This->base, OffsetToLock, SizeToLock, ppbData, Flags); -} - -HRESULT NINE_WINAPI -NineIndexBuffer9_Unlock( struct NineIndexBuffer9 *This ) -{ - return NineBuffer9_Unlock(&This->base); -} - -HRESULT NINE_WINAPI -NineIndexBuffer9_GetDesc( struct NineIndexBuffer9 *This, - D3DINDEXBUFFER_DESC *pDesc ) -{ - user_assert(pDesc, E_POINTER); - *pDesc = This->desc; - return D3D_OK; -} - -IDirect3DIndexBuffer9Vtbl NineIndexBuffer9_vtable = { - (void *)NineUnknown_QueryInterface, - (void *)NineUnknown_AddRef, - (void *)NineUnknown_Release, - (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */ - (void *)NineUnknown_SetPrivateData, - (void *)NineUnknown_GetPrivateData, - (void *)NineUnknown_FreePrivateData, - (void *)NineResource9_SetPriority, - (void *)NineResource9_GetPriority, - (void *)NineResource9_PreLoad, - (void *)NineResource9_GetType, - (void *)NineIndexBuffer9_Lock, - (void *)NineIndexBuffer9_Unlock, - (void *)NineIndexBuffer9_GetDesc -}; - -static const GUID *NineIndexBuffer9_IIDs[] = { - &IID_IDirect3DIndexBuffer9, - &IID_IDirect3DResource9, - &IID_IUnknown, - NULL -}; - -HRESULT -NineIndexBuffer9_new( struct NineDevice9 *pDevice, - D3DINDEXBUFFER_DESC *pDesc, - struct NineIndexBuffer9 **ppOut ) -{ - NINE_DEVICE_CHILD_NEW(IndexBuffer9, ppOut, /* args */ pDevice, pDesc); -} diff --git a/src/gallium/state_trackers/nine/indexbuffer9.h b/src/gallium/state_trackers/nine/indexbuffer9.h deleted file mode 100644 index e688488da84..00000000000 --- a/src/gallium/state_trackers/nine/indexbuffer9.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef _NINE_INDEXBUFFER9_H_ -#define _NINE_INDEXBUFFER9_H_ - -#include "resource9.h" -#include "buffer9.h" -#include "pipe/p_state.h" - -struct pipe_screen; -struct pipe_context; -struct pipe_transfer; -struct NineDevice9; - -struct NineIndexBuffer9 -{ - struct NineBuffer9 base; - - /* g3d stuff */ - unsigned index_size; - - D3DINDEXBUFFER_DESC desc; -}; -static inline struct NineIndexBuffer9 * -NineIndexBuffer9( void *data ) -{ - return (struct NineIndexBuffer9 *)data; -} - -HRESULT -NineIndexBuffer9_new( struct NineDevice9 *pDevice, - D3DINDEXBUFFER_DESC *pDesc, - struct NineIndexBuffer9 **ppOut ); - -HRESULT -NineIndexBuffer9_ctor( struct NineIndexBuffer9 *This, - struct NineUnknownParams *pParams, - D3DINDEXBUFFER_DESC *pDesc ); - -void -NineIndexBuffer9_dtor( struct NineIndexBuffer9 *This ); - -/*** Nine private ***/ - -struct pipe_resource * -NineIndexBuffer9_GetBuffer( struct NineIndexBuffer9 *This, - unsigned *offset ); - -/*** Direct3D public ***/ - -HRESULT NINE_WINAPI -NineIndexBuffer9_Lock( struct NineIndexBuffer9 *This, - UINT OffsetToLock, - UINT SizeToLock, - void **ppbData, - DWORD Flags ); - -HRESULT NINE_WINAPI -NineIndexBuffer9_Unlock( struct NineIndexBuffer9 *This ); - -HRESULT NINE_WINAPI -NineIndexBuffer9_GetDesc( struct NineIndexBuffer9 *This, - D3DINDEXBUFFER_DESC *pDesc ); - -#endif /* _NINE_INDEXBUFFER9_H_ */ diff --git a/src/gallium/state_trackers/nine/iunknown.c b/src/gallium/state_trackers/nine/iunknown.c deleted file mode 100644 index 2d69afd5496..00000000000 --- a/src/gallium/state_trackers/nine/iunknown.c +++ /dev/null @@ -1,288 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "iunknown.h" -#include "util/u_atomic.h" -#include "util/u_hash_table.h" - -#include "nine_helpers.h" -#include "nine_pdata.h" -#include "nine_lock.h" - -#define DBG_CHANNEL DBG_UNKNOWN - -HRESULT -NineUnknown_ctor( struct NineUnknown *This, - struct NineUnknownParams *pParams ) -{ - if (pParams->container) { - This->refs = 0; - This->forward = true; - This->bind = 0; - assert(!pParams->start_with_bind_not_ref); - } else if (pParams->start_with_bind_not_ref) { - This->refs = 0; - This->forward = false; - This->bind = 1; - } else { - This->refs = 1; - This->forward = false; - This->bind = 0; - } - - This->container = pParams->container; - This->device = pParams->device; - if (This->refs && This->device) - NineUnknown_AddRef(NineUnknown(This->device)); - - This->vtable = pParams->vtable; - This->vtable_internal = pParams->vtable; - This->guids = pParams->guids; - This->dtor = pParams->dtor; - - This->pdata = _mesa_hash_table_create(NULL, ht_guid_hash, ht_guid_compare); - if (!This->pdata) - return E_OUTOFMEMORY; - - return D3D_OK; -} - -void -NineUnknown_dtor( struct NineUnknown *This ) -{ - if (This->refs && This->device) /* Possible only if early exit after a ctor failed */ - (void) NineUnknown_Release(NineUnknown(This->device)); - - if (This->pdata) { - util_hash_table_foreach(This->pdata, ht_guid_delete, NULL); - _mesa_hash_table_destroy(This->pdata, NULL); - } - - FREE(This); -} - -HRESULT NINE_WINAPI -NineUnknown_QueryInterface( struct NineUnknown *This, - REFIID riid, - void **ppvObject ) -{ - unsigned i = 0; - char guid_str[64]; - - DBG("This=%p riid=%p id=%s ppvObject=%p\n", - This, riid, riid ? GUID_sprintf(guid_str, riid) : "", ppvObject); - - (void)guid_str; - - if (!ppvObject) return E_POINTER; - - do { - if (GUID_equal(This->guids[i], riid)) { - *ppvObject = This; - /* Tests showed that this call succeeds even on objects with - * zero refcount. This can happen if the app released all references - * but the resource is still bound. - */ - NineUnknown_AddRef(This); - return S_OK; - } - } while (This->guids[++i]); - - *ppvObject = NULL; - return E_NOINTERFACE; -} - -ULONG NINE_WINAPI -NineUnknown_AddRef( struct NineUnknown *This ) -{ - ULONG r; - if (This->forward) - return NineUnknown_AddRef(This->container); - else - r = p_atomic_inc_return(&This->refs); - - if (r == 1) { - if (This->device) - NineUnknown_AddRef(NineUnknown(This->device)); - } - return r; -} - -ULONG NINE_WINAPI -NineUnknown_Release( struct NineUnknown *This ) -{ - if (This->forward) - return NineUnknown_Release(This->container); - - ULONG r = p_atomic_dec_return(&This->refs); - - if (r == 0) { - if (This->device) { - if (NineUnknown_Release(NineUnknown(This->device)) == 0) - return r; /* everything's gone */ - } - /* Containers (here with !forward) take care of item destruction */ - if (!This->container && This->bind == 0) { - This->dtor(This); - } - } - return r; -} - -/* No need to lock the mutex protecting nine (when D3DCREATE_MULTITHREADED) - * for AddRef and Release, except for dtor as some of the dtors require it. */ -ULONG NINE_WINAPI -NineUnknown_ReleaseWithDtorLock( struct NineUnknown *This ) -{ - if (This->forward) - return NineUnknown_ReleaseWithDtorLock(This->container); - - ULONG r = p_atomic_dec_return(&This->refs); - - if (r == 0) { - if (This->device) { - if (NineUnknown_ReleaseWithDtorLock(NineUnknown(This->device)) == 0) - return r; /* everything's gone */ - } - /* Containers (here with !forward) take care of item destruction */ - if (!This->container && This->bind == 0) { - NineLockGlobalMutex(); - This->dtor(This); - NineUnlockGlobalMutex(); - } - } - return r; -} - -HRESULT NINE_WINAPI -NineUnknown_GetDevice( struct NineUnknown *This, - IDirect3DDevice9 **ppDevice ) -{ - user_assert(ppDevice, E_POINTER); - NineUnknown_AddRef(NineUnknown(This->device)); - *ppDevice = (IDirect3DDevice9 *)This->device; - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineUnknown_SetPrivateData( struct NineUnknown *This, - REFGUID refguid, - const void *pData, - DWORD SizeOfData, - DWORD Flags ) -{ - enum pipe_error err; - struct pheader *header; - const void *user_data = pData; - char guid_str[64]; - void *header_data; - - DBG("This=%p GUID=%s pData=%p SizeOfData=%u Flags=%x\n", - This, GUID_sprintf(guid_str, refguid), pData, SizeOfData, Flags); - - (void)guid_str; - - if (Flags & D3DSPD_IUNKNOWN) - user_assert(SizeOfData == sizeof(IUnknown *), D3DERR_INVALIDCALL); - - /* data consists of a header and the actual data. avoiding 2 mallocs */ - header = CALLOC_VARIANT_LENGTH_STRUCT(pheader, SizeOfData); - if (!header) { return E_OUTOFMEMORY; } - header->unknown = (Flags & D3DSPD_IUNKNOWN) ? TRUE : FALSE; - - /* if the refguid already exists, delete it */ - NineUnknown_FreePrivateData(This, refguid); - - /* IUnknown special case */ - if (header->unknown) { - /* here the pointer doesn't point to the data we want, so point at the - * pointer making what we eventually copy is the pointer itself */ - user_data = &pData; - } - - header->size = SizeOfData; - header_data = (void *)header + sizeof(*header); - memcpy(header_data, user_data, header->size); - memcpy(&header->guid, refguid, sizeof(header->guid)); - - _mesa_hash_table_insert(This->pdata, &header->guid, header); - if (header->unknown) { IUnknown_AddRef(*(IUnknown **)header_data); } - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineUnknown_GetPrivateData( struct NineUnknown *This, - REFGUID refguid, - void *pData, - DWORD *pSizeOfData ) -{ - struct pheader *header; - DWORD sizeofdata; - char guid_str[64]; - void *header_data; - - DBG("This=%p GUID=%s pData=%p pSizeOfData=%p\n", - This, GUID_sprintf(guid_str, refguid), pData, pSizeOfData); - - (void)guid_str; - - header = util_hash_table_get(This->pdata, refguid); - if (!header) { return D3DERR_NOTFOUND; } - - user_assert(pSizeOfData, E_POINTER); - sizeofdata = *pSizeOfData; - *pSizeOfData = header->size; - - if (!pData) { - return D3D_OK; - } - if (sizeofdata < header->size) { - return D3DERR_MOREDATA; - } - - header_data = (void *)header + sizeof(*header); - if (header->unknown) { IUnknown_AddRef(*(IUnknown **)header_data); } - memcpy(pData, header_data, header->size); - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineUnknown_FreePrivateData( struct NineUnknown *This, - REFGUID refguid ) -{ - struct pheader *header; - char guid_str[64]; - - DBG("This=%p GUID=%s\n", This, GUID_sprintf(guid_str, refguid)); - - (void)guid_str; - - header = util_hash_table_get(This->pdata, refguid); - if (!header) - return D3DERR_NOTFOUND; - - ht_guid_delete(NULL, header, NULL); - _mesa_hash_table_remove_key(This->pdata, refguid); - - return D3D_OK; -} diff --git a/src/gallium/state_trackers/nine/iunknown.h b/src/gallium/state_trackers/nine/iunknown.h deleted file mode 100644 index 20ad191cf44..00000000000 --- a/src/gallium/state_trackers/nine/iunknown.h +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef _NINE_IUNKNOWN_H_ -#define _NINE_IUNKNOWN_H_ - -#include "pipe/p_compiler.h" - -#include "util/u_atomic.h" -#include "util/u_memory.h" - -#include "guid.h" -#include "nine_flags.h" -#include "nine_debug.h" -#include "nine_quirk.h" - -#include "d3d9.h" - -struct Nine9; -struct NineDevice9; - -struct NineUnknown -{ - /* pointer to vtable (can be overriden outside gallium nine) */ - void *vtable; - /* pointer to internal vtable */ - void *vtable_internal; - - int32_t refs; /* external reference count */ - int32_t bind; /* internal bind count */ - boolean forward; /* whether to forward references to the container */ - - /* container: for surfaces and volumes only. - * Can be a texture, a volume texture or a swapchain. - * forward is set to false for the swapchain case. - * If forward is set, refs are passed to the container if forward is set - * and the container has bind increased if the object has non null bind. */ - struct NineUnknown *container; - struct NineDevice9 *device; /* referenced if (refs) */ - - const GUID **guids; /* for QueryInterface */ - - /* for [GS]etPrivateData/FreePrivateData */ - struct hash_table *pdata; - - void (*dtor)(void *data); /* top-level dtor */ -}; -static inline struct NineUnknown * -NineUnknown( void *data ) -{ - return (struct NineUnknown *)data; -} - -/* Use this instead of a shitload of arguments: */ -struct NineUnknownParams -{ - void *vtable; - const GUID **guids; - void (*dtor)(void *data); - struct NineUnknown *container; - struct NineDevice9 *device; - bool start_with_bind_not_ref; -}; - -HRESULT -NineUnknown_ctor( struct NineUnknown *This, - struct NineUnknownParams *pParams ); - -void -NineUnknown_dtor( struct NineUnknown *This ); - -/*** Direct3D public methods ***/ - -HRESULT NINE_WINAPI -NineUnknown_QueryInterface( struct NineUnknown *This, - REFIID riid, - void **ppvObject ); - -ULONG NINE_WINAPI -NineUnknown_AddRef( struct NineUnknown *This ); - -ULONG NINE_WINAPI -NineUnknown_Release( struct NineUnknown *This ); - -ULONG NINE_WINAPI -NineUnknown_ReleaseWithDtorLock( struct NineUnknown *This ); - -HRESULT NINE_WINAPI -NineUnknown_GetDevice( struct NineUnknown *This, - IDirect3DDevice9 **ppDevice ); - -HRESULT NINE_WINAPI -NineUnknown_SetPrivateData( struct NineUnknown *This, - REFGUID refguid, - const void *pData, - DWORD SizeOfData, - DWORD Flags ); - -HRESULT NINE_WINAPI -NineUnknown_GetPrivateData( struct NineUnknown *This, - REFGUID refguid, - void *pData, - DWORD *pSizeOfData ); - -HRESULT NINE_WINAPI -NineUnknown_FreePrivateData( struct NineUnknown *This, - REFGUID refguid ); - -/*** Nine private methods ***/ - -static inline void -NineUnknown_Destroy( struct NineUnknown *This ) -{ - assert(!(This->refs | This->bind)); - This->dtor(This); -} - -static inline UINT -NineUnknown_Bind( struct NineUnknown *This ) -{ - UINT b = p_atomic_inc_return(&This->bind); - assert(b); - - if (b == 1 && This->forward) - NineUnknown_Bind(This->container); - - return b; -} - -static inline UINT -NineUnknown_Unbind( struct NineUnknown *This ) -{ - UINT b = p_atomic_dec_return(&This->bind); - - if (b == 0 && This->forward) - NineUnknown_Unbind(This->container); - else if (b == 0 && This->refs == 0 && !This->container) - This->dtor(This); - - return b; -} - -static inline void -NineUnknown_ConvertRefToBind( struct NineUnknown *This ) -{ - NineUnknown_Bind(This); - NineUnknown_Release(This); -} - -/* Detach from container. */ -static inline void -NineUnknown_Detach( struct NineUnknown *This ) -{ - assert(This->container && !This->forward); - - This->container = NULL; - if (!(This->refs | This->bind)) - This->dtor(This); -} - -#endif /* _NINE_IUNKNOWN_H_ */ diff --git a/src/gallium/state_trackers/nine/meson.build b/src/gallium/state_trackers/nine/meson.build deleted file mode 100644 index 7c9e035cafc..00000000000 --- a/src/gallium/state_trackers/nine/meson.build +++ /dev/null @@ -1,75 +0,0 @@ -# Copyright © 2017 Intel Corporation - -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: - -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. - -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -nine_st_files = files( - 'adapter9.c', - 'authenticatedchannel9.c', - 'basetexture9.c', - 'buffer9.c', - 'cryptosession9.c', - 'cubetexture9.c', - 'device9.c', - 'device9ex.c', - 'device9video.c', - 'guid.c', - 'indexbuffer9.c', - 'iunknown.c', - 'nine_buffer_upload.c', - 'nine_debug.c', - 'nine_dump.c', - 'nineexoverlayextension.c', - 'nine_ff.c', - 'nine_helpers.c', - 'nine_lock.c', - 'nine_pipe.c', - 'nine_quirk.c', - 'nine_queue.c', - 'nine_shader.c', - 'nine_state.c', - 'pixelshader9.c', - 'query9.c', - 'resource9.c', - 'stateblock9.c', - 'surface9.c', - 'swapchain9.c', - 'swapchain9ex.c', - 'texture9.c', - 'threadpool.c', - 'vertexbuffer9.c', - 'vertexdeclaration9.c', - 'vertexshader9.c', - 'volume9.c', - 'volumetexture9.c', -) - -libnine_st = static_library( - 'nine_st', - nine_st_files, - c_args : c_vis_args, - include_directories : [ - inc_d3d9, inc_gallium, inc_include, inc_src, inc_gallium_aux, - ], - dependencies : [ - dep_thread, idep_nir, idep_nir_headers - ], - link_with : [ - libmesa_gallium - ] -) diff --git a/src/gallium/state_trackers/nine/nine_buffer_upload.c b/src/gallium/state_trackers/nine/nine_buffer_upload.c deleted file mode 100644 index a71f0195a2a..00000000000 --- a/src/gallium/state_trackers/nine/nine_buffer_upload.c +++ /dev/null @@ -1,294 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 VMware, Inc. - * Copyright 2016 Axel Davy - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ -/* Adapted from u_upload_mgr. - * Makes suballocations from bigger allocations, - * while enabling fast mapping. */ - -#include "pipe/p_defines.h" -#include "util/u_inlines.h" -#include "pipe/p_context.h" -#include "util/u_memory.h" -#include "util/u_math.h" -#include "util/slab.h" - -#include "nine_buffer_upload.h" - -#include "nine_debug.h" - -#define DBG_CHANNEL (DBG_INDEXBUFFER|DBG_VERTEXBUFFER) - -struct nine_buffer_group { - unsigned refcount; /* How many sub-buffers live inside the buffer */ - struct pipe_resource *resource; - struct pipe_transfer *transfer; - uint8_t *map; - unsigned free_offset; /* Aligned offset to the upload buffer, pointing - * at the first unused byte. */ -}; - -struct nine_subbuffer { - struct nine_buffer_group *parent; /* Can be NULL */ - struct pipe_resource *resource; /* The parent resource if apply */ - unsigned offset; /* Offset inside the resource */ - /* If there is no parent, the resource map. Else NULL. */ - struct pipe_transfer *transfer; - uint8_t *map; -}; - -struct nine_buffer_upload { - struct pipe_context *pipe; - struct slab_mempool buffer_pool; - - unsigned buffers_size; /* Size of the big allocated buffers */ - unsigned num_buffers; - struct nine_buffer_group *buffers; -}; - -static void -nine_upload_create_buffer_group(struct nine_buffer_upload *upload, - struct nine_buffer_group *group) -{ - struct pipe_resource resource; - struct pipe_screen *screen = upload->pipe->screen; - DBG("%p %p\n", upload, group); - - memset(&resource, 0, sizeof(resource)); - resource.target = PIPE_BUFFER; - resource.format = PIPE_FORMAT_R8_UNORM; - resource.bind = PIPE_BIND_VERTEX_BUFFER; - resource.usage = PIPE_USAGE_STREAM; - resource.width0 = upload->buffers_size; - resource.height0 = 1; - resource.depth0 = 1; - resource.array_size = 1; - resource.flags = PIPE_RESOURCE_FLAG_MAP_PERSISTENT | - PIPE_RESOURCE_FLAG_MAP_COHERENT; - - group->refcount = 0; - group->resource = screen->resource_create(screen, &resource); - if (group->resource == NULL) - return; - - group->map = pipe_buffer_map_range(upload->pipe, group->resource, - 0, upload->buffers_size, - PIPE_TRANSFER_WRITE | - PIPE_TRANSFER_PERSISTENT | - PIPE_TRANSFER_COHERENT, - &group->transfer); - if (group->map == NULL) { - group->transfer = NULL; - pipe_resource_reference(&group->resource, NULL); - return; - } - - group->free_offset = 0; -} - -static void -nine_upload_destroy_buffer_group(struct nine_buffer_upload *upload, - struct nine_buffer_group *group) -{ - DBG("%p %p\n", upload, group); - assert(group->refcount == 0); - - if (group->transfer) - pipe_transfer_unmap(upload->pipe, group->transfer); - if (group->resource) - pipe_resource_reference(&group->resource, NULL); - group->transfer = NULL; - group->map = NULL; -} - -struct nine_buffer_upload * -nine_upload_create(struct pipe_context *pipe, unsigned buffers_size, - unsigned num_buffers) -{ - struct nine_buffer_upload *upload; - int i; - - DBG("\n"); - - if (!pipe->screen->get_param(pipe->screen, - PIPE_CAP_BUFFER_MAP_PERSISTENT_COHERENT)) - return NULL; - - upload = CALLOC_STRUCT(nine_buffer_upload); - - if (!upload) - return NULL; - - slab_create(&upload->buffer_pool, sizeof(struct nine_subbuffer), 4096); - - upload->pipe = pipe; - upload->buffers_size = align(buffers_size, 4096); - upload->num_buffers = num_buffers; - - upload->buffers = CALLOC(num_buffers, sizeof(struct nine_buffer_group)); - if (!upload->buffers) - goto buffers_fail; - - for (i = 0; i < num_buffers; i++) - nine_upload_create_buffer_group(upload, &upload->buffers[i]); - - return upload; - -buffers_fail: - slab_destroy(&upload->buffer_pool); - FREE(upload); - return NULL; -} - -void -nine_upload_destroy(struct nine_buffer_upload *upload) -{ - int i; - - DBG("%p\n", upload); - - for (i = 0; i < upload->num_buffers; i++) - nine_upload_destroy_buffer_group(upload, &upload->buffers[i]); - slab_destroy(&upload->buffer_pool); - FREE(upload); -} - -struct nine_subbuffer * -nine_upload_create_buffer(struct nine_buffer_upload *upload, - unsigned buffer_size) -{ - struct nine_subbuffer *buf = slab_alloc_st(&upload->buffer_pool); - struct nine_buffer_group *group = NULL; - unsigned size = align(buffer_size, 4096); - int i = 0; - - DBG("%p %d\n", upload, buffer_size); - - if (!buf) - return NULL; - - for (i = 0; i < upload->num_buffers; i++) { - group = &upload->buffers[i]; - if (group->resource && - group->free_offset + size <= upload->buffers_size) - break; - } - - if (i == upload->num_buffers) { - /* Allocate lonely buffer */ - struct pipe_resource resource; - struct pipe_screen *screen = upload->pipe->screen; - - DBG("Allocating buffer\n"); - buf->parent = NULL; - - memset(&resource, 0, sizeof(resource)); - resource.target = PIPE_BUFFER; - resource.format = PIPE_FORMAT_R8_UNORM; - resource.bind = PIPE_BIND_VERTEX_BUFFER; - resource.usage = PIPE_USAGE_STREAM; - resource.width0 = buffer_size; - resource.height0 = 1; - resource.depth0 = 1; - resource.array_size = 1; - resource.flags = PIPE_RESOURCE_FLAG_MAP_PERSISTENT | - PIPE_RESOURCE_FLAG_MAP_COHERENT; - - buf->resource = screen->resource_create(screen, &resource); - if (buf->resource == NULL) { - slab_free_st(&upload->buffer_pool, buf); - return NULL; - } - - buf->map = pipe_buffer_map_range(upload->pipe, buf->resource, - 0, buffer_size, - PIPE_TRANSFER_WRITE | - PIPE_TRANSFER_PERSISTENT | - PIPE_TRANSFER_COHERENT, - &buf->transfer); - if (buf->map == NULL) { - pipe_resource_reference(&buf->resource, NULL); - slab_free_st(&upload->buffer_pool, buf); - return NULL; - } - buf->offset = 0; - return buf; - } - - DBG("Using buffer group %d\n", i); - - buf->parent = group; - buf->resource = NULL; - pipe_resource_reference(&buf->resource, group->resource); - buf->offset = group->free_offset; - - group->free_offset += size; - group->refcount += 1; - - return buf; -} - -void -nine_upload_release_buffer(struct nine_buffer_upload *upload, - struct nine_subbuffer *buf) -{ - DBG("%p %p %p\n", upload, buf, buf->parent); - - if (buf->parent) { - pipe_resource_reference(&buf->resource, NULL); - buf->parent->refcount--; - if (buf->parent->refcount == 0) { - /* Allocate new buffer */ - nine_upload_destroy_buffer_group(upload, buf->parent); - nine_upload_create_buffer_group(upload, buf->parent); - } - } else { - /* lonely buffer */ - if (buf->transfer) - pipe_transfer_unmap(upload->pipe, buf->transfer); - pipe_resource_reference(&buf->resource, NULL); - } - - slab_free_st(&upload->buffer_pool, buf); -} - -uint8_t * -nine_upload_buffer_get_map(struct nine_subbuffer *buf) -{ - if (buf->parent) { - return buf->parent->map + buf->offset; - } - /* lonely buffer */ - return buf->map; -} - -struct pipe_resource * -nine_upload_buffer_resource_and_offset(struct nine_subbuffer *buf, - unsigned *offset) -{ - *offset = buf->offset; - return buf->resource; -} diff --git a/src/gallium/state_trackers/nine/nine_buffer_upload.h b/src/gallium/state_trackers/nine/nine_buffer_upload.h deleted file mode 100644 index b7088250a83..00000000000 --- a/src/gallium/state_trackers/nine/nine_buffer_upload.h +++ /dev/null @@ -1,59 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 VMware, Inc. - * Copyright 2016 Axel Davy - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#ifndef _NINE_BUFFER_UPLOAD_H_ -#define _NINE_BUFFER_UPLOAD_H_ - -#include "pipe/p_defines.h" - -struct nine_buffer_upload; -struct nine_subbuffer; - -struct nine_buffer_upload * -nine_upload_create(struct pipe_context *pipe, unsigned buffers_size, - unsigned num_buffers); - -void -nine_upload_destroy(struct nine_buffer_upload *upload); - -struct nine_subbuffer * -nine_upload_create_buffer(struct nine_buffer_upload *upload, - unsigned buffer_size); - -void -nine_upload_release_buffer(struct nine_buffer_upload *upload, - struct nine_subbuffer *buf); - -uint8_t * -nine_upload_buffer_get_map(struct nine_subbuffer *buf); - -struct pipe_resource * -nine_upload_buffer_resource_and_offset(struct nine_subbuffer *buf, - unsigned *offset); - -#endif /* _NINE_BUFFER_UPLOAD_H_ */ diff --git a/src/gallium/state_trackers/nine/nine_csmt_helper.h b/src/gallium/state_trackers/nine/nine_csmt_helper.h deleted file mode 100644 index 7286cc31140..00000000000 --- a/src/gallium/state_trackers/nine/nine_csmt_helper.h +++ /dev/null @@ -1,438 +0,0 @@ -/* - * Copyright 2016 Patrick Rudolph - * - * Permission is hereby granted, free of charge, f, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, f, copy, modify, merge, f, publish, distribute, f, sub - * license, f, and/or sell copies of the Software, f, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISe, f, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -/* get number of arguments with __NARG__ */ -#define __NARG__(...) __NARG_I_(__VA_ARGS__,__RSEQ_N()) -#define __NARG_I_(...) __ARG_N(__VA_ARGS__) -#define __ARG_N( \ - _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \ - _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \ - _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \ - _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \ - _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \ - _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \ - _61,_62,_63,N,...) N -#define __RSEQ_N() \ - 63,62,61,60, \ - 59,58,57,56,55,54,53,52,51,50, \ - 49,48,47,46,45,44,43,42,41,40, \ - 39,38,37,36,35,34,33,32,31,30, \ - 29,28,27,26,25,24,23,22,21,20, \ - 19,18,17,16,15,14,13,12,11,10, \ - 9,8,7,6,5,4,3,2,1,0 - - -#define _args_for_bypass_1(a) a -#define _args_for_bypass_7(a, b, c, d, e, f, g) ,g -#define _args_for_bypass_14(a, b, c, d, e, f, g, ...) ,g _args_for_bypass_7(__VA_ARGS__) -#define _args_for_bypass_21(a, b, c, d, e, f, g, ...) ,g _args_for_bypass_14(__VA_ARGS__) -#define _args_for_bypass_28(a, b, c, d, e, f, g, ...) ,g _args_for_bypass_21(__VA_ARGS__) -#define _args_for_bypass_35(a, b, c, d, e, f, g, ...) ,g _args_for_bypass_28(__VA_ARGS__) -#define _args_for_bypass_42(a, b, c, d, e, f, g, ...) ,g _args_for_bypass_35(__VA_ARGS__) -#define _args_for_bypass_49(a, b, c, d, e, f, g, ...) ,g _args_for_bypass_42(__VA_ARGS__) -#define _args_for_bypass_56(a, b, c, d, e, f, g, ...) ,g _args_for_bypass_49(__VA_ARGS__) -#define _args_for_bypass_63(a, b, c, d, e, f, g, ...) ,g _args_for_bypass_56(__VA_ARGS__) -#define _args_for_bypass_70(a, b, c, d, e, f, g, ...) ,g _args_for_bypass_63(__VA_ARGS__) - -#define _GFUNC_(n) _args_for_bypass_##n -#define _GFUNC(n) _GFUNC_(n) - -#define ARGS_FOR_BYPASS(...) _GFUNC(__NARG__(__VA_ARGS__)) (__VA_ARGS__) - -#define _args_for_mem_1(a) a; -#define _args_for_mem_7(a, b, c, d, e, f, g) f; -#define _args_for_mem_14(a, b, c, d, e, f, g, ...) f; _args_for_mem_7(__VA_ARGS__) -#define _args_for_mem_21(a, b, c, d, e, f, g, ...) f; _args_for_mem_14(__VA_ARGS__) -#define _args_for_mem_28(a, b, c, d, e, f, g, ...) f; _args_for_mem_21(__VA_ARGS__) -#define _args_for_mem_35(a, b, c, d, e, f, g, ...) f; _args_for_mem_28(__VA_ARGS__) -#define _args_for_mem_42(a, b, c, d, e, f, g, ...) f; _args_for_mem_35(__VA_ARGS__) -#define _args_for_mem_49(a, b, c, d, e, f, g, ...) f; _args_for_mem_42(__VA_ARGS__) -#define _args_for_mem_56(a, b, c, d, e, f, g, ...) f; _args_for_mem_49(__VA_ARGS__) -#define _args_for_mem_63(a, b, c, d, e, f, g, ...) f; _args_for_mem_56(__VA_ARGS__) -#define _args_for_mem_70(a, b, c, d, e, f, g, ...) f; _args_for_mem_63(__VA_ARGS__) - -#define _FFUNC_(n) _args_for_mem_##n -#define _FFUNC(n) _FFUNC_(n) - -#define ARGS_FOR_MEM(...) _FFUNC(__NARG__(__VA_ARGS__)) (__VA_ARGS__) - -#define _args_for_unbind_1(a) a; -#define _args_for_unbind_7(a, b, c, d, e, f, g) e; -#define _args_for_unbind_14(a, b, c, d, e, f, g, ...) e; _args_for_unbind_7(__VA_ARGS__) -#define _args_for_unbind_21(a, b, c, d, e, f, g, ...) e; _args_for_unbind_14(__VA_ARGS__) -#define _args_for_unbind_28(a, b, c, d, e, f, g, ...) e; _args_for_unbind_21(__VA_ARGS__) -#define _args_for_unbind_35(a, b, c, d, e, f, g, ...) e; _args_for_unbind_28(__VA_ARGS__) -#define _args_for_unbind_42(a, b, c, d, e, f, g, ...) e; _args_for_unbind_35(__VA_ARGS__) -#define _args_for_unbind_49(a, b, c, d, e, f, g, ...) e; _args_for_unbind_42(__VA_ARGS__) -#define _args_for_unbind_56(a, b, c, d, e, f, g, ...) e; _args_for_unbind_49(__VA_ARGS__) -#define _args_for_unbind_63(a, b, c, d, e, f, g, ...) e; _args_for_unbind_56(__VA_ARGS__) -#define _args_for_unbind_70(a, b, c, d, e, f, g, ...) e; _args_for_unbind_63(__VA_ARGS__) - -#define _EFUNC_(n) _args_for_unbind_##n -#define _EFUNC(n) _EFUNC_(n) - -#define ARGS_FOR_UNBIND(...) _EFUNC(__NARG__(__VA_ARGS__)) (__VA_ARGS__) - -#define _args_for_call_1(a) a -#define _args_for_call_7(a, b, c, d, e, f, g) ,d -#define _args_for_call_14(a, b, c, d, e, f, g, ...) ,d _args_for_call_7(__VA_ARGS__) -#define _args_for_call_21(a, b, c, d, e, f, g, ...) ,d _args_for_call_14(__VA_ARGS__) -#define _args_for_call_28(a, b, c, d, e, f, g, ...) ,d _args_for_call_21(__VA_ARGS__) -#define _args_for_call_35(a, b, c, d, e, f, g, ...) ,d _args_for_call_28(__VA_ARGS__) -#define _args_for_call_42(a, b, c, d, e, f, g, ...) ,d _args_for_call_35(__VA_ARGS__) -#define _args_for_call_49(a, b, c, d, e, f, g, ...) ,d _args_for_call_42(__VA_ARGS__) -#define _args_for_call_56(a, b, c, d, e, f, g, ...) ,d _args_for_call_49(__VA_ARGS__) -#define _args_for_call_63(a, b, c, d, e, f, g, ...) ,d _args_for_call_56(__VA_ARGS__) -#define _args_for_call_70(a, b, c, d, e, f, g, ...) ,d _args_for_call_63(__VA_ARGS__) - -#define _DFUNC_(n) _args_for_call_##n -#define _DFUNC(n) _DFUNC_(n) - -#define ARGS_FOR_CALL(...) _DFUNC(__NARG__(__VA_ARGS__)) (__VA_ARGS__) - -#define _args_for_decl_1(a) a -#define _args_for_decl_7(a, b, c, d, e, f, g) ,c -#define _args_for_decl_14(a, b, c, d, e, f, g, ...) ,c _args_for_decl_7(__VA_ARGS__) -#define _args_for_decl_21(a, b, c, d, e, f, g, ...) ,c _args_for_decl_14(__VA_ARGS__) -#define _args_for_decl_28(a, b, c, d, e, f, g, ...) ,c _args_for_decl_21(__VA_ARGS__) -#define _args_for_decl_35(a, b, c, d, e, f, g, ...) ,c _args_for_decl_28(__VA_ARGS__) -#define _args_for_decl_42(a, b, c, d, e, f, g, ...) ,c _args_for_decl_35(__VA_ARGS__) -#define _args_for_decl_49(a, b, c, d, e, f, g, ...) ,c _args_for_decl_42(__VA_ARGS__) -#define _args_for_decl_56(a, b, c, d, e, f, g, ...) ,c _args_for_decl_49(__VA_ARGS__) -#define _args_for_decl_63(a, b, c, d, e, f, g, ...) ,c _args_for_decl_56(__VA_ARGS__) -#define _args_for_decl_70(a, b, c, d, e, f, g, ...) ,c _args_for_decl_63(__VA_ARGS__) - -#define _CFUNC_(n) _args_for_decl_##n -#define _CFUNC(n) _CFUNC_(n) - -#define ARGS_FOR_DECLARATION(...) _CFUNC(__NARG__(__VA_ARGS__)) (__VA_ARGS__) - -#define _args_for_assign_1(a) a -#define _args_for_assign_7(a, b, c, d, e, f, g) b; -#define _args_for_assign_14(a, b, c, d, e, f, g, ...) b; _args_for_assign_7(__VA_ARGS__) -#define _args_for_assign_21(a, b, c, d, e, f, g, ...) b; _args_for_assign_14(__VA_ARGS__) -#define _args_for_assign_28(a, b, c, d, e, f, g, ...) b; _args_for_assign_21(__VA_ARGS__) -#define _args_for_assign_35(a, b, c, d, e, f, g, ...) b; _args_for_assign_28(__VA_ARGS__) -#define _args_for_assign_42(a, b, c, d, e, f, g, ...) b; _args_for_assign_35(__VA_ARGS__) -#define _args_for_assign_49(a, b, c, d, e, f, g, ...) b; _args_for_assign_42(__VA_ARGS__) -#define _args_for_assign_56(a, b, c, d, e, f, g, ...) b; _args_for_assign_49(__VA_ARGS__) -#define _args_for_assign_63(a, b, c, d, e, f, g, ...) b; _args_for_assign_56(__VA_ARGS__) -#define _args_for_assign_70(a, b, c, d, e, f, g, ...) b; _args_for_assign_63(__VA_ARGS__) - -#define _BFUNC_(n) _args_for_assign_##n -#define _BFUNC(n) _BFUNC_(n) - -#define ARGS_FOR_ASSIGN(...) _BFUNC(__NARG__(__VA_ARGS__)) (__VA_ARGS__) - -#define _args_for_struct_1(a) a; -#define _args_for_struct_7(a, b, c, d, e, f, g) a; -#define _args_for_struct_14(a, b, c, d, e, f, g, ...) a; _args_for_struct_7(__VA_ARGS__) -#define _args_for_struct_21(a, b, c, d, e, f, g, ...) a; _args_for_struct_14(__VA_ARGS__) -#define _args_for_struct_28(a, b, c, d, e, f, g, ...) a; _args_for_struct_21(__VA_ARGS__) -#define _args_for_struct_35(a, b, c, d, e, f, g, ...) a; _args_for_struct_28(__VA_ARGS__) -#define _args_for_struct_42(a, b, c, d, e, f, g, ...) a; _args_for_struct_35(__VA_ARGS__) -#define _args_for_struct_49(a, b, c, d, e, f, g, ...) a; _args_for_struct_42(__VA_ARGS__) -#define _args_for_struct_56(a, b, c, d, e, f, g, ...) a; _args_for_struct_49(__VA_ARGS__) -#define _args_for_struct_63(a, b, c, d, e, f, g, ...) a; _args_for_struct_56(__VA_ARGS__) -#define _args_for_struct_70(a, b, c, d, e, f, g, ...) a; _args_for_struct_63(__VA_ARGS__) - -#define _AFUNC_(n) _args_for_struct_##n -#define _AFUNC(n) _AFUNC_(n) - -#define ARGS_FOR_STRUCT(...) _AFUNC(__NARG__(__VA_ARGS__)) (__VA_ARGS__) - -/* Serialization and deserialization */ - -#define CSMT_ITEM_NO_WAIT(name, ...) \ -\ -struct s_##name##_private { \ - struct csmt_instruction instr; \ - ARGS_FOR_STRUCT( __VA_ARGS__ ) \ -}; \ -\ -static void \ -name##_priv( struct NineDevice9 *device ARGS_FOR_DECLARATION( __VA_ARGS__ ) ); \ -\ -static int \ -name##_rx( struct NineDevice9 *device, struct csmt_instruction *instr ) \ -{ \ - struct csmt_context *ctx = device->csmt_ctx; \ - struct s_##name##_private *args = (struct s_##name##_private *)instr; \ - \ - (void) args; \ - (void) ctx; \ - name##_priv( \ - device ARGS_FOR_CALL( __VA_ARGS__ ) \ - ); \ - ARGS_FOR_UNBIND( __VA_ARGS__ ) \ - return 0; \ -} \ -\ -void \ -name( struct NineDevice9 *device ARGS_FOR_DECLARATION( __VA_ARGS__ ) ) \ -{ \ - struct csmt_context *ctx = device->csmt_ctx; \ - struct s_##name##_private *args; \ - unsigned memsize = sizeof(struct s_##name##_private); \ - unsigned memsize2 = 0; \ - \ - if (!device->csmt_active) { \ - name##_priv( \ - device ARGS_FOR_BYPASS( __VA_ARGS__ ) \ - ); \ - return; \ - } \ - ARGS_FOR_MEM ( __VA_ARGS__ ) \ - args = nine_queue_alloc(ctx->pool, memsize + memsize2); \ - assert(args); \ - args->instr.func = &name##_rx; \ - ARGS_FOR_ASSIGN( __VA_ARGS__ ) \ -} \ -\ -static void \ -name##_priv( struct NineDevice9 *device ARGS_FOR_DECLARATION( __VA_ARGS__ ) ) - -#define CSMT_ITEM_NO_WAIT_WITH_COUNTER(name, ...) \ -\ -struct s_##name##_private { \ - struct csmt_instruction instr; \ - unsigned *counter; \ - ARGS_FOR_STRUCT( __VA_ARGS__ ) \ -}; \ -\ -static void \ -name##_priv( struct NineDevice9 *device ARGS_FOR_DECLARATION( __VA_ARGS__ ) ); \ -\ -static int \ -name##_rx( struct NineDevice9 *device, struct csmt_instruction *instr ) \ -{ \ - struct csmt_context *ctx = device->csmt_ctx; \ - struct s_##name##_private *args = (struct s_##name##_private *)instr; \ - \ - (void) args; \ - (void) ctx; \ - name##_priv( \ - device ARGS_FOR_CALL( __VA_ARGS__ ) \ - ); \ - p_atomic_dec(args->counter); \ - ARGS_FOR_UNBIND( __VA_ARGS__ ) \ - return 0; \ -} \ -\ -void \ -name( struct NineDevice9 *device, unsigned *counter ARGS_FOR_DECLARATION( __VA_ARGS__ ) ) \ -{ \ - struct csmt_context *ctx = device->csmt_ctx; \ - struct s_##name##_private *args; \ - unsigned memsize = sizeof(struct s_##name##_private); \ - unsigned memsize2 = 0; \ - \ - if (!device->csmt_active) { \ - name##_priv( \ - device ARGS_FOR_BYPASS( __VA_ARGS__ ) \ - ); \ - return; \ - } \ - assert(counter); \ - p_atomic_inc(counter); \ - ARGS_FOR_MEM ( __VA_ARGS__ ) \ - args = nine_queue_alloc(ctx->pool, memsize + memsize2); \ - assert(args); \ - args->instr.func = &name##_rx; \ - args->counter = counter; \ - ARGS_FOR_ASSIGN( __VA_ARGS__ ) \ -} \ -\ -static void \ -name##_priv( struct NineDevice9 *device ARGS_FOR_DECLARATION( __VA_ARGS__ ) ) - -#define CSMT_ITEM_DO_WAIT(name, ...) \ -\ -struct s_##name##_private { \ - struct csmt_instruction instr; \ - ARGS_FOR_STRUCT( __VA_ARGS__ ) \ -}; \ -static void \ -name##_priv( struct NineDevice9 *device ARGS_FOR_DECLARATION( __VA_ARGS__ ) ); \ -\ -static int \ -name##_rx( struct NineDevice9 *device, struct csmt_instruction *instr) \ -{ \ - struct csmt_context *ctx = device->csmt_ctx; \ - struct s_##name##_private *args = (struct s_##name##_private *)instr; \ - \ - (void) args; \ - (void) ctx; \ - name##_priv( \ - device ARGS_FOR_CALL( __VA_ARGS__ ) \ - ); \ - ARGS_FOR_UNBIND( __VA_ARGS__ ) \ - return 1; \ -} \ -\ -void \ -name( struct NineDevice9 *device ARGS_FOR_DECLARATION( __VA_ARGS__ ) ) \ -{ \ - struct csmt_context *ctx = device->csmt_ctx; \ - struct s_##name##_private *args; \ - unsigned memsize = sizeof(struct s_##name##_private); \ - unsigned memsize2 = 0; \ - \ - if (!device->csmt_active) { \ - name##_priv( \ - device ARGS_FOR_BYPASS( __VA_ARGS__ ) \ - ); \ - return; \ - } \ - ARGS_FOR_MEM ( __VA_ARGS__ ) \ - args = nine_queue_alloc(ctx->pool, memsize + memsize2); \ - assert(args); \ - args->instr.func = &name##_rx; \ - ARGS_FOR_ASSIGN( __VA_ARGS__ ) \ - ctx->processed = FALSE; \ - nine_queue_flush(ctx->pool); \ - nine_csmt_wait_processed(ctx); \ -} \ -\ -static void \ -name##_priv( struct NineDevice9 *device ARGS_FOR_DECLARATION( __VA_ARGS__ ) ) - -/* ARGS_FOR_STRUCT, ARGS_FOR_ASSIGN, ARGS_FOR_DECLARATION, ARGS_FOR_CALL, ARGS_FOR_UNBIND, ARGS_FOR_MEM, ARGS_FOR_BYPASS */ -#define ARG_VAL(x, y) \ - x _##y ; ,\ - args->_##y = y ; ,\ - x y ,\ - args->_##y ,\ - ,\ - ,\ - y - -#define ARG_REF(x, y) \ - x* _##y ; ,\ - args->_##y = y; ,\ - x *y ,\ - args->_##y ,\ - ,\ - ,\ - y - -#define ARG_COPY_REF(x, y) \ - x * _##y ; x __##y ; ,\ - if ( y ) { args->_##y = &args->__##y ; args->__##y = *y ; } else { args->_##y = NULL; } ,\ - const x *y ,\ - (const x *)args->_##y ,\ - ,\ - ,\ - (const x *)y - -#define ARG_BIND_REF(x, y) \ - x * _##y ,\ - if ( y ) \ - NineUnknown_Bind( (void *)y ); \ - args->_##y = y ; ,\ - x *y ,\ - args->_##y,\ - if (args->_##y) \ - NineUnknown_Unbind((void *)(args->_##y)); \ - args->_##y = NULL; ,\ - ,\ - y - -#define ARG_BIND_RES(x, y) \ - x * _##y ,\ - args->_##y = NULL; \ - if (y) \ - pipe_resource_reference(&args->_##y, y); ,\ - x *y ,\ - args->_##y ,\ - if (args->_##y) \ - pipe_resource_reference(&args->_##y, NULL); ,\ - ,\ - y - -#define ARG_MEM(x, y) \ - x * _##y ,\ - args->_##y = (void *)args + memsize;\ - memcpy(args->_##y, y, memsize2); ,\ - const x *y ,\ - (const x *)args->_##y ,\ - ,\ - ,\ - (const x *)y - -#define ARG_MEM_SIZE(x, y) \ - x _##y ,\ - args->_##y = y; ,\ - x y ,\ - args->_##y ,\ - ,\ - memsize2 = y, \ - y - -#define ARG_BIND_BLIT(x, y) \ - x _##y ,\ - memcpy(&args->_##y , y, sizeof(x)); \ - args->_##y.src.resource = NULL; \ - args->_##y.dst.resource = NULL; \ - pipe_resource_reference(&args->_##y.src.resource, y->src.resource); \ - pipe_resource_reference(&args->_##y.dst.resource, y->dst.resource);,\ - x *y ,\ - &args->_##y ,\ - pipe_resource_reference(&args->_##y.src.resource, NULL); \ - pipe_resource_reference(&args->_##y.dst.resource, NULL);,\ - ,\ - y - -#define ARG_BIND_VBUF(x, y) \ - x _##y ,\ - memcpy(&args->_##y , y, sizeof(x)); \ - args->_##y.buffer.resource = NULL; \ - pipe_resource_reference(&args->_##y.buffer.resource, y->buffer.resource); ,\ - x *y ,\ - &args->_##y ,\ - pipe_resource_reference(&args->_##y.buffer.resource, NULL); ,\ - ,\ - y - -#define ARG_BIND_IBUF(x, y) \ - x _##y ,\ - memcpy(&args->_##y , y, sizeof(x)); \ - args->_##y.buffer = NULL; \ - pipe_resource_reference(&args->_##y.buffer, y->buffer); ,\ - x *y ,\ - &args->_##y ,\ - pipe_resource_reference(&args->_##y.buffer, NULL); ,\ - ,\ - y - -#define ARG_BIND_VIEW(x, y) \ - x * _##y ,\ - args->_##y = NULL; \ - if (y) \ - pipe_sampler_view_reference(&args->_##y, y); ,\ - x *y ,\ - args->_##y ,\ - if (args->_##y) \ - pipe_sampler_view_reference(&args->_##y, NULL); ,\ - ,\ - y - diff --git a/src/gallium/state_trackers/nine/nine_debug.c b/src/gallium/state_trackers/nine/nine_debug.c deleted file mode 100644 index 784d535d213..00000000000 --- a/src/gallium/state_trackers/nine/nine_debug.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "nine_debug.h" - -#include -#include "c11/threads.h" - -static const struct debug_named_value nine_debug_flags[] = { - { "unknown", DBG_UNKNOWN, "IUnknown implementation." }, - { "adapter", DBG_ADAPTER, "ID3D9Adapter implementation." }, - { "overlay", DBG_OVERLAYEXTENSION, "IDirect3D9ExOverlayExtension implementation." }, - { "auth", DBG_AUTHENTICATEDCHANNEL, "IDirect3DAuthenticatedChannel9 implementation." }, - { "basetex", DBG_BASETEXTURE, "IDirect3DBaseTexture9 implementation." }, - { "crypto", DBG_CRYPTOSESSION, "IDirect3DCryptoSession9 implementation." }, - { "cubetex", DBG_CUBETEXTURE, "IDirect3DCubeTexture9 implementation." }, - { "device", DBG_DEVICE, "IDirect3DDevice9(Ex) implementation." }, - { "video", DBG_DEVICEVIDEO, "IDirect3DDeviceVideo9 implementation." }, - { "ibuf", DBG_INDEXBUFFER, "IDirect3DIndexBuffer9 implementation." }, - { "ps", DBG_PIXELSHADER, "IDirect3DPixelShader9 implementation." }, - { "query", DBG_QUERY, "IDirect3DQuery9 implementation." }, - { "res", DBG_RESOURCE, "IDirect3DResource9 implementation." }, - { "state", DBG_STATEBLOCK, "IDirect3DStateBlock9 implementation." }, - { "surf", DBG_SURFACE, "IDirect3DSurface9 implementation." }, - { "swap", DBG_SWAPCHAIN, "IDirect3DSwapChain9(Ex) implementation." }, - { "tex", DBG_TEXTURE, "IDirect3DTexture9 implementation." }, - { "vbuf", DBG_VERTEXBUFFER, "IDirect3DVertexBuffer9 implementation." }, - { "vdecl", DBG_VERTEXDECLARATION, "IDirect3DVertexDeclaration9 implementation." }, - { "vs", DBG_VERTEXSHADER, "IDirect3DVertexShader9 implementation." }, - { "3dsurf", DBG_VOLUME, "IDirect3DVolume9 implementation." }, - { "3dtex", DBG_VOLUMETEXTURE, "IDirect3DVolumeTexture9 implementation." }, - { "shader", DBG_SHADER, "Shader token stream translator." }, - { "ff", DBG_FF, "Fixed function emulation." }, - { "user", DBG_USER, "User errors, both fixable and unfixable." }, - { "error", DBG_ERROR, "Driver errors, always visible." }, - { "warn", DBG_WARN, "Driver warnings, always visible in debug builds." }, - { "tid", DBG_TID, "Display thread-ids." }, - DEBUG_NAMED_VALUE_END -}; - -void -_nine_debug_printf( unsigned long flag, - const char *func, - const char *fmt, - ... ) -{ - static boolean first = TRUE; - static unsigned long dbg_flags = DBG_ERROR | DBG_WARN; - unsigned long tid = 0; - - if (first) { - first = FALSE; - dbg_flags |= debug_get_flags_option("NINE_DEBUG", nine_debug_flags, 0); - } - -#if defined(HAVE_PTHREAD) - if (dbg_flags & DBG_TID) - tid = pthread_self(); -#endif - - if (dbg_flags & flag) { - const char *f = func ? strrchr(func, '_') : NULL; - va_list ap; - /* inside a class this will print nine:tid:classinlowercase:func: while - * outside a class (rarely used) it will just print nine:tid:func - * the reason for lower case is simply to match the filenames, as it - * will also strip off the "Nine" */ - if (f && strncmp(func, "Nine", 4) == 0) { - char klass[96]; /* no class name is this long */ - char *ptr = klass; - for (func += 4; func != f; ++func) { *ptr++ = tolower(*func); } - *ptr = '\0'; - if (tid) - _debug_printf("nine:0x%08lx:%s:%s: ", tid, klass, ++f); - else - _debug_printf("nine:%s:%s: ", klass, ++f); - } else if (func) { - if (tid) - _debug_printf("nine:0x%08lx:%s ", tid, func); - else - _debug_printf("nine:%s ", func); - } - - va_start(ap, fmt); - _debug_vprintf(fmt, ap); - va_end(ap); - } -} - -void -_nine_stub( const char *file, - const char *func, - unsigned line ) -{ - const char *r = strrchr(file, '/'); - if (r == NULL) { r = strrchr(file, '\\'); } - _debug_printf("nine:%s:%d: %s STUB!\n", r ? ++r : file, line, func); -} diff --git a/src/gallium/state_trackers/nine/nine_debug.h b/src/gallium/state_trackers/nine/nine_debug.h deleted file mode 100644 index 75e412497b0..00000000000 --- a/src/gallium/state_trackers/nine/nine_debug.h +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef _NINE_DEBUG_H_ -#define _NINE_DEBUG_H_ - -#include "util/u_debug.h" -#include "pipe/p_compiler.h" - -void -_nine_debug_printf( unsigned long flag, - const char *func, - const char *fmt, - ... ) _util_printf_format(3,4); - -#define ERR(fmt, ...) _nine_debug_printf(DBG_ERROR, __FUNCTION__, fmt, ## __VA_ARGS__) - -#if defined(DEBUG) || !defined(NDEBUG) -#define WARN(fmt, ...) _nine_debug_printf(DBG_WARN, __FUNCTION__, fmt, ## __VA_ARGS__) -#define WARN_ONCE(fmt, ...) \ - do { \ - static boolean once = TRUE; \ - if (once) { \ - once = FALSE; \ - _nine_debug_printf(DBG_WARN, __FUNCTION__, fmt, ## __VA_ARGS__); \ - } \ - } while(0) -#else -#define WARN(fmt, ...) do {} while(0) -#define WARN_ONCE(fmt, ...) do {} while(0) -#endif - -#if defined(DEBUG) || !defined(NDEBUG) -#define DBG_FLAG(flag, fmt, ...) \ - _nine_debug_printf(flag, __FUNCTION__, fmt, ## __VA_ARGS__) -#else -#define DBG_FLAG(flag, fmt, ...) do {} while(0) -#endif -#define DBG(fmt, ...) DBG_FLAG(DBG_CHANNEL, fmt, ## __VA_ARGS__) - -#define DBG_UNKNOWN (1<< 0) -#define DBG_ADAPTER (1<< 1) -#define DBG_OVERLAYEXTENSION (1<< 2) -#define DBG_AUTHENTICATEDCHANNEL (1<< 3) -#define DBG_BASETEXTURE (1<< 4) -#define DBG_CRYPTOSESSION (1<< 5) -#define DBG_CUBETEXTURE (1<< 6) -#define DBG_DEVICE (1<< 7) -#define DBG_DEVICEVIDEO (1<< 8) -#define DBG_INDEXBUFFER (1<< 9) -#define DBG_PIXELSHADER (1<<10) -#define DBG_QUERY (1<<11) -#define DBG_RESOURCE (1<<12) -#define DBG_STATEBLOCK (1<<13) -#define DBG_SURFACE (1<<14) -#define DBG_SWAPCHAIN (1<<15) -#define DBG_TEXTURE (1<<16) -#define DBG_VERTEXBUFFER (1<<17) -#define DBG_VERTEXDECLARATION (1<<18) -#define DBG_VERTEXSHADER (1<<19) -#define DBG_VOLUME (1<<20) -#define DBG_VOLUMETEXTURE (1<<21) -#define DBG_SHADER (1<<22) -#define DBG_FF (1<<23) -#define DBG_USER (1<<24) -#define DBG_ERROR (1<<25) -#define DBG_WARN (1<<26) -#define DBG_TID (1<<27) - -void -_nine_stub( const char *file, - const char *func, - unsigned line ); - -#if defined(DEBUG) || !defined(NDEBUG) -#define STUB(ret) \ - do { \ - _nine_stub(__FILE__, __FUNCTION__, __LINE__); \ - return ret; \ - } while (0) -#else -#define STUB(ret) do { return ret; } while (0) -#endif - -/* the expression for this macro is equivalent of that to assert, however this - * macro is designed to be used in conditionals ala - * if (user_error(required condition)) { assertion failed } - * It also prints debug message if the assertion fails. */ -#if defined(DEBUG) || !defined(NDEBUG) -#define user_error(x) \ - (!(x) ? (DBG_FLAG(DBG_USER, "User assertion failed: `%s'\n", #x), TRUE) \ - : FALSE) -#else -#define user_error(x) (!(x) ? TRUE : FALSE) -#endif - -#if defined(DEBUG) || !defined(NDEBUG) -#define user_warn(x) \ - if ((x)) { DBG_FLAG(DBG_USER, "User warning: `%s'\n", #x); } -#else -#define user_warn(x) do {} while(0) -#endif - -/* nonfatal assert */ -#define user_assert(x, r) \ - do { \ - if (user_error(x)) { \ - return r; \ - } \ - } while (0) - -#define ret_err(x, r) \ - do { \ - ERR(x); \ - return r; \ - } while(0) - -#endif /* _NINE_DEBUG_H_ */ diff --git a/src/gallium/state_trackers/nine/nine_defines.h b/src/gallium/state_trackers/nine/nine_defines.h deleted file mode 100644 index 26aa064b1ac..00000000000 --- a/src/gallium/state_trackers/nine/nine_defines.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef _NINE_DEFINES_H_ -#define _NINE_DEFINES_H_ - -#include "pipe/p_defines.h" - - -#define NINE_RESOURCE_FLAG_LOCKABLE (PIPE_RESOURCE_FLAG_ST_PRIV << 1) -#define NINE_RESOURCE_FLAG_DUMMY (PIPE_RESOURCE_FLAG_ST_PRIV << 2) - -/* vertexdeclaration9.c */ -uint16_t nine_d3d9_to_nine_declusage(unsigned usage, unsigned index); - -#define NINE_DECLUSAGE_POSITION 0 -#define NINE_DECLUSAGE_BLENDWEIGHT 1 -#define NINE_DECLUSAGE_BLENDINDICES 2 -#define NINE_DECLUSAGE_NORMAL 3 -#define NINE_DECLUSAGE_TEXCOORD 4 -#define NINE_DECLUSAGE_TANGENT 5 -#define NINE_DECLUSAGE_BINORMAL 6 -#define NINE_DECLUSAGE_COLOR 7 -#define NINE_DECLUSAGE_POSITIONT 8 - -#define NINE_DECLUSAGE_PSIZE 9 -#define NINE_DECLUSAGE_TESSFACTOR 10 -#define NINE_DECLUSAGE_DEPTH 11 -#define NINE_DECLUSAGE_FOG 12 -#define NINE_DECLUSAGE_SAMPLE 13 -#define NINE_DECLUSAGE_NONE 14 -#define NINE_DECLUSAGE_COUNT (NINE_DECLUSAGE_NONE + 1) - -#define NINE_DECLUSAGE_i(declusage, n) NINE_DECLUSAGE_##declusage + n * NINE_DECLUSAGE_COUNT - -#define NINED3DCLEAR_DEPTHSTENCIL (D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL) - -#define NINE_BIND_BACKBUFFER_FLAGS (PIPE_BIND_RENDER_TARGET |\ - PIPE_BIND_SAMPLER_VIEW) - -#define NINE_BIND_PRESENTBUFFER_FLAGS (PIPE_BIND_RENDER_TARGET |\ - PIPE_BIND_DISPLAY_TARGET |\ - PIPE_BIND_SCANOUT |\ - PIPE_BIND_SHARED) - -#endif /* _NINE_DEFINES_H_ */ diff --git a/src/gallium/state_trackers/nine/nine_dump.c b/src/gallium/state_trackers/nine/nine_dump.c deleted file mode 100644 index 85ee266defb..00000000000 --- a/src/gallium/state_trackers/nine/nine_dump.c +++ /dev/null @@ -1,813 +0,0 @@ - -#include "nine_debug.h" -#include "nine_pipe.h" - -#include -#include "util/u_memory.h" -#include "util/u_math.h" - -#include "nine_dump.h" - -#if defined(DEBUG) || !defined(NDEBUG) - -static char __thread tls[128]; - -const char *nine_D3DDEVTYPE_to_str(D3DDEVTYPE type) -{ - switch (type) { - case D3DDEVTYPE_HAL: return "HAL"; - case D3DDEVTYPE_NULLREF: return "NULLREF"; - case D3DDEVTYPE_REF: return "REF"; - case D3DDEVTYPE_SW: return "SW"; - default: - return "(D3DDEVTYPE_?)"; - } -} - -const char *nine_D3DPOOL_to_str(D3DPOOL pool) -{ - switch (pool) { - case D3DPOOL_DEFAULT: return "DEFAULT"; - case D3DPOOL_MANAGED: return "MANAGED"; - case D3DPOOL_SYSTEMMEM: return "SYSTEMMEM"; - case D3DPOOL_SCRATCH: return "SCRATCH"; - default: - return "(D3DPOOL_?)"; - } -} - -const char *nine_D3DSAMP_to_str(DWORD samp) -{ - switch (samp) { - case D3DSAMP_ADDRESSU: return "ADDRESSU"; - case D3DSAMP_ADDRESSV: return "ADDRESSV"; - case D3DSAMP_ADDRESSW: return "ADDRESSW"; - case D3DSAMP_BORDERCOLOR: return "BORDERCOLOR"; - case D3DSAMP_MAGFILTER: return "MAGFILTER"; - case D3DSAMP_MINFILTER: return "MINFILTER"; - case D3DSAMP_MIPFILTER: return "MIPFILTER"; - case D3DSAMP_MIPMAPLODBIAS: return "MIPMAPLODBIAS"; - case D3DSAMP_MAXMIPLEVEL: return "MAXMIPLEVEL"; - case D3DSAMP_MAXANISOTROPY: return "MAXANISOTROPY"; - case D3DSAMP_SRGBTEXTURE: return "SRGBTEXTURE"; - case D3DSAMP_ELEMENTINDEX: return "ELEMENTINDEX"; - case D3DSAMP_DMAPOFFSET: return "DMAPOFFSET"; - default: - return "(D3DSAMP_?)"; - } -} - -#define C2S(n,s) \ - do { \ - if (usage & D3DUSAGE_##n) p += snprintf(&tls[p], sizeof(tls) - p, s); \ - } while(0) -const char *nine_D3DUSAGE_to_str(DWORD usage) -{ - int p = 0; - tls[0] = 0; - C2S(AUTOGENMIPMAP, "MIPGEN"); - C2S(WRITEONLY, "WO"); - C2S(DYNAMIC, "DYNAMIC"); - C2S(DEPTHSTENCIL, "DS"); - C2S(RENDERTARGET, "RT"); - C2S(SOFTWAREPROCESSING, "SW"); - C2S(DONOTCLIP, "NOCLIP"); - C2S(POINTS, "POINTS"); - C2S(DMAP, "DMAP"); - C2S(NPATCHES, "NPATCHES"); - C2S(RTPATCHES, "RTPATCHES"); - C2S(TEXTAPI, "TEXTAPI"); - C2S(NONSECURE, "NONSECURE"); - C2S(RESTRICTED_CONTENT, "RESTRICTED_CONTENT"); - C2S(RESTRICT_SHARED_RESOURCE, "RESTRICT_SHARED_RESOURCE"); - C2S(RESTRICT_SHARED_RESOURCE_DRIVER, "RESTRICT_SHARED_RESOURCE_DRIVER"); - return tls; -} -#undef C2S - -#define C2S(n) \ - do { \ - if (flags & D3DPRESENTFLAG_##n) \ - p += snprintf(&tls[p], sizeof(tls) - p, #n); \ - } while(0) -const char *nine_D3DPRESENTFLAG_to_str(DWORD flags) -{ - int p = 0; - tls[0] = 0; - C2S(DEVICECLIP); - C2S(DISCARD_DEPTHSTENCIL); - C2S(LOCKABLE_BACKBUFFER); - C2S(NOAUTOROTATE); - C2S(UNPRUNEDMODE); - C2S(VIDEO); - C2S(OVERLAY_LIMITEDRGB); - C2S(OVERLAY_YCbCr_BT709); - C2S(OVERLAY_YCbCr_xvYCC); - C2S(RESTRICTED_CONTENT); - C2S(RESTRICT_SHARED_RESOURCE_DRIVER); - return tls; -} -#undef C2S - -#define C2S(n) \ - do { \ - if (lock & D3DLOCK_##n) p += snprintf(&tls[p], sizeof(tls) - p, #n"|"); \ - } while(0) -const char *nine_D3DLOCK_to_str(DWORD lock) -{ - int p = 0; - tls[0] = 0; - C2S(DISCARD); - C2S(DONOTWAIT); - C2S(NO_DIRTY_UPDATE); - C2S(NOOVERWRITE); - C2S(NOSYSLOCK); - C2S(READONLY); - return tls; -} -#undef C2S - -const char *nine_D3DRTYPE_to_str(D3DRESOURCETYPE type) -{ - switch (type) { - case D3DRTYPE_SURFACE: return "SURFACE"; - case D3DRTYPE_VOLUME: return "VOLUME"; - case D3DRTYPE_TEXTURE: return "TEXTURE"; - case D3DRTYPE_VOLUMETEXTURE: return "VOLUMETEXTURE"; - case D3DRTYPE_CUBETEXTURE: return "CUBETEXTURE"; - case D3DRTYPE_VERTEXBUFFER: return "VERTEXBUFFER"; - case D3DRTYPE_INDEXBUFFER: return "INDEXBUFFER"; - default: - return "(D3DRTYPE_?)"; - } -} - -const char *nine_D3DQUERYTYPE_to_str(D3DQUERYTYPE type) -{ - switch (type) { - case D3DQUERYTYPE_VCACHE: return "VCACHE"; - case D3DQUERYTYPE_RESOURCEMANAGER: return "RESOURCEMANAGER"; - case D3DQUERYTYPE_VERTEXSTATS: return "VERTEXSTATS"; - case D3DQUERYTYPE_EVENT: return "EVENT"; - case D3DQUERYTYPE_OCCLUSION: return "OCCLUSION"; - case D3DQUERYTYPE_TIMESTAMP: return "TIMESTAMP"; - case D3DQUERYTYPE_TIMESTAMPDISJOINT: return "TIMESTAMPDISJOINT"; - case D3DQUERYTYPE_TIMESTAMPFREQ: return "TIMESTAMPFREQ"; - case D3DQUERYTYPE_PIPELINETIMINGS: return "PIPELINETIMINGS"; - case D3DQUERYTYPE_INTERFACETIMINGS: return "INTERFACETIMINGS"; - case D3DQUERYTYPE_VERTEXTIMINGS: return "VERTEXTIMINGS"; - case D3DQUERYTYPE_PIXELTIMINGS: return "PIXELTIMINGS"; - case D3DQUERYTYPE_BANDWIDTHTIMINGS: return "BANDWIDTHTIMINGS"; - case D3DQUERYTYPE_CACHEUTILIZATION: return "CACHEUTILIZATION"; - default: - return "(D3DQUERYTYPE_?)"; - } -} - -const char *nine_D3DTSS_to_str(D3DTEXTURESTAGESTATETYPE type) -{ - switch (type) { - case D3DTSS_COLOROP: return "COLOROP"; - case D3DTSS_ALPHAOP: return "ALPHAOP"; - case D3DTSS_COLORARG0: return "COLORARG0"; - case D3DTSS_COLORARG1: return "COLORARG1"; - case D3DTSS_COLORARG2: return "COLORARG2"; - case D3DTSS_ALPHAARG0: return "ALPHAARG0"; - case D3DTSS_ALPHAARG1: return "ALPHAARG1"; - case D3DTSS_ALPHAARG2: return "ALPHAARG2"; - case D3DTSS_RESULTARG: return "RESULTARG"; - case D3DTSS_BUMPENVMAT00: return "BUMPENVMAT00"; - case D3DTSS_BUMPENVMAT01: return "BUMPENVMAT01"; - case D3DTSS_BUMPENVMAT10: return "BUMPENVMAT10"; - case D3DTSS_BUMPENVMAT11: return "BUMPENVMAT11"; - case D3DTSS_BUMPENVLSCALE: return "BUMPENVLSCALE"; - case D3DTSS_BUMPENVLOFFSET: return "BUMPENVLOFFSET"; - case D3DTSS_TEXCOORDINDEX: return "TEXCOORDINDEX"; - case D3DTSS_TEXTURETRANSFORMFLAGS: return "TEXTURETRANSFORMFLAGS"; - case D3DTSS_CONSTANT: return "CONSTANT"; - default: - return "(D3DTSS_?)"; - } -} - -#define D3DTOP_TO_STR_CASE(n) case D3DTOP_##n: return #n -const char *nine_D3DTOP_to_str(D3DTEXTUREOP top) -{ - switch (top) { - D3DTOP_TO_STR_CASE(DISABLE); - D3DTOP_TO_STR_CASE(SELECTARG1); - D3DTOP_TO_STR_CASE(SELECTARG2); - D3DTOP_TO_STR_CASE(MODULATE); - D3DTOP_TO_STR_CASE(MODULATE2X); - D3DTOP_TO_STR_CASE(MODULATE4X); - D3DTOP_TO_STR_CASE(ADD); - D3DTOP_TO_STR_CASE(ADDSIGNED); - D3DTOP_TO_STR_CASE(ADDSIGNED2X); - D3DTOP_TO_STR_CASE(SUBTRACT); - D3DTOP_TO_STR_CASE(ADDSMOOTH); - D3DTOP_TO_STR_CASE(BLENDDIFFUSEALPHA); - D3DTOP_TO_STR_CASE(BLENDTEXTUREALPHA); - D3DTOP_TO_STR_CASE(BLENDFACTORALPHA); - D3DTOP_TO_STR_CASE(BLENDTEXTUREALPHAPM); - D3DTOP_TO_STR_CASE(BLENDCURRENTALPHA); - D3DTOP_TO_STR_CASE(PREMODULATE); - D3DTOP_TO_STR_CASE(MODULATEALPHA_ADDCOLOR); - D3DTOP_TO_STR_CASE(MODULATECOLOR_ADDALPHA); - D3DTOP_TO_STR_CASE(MODULATEINVALPHA_ADDCOLOR); - D3DTOP_TO_STR_CASE(MODULATEINVCOLOR_ADDALPHA); - D3DTOP_TO_STR_CASE(BUMPENVMAP); - D3DTOP_TO_STR_CASE(BUMPENVMAPLUMINANCE); - D3DTOP_TO_STR_CASE(DOTPRODUCT3); - D3DTOP_TO_STR_CASE(MULTIPLYADD); - D3DTOP_TO_STR_CASE(LERP); - default: - return "(D3DTOP_?)"; - } -} - -static const char * -nine_D3DLIGHTTYPE_to_str(D3DLIGHTTYPE type) -{ - switch (type) { - case D3DLIGHT_POINT: return "POINT"; - case D3DLIGHT_SPOT: return "SPOT"; - case D3DLIGHT_DIRECTIONAL: return "DIRECTIONAL"; - default: - return "(D3DLIGHT_?)"; - } -} - -static const char * -nine_D3DTA_to_str(DWORD value) -{ - switch (value & D3DTA_SELECTMASK) { - case D3DTA_DIFFUSE: return "DIFFUSE"; - case D3DTA_CURRENT: return "CURRENT"; - case D3DTA_TEXTURE: return "TEXTURE"; - case D3DTA_TFACTOR: return "TFACTOR"; - case D3DTA_SPECULAR: return "SPECULAR"; - case D3DTA_TEMP: return "TEMP"; - case D3DTA_CONSTANT: return "CONSTANT"; - default: - return "(D3DTA_?)"; - } -} - -static const char * -nine_D3DTSS_TCI_to_str(DWORD value) -{ - switch (value & 0xf0000) { - case D3DTSS_TCI_PASSTHRU: return "PASSTHRU"; - case D3DTSS_TCI_CAMERASPACENORMAL: return "CAMERASPACENORMAL"; - case D3DTSS_TCI_CAMERASPACEPOSITION: return "CAMERASPACEPOSITION"; - case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR: - return "CAMERASPACEREFLECTIONVECTOR"; - case D3DTSS_TCI_SPHEREMAP: return "SPHEREMAP"; - default: - return "(D3DTSS_TCI_?)"; - } -} - -static const char * -nine_D3DTTFF_to_str(DWORD value) -{ - switch (value) { - case D3DTTFF_DISABLE: return "DISABLE"; - case D3DTTFF_COUNT1: return "COUNT1"; - case D3DTTFF_COUNT2: return "COUNT2"; - case D3DTTFF_COUNT3: return "COUNT3"; - case D3DTTFF_COUNT4: return "COUNT4"; - case D3DTTFF_PROJECTED: return "PROJECTED"; - default: - return "(D3DTTFF_?)"; - } -} - -void -nine_dump_D3DLIGHT9(unsigned ch, const D3DLIGHT9 *lit) -{ - DBG_FLAG(ch, "D3DLIGHT9(%p):\n" - "Type: %s\n" - "Diffuse: (%f %f %f %f)\n" - "Specular: (%f %f %f %f)\n" - "Ambient: (%f %f %f %f)\n" - "Position: (%f %f %f)\n" - "Direction: (%f %f %f)\n" - "Range: %f\n" - "Falloff: %f\n" - "Attenuation: %f + %f * d + %f * d^2\n" - "Theta: %f deg\n" - "Phi: %f deg\n", lit, - nine_D3DLIGHTTYPE_to_str(lit->Type), - lit->Diffuse.r,lit->Diffuse.r,lit->Diffuse.g,lit->Diffuse.a, - lit->Specular.r,lit->Specular.r,lit->Specular.g,lit->Specular.a, - lit->Ambient.r,lit->Ambient.r,lit->Ambient.g,lit->Ambient.a, - lit->Position.x,lit->Position.y,lit->Position.z, - lit->Direction.x,lit->Direction.y,lit->Direction.z, - lit->Range,lit->Falloff, - lit->Attenuation0,lit->Attenuation1,lit->Attenuation2, - lit->Theta * 360.0f / M_PI,lit->Phi * 360.0f / M_PI); -} - -void -nine_dump_D3DMATERIAL9(unsigned ch, const D3DMATERIAL9 *mat) -{ - DBG_FLAG(ch, "D3DMATERIAL9(%p):\n" - "Diffuse: (%f %f %f %f)\n" - "Specular: (%f %f %f %f)\n" - "Ambient: (%f %f %f %f)\n" - "Emissive: (%f %f %f %f)\n" - "Power: %f\n", mat, - mat->Diffuse.r,mat->Diffuse.r,mat->Diffuse.g,mat->Diffuse.a, - mat->Specular.r,mat->Specular.r,mat->Specular.g,mat->Specular.a, - mat->Ambient.r,mat->Ambient.r,mat->Ambient.g,mat->Ambient.a, - mat->Emissive.r,mat->Emissive.r,mat->Emissive.g,mat->Emissive.a, - mat->Power); -} - -void -nine_dump_D3DTSS_value(unsigned ch, D3DTEXTURESTAGESTATETYPE type, DWORD value) -{ - float rgba[4]; - - switch (type) { - case D3DTSS_COLOROP: - case D3DTSS_ALPHAOP: - DBG_FLAG(ch, "D3DTSS_%s = %s\n", - nine_D3DTSS_to_str(type), nine_D3DTOP_to_str(value)); - break; - case D3DTSS_COLORARG0: - case D3DTSS_COLORARG1: - case D3DTSS_COLORARG2: - case D3DTSS_ALPHAARG0: - case D3DTSS_ALPHAARG1: - case D3DTSS_ALPHAARG2: - case D3DTSS_RESULTARG: - DBG_FLAG(ch, "D3DTSS_%s = %s%s%s\n", - nine_D3DTSS_to_str(type), - (value & D3DTA_COMPLEMENT) ? "COMPLEMENT " : "", - (value & D3DTA_ALPHAREPLICATE) ? "ALPHAREPLICATE " : "", - nine_D3DTA_to_str(value)); - break; - case D3DTSS_BUMPENVMAT00: - case D3DTSS_BUMPENVMAT01: - case D3DTSS_BUMPENVMAT10: - case D3DTSS_BUMPENVMAT11: - case D3DTSS_BUMPENVLSCALE: - case D3DTSS_BUMPENVLOFFSET: - DBG_FLAG(ch, "D3DTSS_%s = %f\n", - nine_D3DTSS_to_str(type), asfloat(value)); - break; - case D3DTSS_TEXCOORDINDEX: - DBG_FLAG(ch, "D3DTSS_TEXCOORDINDEX = %s %u\n", - nine_D3DTSS_TCI_to_str(value), - value & 0xffff); - break; - case D3DTSS_TEXTURETRANSFORMFLAGS: - DBG_FLAG(ch, "D3DTSS_TEXTURETRANSFORMFLAGS = %s\n", - nine_D3DTTFF_to_str(value)); - break; - case D3DTSS_CONSTANT: - d3dcolor_to_rgba(rgba, value); - DBG_FLAG(ch, "D3DTSS_CONSTANT = %f %f %f %F\n", - rgba[0],rgba[1],rgba[2],rgba[3]); - break; - default: - DBG_FLAG(ch, "D3DTSS_? = 0x%08x\n", value); - break; - } -} - -void -nine_dump_D3DADAPTER_IDENTIFIER9(unsigned ch, const D3DADAPTER_IDENTIFIER9 *id) -{ - DBG_FLAG(ch, "D3DADAPTER_IDENTIFIER9(%p):\n" - "Driver: %s\n" - "Description: %s\n" - "DeviceName: %s\n" - "DriverVersion: %08x.%08x\n" - "VendorId: %x\n" - "DeviceId: %x\n" - "SubSysId: %x\n" - "Revision: %u\n" - "GUID: %08x.%04x.%04x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x\n" - "WHQLLevel: %u\n", id, id->Driver, id->Description, - id->DeviceName, - id->DriverVersionLowPart, id->DriverVersionHighPart, - id->VendorId, id->DeviceId, id->SubSysId, - id->Revision, - id->DeviceIdentifier.Data1, - id->DeviceIdentifier.Data2, - id->DeviceIdentifier.Data3, - id->DeviceIdentifier.Data4[0], - id->DeviceIdentifier.Data4[1], - id->DeviceIdentifier.Data4[2], - id->DeviceIdentifier.Data4[3], - id->DeviceIdentifier.Data4[4], - id->DeviceIdentifier.Data4[5], - id->DeviceIdentifier.Data4[6], - id->DeviceIdentifier.Data4[7], - id->WHQLLevel); -} - -#define C2S(args...) p += snprintf(&s[p],c-p,args) - -#define CAP_CASE(m,p,n) \ - do { \ - if (caps->m & p##_##n) \ - C2S(" "#n); \ - else \ - C2S(" ("#n")"); \ - } while(0) - -void -nine_dump_D3DCAPS9(unsigned ch, const D3DCAPS9 *caps) -{ - const int c = 1 << 17; - int p = 0; - char *s = (char *)MALLOC(c); - - if (!s) { - DBG_FLAG(ch, "D3DCAPS9(%p): (out of memory)\n", caps); - return; - } - - C2S("DeviceType: %s\n", nine_D3DDEVTYPE_to_str(caps->DeviceType)); - - C2S("AdapterOrdinal: %u\nCaps:", caps->AdapterOrdinal); - if (caps->Caps & 0x20000) - C2S(" READ_SCANLINE"); - if (caps->Caps & ~0x20000) - C2S(" %x", caps->Caps & ~0x20000); - - C2S("\nCaps2:"); - CAP_CASE(Caps2, D3DCAPS2, CANAUTOGENMIPMAP); - CAP_CASE(Caps2, D3DCAPS2, CANCALIBRATEGAMMA); - CAP_CASE(Caps2, D3DCAPS2, CANSHARERESOURCE); - CAP_CASE(Caps2, D3DCAPS2, CANMANAGERESOURCE); - CAP_CASE(Caps2, D3DCAPS2, DYNAMICTEXTURES); - CAP_CASE(Caps2, D3DCAPS2, FULLSCREENGAMMA); - - C2S("\nCaps3:"); - CAP_CASE(Caps3, D3DCAPS3, ALPHA_FULLSCREEN_FLIP_OR_DISCARD); - CAP_CASE(Caps3, D3DCAPS3, COPY_TO_VIDMEM); - CAP_CASE(Caps3, D3DCAPS3, COPY_TO_SYSTEMMEM); - CAP_CASE(Caps3, D3DCAPS3, DXVAHD); - CAP_CASE(Caps3, D3DCAPS3, LINEAR_TO_SRGB_PRESENTATION); - - C2S("\nPresentationIntervals:"); - CAP_CASE(PresentationIntervals, D3DPRESENT_INTERVAL, ONE); - CAP_CASE(PresentationIntervals, D3DPRESENT_INTERVAL, TWO); - CAP_CASE(PresentationIntervals, D3DPRESENT_INTERVAL, THREE); - CAP_CASE(PresentationIntervals, D3DPRESENT_INTERVAL, FOUR); - CAP_CASE(PresentationIntervals, D3DPRESENT_INTERVAL, IMMEDIATE); - - C2S("\nCursorCaps:"); - CAP_CASE(CursorCaps, D3DCURSORCAPS, COLOR); - CAP_CASE(CursorCaps, D3DCURSORCAPS, LOWRES); - - C2S("\nDevCaps:"); - CAP_CASE(DevCaps, D3DDEVCAPS, CANBLTSYSTONONLOCAL); - CAP_CASE(DevCaps, D3DDEVCAPS, CANRENDERAFTERFLIP); - CAP_CASE(DevCaps, D3DDEVCAPS, DRAWPRIMITIVES2); - CAP_CASE(DevCaps, D3DDEVCAPS, DRAWPRIMITIVES2EX); - CAP_CASE(DevCaps, D3DDEVCAPS, DRAWPRIMTLVERTEX); - CAP_CASE(DevCaps, D3DDEVCAPS, EXECUTESYSTEMMEMORY); - CAP_CASE(DevCaps, D3DDEVCAPS, EXECUTEVIDEOMEMORY); - CAP_CASE(DevCaps, D3DDEVCAPS, HWRASTERIZATION); - CAP_CASE(DevCaps, D3DDEVCAPS, HWTRANSFORMANDLIGHT); - CAP_CASE(DevCaps, D3DDEVCAPS, NPATCHES); - CAP_CASE(DevCaps, D3DDEVCAPS, PUREDEVICE); - CAP_CASE(DevCaps, D3DDEVCAPS, QUINTICRTPATCHES); - CAP_CASE(DevCaps, D3DDEVCAPS, RTPATCHES); - CAP_CASE(DevCaps, D3DDEVCAPS, RTPATCHHANDLEZERO); - CAP_CASE(DevCaps, D3DDEVCAPS, SEPARATETEXTUREMEMORIES); - CAP_CASE(DevCaps, D3DDEVCAPS, TEXTURENONLOCALVIDMEM); - CAP_CASE(DevCaps, D3DDEVCAPS, TEXTURESYSTEMMEMORY); - CAP_CASE(DevCaps, D3DDEVCAPS, TEXTUREVIDEOMEMORY); - CAP_CASE(DevCaps, D3DDEVCAPS, TLVERTEXSYSTEMMEMORY); - CAP_CASE(DevCaps, D3DDEVCAPS, TLVERTEXVIDEOMEMORY); - - C2S("\nPrimitiveMiscCaps:"); - CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, MASKZ); - CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, CULLNONE); - CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, CULLCW); - CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, CULLCCW); - CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, COLORWRITEENABLE); - CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, CLIPPLANESCALEDPOINTS); - CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, CLIPTLVERTS); - CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, TSSARGTEMP); - CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, BLENDOP); - CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, NULLREFERENCE); - CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, INDEPENDENTWRITEMASKS); - CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, PERSTAGECONSTANT); - CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, POSTBLENDSRGBCONVERT); - CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, FOGANDSPECULARALPHA); - CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, SEPARATEALPHABLEND); - CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, MRTINDEPENDENTBITDEPTHS); - CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, MRTPOSTPIXELSHADERBLENDING); - CAP_CASE(PrimitiveMiscCaps, D3DPMISCCAPS, FOGVERTEXCLAMPED); - - C2S("\nRasterCaps:"); - CAP_CASE(RasterCaps, D3DPRASTERCAPS, ANISOTROPY); - CAP_CASE(RasterCaps, D3DPRASTERCAPS, COLORPERSPECTIVE); - CAP_CASE(RasterCaps, D3DPRASTERCAPS, DITHER); - CAP_CASE(RasterCaps, D3DPRASTERCAPS, DEPTHBIAS); - CAP_CASE(RasterCaps, D3DPRASTERCAPS, FOGRANGE); - CAP_CASE(RasterCaps, D3DPRASTERCAPS, FOGTABLE); - CAP_CASE(RasterCaps, D3DPRASTERCAPS, FOGVERTEX); - CAP_CASE(RasterCaps, D3DPRASTERCAPS, MIPMAPLODBIAS); - CAP_CASE(RasterCaps, D3DPRASTERCAPS, MULTISAMPLE_TOGGLE); - CAP_CASE(RasterCaps, D3DPRASTERCAPS, SCISSORTEST); - CAP_CASE(RasterCaps, D3DPRASTERCAPS, SLOPESCALEDEPTHBIAS); - CAP_CASE(RasterCaps, D3DPRASTERCAPS, WBUFFER); - CAP_CASE(RasterCaps, D3DPRASTERCAPS, WFOG); - CAP_CASE(RasterCaps, D3DPRASTERCAPS, ZBUFFERLESSHSR); - CAP_CASE(RasterCaps, D3DPRASTERCAPS, ZFOG); - CAP_CASE(RasterCaps, D3DPRASTERCAPS, ZTEST); - - C2S("\nZCmpCaps:"); - CAP_CASE(ZCmpCaps, D3DPCMPCAPS, ALWAYS); - CAP_CASE(ZCmpCaps, D3DPCMPCAPS, EQUAL); - CAP_CASE(ZCmpCaps, D3DPCMPCAPS, GREATER); - CAP_CASE(ZCmpCaps, D3DPCMPCAPS, GREATEREQUAL); - CAP_CASE(ZCmpCaps, D3DPCMPCAPS, LESS); - CAP_CASE(ZCmpCaps, D3DPCMPCAPS, LESSEQUAL); - CAP_CASE(ZCmpCaps, D3DPCMPCAPS, NEVER); - CAP_CASE(ZCmpCaps, D3DPCMPCAPS, NOTEQUAL); - - C2S("\nSrcBlendCaps"); - CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, BLENDFACTOR); - CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, BOTHINVSRCALPHA); - CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, BOTHSRCALPHA); - CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, DESTALPHA); - CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, DESTCOLOR); - CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, INVDESTALPHA); - CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, INVDESTCOLOR); - CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, INVSRCALPHA); - CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, INVSRCCOLOR); - CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, INVSRCCOLOR2); - CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, ONE); - CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, SRCALPHA); - CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, SRCALPHASAT); - CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, SRCCOLOR); - CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, SRCCOLOR2); - CAP_CASE(SrcBlendCaps, D3DPBLENDCAPS, ZERO); - - C2S("\nDestBlendCaps"); - CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, BLENDFACTOR); - CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, BOTHINVSRCALPHA); - CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, BOTHSRCALPHA); - CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, DESTALPHA); - CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, DESTCOLOR); - CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, INVDESTALPHA); - CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, INVDESTCOLOR); - CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, INVSRCALPHA); - CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, INVSRCCOLOR); - CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, INVSRCCOLOR2); - CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, ONE); - CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, SRCALPHA); - CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, SRCALPHASAT); - CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, SRCCOLOR); - CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, SRCCOLOR2); - CAP_CASE(DestBlendCaps, D3DPBLENDCAPS, ZERO); - - C2S("\nAlphaCmpCaps:"); - CAP_CASE(AlphaCmpCaps, D3DPCMPCAPS, ALWAYS); - CAP_CASE(AlphaCmpCaps, D3DPCMPCAPS, EQUAL); - CAP_CASE(AlphaCmpCaps, D3DPCMPCAPS, GREATER); - CAP_CASE(AlphaCmpCaps, D3DPCMPCAPS, GREATEREQUAL); - CAP_CASE(AlphaCmpCaps, D3DPCMPCAPS, LESS); - CAP_CASE(AlphaCmpCaps, D3DPCMPCAPS, LESSEQUAL); - CAP_CASE(AlphaCmpCaps, D3DPCMPCAPS, NEVER); - CAP_CASE(AlphaCmpCaps, D3DPCMPCAPS, NOTEQUAL); - - C2S("\nShadeCaps:"); - CAP_CASE(ShadeCaps, D3DPSHADECAPS, ALPHAGOURAUDBLEND); - CAP_CASE(ShadeCaps, D3DPSHADECAPS, COLORGOURAUDRGB); - CAP_CASE(ShadeCaps, D3DPSHADECAPS, FOGGOURAUD); - CAP_CASE(ShadeCaps, D3DPSHADECAPS, SPECULARGOURAUDRGB); - - C2S("\nTextureCaps:"); - CAP_CASE(TextureCaps, D3DPTEXTURECAPS, ALPHA); - CAP_CASE(TextureCaps, D3DPTEXTURECAPS, ALPHAPALETTE); - CAP_CASE(TextureCaps, D3DPTEXTURECAPS, CUBEMAP); - CAP_CASE(TextureCaps, D3DPTEXTURECAPS, CUBEMAP_POW2); - CAP_CASE(TextureCaps, D3DPTEXTURECAPS, MIPCUBEMAP); - CAP_CASE(TextureCaps, D3DPTEXTURECAPS, MIPMAP); - CAP_CASE(TextureCaps, D3DPTEXTURECAPS, MIPVOLUMEMAP); - CAP_CASE(TextureCaps, D3DPTEXTURECAPS, NONPOW2CONDITIONAL); - CAP_CASE(TextureCaps, D3DPTEXTURECAPS, NOPROJECTEDBUMPENV); - CAP_CASE(TextureCaps, D3DPTEXTURECAPS, PERSPECTIVE); - CAP_CASE(TextureCaps, D3DPTEXTURECAPS, POW2); - CAP_CASE(TextureCaps, D3DPTEXTURECAPS, PROJECTED); - CAP_CASE(TextureCaps, D3DPTEXTURECAPS, SQUAREONLY); - CAP_CASE(TextureCaps, D3DPTEXTURECAPS, TEXREPEATNOTSCALEDBYSIZE); - CAP_CASE(TextureCaps, D3DPTEXTURECAPS, VOLUMEMAP); - CAP_CASE(TextureCaps, D3DPTEXTURECAPS, VOLUMEMAP_POW2); - - C2S("\nTextureFilterCaps:"); - /* CAP_CASE(TextureFilterCaps, D3DPTFILTERCAPS, CONVOLUTIONMONO); */ - CAP_CASE(TextureFilterCaps, D3DPTFILTERCAPS, MAGFPOINT); - CAP_CASE(TextureFilterCaps, D3DPTFILTERCAPS, MAGFLINEAR); - CAP_CASE(TextureFilterCaps, D3DPTFILTERCAPS, MAGFANISOTROPIC); - CAP_CASE(TextureFilterCaps, D3DPTFILTERCAPS, MAGFPYRAMIDALQUAD); - CAP_CASE(TextureFilterCaps, D3DPTFILTERCAPS, MAGFGAUSSIANQUAD); - CAP_CASE(TextureFilterCaps, D3DPTFILTERCAPS, MINFPOINT); - CAP_CASE(TextureFilterCaps, D3DPTFILTERCAPS, MINFLINEAR); - CAP_CASE(TextureFilterCaps, D3DPTFILTERCAPS, MINFANISOTROPIC); - CAP_CASE(TextureFilterCaps, D3DPTFILTERCAPS, MINFPYRAMIDALQUAD); - CAP_CASE(TextureFilterCaps, D3DPTFILTERCAPS, MINFGAUSSIANQUAD); - CAP_CASE(TextureFilterCaps, D3DPTFILTERCAPS, MIPFPOINT); - CAP_CASE(TextureFilterCaps, D3DPTFILTERCAPS, MIPFLINEAR); - - C2S("\nCubeTextureFilterCaps:"); - /* CAP_CASE(CubeTextureFilterCaps, D3DPTFILTERCAPS, CONVOLUTIONMONO); */ - CAP_CASE(CubeTextureFilterCaps, D3DPTFILTERCAPS, MAGFPOINT); - CAP_CASE(CubeTextureFilterCaps, D3DPTFILTERCAPS, MAGFLINEAR); - CAP_CASE(CubeTextureFilterCaps, D3DPTFILTERCAPS, MAGFANISOTROPIC); - CAP_CASE(CubeTextureFilterCaps, D3DPTFILTERCAPS, MAGFPYRAMIDALQUAD); - CAP_CASE(CubeTextureFilterCaps, D3DPTFILTERCAPS, MAGFGAUSSIANQUAD); - CAP_CASE(CubeTextureFilterCaps, D3DPTFILTERCAPS, MINFPOINT); - CAP_CASE(CubeTextureFilterCaps, D3DPTFILTERCAPS, MINFLINEAR); - CAP_CASE(CubeTextureFilterCaps, D3DPTFILTERCAPS, MINFANISOTROPIC); - CAP_CASE(CubeTextureFilterCaps, D3DPTFILTERCAPS, MINFPYRAMIDALQUAD); - CAP_CASE(CubeTextureFilterCaps, D3DPTFILTERCAPS, MINFGAUSSIANQUAD); - CAP_CASE(CubeTextureFilterCaps, D3DPTFILTERCAPS, MIPFPOINT); - CAP_CASE(CubeTextureFilterCaps, D3DPTFILTERCAPS, MIPFLINEAR); - - C2S("\nVolumeTextureFilterCaps:"); - /* CAP_CASE(VolumeTextureFilterCaps, D3DPTFILTERCAPS, CONVOLUTIONMONO); */ - CAP_CASE(VolumeTextureFilterCaps, D3DPTFILTERCAPS, MAGFPOINT); - CAP_CASE(VolumeTextureFilterCaps, D3DPTFILTERCAPS, MAGFLINEAR); - CAP_CASE(VolumeTextureFilterCaps, D3DPTFILTERCAPS, MAGFANISOTROPIC); - CAP_CASE(VolumeTextureFilterCaps, D3DPTFILTERCAPS, MAGFPYRAMIDALQUAD); - CAP_CASE(VolumeTextureFilterCaps, D3DPTFILTERCAPS, MAGFGAUSSIANQUAD); - CAP_CASE(VolumeTextureFilterCaps, D3DPTFILTERCAPS, MINFPOINT); - CAP_CASE(VolumeTextureFilterCaps, D3DPTFILTERCAPS, MINFLINEAR); - CAP_CASE(VolumeTextureFilterCaps, D3DPTFILTERCAPS, MINFANISOTROPIC); - CAP_CASE(VolumeTextureFilterCaps, D3DPTFILTERCAPS, MINFPYRAMIDALQUAD); - CAP_CASE(VolumeTextureFilterCaps, D3DPTFILTERCAPS, MINFGAUSSIANQUAD); - CAP_CASE(VolumeTextureFilterCaps, D3DPTFILTERCAPS, MIPFPOINT); - CAP_CASE(VolumeTextureFilterCaps, D3DPTFILTERCAPS, MIPFLINEAR); - - C2S("\nTextureAddressCaps:"); - CAP_CASE(TextureAddressCaps, D3DPTADDRESSCAPS, BORDER); - CAP_CASE(TextureAddressCaps, D3DPTADDRESSCAPS, CLAMP); - CAP_CASE(TextureAddressCaps, D3DPTADDRESSCAPS, INDEPENDENTUV); - CAP_CASE(TextureAddressCaps, D3DPTADDRESSCAPS, MIRROR); - CAP_CASE(TextureAddressCaps, D3DPTADDRESSCAPS, MIRRORONCE); - CAP_CASE(TextureAddressCaps, D3DPTADDRESSCAPS, WRAP); - - C2S("\nVolumeTextureAddressCaps:"); - CAP_CASE(VolumeTextureAddressCaps, D3DPTADDRESSCAPS, BORDER); - CAP_CASE(VolumeTextureAddressCaps, D3DPTADDRESSCAPS, CLAMP); - CAP_CASE(VolumeTextureAddressCaps, D3DPTADDRESSCAPS, INDEPENDENTUV); - CAP_CASE(VolumeTextureAddressCaps, D3DPTADDRESSCAPS, MIRROR); - CAP_CASE(VolumeTextureAddressCaps, D3DPTADDRESSCAPS, MIRRORONCE); - CAP_CASE(VolumeTextureAddressCaps, D3DPTADDRESSCAPS, WRAP); - - C2S("\nLineCaps:"); - CAP_CASE(LineCaps, D3DLINECAPS, ALPHACMP); - CAP_CASE(LineCaps, D3DLINECAPS, ANTIALIAS); - CAP_CASE(LineCaps, D3DLINECAPS, BLEND); - CAP_CASE(LineCaps, D3DLINECAPS, FOG); - CAP_CASE(LineCaps, D3DLINECAPS, TEXTURE); - CAP_CASE(LineCaps, D3DLINECAPS, ZTEST); - - C2S("\nMaxTextureWidth: %u", caps->MaxTextureWidth); - C2S("\nMaxTextureHeight: %u", caps->MaxTextureHeight); - C2S("\nMaxVolumeExtent: %u", caps->MaxVolumeExtent); - C2S("\nMaxTextureRepeat: %u", caps->MaxTextureRepeat); - C2S("\nMaxTextureAspectRatio: %u", caps->MaxTextureAspectRatio); - C2S("\nMaxAnisotropy: %u", caps->MaxAnisotropy); - C2S("\nMaxVertexW: %f", caps->MaxVertexW); - - C2S("\nGuardBandLef,Top,Right,Bottom: %f %f %f %f", - caps->GuardBandLeft, caps->GuardBandTop, - caps->GuardBandRight, caps->GuardBandBottom); - - C2S("\nExtentsAdjust: %f", caps->ExtentsAdjust); - - C2S("\nStencilCaps:"); - CAP_CASE(StencilCaps, D3DSTENCILCAPS, KEEP); - CAP_CASE(StencilCaps, D3DSTENCILCAPS, ZERO); - CAP_CASE(StencilCaps, D3DSTENCILCAPS, REPLACE); - CAP_CASE(StencilCaps, D3DSTENCILCAPS, INCRSAT); - CAP_CASE(StencilCaps, D3DSTENCILCAPS, DECRSAT); - CAP_CASE(StencilCaps, D3DSTENCILCAPS, INVERT); - CAP_CASE(StencilCaps, D3DSTENCILCAPS, INCR); - CAP_CASE(StencilCaps, D3DSTENCILCAPS, DECR); - CAP_CASE(StencilCaps, D3DSTENCILCAPS, TWOSIDED); - - C2S("\nFVFCaps:"); - CAP_CASE(FVFCaps, D3DFVFCAPS, DONOTSTRIPELEMENTS); - CAP_CASE(FVFCaps, D3DFVFCAPS, PSIZE); - CAP_CASE(FVFCaps, D3DFVFCAPS, TEXCOORDCOUNTMASK); - - C2S("\nTextureOpCaps:"); - CAP_CASE(TextureOpCaps, D3DTEXOPCAPS, ADD); - CAP_CASE(TextureOpCaps, D3DTEXOPCAPS, ADDSIGNED); - C2S(" ..."); - - C2S("\nMaxTextureBlendStages: %u", caps->MaxTextureBlendStages); - C2S("\nMaxSimultaneousTextures: %u", caps->MaxTextureBlendStages); - - C2S("\nVertexProcessingCaps:"); - CAP_CASE(VertexProcessingCaps, D3DVTXPCAPS, DIRECTIONALLIGHTS); - CAP_CASE(VertexProcessingCaps, D3DVTXPCAPS, LOCALVIEWER); - CAP_CASE(VertexProcessingCaps, D3DVTXPCAPS, MATERIALSOURCE7); - CAP_CASE(VertexProcessingCaps, D3DVTXPCAPS, NO_TEXGEN_NONLOCALVIEWER); - CAP_CASE(VertexProcessingCaps, D3DVTXPCAPS, POSITIONALLIGHTS); - CAP_CASE(VertexProcessingCaps, D3DVTXPCAPS, TEXGEN); - CAP_CASE(VertexProcessingCaps, D3DVTXPCAPS, TEXGEN_SPHEREMAP); - CAP_CASE(VertexProcessingCaps, D3DVTXPCAPS, TWEENING); - - C2S("\nMaxActiveLights: %u", caps->MaxActiveLights); - C2S("\nMaxUserClipPlanes: %u", caps->MaxUserClipPlanes); - C2S("\nMaxVertexBlendMatrices: %u", caps->MaxVertexBlendMatrices); - C2S("\nMaxVertexBlendMatrixIndex: %u", caps->MaxVertexBlendMatrixIndex); - C2S("\nMaxPointSize: %f", caps->MaxPointSize); - C2S("\nMaxPrimitiveCount: 0x%x", caps->MaxPrimitiveCount); - C2S("\nMaxVertexIndex: 0x%x", caps->MaxVertexIndex); - C2S("\nMaxStreams: %u", caps->MaxStreams); - C2S("\nMaxStreamStride: 0x%x", caps->MaxStreamStride); - - C2S("\nVertexShaderVersion: %08x", caps->VertexShaderVersion); - C2S("\nMaxVertexShaderConst: %u", caps->MaxVertexShaderConst); - C2S("\nPixelShaderVersion: %08x", caps->PixelShaderVersion); - C2S("\nPixelShader1xMaxValue: %f", caps->PixelShader1xMaxValue); - - DBG_FLAG(ch, "D3DCAPS9(%p) part 1:\n%s\n", caps, s); - p = 0; - - C2S("DevCaps2:"); - CAP_CASE(DevCaps2, D3DDEVCAPS2, ADAPTIVETESSRTPATCH); - CAP_CASE(DevCaps2, D3DDEVCAPS2, ADAPTIVETESSNPATCH); - CAP_CASE(DevCaps2, D3DDEVCAPS2, CAN_STRETCHRECT_FROM_TEXTURES); - CAP_CASE(DevCaps2, D3DDEVCAPS2, DMAPNPATCH); - CAP_CASE(DevCaps2, D3DDEVCAPS2, PRESAMPLEDDMAPNPATCH); - CAP_CASE(DevCaps2, D3DDEVCAPS2, STREAMOFFSET); - CAP_CASE(DevCaps2, D3DDEVCAPS2, VERTEXELEMENTSCANSHARESTREAMOFFSET); - - C2S("\nMasterAdapterOrdinal: %u", caps->MasterAdapterOrdinal); - C2S("\nAdapterOrdinalInGroup: %u", caps->AdapterOrdinalInGroup); - C2S("\nNumberOfAdaptersInGroup: %u", caps->NumberOfAdaptersInGroup); - - C2S("\nDeclTypes:"); - CAP_CASE(DeclTypes, D3DDTCAPS, UBYTE4); - CAP_CASE(DeclTypes, D3DDTCAPS, UBYTE4N); - CAP_CASE(DeclTypes, D3DDTCAPS, SHORT2N); - CAP_CASE(DeclTypes, D3DDTCAPS, SHORT4N); - CAP_CASE(DeclTypes, D3DDTCAPS, USHORT2N); - CAP_CASE(DeclTypes, D3DDTCAPS, USHORT4N); - CAP_CASE(DeclTypes, D3DDTCAPS, UDEC3); - CAP_CASE(DeclTypes, D3DDTCAPS, DEC3N); - CAP_CASE(DeclTypes, D3DDTCAPS, FLOAT16_2); - CAP_CASE(DeclTypes, D3DDTCAPS, FLOAT16_4); - - C2S("\nNumSimultaneousRTs: %u", caps->NumSimultaneousRTs); - - C2S("\nStretchRectFilterCaps:"); - CAP_CASE(StretchRectFilterCaps, D3DPTFILTERCAPS, MINFPOINT); - CAP_CASE(StretchRectFilterCaps, D3DPTFILTERCAPS, MINFLINEAR); - CAP_CASE(StretchRectFilterCaps, D3DPTFILTERCAPS, MAGFPOINT); - CAP_CASE(StretchRectFilterCaps, D3DPTFILTERCAPS, MAGFLINEAR); - - C2S("\nVS20Caps.Caps: Predication=%s", caps->VS20Caps.Caps ? "yes" : "no"); - C2S("\nVS20Caps.DynamicFlowControlDepth: %u", caps->VS20Caps.DynamicFlowControlDepth); - C2S("\nVS20Caps.NumTemps: %u", caps->VS20Caps.NumTemps); - C2S("\nVS20Caps.StaticFlowControlDepth: %u", caps->VS20Caps.StaticFlowControlDepth); - - C2S("\nPS20Caps.Caps: Predication=%s", caps->VS20Caps.Caps ? "yes" : "no"); - C2S("\nPS20Caps.DynamicFlowControlDepth: %u", caps->PS20Caps.DynamicFlowControlDepth); - C2S("\nPS20Caps.NumTemps: %u", caps->PS20Caps.NumTemps); - C2S("\nPS20Caps.StaticFlowControlDepth: %u", caps->PS20Caps.StaticFlowControlDepth); - C2S("\nPS20Caps.NumInstructionSlots: %u", caps->PS20Caps.NumInstructionSlots); - - C2S("\nVertexTextureFilterCaps"); - /* CAP_CASE(VertexTextureFilterCaps, D3DPTFILTERCAPS, CONVOLUTIONMONO); */ - CAP_CASE(VertexTextureFilterCaps, D3DPTFILTERCAPS, MAGFPOINT); - CAP_CASE(VertexTextureFilterCaps, D3DPTFILTERCAPS, MAGFLINEAR); - CAP_CASE(VertexTextureFilterCaps, D3DPTFILTERCAPS, MAGFANISOTROPIC); - CAP_CASE(VertexTextureFilterCaps, D3DPTFILTERCAPS, MAGFPYRAMIDALQUAD); - CAP_CASE(VertexTextureFilterCaps, D3DPTFILTERCAPS, MAGFGAUSSIANQUAD); - CAP_CASE(VertexTextureFilterCaps, D3DPTFILTERCAPS, MINFPOINT); - CAP_CASE(VertexTextureFilterCaps, D3DPTFILTERCAPS, MINFLINEAR); - CAP_CASE(VertexTextureFilterCaps, D3DPTFILTERCAPS, MINFANISOTROPIC); - CAP_CASE(VertexTextureFilterCaps, D3DPTFILTERCAPS, MINFPYRAMIDALQUAD); - CAP_CASE(VertexTextureFilterCaps, D3DPTFILTERCAPS, MINFGAUSSIANQUAD); - CAP_CASE(VertexTextureFilterCaps, D3DPTFILTERCAPS, MIPFPOINT); - CAP_CASE(VertexTextureFilterCaps, D3DPTFILTERCAPS, MIPFLINEAR); - - C2S("\nMaxVShaderInstructionsExecuted: %u", caps->MaxVShaderInstructionsExecuted); - C2S("\nMaxPShaderInstructionsExecuted: %u", caps->MaxPShaderInstructionsExecuted); - C2S("\nMaxVertexShader30InstructionSlots: %u >= 512", caps->MaxVertexShader30InstructionSlots); - C2S("\nMaxPixelShader30InstructionSlots: %u >= 512", caps->MaxPixelShader30InstructionSlots); - - DBG_FLAG(ch, "D3DCAPS9(%p) part 2:\n%s\n", caps, s); - - FREE(s); -} - -#endif /* DEBUG || !NDEBUG */ diff --git a/src/gallium/state_trackers/nine/nine_dump.h b/src/gallium/state_trackers/nine/nine_dump.h deleted file mode 100644 index 72342557d77..00000000000 --- a/src/gallium/state_trackers/nine/nine_dump.h +++ /dev/null @@ -1,52 +0,0 @@ - -#ifndef _NINE_DUMP_H_ -#define _NINE_DUMP_H_ - -#include "d3d9types.h" -#include "d3d9caps.h" - -const char *nine_D3DDEVTYPE_to_str(D3DDEVTYPE); -const char *nine_D3DQUERYTYPE_to_str(D3DQUERYTYPE); -const char *nine_D3DTSS_to_str(D3DTEXTURESTAGESTATETYPE); -const char *nine_D3DTOP_to_str(D3DTEXTUREOP); -const char *nine_D3DPOOL_to_str(D3DPOOL); -const char *nine_D3DRTYPE_to_str(D3DRESOURCETYPE); -const char *nine_D3DUSAGE_to_str(DWORD); -const char *nine_D3DPRESENTFLAG_to_str(DWORD); -const char *nine_D3DLOCK_to_str(DWORD); -const char *nine_D3DSAMP_to_str(DWORD); - -#if defined(DEBUG) || !defined(NDEBUG) - -void -nine_dump_D3DADAPTER_IDENTIFIER9(unsigned, const D3DADAPTER_IDENTIFIER9 *); -void -nine_dump_D3DCAPS9(unsigned, const D3DCAPS9 *); -void -nine_dump_D3DLIGHT9(unsigned, const D3DLIGHT9 *); -void -nine_dump_D3DMATERIAL9(unsigned, const D3DMATERIAL9 *); -void -nine_dump_D3DTSS_value(unsigned, D3DTEXTURESTAGESTATETYPE, DWORD); - -#else /* !DEBUG && NDEBUG */ - -static inline void -nine_dump_D3DADAPTER_IDENTIFIER9(unsigned ch, const D3DADAPTER_IDENTIFIER9 *id) -{ } -static inline void -nine_dump_D3DCAPS9(unsigned ch, const D3DCAPS9 *caps) -{ } -static inline void -nine_dump_D3DLIGHT9(unsigned ch, const D3DLIGHT9 *light) -{ } -static inline void -nine_dump_D3DMATERIAL9(unsigned ch, const D3DMATERIAL9 *mat) -{ } -static inline void -nine_dump_D3DTSS_value(unsigned ch, D3DTEXTURESTAGESTATETYPE tss, DWORD value) -{ } - -#endif /* DEBUG || !NDEBUG */ - -#endif /* _NINE_DUMP_H_H_ */ diff --git a/src/gallium/state_trackers/nine/nine_ff.c b/src/gallium/state_trackers/nine/nine_ff.c deleted file mode 100644 index 16d0ab2ab5c..00000000000 --- a/src/gallium/state_trackers/nine/nine_ff.c +++ /dev/null @@ -1,2500 +0,0 @@ - -/* FF is big and ugly so feel free to write lines as long as you like. - * Aieeeeeeeee ! - * - * Let me make that clearer: - * Aieeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee ! !! !!! - */ - -#include "device9.h" -#include "basetexture9.h" -#include "vertexdeclaration9.h" -#include "vertexshader9.h" -#include "pixelshader9.h" -#include "nine_ff.h" -#include "nine_defines.h" -#include "nine_helpers.h" -#include "nine_pipe.h" -#include "nine_dump.h" - -#include "pipe/p_context.h" -#include "tgsi/tgsi_ureg.h" -#include "tgsi/tgsi_dump.h" -#include "util/u_box.h" -#include "util/u_hash_table.h" -#include "util/u_upload_mgr.h" - -#define DBG_CHANNEL DBG_FF - -#define NINE_FF_NUM_VS_CONST 196 -#define NINE_FF_NUM_PS_CONST 24 - -struct fvec4 -{ - float x, y, z, w; -}; - -struct nine_ff_vs_key -{ - union { - struct { - uint32_t position_t : 1; - uint32_t lighting : 1; - uint32_t darkness : 1; /* lighting enabled but no active lights */ - uint32_t localviewer : 1; - uint32_t vertexpointsize : 1; - uint32_t pointscale : 1; - uint32_t vertexblend : 3; - uint32_t vertexblend_indexed : 1; - uint32_t vertextween : 1; - uint32_t mtl_diffuse : 2; /* 0 = material, 1 = color1, 2 = color2 */ - uint32_t mtl_ambient : 2; - uint32_t mtl_specular : 2; - uint32_t mtl_emissive : 2; - uint32_t fog_mode : 2; - uint32_t fog_range : 1; - uint32_t color0in_one : 1; - uint32_t color1in_zero : 1; - uint32_t has_normal : 1; - uint32_t fog : 1; - uint32_t normalizenormals : 1; - uint32_t ucp : 1; - uint32_t pad1 : 4; - uint32_t tc_dim_input: 16; /* 8 * 2 bits */ - uint32_t pad2 : 16; - uint32_t tc_dim_output: 24; /* 8 * 3 bits */ - uint32_t pad3 : 8; - uint32_t tc_gen : 24; /* 8 * 3 bits */ - uint32_t pad4 : 8; - uint32_t tc_idx : 24; - uint32_t pad5 : 8; - uint32_t passthrough; - }; - uint64_t value64[3]; /* don't forget to resize VertexShader9.ff_key */ - uint32_t value32[6]; - }; -}; - -/* Texture stage state: - * - * COLOROP D3DTOP 5 bit - * ALPHAOP D3DTOP 5 bit - * COLORARG0 D3DTA 3 bit - * COLORARG1 D3DTA 3 bit - * COLORARG2 D3DTA 3 bit - * ALPHAARG0 D3DTA 3 bit - * ALPHAARG1 D3DTA 3 bit - * ALPHAARG2 D3DTA 3 bit - * RESULTARG D3DTA 1 bit (CURRENT:0 or TEMP:1) - * TEXCOORDINDEX 0 - 7 3 bit - * =========================== - * 32 bit per stage - */ -struct nine_ff_ps_key -{ - union { - struct { - struct { - uint32_t colorop : 5; - uint32_t alphaop : 5; - uint32_t colorarg0 : 3; - uint32_t colorarg1 : 3; - uint32_t colorarg2 : 3; - uint32_t alphaarg0 : 3; - uint32_t alphaarg1 : 3; - uint32_t alphaarg2 : 3; - uint32_t resultarg : 1; /* CURRENT:0 or TEMP:1 */ - uint32_t textarget : 2; /* 1D/2D/3D/CUBE */ - uint32_t pad : 1; - /* that's 32 bit exactly */ - } ts[8]; - uint32_t projected : 16; - uint32_t fog : 1; /* for vFog coming from VS */ - uint32_t fog_mode : 2; - uint32_t fog_source : 1; /* 0: Z, 1: W */ - uint32_t specular : 1; - uint32_t pad1 : 11; /* 9 32-bit words with this */ - uint8_t colorarg_b4[3]; - uint8_t colorarg_b5[3]; - uint8_t alphaarg_b4[3]; /* 11 32-bit words plus a byte */ - uint8_t pad2[3]; - }; - uint64_t value64[6]; /* don't forget to resize PixelShader9.ff_key */ - uint32_t value32[12]; - }; -}; - -static uint32_t nine_ff_vs_key_hash(const void *key) -{ - const struct nine_ff_vs_key *vs = key; - unsigned i; - uint32_t hash = vs->value32[0]; - for (i = 1; i < ARRAY_SIZE(vs->value32); ++i) - hash ^= vs->value32[i]; - return hash; -} -static bool nine_ff_vs_key_comp(const void *key1, const void *key2) -{ - struct nine_ff_vs_key *a = (struct nine_ff_vs_key *)key1; - struct nine_ff_vs_key *b = (struct nine_ff_vs_key *)key2; - - return memcmp(a->value64, b->value64, sizeof(a->value64)) == 0; -} -static uint32_t nine_ff_ps_key_hash(const void *key) -{ - const struct nine_ff_ps_key *ps = key; - unsigned i; - uint32_t hash = ps->value32[0]; - for (i = 1; i < ARRAY_SIZE(ps->value32); ++i) - hash ^= ps->value32[i]; - return hash; -} -static bool nine_ff_ps_key_comp(const void *key1, const void *key2) -{ - struct nine_ff_ps_key *a = (struct nine_ff_ps_key *)key1; - struct nine_ff_ps_key *b = (struct nine_ff_ps_key *)key2; - - return memcmp(a->value64, b->value64, sizeof(a->value64)) == 0; -} -static uint32_t nine_ff_fvf_key_hash(const void *key) -{ - return *(DWORD *)key; -} -static bool nine_ff_fvf_key_comp(const void *key1, const void *key2) -{ - return *(DWORD *)key1 == *(DWORD *)key2; -} - -static void nine_ff_prune_vs(struct NineDevice9 *); -static void nine_ff_prune_ps(struct NineDevice9 *); - -static void nine_ureg_tgsi_dump(struct ureg_program *ureg, boolean override) -{ - if (debug_get_bool_option("NINE_FF_DUMP", FALSE) || override) { - const struct tgsi_token *toks = ureg_get_tokens(ureg, NULL); - tgsi_dump(toks, 0); - ureg_free_tokens(toks); - } -} - -#define _X(r) ureg_scalar(ureg_src(r), TGSI_SWIZZLE_X) -#define _Y(r) ureg_scalar(ureg_src(r), TGSI_SWIZZLE_Y) -#define _Z(r) ureg_scalar(ureg_src(r), TGSI_SWIZZLE_Z) -#define _W(r) ureg_scalar(ureg_src(r), TGSI_SWIZZLE_W) - -#define _XXXX(r) ureg_scalar(r, TGSI_SWIZZLE_X) -#define _YYYY(r) ureg_scalar(r, TGSI_SWIZZLE_Y) -#define _ZZZZ(r) ureg_scalar(r, TGSI_SWIZZLE_Z) -#define _WWWW(r) ureg_scalar(r, TGSI_SWIZZLE_W) - -#define _XYZW(r) (r) - -/* AL should contain base address of lights table. */ -#define LIGHT_CONST(i) \ - ureg_src_indirect(ureg_DECL_constant(ureg, i), _X(AL)) - -#define MATERIAL_CONST(i) \ - ureg_DECL_constant(ureg, 19 + (i)) - -#define _CONST(n) ureg_DECL_constant(ureg, n) - -/* VS FF constants layout: - * - * CONST[ 0.. 3] D3DTS_WORLD * D3DTS_VIEW * D3DTS_PROJECTION - * CONST[ 4.. 7] D3DTS_WORLD * D3DTS_VIEW - * CONST[ 8..11] D3DTS_PROJECTION - * CONST[12..15] D3DTS_VIEW^(-1) - * CONST[16..18] Normal matrix - * - * CONST[19].xyz MATERIAL.Emissive + Material.Ambient * RS.Ambient - * CONST[20] MATERIAL.Diffuse - * CONST[21] MATERIAL.Ambient - * CONST[22] MATERIAL.Specular - * CONST[23].x___ MATERIAL.Power - * CONST[24] MATERIAL.Emissive - * CONST[25] RS.Ambient - * - * CONST[26].x___ RS.PointSizeMin - * CONST[26]._y__ RS.PointSizeMax - * CONST[26].__z_ RS.PointSize - * CONST[26].___w RS.PointScaleA - * CONST[27].x___ RS.PointScaleB - * CONST[27]._y__ RS.PointScaleC - * - * CONST[28].x___ RS.FogEnd - * CONST[28]._y__ 1.0f / (RS.FogEnd - RS.FogStart) - * CONST[28].__z_ RS.FogDensity - - * CONST[30].x___ TWEENFACTOR - * - * CONST[32].x___ LIGHT[0].Type - * CONST[32]._yzw LIGHT[0].Attenuation0,1,2 - * CONST[33] LIGHT[0].Diffuse - * CONST[34] LIGHT[0].Specular - * CONST[35] LIGHT[0].Ambient - * CONST[36].xyz_ LIGHT[0].Position - * CONST[36].___w LIGHT[0].Range - * CONST[37].xyz_ LIGHT[0].Direction - * CONST[37].___w LIGHT[0].Falloff - * CONST[38].x___ cos(LIGHT[0].Theta / 2) - * CONST[38]._y__ cos(LIGHT[0].Phi / 2) - * CONST[38].__z_ 1.0f / (cos(LIGHT[0].Theta / 2) - cos(Light[0].Phi / 2)) - * CONST[39].xyz_ LIGHT[0].HalfVector (for directional lights) - * CONST[39].___w 1 if this is the last active light, 0 if not - * CONST[40] LIGHT[1] - * CONST[48] LIGHT[2] - * CONST[56] LIGHT[3] - * CONST[64] LIGHT[4] - * CONST[72] LIGHT[5] - * CONST[80] LIGHT[6] - * CONST[88] LIGHT[7] - * NOTE: no lighting code is generated if there are no active lights - * - * CONST[100].x___ Viewport 2/width - * CONST[100]._y__ Viewport 2/height - * CONST[100].__z_ Viewport 1/(zmax - zmin) - * CONST[100].___w Viewport width - * CONST[101].x___ Viewport x0 - * CONST[101]._y__ Viewport y0 - * CONST[101].__z_ Viewport z0 - * - * CONST[128..131] D3DTS_TEXTURE0 - * CONST[132..135] D3DTS_TEXTURE1 - * CONST[136..139] D3DTS_TEXTURE2 - * CONST[140..143] D3DTS_TEXTURE3 - * CONST[144..147] D3DTS_TEXTURE4 - * CONST[148..151] D3DTS_TEXTURE5 - * CONST[152..155] D3DTS_TEXTURE6 - * CONST[156..159] D3DTS_TEXTURE7 - * - * CONST[160] D3DTS_WORLDMATRIX[0] * D3DTS_VIEW - * CONST[164] D3DTS_WORLDMATRIX[1] * D3DTS_VIEW - * ... - * CONST[192] D3DTS_WORLDMATRIX[8] * D3DTS_VIEW - */ -struct vs_build_ctx -{ - struct ureg_program *ureg; - const struct nine_ff_vs_key *key; - - uint16_t input[PIPE_MAX_ATTRIBS]; - unsigned num_inputs; - - struct ureg_src aVtx; - struct ureg_src aNrm; - struct ureg_src aCol[2]; - struct ureg_src aTex[8]; - struct ureg_src aPsz; - struct ureg_src aInd; - struct ureg_src aWgt; - - struct ureg_src aVtx1; /* tweening */ - struct ureg_src aNrm1; - - struct ureg_src mtlA; - struct ureg_src mtlD; - struct ureg_src mtlS; - struct ureg_src mtlE; -}; - -static inline unsigned -get_texcoord_sn(struct pipe_screen *screen) -{ - if (screen->get_param(screen, PIPE_CAP_TGSI_TEXCOORD)) - return TGSI_SEMANTIC_TEXCOORD; - return TGSI_SEMANTIC_GENERIC; -} - -static inline struct ureg_src -build_vs_add_input(struct vs_build_ctx *vs, uint16_t ndecl) -{ - const unsigned i = vs->num_inputs++; - assert(i < PIPE_MAX_ATTRIBS); - vs->input[i] = ndecl; - return ureg_DECL_vs_input(vs->ureg, i); -} - -/* NOTE: dst may alias src */ -static inline void -ureg_normalize3(struct ureg_program *ureg, - struct ureg_dst dst, struct ureg_src src) -{ - struct ureg_dst tmp = ureg_DECL_temporary(ureg); - struct ureg_dst tmp_x = ureg_writemask(tmp, TGSI_WRITEMASK_X); - - ureg_DP3(ureg, tmp_x, src, src); - ureg_RSQ(ureg, tmp_x, _X(tmp)); - ureg_MUL(ureg, dst, src, _X(tmp)); - ureg_release_temporary(ureg, tmp); -} - -static void * -nine_ff_build_vs(struct NineDevice9 *device, struct vs_build_ctx *vs) -{ - const struct nine_ff_vs_key *key = vs->key; - struct ureg_program *ureg = ureg_create(PIPE_SHADER_VERTEX); - struct ureg_dst oPos, oCol[2], oPsz, oFog; - struct ureg_dst AR; - unsigned i, c; - unsigned label[32], l = 0; - boolean need_aNrm = key->lighting || key->passthrough & (1 << NINE_DECLUSAGE_NORMAL); - boolean has_aNrm = need_aNrm && key->has_normal; - boolean need_aVtx = key->lighting || key->fog_mode || key->pointscale || key->ucp; - const unsigned texcoord_sn = get_texcoord_sn(device->screen); - - vs->ureg = ureg; - - /* Check which inputs we should transform. */ - for (i = 0; i < 8 * 3; i += 3) { - switch ((key->tc_gen >> i) & 0x7) { - case NINED3DTSS_TCI_CAMERASPACENORMAL: - need_aNrm = TRUE; - break; - case NINED3DTSS_TCI_CAMERASPACEPOSITION: - need_aVtx = TRUE; - break; - case NINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR: - need_aVtx = need_aNrm = TRUE; - break; - case NINED3DTSS_TCI_SPHEREMAP: - need_aVtx = need_aNrm = TRUE; - break; - default: - break; - } - } - - /* Declare and record used inputs (needed for linkage with vertex format): - * (texture coordinates handled later) - */ - vs->aVtx = build_vs_add_input(vs, - key->position_t ? NINE_DECLUSAGE_POSITIONT : NINE_DECLUSAGE_POSITION); - - vs->aNrm = ureg_imm1f(ureg, 0.0f); - if (has_aNrm) - vs->aNrm = build_vs_add_input(vs, NINE_DECLUSAGE_NORMAL); - - vs->aCol[0] = ureg_imm1f(ureg, 1.0f); - vs->aCol[1] = ureg_imm1f(ureg, 0.0f); - - if (key->lighting || key->darkness) { - const unsigned mask = key->mtl_diffuse | key->mtl_specular | - key->mtl_ambient | key->mtl_emissive; - if ((mask & 0x1) && !key->color0in_one) - vs->aCol[0] = build_vs_add_input(vs, NINE_DECLUSAGE_i(COLOR, 0)); - if ((mask & 0x2) && !key->color1in_zero) - vs->aCol[1] = build_vs_add_input(vs, NINE_DECLUSAGE_i(COLOR, 1)); - - vs->mtlD = MATERIAL_CONST(1); - vs->mtlA = MATERIAL_CONST(2); - vs->mtlS = MATERIAL_CONST(3); - vs->mtlE = MATERIAL_CONST(5); - if (key->mtl_diffuse == 1) vs->mtlD = vs->aCol[0]; else - if (key->mtl_diffuse == 2) vs->mtlD = vs->aCol[1]; - if (key->mtl_ambient == 1) vs->mtlA = vs->aCol[0]; else - if (key->mtl_ambient == 2) vs->mtlA = vs->aCol[1]; - if (key->mtl_specular == 1) vs->mtlS = vs->aCol[0]; else - if (key->mtl_specular == 2) vs->mtlS = vs->aCol[1]; - if (key->mtl_emissive == 1) vs->mtlE = vs->aCol[0]; else - if (key->mtl_emissive == 2) vs->mtlE = vs->aCol[1]; - } else { - if (!key->color0in_one) vs->aCol[0] = build_vs_add_input(vs, NINE_DECLUSAGE_i(COLOR, 0)); - if (!key->color1in_zero) vs->aCol[1] = build_vs_add_input(vs, NINE_DECLUSAGE_i(COLOR, 1)); - } - - if (key->vertexpointsize) - vs->aPsz = build_vs_add_input(vs, NINE_DECLUSAGE_PSIZE); - - if (key->vertexblend_indexed || key->passthrough & (1 << NINE_DECLUSAGE_BLENDINDICES)) - vs->aInd = build_vs_add_input(vs, NINE_DECLUSAGE_BLENDINDICES); - if (key->vertexblend || key->passthrough & (1 << NINE_DECLUSAGE_BLENDWEIGHT)) - vs->aWgt = build_vs_add_input(vs, NINE_DECLUSAGE_BLENDWEIGHT); - if (key->vertextween) { - vs->aVtx1 = build_vs_add_input(vs, NINE_DECLUSAGE_i(POSITION,1)); - vs->aNrm1 = build_vs_add_input(vs, NINE_DECLUSAGE_i(NORMAL,1)); - } - - /* Declare outputs: - */ - oPos = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0); /* HPOS */ - oCol[0] = ureg_saturate(ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0)); - oCol[1] = ureg_saturate(ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 1)); - if (key->fog || key->passthrough & (1 << NINE_DECLUSAGE_FOG)) { - oFog = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 16); - oFog = ureg_writemask(oFog, TGSI_WRITEMASK_X); - } - - if (key->vertexpointsize || key->pointscale) { - oPsz = ureg_DECL_output_masked(ureg, TGSI_SEMANTIC_PSIZE, 0, - TGSI_WRITEMASK_X, 0, 1); - oPsz = ureg_writemask(oPsz, TGSI_WRITEMASK_X); - } - - if (key->lighting || key->vertexblend) - AR = ureg_DECL_address(ureg); - - /* === Vertex transformation / vertex blending: - */ - - if (key->position_t) { - if (device->driver_caps.window_space_position_support) { - ureg_MOV(ureg, oPos, vs->aVtx); - } else { - struct ureg_dst tmp = ureg_DECL_temporary(ureg); - /* vs->aVtx contains the coordinates buffer wise. - * later in the pipeline, clipping, viewport and division - * by w (rhw = 1/w) are going to be applied, so do the reverse - * of these transformations (except clipping) to have the good - * position at the end.*/ - ureg_MOV(ureg, tmp, vs->aVtx); - /* X from [X_min, X_min + width] to [-1, 1], same for Y. Z to [0, 1] */ - ureg_ADD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XYZ), ureg_src(tmp), ureg_negate(_CONST(101))); - ureg_MUL(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XYZ), ureg_src(tmp), _CONST(100)); - ureg_ADD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XY), ureg_src(tmp), ureg_imm1f(ureg, -1.0f)); - /* Y needs to be reversed */ - ureg_MOV(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Y), ureg_negate(ureg_src(tmp))); - /* inverse rhw */ - ureg_RCP(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_W), _W(tmp)); - /* multiply X, Y, Z by w */ - ureg_MUL(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XYZ), ureg_src(tmp), _W(tmp)); - ureg_MOV(ureg, oPos, ureg_src(tmp)); - ureg_release_temporary(ureg, tmp); - } - } else if (key->vertexblend) { - struct ureg_dst tmp = ureg_DECL_temporary(ureg); - struct ureg_dst tmp2 = ureg_DECL_temporary(ureg); - struct ureg_dst aVtx_dst = ureg_DECL_temporary(ureg); - struct ureg_dst aNrm_dst = ureg_DECL_temporary(ureg); - struct ureg_dst sum_blendweights = ureg_DECL_temporary(ureg); - struct ureg_src cWM[4]; - - for (i = 160; i <= 195; ++i) - ureg_DECL_constant(ureg, i); - - /* translate world matrix index to constant file index */ - if (key->vertexblend_indexed) { - ureg_MAD(ureg, tmp, vs->aInd, ureg_imm1f(ureg, 4.0f), ureg_imm1f(ureg, 160.0f)); - ureg_ARL(ureg, AR, ureg_src(tmp)); - } - - ureg_MOV(ureg, aVtx_dst, ureg_imm4f(ureg, 0.0f, 0.0f, 0.0f, 0.0f)); - ureg_MOV(ureg, aNrm_dst, ureg_imm4f(ureg, 0.0f, 0.0f, 0.0f, 0.0f)); - ureg_MOV(ureg, sum_blendweights, ureg_imm4f(ureg, 1.0f, 1.0f, 1.0f, 1.0f)); - - for (i = 0; i < key->vertexblend; ++i) { - for (c = 0; c < 4; ++c) { - cWM[c] = ureg_src_dimension(ureg_src_register(TGSI_FILE_CONSTANT, (160 + i * 4) * !key->vertexblend_indexed + c), 0); - if (key->vertexblend_indexed) - cWM[c] = ureg_src_indirect(cWM[c], ureg_scalar(ureg_src(AR), i)); - } - - /* multiply by WORLD(index) */ - ureg_MUL(ureg, tmp, _XXXX(vs->aVtx), cWM[0]); - ureg_MAD(ureg, tmp, _YYYY(vs->aVtx), cWM[1], ureg_src(tmp)); - ureg_MAD(ureg, tmp, _ZZZZ(vs->aVtx), cWM[2], ureg_src(tmp)); - ureg_MAD(ureg, tmp, _WWWW(vs->aVtx), cWM[3], ureg_src(tmp)); - - if (has_aNrm) { - /* Note: the spec says the transpose of the inverse of the - * WorldView matrices should be used, but all tests show - * otherwise. - * Only case unknown: D3DVBF_0WEIGHTS */ - ureg_MUL(ureg, tmp2, _XXXX(vs->aNrm), cWM[0]); - ureg_MAD(ureg, tmp2, _YYYY(vs->aNrm), cWM[1], ureg_src(tmp2)); - ureg_MAD(ureg, tmp2, _ZZZZ(vs->aNrm), cWM[2], ureg_src(tmp2)); - } - - if (i < (key->vertexblend - 1)) { - /* accumulate weighted position value */ - ureg_MAD(ureg, aVtx_dst, ureg_src(tmp), ureg_scalar(vs->aWgt, i), ureg_src(aVtx_dst)); - if (has_aNrm) - ureg_MAD(ureg, aNrm_dst, ureg_src(tmp2), ureg_scalar(vs->aWgt, i), ureg_src(aNrm_dst)); - /* subtract weighted position value for last value */ - ureg_ADD(ureg, sum_blendweights, ureg_src(sum_blendweights), ureg_negate(ureg_scalar(vs->aWgt, i))); - } - } - - /* the last weighted position is always 1 - sum_of_previous_weights */ - ureg_MAD(ureg, aVtx_dst, ureg_src(tmp), ureg_scalar(ureg_src(sum_blendweights), key->vertexblend - 1), ureg_src(aVtx_dst)); - if (has_aNrm) - ureg_MAD(ureg, aNrm_dst, ureg_src(tmp2), ureg_scalar(ureg_src(sum_blendweights), key->vertexblend - 1), ureg_src(aNrm_dst)); - - /* multiply by VIEW_PROJ */ - ureg_MUL(ureg, tmp, _X(aVtx_dst), _CONST(8)); - ureg_MAD(ureg, tmp, _Y(aVtx_dst), _CONST(9), ureg_src(tmp)); - ureg_MAD(ureg, tmp, _Z(aVtx_dst), _CONST(10), ureg_src(tmp)); - ureg_MAD(ureg, oPos, _W(aVtx_dst), _CONST(11), ureg_src(tmp)); - - if (need_aVtx) - vs->aVtx = ureg_src(aVtx_dst); - - ureg_release_temporary(ureg, tmp); - ureg_release_temporary(ureg, tmp2); - ureg_release_temporary(ureg, sum_blendweights); - if (!need_aVtx) - ureg_release_temporary(ureg, aVtx_dst); - - if (has_aNrm) { - if (key->normalizenormals) - ureg_normalize3(ureg, aNrm_dst, ureg_src(aNrm_dst)); - vs->aNrm = ureg_src(aNrm_dst); - } else - ureg_release_temporary(ureg, aNrm_dst); - } else { - struct ureg_dst tmp = ureg_DECL_temporary(ureg); - - if (key->vertextween) { - struct ureg_dst aVtx_dst = ureg_DECL_temporary(ureg); - ureg_LRP(ureg, aVtx_dst, _XXXX(_CONST(30)), vs->aVtx1, vs->aVtx); - vs->aVtx = ureg_src(aVtx_dst); - if (has_aNrm) { - struct ureg_dst aNrm_dst = ureg_DECL_temporary(ureg); - ureg_LRP(ureg, aNrm_dst, _XXXX(_CONST(30)), vs->aNrm1, vs->aNrm); - vs->aNrm = ureg_src(aNrm_dst); - } - } - - /* position = vertex * WORLD_VIEW_PROJ */ - ureg_MUL(ureg, tmp, _XXXX(vs->aVtx), _CONST(0)); - ureg_MAD(ureg, tmp, _YYYY(vs->aVtx), _CONST(1), ureg_src(tmp)); - ureg_MAD(ureg, tmp, _ZZZZ(vs->aVtx), _CONST(2), ureg_src(tmp)); - ureg_MAD(ureg, oPos, _WWWW(vs->aVtx), _CONST(3), ureg_src(tmp)); - ureg_release_temporary(ureg, tmp); - - if (need_aVtx) { - struct ureg_dst aVtx_dst = ureg_writemask(ureg_DECL_temporary(ureg), TGSI_WRITEMASK_XYZ); - ureg_MUL(ureg, aVtx_dst, _XXXX(vs->aVtx), _CONST(4)); - ureg_MAD(ureg, aVtx_dst, _YYYY(vs->aVtx), _CONST(5), ureg_src(aVtx_dst)); - ureg_MAD(ureg, aVtx_dst, _ZZZZ(vs->aVtx), _CONST(6), ureg_src(aVtx_dst)); - ureg_MAD(ureg, aVtx_dst, _WWWW(vs->aVtx), _CONST(7), ureg_src(aVtx_dst)); - vs->aVtx = ureg_src(aVtx_dst); - } - if (has_aNrm) { - struct ureg_dst aNrm_dst = ureg_writemask(ureg_DECL_temporary(ureg), TGSI_WRITEMASK_XYZ); - ureg_MUL(ureg, aNrm_dst, _XXXX(vs->aNrm), _CONST(16)); - ureg_MAD(ureg, aNrm_dst, _YYYY(vs->aNrm), _CONST(17), ureg_src(aNrm_dst)); - ureg_MAD(ureg, aNrm_dst, _ZZZZ(vs->aNrm), _CONST(18), ureg_src(aNrm_dst)); - if (key->normalizenormals) - ureg_normalize3(ureg, aNrm_dst, ureg_src(aNrm_dst)); - vs->aNrm = ureg_src(aNrm_dst); - } - } - - /* === Process point size: - */ - if (key->vertexpointsize || key->pointscale) { - struct ureg_dst tmp = ureg_DECL_temporary(ureg); - struct ureg_dst tmp_x = ureg_writemask(tmp, TGSI_WRITEMASK_X); - struct ureg_dst tmp_y = ureg_writemask(tmp, TGSI_WRITEMASK_Y); - struct ureg_dst tmp_z = ureg_writemask(tmp, TGSI_WRITEMASK_Z); - if (key->vertexpointsize) { - struct ureg_src cPsz1 = ureg_DECL_constant(ureg, 26); - ureg_MAX(ureg, tmp_z, _XXXX(vs->aPsz), _XXXX(cPsz1)); - ureg_MIN(ureg, tmp_z, _Z(tmp), _YYYY(cPsz1)); - } else { - struct ureg_src cPsz1 = ureg_DECL_constant(ureg, 26); - ureg_MOV(ureg, tmp_z, _ZZZZ(cPsz1)); - } - - if (key->pointscale) { - struct ureg_src cPsz1 = ureg_DECL_constant(ureg, 26); - struct ureg_src cPsz2 = ureg_DECL_constant(ureg, 27); - - ureg_DP3(ureg, tmp_x, vs->aVtx, vs->aVtx); - ureg_RSQ(ureg, tmp_y, _X(tmp)); - ureg_MUL(ureg, tmp_y, _Y(tmp), _X(tmp)); - ureg_CMP(ureg, tmp_y, ureg_negate(_Y(tmp)), _Y(tmp), ureg_imm1f(ureg, 0.0f)); - ureg_MAD(ureg, tmp_x, _Y(tmp), _YYYY(cPsz2), _XXXX(cPsz2)); - ureg_MAD(ureg, tmp_x, _Y(tmp), _X(tmp), _WWWW(cPsz1)); - ureg_RSQ(ureg, tmp_x, _X(tmp)); - ureg_MUL(ureg, tmp_x, _X(tmp), _Z(tmp)); - ureg_MUL(ureg, tmp_x, _X(tmp), _WWWW(_CONST(100))); - ureg_MAX(ureg, tmp_x, _X(tmp), _XXXX(cPsz1)); - ureg_MIN(ureg, tmp_z, _X(tmp), _YYYY(cPsz1)); - } - - ureg_MOV(ureg, oPsz, _Z(tmp)); - ureg_release_temporary(ureg, tmp); - } - - for (i = 0; i < 8; ++i) { - struct ureg_dst tmp, tmp_x, tmp2; - struct ureg_dst oTex, input_coord, transformed, t, aVtx_normed; - unsigned c, writemask; - const unsigned tci = (key->tc_gen >> (i * 3)) & 0x7; - const unsigned idx = (key->tc_idx >> (i * 3)) & 0x7; - unsigned dim_input = 1 + ((key->tc_dim_input >> (i * 2)) & 0x3); - const unsigned dim_output = (key->tc_dim_output >> (i * 3)) & 0x7; - - /* No texture output of index s */ - if (tci == NINED3DTSS_TCI_DISABLE) - continue; - oTex = ureg_DECL_output(ureg, texcoord_sn, i); - tmp = ureg_DECL_temporary(ureg); - tmp_x = ureg_writemask(tmp, TGSI_WRITEMASK_X); - input_coord = ureg_DECL_temporary(ureg); - transformed = ureg_DECL_temporary(ureg); - - /* Get the coordinate */ - switch (tci) { - case NINED3DTSS_TCI_PASSTHRU: - /* NINED3DTSS_TCI_PASSTHRU => Use texcoord coming from index idx * - * Else the idx is used only to determine wrapping mode. */ - vs->aTex[idx] = build_vs_add_input(vs, NINE_DECLUSAGE_i(TEXCOORD,idx)); - ureg_MOV(ureg, input_coord, vs->aTex[idx]); - break; - case NINED3DTSS_TCI_CAMERASPACENORMAL: - ureg_MOV(ureg, ureg_writemask(input_coord, TGSI_WRITEMASK_XYZ), vs->aNrm); - ureg_MOV(ureg, ureg_writemask(input_coord, TGSI_WRITEMASK_W), ureg_imm1f(ureg, 1.0f)); - dim_input = 4; - break; - case NINED3DTSS_TCI_CAMERASPACEPOSITION: - ureg_MOV(ureg, ureg_writemask(input_coord, TGSI_WRITEMASK_XYZ), vs->aVtx); - ureg_MOV(ureg, ureg_writemask(input_coord, TGSI_WRITEMASK_W), ureg_imm1f(ureg, 1.0f)); - dim_input = 4; - break; - case NINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR: - tmp.WriteMask = TGSI_WRITEMASK_XYZ; - aVtx_normed = ureg_DECL_temporary(ureg); - ureg_normalize3(ureg, aVtx_normed, vs->aVtx); - ureg_DP3(ureg, tmp_x, ureg_src(aVtx_normed), vs->aNrm); - ureg_MUL(ureg, tmp, vs->aNrm, _X(tmp)); - ureg_ADD(ureg, tmp, ureg_src(tmp), ureg_src(tmp)); - ureg_ADD(ureg, ureg_writemask(input_coord, TGSI_WRITEMASK_XYZ), ureg_src(aVtx_normed), ureg_negate(ureg_src(tmp))); - ureg_MOV(ureg, ureg_writemask(input_coord, TGSI_WRITEMASK_W), ureg_imm1f(ureg, 1.0f)); - ureg_release_temporary(ureg, aVtx_normed); - dim_input = 4; - tmp.WriteMask = TGSI_WRITEMASK_XYZW; - break; - case NINED3DTSS_TCI_SPHEREMAP: - /* Implement the formula of GL_SPHERE_MAP */ - tmp.WriteMask = TGSI_WRITEMASK_XYZ; - aVtx_normed = ureg_DECL_temporary(ureg); - tmp2 = ureg_DECL_temporary(ureg); - ureg_normalize3(ureg, aVtx_normed, vs->aVtx); - ureg_DP3(ureg, tmp_x, ureg_src(aVtx_normed), vs->aNrm); - ureg_MUL(ureg, tmp, vs->aNrm, _X(tmp)); - ureg_ADD(ureg, tmp, ureg_src(tmp), ureg_src(tmp)); - ureg_ADD(ureg, tmp, ureg_src(aVtx_normed), ureg_negate(ureg_src(tmp))); - /* now tmp = normed(Vtx) - 2 dot3(normed(Vtx), Nrm) Nrm */ - ureg_MOV(ureg, ureg_writemask(tmp2, TGSI_WRITEMASK_XYZ), ureg_src(tmp)); - ureg_MUL(ureg, tmp2, ureg_src(tmp2), ureg_src(tmp2)); - ureg_DP3(ureg, ureg_writemask(tmp2, TGSI_WRITEMASK_X), ureg_src(tmp2), ureg_src(tmp2)); - ureg_RSQ(ureg, ureg_writemask(tmp2, TGSI_WRITEMASK_X), ureg_src(tmp2)); - ureg_MUL(ureg, ureg_writemask(tmp2, TGSI_WRITEMASK_X), ureg_src(tmp2), ureg_imm1f(ureg, 0.5f)); - /* tmp2 = 0.5 / sqrt(tmp.x^2 + tmp.y^2 + (tmp.z+1)^2) - * TODO: z coordinates are a bit different gl vs d3d, should the formula be adapted ? */ - ureg_MUL(ureg, tmp, ureg_src(tmp), _X(tmp2)); - ureg_ADD(ureg, ureg_writemask(input_coord, TGSI_WRITEMASK_XY), ureg_src(tmp), ureg_imm1f(ureg, 0.5f)); - ureg_MOV(ureg, ureg_writemask(input_coord, TGSI_WRITEMASK_ZW), ureg_imm4f(ureg, 0.0f, 0.0f, 0.0f, 1.0f)); - ureg_release_temporary(ureg, aVtx_normed); - ureg_release_temporary(ureg, tmp2); - dim_input = 4; - tmp.WriteMask = TGSI_WRITEMASK_XYZW; - break; - default: - assert(0); - break; - } - - /* Apply the transformation */ - /* dim_output == 0 => do not transform the components. - * XYZRHW also disables transformation */ - if (!dim_output || key->position_t) { - ureg_release_temporary(ureg, transformed); - transformed = input_coord; - writemask = TGSI_WRITEMASK_XYZW; - } else { - for (c = 0; c < dim_output; c++) { - t = ureg_writemask(transformed, 1 << c); - switch (dim_input) { - /* dim_input = 1 2 3: -> we add trailing 1 to input*/ - case 1: ureg_MAD(ureg, t, _X(input_coord), _XXXX(_CONST(128 + i * 4 + c)), _YYYY(_CONST(128 + i * 4 + c))); - break; - case 2: ureg_DP2(ureg, t, ureg_src(input_coord), _CONST(128 + i * 4 + c)); - ureg_ADD(ureg, t, ureg_src(transformed), _ZZZZ(_CONST(128 + i * 4 + c))); - break; - case 3: ureg_DP3(ureg, t, ureg_src(input_coord), _CONST(128 + i * 4 + c)); - ureg_ADD(ureg, t, ureg_src(transformed), _WWWW(_CONST(128 + i * 4 + c))); - break; - case 4: ureg_DP4(ureg, t, ureg_src(input_coord), _CONST(128 + i * 4 + c)); break; - default: - assert(0); - } - } - writemask = (1 << dim_output) - 1; - ureg_release_temporary(ureg, input_coord); - } - - ureg_MOV(ureg, ureg_writemask(oTex, writemask), ureg_src(transformed)); - ureg_release_temporary(ureg, transformed); - ureg_release_temporary(ureg, tmp); - } - - /* === Lighting: - * - * DIRECTIONAL: Light at infinite distance, parallel rays, no attenuation. - * POINT: Finite distance to scene, divergent rays, isotropic, attenuation. - * SPOT: Finite distance, divergent rays, angular dependence, attenuation. - * - * vec3 normal = normalize(in.Normal * NormalMatrix); - * vec3 hitDir = light.direction; - * float atten = 1.0; - * - * if (light.type != DIRECTIONAL) - * { - * vec3 hitVec = light.position - eyeVertex; - * float d = length(hitVec); - * hitDir = hitVec / d; - * atten = 1 / ((light.atten2 * d + light.atten1) * d + light.atten0); - * } - * - * if (light.type == SPOTLIGHT) - * { - * float rho = dp3(-hitVec, light.direction); - * if (rho < cos(light.phi / 2)) - * atten = 0; - * if (rho < cos(light.theta / 2)) - * atten *= pow(some_func(rho), light.falloff); - * } - * - * float nDotHit = dp3_sat(normal, hitVec); - * float powFact = 0.0; - * - * if (nDotHit > 0.0) - * { - * vec3 midVec = normalize(hitDir + eye); - * float nDotMid = dp3_sat(normal, midVec); - * pFact = pow(nDotMid, material.power); - * } - * - * ambient += light.ambient * atten; - * diffuse += light.diffuse * atten * nDotHit; - * specular += light.specular * atten * powFact; - */ - if (key->lighting) { - struct ureg_dst tmp = ureg_DECL_temporary(ureg); - struct ureg_dst tmp_x = ureg_writemask(tmp, TGSI_WRITEMASK_X); - struct ureg_dst tmp_y = ureg_writemask(tmp, TGSI_WRITEMASK_Y); - struct ureg_dst tmp_z = ureg_writemask(tmp, TGSI_WRITEMASK_Z); - struct ureg_dst rAtt = ureg_writemask(ureg_DECL_temporary(ureg), TGSI_WRITEMASK_W); - struct ureg_dst rHit = ureg_writemask(ureg_DECL_temporary(ureg), TGSI_WRITEMASK_XYZ); - struct ureg_dst rMid = ureg_writemask(ureg_DECL_temporary(ureg), TGSI_WRITEMASK_XYZ); - - struct ureg_dst rCtr = ureg_writemask(ureg_DECL_temporary(ureg), TGSI_WRITEMASK_W); - - struct ureg_dst AL = ureg_writemask(AR, TGSI_WRITEMASK_X); - - /* Light.*.Alpha is not used. */ - struct ureg_dst rD = ureg_writemask(ureg_DECL_temporary(ureg), TGSI_WRITEMASK_XYZ); - struct ureg_dst rA = ureg_writemask(ureg_DECL_temporary(ureg), TGSI_WRITEMASK_XYZ); - struct ureg_dst rS = ureg_DECL_temporary(ureg); - - struct ureg_src mtlP = _XXXX(MATERIAL_CONST(4)); - - struct ureg_src cLKind = _XXXX(LIGHT_CONST(0)); - struct ureg_src cLAtt0 = _YYYY(LIGHT_CONST(0)); - struct ureg_src cLAtt1 = _ZZZZ(LIGHT_CONST(0)); - struct ureg_src cLAtt2 = _WWWW(LIGHT_CONST(0)); - struct ureg_src cLColD = _XYZW(LIGHT_CONST(1)); - struct ureg_src cLColS = _XYZW(LIGHT_CONST(2)); - struct ureg_src cLColA = _XYZW(LIGHT_CONST(3)); - struct ureg_src cLPos = _XYZW(LIGHT_CONST(4)); - struct ureg_src cLRng = _WWWW(LIGHT_CONST(4)); - struct ureg_src cLDir = _XYZW(LIGHT_CONST(5)); - struct ureg_src cLFOff = _WWWW(LIGHT_CONST(5)); - struct ureg_src cLTht = _XXXX(LIGHT_CONST(6)); - struct ureg_src cLPhi = _YYYY(LIGHT_CONST(6)); - struct ureg_src cLSDiv = _ZZZZ(LIGHT_CONST(6)); - struct ureg_src cLLast = _WWWW(LIGHT_CONST(7)); - - const unsigned loop_label = l++; - - /* Declare all light constants to allow indirect adressing */ - for (i = 32; i < 96; i++) - ureg_DECL_constant(ureg, i); - - ureg_MOV(ureg, rCtr, ureg_imm1f(ureg, 32.0f)); /* &lightconst(0) */ - ureg_MOV(ureg, rD, ureg_imm1f(ureg, 0.0f)); - ureg_MOV(ureg, rA, ureg_imm1f(ureg, 0.0f)); - ureg_MOV(ureg, rS, ureg_imm1f(ureg, 0.0f)); - - /* loop management */ - ureg_BGNLOOP(ureg, &label[loop_label]); - ureg_ARL(ureg, AL, _W(rCtr)); - - /* if (not DIRECTIONAL light): */ - ureg_SNE(ureg, tmp_x, cLKind, ureg_imm1f(ureg, D3DLIGHT_DIRECTIONAL)); - ureg_MOV(ureg, rHit, ureg_negate(cLDir)); - ureg_MOV(ureg, rAtt, ureg_imm1f(ureg, 1.0f)); - ureg_IF(ureg, _X(tmp), &label[l++]); - { - /* hitDir = light.position - eyeVtx - * d = length(hitDir) - */ - ureg_ADD(ureg, rHit, cLPos, ureg_negate(vs->aVtx)); - ureg_DP3(ureg, tmp_x, ureg_src(rHit), ureg_src(rHit)); - ureg_RSQ(ureg, tmp_y, _X(tmp)); - ureg_MUL(ureg, tmp_x, _X(tmp), _Y(tmp)); /* length */ - - /* att = 1.0 / (light.att0 + (light.att1 + light.att2 * d) * d) */ - ureg_MAD(ureg, rAtt, _X(tmp), cLAtt2, cLAtt1); - ureg_MAD(ureg, rAtt, _X(tmp), _W(rAtt), cLAtt0); - ureg_RCP(ureg, rAtt, _W(rAtt)); - /* cut-off if distance exceeds Light.Range */ - ureg_SLT(ureg, tmp_x, _X(tmp), cLRng); - ureg_MUL(ureg, rAtt, _W(rAtt), _X(tmp)); - } - ureg_fixup_label(ureg, label[l-1], ureg_get_instruction_number(ureg)); - ureg_ENDIF(ureg); - - /* normalize hitDir */ - ureg_normalize3(ureg, rHit, ureg_src(rHit)); - - /* if (SPOT light) */ - ureg_SEQ(ureg, tmp_x, cLKind, ureg_imm1f(ureg, D3DLIGHT_SPOT)); - ureg_IF(ureg, _X(tmp), &label[l++]); - { - /* rho = dp3(-hitDir, light.spotDir) - * - * if (rho > light.ctht2) NOTE: 0 <= phi <= pi, 0 <= theta <= phi - * spotAtt = 1 - * else - * if (rho <= light.cphi2) - * spotAtt = 0 - * else - * spotAtt = (rho - light.cphi2) / (light.ctht2 - light.cphi2) ^ light.falloff - */ - ureg_DP3(ureg, tmp_y, ureg_negate(ureg_src(rHit)), cLDir); /* rho */ - ureg_ADD(ureg, tmp_x, _Y(tmp), ureg_negate(cLPhi)); - ureg_MUL(ureg, tmp_x, _X(tmp), cLSDiv); - ureg_POW(ureg, tmp_x, _X(tmp), cLFOff); /* spotAtten */ - ureg_SGE(ureg, tmp_z, _Y(tmp), cLTht); /* if inside theta && phi */ - ureg_SGE(ureg, tmp_y, _Y(tmp), cLPhi); /* if inside phi */ - ureg_MAD(ureg, ureg_saturate(tmp_x), _X(tmp), _Y(tmp), _Z(tmp)); - ureg_MUL(ureg, rAtt, _W(rAtt), _X(tmp)); - } - ureg_fixup_label(ureg, label[l-1], ureg_get_instruction_number(ureg)); - ureg_ENDIF(ureg); - - /* directional factors, let's not use LIT because of clarity */ - - if (has_aNrm) { - if (key->localviewer) { - ureg_normalize3(ureg, rMid, vs->aVtx); - ureg_ADD(ureg, rMid, ureg_src(rHit), ureg_negate(ureg_src(rMid))); - } else { - ureg_ADD(ureg, rMid, ureg_src(rHit), ureg_imm3f(ureg, 0.0f, 0.0f, -1.0f)); - } - ureg_normalize3(ureg, rMid, ureg_src(rMid)); - ureg_DP3(ureg, ureg_saturate(tmp_x), vs->aNrm, ureg_src(rHit)); - ureg_DP3(ureg, ureg_saturate(tmp_y), vs->aNrm, ureg_src(rMid)); - ureg_MUL(ureg, tmp_z, _X(tmp), _Y(tmp)); - /* Tests show that specular is computed only if (dp3(normal,hitDir) > 0). - * For front facing, it is more restrictive than test (dp3(normal,mid) > 0). - * No tests were made for backfacing, so add the two conditions */ - ureg_IF(ureg, _Z(tmp), &label[l++]); - { - ureg_DP3(ureg, ureg_saturate(tmp_y), vs->aNrm, ureg_src(rMid)); - ureg_POW(ureg, tmp_y, _Y(tmp), mtlP); - ureg_MUL(ureg, tmp_y, _W(rAtt), _Y(tmp)); /* power factor * att */ - ureg_MAD(ureg, rS, cLColS, _Y(tmp), ureg_src(rS)); /* accumulate specular */ - } - ureg_fixup_label(ureg, label[l-1], ureg_get_instruction_number(ureg)); - ureg_ENDIF(ureg); - - ureg_MUL(ureg, tmp_x, _W(rAtt), _X(tmp)); /* dp3(normal,hitDir) * att */ - ureg_MAD(ureg, rD, cLColD, _X(tmp), ureg_src(rD)); /* accumulate diffuse */ - } - - ureg_MAD(ureg, rA, cLColA, _W(rAtt), ureg_src(rA)); /* accumulate ambient */ - - /* break if this was the last light */ - ureg_IF(ureg, cLLast, &label[l++]); - ureg_BRK(ureg); - ureg_ENDIF(ureg); - ureg_fixup_label(ureg, label[l-1], ureg_get_instruction_number(ureg)); - - ureg_ADD(ureg, rCtr, _W(rCtr), ureg_imm1f(ureg, 8.0f)); - ureg_fixup_label(ureg, label[loop_label], ureg_get_instruction_number(ureg)); - ureg_ENDLOOP(ureg, &label[loop_label]); - - /* Apply to material: - * - * oCol[0] = (material.emissive + material.ambient * rs.ambient) + - * material.ambient * ambient + - * material.diffuse * diffuse + - * oCol[1] = material.specular * specular; - */ - if (key->mtl_emissive == 0 && key->mtl_ambient == 0) - ureg_MAD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XYZ), ureg_src(rA), vs->mtlA, _CONST(19)); - else { - ureg_ADD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XYZ), ureg_src(rA), _CONST(25)); - ureg_MAD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XYZ), vs->mtlA, ureg_src(tmp), vs->mtlE); - } - - ureg_MAD(ureg, ureg_writemask(oCol[0], TGSI_WRITEMASK_XYZ), ureg_src(rD), vs->mtlD, ureg_src(tmp)); - ureg_MOV(ureg, ureg_writemask(oCol[0], TGSI_WRITEMASK_W), vs->mtlD); - ureg_MUL(ureg, oCol[1], ureg_src(rS), vs->mtlS); - ureg_release_temporary(ureg, rAtt); - ureg_release_temporary(ureg, rHit); - ureg_release_temporary(ureg, rMid); - ureg_release_temporary(ureg, rCtr); - ureg_release_temporary(ureg, rD); - ureg_release_temporary(ureg, rA); - ureg_release_temporary(ureg, rS); - ureg_release_temporary(ureg, rAtt); - ureg_release_temporary(ureg, tmp); - } else - /* COLOR */ - if (key->darkness) { - if (key->mtl_emissive == 0 && key->mtl_ambient == 0) - ureg_MOV(ureg, ureg_writemask(oCol[0], TGSI_WRITEMASK_XYZ), _CONST(19)); - else - ureg_MAD(ureg, ureg_writemask(oCol[0], TGSI_WRITEMASK_XYZ), vs->mtlA, _CONST(25), vs->mtlE); - ureg_MOV(ureg, ureg_writemask(oCol[0], TGSI_WRITEMASK_W), vs->mtlD); - ureg_MOV(ureg, oCol[1], ureg_imm1f(ureg, 0.0f)); - } else { - ureg_MOV(ureg, oCol[0], vs->aCol[0]); - ureg_MOV(ureg, oCol[1], vs->aCol[1]); - } - - /* === Process fog. - * - * exp(x) = ex2(log2(e) * x) - */ - if (key->fog_mode) { - struct ureg_dst tmp = ureg_DECL_temporary(ureg); - struct ureg_dst tmp_x = ureg_writemask(tmp, TGSI_WRITEMASK_X); - struct ureg_dst tmp_z = ureg_writemask(tmp, TGSI_WRITEMASK_Z); - if (key->fog_range) { - ureg_DP3(ureg, tmp_x, vs->aVtx, vs->aVtx); - ureg_RSQ(ureg, tmp_z, _X(tmp)); - ureg_MUL(ureg, tmp_z, _Z(tmp), _X(tmp)); - } else { - ureg_MOV(ureg, tmp_z, ureg_abs(_ZZZZ(vs->aVtx))); - } - - if (key->fog_mode == D3DFOG_EXP) { - ureg_MUL(ureg, tmp_x, _Z(tmp), _ZZZZ(_CONST(28))); - ureg_MUL(ureg, tmp_x, _X(tmp), ureg_imm1f(ureg, -1.442695f)); - ureg_EX2(ureg, tmp_x, _X(tmp)); - } else - if (key->fog_mode == D3DFOG_EXP2) { - ureg_MUL(ureg, tmp_x, _Z(tmp), _ZZZZ(_CONST(28))); - ureg_MUL(ureg, tmp_x, _X(tmp), _X(tmp)); - ureg_MUL(ureg, tmp_x, _X(tmp), ureg_imm1f(ureg, -1.442695f)); - ureg_EX2(ureg, tmp_x, _X(tmp)); - } else - if (key->fog_mode == D3DFOG_LINEAR) { - ureg_ADD(ureg, tmp_x, _XXXX(_CONST(28)), ureg_negate(_Z(tmp))); - ureg_MUL(ureg, ureg_saturate(tmp_x), _X(tmp), _YYYY(_CONST(28))); - } - ureg_MOV(ureg, oFog, _X(tmp)); - ureg_release_temporary(ureg, tmp); - } else if (key->fog && !(key->passthrough & (1 << NINE_DECLUSAGE_FOG))) { - ureg_MOV(ureg, oFog, ureg_scalar(vs->aCol[1], TGSI_SWIZZLE_W)); - } - - if (key->passthrough & (1 << NINE_DECLUSAGE_BLENDWEIGHT)) { - struct ureg_src input; - struct ureg_dst output; - input = vs->aWgt; - output = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 19); - ureg_MOV(ureg, output, input); - } - if (key->passthrough & (1 << NINE_DECLUSAGE_BLENDINDICES)) { - struct ureg_src input; - struct ureg_dst output; - input = vs->aInd; - output = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 20); - ureg_MOV(ureg, output, input); - } - if (key->passthrough & (1 << NINE_DECLUSAGE_NORMAL)) { - struct ureg_src input; - struct ureg_dst output; - input = vs->aNrm; - output = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 21); - ureg_MOV(ureg, output, input); - } - if (key->passthrough & (1 << NINE_DECLUSAGE_TANGENT)) { - struct ureg_src input; - struct ureg_dst output; - input = build_vs_add_input(vs, NINE_DECLUSAGE_TANGENT); - output = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 22); - ureg_MOV(ureg, output, input); - } - if (key->passthrough & (1 << NINE_DECLUSAGE_BINORMAL)) { - struct ureg_src input; - struct ureg_dst output; - input = build_vs_add_input(vs, NINE_DECLUSAGE_BINORMAL); - output = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 23); - ureg_MOV(ureg, output, input); - } - if (key->passthrough & (1 << NINE_DECLUSAGE_FOG)) { - struct ureg_src input; - struct ureg_dst output; - input = build_vs_add_input(vs, NINE_DECLUSAGE_FOG); - input = ureg_scalar(input, TGSI_SWIZZLE_X); - output = oFog; - ureg_MOV(ureg, output, input); - } - if (key->passthrough & (1 << NINE_DECLUSAGE_DEPTH)) { - (void) 0; /* TODO: replace z of position output ? */ - } - - /* ucp for ff applies on world coordinates. - * aVtx is in worldview coordinates. */ - if (key->ucp) { - struct ureg_dst clipVect = ureg_DECL_output(ureg, TGSI_SEMANTIC_CLIPVERTEX, 0); - struct ureg_dst tmp = ureg_DECL_temporary(ureg); - ureg_MUL(ureg, tmp, _XXXX(vs->aVtx), _CONST(12)); - ureg_MAD(ureg, tmp, _YYYY(vs->aVtx), _CONST(13), ureg_src(tmp)); - ureg_MAD(ureg, tmp, _ZZZZ(vs->aVtx), _CONST(14), ureg_src(tmp)); - ureg_ADD(ureg, clipVect, _CONST(15), ureg_src(tmp)); - ureg_release_temporary(ureg, tmp); - } - - if (key->position_t && device->driver_caps.window_space_position_support) - ureg_property(ureg, TGSI_PROPERTY_VS_WINDOW_SPACE_POSITION, TRUE); - - ureg_END(ureg); - nine_ureg_tgsi_dump(ureg, FALSE); - return nine_create_shader_with_so_and_destroy(ureg, device->context.pipe, NULL); -} - -/* PS FF constants layout: - * - * CONST[ 0.. 7] stage[i].D3DTSS_CONSTANT - * CONST[ 8..15].x___ stage[i].D3DTSS_BUMPENVMAT00 - * CONST[ 8..15]._y__ stage[i].D3DTSS_BUMPENVMAT01 - * CONST[ 8..15].__z_ stage[i].D3DTSS_BUMPENVMAT10 - * CONST[ 8..15].___w stage[i].D3DTSS_BUMPENVMAT11 - * CONST[16..19].x_z_ stage[i].D3DTSS_BUMPENVLSCALE - * CONST[17..19]._y_w stage[i].D3DTSS_BUMPENVLOFFSET - * - * CONST[20] D3DRS_TEXTUREFACTOR - * CONST[21] D3DRS_FOGCOLOR - * CONST[22].x___ RS.FogEnd - * CONST[22]._y__ 1.0f / (RS.FogEnd - RS.FogStart) - * CONST[22].__z_ RS.FogDensity - */ -struct ps_build_ctx -{ - struct ureg_program *ureg; - - struct ureg_src vC[2]; /* DIFFUSE, SPECULAR */ - struct ureg_src vT[8]; /* TEXCOORD[i] */ - struct ureg_dst rCur; /* D3DTA_CURRENT */ - struct ureg_dst rMod; - struct ureg_src rCurSrc; - struct ureg_dst rTmp; /* D3DTA_TEMP */ - struct ureg_src rTmpSrc; - struct ureg_dst rTex; - struct ureg_src rTexSrc; - struct ureg_src cBEM[8]; - struct ureg_src s[8]; - - struct { - unsigned index; - unsigned index_pre_mod; - } stage; -}; - -static struct ureg_src -ps_get_ts_arg(struct ps_build_ctx *ps, unsigned ta) -{ - struct ureg_src reg; - - switch (ta & D3DTA_SELECTMASK) { - case D3DTA_CONSTANT: - reg = ureg_DECL_constant(ps->ureg, ps->stage.index); - break; - case D3DTA_CURRENT: - reg = (ps->stage.index == ps->stage.index_pre_mod) ? ureg_src(ps->rMod) : ps->rCurSrc; - break; - case D3DTA_DIFFUSE: - reg = ureg_DECL_fs_input(ps->ureg, TGSI_SEMANTIC_COLOR, 0, TGSI_INTERPOLATE_COLOR); - break; - case D3DTA_SPECULAR: - reg = ureg_DECL_fs_input(ps->ureg, TGSI_SEMANTIC_COLOR, 1, TGSI_INTERPOLATE_COLOR); - break; - case D3DTA_TEMP: - reg = ps->rTmpSrc; - break; - case D3DTA_TEXTURE: - reg = ps->rTexSrc; - break; - case D3DTA_TFACTOR: - reg = ureg_DECL_constant(ps->ureg, 20); - break; - default: - assert(0); - reg = ureg_src_undef(); - break; - } - if (ta & D3DTA_COMPLEMENT) { - struct ureg_dst dst = ureg_DECL_temporary(ps->ureg); - ureg_ADD(ps->ureg, dst, ureg_imm1f(ps->ureg, 1.0f), ureg_negate(reg)); - reg = ureg_src(dst); - } - if (ta & D3DTA_ALPHAREPLICATE) - reg = _WWWW(reg); - return reg; -} - -static struct ureg_dst -ps_get_ts_dst(struct ps_build_ctx *ps, unsigned ta) -{ - assert(!(ta & (D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE))); - - switch (ta & D3DTA_SELECTMASK) { - case D3DTA_CURRENT: - return ps->rCur; - case D3DTA_TEMP: - return ps->rTmp; - default: - assert(0); - return ureg_dst_undef(); - } -} - -static uint8_t ps_d3dtop_args_mask(D3DTEXTUREOP top) -{ - switch (top) { - case D3DTOP_DISABLE: - return 0x0; - case D3DTOP_SELECTARG1: - case D3DTOP_PREMODULATE: - return 0x2; - case D3DTOP_SELECTARG2: - return 0x4; - case D3DTOP_MULTIPLYADD: - case D3DTOP_LERP: - return 0x7; - default: - return 0x6; - } -} - -static inline boolean -is_MOV_no_op(struct ureg_dst dst, struct ureg_src src) -{ - return !dst.WriteMask || - (dst.File == src.File && - dst.Index == src.Index && - !dst.Indirect && - !dst.Saturate && - !src.Indirect && - !src.Negate && - !src.Absolute && - (!(dst.WriteMask & TGSI_WRITEMASK_X) || (src.SwizzleX == TGSI_SWIZZLE_X)) && - (!(dst.WriteMask & TGSI_WRITEMASK_Y) || (src.SwizzleY == TGSI_SWIZZLE_Y)) && - (!(dst.WriteMask & TGSI_WRITEMASK_Z) || (src.SwizzleZ == TGSI_SWIZZLE_Z)) && - (!(dst.WriteMask & TGSI_WRITEMASK_W) || (src.SwizzleW == TGSI_SWIZZLE_W))); - -} - -static void -ps_do_ts_op(struct ps_build_ctx *ps, unsigned top, struct ureg_dst dst, struct ureg_src *arg) -{ - struct ureg_program *ureg = ps->ureg; - struct ureg_dst tmp = ureg_DECL_temporary(ureg); - struct ureg_dst tmp2 = ureg_DECL_temporary(ureg); - struct ureg_dst tmp_x = ureg_writemask(tmp, TGSI_WRITEMASK_X); - - tmp.WriteMask = dst.WriteMask; - - if (top != D3DTOP_SELECTARG1 && top != D3DTOP_SELECTARG2 && - top != D3DTOP_MODULATE && top != D3DTOP_PREMODULATE && - top != D3DTOP_BLENDDIFFUSEALPHA && top != D3DTOP_BLENDTEXTUREALPHA && - top != D3DTOP_BLENDFACTORALPHA && top != D3DTOP_BLENDCURRENTALPHA && - top != D3DTOP_BUMPENVMAP && top != D3DTOP_BUMPENVMAPLUMINANCE && - top != D3DTOP_LERP) - dst = ureg_saturate(dst); - - switch (top) { - case D3DTOP_SELECTARG1: - if (!is_MOV_no_op(dst, arg[1])) - ureg_MOV(ureg, dst, arg[1]); - break; - case D3DTOP_SELECTARG2: - if (!is_MOV_no_op(dst, arg[2])) - ureg_MOV(ureg, dst, arg[2]); - break; - case D3DTOP_MODULATE: - ureg_MUL(ureg, dst, arg[1], arg[2]); - break; - case D3DTOP_MODULATE2X: - ureg_MUL(ureg, tmp, arg[1], arg[2]); - ureg_ADD(ureg, dst, ureg_src(tmp), ureg_src(tmp)); - break; - case D3DTOP_MODULATE4X: - ureg_MUL(ureg, tmp, arg[1], arg[2]); - ureg_MUL(ureg, dst, ureg_src(tmp), ureg_imm1f(ureg, 4.0f)); - break; - case D3DTOP_ADD: - ureg_ADD(ureg, dst, arg[1], arg[2]); - break; - case D3DTOP_ADDSIGNED: - ureg_ADD(ureg, tmp, arg[1], arg[2]); - ureg_ADD(ureg, dst, ureg_src(tmp), ureg_imm1f(ureg, -0.5f)); - break; - case D3DTOP_ADDSIGNED2X: - ureg_ADD(ureg, tmp, arg[1], arg[2]); - ureg_MAD(ureg, dst, ureg_src(tmp), ureg_imm1f(ureg, 2.0f), ureg_imm1f(ureg, -1.0f)); - break; - case D3DTOP_SUBTRACT: - ureg_ADD(ureg, dst, arg[1], ureg_negate(arg[2])); - break; - case D3DTOP_ADDSMOOTH: - ureg_ADD(ureg, tmp, ureg_imm1f(ureg, 1.0f), ureg_negate(arg[1])); - ureg_MAD(ureg, dst, ureg_src(tmp), arg[2], arg[1]); - break; - case D3DTOP_BLENDDIFFUSEALPHA: - ureg_LRP(ureg, dst, _WWWW(ps->vC[0]), arg[1], arg[2]); - break; - case D3DTOP_BLENDTEXTUREALPHA: - /* XXX: alpha taken from previous stage, texture or result ? */ - ureg_LRP(ureg, dst, _W(ps->rTex), arg[1], arg[2]); - break; - case D3DTOP_BLENDFACTORALPHA: - ureg_LRP(ureg, dst, _WWWW(_CONST(20)), arg[1], arg[2]); - break; - case D3DTOP_BLENDTEXTUREALPHAPM: - ureg_ADD(ureg, tmp_x, ureg_imm1f(ureg, 1.0f), ureg_negate(_W(ps->rTex))); - ureg_MAD(ureg, dst, arg[2], _X(tmp), arg[1]); - break; - case D3DTOP_BLENDCURRENTALPHA: - ureg_LRP(ureg, dst, _WWWW(ps->rCurSrc), arg[1], arg[2]); - break; - case D3DTOP_PREMODULATE: - ureg_MOV(ureg, dst, arg[1]); - ps->stage.index_pre_mod = ps->stage.index + 1; - break; - case D3DTOP_MODULATEALPHA_ADDCOLOR: - ureg_MAD(ureg, dst, _WWWW(arg[1]), arg[2], arg[1]); - break; - case D3DTOP_MODULATECOLOR_ADDALPHA: - ureg_MAD(ureg, dst, arg[1], arg[2], _WWWW(arg[1])); - break; - case D3DTOP_MODULATEINVALPHA_ADDCOLOR: - ureg_ADD(ureg, tmp_x, ureg_imm1f(ureg, 1.0f), ureg_negate(_WWWW(arg[1]))); - ureg_MAD(ureg, dst, _X(tmp), arg[2], arg[1]); - break; - case D3DTOP_MODULATEINVCOLOR_ADDALPHA: - ureg_ADD(ureg, tmp, ureg_imm1f(ureg, 1.0f), ureg_negate(arg[1])); - ureg_MAD(ureg, dst, ureg_src(tmp), arg[2], _WWWW(arg[1])); - break; - case D3DTOP_BUMPENVMAP: - break; - case D3DTOP_BUMPENVMAPLUMINANCE: - break; - case D3DTOP_DOTPRODUCT3: - ureg_ADD(ureg, tmp, arg[1], ureg_imm4f(ureg,-0.5,-0.5,-0.5,-0.5)); - ureg_ADD(ureg, tmp2, arg[2] , ureg_imm4f(ureg,-0.5,-0.5,-0.5,-0.5)); - ureg_DP3(ureg, tmp, ureg_src(tmp), ureg_src(tmp2)); - ureg_MUL(ureg, ureg_saturate(dst), ureg_src(tmp), ureg_imm4f(ureg,4.0,4.0,4.0,4.0)); - break; - case D3DTOP_MULTIPLYADD: - ureg_MAD(ureg, dst, arg[1], arg[2], arg[0]); - break; - case D3DTOP_LERP: - ureg_LRP(ureg, dst, arg[0], arg[1], arg[2]); - break; - case D3DTOP_DISABLE: - /* no-op ? */ - break; - default: - assert(!"invalid D3DTOP"); - break; - } - ureg_release_temporary(ureg, tmp); - ureg_release_temporary(ureg, tmp2); -} - -static void * -nine_ff_build_ps(struct NineDevice9 *device, struct nine_ff_ps_key *key) -{ - struct ps_build_ctx ps; - struct ureg_program *ureg = ureg_create(PIPE_SHADER_FRAGMENT); - struct ureg_dst oCol; - unsigned s; - const unsigned texcoord_sn = get_texcoord_sn(device->screen); - - memset(&ps, 0, sizeof(ps)); - ps.ureg = ureg; - ps.stage.index_pre_mod = -1; - - ps.vC[0] = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_COLOR, 0, TGSI_INTERPOLATE_COLOR); - - ps.rCur = ureg_DECL_temporary(ureg); - ps.rTmp = ureg_DECL_temporary(ureg); - ps.rTex = ureg_DECL_temporary(ureg); - ps.rCurSrc = ureg_src(ps.rCur); - ps.rTmpSrc = ureg_src(ps.rTmp); - ps.rTexSrc = ureg_src(ps.rTex); - - /* Initial values */ - ureg_MOV(ureg, ps.rCur, ps.vC[0]); - ureg_MOV(ureg, ps.rTmp, ureg_imm1f(ureg, 0.0f)); - ureg_MOV(ureg, ps.rTex, ureg_imm1f(ureg, 0.0f)); - - for (s = 0; s < 8; ++s) { - ps.s[s] = ureg_src_undef(); - - if (key->ts[s].colorop != D3DTOP_DISABLE) { - if (key->ts[s].colorarg0 == D3DTA_SPECULAR || - key->ts[s].colorarg1 == D3DTA_SPECULAR || - key->ts[s].colorarg2 == D3DTA_SPECULAR) - ps.vC[1] = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_COLOR, 1, TGSI_INTERPOLATE_COLOR); - - if (key->ts[s].colorarg0 == D3DTA_TEXTURE || - key->ts[s].colorarg1 == D3DTA_TEXTURE || - key->ts[s].colorarg2 == D3DTA_TEXTURE) { - ps.s[s] = ureg_DECL_sampler(ureg, s); - ps.vT[s] = ureg_DECL_fs_input(ureg, texcoord_sn, s, TGSI_INTERPOLATE_PERSPECTIVE); - } - if (s && (key->ts[s - 1].colorop == D3DTOP_PREMODULATE || - key->ts[s - 1].alphaop == D3DTOP_PREMODULATE)) - ps.s[s] = ureg_DECL_sampler(ureg, s); - } - - if (key->ts[s].alphaop != D3DTOP_DISABLE) { - if (key->ts[s].alphaarg0 == D3DTA_SPECULAR || - key->ts[s].alphaarg1 == D3DTA_SPECULAR || - key->ts[s].alphaarg2 == D3DTA_SPECULAR) - ps.vC[1] = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_COLOR, 1, TGSI_INTERPOLATE_COLOR); - - if (key->ts[s].alphaarg0 == D3DTA_TEXTURE || - key->ts[s].alphaarg1 == D3DTA_TEXTURE || - key->ts[s].alphaarg2 == D3DTA_TEXTURE) { - ps.s[s] = ureg_DECL_sampler(ureg, s); - ps.vT[s] = ureg_DECL_fs_input(ureg, texcoord_sn, s, TGSI_INTERPOLATE_PERSPECTIVE); - } - } - } - if (key->specular) - ps.vC[1] = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_COLOR, 1, TGSI_INTERPOLATE_COLOR); - - oCol = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0); - - /* Run stages. - */ - for (s = 0; s < 8; ++s) { - unsigned colorarg[3]; - unsigned alphaarg[3]; - const uint8_t used_c = ps_d3dtop_args_mask(key->ts[s].colorop); - const uint8_t used_a = ps_d3dtop_args_mask(key->ts[s].alphaop); - struct ureg_dst dst; - struct ureg_src arg[3]; - - if (key->ts[s].colorop == D3DTOP_DISABLE) { - assert (key->ts[s].alphaop == D3DTOP_DISABLE); - continue; - } - ps.stage.index = s; - - DBG("STAGE[%u]: colorop=%s alphaop=%s\n", s, - nine_D3DTOP_to_str(key->ts[s].colorop), - nine_D3DTOP_to_str(key->ts[s].alphaop)); - - if (!ureg_src_is_undef(ps.s[s])) { - unsigned target; - struct ureg_src texture_coord = ps.vT[s]; - struct ureg_dst delta; - switch (key->ts[s].textarget) { - case 0: target = TGSI_TEXTURE_1D; break; - case 1: target = TGSI_TEXTURE_2D; break; - case 2: target = TGSI_TEXTURE_3D; break; - case 3: target = TGSI_TEXTURE_CUBE; break; - /* this is a 2 bit bitfield, do I really need a default case ? */ - } - - /* Modify coordinates */ - if (s >= 1 && - (key->ts[s-1].colorop == D3DTOP_BUMPENVMAP || - key->ts[s-1].colorop == D3DTOP_BUMPENVMAPLUMINANCE)) { - delta = ureg_DECL_temporary(ureg); - /* Du' = D3DTSS_BUMPENVMAT00(stage s-1)*t(s-1)R + D3DTSS_BUMPENVMAT10(stage s-1)*t(s-1)G */ - ureg_MUL(ureg, ureg_writemask(delta, TGSI_WRITEMASK_X), _X(ps.rTex), _XXXX(_CONST(8 + s - 1))); - ureg_MAD(ureg, ureg_writemask(delta, TGSI_WRITEMASK_X), _Y(ps.rTex), _ZZZZ(_CONST(8 + s - 1)), ureg_src(delta)); - /* Dv' = D3DTSS_BUMPENVMAT01(stage s-1)*t(s-1)R + D3DTSS_BUMPENVMAT11(stage s-1)*t(s-1)G */ - ureg_MUL(ureg, ureg_writemask(delta, TGSI_WRITEMASK_Y), _X(ps.rTex), _YYYY(_CONST(8 + s - 1))); - ureg_MAD(ureg, ureg_writemask(delta, TGSI_WRITEMASK_Y), _Y(ps.rTex), _WWWW(_CONST(8 + s - 1)), ureg_src(delta)); - texture_coord = ureg_src(ureg_DECL_temporary(ureg)); - ureg_MOV(ureg, ureg_writemask(ureg_dst(texture_coord), ureg_dst(ps.vT[s]).WriteMask), ps.vT[s]); - ureg_ADD(ureg, ureg_writemask(ureg_dst(texture_coord), TGSI_WRITEMASK_XY), texture_coord, ureg_src(delta)); - /* Prepare luminance multiplier - * t(s)RGBA = t(s)RGBA * clamp[(t(s-1)B * D3DTSS_BUMPENVLSCALE(stage s-1)) + D3DTSS_BUMPENVLOFFSET(stage s-1)] */ - if (key->ts[s-1].colorop == D3DTOP_BUMPENVMAPLUMINANCE) { - struct ureg_src bumpenvlscale = ((s-1) & 1) ? _ZZZZ(_CONST(16 + (s-1) / 2)) : _XXXX(_CONST(16 + (s-1) / 2)); - struct ureg_src bumpenvloffset = ((s-1) & 1) ? _WWWW(_CONST(16 + (s-1) / 2)) : _YYYY(_CONST(16 + (s-1) / 2)); - - ureg_MAD(ureg, ureg_saturate(ureg_writemask(delta, TGSI_WRITEMASK_X)), _Z(ps.rTex), bumpenvlscale, bumpenvloffset); - } - } - if (key->projected & (3 << (s *2))) { - unsigned dim = 1 + ((key->projected >> (2 * s)) & 3); - if (dim == 4) - ureg_TXP(ureg, ps.rTex, target, texture_coord, ps.s[s]); - else { - struct ureg_dst tmp = ureg_DECL_temporary(ureg); - ureg_RCP(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), ureg_scalar(texture_coord, dim-1)); - ureg_MUL(ureg, ps.rTmp, _X(tmp), texture_coord); - ureg_TEX(ureg, ps.rTex, target, ps.rTmpSrc, ps.s[s]); - ureg_release_temporary(ureg, tmp); - } - } else { - ureg_TEX(ureg, ps.rTex, target, texture_coord, ps.s[s]); - } - if (s >= 1 && key->ts[s-1].colorop == D3DTOP_BUMPENVMAPLUMINANCE) - ureg_MUL(ureg, ps.rTex, ureg_src(ps.rTex), _X(delta)); - } - - if (key->ts[s].colorop == D3DTOP_BUMPENVMAP || - key->ts[s].colorop == D3DTOP_BUMPENVMAPLUMINANCE) - continue; - - dst = ps_get_ts_dst(&ps, key->ts[s].resultarg ? D3DTA_TEMP : D3DTA_CURRENT); - - if (ps.stage.index_pre_mod == ps.stage.index) { - ps.rMod = ureg_DECL_temporary(ureg); - ureg_MUL(ureg, ps.rMod, ps.rCurSrc, ps.rTexSrc); - } - - colorarg[0] = (key->ts[s].colorarg0 | (((key->colorarg_b4[0] >> s) & 0x1) << 4) | ((key->colorarg_b5[0] >> s) << 5)) & 0x3f; - colorarg[1] = (key->ts[s].colorarg1 | (((key->colorarg_b4[1] >> s) & 0x1) << 4) | ((key->colorarg_b5[1] >> s) << 5)) & 0x3f; - colorarg[2] = (key->ts[s].colorarg2 | (((key->colorarg_b4[2] >> s) & 0x1) << 4) | ((key->colorarg_b5[2] >> s) << 5)) & 0x3f; - alphaarg[0] = (key->ts[s].alphaarg0 | ((key->alphaarg_b4[0] >> s) << 4)) & 0x1f; - alphaarg[1] = (key->ts[s].alphaarg1 | ((key->alphaarg_b4[1] >> s) << 4)) & 0x1f; - alphaarg[2] = (key->ts[s].alphaarg2 | ((key->alphaarg_b4[2] >> s) << 4)) & 0x1f; - - if (key->ts[s].colorop != key->ts[s].alphaop || - colorarg[0] != alphaarg[0] || - colorarg[1] != alphaarg[1] || - colorarg[2] != alphaarg[2]) - dst.WriteMask = TGSI_WRITEMASK_XYZ; - - /* Special DOTPRODUCT behaviour (see wine tests) */ - if (key->ts[s].colorop == D3DTOP_DOTPRODUCT3) - dst.WriteMask = TGSI_WRITEMASK_XYZW; - - if (used_c & 0x1) arg[0] = ps_get_ts_arg(&ps, colorarg[0]); - if (used_c & 0x2) arg[1] = ps_get_ts_arg(&ps, colorarg[1]); - if (used_c & 0x4) arg[2] = ps_get_ts_arg(&ps, colorarg[2]); - ps_do_ts_op(&ps, key->ts[s].colorop, dst, arg); - - if (dst.WriteMask != TGSI_WRITEMASK_XYZW) { - dst.WriteMask = TGSI_WRITEMASK_W; - - if (used_a & 0x1) arg[0] = ps_get_ts_arg(&ps, alphaarg[0]); - if (used_a & 0x2) arg[1] = ps_get_ts_arg(&ps, alphaarg[1]); - if (used_a & 0x4) arg[2] = ps_get_ts_arg(&ps, alphaarg[2]); - ps_do_ts_op(&ps, key->ts[s].alphaop, dst, arg); - } - } - - if (key->specular) - ureg_ADD(ureg, ureg_writemask(ps.rCur, TGSI_WRITEMASK_XYZ), ps.rCurSrc, ps.vC[1]); - - /* Fog. - */ - if (key->fog_mode) { - struct ureg_dst rFog = ureg_writemask(ps.rTmp, TGSI_WRITEMASK_X); - struct ureg_src vPos; - if (device->screen->get_param(device->screen, - PIPE_CAP_TGSI_FS_POSITION_IS_SYSVAL)) { - vPos = ureg_DECL_system_value(ureg, TGSI_SEMANTIC_POSITION, 0); - } else { - vPos = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_POSITION, 0, - TGSI_INTERPOLATE_LINEAR); - } - - /* Source is either W or Z. - * When we use vs ff, - * Z is when an orthogonal projection matrix is detected, - * W (WFOG) else. - * Z is used for programmable vs. - * Note: Tests indicate that the projection matrix coefficients do - * actually affect pixel fog (and not vertex fog) when vs ff is used, - * which justifies taking the position's w instead of taking the z coordinate - * before the projection in the vs shader. - */ - if (!key->fog_source) - ureg_MOV(ureg, rFog, _ZZZZ(vPos)); - else - /* Position's w is 1/w */ - ureg_RCP(ureg, rFog, _WWWW(vPos)); - - if (key->fog_mode == D3DFOG_EXP) { - ureg_MUL(ureg, rFog, _X(rFog), _ZZZZ(_CONST(22))); - ureg_MUL(ureg, rFog, _X(rFog), ureg_imm1f(ureg, -1.442695f)); - ureg_EX2(ureg, rFog, _X(rFog)); - } else - if (key->fog_mode == D3DFOG_EXP2) { - ureg_MUL(ureg, rFog, _X(rFog), _ZZZZ(_CONST(22))); - ureg_MUL(ureg, rFog, _X(rFog), _X(rFog)); - ureg_MUL(ureg, rFog, _X(rFog), ureg_imm1f(ureg, -1.442695f)); - ureg_EX2(ureg, rFog, _X(rFog)); - } else - if (key->fog_mode == D3DFOG_LINEAR) { - ureg_ADD(ureg, rFog, _XXXX(_CONST(22)), ureg_negate(_X(rFog))); - ureg_MUL(ureg, ureg_saturate(rFog), _X(rFog), _YYYY(_CONST(22))); - } - ureg_LRP(ureg, ureg_writemask(oCol, TGSI_WRITEMASK_XYZ), _X(rFog), ps.rCurSrc, _CONST(21)); - ureg_MOV(ureg, ureg_writemask(oCol, TGSI_WRITEMASK_W), ps.rCurSrc); - } else - if (key->fog) { - struct ureg_src vFog = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_GENERIC, 16, TGSI_INTERPOLATE_PERSPECTIVE); - ureg_LRP(ureg, ureg_writemask(oCol, TGSI_WRITEMASK_XYZ), _XXXX(vFog), ps.rCurSrc, _CONST(21)); - ureg_MOV(ureg, ureg_writemask(oCol, TGSI_WRITEMASK_W), ps.rCurSrc); - } else { - ureg_MOV(ureg, oCol, ps.rCurSrc); - } - - ureg_END(ureg); - nine_ureg_tgsi_dump(ureg, FALSE); - return nine_create_shader_with_so_and_destroy(ureg, device->context.pipe, NULL); -} - -static struct NineVertexShader9 * -nine_ff_get_vs(struct NineDevice9 *device) -{ - const struct nine_context *context = &device->context; - struct NineVertexShader9 *vs; - struct vs_build_ctx bld; - struct nine_ff_vs_key key; - unsigned s, i; - boolean has_indexes = false; - boolean has_weights = false; - char input_texture_coord[8]; - - assert(sizeof(key) <= sizeof(key.value32)); - - memset(&key, 0, sizeof(key)); - memset(&bld, 0, sizeof(bld)); - memset(&input_texture_coord, 0, sizeof(input_texture_coord)); - - bld.key = &key; - - /* FIXME: this shouldn't be NULL, but it is on init */ - if (context->vdecl) { - key.color0in_one = 1; - key.color1in_zero = 1; - for (i = 0; i < context->vdecl->nelems; i++) { - uint16_t usage = context->vdecl->usage_map[i]; - if (usage == NINE_DECLUSAGE_POSITIONT) - key.position_t = 1; - else if (usage == NINE_DECLUSAGE_i(COLOR, 0)) - key.color0in_one = 0; - else if (usage == NINE_DECLUSAGE_i(COLOR, 1)) - key.color1in_zero = 0; - else if (usage == NINE_DECLUSAGE_i(BLENDINDICES, 0)) { - has_indexes = true; - key.passthrough |= 1 << usage; - } else if (usage == NINE_DECLUSAGE_i(BLENDWEIGHT, 0)) { - has_weights = true; - key.passthrough |= 1 << usage; - } else if (usage == NINE_DECLUSAGE_i(NORMAL, 0)) { - key.has_normal = 1; - key.passthrough |= 1 << usage; - } else if (usage == NINE_DECLUSAGE_PSIZE) - key.vertexpointsize = 1; - else if (usage % NINE_DECLUSAGE_COUNT == NINE_DECLUSAGE_TEXCOORD) { - s = usage / NINE_DECLUSAGE_COUNT; - if (s < 8) - input_texture_coord[s] = nine_decltype_get_dim(context->vdecl->decls[i].Type); - else - DBG("FF given texture coordinate >= 8. Ignoring\n"); - } else if (usage < NINE_DECLUSAGE_NONE) - key.passthrough |= 1 << usage; - } - } - /* ff vs + ps 3.0: some elements are passed to the ps (wine test). - * We do restrict to indices 0 */ - key.passthrough &= ~((1 << NINE_DECLUSAGE_POSITION) | (1 << NINE_DECLUSAGE_PSIZE) | - (1 << NINE_DECLUSAGE_TEXCOORD) | (1 << NINE_DECLUSAGE_POSITIONT) | - (1 << NINE_DECLUSAGE_TESSFACTOR) | (1 << NINE_DECLUSAGE_SAMPLE)); - if (!key.position_t) - key.passthrough = 0; - key.pointscale = !!context->rs[D3DRS_POINTSCALEENABLE]; - - key.lighting = !!context->rs[D3DRS_LIGHTING] && context->ff.num_lights_active; - key.darkness = !!context->rs[D3DRS_LIGHTING] && !context->ff.num_lights_active; - if (key.position_t) { - key.darkness = 0; /* |= key.lighting; */ /* XXX ? */ - key.lighting = 0; - } - if ((key.lighting | key.darkness) && context->rs[D3DRS_COLORVERTEX]) { - uint32_t mask = (key.color0in_one ? 0 : 1) | (key.color1in_zero ? 0 : 2); - key.mtl_diffuse = context->rs[D3DRS_DIFFUSEMATERIALSOURCE] & mask; - key.mtl_ambient = context->rs[D3DRS_AMBIENTMATERIALSOURCE] & mask; - key.mtl_specular = context->rs[D3DRS_SPECULARMATERIALSOURCE] & mask; - key.mtl_emissive = context->rs[D3DRS_EMISSIVEMATERIALSOURCE] & mask; - } - key.fog = !!context->rs[D3DRS_FOGENABLE]; - key.fog_mode = (!key.position_t && context->rs[D3DRS_FOGENABLE]) ? context->rs[D3DRS_FOGVERTEXMODE] : 0; - if (key.fog_mode) - key.fog_range = context->rs[D3DRS_RANGEFOGENABLE]; - - key.localviewer = !!context->rs[D3DRS_LOCALVIEWER]; - key.normalizenormals = !!context->rs[D3DRS_NORMALIZENORMALS]; - key.ucp = !!context->rs[D3DRS_CLIPPLANEENABLE]; - - if (context->rs[D3DRS_VERTEXBLEND] != D3DVBF_DISABLE) { - key.vertexblend_indexed = !!context->rs[D3DRS_INDEXEDVERTEXBLENDENABLE] && has_indexes; - - switch (context->rs[D3DRS_VERTEXBLEND]) { - case D3DVBF_0WEIGHTS: key.vertexblend = key.vertexblend_indexed; break; - case D3DVBF_1WEIGHTS: key.vertexblend = 2; break; - case D3DVBF_2WEIGHTS: key.vertexblend = 3; break; - case D3DVBF_3WEIGHTS: key.vertexblend = 4; break; - case D3DVBF_TWEENING: key.vertextween = 1; break; - default: - assert(!"invalid D3DVBF"); - break; - } - if (!has_weights && context->rs[D3DRS_VERTEXBLEND] != D3DVBF_0WEIGHTS) - key.vertexblend = 0; /* TODO: if key.vertexblend_indexed, perhaps it should use 1.0 as weight, or revert to D3DVBF_0WEIGHTS */ - } - - for (s = 0; s < 8; ++s) { - unsigned gen = (context->ff.tex_stage[s][D3DTSS_TEXCOORDINDEX] >> 16) + 1; - unsigned idx = context->ff.tex_stage[s][D3DTSS_TEXCOORDINDEX] & 7; - unsigned dim; - - if (key.position_t && gen > NINED3DTSS_TCI_PASSTHRU) - gen = NINED3DTSS_TCI_PASSTHRU; - - if (!input_texture_coord[idx] && gen == NINED3DTSS_TCI_PASSTHRU) - gen = NINED3DTSS_TCI_DISABLE; - - key.tc_gen |= gen << (s * 3); - key.tc_idx |= idx << (s * 3); - key.tc_dim_input |= ((input_texture_coord[idx]-1) & 0x3) << (s * 2); - - dim = context->ff.tex_stage[s][D3DTSS_TEXTURETRANSFORMFLAGS] & 0x7; - if (dim > 4) - dim = input_texture_coord[idx]; - if (dim == 1) /* NV behaviour */ - dim = 0; - key.tc_dim_output |= dim << (s * 3); - } - - DBG("VS ff key hash: %x\n", nine_ff_vs_key_hash(&key)); - vs = util_hash_table_get(device->ff.ht_vs, &key); - if (vs) - return vs; - NineVertexShader9_new(device, &vs, NULL, nine_ff_build_vs(device, &bld)); - - nine_ff_prune_vs(device); - if (vs) { - unsigned n; - - memcpy(&vs->ff_key, &key, sizeof(vs->ff_key)); - - _mesa_hash_table_insert(device->ff.ht_vs, &vs->ff_key, vs); - device->ff.num_vs++; - - vs->num_inputs = bld.num_inputs; - for (n = 0; n < bld.num_inputs; ++n) - vs->input_map[n].ndecl = bld.input[n]; - - vs->position_t = key.position_t; - vs->point_size = key.vertexpointsize | key.pointscale; - } - return vs; -} - -#define GET_D3DTS(n) nine_state_access_transform(&context->ff, D3DTS_##n, FALSE) -#define IS_D3DTS_DIRTY(s,n) ((s)->ff.changed.transform[(D3DTS_##n) / 32] & (1 << ((D3DTS_##n) % 32))) - -static struct NinePixelShader9 * -nine_ff_get_ps(struct NineDevice9 *device) -{ - struct nine_context *context = &device->context; - D3DMATRIX *projection_matrix = GET_D3DTS(PROJECTION); - struct NinePixelShader9 *ps; - struct nine_ff_ps_key key; - unsigned s; - uint8_t sampler_mask = 0; - - assert(sizeof(key) <= sizeof(key.value32)); - - memset(&key, 0, sizeof(key)); - for (s = 0; s < 8; ++s) { - key.ts[s].colorop = context->ff.tex_stage[s][D3DTSS_COLOROP]; - key.ts[s].alphaop = context->ff.tex_stage[s][D3DTSS_ALPHAOP]; - const uint8_t used_c = ps_d3dtop_args_mask(key.ts[s].colorop); - const uint8_t used_a = ps_d3dtop_args_mask(key.ts[s].alphaop); - /* MSDN says D3DTOP_DISABLE disables this and all subsequent stages. - * ALPHAOP cannot be enabled if COLOROP is disabled. - * Verified on Windows. */ - if (key.ts[s].colorop == D3DTOP_DISABLE) { - key.ts[s].alphaop = D3DTOP_DISABLE; /* DISABLE == 1, avoid degenerate keys */ - break; - } - - if (!context->texture[s].enabled && - ((context->ff.tex_stage[s][D3DTSS_COLORARG0] == D3DTA_TEXTURE && - used_c & 0x1) || - (context->ff.tex_stage[s][D3DTSS_COLORARG1] == D3DTA_TEXTURE && - used_c & 0x2) || - (context->ff.tex_stage[s][D3DTSS_COLORARG2] == D3DTA_TEXTURE && - used_c & 0x4))) { - /* Tested on Windows: Invalid texture read disables the stage - * and the subsequent ones, but only for colorop. For alpha, - * it's as if the texture had alpha of 1.0, which is what - * has our dummy texture in that case. Invalid color also - * disabled the following alpha stages. */ - key.ts[s].colorop = key.ts[s].alphaop = D3DTOP_DISABLE; - break; - } - - if (context->ff.tex_stage[s][D3DTSS_COLORARG0] == D3DTA_TEXTURE || - context->ff.tex_stage[s][D3DTSS_COLORARG1] == D3DTA_TEXTURE || - context->ff.tex_stage[s][D3DTSS_COLORARG2] == D3DTA_TEXTURE || - context->ff.tex_stage[s][D3DTSS_ALPHAARG0] == D3DTA_TEXTURE || - context->ff.tex_stage[s][D3DTSS_ALPHAARG1] == D3DTA_TEXTURE || - context->ff.tex_stage[s][D3DTSS_ALPHAARG2] == D3DTA_TEXTURE) - sampler_mask |= (1 << s); - - if (key.ts[s].colorop != D3DTOP_DISABLE) { - if (used_c & 0x1) key.ts[s].colorarg0 = context->ff.tex_stage[s][D3DTSS_COLORARG0] & 0x7; - if (used_c & 0x2) key.ts[s].colorarg1 = context->ff.tex_stage[s][D3DTSS_COLORARG1] & 0x7; - if (used_c & 0x4) key.ts[s].colorarg2 = context->ff.tex_stage[s][D3DTSS_COLORARG2] & 0x7; - if (used_c & 0x1) key.colorarg_b4[0] |= ((context->ff.tex_stage[s][D3DTSS_COLORARG0] >> 4) & 0x1) << s; - if (used_c & 0x1) key.colorarg_b5[0] |= ((context->ff.tex_stage[s][D3DTSS_COLORARG0] >> 5) & 0x1) << s; - if (used_c & 0x2) key.colorarg_b4[1] |= ((context->ff.tex_stage[s][D3DTSS_COLORARG1] >> 4) & 0x1) << s; - if (used_c & 0x2) key.colorarg_b5[1] |= ((context->ff.tex_stage[s][D3DTSS_COLORARG1] >> 5) & 0x1) << s; - if (used_c & 0x4) key.colorarg_b4[2] |= ((context->ff.tex_stage[s][D3DTSS_COLORARG2] >> 4) & 0x1) << s; - if (used_c & 0x4) key.colorarg_b5[2] |= ((context->ff.tex_stage[s][D3DTSS_COLORARG2] >> 5) & 0x1) << s; - } - if (key.ts[s].alphaop != D3DTOP_DISABLE) { - if (used_a & 0x1) key.ts[s].alphaarg0 = context->ff.tex_stage[s][D3DTSS_ALPHAARG0] & 0x7; - if (used_a & 0x2) key.ts[s].alphaarg1 = context->ff.tex_stage[s][D3DTSS_ALPHAARG1] & 0x7; - if (used_a & 0x4) key.ts[s].alphaarg2 = context->ff.tex_stage[s][D3DTSS_ALPHAARG2] & 0x7; - if (used_a & 0x1) key.alphaarg_b4[0] |= ((context->ff.tex_stage[s][D3DTSS_ALPHAARG0] >> 4) & 0x1) << s; - if (used_a & 0x2) key.alphaarg_b4[1] |= ((context->ff.tex_stage[s][D3DTSS_ALPHAARG1] >> 4) & 0x1) << s; - if (used_a & 0x4) key.alphaarg_b4[2] |= ((context->ff.tex_stage[s][D3DTSS_ALPHAARG2] >> 4) & 0x1) << s; - } - key.ts[s].resultarg = context->ff.tex_stage[s][D3DTSS_RESULTARG] == D3DTA_TEMP; - - if (context->texture[s].enabled) { - switch (context->texture[s].type) { - case D3DRTYPE_TEXTURE: key.ts[s].textarget = 1; break; - case D3DRTYPE_VOLUMETEXTURE: key.ts[s].textarget = 2; break; - case D3DRTYPE_CUBETEXTURE: key.ts[s].textarget = 3; break; - default: - assert(!"unexpected texture type"); - break; - } - } else { - key.ts[s].textarget = 1; - } - } - - /* Note: If colorop is D3DTOP_DISABLE for the first stage - * (which implies alphaop is too), nothing particular happens, - * that is, current is equal to diffuse (which is the case anyway, - * because it is how it is initialized). - * Special case seems if alphaop is D3DTOP_DISABLE and not colorop, - * because then if the resultarg is TEMP, then diffuse alpha is written - * to it. */ - if (key.ts[0].colorop != D3DTOP_DISABLE && - key.ts[0].alphaop == D3DTOP_DISABLE && - key.ts[0].resultarg != 0) { - key.ts[0].alphaop = D3DTOP_SELECTARG1; - key.ts[0].alphaarg1 = D3DTA_DIFFUSE; - } - /* When no alpha stage writes to current, diffuse alpha is taken. - * Since we initialize current to diffuse, we have the behaviour. */ - - /* Last stage always writes to Current */ - if (s >= 1) - key.ts[s-1].resultarg = 0; - - key.projected = nine_ff_get_projected_key_ff(context); - key.specular = !!context->rs[D3DRS_SPECULARENABLE]; - - for (; s < 8; ++s) - key.ts[s].colorop = key.ts[s].alphaop = D3DTOP_DISABLE; - if (context->rs[D3DRS_FOGENABLE]) - key.fog_mode = context->rs[D3DRS_FOGTABLEMODE]; - key.fog = !!context->rs[D3DRS_FOGENABLE]; - /* Pixel fog (with WFOG advertised): source is either Z or W. - * W is the source if vs ff is used, and the - * projection matrix is not orthogonal. - * Tests on Win 10 seem to indicate _34 - * and _33 are checked against 0, 1. */ - if (key.fog_mode && key.fog) - key.fog_source = !context->programmable_vs && - !(projection_matrix->_34 == 0.0f && - projection_matrix->_44 == 1.0f); - - DBG("PS ff key hash: %x\n", nine_ff_ps_key_hash(&key)); - ps = util_hash_table_get(device->ff.ht_ps, &key); - if (ps) - return ps; - NinePixelShader9_new(device, &ps, NULL, nine_ff_build_ps(device, &key)); - - nine_ff_prune_ps(device); - if (ps) { - memcpy(&ps->ff_key, &key, sizeof(ps->ff_key)); - - _mesa_hash_table_insert(device->ff.ht_ps, &ps->ff_key, ps); - device->ff.num_ps++; - - ps->rt_mask = 0x1; - ps->sampler_mask = sampler_mask; - } - return ps; -} - -static void -nine_ff_load_vs_transforms(struct NineDevice9 *device) -{ - struct nine_context *context = &device->context; - D3DMATRIX T; - D3DMATRIX *M = (D3DMATRIX *)device->ff.vs_const; - unsigned i; - - /* TODO: make this nicer, and only upload the ones we need */ - /* TODO: use ff.vs_const as storage of W, V, P matrices */ - - if (IS_D3DTS_DIRTY(context, WORLD) || - IS_D3DTS_DIRTY(context, VIEW) || - IS_D3DTS_DIRTY(context, PROJECTION)) { - /* WVP, WV matrices */ - nine_d3d_matrix_matrix_mul(&M[1], GET_D3DTS(WORLD), GET_D3DTS(VIEW)); - nine_d3d_matrix_matrix_mul(&M[0], &M[1], GET_D3DTS(PROJECTION)); - - /* normal matrix == transpose(inverse(WV)) */ - nine_d3d_matrix_inverse(&T, &M[1]); - nine_d3d_matrix_transpose(&M[4], &T); - - /* P matrix */ - M[2] = *GET_D3DTS(PROJECTION); - - /* V and W matrix */ - nine_d3d_matrix_inverse(&M[3], GET_D3DTS(VIEW)); - M[40] = M[1]; - } - - if (context->rs[D3DRS_VERTEXBLEND] != D3DVBF_DISABLE) { - /* load other world matrices */ - for (i = 1; i <= 8; ++i) { - nine_d3d_matrix_matrix_mul(&M[40 + i], GET_D3DTS(WORLDMATRIX(i)), GET_D3DTS(VIEW)); - } - } - - device->ff.vs_const[30 * 4] = asfloat(context->rs[D3DRS_TWEENFACTOR]); -} - -static void -nine_ff_load_lights(struct NineDevice9 *device) -{ - struct nine_context *context = &device->context; - struct fvec4 *dst = (struct fvec4 *)device->ff.vs_const; - unsigned l; - - if (context->changed.group & NINE_STATE_FF_MATERIAL) { - const D3DMATERIAL9 *mtl = &context->ff.material; - - memcpy(&dst[20], &mtl->Diffuse, 4 * sizeof(float)); - memcpy(&dst[21], &mtl->Ambient, 4 * sizeof(float)); - memcpy(&dst[22], &mtl->Specular, 4 * sizeof(float)); - dst[23].x = mtl->Power; - memcpy(&dst[24], &mtl->Emissive, 4 * sizeof(float)); - d3dcolor_to_rgba(&dst[25].x, context->rs[D3DRS_AMBIENT]); - dst[19].x = dst[25].x * mtl->Ambient.r + mtl->Emissive.r; - dst[19].y = dst[25].y * mtl->Ambient.g + mtl->Emissive.g; - dst[19].z = dst[25].z * mtl->Ambient.b + mtl->Emissive.b; - } - - if (!(context->changed.group & NINE_STATE_FF_LIGHTING)) - return; - - for (l = 0; l < context->ff.num_lights_active; ++l) { - const D3DLIGHT9 *light = &context->ff.light[context->ff.active_light[l]]; - - dst[32 + l * 8].x = light->Type; - dst[32 + l * 8].y = light->Attenuation0; - dst[32 + l * 8].z = light->Attenuation1; - dst[32 + l * 8].w = light->Attenuation2; - memcpy(&dst[33 + l * 8].x, &light->Diffuse, sizeof(light->Diffuse)); - memcpy(&dst[34 + l * 8].x, &light->Specular, sizeof(light->Specular)); - memcpy(&dst[35 + l * 8].x, &light->Ambient, sizeof(light->Ambient)); - nine_d3d_vector4_matrix_mul((D3DVECTOR *)&dst[36 + l * 8].x, &light->Position, GET_D3DTS(VIEW)); - nine_d3d_vector3_matrix_mul((D3DVECTOR *)&dst[37 + l * 8].x, &light->Direction, GET_D3DTS(VIEW)); - dst[36 + l * 8].w = light->Type == D3DLIGHT_DIRECTIONAL ? 1e9f : light->Range; - dst[37 + l * 8].w = light->Falloff; - dst[38 + l * 8].x = cosf(light->Theta * 0.5f); - dst[38 + l * 8].y = cosf(light->Phi * 0.5f); - dst[38 + l * 8].z = 1.0f / (dst[38 + l * 8].x - dst[38 + l * 8].y); - dst[39 + l * 8].w = (float)((l + 1) == context->ff.num_lights_active); - } -} - -static void -nine_ff_load_point_and_fog_params(struct NineDevice9 *device) -{ - struct nine_context *context = &device->context; - struct fvec4 *dst = (struct fvec4 *)device->ff.vs_const; - - if (!(context->changed.group & NINE_STATE_FF_VS_OTHER)) - return; - dst[26].x = asfloat(context->rs[D3DRS_POINTSIZE_MIN]); - dst[26].y = asfloat(context->rs[D3DRS_POINTSIZE_MAX]); - dst[26].z = asfloat(context->rs[D3DRS_POINTSIZE]); - dst[26].w = asfloat(context->rs[D3DRS_POINTSCALE_A]); - dst[27].x = asfloat(context->rs[D3DRS_POINTSCALE_B]); - dst[27].y = asfloat(context->rs[D3DRS_POINTSCALE_C]); - dst[28].x = asfloat(context->rs[D3DRS_FOGEND]); - dst[28].y = 1.0f / (asfloat(context->rs[D3DRS_FOGEND]) - asfloat(context->rs[D3DRS_FOGSTART])); - if (isinf(dst[28].y)) - dst[28].y = 0.0f; - dst[28].z = asfloat(context->rs[D3DRS_FOGDENSITY]); -} - -static void -nine_ff_load_tex_matrices(struct NineDevice9 *device) -{ - struct nine_context *context = &device->context; - D3DMATRIX *M = (D3DMATRIX *)device->ff.vs_const; - unsigned s; - - if (!(context->ff.changed.transform[0] & 0xff0000)) - return; - for (s = 0; s < 8; ++s) { - if (IS_D3DTS_DIRTY(context, TEXTURE0 + s)) - nine_d3d_matrix_transpose(&M[32 + s], nine_state_access_transform(&context->ff, D3DTS_TEXTURE0 + s, FALSE)); - } -} - -static void -nine_ff_load_ps_params(struct NineDevice9 *device) -{ - struct nine_context *context = &device->context; - struct fvec4 *dst = (struct fvec4 *)device->ff.ps_const; - unsigned s; - - if (!(context->changed.group & NINE_STATE_FF_PS_CONSTS)) - return; - - for (s = 0; s < 8; ++s) - d3dcolor_to_rgba(&dst[s].x, context->ff.tex_stage[s][D3DTSS_CONSTANT]); - - for (s = 0; s < 8; ++s) { - dst[8 + s].x = asfloat(context->ff.tex_stage[s][D3DTSS_BUMPENVMAT00]); - dst[8 + s].y = asfloat(context->ff.tex_stage[s][D3DTSS_BUMPENVMAT01]); - dst[8 + s].z = asfloat(context->ff.tex_stage[s][D3DTSS_BUMPENVMAT10]); - dst[8 + s].w = asfloat(context->ff.tex_stage[s][D3DTSS_BUMPENVMAT11]); - if (s & 1) { - dst[16 + s / 2].z = asfloat(context->ff.tex_stage[s][D3DTSS_BUMPENVLSCALE]); - dst[16 + s / 2].w = asfloat(context->ff.tex_stage[s][D3DTSS_BUMPENVLOFFSET]); - } else { - dst[16 + s / 2].x = asfloat(context->ff.tex_stage[s][D3DTSS_BUMPENVLSCALE]); - dst[16 + s / 2].y = asfloat(context->ff.tex_stage[s][D3DTSS_BUMPENVLOFFSET]); - } - } - - d3dcolor_to_rgba(&dst[20].x, context->rs[D3DRS_TEXTUREFACTOR]); - d3dcolor_to_rgba(&dst[21].x, context->rs[D3DRS_FOGCOLOR]); - dst[22].x = asfloat(context->rs[D3DRS_FOGEND]); - dst[22].y = 1.0f / (asfloat(context->rs[D3DRS_FOGEND]) - asfloat(context->rs[D3DRS_FOGSTART])); - dst[22].z = asfloat(context->rs[D3DRS_FOGDENSITY]); -} - -static void -nine_ff_load_viewport_info(struct NineDevice9 *device) -{ - D3DVIEWPORT9 *viewport = &device->context.viewport; - struct fvec4 *dst = (struct fvec4 *)device->ff.vs_const; - float diffZ = viewport->MaxZ - viewport->MinZ; - - /* Note: the other functions avoids to fill the const again if nothing changed. - * But we don't have much to fill, and adding code to allow that may be complex - * so just fill it always */ - dst[100].x = 2.0f / (float)(viewport->Width); - dst[100].y = 2.0f / (float)(viewport->Height); - dst[100].z = (diffZ == 0.0f) ? 0.0f : (1.0f / diffZ); - dst[100].w = (float)(viewport->Width); - dst[101].x = (float)(viewport->X); - dst[101].y = (float)(viewport->Y); - dst[101].z = (float)(viewport->MinZ); -} - -void -nine_ff_update(struct NineDevice9 *device) -{ - struct nine_context *context = &device->context; - struct pipe_constant_buffer cb; - - DBG("vs=%p ps=%p\n", context->vs, context->ps); - - /* NOTE: the only reference belongs to the hash table */ - if (!context->programmable_vs) { - device->ff.vs = nine_ff_get_vs(device); - context->changed.group |= NINE_STATE_VS; - } - if (!context->ps) { - device->ff.ps = nine_ff_get_ps(device); - context->changed.group |= NINE_STATE_PS; - } - - if (!context->programmable_vs) { - nine_ff_load_vs_transforms(device); - nine_ff_load_tex_matrices(device); - nine_ff_load_lights(device); - nine_ff_load_point_and_fog_params(device); - nine_ff_load_viewport_info(device); - - memset(context->ff.changed.transform, 0, sizeof(context->ff.changed.transform)); - - cb.buffer_offset = 0; - cb.buffer = NULL; - cb.user_buffer = device->ff.vs_const; - cb.buffer_size = NINE_FF_NUM_VS_CONST * 4 * sizeof(float); - - context->pipe_data.cb_vs_ff = cb; - context->commit |= NINE_STATE_COMMIT_CONST_VS; - - context->changed.group &= ~NINE_STATE_FF_VS; - } - - if (!context->ps) { - nine_ff_load_ps_params(device); - - cb.buffer_offset = 0; - cb.buffer = NULL; - cb.user_buffer = device->ff.ps_const; - cb.buffer_size = NINE_FF_NUM_PS_CONST * 4 * sizeof(float); - - context->pipe_data.cb_ps_ff = cb; - context->commit |= NINE_STATE_COMMIT_CONST_PS; - - context->changed.group &= ~NINE_STATE_FF_PS; - } -} - - -boolean -nine_ff_init(struct NineDevice9 *device) -{ - device->ff.ht_vs = _mesa_hash_table_create(NULL, nine_ff_vs_key_hash, - nine_ff_vs_key_comp); - device->ff.ht_ps = _mesa_hash_table_create(NULL, nine_ff_ps_key_hash, - nine_ff_ps_key_comp); - - device->ff.ht_fvf = _mesa_hash_table_create(NULL, nine_ff_fvf_key_hash, - nine_ff_fvf_key_comp); - - device->ff.vs_const = CALLOC(NINE_FF_NUM_VS_CONST, 4 * sizeof(float)); - device->ff.ps_const = CALLOC(NINE_FF_NUM_PS_CONST, 4 * sizeof(float)); - - return device->ff.ht_vs && device->ff.ht_ps && - device->ff.ht_fvf && - device->ff.vs_const && device->ff.ps_const; -} - -static enum pipe_error nine_ff_ht_delete_cb(void *key, void *value, void *data) -{ - NineUnknown_Unbind(NineUnknown(value)); - return PIPE_OK; -} - -void -nine_ff_fini(struct NineDevice9 *device) -{ - if (device->ff.ht_vs) { - util_hash_table_foreach(device->ff.ht_vs, nine_ff_ht_delete_cb, NULL); - _mesa_hash_table_destroy(device->ff.ht_vs, NULL); - } - if (device->ff.ht_ps) { - util_hash_table_foreach(device->ff.ht_ps, nine_ff_ht_delete_cb, NULL); - _mesa_hash_table_destroy(device->ff.ht_ps, NULL); - } - if (device->ff.ht_fvf) { - util_hash_table_foreach(device->ff.ht_fvf, nine_ff_ht_delete_cb, NULL); - _mesa_hash_table_destroy(device->ff.ht_fvf, NULL); - } - device->ff.vs = NULL; /* destroyed by unbinding from hash table */ - device->ff.ps = NULL; - - FREE(device->ff.vs_const); - FREE(device->ff.ps_const); -} - -static void -nine_ff_prune_vs(struct NineDevice9 *device) -{ - struct nine_context *context = &device->context; - - if (device->ff.num_vs > 1024) { - /* could destroy the bound one here, so unbind */ - context->pipe->bind_vs_state(context->pipe, NULL); - util_hash_table_foreach(device->ff.ht_vs, nine_ff_ht_delete_cb, NULL); - _mesa_hash_table_clear(device->ff.ht_vs, NULL); - device->ff.num_vs = 0; - context->changed.group |= NINE_STATE_VS; - } -} -static void -nine_ff_prune_ps(struct NineDevice9 *device) -{ - struct nine_context *context = &device->context; - - if (device->ff.num_ps > 1024) { - /* could destroy the bound one here, so unbind */ - context->pipe->bind_fs_state(context->pipe, NULL); - util_hash_table_foreach(device->ff.ht_ps, nine_ff_ht_delete_cb, NULL); - _mesa_hash_table_clear(device->ff.ht_ps, NULL); - device->ff.num_ps = 0; - context->changed.group |= NINE_STATE_PS; - } -} - -/* ========================================================================== */ - -/* Matrix multiplication: - * - * in memory: 0 1 2 3 (row major) - * 4 5 6 7 - * 8 9 a b - * c d e f - * - * cA cB cC cD - * r0 = (r0 * cA) (r0 * cB) . . - * r1 = (r1 * cA) (r1 * cB) - * r2 = (r2 * cA) . - * r3 = (r3 * cA) . - * - * r: (11) (12) (13) (14) - * (21) (22) (23) (24) - * (31) (32) (33) (34) - * (41) (42) (43) (44) - * l: (11 12 13 14) - * (21 22 23 24) - * (31 32 33 34) - * (41 42 43 44) - * - * v: (x y z 1 ) - * - * t.xyzw = MUL(v.xxxx, r[0]); - * t.xyzw = MAD(v.yyyy, r[1], t.xyzw); - * t.xyzw = MAD(v.zzzz, r[2], t.xyzw); - * v.xyzw = MAD(v.wwww, r[3], t.xyzw); - * - * v.x = DP4(v, c[0]); - * v.y = DP4(v, c[1]); - * v.z = DP4(v, c[2]); - * v.w = DP4(v, c[3]) = 1 - */ - -/* -static void -nine_D3DMATRIX_print(const D3DMATRIX *M) -{ - DBG("\n(%f %f %f %f)\n" - "(%f %f %f %f)\n" - "(%f %f %f %f)\n" - "(%f %f %f %f)\n", - M->m[0][0], M->m[0][1], M->m[0][2], M->m[0][3], - M->m[1][0], M->m[1][1], M->m[1][2], M->m[1][3], - M->m[2][0], M->m[2][1], M->m[2][2], M->m[2][3], - M->m[3][0], M->m[3][1], M->m[3][2], M->m[3][3]); -} -*/ - -static inline float -nine_DP4_row_col(const D3DMATRIX *A, int r, const D3DMATRIX *B, int c) -{ - return A->m[r][0] * B->m[0][c] + - A->m[r][1] * B->m[1][c] + - A->m[r][2] * B->m[2][c] + - A->m[r][3] * B->m[3][c]; -} - -static inline float -nine_DP4_vec_col(const D3DVECTOR *v, const D3DMATRIX *M, int c) -{ - return v->x * M->m[0][c] + - v->y * M->m[1][c] + - v->z * M->m[2][c] + - 1.0f * M->m[3][c]; -} - -static inline float -nine_DP3_vec_col(const D3DVECTOR *v, const D3DMATRIX *M, int c) -{ - return v->x * M->m[0][c] + - v->y * M->m[1][c] + - v->z * M->m[2][c]; -} - -void -nine_d3d_matrix_matrix_mul(D3DMATRIX *D, const D3DMATRIX *L, const D3DMATRIX *R) -{ - D->_11 = nine_DP4_row_col(L, 0, R, 0); - D->_12 = nine_DP4_row_col(L, 0, R, 1); - D->_13 = nine_DP4_row_col(L, 0, R, 2); - D->_14 = nine_DP4_row_col(L, 0, R, 3); - - D->_21 = nine_DP4_row_col(L, 1, R, 0); - D->_22 = nine_DP4_row_col(L, 1, R, 1); - D->_23 = nine_DP4_row_col(L, 1, R, 2); - D->_24 = nine_DP4_row_col(L, 1, R, 3); - - D->_31 = nine_DP4_row_col(L, 2, R, 0); - D->_32 = nine_DP4_row_col(L, 2, R, 1); - D->_33 = nine_DP4_row_col(L, 2, R, 2); - D->_34 = nine_DP4_row_col(L, 2, R, 3); - - D->_41 = nine_DP4_row_col(L, 3, R, 0); - D->_42 = nine_DP4_row_col(L, 3, R, 1); - D->_43 = nine_DP4_row_col(L, 3, R, 2); - D->_44 = nine_DP4_row_col(L, 3, R, 3); -} - -void -nine_d3d_vector4_matrix_mul(D3DVECTOR *d, const D3DVECTOR *v, const D3DMATRIX *M) -{ - d->x = nine_DP4_vec_col(v, M, 0); - d->y = nine_DP4_vec_col(v, M, 1); - d->z = nine_DP4_vec_col(v, M, 2); -} - -void -nine_d3d_vector3_matrix_mul(D3DVECTOR *d, const D3DVECTOR *v, const D3DMATRIX *M) -{ - d->x = nine_DP3_vec_col(v, M, 0); - d->y = nine_DP3_vec_col(v, M, 1); - d->z = nine_DP3_vec_col(v, M, 2); -} - -void -nine_d3d_matrix_transpose(D3DMATRIX *D, const D3DMATRIX *M) -{ - unsigned i, j; - for (i = 0; i < 4; ++i) - for (j = 0; j < 4; ++j) - D->m[i][j] = M->m[j][i]; -} - -#define _M_ADD_PROD_1i_2j_3k_4l(i,j,k,l) do { \ - float t = M->_1##i * M->_2##j * M->_3##k * M->_4##l; \ - if (t > 0.0f) pos += t; else neg += t; } while(0) - -#define _M_SUB_PROD_1i_2j_3k_4l(i,j,k,l) do { \ - float t = M->_1##i * M->_2##j * M->_3##k * M->_4##l; \ - if (t > 0.0f) neg -= t; else pos -= t; } while(0) -float -nine_d3d_matrix_det(const D3DMATRIX *M) -{ - float pos = 0.0f; - float neg = 0.0f; - - _M_ADD_PROD_1i_2j_3k_4l(1, 2, 3, 4); - _M_ADD_PROD_1i_2j_3k_4l(1, 3, 4, 2); - _M_ADD_PROD_1i_2j_3k_4l(1, 4, 2, 3); - - _M_ADD_PROD_1i_2j_3k_4l(2, 1, 4, 3); - _M_ADD_PROD_1i_2j_3k_4l(2, 3, 1, 4); - _M_ADD_PROD_1i_2j_3k_4l(2, 4, 3, 1); - - _M_ADD_PROD_1i_2j_3k_4l(3, 1, 2, 4); - _M_ADD_PROD_1i_2j_3k_4l(3, 2, 4, 1); - _M_ADD_PROD_1i_2j_3k_4l(3, 4, 1, 2); - - _M_ADD_PROD_1i_2j_3k_4l(4, 1, 3, 2); - _M_ADD_PROD_1i_2j_3k_4l(4, 2, 1, 3); - _M_ADD_PROD_1i_2j_3k_4l(4, 3, 2, 1); - - _M_SUB_PROD_1i_2j_3k_4l(1, 2, 4, 3); - _M_SUB_PROD_1i_2j_3k_4l(1, 3, 2, 4); - _M_SUB_PROD_1i_2j_3k_4l(1, 4, 3, 2); - - _M_SUB_PROD_1i_2j_3k_4l(2, 1, 3, 4); - _M_SUB_PROD_1i_2j_3k_4l(2, 3, 4, 1); - _M_SUB_PROD_1i_2j_3k_4l(2, 4, 1, 3); - - _M_SUB_PROD_1i_2j_3k_4l(3, 1, 4, 2); - _M_SUB_PROD_1i_2j_3k_4l(3, 2, 1, 4); - _M_SUB_PROD_1i_2j_3k_4l(3, 4, 2, 1); - - _M_SUB_PROD_1i_2j_3k_4l(4, 1, 2, 3); - _M_SUB_PROD_1i_2j_3k_4l(4, 2, 3, 1); - _M_SUB_PROD_1i_2j_3k_4l(4, 3, 1, 2); - - return pos + neg; -} - -/* XXX: Probably better to just use src/mesa/math/m_matrix.c because - * I have no idea where this code came from. - */ -void -nine_d3d_matrix_inverse(D3DMATRIX *D, const D3DMATRIX *M) -{ - int i, k; - float det; - - D->m[0][0] = - M->m[1][1] * M->m[2][2] * M->m[3][3] - - M->m[1][1] * M->m[3][2] * M->m[2][3] - - M->m[1][2] * M->m[2][1] * M->m[3][3] + - M->m[1][2] * M->m[3][1] * M->m[2][3] + - M->m[1][3] * M->m[2][1] * M->m[3][2] - - M->m[1][3] * M->m[3][1] * M->m[2][2]; - - D->m[0][1] = - -M->m[0][1] * M->m[2][2] * M->m[3][3] + - M->m[0][1] * M->m[3][2] * M->m[2][3] + - M->m[0][2] * M->m[2][1] * M->m[3][3] - - M->m[0][2] * M->m[3][1] * M->m[2][3] - - M->m[0][3] * M->m[2][1] * M->m[3][2] + - M->m[0][3] * M->m[3][1] * M->m[2][2]; - - D->m[0][2] = - M->m[0][1] * M->m[1][2] * M->m[3][3] - - M->m[0][1] * M->m[3][2] * M->m[1][3] - - M->m[0][2] * M->m[1][1] * M->m[3][3] + - M->m[0][2] * M->m[3][1] * M->m[1][3] + - M->m[0][3] * M->m[1][1] * M->m[3][2] - - M->m[0][3] * M->m[3][1] * M->m[1][2]; - - D->m[0][3] = - -M->m[0][1] * M->m[1][2] * M->m[2][3] + - M->m[0][1] * M->m[2][2] * M->m[1][3] + - M->m[0][2] * M->m[1][1] * M->m[2][3] - - M->m[0][2] * M->m[2][1] * M->m[1][3] - - M->m[0][3] * M->m[1][1] * M->m[2][2] + - M->m[0][3] * M->m[2][1] * M->m[1][2]; - - D->m[1][0] = - -M->m[1][0] * M->m[2][2] * M->m[3][3] + - M->m[1][0] * M->m[3][2] * M->m[2][3] + - M->m[1][2] * M->m[2][0] * M->m[3][3] - - M->m[1][2] * M->m[3][0] * M->m[2][3] - - M->m[1][3] * M->m[2][0] * M->m[3][2] + - M->m[1][3] * M->m[3][0] * M->m[2][2]; - - D->m[1][1] = - M->m[0][0] * M->m[2][2] * M->m[3][3] - - M->m[0][0] * M->m[3][2] * M->m[2][3] - - M->m[0][2] * M->m[2][0] * M->m[3][3] + - M->m[0][2] * M->m[3][0] * M->m[2][3] + - M->m[0][3] * M->m[2][0] * M->m[3][2] - - M->m[0][3] * M->m[3][0] * M->m[2][2]; - - D->m[1][2] = - -M->m[0][0] * M->m[1][2] * M->m[3][3] + - M->m[0][0] * M->m[3][2] * M->m[1][3] + - M->m[0][2] * M->m[1][0] * M->m[3][3] - - M->m[0][2] * M->m[3][0] * M->m[1][3] - - M->m[0][3] * M->m[1][0] * M->m[3][2] + - M->m[0][3] * M->m[3][0] * M->m[1][2]; - - D->m[1][3] = - M->m[0][0] * M->m[1][2] * M->m[2][3] - - M->m[0][0] * M->m[2][2] * M->m[1][3] - - M->m[0][2] * M->m[1][0] * M->m[2][3] + - M->m[0][2] * M->m[2][0] * M->m[1][3] + - M->m[0][3] * M->m[1][0] * M->m[2][2] - - M->m[0][3] * M->m[2][0] * M->m[1][2]; - - D->m[2][0] = - M->m[1][0] * M->m[2][1] * M->m[3][3] - - M->m[1][0] * M->m[3][1] * M->m[2][3] - - M->m[1][1] * M->m[2][0] * M->m[3][3] + - M->m[1][1] * M->m[3][0] * M->m[2][3] + - M->m[1][3] * M->m[2][0] * M->m[3][1] - - M->m[1][3] * M->m[3][0] * M->m[2][1]; - - D->m[2][1] = - -M->m[0][0] * M->m[2][1] * M->m[3][3] + - M->m[0][0] * M->m[3][1] * M->m[2][3] + - M->m[0][1] * M->m[2][0] * M->m[3][3] - - M->m[0][1] * M->m[3][0] * M->m[2][3] - - M->m[0][3] * M->m[2][0] * M->m[3][1] + - M->m[0][3] * M->m[3][0] * M->m[2][1]; - - D->m[2][2] = - M->m[0][0] * M->m[1][1] * M->m[3][3] - - M->m[0][0] * M->m[3][1] * M->m[1][3] - - M->m[0][1] * M->m[1][0] * M->m[3][3] + - M->m[0][1] * M->m[3][0] * M->m[1][3] + - M->m[0][3] * M->m[1][0] * M->m[3][1] - - M->m[0][3] * M->m[3][0] * M->m[1][1]; - - D->m[2][3] = - -M->m[0][0] * M->m[1][1] * M->m[2][3] + - M->m[0][0] * M->m[2][1] * M->m[1][3] + - M->m[0][1] * M->m[1][0] * M->m[2][3] - - M->m[0][1] * M->m[2][0] * M->m[1][3] - - M->m[0][3] * M->m[1][0] * M->m[2][1] + - M->m[0][3] * M->m[2][0] * M->m[1][1]; - - D->m[3][0] = - -M->m[1][0] * M->m[2][1] * M->m[3][2] + - M->m[1][0] * M->m[3][1] * M->m[2][2] + - M->m[1][1] * M->m[2][0] * M->m[3][2] - - M->m[1][1] * M->m[3][0] * M->m[2][2] - - M->m[1][2] * M->m[2][0] * M->m[3][1] + - M->m[1][2] * M->m[3][0] * M->m[2][1]; - - D->m[3][1] = - M->m[0][0] * M->m[2][1] * M->m[3][2] - - M->m[0][0] * M->m[3][1] * M->m[2][2] - - M->m[0][1] * M->m[2][0] * M->m[3][2] + - M->m[0][1] * M->m[3][0] * M->m[2][2] + - M->m[0][2] * M->m[2][0] * M->m[3][1] - - M->m[0][2] * M->m[3][0] * M->m[2][1]; - - D->m[3][2] = - -M->m[0][0] * M->m[1][1] * M->m[3][2] + - M->m[0][0] * M->m[3][1] * M->m[1][2] + - M->m[0][1] * M->m[1][0] * M->m[3][2] - - M->m[0][1] * M->m[3][0] * M->m[1][2] - - M->m[0][2] * M->m[1][0] * M->m[3][1] + - M->m[0][2] * M->m[3][0] * M->m[1][1]; - - D->m[3][3] = - M->m[0][0] * M->m[1][1] * M->m[2][2] - - M->m[0][0] * M->m[2][1] * M->m[1][2] - - M->m[0][1] * M->m[1][0] * M->m[2][2] + - M->m[0][1] * M->m[2][0] * M->m[1][2] + - M->m[0][2] * M->m[1][0] * M->m[2][1] - - M->m[0][2] * M->m[2][0] * M->m[1][1]; - - det = - M->m[0][0] * D->m[0][0] + - M->m[1][0] * D->m[0][1] + - M->m[2][0] * D->m[0][2] + - M->m[3][0] * D->m[0][3]; - - if (fabsf(det) < 1e-30) {/* non inversible */ - *D = *M; /* wine tests */ - return; - } - - det = 1.0 / det; - - for (i = 0; i < 4; i++) - for (k = 0; k < 4; k++) - D->m[i][k] *= det; - -#if defined(DEBUG) || !defined(NDEBUG) - { - D3DMATRIX I; - - nine_d3d_matrix_matrix_mul(&I, D, M); - - for (i = 0; i < 4; ++i) - for (k = 0; k < 4; ++k) - if (fabsf(I.m[i][k] - (float)(i == k)) > 1e-3) - DBG("Matrix inversion check FAILED !\n"); - } -#endif -} diff --git a/src/gallium/state_trackers/nine/nine_ff.h b/src/gallium/state_trackers/nine/nine_ff.h deleted file mode 100644 index 5345b99dbb5..00000000000 --- a/src/gallium/state_trackers/nine/nine_ff.h +++ /dev/null @@ -1,126 +0,0 @@ - -#ifndef _NINE_FF_H_ -#define _NINE_FF_H_ - -#include "device9.h" -#include "vertexdeclaration9.h" - -boolean nine_ff_init(struct NineDevice9 *); -void nine_ff_fini(struct NineDevice9 *); - -void nine_ff_update(struct NineDevice9 *); - -void -nine_d3d_matrix_matrix_mul(D3DMATRIX *, const D3DMATRIX *, const D3DMATRIX *); - -void -nine_d3d_vector4_matrix_mul(D3DVECTOR *, const D3DVECTOR *, const D3DMATRIX *); -void -nine_d3d_vector3_matrix_mul(D3DVECTOR *, const D3DVECTOR *, const D3DMATRIX *); - -float -nine_d3d_matrix_det(const D3DMATRIX *); - -void -nine_d3d_matrix_inverse(D3DMATRIX *, const D3DMATRIX *); - -void -nine_d3d_matrix_transpose(D3DMATRIX *, const D3DMATRIX *); - -#define NINED3DTSS_TCI_DISABLE 0 -#define NINED3DTSS_TCI_PASSTHRU 1 -#define NINED3DTSS_TCI_CAMERASPACENORMAL 2 -#define NINED3DTSS_TCI_CAMERASPACEPOSITION 3 -#define NINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR 4 -#define NINED3DTSS_TCI_SPHEREMAP 5 - -static inline unsigned -nine_decltype_get_dim(BYTE type) -{ - switch (type) { - case D3DDECLTYPE_FLOAT1: return 1; - case D3DDECLTYPE_FLOAT2: return 2; - case D3DDECLTYPE_FLOAT3: return 3; - case D3DDECLTYPE_FLOAT4: return 4; - case D3DDECLTYPE_D3DCOLOR: return 1; - case D3DDECLTYPE_UBYTE4: return 4; - case D3DDECLTYPE_SHORT2: return 2; - case D3DDECLTYPE_SHORT4: return 4; - case D3DDECLTYPE_UBYTE4N: return 4; - case D3DDECLTYPE_SHORT2N: return 2; - case D3DDECLTYPE_SHORT4N: return 4; - case D3DDECLTYPE_USHORT2N: return 2; - case D3DDECLTYPE_USHORT4N: return 4; - case D3DDECLTYPE_UDEC3: return 3; - case D3DDECLTYPE_DEC3N: return 3; - case D3DDECLTYPE_FLOAT16_2: return 2; - case D3DDECLTYPE_FLOAT16_4: return 4; - default: - assert(!"Implementation error !"); - } - return 0; -} - -static inline uint16_t -nine_ff_get_projected_key(struct nine_context *context, unsigned num_stages) -{ - unsigned s, i; - uint16_t projected = 0; - char input_texture_coord[num_stages]; - memset(&input_texture_coord, 0, sizeof(input_texture_coord)); - - if (context->vdecl) { - for (i = 0; i < context->vdecl->nelems; i++) { - uint16_t usage = context->vdecl->usage_map[i]; - if (usage % NINE_DECLUSAGE_COUNT == NINE_DECLUSAGE_TEXCOORD) { - s = usage / NINE_DECLUSAGE_COUNT; - if (s < num_stages) - input_texture_coord[s] = nine_decltype_get_dim(context->vdecl->decls[i].Type); - } - } - } - - for (s = 0; s < num_stages; ++s) { - unsigned gen = (context->ff.tex_stage[s][D3DTSS_TEXCOORDINDEX] >> 16) + 1; - unsigned dim = context->ff.tex_stage[s][D3DTSS_TEXTURETRANSFORMFLAGS] & 0x7; - unsigned proj = !!(context->ff.tex_stage[s][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED); - - if (!context->vs) { - if (dim > 4) - dim = input_texture_coord[s]; - - if (!dim && gen == NINED3DTSS_TCI_PASSTHRU) - dim = input_texture_coord[s]; - else if (!dim) - dim = 4; - - if (dim == 1) /* NV behaviour */ - proj = 0; - if (dim > input_texture_coord[s] && gen == NINED3DTSS_TCI_PASSTHRU) - proj = 0; - } else { - dim = 4; - } - if (proj) - projected |= (dim-1) << (2 * s); - } - return projected; -} - -static inline uint16_t -nine_ff_get_projected_key_ff(struct nine_context *context) -{ - /* 8 stages */ - return nine_ff_get_projected_key(context, 8); -} - -static inline uint8_t -nine_ff_get_projected_key_programmable(struct nine_context *context) -{ - /* We only look at the 4 stages because this function - * is used only for ps 1.1-3, where only the first four - * slots are available */ - return (uint8_t)nine_ff_get_projected_key(context, 4); -} - -#endif /* _NINE_FF_H_ */ diff --git a/src/gallium/state_trackers/nine/nine_flags.h b/src/gallium/state_trackers/nine/nine_flags.h deleted file mode 100644 index 61686a7f60f..00000000000 --- a/src/gallium/state_trackers/nine/nine_flags.h +++ /dev/null @@ -1,14 +0,0 @@ - - -#ifndef _NINE_FLAGS_H_ -#define _NINE_FLAGS_H_ - -#include "pipe/p_compiler.h" - -/* Incoming 32 bits calls are 4-byte aligned. - * We need to realign them to be able to use - * SSE and to work with other libraries (llvm, etc) - */ -#define NINE_WINAPI WINAPI PIPE_ALIGN_STACK - -#endif /* _NINE_FLAGS_H_ */ \ No newline at end of file diff --git a/src/gallium/state_trackers/nine/nine_helpers.c b/src/gallium/state_trackers/nine/nine_helpers.c deleted file mode 100644 index 98c2ae30eba..00000000000 --- a/src/gallium/state_trackers/nine/nine_helpers.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright 2013 Christoph Bumiller - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "nine_helpers.h" - -static struct nine_range * -nine_range_pool_more(struct nine_range_pool *pool) -{ - struct nine_range *r = MALLOC(64 * sizeof(struct nine_range)); - int i; - assert(!pool->free); - - if (pool->num_slabs == pool->num_slabs_max) { - unsigned p = pool->num_slabs_max; - unsigned n = pool->num_slabs_max * 2; - if (!n) - n = 4; - pool->slabs = REALLOC(pool->slabs, - p * sizeof(struct nine_range *), - n * sizeof(struct nine_range *)); - pool->num_slabs_max = n; - } - pool->free = pool->slabs[pool->num_slabs++] = r; - - for (i = 0; i < 63; ++i, r = r->next) - r->next = (struct nine_range *) - ((uint8_t *)r + sizeof(struct nine_range)); - r->next = NULL; - - return pool->free; -} - -static inline struct nine_range * -nine_range_pool_get(struct nine_range_pool *pool, int16_t bgn, int16_t end) -{ - struct nine_range *r = pool->free; - if (!r) - r = nine_range_pool_more(pool); - assert(r); - pool->free = r->next; - r->bgn = bgn; - r->end = end; - return r; -} - -static inline void -nine_ranges_coalesce(struct nine_range *r, struct nine_range_pool *pool) -{ - struct nine_range *n; - - while (r->next && r->end >= r->next->bgn) { - n = r->next->next; - r->end = (r->end >= r->next->end) ? r->end : r->next->end; - nine_range_pool_put(pool, r->next); - r->next = n; - } -} - -void -nine_ranges_insert(struct nine_range **head, int16_t bgn, int16_t end, - struct nine_range_pool *pool) -{ - struct nine_range *r, **pn = head; - - for (r = *head; r && bgn > r->end; pn = &r->next, r = r->next); - - if (!r || end < r->bgn) { - *pn = nine_range_pool_get(pool, bgn, end); - (*pn)->next = r; - } else - if (bgn < r->bgn) { - r->bgn = bgn; - if (end > r->end) - r->end = end; - nine_ranges_coalesce(r, pool); - } else - if (end > r->end) { - r->end = end; - nine_ranges_coalesce(r, pool); - } -} diff --git a/src/gallium/state_trackers/nine/nine_helpers.h b/src/gallium/state_trackers/nine/nine_helpers.h deleted file mode 100644 index c14dd1c04fc..00000000000 --- a/src/gallium/state_trackers/nine/nine_helpers.h +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef _NINE_HELPERS_H_ -#define _NINE_HELPERS_H_ - -#include "iunknown.h" -#include "nine_lock.h" - -/* - * Note: we use these function rather than the MIN2, MAX2, CLAMP macros to - * avoid evaluating arguments (which are often function calls) more than once. - */ - -static inline unsigned _min(unsigned a, unsigned b) -{ - return (a < b) ? a : b; -} - - -/* Sshhh ... */ -#define nine_reference(a, b) _nine_reference((void **)(a), (b)) - -static inline void _nine_reference(void **ref, void *ptr) -{ - if (*ref != ptr) { - if (*ref) - NineUnknown_Release(*ref); - if (ptr) - NineUnknown_AddRef(ptr); - *ref = ptr; - } -} - -#define nine_reference_set(a, b) _nine_reference_set((void **)(a), (b)) - -static inline void _nine_reference_set(void **ref, void *ptr) -{ - *ref = ptr; - if (ptr) - NineUnknown_AddRef(ptr); -} - -#define nine_bind(a, b) _nine_bind((void **)(a), (b)) - -static inline void _nine_bind(void **dst, void *obj) -{ - if (*dst != obj) { - if (*dst) - NineUnknown_Unbind(*dst); - if (obj) - NineUnknown_Bind(obj); - *dst = obj; - } -} - -#define NINE_DEVICE_CHILD_NEW(nine, out, dev, ...) \ - { \ - struct NineUnknownParams __params; \ - struct Nine##nine *__data; \ - \ - __data = CALLOC_STRUCT(Nine##nine); \ - if (!__data) { return E_OUTOFMEMORY; } \ - \ - __params.vtable = ((dev)->params.BehaviorFlags & D3DCREATE_MULTITHREADED) ? &Lock##nine##_vtable : &Nine##nine##_vtable; \ - __params.guids = Nine##nine##_IIDs; \ - __params.dtor = (void *)Nine##nine##_dtor; \ - __params.container = NULL; \ - __params.device = dev; \ - __params.start_with_bind_not_ref = false; \ - { \ - HRESULT __hr = Nine##nine##_ctor(__data, &__params, ## __VA_ARGS__); \ - if (FAILED(__hr)) { \ - Nine##nine##_dtor(__data); \ - return __hr; \ - } \ - } \ - \ - *(out) = __data; \ - } \ - return D3D_OK - -#define NINE_DEVICE_CHILD_BIND_NEW(nine, out, dev, ...) \ - { \ - struct NineUnknownParams __params; \ - struct Nine##nine *__data; \ - \ - __data = CALLOC_STRUCT(Nine##nine); \ - if (!__data) { return E_OUTOFMEMORY; } \ - \ - __params.vtable = ((dev)->params.BehaviorFlags & D3DCREATE_MULTITHREADED) ? &Lock##nine##_vtable : &Nine##nine##_vtable; \ - __params.guids = Nine##nine##_IIDs; \ - __params.dtor = (void *)Nine##nine##_dtor; \ - __params.container = NULL; \ - __params.device = dev; \ - __params.start_with_bind_not_ref = true; \ - { \ - HRESULT __hr = Nine##nine##_ctor(__data, &__params, ## __VA_ARGS__); \ - if (FAILED(__hr)) { \ - Nine##nine##_dtor(__data); \ - return __hr; \ - } \ - } \ - \ - *(out) = __data; \ - } \ - return D3D_OK - -#define NINE_NEW(nine, out, lock, ...) \ - { \ - struct NineUnknownParams __params; \ - struct Nine##nine *__data; \ - \ - __data = CALLOC_STRUCT(Nine##nine); \ - if (!__data) { return E_OUTOFMEMORY; } \ - \ - __params.vtable = (lock) ? &Lock##nine##_vtable : &Nine##nine##_vtable; \ - __params.guids = Nine##nine##_IIDs; \ - __params.dtor = (void *)Nine##nine##_dtor; \ - __params.container = NULL; \ - __params.device = NULL; \ - __params.start_with_bind_not_ref = false; \ - { \ - HRESULT __hr = Nine##nine##_ctor(__data, &__params, ## __VA_ARGS__); \ - if (FAILED(__hr)) { \ - Nine##nine##_dtor(__data); \ - return __hr; \ - } \ - } \ - \ - *(out) = __data; \ - } \ - return D3D_OK - -static inline float asfloat(DWORD value) -{ - union { - float f; - DWORD w; - } u; - u.w = value; - return u.f; -} - -struct nine_range -{ - struct nine_range *next; - int16_t bgn; /* inclusive */ - int16_t end; /* exclusive */ -}; - -/* We won't ever need more than 256 ranges, so just allocate once. */ -struct nine_range_pool -{ - struct nine_range *free; - struct nine_range **slabs; - unsigned num_slabs; - unsigned num_slabs_max; -}; - -static inline void -nine_range_pool_put(struct nine_range_pool *pool, struct nine_range *r) -{ - r->next = pool->free; - pool->free = r; -} - -static inline void -nine_range_pool_put_chain(struct nine_range_pool *pool, - struct nine_range *head, - struct nine_range *tail) -{ - tail->next = pool->free; - pool->free = head; -} - -void -nine_ranges_insert(struct nine_range **head, int16_t bgn, int16_t end, - struct nine_range_pool *pool); - -#endif /* _NINE_HELPERS_H_ */ diff --git a/src/gallium/state_trackers/nine/nine_limits.h b/src/gallium/state_trackers/nine/nine_limits.h deleted file mode 100644 index b5090daa11d..00000000000 --- a/src/gallium/state_trackers/nine/nine_limits.h +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright 2015 Axel Davy - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef _NINE_LIMITS_H_ -#define _NINE_LIMITS_H_ - -#include "assert.h" -#include "d3d9types.h" - -// state can be any value -#define NINE_STATE_NO_LIMIT 0 -// value is clamped if below min or max -#define NINE_STATE_CLAMP 1 -// boolean: 0 -> false; any other value -> true -#define NINE_STATE_BOOL 2 -// a mask is applied on the value -#define NINE_STATE_MASK 3 -// if outside a range, state value is changed to a default value -#define NINE_STATE_RANGE_DEF_VAL 4 - -struct nine_state_behaviour { - unsigned state_value_behaviour; - union { - struct { - unsigned min; - unsigned max; - } clamp; - unsigned mask; - struct { - unsigned min; - unsigned max; - unsigned default_val; - } range_def_val; - } u; -}; - -#define __NO_LIMIT_RS(o) \ - [D3DRS_##o] = {NINE_STATE_NO_LIMIT} - -#define __CLAMP_RS(o, m, M) \ - [D3DRS_##o] = {NINE_STATE_CLAMP, {.clamp = {m, M}}} - -#define __BOOLEAN_RS(o) \ - [D3DRS_##o] = {NINE_STATE_BOOL} - -#define __MASK_RS(o, m) \ - [D3DRS_##o] = {NINE_STATE_MASK, {.mask = m}} - -#define __RANGE_DEF_VAL_RS(o, m, M, d) \ - [D3DRS_##o] = {NINE_STATE_RANGE_DEF_VAL, {.range_def_val = {m, M, d}}} - -#define __TO_DETERMINE_RS(o, m, M) \ - [D3DRS_##o] = {NINE_STATE_NO_LIMIT} - -static const struct nine_state_behaviour -render_state_limits_table[D3DRS_BLENDOPALPHA + 1] = { - __TO_DETERMINE_RS(ZENABLE, 0, 3), - __TO_DETERMINE_RS(FILLMODE, 1, 3), - __CLAMP_RS(SHADEMODE, 1, 3), - __BOOLEAN_RS(ZWRITEENABLE), - __BOOLEAN_RS(ALPHATESTENABLE), - __BOOLEAN_RS(LASTPIXEL), - __RANGE_DEF_VAL_RS(SRCBLEND, 1, 17, D3DBLEND_ZERO), - __RANGE_DEF_VAL_RS(DESTBLEND, 1, 17, D3DBLEND_ZERO), - __CLAMP_RS(CULLMODE, 1, 3), - __CLAMP_RS(ZFUNC, 1, 8), - __MASK_RS(ALPHAREF, 0x000000FF), - __CLAMP_RS(ALPHAFUNC, 1, 8), - __BOOLEAN_RS(DITHERENABLE), - __BOOLEAN_RS(ALPHABLENDENABLE), - __BOOLEAN_RS(FOGENABLE), - __BOOLEAN_RS(SPECULARENABLE), - __NO_LIMIT_RS(FOGCOLOR), - __MASK_RS(FOGTABLEMODE, 0x00000007), - __NO_LIMIT_RS(FOGSTART), /* a bit more complex than that, lets ignore */ - __NO_LIMIT_RS(FOGEND), - __NO_LIMIT_RS(FOGDENSITY), /* actually should be between 0.0 and 1.0 */ - __BOOLEAN_RS(RANGEFOGENABLE), - __BOOLEAN_RS(STENCILENABLE), - __CLAMP_RS(STENCILFAIL, 1, 8), - __CLAMP_RS(STENCILZFAIL, 1, 8), - __CLAMP_RS(STENCILPASS, 1, 8), - __CLAMP_RS(STENCILFUNC, 1, 8), - __NO_LIMIT_RS(STENCILREF), - __NO_LIMIT_RS(STENCILMASK), - __NO_LIMIT_RS(STENCILWRITEMASK), - __NO_LIMIT_RS(TEXTUREFACTOR), - __TO_DETERMINE_RS(WRAP0, 0, 15), - __TO_DETERMINE_RS(WRAP1, 0, 15), - __TO_DETERMINE_RS(WRAP2, 0, 15), - __TO_DETERMINE_RS(WRAP3, 0, 15), - __TO_DETERMINE_RS(WRAP4, 0, 15), - __TO_DETERMINE_RS(WRAP5, 0, 15), - __TO_DETERMINE_RS(WRAP6, 0, 15), - __TO_DETERMINE_RS(WRAP7, 0, 15), - __BOOLEAN_RS(CLIPPING), - __BOOLEAN_RS(LIGHTING), - __NO_LIMIT_RS(AMBIENT), - __MASK_RS(FOGVERTEXMODE, 0x00000007), - __BOOLEAN_RS(COLORVERTEX), - __BOOLEAN_RS(LOCALVIEWER), - __BOOLEAN_RS(NORMALIZENORMALS), - __TO_DETERMINE_RS(DIFFUSEMATERIALSOURCE, 0, 2), - __TO_DETERMINE_RS(SPECULARMATERIALSOURCE, 0, 2), - __TO_DETERMINE_RS(AMBIENTMATERIALSOURCE, 0, 2), - __TO_DETERMINE_RS(EMISSIVEMATERIALSOURCE, 0, 2), - __TO_DETERMINE_RS(VERTEXBLEND, 0, 256), /* values between 4 and 254 -both included- are forbidden too */ - __NO_LIMIT_RS(CLIPPLANEENABLE), /* expected check seems complex */ - __TO_DETERMINE_RS(POINTSIZE, 0, 0xFFFFFFFF), - __TO_DETERMINE_RS(POINTSIZE_MIN, 0, 0x7FFFFFFF), /* float >= 0.0 */ - __BOOLEAN_RS(POINTSPRITEENABLE), - __BOOLEAN_RS(POINTSCALEENABLE), - __TO_DETERMINE_RS(POINTSCALE_A, 0, 0x7FFFFFFF), /* float >= 0.0 */ - __TO_DETERMINE_RS(POINTSCALE_B, 0, 0x7FFFFFFF), /* float >= 0.0 */ - __TO_DETERMINE_RS(POINTSCALE_C, 0, 0x7FFFFFFF), /* float >= 0.0 */ - __BOOLEAN_RS(MULTISAMPLEANTIALIAS), - __NO_LIMIT_RS(MULTISAMPLEMASK), - __TO_DETERMINE_RS(PATCHEDGESTYLE, 0, 1), - __TO_DETERMINE_RS(DEBUGMONITORTOKEN, 0, 1), - __TO_DETERMINE_RS(POINTSIZE_MAX, 0, 0x7FFFFFFF), /* check more complex than that */ - __BOOLEAN_RS(INDEXEDVERTEXBLENDENABLE), - __TO_DETERMINE_RS(COLORWRITEENABLE, 0, 15), - __NO_LIMIT_RS(TWEENFACTOR), - __CLAMP_RS(BLENDOP, 1, 5), - __TO_DETERMINE_RS(POSITIONDEGREE, 1, 5), /* can actually be only 1 or 5 */ - __TO_DETERMINE_RS(NORMALDEGREE, 1, 2), - __BOOLEAN_RS(SCISSORTESTENABLE), - __NO_LIMIT_RS(SLOPESCALEDEPTHBIAS), - __BOOLEAN_RS(ANTIALIASEDLINEENABLE), - __NO_LIMIT_RS(MINTESSELLATIONLEVEL), - __NO_LIMIT_RS(MAXTESSELLATIONLEVEL), - __NO_LIMIT_RS(ADAPTIVETESS_X), - __NO_LIMIT_RS(ADAPTIVETESS_Y), - __NO_LIMIT_RS(ADAPTIVETESS_Z), - __NO_LIMIT_RS(ADAPTIVETESS_W), - __BOOLEAN_RS(ENABLEADAPTIVETESSELLATION), - __BOOLEAN_RS(TWOSIDEDSTENCILMODE), - __CLAMP_RS(CCW_STENCILFAIL, 1, 8), - __CLAMP_RS(CCW_STENCILZFAIL, 1, 8), - __CLAMP_RS(CCW_STENCILPASS, 1, 8), - __CLAMP_RS(CCW_STENCILFUNC, 1, 8), - __TO_DETERMINE_RS(COLORWRITEENABLE1, 0, 15), - __TO_DETERMINE_RS(COLORWRITEENABLE2, 0, 15), - __TO_DETERMINE_RS(COLORWRITEENABLE3, 0, 15), - __NO_LIMIT_RS(BLENDFACTOR), - __BOOLEAN_RS(SRGBWRITEENABLE), - __NO_LIMIT_RS(DEPTHBIAS), - __TO_DETERMINE_RS(WRAP8, 0, 15), - __TO_DETERMINE_RS(WRAP9, 0, 15), - __TO_DETERMINE_RS(WRAP10, 0, 15), - __TO_DETERMINE_RS(WRAP11, 0, 15), - __TO_DETERMINE_RS(WRAP12, 0, 15), - __TO_DETERMINE_RS(WRAP13, 0, 15), - __TO_DETERMINE_RS(WRAP14, 0, 15), - __TO_DETERMINE_RS(WRAP15, 0, 15), - __BOOLEAN_RS(SEPARATEALPHABLENDENABLE), - __RANGE_DEF_VAL_RS(SRCBLENDALPHA, 1, 17, D3DBLEND_ZERO), - __RANGE_DEF_VAL_RS(DESTBLENDALPHA, 1, 17, D3DBLEND_ZERO), - __CLAMP_RS(BLENDOPALPHA, 1, 5) -}; - -static DWORD inline -nine_fix_render_state_value(D3DRENDERSTATETYPE State, - DWORD Value) -{ - struct nine_state_behaviour behaviour = render_state_limits_table[State]; - - switch (behaviour.state_value_behaviour) { - case NINE_STATE_NO_LIMIT: - break; - case NINE_STATE_CLAMP: - if (Value < behaviour.u.clamp.min) - Value = behaviour.u.clamp.min; - else if (Value > behaviour.u.clamp.max) - Value = behaviour.u.clamp.max; - break; - case NINE_STATE_BOOL: - Value = Value ? 1 : 0; - break; - case NINE_STATE_MASK: - Value = Value & behaviour.u.mask; - break; - case NINE_STATE_RANGE_DEF_VAL: - if (Value < behaviour.u.range_def_val.min || Value > behaviour.u.range_def_val.max) - Value = behaviour.u.range_def_val.default_val; - break; - } - - return Value; -} - -struct nine_limits -{ - unsigned min; - unsigned max; -}; - -#define __VALUE_SAMP(o, m, M) \ - [D3DSAMP_##o] = {m, M} - -static const struct nine_limits -sampler_state_limits_table[D3DRS_BLENDOPALPHA + 1] = { - __VALUE_SAMP(ADDRESSU, 1, 5), - __VALUE_SAMP(ADDRESSV, 1, 5), - __VALUE_SAMP(ADDRESSW, 1, 5), - __VALUE_SAMP(BORDERCOLOR, 0, 0xFFFFFFFF), - __VALUE_SAMP(MAGFILTER, 0, 8), /* 4-5 should be forbidden */ - __VALUE_SAMP(MINFILTER, 0, 8), /* same */ - __VALUE_SAMP(MIPFILTER, 0, 8), /* same */ - __VALUE_SAMP(MIPMAPLODBIAS, 0, 0xFFFFFFFF), - __VALUE_SAMP(MAXMIPLEVEL, 0, 0xFFFFFFFF), - __VALUE_SAMP(MAXANISOTROPY, 1, 0xFFFFFFFF), /* Max value should be pCaps->MaxAnisotropy */ - __VALUE_SAMP(SRGBTEXTURE, 0, 1), - __VALUE_SAMP(ELEMENTINDEX, 0, 0xFFFFFFFF), - __VALUE_SAMP(DMAPOFFSET, 0, 0xFFFFFFFF) -}; - -static BOOL inline -nine_check_sampler_state_value(D3DSAMPLERSTATETYPE State, - DWORD Value) -{ - struct nine_limits limit; - - limit = sampler_state_limits_table[State]; - return (limit.min <= Value && Value <= limit.max); -} - -#endif /* _NINE_HELPERS_H_ */ diff --git a/src/gallium/state_trackers/nine/nine_lock.c b/src/gallium/state_trackers/nine/nine_lock.c deleted file mode 100644 index ca0f04a69b3..00000000000 --- a/src/gallium/state_trackers/nine/nine_lock.c +++ /dev/null @@ -1,3294 +0,0 @@ -/* - * Copyright 2013 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "authenticatedchannel9.h" -#include "basetexture9.h" -#include "cryptosession9.h" -#include "cubetexture9.h" -#include "device9.h" -#include "device9ex.h" -#include "device9video.h" -#include "indexbuffer9.h" -#include "pixelshader9.h" -#include "query9.h" -#include "resource9.h" -#include "stateblock9.h" -#include "surface9.h" -#include "swapchain9.h" -#include "swapchain9ex.h" -#include "texture9.h" -#include "vertexbuffer9.h" -#include "vertexdeclaration9.h" -#include "vertexshader9.h" -#include "volume9.h" -#include "volumetexture9.h" - -#include "d3d9.h" -#include "nine_lock.h" - -#include "os/os_thread.h" - -/* Global mutex as described by MSDN */ -static mtx_t d3dlock_global = _MTX_INITIALIZER_NP; - -void -NineLockGlobalMutex() -{ - mtx_lock(&d3dlock_global); -} - -void -NineUnlockGlobalMutex() -{ - mtx_unlock(&d3dlock_global); -} - -static HRESULT NINE_WINAPI -LockAuthenticatedChannel9_GetCertificateSize( struct NineAuthenticatedChannel9 *This, - UINT *pCertificateSize ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineAuthenticatedChannel9_GetCertificateSize(This, pCertificateSize); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockAuthenticatedChannel9_GetCertificate( struct NineAuthenticatedChannel9 *This, - UINT CertifacteSize, - BYTE *ppCertificate ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineAuthenticatedChannel9_GetCertificate(This, CertifacteSize, ppCertificate); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockAuthenticatedChannel9_NegotiateKeyExchange( struct NineAuthenticatedChannel9 *This, - UINT DataSize, - void *pData ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineAuthenticatedChannel9_NegotiateKeyExchange(This, DataSize, pData); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockAuthenticatedChannel9_Query( struct NineAuthenticatedChannel9 *This, - UINT InputSize, - const void *pInput, - UINT OutputSize, - void *pOutput ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineAuthenticatedChannel9_Query(This, InputSize, pInput, OutputSize, pOutput); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockAuthenticatedChannel9_Configure( struct NineAuthenticatedChannel9 *This, - UINT InputSize, - const void *pInput, - D3DAUTHENTICATEDCHANNEL_CONFIGURE_OUTPUT *pOutput ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineAuthenticatedChannel9_Configure(This, InputSize, pInput, pOutput); - mtx_unlock(&d3dlock_global); - return r; -} - -IDirect3DAuthenticatedChannel9Vtbl LockAuthenticatedChannel9_vtable = { - (void *)NineUnknown_QueryInterface, - (void *)NineUnknown_AddRef, - (void *)NineUnknown_ReleaseWithDtorLock, - (void *)LockAuthenticatedChannel9_GetCertificateSize, - (void *)LockAuthenticatedChannel9_GetCertificate, - (void *)LockAuthenticatedChannel9_NegotiateKeyExchange, - (void *)LockAuthenticatedChannel9_Query, - (void *)LockAuthenticatedChannel9_Configure -}; - -static HRESULT NINE_WINAPI -LockUnknown_SetPrivateData( struct NineUnknown *This, - REFGUID refguid, - const void *pData, - DWORD SizeOfData, - DWORD Flags ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineUnknown_SetPrivateData(This, refguid, pData, SizeOfData, Flags); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockUnknown_GetPrivateData( struct NineUnknown *This, - REFGUID refguid, - void *pData, - DWORD *pSizeOfData ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineUnknown_GetPrivateData(This, refguid, pData, pSizeOfData); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockUnknown_FreePrivateData( struct NineUnknown *This, - REFGUID refguid ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineUnknown_FreePrivateData(This, refguid); - mtx_unlock(&d3dlock_global); - return r; -} - -#if 0 -static HRESULT NINE_WINAPI -LockResource9_GetDevice( struct NineResource9 *This, - IDirect3DDevice9 **ppDevice ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineUnknown_GetDevice(NineUnknown(This), ppDevice); - mtx_unlock(&d3dlock_global); - return r; -} -#endif - -static DWORD NINE_WINAPI -LockResource9_SetPriority( struct NineResource9 *This, - DWORD PriorityNew ) -{ - DWORD r; - mtx_lock(&d3dlock_global); - r = NineResource9_SetPriority(This, PriorityNew); - mtx_unlock(&d3dlock_global); - return r; -} - -static DWORD NINE_WINAPI -LockResource9_GetPriority( struct NineResource9 *This ) -{ - DWORD r; - mtx_lock(&d3dlock_global); - r = NineResource9_GetPriority(This); - mtx_unlock(&d3dlock_global); - return r; -} - -#if 0 -static void NINE_WINAPI -LockResource9_PreLoad( struct NineResource9 *This ) -{ - mtx_lock(&d3dlock_global); - NineResource9_PreLoad(This); - mtx_unlock(&d3dlock_global); -} -#endif - -#if 0 -static D3DRESOURCETYPE NINE_WINAPI -LockResource9_GetType( struct NineResource9 *This ) -{ - D3DRESOURCETYPE r; - mtx_lock(&d3dlock_global); - r = NineResource9_GetType(This); - mtx_unlock(&d3dlock_global); - return r; -} -#endif - -static DWORD NINE_WINAPI -LockBaseTexture9_SetLOD( struct NineBaseTexture9 *This, - DWORD LODNew ) -{ - DWORD r; - mtx_lock(&d3dlock_global); - r = NineBaseTexture9_SetLOD(This, LODNew); - mtx_unlock(&d3dlock_global); - return r; -} - -static DWORD NINE_WINAPI -LockBaseTexture9_GetLOD( struct NineBaseTexture9 *This ) -{ - DWORD r; - mtx_lock(&d3dlock_global); - r = NineBaseTexture9_GetLOD(This); - mtx_unlock(&d3dlock_global); - return r; -} - -static DWORD NINE_WINAPI -LockBaseTexture9_GetLevelCount( struct NineBaseTexture9 *This ) -{ - DWORD r; - mtx_lock(&d3dlock_global); - r = NineBaseTexture9_GetLevelCount(This); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockBaseTexture9_SetAutoGenFilterType( struct NineBaseTexture9 *This, - D3DTEXTUREFILTERTYPE FilterType ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineBaseTexture9_SetAutoGenFilterType(This, FilterType); - mtx_unlock(&d3dlock_global); - return r; -} - -static D3DTEXTUREFILTERTYPE NINE_WINAPI -LockBaseTexture9_GetAutoGenFilterType( struct NineBaseTexture9 *This ) -{ - D3DTEXTUREFILTERTYPE r; - mtx_lock(&d3dlock_global); - r = NineBaseTexture9_GetAutoGenFilterType(This); - mtx_unlock(&d3dlock_global); - return r; -} - -static void NINE_WINAPI -LockBaseTexture9_PreLoad( struct NineBaseTexture9 *This ) -{ - mtx_lock(&d3dlock_global); - NineBaseTexture9_PreLoad(This); - mtx_unlock(&d3dlock_global); -} - -static void NINE_WINAPI -LockBaseTexture9_GenerateMipSubLevels( struct NineBaseTexture9 *This ) -{ - mtx_lock(&d3dlock_global); - NineBaseTexture9_GenerateMipSubLevels(This); - mtx_unlock(&d3dlock_global); -} - -static HRESULT NINE_WINAPI -LockCryptoSession9_GetCertificateSize( struct NineCryptoSession9 *This, - UINT *pCertificateSize ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineCryptoSession9_GetCertificateSize(This, pCertificateSize); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockCryptoSession9_GetCertificate( struct NineCryptoSession9 *This, - UINT CertifacteSize, - BYTE *ppCertificate ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineCryptoSession9_GetCertificate(This, CertifacteSize, ppCertificate); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockCryptoSession9_NegotiateKeyExchange( struct NineCryptoSession9 *This, - UINT DataSize, - void *pData ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineCryptoSession9_NegotiateKeyExchange(This, DataSize, pData); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockCryptoSession9_EncryptionBlt( struct NineCryptoSession9 *This, - IDirect3DSurface9 *pSrcSurface, - IDirect3DSurface9 *pDstSurface, - UINT DstSurfaceSize, - void *pIV ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineCryptoSession9_EncryptionBlt(This, pSrcSurface, pDstSurface, DstSurfaceSize, pIV); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockCryptoSession9_DecryptionBlt( struct NineCryptoSession9 *This, - IDirect3DSurface9 *pSrcSurface, - IDirect3DSurface9 *pDstSurface, - UINT SrcSurfaceSize, - D3DENCRYPTED_BLOCK_INFO *pEncryptedBlockInfo, - void *pContentKey, - void *pIV ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineCryptoSession9_DecryptionBlt(This, pSrcSurface, pDstSurface, SrcSurfaceSize, pEncryptedBlockInfo, pContentKey, pIV); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockCryptoSession9_GetSurfacePitch( struct NineCryptoSession9 *This, - IDirect3DSurface9 *pSrcSurface, - UINT *pSurfacePitch ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineCryptoSession9_GetSurfacePitch(This, pSrcSurface, pSurfacePitch); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockCryptoSession9_StartSessionKeyRefresh( struct NineCryptoSession9 *This, - void *pRandomNumber, - UINT RandomNumberSize ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineCryptoSession9_StartSessionKeyRefresh(This, pRandomNumber, RandomNumberSize); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockCryptoSession9_FinishSessionKeyRefresh( struct NineCryptoSession9 *This ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineCryptoSession9_FinishSessionKeyRefresh(This); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockCryptoSession9_GetEncryptionBltKey( struct NineCryptoSession9 *This, - void *pReadbackKey, - UINT KeySize ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineCryptoSession9_GetEncryptionBltKey(This, pReadbackKey, KeySize); - mtx_unlock(&d3dlock_global); - return r; -} - -IDirect3DCryptoSession9Vtbl LockCryptoSession9_vtable = { - (void *)NineUnknown_QueryInterface, - (void *)NineUnknown_AddRef, - (void *)NineUnknown_ReleaseWithDtorLock, - (void *)LockCryptoSession9_GetCertificateSize, - (void *)LockCryptoSession9_GetCertificate, - (void *)LockCryptoSession9_NegotiateKeyExchange, - (void *)LockCryptoSession9_EncryptionBlt, - (void *)LockCryptoSession9_DecryptionBlt, - (void *)LockCryptoSession9_GetSurfacePitch, - (void *)LockCryptoSession9_StartSessionKeyRefresh, - (void *)LockCryptoSession9_FinishSessionKeyRefresh, - (void *)LockCryptoSession9_GetEncryptionBltKey -}; - -#if 0 -static HRESULT NINE_WINAPI -LockCubeTexture9_GetLevelDesc( struct NineCubeTexture9 *This, - UINT Level, - D3DSURFACE_DESC *pDesc ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineCubeTexture9_GetLevelDesc(This, Level, pDesc); - mtx_unlock(&d3dlock_global); - return r; -} -#endif - -#if 0 -static HRESULT NINE_WINAPI -LockCubeTexture9_GetCubeMapSurface( struct NineCubeTexture9 *This, - D3DCUBEMAP_FACES FaceType, - UINT Level, - IDirect3DSurface9 **ppCubeMapSurface ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineCubeTexture9_GetCubeMapSurface(This, FaceType, Level, ppCubeMapSurface); - mtx_unlock(&d3dlock_global); - return r; -} -#endif - -static HRESULT NINE_WINAPI -LockCubeTexture9_LockRect( struct NineCubeTexture9 *This, - D3DCUBEMAP_FACES FaceType, - UINT Level, - D3DLOCKED_RECT *pLockedRect, - const RECT *pRect, - DWORD Flags ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineCubeTexture9_LockRect(This, FaceType, Level, pLockedRect, pRect, Flags); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockCubeTexture9_UnlockRect( struct NineCubeTexture9 *This, - D3DCUBEMAP_FACES FaceType, - UINT Level ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineCubeTexture9_UnlockRect(This, FaceType, Level); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockCubeTexture9_AddDirtyRect( struct NineCubeTexture9 *This, - D3DCUBEMAP_FACES FaceType, - const RECT *pDirtyRect ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineCubeTexture9_AddDirtyRect(This, FaceType, pDirtyRect); - mtx_unlock(&d3dlock_global); - return r; -} - -IDirect3DCubeTexture9Vtbl LockCubeTexture9_vtable = { - (void *)NineUnknown_QueryInterface, - (void *)NineUnknown_AddRef, - (void *)NineUnknown_ReleaseWithDtorLock, - (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */ - (void *)LockUnknown_SetPrivateData, - (void *)LockUnknown_GetPrivateData, - (void *)LockUnknown_FreePrivateData, - (void *)LockResource9_SetPriority, - (void *)LockResource9_GetPriority, - (void *)LockBaseTexture9_PreLoad, - (void *)NineResource9_GetType, /* immutable */ - (void *)LockBaseTexture9_SetLOD, - (void *)LockBaseTexture9_GetLOD, - (void *)LockBaseTexture9_GetLevelCount, - (void *)LockBaseTexture9_SetAutoGenFilterType, - (void *)LockBaseTexture9_GetAutoGenFilterType, - (void *)LockBaseTexture9_GenerateMipSubLevels, - (void *)NineCubeTexture9_GetLevelDesc, /* immutable */ - (void *)NineCubeTexture9_GetCubeMapSurface, /* AddRef */ - (void *)LockCubeTexture9_LockRect, - (void *)LockCubeTexture9_UnlockRect, - (void *)LockCubeTexture9_AddDirtyRect -}; - -static HRESULT NINE_WINAPI -LockDevice9_TestCooperativeLevel( struct NineDevice9 *This ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_TestCooperativeLevel(This); - mtx_unlock(&d3dlock_global); - return r; -} - -static UINT NINE_WINAPI -LockDevice9_GetAvailableTextureMem( struct NineDevice9 *This ) -{ - UINT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_GetAvailableTextureMem(This); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_EvictManagedResources( struct NineDevice9 *This ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_EvictManagedResources(This); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_GetDirect3D( struct NineDevice9 *This, - IDirect3D9 **ppD3D9 ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_GetDirect3D(This, ppD3D9); - mtx_unlock(&d3dlock_global); - return r; -} - -#if 0 -static HRESULT NINE_WINAPI -LockDevice9_GetDeviceCaps( struct NineDevice9 *This, - D3DCAPS9 *pCaps ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_GetDeviceCaps(This, pCaps); - mtx_unlock(&d3dlock_global); - return r; -} -#endif - -static HRESULT NINE_WINAPI -LockDevice9_GetDisplayMode( struct NineDevice9 *This, - UINT iSwapChain, - D3DDISPLAYMODE *pMode ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_GetDisplayMode(This, iSwapChain, pMode); - mtx_unlock(&d3dlock_global); - return r; -} - -#if 0 -static HRESULT NINE_WINAPI -LockDevice9_GetCreationParameters( struct NineDevice9 *This, - D3DDEVICE_CREATION_PARAMETERS *pParameters ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_GetCreationParameters(This, pParameters); - mtx_unlock(&d3dlock_global); - return r; -} -#endif - -static HRESULT NINE_WINAPI -LockDevice9_SetCursorProperties( struct NineDevice9 *This, - UINT XHotSpot, - UINT YHotSpot, - IDirect3DSurface9 *pCursorBitmap ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_SetCursorProperties(This, XHotSpot, YHotSpot, pCursorBitmap); - mtx_unlock(&d3dlock_global); - return r; -} - -static void NINE_WINAPI -LockDevice9_SetCursorPosition( struct NineDevice9 *This, - int X, - int Y, - DWORD Flags ) -{ - mtx_lock(&d3dlock_global); - NineDevice9_SetCursorPosition(This, X, Y, Flags); - mtx_unlock(&d3dlock_global); -} - -static BOOL NINE_WINAPI -LockDevice9_ShowCursor( struct NineDevice9 *This, - BOOL bShow ) -{ - BOOL r; - mtx_lock(&d3dlock_global); - r = NineDevice9_ShowCursor(This, bShow); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_CreateAdditionalSwapChain( struct NineDevice9 *This, - D3DPRESENT_PARAMETERS *pPresentationParameters, - IDirect3DSwapChain9 **pSwapChain ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_CreateAdditionalSwapChain(This, pPresentationParameters, pSwapChain); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_GetSwapChain( struct NineDevice9 *This, - UINT iSwapChain, - IDirect3DSwapChain9 **pSwapChain ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_GetSwapChain(This, iSwapChain, pSwapChain); - mtx_unlock(&d3dlock_global); - return r; -} - -static UINT NINE_WINAPI -LockDevice9_GetNumberOfSwapChains( struct NineDevice9 *This ) -{ - UINT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_GetNumberOfSwapChains(This); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_Reset( struct NineDevice9 *This, - D3DPRESENT_PARAMETERS *pPresentationParameters ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_Reset(This, pPresentationParameters); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_Present( struct NineDevice9 *This, - const RECT *pSourceRect, - const RECT *pDestRect, - HWND hDestWindowOverride, - const RGNDATA *pDirtyRegion ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_Present(This, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_GetBackBuffer( struct NineDevice9 *This, - UINT iSwapChain, - UINT iBackBuffer, - D3DBACKBUFFER_TYPE Type, - IDirect3DSurface9 **ppBackBuffer ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_GetBackBuffer(This, iSwapChain, iBackBuffer, Type, ppBackBuffer); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_GetRasterStatus( struct NineDevice9 *This, - UINT iSwapChain, - D3DRASTER_STATUS *pRasterStatus ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_GetRasterStatus(This, iSwapChain, pRasterStatus); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_SetDialogBoxMode( struct NineDevice9 *This, - BOOL bEnableDialogs ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_SetDialogBoxMode(This, bEnableDialogs); - mtx_unlock(&d3dlock_global); - return r; -} - -static void NINE_WINAPI -LockDevice9_SetGammaRamp( struct NineDevice9 *This, - UINT iSwapChain, - DWORD Flags, - const D3DGAMMARAMP *pRamp ) -{ - mtx_lock(&d3dlock_global); - NineDevice9_SetGammaRamp(This, iSwapChain, Flags, pRamp); - mtx_unlock(&d3dlock_global); -} - -static void NINE_WINAPI -LockDevice9_GetGammaRamp( struct NineDevice9 *This, - UINT iSwapChain, - D3DGAMMARAMP *pRamp ) -{ - mtx_lock(&d3dlock_global); - NineDevice9_GetGammaRamp(This, iSwapChain, pRamp); - mtx_unlock(&d3dlock_global); -} - -static HRESULT NINE_WINAPI -LockDevice9_CreateTexture( struct NineDevice9 *This, - UINT Width, - UINT Height, - UINT Levels, - DWORD Usage, - D3DFORMAT Format, - D3DPOOL Pool, - IDirect3DTexture9 **ppTexture, - HANDLE *pSharedHandle ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_CreateTexture(This, Width, Height, Levels, Usage, Format, Pool, ppTexture, pSharedHandle); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_CreateVolumeTexture( struct NineDevice9 *This, - UINT Width, - UINT Height, - UINT Depth, - UINT Levels, - DWORD Usage, - D3DFORMAT Format, - D3DPOOL Pool, - IDirect3DVolumeTexture9 **ppVolumeTexture, - HANDLE *pSharedHandle ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_CreateVolumeTexture(This, Width, Height, Depth, Levels, Usage, Format, Pool, ppVolumeTexture, pSharedHandle); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_CreateCubeTexture( struct NineDevice9 *This, - UINT EdgeLength, - UINT Levels, - DWORD Usage, - D3DFORMAT Format, - D3DPOOL Pool, - IDirect3DCubeTexture9 **ppCubeTexture, - HANDLE *pSharedHandle ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_CreateCubeTexture(This, EdgeLength, Levels, Usage, Format, Pool, ppCubeTexture, pSharedHandle); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_CreateVertexBuffer( struct NineDevice9 *This, - UINT Length, - DWORD Usage, - DWORD FVF, - D3DPOOL Pool, - IDirect3DVertexBuffer9 **ppVertexBuffer, - HANDLE *pSharedHandle ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_CreateVertexBuffer(This, Length, Usage, FVF, Pool, ppVertexBuffer, pSharedHandle); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_CreateIndexBuffer( struct NineDevice9 *This, - UINT Length, - DWORD Usage, - D3DFORMAT Format, - D3DPOOL Pool, - IDirect3DIndexBuffer9 **ppIndexBuffer, - HANDLE *pSharedHandle ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_CreateIndexBuffer(This, Length, Usage, Format, Pool, ppIndexBuffer, pSharedHandle); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_CreateRenderTarget( struct NineDevice9 *This, - UINT Width, - UINT Height, - D3DFORMAT Format, - D3DMULTISAMPLE_TYPE MultiSample, - DWORD MultisampleQuality, - BOOL Lockable, - IDirect3DSurface9 **ppSurface, - HANDLE *pSharedHandle ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_CreateRenderTarget(This, Width, Height, Format, MultiSample, MultisampleQuality, Lockable, ppSurface, pSharedHandle); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_CreateDepthStencilSurface( struct NineDevice9 *This, - UINT Width, - UINT Height, - D3DFORMAT Format, - D3DMULTISAMPLE_TYPE MultiSample, - DWORD MultisampleQuality, - BOOL Discard, - IDirect3DSurface9 **ppSurface, - HANDLE *pSharedHandle ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_CreateDepthStencilSurface(This, Width, Height, Format, MultiSample, MultisampleQuality, Discard, ppSurface, pSharedHandle); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_UpdateSurface( struct NineDevice9 *This, - IDirect3DSurface9 *pSourceSurface, - const RECT *pSourceRect, - IDirect3DSurface9 *pDestinationSurface, - const POINT *pDestPoint ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_UpdateSurface(This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_UpdateTexture( struct NineDevice9 *This, - IDirect3DBaseTexture9 *pSourceTexture, - IDirect3DBaseTexture9 *pDestinationTexture ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_UpdateTexture(This, pSourceTexture, pDestinationTexture); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_GetRenderTargetData( struct NineDevice9 *This, - IDirect3DSurface9 *pRenderTarget, - IDirect3DSurface9 *pDestSurface ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_GetRenderTargetData(This, pRenderTarget, pDestSurface); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_GetFrontBufferData( struct NineDevice9 *This, - UINT iSwapChain, - IDirect3DSurface9 *pDestSurface ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_GetFrontBufferData(This, iSwapChain, pDestSurface); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_StretchRect( struct NineDevice9 *This, - IDirect3DSurface9 *pSourceSurface, - const RECT *pSourceRect, - IDirect3DSurface9 *pDestSurface, - const RECT *pDestRect, - D3DTEXTUREFILTERTYPE Filter ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_StretchRect(This, pSourceSurface, pSourceRect, pDestSurface, pDestRect, Filter); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_ColorFill( struct NineDevice9 *This, - IDirect3DSurface9 *pSurface, - const RECT *pRect, - D3DCOLOR color ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_ColorFill(This, pSurface, pRect, color); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_CreateOffscreenPlainSurface( struct NineDevice9 *This, - UINT Width, - UINT Height, - D3DFORMAT Format, - D3DPOOL Pool, - IDirect3DSurface9 **ppSurface, - HANDLE *pSharedHandle ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_CreateOffscreenPlainSurface(This, Width, Height, Format, Pool, ppSurface, pSharedHandle); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_SetRenderTarget( struct NineDevice9 *This, - DWORD RenderTargetIndex, - IDirect3DSurface9 *pRenderTarget ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_SetRenderTarget(This, RenderTargetIndex, pRenderTarget); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_GetRenderTarget( struct NineDevice9 *This, - DWORD RenderTargetIndex, - IDirect3DSurface9 **ppRenderTarget ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_GetRenderTarget(This, RenderTargetIndex, ppRenderTarget); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_SetDepthStencilSurface( struct NineDevice9 *This, - IDirect3DSurface9 *pNewZStencil ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_SetDepthStencilSurface(This, pNewZStencil); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_GetDepthStencilSurface( struct NineDevice9 *This, - IDirect3DSurface9 **ppZStencilSurface ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_GetDepthStencilSurface(This, ppZStencilSurface); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_BeginScene( struct NineDevice9 *This ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_BeginScene(This); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_EndScene( struct NineDevice9 *This ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_EndScene(This); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_Clear( struct NineDevice9 *This, - DWORD Count, - const D3DRECT *pRects, - DWORD Flags, - D3DCOLOR Color, - float Z, - DWORD Stencil ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_Clear(This, Count, pRects, Flags, Color, Z, Stencil); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_SetTransform( struct NineDevice9 *This, - D3DTRANSFORMSTATETYPE State, - const D3DMATRIX *pMatrix ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_SetTransform(This, State, pMatrix); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_GetTransform( struct NineDevice9 *This, - D3DTRANSFORMSTATETYPE State, - D3DMATRIX *pMatrix ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_GetTransform(This, State, pMatrix); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_MultiplyTransform( struct NineDevice9 *This, - D3DTRANSFORMSTATETYPE State, - const D3DMATRIX *pMatrix ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_MultiplyTransform(This, State, pMatrix); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_SetViewport( struct NineDevice9 *This, - const D3DVIEWPORT9 *pViewport ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_SetViewport(This, pViewport); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_GetViewport( struct NineDevice9 *This, - D3DVIEWPORT9 *pViewport ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_GetViewport(This, pViewport); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_SetMaterial( struct NineDevice9 *This, - const D3DMATERIAL9 *pMaterial ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_SetMaterial(This, pMaterial); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_GetMaterial( struct NineDevice9 *This, - D3DMATERIAL9 *pMaterial ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_GetMaterial(This, pMaterial); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_SetLight( struct NineDevice9 *This, - DWORD Index, - const D3DLIGHT9 *pLight ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_SetLight(This, Index, pLight); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_GetLight( struct NineDevice9 *This, - DWORD Index, - D3DLIGHT9 *pLight ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_GetLight(This, Index, pLight); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_LightEnable( struct NineDevice9 *This, - DWORD Index, - BOOL Enable ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_LightEnable(This, Index, Enable); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_GetLightEnable( struct NineDevice9 *This, - DWORD Index, - BOOL *pEnable ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_GetLightEnable(This, Index, pEnable); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_SetClipPlane( struct NineDevice9 *This, - DWORD Index, - const float *pPlane ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_SetClipPlane(This, Index, pPlane); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_GetClipPlane( struct NineDevice9 *This, - DWORD Index, - float *pPlane ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_GetClipPlane(This, Index, pPlane); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_SetRenderState( struct NineDevice9 *This, - D3DRENDERSTATETYPE State, - DWORD Value ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_SetRenderState(This, State, Value); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_GetRenderState( struct NineDevice9 *This, - D3DRENDERSTATETYPE State, - DWORD *pValue ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_GetRenderState(This, State, pValue); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_CreateStateBlock( struct NineDevice9 *This, - D3DSTATEBLOCKTYPE Type, - IDirect3DStateBlock9 **ppSB ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_CreateStateBlock(This, Type, ppSB); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_BeginStateBlock( struct NineDevice9 *This ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_BeginStateBlock(This); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_EndStateBlock( struct NineDevice9 *This, - IDirect3DStateBlock9 **ppSB ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_EndStateBlock(This, ppSB); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_SetClipStatus( struct NineDevice9 *This, - const D3DCLIPSTATUS9 *pClipStatus ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_SetClipStatus(This, pClipStatus); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_GetClipStatus( struct NineDevice9 *This, - D3DCLIPSTATUS9 *pClipStatus ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_GetClipStatus(This, pClipStatus); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_GetTexture( struct NineDevice9 *This, - DWORD Stage, - IDirect3DBaseTexture9 **ppTexture ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_GetTexture(This, Stage, ppTexture); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_SetTexture( struct NineDevice9 *This, - DWORD Stage, - IDirect3DBaseTexture9 *pTexture ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_SetTexture(This, Stage, pTexture); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_GetTextureStageState( struct NineDevice9 *This, - DWORD Stage, - D3DTEXTURESTAGESTATETYPE Type, - DWORD *pValue ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_GetTextureStageState(This, Stage, Type, pValue); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_SetTextureStageState( struct NineDevice9 *This, - DWORD Stage, - D3DTEXTURESTAGESTATETYPE Type, - DWORD Value ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_SetTextureStageState(This, Stage, Type, Value); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_GetSamplerState( struct NineDevice9 *This, - DWORD Sampler, - D3DSAMPLERSTATETYPE Type, - DWORD *pValue ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_GetSamplerState(This, Sampler, Type, pValue); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_SetSamplerState( struct NineDevice9 *This, - DWORD Sampler, - D3DSAMPLERSTATETYPE Type, - DWORD Value ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_SetSamplerState(This, Sampler, Type, Value); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_ValidateDevice( struct NineDevice9 *This, - DWORD *pNumPasses ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_ValidateDevice(This, pNumPasses); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_SetPaletteEntries( struct NineDevice9 *This, - UINT PaletteNumber, - const PALETTEENTRY *pEntries ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_SetPaletteEntries(This, PaletteNumber, pEntries); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_GetPaletteEntries( struct NineDevice9 *This, - UINT PaletteNumber, - PALETTEENTRY *pEntries ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_GetPaletteEntries(This, PaletteNumber, pEntries); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_SetCurrentTexturePalette( struct NineDevice9 *This, - UINT PaletteNumber ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_SetCurrentTexturePalette(This, PaletteNumber); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_GetCurrentTexturePalette( struct NineDevice9 *This, - UINT *PaletteNumber ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_GetCurrentTexturePalette(This, PaletteNumber); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_SetScissorRect( struct NineDevice9 *This, - const RECT *pRect ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_SetScissorRect(This, pRect); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_GetScissorRect( struct NineDevice9 *This, - RECT *pRect ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_GetScissorRect(This, pRect); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_SetSoftwareVertexProcessing( struct NineDevice9 *This, - BOOL bSoftware ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_SetSoftwareVertexProcessing(This, bSoftware); - mtx_unlock(&d3dlock_global); - return r; -} - -static BOOL NINE_WINAPI -LockDevice9_GetSoftwareVertexProcessing( struct NineDevice9 *This ) -{ - BOOL r; - mtx_lock(&d3dlock_global); - r = NineDevice9_GetSoftwareVertexProcessing(This); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_SetNPatchMode( struct NineDevice9 *This, - float nSegments ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_SetNPatchMode(This, nSegments); - mtx_unlock(&d3dlock_global); - return r; -} - -static float NINE_WINAPI -LockDevice9_GetNPatchMode( struct NineDevice9 *This ) -{ - float r; - mtx_lock(&d3dlock_global); - r = NineDevice9_GetNPatchMode(This); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_DrawPrimitive( struct NineDevice9 *This, - D3DPRIMITIVETYPE PrimitiveType, - UINT StartVertex, - UINT PrimitiveCount ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_DrawPrimitive(This, PrimitiveType, StartVertex, PrimitiveCount); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_DrawIndexedPrimitive( struct NineDevice9 *This, - D3DPRIMITIVETYPE PrimitiveType, - INT BaseVertexIndex, - UINT MinVertexIndex, - UINT NumVertices, - UINT startIndex, - UINT primCount ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_DrawIndexedPrimitive(This, PrimitiveType, BaseVertexIndex, MinVertexIndex, NumVertices, startIndex, primCount); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_DrawPrimitiveUP( struct NineDevice9 *This, - D3DPRIMITIVETYPE PrimitiveType, - UINT PrimitiveCount, - const void *pVertexStreamZeroData, - UINT VertexStreamZeroStride ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_DrawPrimitiveUP(This, PrimitiveType, PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_DrawIndexedPrimitiveUP( struct NineDevice9 *This, - D3DPRIMITIVETYPE PrimitiveType, - UINT MinVertexIndex, - UINT NumVertices, - UINT PrimitiveCount, - const void *pIndexData, - D3DFORMAT IndexDataFormat, - const void *pVertexStreamZeroData, - UINT VertexStreamZeroStride ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_DrawIndexedPrimitiveUP(This, PrimitiveType, MinVertexIndex, NumVertices, PrimitiveCount, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_ProcessVertices( struct NineDevice9 *This, - UINT SrcStartIndex, - UINT DestIndex, - UINT VertexCount, - IDirect3DVertexBuffer9 *pDestBuffer, - IDirect3DVertexDeclaration9 *pVertexDecl, - DWORD Flags ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_ProcessVertices(This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_CreateVertexDeclaration( struct NineDevice9 *This, - const D3DVERTEXELEMENT9 *pVertexElements, - IDirect3DVertexDeclaration9 **ppDecl ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_CreateVertexDeclaration(This, pVertexElements, ppDecl); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_SetVertexDeclaration( struct NineDevice9 *This, - IDirect3DVertexDeclaration9 *pDecl ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_SetVertexDeclaration(This, pDecl); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_GetVertexDeclaration( struct NineDevice9 *This, - IDirect3DVertexDeclaration9 **ppDecl ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_GetVertexDeclaration(This, ppDecl); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_SetFVF( struct NineDevice9 *This, - DWORD FVF ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_SetFVF(This, FVF); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_GetFVF( struct NineDevice9 *This, - DWORD *pFVF ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_GetFVF(This, pFVF); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_CreateVertexShader( struct NineDevice9 *This, - const DWORD *pFunction, - IDirect3DVertexShader9 **ppShader ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_CreateVertexShader(This, pFunction, ppShader); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_SetVertexShader( struct NineDevice9 *This, - IDirect3DVertexShader9 *pShader ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_SetVertexShader(This, pShader); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_GetVertexShader( struct NineDevice9 *This, - IDirect3DVertexShader9 **ppShader ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_GetVertexShader(This, ppShader); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_SetVertexShaderConstantF( struct NineDevice9 *This, - UINT StartRegister, - const float *pConstantData, - UINT Vector4fCount ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_SetVertexShaderConstantF(This, StartRegister, pConstantData, Vector4fCount); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_GetVertexShaderConstantF( struct NineDevice9 *This, - UINT StartRegister, - float *pConstantData, - UINT Vector4fCount ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_GetVertexShaderConstantF(This, StartRegister, pConstantData, Vector4fCount); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_SetVertexShaderConstantI( struct NineDevice9 *This, - UINT StartRegister, - const int *pConstantData, - UINT Vector4iCount ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_SetVertexShaderConstantI(This, StartRegister, pConstantData, Vector4iCount); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_GetVertexShaderConstantI( struct NineDevice9 *This, - UINT StartRegister, - int *pConstantData, - UINT Vector4iCount ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_GetVertexShaderConstantI(This, StartRegister, pConstantData, Vector4iCount); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_SetVertexShaderConstantB( struct NineDevice9 *This, - UINT StartRegister, - const BOOL *pConstantData, - UINT BoolCount ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_SetVertexShaderConstantB(This, StartRegister, pConstantData, BoolCount); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_GetVertexShaderConstantB( struct NineDevice9 *This, - UINT StartRegister, - BOOL *pConstantData, - UINT BoolCount ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_GetVertexShaderConstantB(This, StartRegister, pConstantData, BoolCount); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_SetStreamSource( struct NineDevice9 *This, - UINT StreamNumber, - IDirect3DVertexBuffer9 *pStreamData, - UINT OffsetInBytes, - UINT Stride ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_SetStreamSource(This, StreamNumber, pStreamData, OffsetInBytes, Stride); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_GetStreamSource( struct NineDevice9 *This, - UINT StreamNumber, - IDirect3DVertexBuffer9 **ppStreamData, - UINT *pOffsetInBytes, - UINT *pStride ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_GetStreamSource(This, StreamNumber, ppStreamData, pOffsetInBytes, pStride); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_SetStreamSourceFreq( struct NineDevice9 *This, - UINT StreamNumber, - UINT Setting ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_SetStreamSourceFreq(This, StreamNumber, Setting); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_GetStreamSourceFreq( struct NineDevice9 *This, - UINT StreamNumber, - UINT *pSetting ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_GetStreamSourceFreq(This, StreamNumber, pSetting); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_SetIndices( struct NineDevice9 *This, - IDirect3DIndexBuffer9 *pIndexData ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_SetIndices(This, pIndexData); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_GetIndices( struct NineDevice9 *This, - IDirect3DIndexBuffer9 **ppIndexData ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_GetIndices(This, ppIndexData); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_CreatePixelShader( struct NineDevice9 *This, - const DWORD *pFunction, - IDirect3DPixelShader9 **ppShader ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_CreatePixelShader(This, pFunction, ppShader); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_SetPixelShader( struct NineDevice9 *This, - IDirect3DPixelShader9 *pShader ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_SetPixelShader(This, pShader); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_GetPixelShader( struct NineDevice9 *This, - IDirect3DPixelShader9 **ppShader ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_GetPixelShader(This, ppShader); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_SetPixelShaderConstantF( struct NineDevice9 *This, - UINT StartRegister, - const float *pConstantData, - UINT Vector4fCount ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_SetPixelShaderConstantF(This, StartRegister, pConstantData, Vector4fCount); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_GetPixelShaderConstantF( struct NineDevice9 *This, - UINT StartRegister, - float *pConstantData, - UINT Vector4fCount ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_GetPixelShaderConstantF(This, StartRegister, pConstantData, Vector4fCount); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_SetPixelShaderConstantI( struct NineDevice9 *This, - UINT StartRegister, - const int *pConstantData, - UINT Vector4iCount ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_SetPixelShaderConstantI(This, StartRegister, pConstantData, Vector4iCount); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_GetPixelShaderConstantI( struct NineDevice9 *This, - UINT StartRegister, - int *pConstantData, - UINT Vector4iCount ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_GetPixelShaderConstantI(This, StartRegister, pConstantData, Vector4iCount); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_SetPixelShaderConstantB( struct NineDevice9 *This, - UINT StartRegister, - const BOOL *pConstantData, - UINT BoolCount ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_SetPixelShaderConstantB(This, StartRegister, pConstantData, BoolCount); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_GetPixelShaderConstantB( struct NineDevice9 *This, - UINT StartRegister, - BOOL *pConstantData, - UINT BoolCount ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_GetPixelShaderConstantB(This, StartRegister, pConstantData, BoolCount); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_DrawRectPatch( struct NineDevice9 *This, - UINT Handle, - const float *pNumSegs, - const D3DRECTPATCH_INFO *pRectPatchInfo ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_DrawRectPatch(This, Handle, pNumSegs, pRectPatchInfo); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_DrawTriPatch( struct NineDevice9 *This, - UINT Handle, - const float *pNumSegs, - const D3DTRIPATCH_INFO *pTriPatchInfo ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_DrawTriPatch(This, Handle, pNumSegs, pTriPatchInfo); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_DeletePatch( struct NineDevice9 *This, - UINT Handle ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_DeletePatch(This, Handle); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9_CreateQuery( struct NineDevice9 *This, - D3DQUERYTYPE Type, - IDirect3DQuery9 **ppQuery ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9_CreateQuery(This, Type, ppQuery); - mtx_unlock(&d3dlock_global); - return r; -} - -IDirect3DDevice9Vtbl LockDevice9_vtable = { - (void *)NineUnknown_QueryInterface, - (void *)NineUnknown_AddRef, - (void *)NineUnknown_ReleaseWithDtorLock, - (void *)LockDevice9_TestCooperativeLevel, - (void *)LockDevice9_GetAvailableTextureMem, - (void *)LockDevice9_EvictManagedResources, - (void *)LockDevice9_GetDirect3D, - (void *)NineDevice9_GetDeviceCaps, /* immutable */ - (void *)LockDevice9_GetDisplayMode, - (void *)NineDevice9_GetCreationParameters, /* immutable */ - (void *)LockDevice9_SetCursorProperties, - (void *)LockDevice9_SetCursorPosition, - (void *)LockDevice9_ShowCursor, - (void *)LockDevice9_CreateAdditionalSwapChain, - (void *)LockDevice9_GetSwapChain, - (void *)LockDevice9_GetNumberOfSwapChains, - (void *)LockDevice9_Reset, - (void *)LockDevice9_Present, - (void *)LockDevice9_GetBackBuffer, - (void *)LockDevice9_GetRasterStatus, - (void *)LockDevice9_SetDialogBoxMode, - (void *)LockDevice9_SetGammaRamp, - (void *)LockDevice9_GetGammaRamp, - (void *)LockDevice9_CreateTexture, - (void *)LockDevice9_CreateVolumeTexture, - (void *)LockDevice9_CreateCubeTexture, - (void *)LockDevice9_CreateVertexBuffer, - (void *)LockDevice9_CreateIndexBuffer, - (void *)LockDevice9_CreateRenderTarget, - (void *)LockDevice9_CreateDepthStencilSurface, - (void *)LockDevice9_UpdateSurface, - (void *)LockDevice9_UpdateTexture, - (void *)LockDevice9_GetRenderTargetData, - (void *)LockDevice9_GetFrontBufferData, - (void *)LockDevice9_StretchRect, - (void *)LockDevice9_ColorFill, - (void *)LockDevice9_CreateOffscreenPlainSurface, - (void *)LockDevice9_SetRenderTarget, - (void *)LockDevice9_GetRenderTarget, - (void *)LockDevice9_SetDepthStencilSurface, - (void *)LockDevice9_GetDepthStencilSurface, - (void *)LockDevice9_BeginScene, - (void *)LockDevice9_EndScene, - (void *)LockDevice9_Clear, - (void *)LockDevice9_SetTransform, - (void *)LockDevice9_GetTransform, - (void *)LockDevice9_MultiplyTransform, - (void *)LockDevice9_SetViewport, - (void *)LockDevice9_GetViewport, - (void *)LockDevice9_SetMaterial, - (void *)LockDevice9_GetMaterial, - (void *)LockDevice9_SetLight, - (void *)LockDevice9_GetLight, - (void *)LockDevice9_LightEnable, - (void *)LockDevice9_GetLightEnable, - (void *)LockDevice9_SetClipPlane, - (void *)LockDevice9_GetClipPlane, - (void *)LockDevice9_SetRenderState, - (void *)LockDevice9_GetRenderState, - (void *)LockDevice9_CreateStateBlock, - (void *)LockDevice9_BeginStateBlock, - (void *)LockDevice9_EndStateBlock, - (void *)LockDevice9_SetClipStatus, - (void *)LockDevice9_GetClipStatus, - (void *)LockDevice9_GetTexture, - (void *)LockDevice9_SetTexture, - (void *)LockDevice9_GetTextureStageState, - (void *)LockDevice9_SetTextureStageState, - (void *)LockDevice9_GetSamplerState, - (void *)LockDevice9_SetSamplerState, - (void *)LockDevice9_ValidateDevice, - (void *)LockDevice9_SetPaletteEntries, - (void *)LockDevice9_GetPaletteEntries, - (void *)LockDevice9_SetCurrentTexturePalette, - (void *)LockDevice9_GetCurrentTexturePalette, - (void *)LockDevice9_SetScissorRect, - (void *)LockDevice9_GetScissorRect, - (void *)LockDevice9_SetSoftwareVertexProcessing, - (void *)LockDevice9_GetSoftwareVertexProcessing, - (void *)LockDevice9_SetNPatchMode, - (void *)LockDevice9_GetNPatchMode, - (void *)LockDevice9_DrawPrimitive, - (void *)LockDevice9_DrawIndexedPrimitive, - (void *)LockDevice9_DrawPrimitiveUP, - (void *)LockDevice9_DrawIndexedPrimitiveUP, - (void *)LockDevice9_ProcessVertices, - (void *)LockDevice9_CreateVertexDeclaration, - (void *)LockDevice9_SetVertexDeclaration, - (void *)LockDevice9_GetVertexDeclaration, - (void *)LockDevice9_SetFVF, - (void *)LockDevice9_GetFVF, - (void *)LockDevice9_CreateVertexShader, - (void *)LockDevice9_SetVertexShader, - (void *)LockDevice9_GetVertexShader, - (void *)LockDevice9_SetVertexShaderConstantF, - (void *)LockDevice9_GetVertexShaderConstantF, - (void *)LockDevice9_SetVertexShaderConstantI, - (void *)LockDevice9_GetVertexShaderConstantI, - (void *)LockDevice9_SetVertexShaderConstantB, - (void *)LockDevice9_GetVertexShaderConstantB, - (void *)LockDevice9_SetStreamSource, - (void *)LockDevice9_GetStreamSource, - (void *)LockDevice9_SetStreamSourceFreq, - (void *)LockDevice9_GetStreamSourceFreq, - (void *)LockDevice9_SetIndices, - (void *)LockDevice9_GetIndices, - (void *)LockDevice9_CreatePixelShader, - (void *)LockDevice9_SetPixelShader, - (void *)LockDevice9_GetPixelShader, - (void *)LockDevice9_SetPixelShaderConstantF, - (void *)LockDevice9_GetPixelShaderConstantF, - (void *)LockDevice9_SetPixelShaderConstantI, - (void *)LockDevice9_GetPixelShaderConstantI, - (void *)LockDevice9_SetPixelShaderConstantB, - (void *)LockDevice9_GetPixelShaderConstantB, - (void *)LockDevice9_DrawRectPatch, - (void *)LockDevice9_DrawTriPatch, - (void *)LockDevice9_DeletePatch, - (void *)LockDevice9_CreateQuery -}; - -static HRESULT NINE_WINAPI -LockDevice9Ex_SetConvolutionMonoKernel( struct NineDevice9Ex *This, - UINT width, - UINT height, - float *rows, - float *columns ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9Ex_SetConvolutionMonoKernel(This, width, height, rows, columns); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9Ex_ComposeRects( struct NineDevice9Ex *This, - IDirect3DSurface9 *pSrc, - IDirect3DSurface9 *pDst, - IDirect3DVertexBuffer9 *pSrcRectDescs, - UINT NumRects, - IDirect3DVertexBuffer9 *pDstRectDescs, - D3DCOMPOSERECTSOP Operation, - int Xoffset, - int Yoffset ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9Ex_ComposeRects(This, pSrc, pDst, pSrcRectDescs, NumRects, pDstRectDescs, Operation, Xoffset, Yoffset); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9Ex_PresentEx( struct NineDevice9Ex *This, - const RECT *pSourceRect, - const RECT *pDestRect, - HWND hDestWindowOverride, - const RGNDATA *pDirtyRegion, - DWORD dwFlags ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9Ex_PresentEx(This, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, dwFlags); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9Ex_GetGPUThreadPriority( struct NineDevice9Ex *This, - INT *pPriority ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9Ex_GetGPUThreadPriority(This, pPriority); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9Ex_SetGPUThreadPriority( struct NineDevice9Ex *This, - INT Priority ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9Ex_SetGPUThreadPriority(This, Priority); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9Ex_WaitForVBlank( struct NineDevice9Ex *This, - UINT iSwapChain ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9Ex_WaitForVBlank(This, iSwapChain); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9Ex_CheckResourceResidency( struct NineDevice9Ex *This, - IDirect3DResource9 **pResourceArray, - UINT32 NumResources ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9Ex_CheckResourceResidency(This, pResourceArray, NumResources); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9Ex_SetMaximumFrameLatency( struct NineDevice9Ex *This, - UINT MaxLatency ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9Ex_SetMaximumFrameLatency(This, MaxLatency); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9Ex_GetMaximumFrameLatency( struct NineDevice9Ex *This, - UINT *pMaxLatency ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9Ex_GetMaximumFrameLatency(This, pMaxLatency); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9Ex_CheckDeviceState( struct NineDevice9Ex *This, - HWND hDestinationWindow ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9Ex_CheckDeviceState(This, hDestinationWindow); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9Ex_CreateRenderTargetEx( struct NineDevice9Ex *This, - UINT Width, - UINT Height, - D3DFORMAT Format, - D3DMULTISAMPLE_TYPE MultiSample, - DWORD MultisampleQuality, - BOOL Lockable, - IDirect3DSurface9 **ppSurface, - HANDLE *pSharedHandle, - DWORD Usage ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9Ex_CreateRenderTargetEx(This, Width, Height, Format, MultiSample, MultisampleQuality, Lockable, ppSurface, pSharedHandle, Usage); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9Ex_CreateOffscreenPlainSurfaceEx( struct NineDevice9Ex *This, - UINT Width, - UINT Height, - D3DFORMAT Format, - D3DPOOL Pool, - IDirect3DSurface9 **ppSurface, - HANDLE *pSharedHandle, - DWORD Usage ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9Ex_CreateOffscreenPlainSurfaceEx(This, Width, Height, Format, Pool, ppSurface, pSharedHandle, Usage); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9Ex_CreateDepthStencilSurfaceEx( struct NineDevice9Ex *This, - UINT Width, - UINT Height, - D3DFORMAT Format, - D3DMULTISAMPLE_TYPE MultiSample, - DWORD MultisampleQuality, - BOOL Discard, - IDirect3DSurface9 **ppSurface, - HANDLE *pSharedHandle, - DWORD Usage ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9Ex_CreateDepthStencilSurfaceEx(This, Width, Height, Format, MultiSample, MultisampleQuality, Discard, ppSurface, pSharedHandle, Usage); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9Ex_ResetEx( struct NineDevice9Ex *This, - D3DPRESENT_PARAMETERS *pPresentationParameters, - D3DDISPLAYMODEEX *pFullscreenDisplayMode ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9Ex_ResetEx(This, pPresentationParameters, pFullscreenDisplayMode); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9Ex_GetDisplayModeEx( struct NineDevice9Ex *This, - UINT iSwapChain, - D3DDISPLAYMODEEX *pMode, - D3DDISPLAYROTATION *pRotation ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9Ex_GetDisplayModeEx(This, iSwapChain, pMode, pRotation); - mtx_unlock(&d3dlock_global); - return r; -} - -IDirect3DDevice9ExVtbl LockDevice9Ex_vtable = { - (void *)NineUnknown_QueryInterface, - (void *)NineUnknown_AddRef, - (void *)NineUnknown_ReleaseWithDtorLock, - (void *)LockDevice9_TestCooperativeLevel, - (void *)LockDevice9_GetAvailableTextureMem, - (void *)LockDevice9_EvictManagedResources, - (void *)LockDevice9_GetDirect3D, - (void *)NineDevice9_GetDeviceCaps, - (void *)LockDevice9_GetDisplayMode, - (void *)NineDevice9_GetCreationParameters, - (void *)LockDevice9_SetCursorProperties, - (void *)LockDevice9_SetCursorPosition, - (void *)LockDevice9_ShowCursor, - (void *)LockDevice9_CreateAdditionalSwapChain, - (void *)LockDevice9_GetSwapChain, - (void *)LockDevice9_GetNumberOfSwapChains, - (void *)LockDevice9_Reset, - (void *)LockDevice9_Present, - (void *)LockDevice9_GetBackBuffer, - (void *)LockDevice9_GetRasterStatus, - (void *)LockDevice9_SetDialogBoxMode, - (void *)LockDevice9_SetGammaRamp, - (void *)LockDevice9_GetGammaRamp, - (void *)LockDevice9_CreateTexture, - (void *)LockDevice9_CreateVolumeTexture, - (void *)LockDevice9_CreateCubeTexture, - (void *)LockDevice9_CreateVertexBuffer, - (void *)LockDevice9_CreateIndexBuffer, - (void *)LockDevice9_CreateRenderTarget, - (void *)LockDevice9_CreateDepthStencilSurface, - (void *)LockDevice9_UpdateSurface, - (void *)LockDevice9_UpdateTexture, - (void *)LockDevice9_GetRenderTargetData, - (void *)LockDevice9_GetFrontBufferData, - (void *)LockDevice9_StretchRect, - (void *)LockDevice9_ColorFill, - (void *)LockDevice9_CreateOffscreenPlainSurface, - (void *)LockDevice9_SetRenderTarget, - (void *)LockDevice9_GetRenderTarget, - (void *)LockDevice9_SetDepthStencilSurface, - (void *)LockDevice9_GetDepthStencilSurface, - (void *)LockDevice9_BeginScene, - (void *)LockDevice9_EndScene, - (void *)LockDevice9_Clear, - (void *)LockDevice9_SetTransform, - (void *)LockDevice9_GetTransform, - (void *)LockDevice9_MultiplyTransform, - (void *)LockDevice9_SetViewport, - (void *)LockDevice9_GetViewport, - (void *)LockDevice9_SetMaterial, - (void *)LockDevice9_GetMaterial, - (void *)LockDevice9_SetLight, - (void *)LockDevice9_GetLight, - (void *)LockDevice9_LightEnable, - (void *)LockDevice9_GetLightEnable, - (void *)LockDevice9_SetClipPlane, - (void *)LockDevice9_GetClipPlane, - (void *)LockDevice9_SetRenderState, - (void *)LockDevice9_GetRenderState, - (void *)LockDevice9_CreateStateBlock, - (void *)LockDevice9_BeginStateBlock, - (void *)LockDevice9_EndStateBlock, - (void *)LockDevice9_SetClipStatus, - (void *)LockDevice9_GetClipStatus, - (void *)LockDevice9_GetTexture, - (void *)LockDevice9_SetTexture, - (void *)LockDevice9_GetTextureStageState, - (void *)LockDevice9_SetTextureStageState, - (void *)LockDevice9_GetSamplerState, - (void *)LockDevice9_SetSamplerState, - (void *)LockDevice9_ValidateDevice, - (void *)LockDevice9_SetPaletteEntries, - (void *)LockDevice9_GetPaletteEntries, - (void *)LockDevice9_SetCurrentTexturePalette, - (void *)LockDevice9_GetCurrentTexturePalette, - (void *)LockDevice9_SetScissorRect, - (void *)LockDevice9_GetScissorRect, - (void *)LockDevice9_SetSoftwareVertexProcessing, - (void *)LockDevice9_GetSoftwareVertexProcessing, - (void *)LockDevice9_SetNPatchMode, - (void *)LockDevice9_GetNPatchMode, - (void *)LockDevice9_DrawPrimitive, - (void *)LockDevice9_DrawIndexedPrimitive, - (void *)LockDevice9_DrawPrimitiveUP, - (void *)LockDevice9_DrawIndexedPrimitiveUP, - (void *)LockDevice9_ProcessVertices, - (void *)LockDevice9_CreateVertexDeclaration, - (void *)LockDevice9_SetVertexDeclaration, - (void *)LockDevice9_GetVertexDeclaration, - (void *)LockDevice9_SetFVF, - (void *)LockDevice9_GetFVF, - (void *)LockDevice9_CreateVertexShader, - (void *)LockDevice9_SetVertexShader, - (void *)LockDevice9_GetVertexShader, - (void *)LockDevice9_SetVertexShaderConstantF, - (void *)LockDevice9_GetVertexShaderConstantF, - (void *)LockDevice9_SetVertexShaderConstantI, - (void *)LockDevice9_GetVertexShaderConstantI, - (void *)LockDevice9_SetVertexShaderConstantB, - (void *)LockDevice9_GetVertexShaderConstantB, - (void *)LockDevice9_SetStreamSource, - (void *)LockDevice9_GetStreamSource, - (void *)LockDevice9_SetStreamSourceFreq, - (void *)LockDevice9_GetStreamSourceFreq, - (void *)LockDevice9_SetIndices, - (void *)LockDevice9_GetIndices, - (void *)LockDevice9_CreatePixelShader, - (void *)LockDevice9_SetPixelShader, - (void *)LockDevice9_GetPixelShader, - (void *)LockDevice9_SetPixelShaderConstantF, - (void *)LockDevice9_GetPixelShaderConstantF, - (void *)LockDevice9_SetPixelShaderConstantI, - (void *)LockDevice9_GetPixelShaderConstantI, - (void *)LockDevice9_SetPixelShaderConstantB, - (void *)LockDevice9_GetPixelShaderConstantB, - (void *)LockDevice9_DrawRectPatch, - (void *)LockDevice9_DrawTriPatch, - (void *)LockDevice9_DeletePatch, - (void *)LockDevice9_CreateQuery, - (void *)LockDevice9Ex_SetConvolutionMonoKernel, - (void *)LockDevice9Ex_ComposeRects, - (void *)LockDevice9Ex_PresentEx, - (void *)LockDevice9Ex_GetGPUThreadPriority, - (void *)LockDevice9Ex_SetGPUThreadPriority, - (void *)LockDevice9Ex_WaitForVBlank, - (void *)LockDevice9Ex_CheckResourceResidency, - (void *)LockDevice9Ex_SetMaximumFrameLatency, - (void *)LockDevice9Ex_GetMaximumFrameLatency, - (void *)LockDevice9Ex_CheckDeviceState, - (void *)LockDevice9Ex_CreateRenderTargetEx, - (void *)LockDevice9Ex_CreateOffscreenPlainSurfaceEx, - (void *)LockDevice9Ex_CreateDepthStencilSurfaceEx, - (void *)LockDevice9Ex_ResetEx, - (void *)LockDevice9Ex_GetDisplayModeEx -}; - -static HRESULT NINE_WINAPI -LockDevice9Video_GetContentProtectionCaps( struct NineDevice9Video *This, - const GUID *pCryptoType, - const GUID *pDecodeProfile, - D3DCONTENTPROTECTIONCAPS *pCaps ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9Video_GetContentProtectionCaps(This, pCryptoType, pDecodeProfile, pCaps); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9Video_CreateAuthenticatedChannel( struct NineDevice9Video *This, - D3DAUTHENTICATEDCHANNELTYPE ChannelType, - IDirect3DAuthenticatedChannel9 **ppAuthenticatedChannel, - HANDLE *pChannelHandle ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9Video_CreateAuthenticatedChannel(This, ChannelType, ppAuthenticatedChannel, pChannelHandle); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockDevice9Video_CreateCryptoSession( struct NineDevice9Video *This, - const GUID *pCryptoType, - const GUID *pDecodeProfile, - IDirect3DCryptoSession9 **ppCryptoSession, - HANDLE *pCryptoHandle ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineDevice9Video_CreateCryptoSession(This, pCryptoType, pDecodeProfile, ppCryptoSession, pCryptoHandle); - mtx_unlock(&d3dlock_global); - return r; -} - -IDirect3DDevice9VideoVtbl LockDevice9Video_vtable = { - (void *)NineUnknown_QueryInterface, - (void *)NineUnknown_AddRef, - (void *)NineUnknown_ReleaseWithDtorLock, - (void *)LockDevice9Video_GetContentProtectionCaps, - (void *)LockDevice9Video_CreateAuthenticatedChannel, - (void *)LockDevice9Video_CreateCryptoSession -}; - -static HRESULT NINE_WINAPI -LockIndexBuffer9_Lock( struct NineIndexBuffer9 *This, - UINT OffsetToLock, - UINT SizeToLock, - void **ppbData, - DWORD Flags ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineIndexBuffer9_Lock(This, OffsetToLock, SizeToLock, ppbData, Flags); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockIndexBuffer9_Unlock( struct NineIndexBuffer9 *This ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineIndexBuffer9_Unlock(This); - mtx_unlock(&d3dlock_global); - return r; -} - -#if 0 -static HRESULT NINE_WINAPI -LockIndexBuffer9_GetDesc( struct NineIndexBuffer9 *This, - D3DINDEXBUFFER_DESC *pDesc ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineIndexBuffer9_GetDesc(This, pDesc); - mtx_unlock(&d3dlock_global); - return r; -} -#endif - -IDirect3DIndexBuffer9Vtbl LockIndexBuffer9_vtable = { - (void *)NineUnknown_QueryInterface, - (void *)NineUnknown_AddRef, - (void *)NineUnknown_ReleaseWithDtorLock, - (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */ - (void *)LockUnknown_SetPrivateData, - (void *)LockUnknown_GetPrivateData, - (void *)LockUnknown_FreePrivateData, - (void *)LockResource9_SetPriority, - (void *)LockResource9_GetPriority, - (void *)NineResource9_PreLoad, /* nop */ - (void *)NineResource9_GetType, /* immutable */ - (void *)LockIndexBuffer9_Lock, - (void *)LockIndexBuffer9_Unlock, - (void *)NineIndexBuffer9_GetDesc /* immutable */ -}; - -#if 0 -static HRESULT NINE_WINAPI -LockPixelShader9_GetDevice( struct NinePixelShader9 *This, - IDirect3DDevice9 **ppDevice ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineUnknown_GetDevice(NineUnknown(This), ppDevice); - mtx_unlock(&d3dlock_global); - return r; -} -#endif - -static HRESULT NINE_WINAPI -LockPixelShader9_GetFunction( struct NinePixelShader9 *This, - void *pData, - UINT *pSizeOfData ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NinePixelShader9_GetFunction(This, pData, pSizeOfData); - mtx_unlock(&d3dlock_global); - return r; -} - -IDirect3DPixelShader9Vtbl LockPixelShader9_vtable = { - (void *)NineUnknown_QueryInterface, - (void *)NineUnknown_AddRef, - (void *)NineUnknown_ReleaseWithDtorLock, - (void *)NineUnknown_GetDevice, - (void *)LockPixelShader9_GetFunction -}; - -#if 0 -static HRESULT NINE_WINAPI -LockQuery9_GetDevice( struct NineQuery9 *This, - IDirect3DDevice9 **ppDevice ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineUnknown_GetDevice(NineUnknown(This), ppDevice); - mtx_unlock(&d3dlock_global); - return r; -} -#endif - -#if 0 -static D3DQUERYTYPE NINE_WINAPI -LockQuery9_GetType( struct NineQuery9 *This ) -{ - D3DQUERYTYPE r; - mtx_lock(&d3dlock_global); - r = NineQuery9_GetType(This); - mtx_unlock(&d3dlock_global); - return r; -} -#endif - -#if 0 -static DWORD NINE_WINAPI -LockQuery9_GetDataSize( struct NineQuery9 *This ) -{ - DWORD r; - mtx_lock(&d3dlock_global); - r = NineQuery9_GetDataSize(This); - mtx_unlock(&d3dlock_global); - return r; -} -#endif - -static HRESULT NINE_WINAPI -LockQuery9_Issue( struct NineQuery9 *This, - DWORD dwIssueFlags ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineQuery9_Issue(This, dwIssueFlags); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockQuery9_GetData( struct NineQuery9 *This, - void *pData, - DWORD dwSize, - DWORD dwGetDataFlags ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineQuery9_GetData(This, pData, dwSize, dwGetDataFlags); - mtx_unlock(&d3dlock_global); - return r; -} - -IDirect3DQuery9Vtbl LockQuery9_vtable = { - (void *)NineUnknown_QueryInterface, - (void *)NineUnknown_AddRef, - (void *)NineUnknown_ReleaseWithDtorLock, - (void *)NineUnknown_GetDevice, /* actually part of Query9 iface */ - (void *)NineQuery9_GetType, /* immutable */ - (void *)NineQuery9_GetDataSize, /* immutable */ - (void *)LockQuery9_Issue, - (void *)LockQuery9_GetData -}; - -#if 0 -static HRESULT NINE_WINAPI -LockStateBlock9_GetDevice( struct NineStateBlock9 *This, - IDirect3DDevice9 **ppDevice ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineUnknown_GetDevice(NineUnknown(This), ppDevice); - mtx_unlock(&d3dlock_global); - return r; -} -#endif - -static HRESULT NINE_WINAPI -LockStateBlock9_Capture( struct NineStateBlock9 *This ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineStateBlock9_Capture(This); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockStateBlock9_Apply( struct NineStateBlock9 *This ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineStateBlock9_Apply(This); - mtx_unlock(&d3dlock_global); - return r; -} - -IDirect3DStateBlock9Vtbl LockStateBlock9_vtable = { - (void *)NineUnknown_QueryInterface, - (void *)NineUnknown_AddRef, - (void *)NineUnknown_ReleaseWithDtorLock, - (void *)NineUnknown_GetDevice, /* actually part of StateBlock9 iface */ - (void *)LockStateBlock9_Capture, - (void *)LockStateBlock9_Apply -}; - -static HRESULT NINE_WINAPI -LockSurface9_GetContainer( struct NineSurface9 *This, - REFIID riid, - void **ppContainer ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineSurface9_GetContainer(This, riid, ppContainer); - mtx_unlock(&d3dlock_global); - return r; -} - -#if 0 -static HRESULT NINE_WINAPI -LockSurface9_GetDesc( struct NineSurface9 *This, - D3DSURFACE_DESC *pDesc ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineSurface9_GetDesc(This, pDesc); - mtx_unlock(&d3dlock_global); - return r; -} -#endif - -static HRESULT NINE_WINAPI -LockSurface9_LockRect( struct NineSurface9 *This, - D3DLOCKED_RECT *pLockedRect, - const RECT *pRect, - DWORD Flags ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineSurface9_LockRect(This, pLockedRect, pRect, Flags); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockSurface9_UnlockRect( struct NineSurface9 *This ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineSurface9_UnlockRect(This); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockSurface9_GetDC( struct NineSurface9 *This, - HDC *phdc ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineSurface9_GetDC(This, phdc); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockSurface9_ReleaseDC( struct NineSurface9 *This, - HDC hdc ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineSurface9_ReleaseDC(This, hdc); - mtx_unlock(&d3dlock_global); - return r; -} - -IDirect3DSurface9Vtbl LockSurface9_vtable = { - (void *)NineUnknown_QueryInterface, - (void *)NineUnknown_AddRef, - (void *)NineUnknown_ReleaseWithDtorLock, - (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */ - (void *)LockUnknown_SetPrivateData, - (void *)LockUnknown_GetPrivateData, - (void *)LockUnknown_FreePrivateData, - (void *)LockResource9_SetPriority, - (void *)LockResource9_GetPriority, - (void *)NineResource9_PreLoad, /* nop */ - (void *)NineResource9_GetType, /* immutable */ - (void *)LockSurface9_GetContainer, - (void *)NineSurface9_GetDesc, /* immutable */ - (void *)LockSurface9_LockRect, - (void *)LockSurface9_UnlockRect, - (void *)LockSurface9_GetDC, - (void *)LockSurface9_ReleaseDC -}; - -static HRESULT NINE_WINAPI -LockSwapChain9_Present( struct NineSwapChain9 *This, - const RECT *pSourceRect, - const RECT *pDestRect, - HWND hDestWindowOverride, - const RGNDATA *pDirtyRegion, - DWORD dwFlags ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineSwapChain9_Present(This, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, dwFlags); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockSwapChain9_GetFrontBufferData( struct NineSwapChain9 *This, - IDirect3DSurface9 *pDestSurface ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineSwapChain9_GetFrontBufferData(This, pDestSurface); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockSwapChain9_GetBackBuffer( struct NineSwapChain9 *This, - UINT iBackBuffer, - D3DBACKBUFFER_TYPE Type, - IDirect3DSurface9 **ppBackBuffer ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineSwapChain9_GetBackBuffer(This, iBackBuffer, Type, ppBackBuffer); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockSwapChain9_GetRasterStatus( struct NineSwapChain9 *This, - D3DRASTER_STATUS *pRasterStatus ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineSwapChain9_GetRasterStatus(This, pRasterStatus); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockSwapChain9_GetDisplayMode( struct NineSwapChain9 *This, - D3DDISPLAYMODE *pMode ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineSwapChain9_GetDisplayMode(This, pMode); - mtx_unlock(&d3dlock_global); - return r; -} - -#if 0 -static HRESULT NINE_WINAPI -LockSwapChain9_GetDevice( struct NineSwapChain9 *This, - IDirect3DDevice9 **ppDevice ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineUnknown_GetDevice(NineUnknown(This), ppDevice); - mtx_unlock(&d3dlock_global); - return r; -} -#endif - -static HRESULT NINE_WINAPI -LockSwapChain9_GetPresentParameters( struct NineSwapChain9 *This, - D3DPRESENT_PARAMETERS *pPresentationParameters ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineSwapChain9_GetPresentParameters(This, pPresentationParameters); - mtx_unlock(&d3dlock_global); - return r; -} - -IDirect3DSwapChain9Vtbl LockSwapChain9_vtable = { - (void *)NineUnknown_QueryInterface, - (void *)NineUnknown_AddRef, - (void *)NineUnknown_ReleaseWithDtorLock, - (void *)LockSwapChain9_Present, - (void *)LockSwapChain9_GetFrontBufferData, - (void *)LockSwapChain9_GetBackBuffer, - (void *)LockSwapChain9_GetRasterStatus, - (void *)LockSwapChain9_GetDisplayMode, - (void *)NineUnknown_GetDevice, /* actually part of SwapChain9 iface */ - (void *)LockSwapChain9_GetPresentParameters -}; - -static HRESULT NINE_WINAPI -LockSwapChain9Ex_GetLastPresentCount( struct NineSwapChain9Ex *This, - UINT *pLastPresentCount ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineSwapChain9Ex_GetLastPresentCount(This, pLastPresentCount); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockSwapChain9Ex_GetPresentStats( struct NineSwapChain9Ex *This, - D3DPRESENTSTATS *pPresentationStatistics ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineSwapChain9Ex_GetPresentStats(This, pPresentationStatistics); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockSwapChain9Ex_GetDisplayModeEx( struct NineSwapChain9Ex *This, - D3DDISPLAYMODEEX *pMode, - D3DDISPLAYROTATION *pRotation ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineSwapChain9Ex_GetDisplayModeEx(This, pMode, pRotation); - mtx_unlock(&d3dlock_global); - return r; -} - -IDirect3DSwapChain9ExVtbl LockSwapChain9Ex_vtable = { - (void *)NineUnknown_QueryInterface, - (void *)NineUnknown_AddRef, - (void *)NineUnknown_ReleaseWithDtorLock, - (void *)LockSwapChain9_Present, - (void *)LockSwapChain9_GetFrontBufferData, - (void *)LockSwapChain9_GetBackBuffer, - (void *)LockSwapChain9_GetRasterStatus, - (void *)LockSwapChain9_GetDisplayMode, - (void *)NineUnknown_GetDevice, /* actually part of NineSwapChain9 iface */ - (void *)LockSwapChain9_GetPresentParameters, - (void *)LockSwapChain9Ex_GetLastPresentCount, - (void *)LockSwapChain9Ex_GetPresentStats, - (void *)LockSwapChain9Ex_GetDisplayModeEx -}; - -#if 0 -static HRESULT NINE_WINAPI -LockTexture9_GetLevelDesc( struct NineTexture9 *This, - UINT Level, - D3DSURFACE_DESC *pDesc ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineTexture9_GetLevelDesc(This, Level, pDesc); - mtx_unlock(&d3dlock_global); - return r; -} -#endif - -#if 0 -static HRESULT NINE_WINAPI -LockTexture9_GetSurfaceLevel( struct NineTexture9 *This, - UINT Level, - IDirect3DSurface9 **ppSurfaceLevel ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineTexture9_GetSurfaceLevel(This, Level, ppSurfaceLevel); - mtx_unlock(&d3dlock_global); - return r; -} -#endif - -static HRESULT NINE_WINAPI -LockTexture9_LockRect( struct NineTexture9 *This, - UINT Level, - D3DLOCKED_RECT *pLockedRect, - const RECT *pRect, - DWORD Flags ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineTexture9_LockRect(This, Level, pLockedRect, pRect, Flags); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockTexture9_UnlockRect( struct NineTexture9 *This, - UINT Level ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineTexture9_UnlockRect(This, Level); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockTexture9_AddDirtyRect( struct NineTexture9 *This, - const RECT *pDirtyRect ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineTexture9_AddDirtyRect(This, pDirtyRect); - mtx_unlock(&d3dlock_global); - return r; -} - -IDirect3DTexture9Vtbl LockTexture9_vtable = { - (void *)NineUnknown_QueryInterface, - (void *)NineUnknown_AddRef, - (void *)NineUnknown_ReleaseWithDtorLock, - (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */ - (void *)LockUnknown_SetPrivateData, - (void *)LockUnknown_GetPrivateData, - (void *)LockUnknown_FreePrivateData, - (void *)LockResource9_SetPriority, - (void *)LockResource9_GetPriority, - (void *)LockBaseTexture9_PreLoad, - (void *)NineResource9_GetType, /* immutable */ - (void *)LockBaseTexture9_SetLOD, - (void *)LockBaseTexture9_GetLOD, - (void *)LockBaseTexture9_GetLevelCount, - (void *)LockBaseTexture9_SetAutoGenFilterType, - (void *)LockBaseTexture9_GetAutoGenFilterType, - (void *)LockBaseTexture9_GenerateMipSubLevels, - (void *)NineTexture9_GetLevelDesc, /* immutable */ - (void *)NineTexture9_GetSurfaceLevel, /* AddRef */ - (void *)LockTexture9_LockRect, - (void *)LockTexture9_UnlockRect, - (void *)LockTexture9_AddDirtyRect -}; - -static HRESULT NINE_WINAPI -LockVertexBuffer9_Lock( struct NineVertexBuffer9 *This, - UINT OffsetToLock, - UINT SizeToLock, - void **ppbData, - DWORD Flags ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineVertexBuffer9_Lock(This, OffsetToLock, SizeToLock, ppbData, Flags); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockVertexBuffer9_Unlock( struct NineVertexBuffer9 *This ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineVertexBuffer9_Unlock(This); - mtx_unlock(&d3dlock_global); - return r; -} - -#if 0 -static HRESULT NINE_WINAPI -LockVertexBuffer9_GetDesc( struct NineVertexBuffer9 *This, - D3DVERTEXBUFFER_DESC *pDesc ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineVertexBuffer9_GetDesc(This, pDesc); - mtx_unlock(&d3dlock_global); - return r; -} -#endif - -IDirect3DVertexBuffer9Vtbl LockVertexBuffer9_vtable = { - (void *)NineUnknown_QueryInterface, - (void *)NineUnknown_AddRef, - (void *)NineUnknown_ReleaseWithDtorLock, - (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */ - (void *)LockUnknown_SetPrivateData, - (void *)LockUnknown_GetPrivateData, - (void *)LockUnknown_FreePrivateData, - (void *)LockResource9_SetPriority, - (void *)LockResource9_GetPriority, - (void *)NineResource9_PreLoad, /* nop */ - (void *)NineResource9_GetType, /* immutable */ - (void *)LockVertexBuffer9_Lock, - (void *)LockVertexBuffer9_Unlock, - (void *)NineVertexBuffer9_GetDesc /* immutable */ -}; - -#if 0 -static HRESULT NINE_WINAPI -LockVertexDeclaration9_GetDevice( struct NineVertexDeclaration9 *This, - IDirect3DDevice9 **ppDevice ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineUnknown_GetDevice(NineUnknown(This), ppDevice); - mtx_unlock(&d3dlock_global); - return r; -} -#endif - -static HRESULT NINE_WINAPI -LockVertexDeclaration9_GetDeclaration( struct NineVertexDeclaration9 *This, - D3DVERTEXELEMENT9 *pElement, - UINT *pNumElements ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineVertexDeclaration9_GetDeclaration(This, pElement, pNumElements); - mtx_unlock(&d3dlock_global); - return r; -} - -IDirect3DVertexDeclaration9Vtbl LockVertexDeclaration9_vtable = { - (void *)NineUnknown_QueryInterface, - (void *)NineUnknown_AddRef, - (void *)NineUnknown_ReleaseWithDtorLock, - (void *)NineUnknown_GetDevice, /* actually part of VertexDecl9 iface */ - (void *)LockVertexDeclaration9_GetDeclaration -}; - -#if 0 -static HRESULT NINE_WINAPI -LockVertexShader9_GetDevice( struct NineVertexShader9 *This, - IDirect3DDevice9 **ppDevice ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineUnknown_GetDevice(NineUnknown(This), ppDevice); - mtx_unlock(&d3dlock_global); - return r; -} -#endif - -static HRESULT NINE_WINAPI -LockVertexShader9_GetFunction( struct NineVertexShader9 *This, - void *pData, - UINT *pSizeOfData ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineVertexShader9_GetFunction(This, pData, pSizeOfData); - mtx_unlock(&d3dlock_global); - return r; -} - -IDirect3DVertexShader9Vtbl LockVertexShader9_vtable = { - (void *)NineUnknown_QueryInterface, - (void *)NineUnknown_AddRef, - (void *)NineUnknown_ReleaseWithDtorLock, - (void *)NineUnknown_GetDevice, - (void *)LockVertexShader9_GetFunction -}; - -#if 0 -static HRESULT NINE_WINAPI -LockVolume9_GetDevice( struct NineVolume9 *This, - IDirect3DDevice9 **ppDevice ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineUnknown_GetDevice(NineUnknown(This), ppDevice); - mtx_unlock(&d3dlock_global); - return r; -} -#endif - -static HRESULT NINE_WINAPI -LockVolume9_GetContainer( struct NineVolume9 *This, - REFIID riid, - void **ppContainer ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineVolume9_GetContainer(This, riid, ppContainer); - mtx_unlock(&d3dlock_global); - return r; -} - -#if 0 -static HRESULT NINE_WINAPI -LockVolume9_GetDesc( struct NineVolume9 *This, - D3DVOLUME_DESC *pDesc ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineVolume9_GetDesc(This, pDesc); - mtx_unlock(&d3dlock_global); - return r; -} -#endif - -static HRESULT NINE_WINAPI -LockVolume9_LockBox( struct NineVolume9 *This, - D3DLOCKED_BOX *pLockedVolume, - const D3DBOX *pBox, - DWORD Flags ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineVolume9_LockBox(This, pLockedVolume, pBox, Flags); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockVolume9_UnlockBox( struct NineVolume9 *This ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineVolume9_UnlockBox(This); - mtx_unlock(&d3dlock_global); - return r; -} - -IDirect3DVolume9Vtbl LockVolume9_vtable = { - (void *)NineUnknown_QueryInterface, - (void *)NineUnknown_AddRef, - (void *)NineUnknown_ReleaseWithDtorLock, - (void *)NineUnknown_GetDevice, /* actually part of Volume9 iface */ - (void *)NineUnknown_SetPrivateData, - (void *)NineUnknown_GetPrivateData, - (void *)NineUnknown_FreePrivateData, - (void *)LockVolume9_GetContainer, - (void *)NineVolume9_GetDesc, /* immutable */ - (void *)LockVolume9_LockBox, - (void *)LockVolume9_UnlockBox -}; - -#if 0 -static HRESULT NINE_WINAPI -LockVolumeTexture9_GetLevelDesc( struct NineVolumeTexture9 *This, - UINT Level, - D3DVOLUME_DESC *pDesc ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineVolumeTexture9_GetLevelDesc(This, Level, pDesc); - mtx_unlock(&d3dlock_global); - return r; -} -#endif - -#if 0 -static HRESULT NINE_WINAPI -LockVolumeTexture9_GetVolumeLevel( struct NineVolumeTexture9 *This, - UINT Level, - IDirect3DVolume9 **ppVolumeLevel ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineVolumeTexture9_GetVolumeLevel(This, Level, ppVolumeLevel); - mtx_unlock(&d3dlock_global); - return r; -} -#endif - -static HRESULT NINE_WINAPI -LockVolumeTexture9_LockBox( struct NineVolumeTexture9 *This, - UINT Level, - D3DLOCKED_BOX *pLockedVolume, - const D3DBOX *pBox, - DWORD Flags ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineVolumeTexture9_LockBox(This, Level, pLockedVolume, pBox, Flags); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockVolumeTexture9_UnlockBox( struct NineVolumeTexture9 *This, - UINT Level ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineVolumeTexture9_UnlockBox(This, Level); - mtx_unlock(&d3dlock_global); - return r; -} - -static HRESULT NINE_WINAPI -LockVolumeTexture9_AddDirtyBox( struct NineVolumeTexture9 *This, - const D3DBOX *pDirtyBox ) -{ - HRESULT r; - mtx_lock(&d3dlock_global); - r = NineVolumeTexture9_AddDirtyBox(This, pDirtyBox); - mtx_unlock(&d3dlock_global); - return r; -} - -IDirect3DVolumeTexture9Vtbl LockVolumeTexture9_vtable = { - (void *)NineUnknown_QueryInterface, - (void *)NineUnknown_AddRef, - (void *)NineUnknown_ReleaseWithDtorLock, - (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */ - (void *)LockUnknown_SetPrivateData, - (void *)LockUnknown_GetPrivateData, - (void *)LockUnknown_FreePrivateData, - (void *)LockResource9_SetPriority, - (void *)LockResource9_GetPriority, - (void *)LockBaseTexture9_PreLoad, - (void *)NineResource9_GetType, /* immutable */ - (void *)LockBaseTexture9_SetLOD, - (void *)LockBaseTexture9_GetLOD, - (void *)LockBaseTexture9_GetLevelCount, - (void *)LockBaseTexture9_SetAutoGenFilterType, - (void *)LockBaseTexture9_GetAutoGenFilterType, - (void *)LockBaseTexture9_GenerateMipSubLevels, - (void *)NineVolumeTexture9_GetLevelDesc, /* immutable */ - (void *)NineVolumeTexture9_GetVolumeLevel, /* AddRef */ - (void *)LockVolumeTexture9_LockBox, - (void *)LockVolumeTexture9_UnlockBox, - (void *)LockVolumeTexture9_AddDirtyBox -}; - -ID3DAdapter9Vtbl LockAdapter9_vtable = { /* not used */ - (void *)NULL, - (void *)NULL, - (void *)NULL, - (void *)NULL, - (void *)NULL, - (void *)NULL, - (void *)NULL, - (void *)NULL, - (void *)NULL, - (void *)NULL, - (void *)NULL, - (void *)NULL -}; diff --git a/src/gallium/state_trackers/nine/nine_lock.h b/src/gallium/state_trackers/nine/nine_lock.h deleted file mode 100644 index 4f4a5f14e54..00000000000 --- a/src/gallium/state_trackers/nine/nine_lock.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2013 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef _NINE_LOCK_H_ -#define _NINE_LOCK_H_ - -#include "d3d9.h" -#include "d3dadapter/d3dadapter9.h" - -extern IDirect3DAuthenticatedChannel9Vtbl LockAuthenticatedChannel9_vtable; -extern IDirect3DCryptoSession9Vtbl LockCryptoSession9_vtable; -extern IDirect3DCubeTexture9Vtbl LockCubeTexture9_vtable; -extern IDirect3DDevice9Vtbl LockDevice9_vtable; -extern IDirect3DDevice9ExVtbl LockDevice9Ex_vtable; -extern IDirect3DDevice9VideoVtbl LockDevice9Video_vtable; -extern IDirect3DIndexBuffer9Vtbl LockIndexBuffer9_vtable; -extern IDirect3DPixelShader9Vtbl LockPixelShader9_vtable; -extern IDirect3DQuery9Vtbl LockQuery9_vtable; -extern IDirect3DStateBlock9Vtbl LockStateBlock9_vtable; -extern IDirect3DSurface9Vtbl LockSurface9_vtable; -extern IDirect3DSwapChain9Vtbl LockSwapChain9_vtable; -extern IDirect3DSwapChain9ExVtbl LockSwapChain9Ex_vtable; -extern IDirect3DTexture9Vtbl LockTexture9_vtable; -extern IDirect3DVertexBuffer9Vtbl LockVertexBuffer9_vtable; -extern IDirect3DVertexDeclaration9Vtbl LockVertexDeclaration9_vtable; -extern IDirect3DVertexShader9Vtbl LockVertexShader9_vtable; -extern IDirect3DVolume9Vtbl LockVolume9_vtable; -extern IDirect3DVolumeTexture9Vtbl LockVolumeTexture9_vtable; -extern IDirect3DVolumeTexture9Vtbl LockVolumeTexture9_vtable; -extern ID3DAdapter9Vtbl LockAdapter9_vtable; - -void NineLockGlobalMutex(void); -void NineUnlockGlobalMutex(void); - -#endif /* _NINE_LOCK_H_ */ diff --git a/src/gallium/state_trackers/nine/nine_pdata.h b/src/gallium/state_trackers/nine/nine_pdata.h deleted file mode 100644 index 8c73cd619ba..00000000000 --- a/src/gallium/state_trackers/nine/nine_pdata.h +++ /dev/null @@ -1,46 +0,0 @@ - -#ifndef _NINE_PDATA_H_ -#define _NINE_PDATA_H_ - -struct pheader -{ - boolean unknown; - GUID guid; - DWORD size; -}; - -static bool -ht_guid_compare( const void *a, - const void *b ) -{ - return GUID_equal(a, b); -} - -static uint32_t -ht_guid_hash( const void *key ) -{ - unsigned i, hash = 0; - const unsigned char *str = key; - - for (i = 0; i < sizeof(GUID); i++) { - hash = (unsigned)(str[i]) + (hash << 6) + (hash << 16) - hash; - } - - return hash; -} - -static enum pipe_error -ht_guid_delete( void *key, - void *value, - void *data ) -{ - struct pheader *header = value; - void *header_data = (void *)header + sizeof(*header); - - if (header->unknown) { IUnknown_Release(*(IUnknown **)header_data); } - FREE(header); - - return PIPE_OK; -} - -#endif /* _NINE_PDATA_H_ */ diff --git a/src/gallium/state_trackers/nine/nine_pipe.c b/src/gallium/state_trackers/nine/nine_pipe.c deleted file mode 100644 index cc63a9fce8f..00000000000 --- a/src/gallium/state_trackers/nine/nine_pipe.c +++ /dev/null @@ -1,383 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * Copyright 2013 Christoph Bumiller - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "device9.h" -#include "nine_pipe.h" - -#include "cso_cache/cso_context.h" - -void -nine_convert_dsa_state(struct pipe_depth_stencil_alpha_state *dsa_state, - const DWORD *rs) -{ - struct pipe_depth_stencil_alpha_state dsa; - - memset(&dsa, 0, sizeof(dsa)); /* memcmp safety */ - - if (rs[D3DRS_ZENABLE]) { - dsa.depth.enabled = 1; - dsa.depth.func = d3dcmpfunc_to_pipe_func(rs[D3DRS_ZFUNC]); - /* Disable depth write if no change can occur */ - dsa.depth.writemask = !!rs[D3DRS_ZWRITEENABLE] && - dsa.depth.func != PIPE_FUNC_EQUAL && - dsa.depth.func != PIPE_FUNC_NEVER; - } - - if (rs[D3DRS_STENCILENABLE]) { - dsa.stencil[0].enabled = 1; - dsa.stencil[0].func = d3dcmpfunc_to_pipe_func(rs[D3DRS_STENCILFUNC]); - dsa.stencil[0].fail_op = d3dstencilop_to_pipe_stencil_op(rs[D3DRS_STENCILFAIL]); - dsa.stencil[0].zpass_op = d3dstencilop_to_pipe_stencil_op(rs[D3DRS_STENCILPASS]); - dsa.stencil[0].zfail_op = d3dstencilop_to_pipe_stencil_op(rs[D3DRS_STENCILZFAIL]); - dsa.stencil[0].valuemask = rs[D3DRS_STENCILMASK]; - dsa.stencil[0].writemask = rs[D3DRS_STENCILWRITEMASK]; - - if (rs[D3DRS_TWOSIDEDSTENCILMODE]) { - dsa.stencil[1].enabled = 1; - dsa.stencil[1].func = d3dcmpfunc_to_pipe_func(rs[D3DRS_CCW_STENCILFUNC]); - dsa.stencil[1].fail_op = d3dstencilop_to_pipe_stencil_op(rs[D3DRS_CCW_STENCILFAIL]); - dsa.stencil[1].zpass_op = d3dstencilop_to_pipe_stencil_op(rs[D3DRS_CCW_STENCILPASS]); - dsa.stencil[1].zfail_op = d3dstencilop_to_pipe_stencil_op(rs[D3DRS_CCW_STENCILZFAIL]); - dsa.stencil[1].valuemask = dsa.stencil[0].valuemask; - dsa.stencil[1].writemask = dsa.stencil[0].writemask; - } - } - - if (rs[D3DRS_ALPHATESTENABLE]) { - dsa.alpha.enabled = 1; - dsa.alpha.func = d3dcmpfunc_to_pipe_func(rs[D3DRS_ALPHAFUNC]); - dsa.alpha.ref_value = (float)rs[D3DRS_ALPHAREF] / 255.0f; - } - - *dsa_state = dsa; -} - -void -nine_convert_rasterizer_state(struct NineDevice9 *device, - struct pipe_rasterizer_state *rast_state, - const DWORD *rs) -{ - struct pipe_rasterizer_state rast; - - memset(&rast, 0, sizeof(rast)); - - rast.flatshade = rs[D3DRS_SHADEMODE] == D3DSHADE_FLAT; - /* rast.light_twoside = 0; */ - /* rast.clamp_fragment_color = 0; */ - /* rast.clamp_vertex_color = 0; */ - /* rast.front_ccw = 0; */ - rast.cull_face = d3dcull_to_pipe_face(rs[D3DRS_CULLMODE]); - rast.fill_front = d3dfillmode_to_pipe_polygon_mode(rs[D3DRS_FILLMODE]); - rast.fill_back = rast.fill_front; - rast.offset_tri = !!(rs[D3DRS_DEPTHBIAS] | rs[D3DRS_SLOPESCALEDEPTHBIAS]); - rast.offset_line = rast.offset_tri; /* triangles in wireframe mode */ - rast.offset_point = 0; /* XXX ? */ - rast.scissor = !!rs[D3DRS_SCISSORTESTENABLE]; - /* rast.poly_smooth = 0; */ - /* rast.poly_stipple_enable = 0; */ - /* rast.point_smooth = 0; */ - rast.sprite_coord_mode = PIPE_SPRITE_COORD_UPPER_LEFT; - rast.point_quad_rasterization = 1; - rast.point_size_per_vertex = rs[NINED3DRS_VSPOINTSIZE]; - rast.multisample = rs[NINED3DRS_MULTISAMPLE]; - rast.line_smooth = !!rs[D3DRS_ANTIALIASEDLINEENABLE]; - /* rast.line_stipple_enable = 0; */ - rast.line_last_pixel = !!rs[D3DRS_LASTPIXEL]; - rast.flatshade_first = 1; - /* rast.half_pixel_center = 0; */ - /* rast.lower_left_origin = 0; */ - /* rast.bottom_edge_rule = 0; */ - /* rast.rasterizer_discard = 0; */ - rast.depth_clip_near = 1; - rast.depth_clip_far = 1; - rast.clip_halfz = 1; - rast.clip_plane_enable = rs[D3DRS_CLIPPLANEENABLE]; - /* rast.line_stipple_factor = 0; */ - /* rast.line_stipple_pattern = 0; */ - rast.sprite_coord_enable = rs[D3DRS_POINTSPRITEENABLE] ? 0xff : 0x00; - rast.line_width = 1.0f; - if (rs[NINED3DRS_VSPOINTSIZE]) { - rast.point_size = 1.0f; - } else { - rast.point_size = CLAMP(asfloat(rs[D3DRS_POINTSIZE]), - asfloat(rs[D3DRS_POINTSIZE_MIN]), - asfloat(rs[D3DRS_POINTSIZE_MAX])); - } - /* offset_units has the ogl/d3d11 meaning. - * d3d9: offset = scale * dz + bias - * ogl/d3d11: offset = scale * dz + r * bias - * with r implementation dependent (+ different formula for float depth - * buffers). r=2^-23 is often the right value for gallium drivers. - * If possible, use offset_units_unscaled, which gives the d3d9 - * behaviour, else scale by 1 << 23 */ - rast.offset_units = asfloat(rs[D3DRS_DEPTHBIAS]) * (device->driver_caps.offset_units_unscaled ? 1.0f : (float)(1 << 23)); - rast.offset_units_unscaled = device->driver_caps.offset_units_unscaled; - rast.offset_scale = asfloat(rs[D3DRS_SLOPESCALEDEPTHBIAS]); - /* rast.offset_clamp = 0.0f; */ - - *rast_state = rast; -} - -static inline void -nine_convert_blend_state_fixup(struct pipe_blend_state *blend, const DWORD *rs) -{ - if (unlikely(rs[D3DRS_SRCBLEND] == D3DBLEND_BOTHSRCALPHA || - rs[D3DRS_SRCBLEND] == D3DBLEND_BOTHINVSRCALPHA)) { - blend->rt[0].rgb_dst_factor = (rs[D3DRS_SRCBLEND] == D3DBLEND_BOTHSRCALPHA) ? - PIPE_BLENDFACTOR_INV_SRC_ALPHA : PIPE_BLENDFACTOR_SRC_ALPHA; - if (!rs[D3DRS_SEPARATEALPHABLENDENABLE]) - blend->rt[0].alpha_dst_factor = blend->rt[0].rgb_dst_factor; - } else - if (unlikely(rs[D3DRS_SEPARATEALPHABLENDENABLE] && - (rs[D3DRS_SRCBLENDALPHA] == D3DBLEND_BOTHSRCALPHA || - rs[D3DRS_SRCBLENDALPHA] == D3DBLEND_BOTHINVSRCALPHA))) { - blend->rt[0].alpha_dst_factor = (rs[D3DRS_SRCBLENDALPHA] == D3DBLEND_BOTHSRCALPHA) ? - PIPE_BLENDFACTOR_INV_SRC_ALPHA : PIPE_BLENDFACTOR_SRC_ALPHA; - } -} - -void -nine_convert_blend_state(struct pipe_blend_state *blend_state, const DWORD *rs) -{ - struct pipe_blend_state blend; - - memset(&blend, 0, sizeof(blend)); /* memcmp safety */ - - blend.dither = !!rs[D3DRS_DITHERENABLE]; - - /* blend.alpha_to_one = 0; */ - blend.alpha_to_coverage = rs[NINED3DRS_ALPHACOVERAGE] & 1; - - blend.rt[0].blend_enable = !!rs[D3DRS_ALPHABLENDENABLE]; - if (blend.rt[0].blend_enable) { - blend.rt[0].rgb_func = d3dblendop_to_pipe_blend(rs[D3DRS_BLENDOP]); - blend.rt[0].rgb_src_factor = d3dblend_color_to_pipe_blendfactor(rs[D3DRS_SRCBLEND]); - blend.rt[0].rgb_dst_factor = d3dblend_color_to_pipe_blendfactor(rs[D3DRS_DESTBLEND]); - if (rs[D3DRS_SEPARATEALPHABLENDENABLE]) { - blend.rt[0].alpha_func = d3dblendop_to_pipe_blend(rs[D3DRS_BLENDOPALPHA]); - blend.rt[0].alpha_src_factor = d3dblend_alpha_to_pipe_blendfactor(rs[D3DRS_SRCBLENDALPHA]); - blend.rt[0].alpha_dst_factor = d3dblend_alpha_to_pipe_blendfactor(rs[D3DRS_DESTBLENDALPHA]); - } else { - /* TODO: Just copy the rgb values ? SRC1_x may differ ... */ - blend.rt[0].alpha_func = blend.rt[0].rgb_func; - blend.rt[0].alpha_src_factor = d3dblend_alpha_to_pipe_blendfactor(rs[D3DRS_SRCBLEND]); - blend.rt[0].alpha_dst_factor = d3dblend_alpha_to_pipe_blendfactor(rs[D3DRS_DESTBLEND]); - } - nine_convert_blend_state_fixup(&blend, rs); /* for BOTH[INV]SRCALPHA */ - } - - blend.max_rt = 3; /* Upper bound. Could be optimized to fb->nr_cbufs for example */ - blend.rt[0].colormask = rs[D3DRS_COLORWRITEENABLE]; - - if (rs[D3DRS_COLORWRITEENABLE1] != rs[D3DRS_COLORWRITEENABLE] || - rs[D3DRS_COLORWRITEENABLE2] != rs[D3DRS_COLORWRITEENABLE] || - rs[D3DRS_COLORWRITEENABLE3] != rs[D3DRS_COLORWRITEENABLE]) { - unsigned i; - blend.independent_blend_enable = TRUE; - for (i = 1; i < 4; ++i) - blend.rt[i] = blend.rt[0]; - blend.rt[1].colormask = rs[D3DRS_COLORWRITEENABLE1]; - blend.rt[2].colormask = rs[D3DRS_COLORWRITEENABLE2]; - blend.rt[3].colormask = rs[D3DRS_COLORWRITEENABLE3]; - } - - /* blend.force_srgb = !!rs[D3DRS_SRGBWRITEENABLE]; */ - - *blend_state = blend; -} - -void -nine_convert_sampler_state(struct cso_context *ctx, int idx, const DWORD *ss) -{ - struct pipe_sampler_state samp; - - assert(idx >= 0 && - (idx < NINE_MAX_SAMPLERS_PS || idx >= NINE_SAMPLER_VS(0)) && - (idx < NINE_MAX_SAMPLERS)); - - memset(&samp, 0, sizeof(samp)); /* memcmp safety */ - - if (ss[D3DSAMP_MIPFILTER] != D3DTEXF_NONE) { - samp.lod_bias = asfloat(ss[D3DSAMP_MIPMAPLODBIAS]); - samp.min_lod = ss[NINED3DSAMP_MINLOD]; - samp.min_mip_filter = (ss[D3DSAMP_MIPFILTER] == D3DTEXF_POINT) ? PIPE_TEX_FILTER_NEAREST : PIPE_TEX_FILTER_LINEAR; - } else { - samp.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; - } - samp.max_lod = 15.0f; - - if (ss[NINED3DSAMP_CUBETEX]) { - /* Cube textures are always clamped to edge on D3D */ - samp.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; - samp.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; - samp.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; - } else { - samp.wrap_s = d3dtextureaddress_to_pipe_tex_wrap(ss[D3DSAMP_ADDRESSU]); - samp.wrap_t = d3dtextureaddress_to_pipe_tex_wrap(ss[D3DSAMP_ADDRESSV]); - samp.wrap_r = d3dtextureaddress_to_pipe_tex_wrap(ss[D3DSAMP_ADDRESSW]); - } - samp.min_img_filter = (ss[D3DSAMP_MINFILTER] == D3DTEXF_POINT && !ss[NINED3DSAMP_SHADOW]) ? PIPE_TEX_FILTER_NEAREST : PIPE_TEX_FILTER_LINEAR; - samp.mag_img_filter = (ss[D3DSAMP_MAGFILTER] == D3DTEXF_POINT && !ss[NINED3DSAMP_SHADOW]) ? PIPE_TEX_FILTER_NEAREST : PIPE_TEX_FILTER_LINEAR; - if (ss[D3DSAMP_MINFILTER] == D3DTEXF_ANISOTROPIC || - ss[D3DSAMP_MAGFILTER] == D3DTEXF_ANISOTROPIC) - samp.max_anisotropy = ss[D3DSAMP_MAXANISOTROPY]; - samp.compare_mode = ss[NINED3DSAMP_SHADOW] ? PIPE_TEX_COMPARE_R_TO_TEXTURE : PIPE_TEX_COMPARE_NONE; - samp.compare_func = PIPE_FUNC_LEQUAL; - samp.normalized_coords = 1; - samp.seamless_cube_map = 0; - d3dcolor_to_pipe_color_union(&samp.border_color, ss[D3DSAMP_BORDERCOLOR]); - - /* see nine_state.h */ - if (idx < NINE_MAX_SAMPLERS_PS) - cso_single_sampler(ctx, PIPE_SHADER_FRAGMENT, idx - NINE_SAMPLER_PS(0), &samp); - else - cso_single_sampler(ctx, PIPE_SHADER_VERTEX, idx - NINE_SAMPLER_VS(0), &samp); -} - -const enum pipe_format nine_d3d9_to_pipe_format_map[120] = -{ - [D3DFMT_UNKNOWN] = PIPE_FORMAT_NONE, - [D3DFMT_R8G8B8] = PIPE_FORMAT_R8G8B8_UNORM, - [D3DFMT_A8R8G8B8] = PIPE_FORMAT_B8G8R8A8_UNORM, - [D3DFMT_X8R8G8B8] = PIPE_FORMAT_B8G8R8X8_UNORM, - [D3DFMT_R5G6B5] = PIPE_FORMAT_B5G6R5_UNORM, - [D3DFMT_X1R5G5B5] = PIPE_FORMAT_B5G5R5X1_UNORM, - [D3DFMT_A1R5G5B5] = PIPE_FORMAT_B5G5R5A1_UNORM, - [D3DFMT_A4R4G4B4] = PIPE_FORMAT_B4G4R4A4_UNORM, - [D3DFMT_R3G3B2] = PIPE_FORMAT_B2G3R3_UNORM, - [D3DFMT_A8] = PIPE_FORMAT_A8_UNORM, - [D3DFMT_A8R3G3B2] = PIPE_FORMAT_NONE, - [D3DFMT_X4R4G4B4] = PIPE_FORMAT_B4G4R4X4_UNORM, - [D3DFMT_A2B10G10R10] = PIPE_FORMAT_R10G10B10A2_UNORM, - [D3DFMT_A8B8G8R8] = PIPE_FORMAT_R8G8B8A8_UNORM, - [D3DFMT_X8B8G8R8] = PIPE_FORMAT_R8G8B8X8_UNORM, - [D3DFMT_G16R16] = PIPE_FORMAT_R16G16_UNORM, - [D3DFMT_A2R10G10B10] = PIPE_FORMAT_B10G10R10A2_UNORM, - [D3DFMT_A16B16G16R16] = PIPE_FORMAT_R16G16B16A16_UNORM, - [D3DFMT_A8P8] = PIPE_FORMAT_NONE, - [D3DFMT_P8] = PIPE_FORMAT_NONE, - [D3DFMT_L8] = PIPE_FORMAT_L8_UNORM, - [D3DFMT_A8L8] = PIPE_FORMAT_L8A8_UNORM, - [D3DFMT_A4L4] = PIPE_FORMAT_L4A4_UNORM, - [D3DFMT_V8U8] = PIPE_FORMAT_R8G8_SNORM, - [D3DFMT_L6V5U5] = PIPE_FORMAT_NONE, /* Should be PIPE_FORMAT_R5SG5SB6U_NORM, but interpretation of the data differs a bit. */ - [D3DFMT_X8L8V8U8] = PIPE_FORMAT_R8SG8SB8UX8U_NORM, - [D3DFMT_Q8W8V8U8] = PIPE_FORMAT_R8G8B8A8_SNORM, - [D3DFMT_V16U16] = PIPE_FORMAT_R16G16_SNORM, - [D3DFMT_A2W10V10U10] = PIPE_FORMAT_R10SG10SB10SA2U_NORM, - [D3DFMT_D16_LOCKABLE] = PIPE_FORMAT_Z16_UNORM, - [D3DFMT_D32] = PIPE_FORMAT_Z32_UNORM, - [D3DFMT_D15S1] = PIPE_FORMAT_NONE, - [D3DFMT_D24S8] = PIPE_FORMAT_S8_UINT_Z24_UNORM, - [D3DFMT_D24X8] = PIPE_FORMAT_X8Z24_UNORM, - [D3DFMT_D24X4S4] = PIPE_FORMAT_NONE, - [D3DFMT_D16] = PIPE_FORMAT_Z16_UNORM, - [D3DFMT_D32F_LOCKABLE] = PIPE_FORMAT_Z32_FLOAT, - [D3DFMT_D24FS8] = PIPE_FORMAT_Z32_FLOAT_S8X24_UINT, - [D3DFMT_D32_LOCKABLE] = PIPE_FORMAT_NONE, - [D3DFMT_S8_LOCKABLE] = PIPE_FORMAT_NONE, - [D3DFMT_L16] = PIPE_FORMAT_L16_UNORM, - [D3DFMT_VERTEXDATA] = PIPE_FORMAT_NONE, - [D3DFMT_INDEX16] = PIPE_FORMAT_R16_UINT, - [D3DFMT_INDEX32] = PIPE_FORMAT_R32_UINT, - [D3DFMT_Q16W16V16U16] = PIPE_FORMAT_R16G16B16A16_SNORM, - [D3DFMT_R16F] = PIPE_FORMAT_R16_FLOAT, - [D3DFMT_G16R16F] = PIPE_FORMAT_R16G16_FLOAT, - [D3DFMT_A16B16G16R16F] = PIPE_FORMAT_R16G16B16A16_FLOAT, - [D3DFMT_R32F] = PIPE_FORMAT_R32_FLOAT, - [D3DFMT_G32R32F] = PIPE_FORMAT_R32G32_FLOAT, - [D3DFMT_A32B32G32R32F] = PIPE_FORMAT_R32G32B32A32_FLOAT, - [D3DFMT_CxV8U8] = PIPE_FORMAT_NONE, - [D3DFMT_A1] = PIPE_FORMAT_NONE, - [D3DFMT_A2B10G10R10_XR_BIAS] = PIPE_FORMAT_NONE, -}; - -const D3DFORMAT nine_pipe_to_d3d9_format_map[PIPE_FORMAT_COUNT] = -{ - [PIPE_FORMAT_NONE] = D3DFMT_UNKNOWN, - /* TODO: rename PIPE_FORMAT_R8G8B8_UNORM to PIPE_FORMAT_B8G8R8_UNORM */ - [PIPE_FORMAT_R8G8B8_UNORM] = D3DFMT_R8G8B8, - [PIPE_FORMAT_B8G8R8A8_UNORM] = D3DFMT_A8R8G8B8, - [PIPE_FORMAT_B8G8R8X8_UNORM] = D3DFMT_X8R8G8B8, - [PIPE_FORMAT_B5G6R5_UNORM] = D3DFMT_R5G6B5, - [PIPE_FORMAT_B5G5R5X1_UNORM] = D3DFMT_X1R5G5B5, - [PIPE_FORMAT_B5G5R5A1_UNORM] = D3DFMT_A1R5G5B5, - [PIPE_FORMAT_B4G4R4A4_UNORM] = D3DFMT_A4R4G4B4, - [PIPE_FORMAT_B2G3R3_UNORM] = D3DFMT_R3G3B2, - [PIPE_FORMAT_A8_UNORM] = D3DFMT_A8, -/* [PIPE_FORMAT_B2G3R3A8_UNORM] = D3DFMT_A8R3G3B2, */ - [PIPE_FORMAT_B4G4R4X4_UNORM] = D3DFMT_X4R4G4B4, - [PIPE_FORMAT_R10G10B10A2_UNORM] = D3DFMT_A2B10G10R10, - [PIPE_FORMAT_R8G8B8A8_UNORM] = D3DFMT_A8B8G8R8, - [PIPE_FORMAT_R8G8B8X8_UNORM] = D3DFMT_X8B8G8R8, - [PIPE_FORMAT_R16G16_UNORM] = D3DFMT_G16R16, - [PIPE_FORMAT_B10G10R10A2_UNORM] = D3DFMT_A2R10G10B10, - [PIPE_FORMAT_R16G16B16A16_UNORM] = D3DFMT_A16B16G16R16, - - [PIPE_FORMAT_R8_UINT] = D3DFMT_P8, - [PIPE_FORMAT_R8A8_UINT] = D3DFMT_A8P8, - - [PIPE_FORMAT_L8_UNORM] = D3DFMT_L8, - [PIPE_FORMAT_L8A8_UNORM] = D3DFMT_A8L8, - [PIPE_FORMAT_L4A4_UNORM] = D3DFMT_A4L4, - - [PIPE_FORMAT_R8G8_SNORM] = D3DFMT_V8U8, -/* [PIPE_FORMAT_?] = D3DFMT_L6V5U5, */ -/* [PIPE_FORMAT_?] = D3DFMT_X8L8V8U8, */ - [PIPE_FORMAT_R8G8B8A8_SNORM] = D3DFMT_Q8W8V8U8, - [PIPE_FORMAT_R16G16_SNORM] = D3DFMT_V16U16, - [PIPE_FORMAT_R10SG10SB10SA2U_NORM] = D3DFMT_A2W10V10U10, - - [PIPE_FORMAT_YUYV] = D3DFMT_UYVY, -/* [PIPE_FORMAT_YUY2] = D3DFMT_YUY2, */ - [PIPE_FORMAT_DXT1_RGBA] = D3DFMT_DXT1, -/* [PIPE_FORMAT_DXT2_RGBA] = D3DFMT_DXT2, */ - [PIPE_FORMAT_DXT3_RGBA] = D3DFMT_DXT3, -/* [PIPE_FORMAT_DXT4_RGBA] = D3DFMT_DXT4, */ - [PIPE_FORMAT_DXT5_RGBA] = D3DFMT_DXT5, -/* [PIPE_FORMAT_?] = D3DFMT_MULTI2_ARGB8, (MET) */ - [PIPE_FORMAT_R8G8_B8G8_UNORM] = D3DFMT_R8G8_B8G8, /* XXX: order */ - [PIPE_FORMAT_G8R8_G8B8_UNORM] = D3DFMT_G8R8_G8B8, - - [PIPE_FORMAT_Z16_UNORM] = D3DFMT_D16_LOCKABLE, - [PIPE_FORMAT_Z32_UNORM] = D3DFMT_D32, -/* [PIPE_FORMAT_Z15_UNORM_S1_UINT] = D3DFMT_D15S1, */ - [PIPE_FORMAT_S8_UINT_Z24_UNORM] = D3DFMT_D24S8, - [PIPE_FORMAT_X8Z24_UNORM] = D3DFMT_D24X8, - [PIPE_FORMAT_L16_UNORM] = D3DFMT_L16, - [PIPE_FORMAT_Z32_FLOAT] = D3DFMT_D32F_LOCKABLE, -/* [PIPE_FORMAT_Z24_FLOAT_S8_UINT] = D3DFMT_D24FS8, */ - - [PIPE_FORMAT_R16_UINT] = D3DFMT_INDEX16, - [PIPE_FORMAT_R32_UINT] = D3DFMT_INDEX32, - [PIPE_FORMAT_R16G16B16A16_SNORM] = D3DFMT_Q16W16V16U16, - - [PIPE_FORMAT_R16_FLOAT] = D3DFMT_R16F, - [PIPE_FORMAT_R32_FLOAT] = D3DFMT_R32F, - [PIPE_FORMAT_R16G16_FLOAT] = D3DFMT_G16R16F, - [PIPE_FORMAT_R32G32_FLOAT] = D3DFMT_G32R32F, - [PIPE_FORMAT_R16G16B16A16_FLOAT] = D3DFMT_A16B16G16R16F, - [PIPE_FORMAT_R32G32B32A32_FLOAT] = D3DFMT_A32B32G32R32F, - -/* [PIPE_FORMAT_?] = D3DFMT_CxV8U8, */ -}; diff --git a/src/gallium/state_trackers/nine/nine_pipe.h b/src/gallium/state_trackers/nine/nine_pipe.h deleted file mode 100644 index 6a85c042db7..00000000000 --- a/src/gallium/state_trackers/nine/nine_pipe.h +++ /dev/null @@ -1,827 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef _NINE_PIPE_H_ -#define _NINE_PIPE_H_ - -#include "d3d9.h" -#include "pipe/p_format.h" -#include "pipe/p_screen.h" -#include "pipe/p_state.h" /* pipe_box */ -#include "util/macros.h" -#include "util/u_rect.h" -#include "util/format/u_format.h" -#include "nine_helpers.h" - -struct cso_context; - -extern const enum pipe_format nine_d3d9_to_pipe_format_map[120]; -extern const D3DFORMAT nine_pipe_to_d3d9_format_map[PIPE_FORMAT_COUNT]; - -void nine_convert_dsa_state(struct pipe_depth_stencil_alpha_state *, const DWORD *); -void nine_convert_rasterizer_state(struct NineDevice9 *, struct pipe_rasterizer_state *, const DWORD *); -void nine_convert_blend_state(struct pipe_blend_state *, const DWORD *); -void nine_convert_sampler_state(struct cso_context *, int idx, const DWORD *); - -#define is_ATI1_ATI2(format) (format == PIPE_FORMAT_RGTC1_UNORM || format == PIPE_FORMAT_RGTC2_UNORM) - -static inline void -rect_to_pipe_box(struct pipe_box *dst, const RECT *src) -{ - dst->x = src->left; - dst->y = src->top; - dst->z = 0; - dst->width = src->right - src->left; - dst->height = src->bottom - src->top; - dst->depth = 1; -} - -static inline void -pipe_box_to_rect(RECT *dst, const struct pipe_box *src) -{ - dst->left = src->x; - dst->right = src->x + src->width; - dst->top = src->y; - dst->bottom = src->y + src->height; -} - -static inline void -rect_minify_inclusive(RECT *rect) -{ - rect->left = rect->left >> 2; - rect->top = rect->top >> 2; - rect->right = DIV_ROUND_UP(rect->right, 2); - rect->bottom = DIV_ROUND_UP(rect->bottom, 2); -} - -/* We suppose: - * 0 <= rect->left < rect->right - * 0 <= rect->top < rect->bottom - */ -static inline void -fit_rect_format_inclusive(enum pipe_format format, RECT *rect, int width, int height) -{ - const unsigned w = util_format_get_blockwidth(format); - const unsigned h = util_format_get_blockheight(format); - - if (util_format_is_compressed(format)) { - rect->left = rect->left - rect->left % w; - rect->top = rect->top - rect->top % h; - rect->right = (rect->right % w) == 0 ? - rect->right : - rect->right - (rect->right % w) + w; - rect->bottom = (rect->bottom % h) == 0 ? - rect->bottom : - rect->bottom - (rect->bottom % h) + h; - } - - rect->right = MIN2(rect->right, width); - rect->bottom = MIN2(rect->bottom, height); -} - -static inline boolean -rect_to_pipe_box_clamp(struct pipe_box *dst, const RECT *src) -{ - rect_to_pipe_box(dst, src); - - if (dst->width <= 0 || dst->height <= 0) { - DBG_FLAG(DBG_UNKNOWN, "Warning: NULL box"); - dst->width = MAX2(dst->width, 0); - dst->height = MAX2(dst->height, 0); - return TRUE; - } - return FALSE; -} - -static inline boolean -rect_to_pipe_box_flip(struct pipe_box *dst, const RECT *src) -{ - rect_to_pipe_box(dst, src); - - if (dst->width >= 0 && dst->height >= 0) - return FALSE; - if (dst->width < 0) dst->width = -dst->width; - if (dst->height < 0) dst->height = -dst->height; - return TRUE; -} - -static inline void -rect_to_pipe_box_xy_only(struct pipe_box *dst, const RECT *src) -{ - user_warn(src->left > src->right || src->top > src->bottom); - - dst->x = src->left; - dst->y = src->top; - dst->width = src->right - src->left; - dst->height = src->bottom - src->top; -} - -static inline boolean -rect_to_pipe_box_xy_only_clamp(struct pipe_box *dst, const RECT *src) -{ - rect_to_pipe_box_xy_only(dst, src); - - if (dst->width <= 0 || dst->height <= 0) { - DBG_FLAG(DBG_UNKNOWN, "Warning: NULL box"); - dst->width = MAX2(dst->width, 0); - dst->height = MAX2(dst->height, 0); - return TRUE; - } - return FALSE; -} - -static inline void -rect_to_g3d_u_rect(struct u_rect *dst, const RECT *src) -{ - user_warn(src->left > src->right || src->top > src->bottom); - - dst->x0 = src->left; - dst->x1 = src->right; - dst->y0 = src->top; - dst->y1 = src->bottom; -} - -static inline void -d3dbox_to_pipe_box(struct pipe_box *dst, const D3DBOX *src) -{ - user_warn(src->Left > src->Right); - user_warn(src->Top > src->Bottom); - user_warn(src->Front > src->Back); - - dst->x = src->Left; - dst->y = src->Top; - dst->z = src->Front; - dst->width = src->Right - src->Left; - dst->height = src->Bottom - src->Top; - dst->depth = src->Back - src->Front; -} - -static inline D3DFORMAT -pipe_to_d3d9_format(enum pipe_format format) -{ - return nine_pipe_to_d3d9_format_map[format]; -} - -/* ATI1 and ATI2 are not officially compressed in d3d9 */ -static inline boolean -compressed_format( D3DFORMAT fmt ) -{ - switch (fmt) { - case D3DFMT_DXT1: - case D3DFMT_DXT2: - case D3DFMT_DXT3: - case D3DFMT_DXT4: - case D3DFMT_DXT5: - return TRUE; - default: - break; - } - return FALSE; -} - -static inline boolean -depth_stencil_format( D3DFORMAT fmt ) -{ - static const D3DFORMAT allowed[] = { - D3DFMT_D16_LOCKABLE, - D3DFMT_D32, - D3DFMT_D15S1, - D3DFMT_D24S8, - D3DFMT_D24X8, - D3DFMT_D24X4S4, - D3DFMT_D16, - D3DFMT_D32F_LOCKABLE, - D3DFMT_D24FS8, - D3DFMT_D32_LOCKABLE, - D3DFMT_DF16, - D3DFMT_DF24, - D3DFMT_INTZ - }; - unsigned i; - - for (i = 0; i < sizeof(allowed)/sizeof(D3DFORMAT); i++) { - if (fmt == allowed[i]) { return TRUE; } - } - return FALSE; -} - -static inline unsigned -d3d9_get_pipe_depth_format_bindings(D3DFORMAT format) -{ - switch (format) { - case D3DFMT_D32: - case D3DFMT_D15S1: - case D3DFMT_D24S8: - case D3DFMT_D24X8: - case D3DFMT_D24X4S4: - case D3DFMT_D16: - case D3DFMT_D24FS8: - return PIPE_BIND_DEPTH_STENCIL; - case D3DFMT_D32F_LOCKABLE: - case D3DFMT_D16_LOCKABLE: - case D3DFMT_D32_LOCKABLE: - return PIPE_BIND_DEPTH_STENCIL; - case D3DFMT_DF16: - case D3DFMT_DF24: - case D3DFMT_INTZ: - return PIPE_BIND_DEPTH_STENCIL | PIPE_BIND_SAMPLER_VIEW; - default: unreachable("Unexpected format"); - } -} - -static inline enum pipe_format -d3d9_to_pipe_format_internal(D3DFORMAT format) -{ - if (format <= D3DFMT_A2B10G10R10_XR_BIAS) - return nine_d3d9_to_pipe_format_map[format]; - switch (format) { - case D3DFMT_INTZ: return PIPE_FORMAT_S8_UINT_Z24_UNORM; - case D3DFMT_DF16: return PIPE_FORMAT_Z16_UNORM; - case D3DFMT_DXT1: return PIPE_FORMAT_DXT1_RGBA; - case D3DFMT_DXT2: return PIPE_FORMAT_DXT3_RGBA; /* XXX */ - case D3DFMT_DXT3: return PIPE_FORMAT_DXT3_RGBA; - case D3DFMT_DXT4: return PIPE_FORMAT_DXT5_RGBA; /* XXX */ - case D3DFMT_DXT5: return PIPE_FORMAT_DXT5_RGBA; - case D3DFMT_ATI1: return PIPE_FORMAT_RGTC1_UNORM; - case D3DFMT_ATI2: return PIPE_FORMAT_RGTC2_UNORM; - case D3DFMT_UYVY: return PIPE_FORMAT_UYVY; - case D3DFMT_YUY2: return PIPE_FORMAT_YUYV; /* XXX check */ - case D3DFMT_NV12: return PIPE_FORMAT_NV12; - case D3DFMT_G8R8_G8B8: return PIPE_FORMAT_G8R8_G8B8_UNORM; /* XXX order ? */ - case D3DFMT_R8G8_B8G8: return PIPE_FORMAT_R8G8_B8G8_UNORM; /* XXX order ? */ - case D3DFMT_BINARYBUFFER: return PIPE_FORMAT_NONE; /* not a format */ - case D3DFMT_MULTI2_ARGB8: return PIPE_FORMAT_NONE; /* not supported */ - case D3DFMT_Y210: /* XXX */ - case D3DFMT_Y216: - case D3DFMT_NV11: - case D3DFMT_DF24: /* Similar to D3DFMT_DF16 but for 24-bits. - We don't advertise it because when it is supported, Fetch-4 is - supposed to be supported, which we don't support yet. */ - case D3DFMT_NULL: /* special cased, only for surfaces */ - return PIPE_FORMAT_NONE; - default: - DBG_FLAG(DBG_UNKNOWN, "unknown D3DFORMAT: 0x%x/%c%c%c%c\n", - format, (char)format, (char)(format >> 8), - (char)(format >> 16), (char)(format >> 24)); - return PIPE_FORMAT_NONE; - } -} - -#define format_check_internal(pipe_format) \ - screen->is_format_supported(screen, pipe_format, target, \ - sample_count, sample_count, bindings) - -static inline enum pipe_format -d3d9_to_pipe_format_checked(struct pipe_screen *screen, - D3DFORMAT format, - enum pipe_texture_target target, - unsigned sample_count, - unsigned bindings, - boolean srgb, - boolean bypass_check) -{ - enum pipe_format result; - - result = d3d9_to_pipe_format_internal(format); - if (result == PIPE_FORMAT_NONE) - return PIPE_FORMAT_NONE; - - if (srgb) - result = util_format_srgb(result); - - /* bypass_check: Used for D3DPOOL_SCRATCH, which - * isn't limited to the formats supported by the - * device, and to check we are not using a format - * fallback. */ - if (bypass_check || format_check_internal(result)) - return result; - - /* fallback to another format for formats - * that match several pipe_format */ - switch(format) { - /* depth buffer formats are not lockable (except those for which it - * is precised in the name), so it is ok to match to another similar - * format. In all cases, if the app reads the texture with a shader, - * it gets depth on r and doesn't get stencil.*/ - case D3DFMT_INTZ: - case D3DFMT_D24S8: - if (format_check_internal(PIPE_FORMAT_Z24_UNORM_S8_UINT)) - return PIPE_FORMAT_Z24_UNORM_S8_UINT; - break; - case D3DFMT_D24X8: - if (format_check_internal(PIPE_FORMAT_Z24X8_UNORM)) - return PIPE_FORMAT_Z24X8_UNORM; - break; - /* Support for X8L8V8U8 bumpenvmap format with lighting bits. - * X8L8V8U8 is commonly supported among dx9 cards. - * To avoid precision loss, we use PIPE_FORMAT_R32G32B32X32_FLOAT, - * however using PIPE_FORMAT_R8G8B8A8_SNORM should be ok */ - case D3DFMT_X8L8V8U8: - if (bindings & PIPE_BIND_RENDER_TARGET) - return PIPE_FORMAT_NONE; - if (format_check_internal(PIPE_FORMAT_R32G32B32X32_FLOAT)) - return PIPE_FORMAT_R32G32B32X32_FLOAT; - default: - break; - } - return PIPE_FORMAT_NONE; -} - -/* The quality levels are vendor dependent, so we set our own. - * Every quality level has its own sample count and sample - * position matrix. - * The exact mapping might differ from system to system but thats OK, - * as there's no way to gather more information about quality levels - * in D3D9. - * In case of NONMASKABLE multisample map every quality-level - * to a MASKABLE MultiSampleType: - * 0: no MSAA - * 1: 2x MSAA - * 2: 4x MSAA - * ... - * If the requested quality level is not available to nearest - * matching quality level is used. - * If no multisample is available the function sets - * multisample to D3DMULTISAMPLE_NONE and returns zero. - */ -static inline HRESULT -d3dmultisample_type_check(struct pipe_screen *screen, - D3DFORMAT format, - D3DMULTISAMPLE_TYPE *multisample, - DWORD multisamplequality, - DWORD *levels) -{ - unsigned bind, i; - - assert(multisample); - - if (levels) - *levels = 1; - - /* Ignores multisamplequality */ - if (*multisample == D3DMULTISAMPLE_NONE) - return D3D_OK; - - if (*multisample == D3DMULTISAMPLE_NONMASKABLE) { - if (depth_stencil_format(format)) - bind = d3d9_get_pipe_depth_format_bindings(format); - else /* render-target */ - bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; - - *multisample = 0; - for (i = D3DMULTISAMPLE_2_SAMPLES; i < D3DMULTISAMPLE_16_SAMPLES && - multisamplequality; ++i) { - if (d3d9_to_pipe_format_checked(screen, format, PIPE_TEXTURE_2D, - i, bind, FALSE, FALSE) != PIPE_FORMAT_NONE) { - multisamplequality--; - if (levels) - (*levels)++; - *multisample = i; - } - } - } - /* Make sure to get an exact match */ - if (multisamplequality) - return D3DERR_INVALIDCALL; - return D3D_OK; -} - -static inline const char * -d3dformat_to_string(D3DFORMAT fmt) -{ - switch (fmt) { - case D3DFMT_UNKNOWN: return "D3DFMT_UNKNOWN"; - case D3DFMT_R8G8B8: return "D3DFMT_R8G8B8"; - case D3DFMT_A8R8G8B8: return "D3DFMT_A8R8G8B8"; - case D3DFMT_X8R8G8B8: return "D3DFMT_X8R8G8B8"; - case D3DFMT_R5G6B5: return "D3DFMT_R5G6B5"; - case D3DFMT_X1R5G5B5: return "D3DFMT_X1R5G5B5"; - case D3DFMT_A1R5G5B5: return "D3DFMT_A1R5G5B5"; - case D3DFMT_A4R4G4B4: return "D3DFMT_A4R4G4B4"; - case D3DFMT_R3G3B2: return "D3DFMT_R3G3B2"; - case D3DFMT_A8: return "D3DFMT_A8"; - case D3DFMT_A8R3G3B2: return "D3DFMT_A8R3G3B2"; - case D3DFMT_X4R4G4B4: return "D3DFMT_X4R4G4B4"; - case D3DFMT_A2B10G10R10: return "D3DFMT_A2B10G10R10"; - case D3DFMT_A8B8G8R8: return "D3DFMT_A8B8G8R8"; - case D3DFMT_X8B8G8R8: return "D3DFMT_X8B8G8R8"; - case D3DFMT_G16R16: return "D3DFMT_G16R16"; - case D3DFMT_A2R10G10B10: return "D3DFMT_A2R10G10B10"; - case D3DFMT_A16B16G16R16: return "D3DFMT_A16B16G16R16"; - case D3DFMT_A8P8: return "D3DFMT_A8P8"; - case D3DFMT_P8: return "D3DFMT_P8"; - case D3DFMT_L8: return "D3DFMT_L8"; - case D3DFMT_A8L8: return "D3DFMT_A8L8"; - case D3DFMT_A4L4: return "D3DFMT_A4L4"; - case D3DFMT_V8U8: return "D3DFMT_V8U8"; - case D3DFMT_L6V5U5: return "D3DFMT_L6V5U5"; - case D3DFMT_X8L8V8U8: return "D3DFMT_X8L8V8U8"; - case D3DFMT_Q8W8V8U8: return "D3DFMT_Q8W8V8U8"; - case D3DFMT_V16U16: return "D3DFMT_V16U16"; - case D3DFMT_A2W10V10U10: return "D3DFMT_A2W10V10U10"; - case D3DFMT_UYVY: return "D3DFMT_UYVY"; - case D3DFMT_R8G8_B8G8: return "D3DFMT_R8G8_B8G8"; - case D3DFMT_YUY2: return "D3DFMT_YUY2"; - case D3DFMT_G8R8_G8B8: return "D3DFMT_G8R8_G8B8"; - case D3DFMT_DXT1: return "D3DFMT_DXT1"; - case D3DFMT_DXT2: return "D3DFMT_DXT2"; - case D3DFMT_DXT3: return "D3DFMT_DXT3"; - case D3DFMT_DXT4: return "D3DFMT_DXT4"; - case D3DFMT_DXT5: return "D3DFMT_DXT5"; - case D3DFMT_ATI1: return "D3DFMT_ATI1"; - case D3DFMT_ATI2: return "D3DFMT_ATI2"; - case D3DFMT_D16_LOCKABLE: return "D3DFMT_D16_LOCKABLE"; - case D3DFMT_D32: return "D3DFMT_D32"; - case D3DFMT_D15S1: return "D3DFMT_D15S1"; - case D3DFMT_D24S8: return "D3DFMT_D24S8"; - case D3DFMT_D24X8: return "D3DFMT_D24X8"; - case D3DFMT_D24X4S4: return "D3DFMT_D24X4S4"; - case D3DFMT_D16: return "D3DFMT_D16"; - case D3DFMT_D32F_LOCKABLE: return "D3DFMT_D32F_LOCKABLE"; - case D3DFMT_D24FS8: return "D3DFMT_D24FS8"; - case D3DFMT_D32_LOCKABLE: return "D3DFMT_D32_LOCKABLE"; - case D3DFMT_S8_LOCKABLE: return "D3DFMT_S8_LOCKABLE"; - case D3DFMT_L16: return "D3DFMT_L16"; - case D3DFMT_VERTEXDATA: return "D3DFMT_VERTEXDATA"; - case D3DFMT_INDEX16: return "D3DFMT_INDEX16"; - case D3DFMT_INDEX32: return "D3DFMT_INDEX32"; - case D3DFMT_Q16W16V16U16: return "D3DFMT_Q16W16V16U16"; - case D3DFMT_MULTI2_ARGB8: return "D3DFMT_MULTI2_ARGB8"; - case D3DFMT_R16F: return "D3DFMT_R16F"; - case D3DFMT_G16R16F: return "D3DFMT_G16R16F"; - case D3DFMT_A16B16G16R16F: return "D3DFMT_A16B16G16R16F"; - case D3DFMT_R32F: return "D3DFMT_R32F"; - case D3DFMT_G32R32F: return "D3DFMT_G32R32F"; - case D3DFMT_A32B32G32R32F: return "D3DFMT_A32B32G32R32F"; - case D3DFMT_CxV8U8: return "D3DFMT_CxV8U8"; - case D3DFMT_A1: return "D3DFMT_A1"; - case D3DFMT_A2B10G10R10_XR_BIAS: return "D3DFMT_A2B10G10R10_XR_BIAS"; - case D3DFMT_BINARYBUFFER: return "D3DFMT_BINARYBUFFER"; - case D3DFMT_DF16: return "D3DFMT_DF16"; - case D3DFMT_DF24: return "D3DFMT_DF24"; - case D3DFMT_INTZ: return "D3DFMT_INTZ"; - case D3DFMT_NVDB: return "D3DFMT_NVDB"; - case D3DFMT_RESZ: return "D3DFMT_RESZ"; - case D3DFMT_NULL: return "D3DFMT_NULL"; - case D3DFMT_ATOC: return "D3DFMT_ATOC"; - default: - break; - } - return "Unknown"; -} - -static inline unsigned -nine_fvf_stride( DWORD fvf ) -{ - unsigned texcount, i, size = 0; - - switch (fvf & D3DFVF_POSITION_MASK) { - case D3DFVF_XYZ: size += 3*4; break; - case D3DFVF_XYZRHW: size += 4*4; break; - case D3DFVF_XYZB1: size += 4*4; break; - case D3DFVF_XYZB2: size += 5*4; break; - case D3DFVF_XYZB3: size += 6*4; break; - case D3DFVF_XYZB4: size += 7*4; break; - case D3DFVF_XYZB5: size += 8*4; break; - case D3DFVF_XYZW: size += 4*4; break; - default: - user_warn("Position doesn't match any known combination."); - break; - } - - if (fvf & D3DFVF_NORMAL) { size += 3*4; } - if (fvf & D3DFVF_PSIZE) { size += 1*4; } - if (fvf & D3DFVF_DIFFUSE) { size += 1*4; } - if (fvf & D3DFVF_SPECULAR) { size += 1*4; } - - texcount = (fvf >> D3DFVF_TEXCOUNT_SHIFT) & D3DFVF_TEXCOUNT_MASK; - if (user_error(texcount <= 8)) - texcount = 8; - - for (i = 0; i < texcount; ++i) { - unsigned texformat = (fvf>>(16+i*2))&0x3; - /* texformats are defined having been shifted around so 1=3,2=0,3=1,4=2 - * meaning we can just do this instead of the switch below */ - size += (((texformat+1)&0x3)+1)*4; - - /* - switch (texformat) { - case D3DFVF_TEXTUREFORMAT1: size += 1*4; - case D3DFVF_TEXTUREFORMAT2: size += 2*4; - case D3DFVF_TEXTUREFORMAT3: size += 3*4; - case D3DFVF_TEXTUREFORMAT4: size += 4*4; - } - */ - } - - return size; -} - -static inline void -d3dcolor_to_rgba(float *rgba, D3DCOLOR color) -{ - rgba[0] = (float)((color >> 16) & 0xFF) / 0xFF; - rgba[1] = (float)((color >> 8) & 0xFF) / 0xFF; - rgba[2] = (float)((color >> 0) & 0xFF) / 0xFF; - rgba[3] = (float)((color >> 24) & 0xFF) / 0xFF; -} - -static inline void -d3dcolor_to_pipe_color_union(union pipe_color_union *rgba, D3DCOLOR color) -{ - d3dcolor_to_rgba(&rgba->f[0], color); -} - -static inline unsigned -d3dprimitivetype_to_pipe_prim(D3DPRIMITIVETYPE prim) -{ - switch (prim) { - case D3DPT_POINTLIST: return PIPE_PRIM_POINTS; - case D3DPT_LINELIST: return PIPE_PRIM_LINES; - case D3DPT_LINESTRIP: return PIPE_PRIM_LINE_STRIP; - case D3DPT_TRIANGLELIST: return PIPE_PRIM_TRIANGLES; - case D3DPT_TRIANGLESTRIP: return PIPE_PRIM_TRIANGLE_STRIP; - case D3DPT_TRIANGLEFAN: return PIPE_PRIM_TRIANGLE_FAN; - default: - assert(0); - return PIPE_PRIM_POINTS; - } -} - -static inline unsigned -prim_count_to_vertex_count(D3DPRIMITIVETYPE prim, UINT count) -{ - switch (prim) { - case D3DPT_POINTLIST: return count; - case D3DPT_LINELIST: return count * 2; - case D3DPT_LINESTRIP: return count + 1; - case D3DPT_TRIANGLELIST: return count * 3; - case D3DPT_TRIANGLESTRIP: return count + 2; - case D3DPT_TRIANGLEFAN: return count + 2; - default: - assert(0); - return 0; - } -} - -static inline unsigned -d3dcmpfunc_to_pipe_func(D3DCMPFUNC func) -{ - switch (func) { - case D3DCMP_NEVER: return PIPE_FUNC_NEVER; - case D3DCMP_LESS: return PIPE_FUNC_LESS; - case D3DCMP_EQUAL: return PIPE_FUNC_EQUAL; - case D3DCMP_LESSEQUAL: return PIPE_FUNC_LEQUAL; - case D3DCMP_GREATER: return PIPE_FUNC_GREATER; - case D3DCMP_NOTEQUAL: return PIPE_FUNC_NOTEQUAL; - case D3DCMP_GREATEREQUAL: return PIPE_FUNC_GEQUAL; - case D3DCMP_ALWAYS: return PIPE_FUNC_ALWAYS; - case D3DCMP_NEVER_ZERO: return PIPE_FUNC_NEVER; // Tested on windows + ATI HD5770 - default: - assert(0); - return PIPE_FUNC_NEVER; - } -} - -static inline unsigned -d3dstencilop_to_pipe_stencil_op(D3DSTENCILOP op) -{ - switch (op) { - case D3DSTENCILOP_KEEP: return PIPE_STENCIL_OP_KEEP; - case D3DSTENCILOP_ZERO: return PIPE_STENCIL_OP_ZERO; - case D3DSTENCILOP_REPLACE: return PIPE_STENCIL_OP_REPLACE; - case D3DSTENCILOP_INCRSAT: return PIPE_STENCIL_OP_INCR; - case D3DSTENCILOP_DECRSAT: return PIPE_STENCIL_OP_DECR; - case D3DSTENCILOP_INVERT: return PIPE_STENCIL_OP_INVERT; - case D3DSTENCILOP_INCR: return PIPE_STENCIL_OP_INCR_WRAP; - case D3DSTENCILOP_DECR: return PIPE_STENCIL_OP_DECR_WRAP; - default: - return PIPE_STENCIL_OP_ZERO; - } -} - -static inline unsigned -d3dcull_to_pipe_face(D3DCULL cull) -{ - switch (cull) { - case D3DCULL_NONE: return PIPE_FACE_NONE; - case D3DCULL_CW: return PIPE_FACE_FRONT; - case D3DCULL_CCW: return PIPE_FACE_BACK; - default: - assert(0); - return PIPE_FACE_NONE; - } -} - -static inline unsigned -d3dfillmode_to_pipe_polygon_mode(D3DFILLMODE mode) -{ - switch (mode) { - case D3DFILL_POINT: return PIPE_POLYGON_MODE_POINT; - case D3DFILL_WIREFRAME: return PIPE_POLYGON_MODE_LINE; - case D3DFILL_SOLID: return PIPE_POLYGON_MODE_FILL; - case D3DFILL_SOLID_ZERO:return PIPE_POLYGON_MODE_FILL; - default: - assert(0); - return PIPE_POLYGON_MODE_FILL; - } -} - -static inline unsigned -d3dblendop_to_pipe_blend(D3DBLENDOP op) -{ - switch (op) { - case D3DBLENDOP_ADD: return PIPE_BLEND_ADD; - case D3DBLENDOP_SUBTRACT: return PIPE_BLEND_SUBTRACT; - case D3DBLENDOP_REVSUBTRACT: return PIPE_BLEND_REVERSE_SUBTRACT; - case D3DBLENDOP_MIN: return PIPE_BLEND_MIN; - case D3DBLENDOP_MAX: return PIPE_BLEND_MAX; - default: - assert(0); - return PIPE_BLEND_ADD; - } -} - -/* NOTE: The COLOR factors for are equal to the ALPHA ones for alpha. - * Drivers may check RGB and ALPHA factors for equality so we should not - * simply substitute the ALPHA variants. - */ -static inline unsigned -d3dblend_alpha_to_pipe_blendfactor(D3DBLEND b) -{ - switch (b) { - case D3DBLEND_ZERO: return PIPE_BLENDFACTOR_ZERO; - case D3DBLEND_ONE: return PIPE_BLENDFACTOR_ONE; - case D3DBLEND_SRCCOLOR: return PIPE_BLENDFACTOR_SRC_COLOR/*ALPHA*/; - case D3DBLEND_INVSRCCOLOR: return PIPE_BLENDFACTOR_INV_SRC_COLOR/*ALPHA*/; - case D3DBLEND_SRCALPHA: return PIPE_BLENDFACTOR_SRC_ALPHA; - case D3DBLEND_INVSRCALPHA: return PIPE_BLENDFACTOR_INV_SRC_ALPHA; - case D3DBLEND_DESTALPHA: return PIPE_BLENDFACTOR_DST_ALPHA; - case D3DBLEND_INVDESTALPHA: return PIPE_BLENDFACTOR_INV_DST_ALPHA; - case D3DBLEND_DESTCOLOR: return PIPE_BLENDFACTOR_DST_COLOR/*ALPHA*/; - case D3DBLEND_INVDESTCOLOR: return PIPE_BLENDFACTOR_INV_DST_COLOR/*ALPHA*/; - case D3DBLEND_SRCALPHASAT: return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE; - case D3DBLEND_BOTHSRCALPHA: return PIPE_BLENDFACTOR_SRC_ALPHA; - case D3DBLEND_BOTHINVSRCALPHA: return PIPE_BLENDFACTOR_INV_SRC_ALPHA; - case D3DBLEND_BLENDFACTOR: return PIPE_BLENDFACTOR_CONST_COLOR/*ALPHA*/; - case D3DBLEND_INVBLENDFACTOR: return PIPE_BLENDFACTOR_INV_CONST_COLOR/*ALPHA*/; - case D3DBLEND_SRCCOLOR2: return PIPE_BLENDFACTOR_ONE; /* XXX */ - case D3DBLEND_INVSRCCOLOR2: return PIPE_BLENDFACTOR_ZERO; /* XXX */ - default: - DBG_FLAG(DBG_UNKNOWN, "Unhandled blend factor %d\n", b); - return PIPE_BLENDFACTOR_ZERO; - } -} - -static inline unsigned -d3dblend_color_to_pipe_blendfactor(D3DBLEND b) -{ - switch (b) { - case D3DBLEND_ZERO: return PIPE_BLENDFACTOR_ZERO; - case D3DBLEND_ONE: return PIPE_BLENDFACTOR_ONE; - case D3DBLEND_SRCCOLOR: return PIPE_BLENDFACTOR_SRC_COLOR; - case D3DBLEND_INVSRCCOLOR: return PIPE_BLENDFACTOR_INV_SRC_COLOR; - case D3DBLEND_SRCALPHA: return PIPE_BLENDFACTOR_SRC_ALPHA; - case D3DBLEND_INVSRCALPHA: return PIPE_BLENDFACTOR_INV_SRC_ALPHA; - case D3DBLEND_DESTALPHA: return PIPE_BLENDFACTOR_DST_ALPHA; - case D3DBLEND_INVDESTALPHA: return PIPE_BLENDFACTOR_INV_DST_ALPHA; - case D3DBLEND_DESTCOLOR: return PIPE_BLENDFACTOR_DST_COLOR; - case D3DBLEND_INVDESTCOLOR: return PIPE_BLENDFACTOR_INV_DST_COLOR; - case D3DBLEND_SRCALPHASAT: return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE; - case D3DBLEND_BOTHSRCALPHA: return PIPE_BLENDFACTOR_SRC_ALPHA; - case D3DBLEND_BOTHINVSRCALPHA: return PIPE_BLENDFACTOR_INV_SRC_ALPHA; - case D3DBLEND_BLENDFACTOR: return PIPE_BLENDFACTOR_CONST_COLOR; - case D3DBLEND_INVBLENDFACTOR: return PIPE_BLENDFACTOR_INV_CONST_COLOR; - case D3DBLEND_SRCCOLOR2: return PIPE_BLENDFACTOR_SRC1_COLOR; - case D3DBLEND_INVSRCCOLOR2: return PIPE_BLENDFACTOR_INV_SRC1_COLOR; - default: - DBG_FLAG(DBG_UNKNOWN, "Unhandled blend factor %d\n", b); - return PIPE_BLENDFACTOR_ZERO; - } -} - -static inline unsigned -d3dtextureaddress_to_pipe_tex_wrap(D3DTEXTUREADDRESS addr) -{ - switch (addr) { - case D3DTADDRESS_WRAP: return PIPE_TEX_WRAP_REPEAT; - case D3DTADDRESS_MIRROR: return PIPE_TEX_WRAP_MIRROR_REPEAT; - case D3DTADDRESS_CLAMP: return PIPE_TEX_WRAP_CLAMP_TO_EDGE; - case D3DTADDRESS_BORDER: return PIPE_TEX_WRAP_CLAMP_TO_BORDER; - case D3DTADDRESS_MIRRORONCE: return PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE; - default: - assert(0); - return PIPE_TEX_WRAP_CLAMP_TO_EDGE; - } -} - -static inline unsigned -d3dtexturefiltertype_to_pipe_tex_filter(D3DTEXTUREFILTERTYPE filter) -{ - switch (filter) { - case D3DTEXF_POINT: return PIPE_TEX_FILTER_NEAREST; - case D3DTEXF_LINEAR: return PIPE_TEX_FILTER_LINEAR; - case D3DTEXF_ANISOTROPIC: return PIPE_TEX_FILTER_LINEAR; - - case D3DTEXF_NONE: - case D3DTEXF_PYRAMIDALQUAD: - case D3DTEXF_GAUSSIANQUAD: - case D3DTEXF_CONVOLUTIONMONO: - default: - assert(0); - return PIPE_TEX_FILTER_NEAREST; - } -} - -static inline unsigned -d3dtexturefiltertype_to_pipe_tex_mipfilter(D3DTEXTUREFILTERTYPE filter) -{ - switch (filter) { - case D3DTEXF_NONE: return PIPE_TEX_MIPFILTER_NONE; - case D3DTEXF_POINT: return PIPE_TEX_FILTER_NEAREST; - case D3DTEXF_LINEAR: return PIPE_TEX_FILTER_LINEAR; - case D3DTEXF_ANISOTROPIC: return PIPE_TEX_FILTER_LINEAR; - - case D3DTEXF_PYRAMIDALQUAD: - case D3DTEXF_GAUSSIANQUAD: - case D3DTEXF_CONVOLUTIONMONO: - default: - assert(0); - return PIPE_TEX_MIPFILTER_NONE; - } -} - -static inline unsigned nine_format_get_stride(enum pipe_format format, - unsigned width) -{ - unsigned stride = util_format_get_stride(format, width); - - return align(stride, 4); -} - -static inline unsigned nine_format_get_level_alloc_size(enum pipe_format format, - unsigned width, - unsigned height, - unsigned level) -{ - unsigned w, h, size; - - w = u_minify(width, level); - h = u_minify(height, level); - if (is_ATI1_ATI2(format)) { - /* For "unknown" formats like ATIx use width * height bytes */ - size = w * h; - } else if (format == PIPE_FORMAT_NONE) { /* D3DFMT_NULL */ - size = w * h * 4; - } else { - size = nine_format_get_stride(format, w) * - util_format_get_nblocksy(format, h); - } - - return size; -} - -static inline unsigned nine_format_get_size_and_offsets(enum pipe_format format, - unsigned *offsets, - unsigned width, - unsigned height, - unsigned last_level) -{ - unsigned l, w, h, size = 0; - - for (l = 0; l <= last_level; ++l) { - w = u_minify(width, l); - h = u_minify(height, l); - offsets[l] = size; - if (is_ATI1_ATI2(format)) { - /* For "unknown" formats like ATIx use width * height bytes */ - size += w * h; - } else { - size += nine_format_get_stride(format, w) * - util_format_get_nblocksy(format, h); - } - } - - return size; -} - -#endif /* _NINE_PIPE_H_ */ diff --git a/src/gallium/state_trackers/nine/nine_queue.c b/src/gallium/state_trackers/nine/nine_queue.c deleted file mode 100644 index c09810b1a8a..00000000000 --- a/src/gallium/state_trackers/nine/nine_queue.c +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright 2016 Patrick Rudolph - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "nine_queue.h" -#include "os/os_thread.h" -#include "util/macros.h" -#include "nine_helpers.h" - -#define NINE_CMD_BUF_INSTR (256) - -#define NINE_CMD_BUFS (32) -#define NINE_CMD_BUFS_MASK (NINE_CMD_BUFS - 1) - -#define NINE_QUEUE_SIZE (8192 * 16 + 128) - -#define DBG_CHANNEL DBG_DEVICE - -/* - * Single producer - single consumer pool queue - * - * Producer: - * Calls nine_queue_alloc to get a slice of memory in current cmdbuf. - * Calls nine_queue_flush to flush the queue by request. - * The queue is flushed automatically on insufficient space or once the - * cmdbuf contains NINE_CMD_BUF_INSTR instructions. - * - * nine_queue_flush does block, while nine_queue_alloc doesn't block. - * - * nine_queue_alloc returns NULL on insufficent space. - * - * Consumer: - * Calls nine_queue_wait_flush to wait for a cmdbuf. - * After waiting for a cmdbuf it calls nine_queue_get until NULL is returned. - * - * nine_queue_wait_flush does block, while nine_queue_get doesn't block. - * - * Constrains: - * Only a single consumer and a single producer are supported. - * - */ - -struct nine_cmdbuf { - unsigned instr_size[NINE_CMD_BUF_INSTR]; - unsigned num_instr; - unsigned offset; - void *mem_pool; - BOOL full; -}; - -struct nine_queue_pool { - struct nine_cmdbuf pool[NINE_CMD_BUFS]; - unsigned head; - unsigned tail; - unsigned cur_instr; - BOOL worker_wait; - cnd_t event_pop; - cnd_t event_push; - mtx_t mutex_pop; - mtx_t mutex_push; -}; - -/* Consumer functions: */ -void -nine_queue_wait_flush(struct nine_queue_pool* ctx) -{ - struct nine_cmdbuf *cmdbuf = &ctx->pool[ctx->tail]; - - /* wait for cmdbuf full */ - mtx_lock(&ctx->mutex_push); - while (!cmdbuf->full) - { - DBG("waiting for full cmdbuf\n"); - cnd_wait(&ctx->event_push, &ctx->mutex_push); - } - DBG("got cmdbuf=%p\n", cmdbuf); - mtx_unlock(&ctx->mutex_push); - - cmdbuf->offset = 0; - ctx->cur_instr = 0; -} - -/* Gets a pointer to the next memory slice. - * Does not block. - * Returns NULL on empty cmdbuf. */ -void * -nine_queue_get(struct nine_queue_pool* ctx) -{ - struct nine_cmdbuf *cmdbuf = &ctx->pool[ctx->tail]; - unsigned offset; - - /* At this pointer there's always a cmdbuf. */ - - if (ctx->cur_instr == cmdbuf->num_instr) { - /* signal waiting producer */ - mtx_lock(&ctx->mutex_pop); - DBG("freeing cmdbuf=%p\n", cmdbuf); - cmdbuf->full = 0; - cnd_signal(&ctx->event_pop); - mtx_unlock(&ctx->mutex_pop); - - ctx->tail = (ctx->tail + 1) & NINE_CMD_BUFS_MASK; - - return NULL; - } - - /* At this pointer there's always a cmdbuf with instruction to process. */ - offset = cmdbuf->offset; - cmdbuf->offset += cmdbuf->instr_size[ctx->cur_instr]; - ctx->cur_instr ++; - - return cmdbuf->mem_pool + offset; -} - -/* Producer functions: */ - -/* Flushes the queue. - * Moves the current cmdbuf to worker thread. - * Blocks until next cmdbuf is free. */ -void -nine_queue_flush(struct nine_queue_pool* ctx) -{ - struct nine_cmdbuf *cmdbuf = &ctx->pool[ctx->head]; - - DBG("flushing cmdbuf=%p instr=%d size=%d\n", - cmdbuf, cmdbuf->num_instr, cmdbuf->offset); - - /* Nothing to flush */ - if (!cmdbuf->num_instr) - return; - - /* signal waiting worker */ - mtx_lock(&ctx->mutex_push); - cmdbuf->full = 1; - cnd_signal(&ctx->event_push); - mtx_unlock(&ctx->mutex_push); - - ctx->head = (ctx->head + 1) & NINE_CMD_BUFS_MASK; - - cmdbuf = &ctx->pool[ctx->head]; - - /* wait for queue empty */ - mtx_lock(&ctx->mutex_pop); - while (cmdbuf->full) - { - DBG("waiting for empty cmdbuf\n"); - cnd_wait(&ctx->event_pop, &ctx->mutex_pop); - } - DBG("got empty cmdbuf=%p\n", cmdbuf); - mtx_unlock(&ctx->mutex_pop); - cmdbuf->offset = 0; - cmdbuf->num_instr = 0; -} - -/* Gets a a pointer to slice of memory with size @space. - * Does block if queue is full. - * Returns NULL on @space > NINE_QUEUE_SIZE. */ -void * -nine_queue_alloc(struct nine_queue_pool* ctx, unsigned space) -{ - unsigned offset; - struct nine_cmdbuf *cmdbuf = &ctx->pool[ctx->head]; - - if (space > NINE_QUEUE_SIZE) - return NULL; - - /* at this pointer there's always a free queue available */ - - if ((cmdbuf->offset + space > NINE_QUEUE_SIZE) || - (cmdbuf->num_instr == NINE_CMD_BUF_INSTR)) { - - nine_queue_flush(ctx); - - cmdbuf = &ctx->pool[ctx->head]; - } - - DBG("cmdbuf=%p space=%d\n", cmdbuf, space); - - /* at this pointer there's always a free queue with sufficient space available */ - - offset = cmdbuf->offset; - cmdbuf->offset += space; - cmdbuf->instr_size[cmdbuf->num_instr] = space; - cmdbuf->num_instr ++; - - return cmdbuf->mem_pool + offset; -} - -/* Returns the current queue flush state. - * TRUE nothing flushed - * FALSE one ore more instructions queued flushed. */ -bool -nine_queue_no_flushed_work(struct nine_queue_pool* ctx) -{ - return (ctx->tail == ctx->head); -} - -/* Returns the current queue empty state. - * TRUE no instructions queued. - * FALSE one ore more instructions queued. */ -bool -nine_queue_isempty(struct nine_queue_pool* ctx) -{ - struct nine_cmdbuf *cmdbuf = &ctx->pool[ctx->head]; - - return (ctx->tail == ctx->head) && !cmdbuf->num_instr; -} - -struct nine_queue_pool* -nine_queue_create(void) -{ - unsigned i; - struct nine_queue_pool *ctx; - - ctx = CALLOC_STRUCT(nine_queue_pool); - if (!ctx) - goto failed; - - for (i = 0; i < NINE_CMD_BUFS; i++) { - ctx->pool[i].mem_pool = MALLOC(NINE_QUEUE_SIZE); - if (!ctx->pool[i].mem_pool) - goto failed; - } - - cnd_init(&ctx->event_pop); - (void) mtx_init(&ctx->mutex_pop, mtx_plain); - - cnd_init(&ctx->event_push); - (void) mtx_init(&ctx->mutex_push, mtx_plain); - - /* Block until first cmdbuf has been flushed. */ - ctx->worker_wait = TRUE; - - return ctx; -failed: - if (ctx) { - for (i = 0; i < NINE_CMD_BUFS; i++) { - if (ctx->pool[i].mem_pool) - FREE(ctx->pool[i].mem_pool); - } - FREE(ctx); - } - return NULL; -} - -void -nine_queue_delete(struct nine_queue_pool *ctx) -{ - unsigned i; - - mtx_destroy(&ctx->mutex_pop); - cnd_destroy(&ctx->event_pop); - - mtx_destroy(&ctx->mutex_push); - cnd_destroy(&ctx->event_push); - - for (i = 0; i < NINE_CMD_BUFS; i++) - FREE(ctx->pool[i].mem_pool); - - FREE(ctx); -} diff --git a/src/gallium/state_trackers/nine/nine_queue.h b/src/gallium/state_trackers/nine/nine_queue.h deleted file mode 100644 index 52f6cbdfa87..00000000000 --- a/src/gallium/state_trackers/nine/nine_queue.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2016 Patrick Rudolph - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef _NINE_QUEUE_H_ -#define _NINE_QUEUE_H_ - -#include "pipe/p_compiler.h" - -struct nine_queue_pool; - -void -nine_queue_wait_flush(struct nine_queue_pool* ctx); - -void * -nine_queue_get(struct nine_queue_pool* ctx); - -void -nine_queue_flush(struct nine_queue_pool* ctx); - -void * -nine_queue_alloc(struct nine_queue_pool* ctx, unsigned space); - -bool -nine_queue_no_flushed_work(struct nine_queue_pool* ctx); - -bool -nine_queue_isempty(struct nine_queue_pool* ctx); - -struct nine_queue_pool* -nine_queue_create(void); - -void -nine_queue_delete(struct nine_queue_pool *ctx); - -#endif /* _NINE_QUEUE_H_ */ diff --git a/src/gallium/state_trackers/nine/nine_quirk.c b/src/gallium/state_trackers/nine/nine_quirk.c deleted file mode 100644 index 267436b14de..00000000000 --- a/src/gallium/state_trackers/nine/nine_quirk.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "nine_quirk.h" - -#include "util/u_debug.h" - -static const struct debug_named_value nine_quirk_table[] = { - { "fakecaps", QUIRK_FAKE_CAPS, - "Fake caps to emulate D3D specs regardless of hardware caps." }, - { "lenientshader", QUIRK_LENIENT_SHADER, - "Be lenient when translating shaders." }, - { "all", ~0U, - "Enable all quirks." }, - DEBUG_NAMED_VALUE_END -}; - -boolean -_nine_get_quirk( unsigned quirk ) -{ - static boolean first = TRUE; - static unsigned long flags = 0; - - if (first) { - first = FALSE; - flags = debug_get_flags_option("NINE_QUIRKS", nine_quirk_table, 0); - } - - return !!(flags & quirk); -} diff --git a/src/gallium/state_trackers/nine/nine_quirk.h b/src/gallium/state_trackers/nine/nine_quirk.h deleted file mode 100644 index 9c082dd9f93..00000000000 --- a/src/gallium/state_trackers/nine/nine_quirk.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef _NINE_QUIRK_H_ -#define _NINE_QUIRK_H_ - -#include "pipe/p_compiler.h" - -boolean -_nine_get_quirk( unsigned quirk ); - -#define QUIRK(q) (_nine_get_quirk(QUIRK_##q)) - -#define QUIRK_FAKE_CAPS 0x00000001 -#define QUIRK_LENIENT_SHADER 0x00000002 - -#endif /* _NINE_QUIRK_H_ */ diff --git a/src/gallium/state_trackers/nine/nine_shader.c b/src/gallium/state_trackers/nine/nine_shader.c deleted file mode 100644 index 195a1fe5f59..00000000000 --- a/src/gallium/state_trackers/nine/nine_shader.c +++ /dev/null @@ -1,4140 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * Copyright 2013 Christoph Bumiller - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "nine_shader.h" - -#include "device9.h" -#include "nine_debug.h" -#include "nine_state.h" -#include "vertexdeclaration9.h" - -#include "util/macros.h" -#include "util/u_memory.h" -#include "util/u_inlines.h" -#include "pipe/p_shader_tokens.h" -#include "tgsi/tgsi_ureg.h" -#include "tgsi/tgsi_dump.h" -#include "nir/tgsi_to_nir.h" - -#define DBG_CHANNEL DBG_SHADER - -#define DUMP(args...) _nine_debug_printf(DBG_CHANNEL, NULL, args) - - -struct shader_translator; - -typedef HRESULT (*translate_instruction_func)(struct shader_translator *); - -static inline const char *d3dsio_to_string(unsigned opcode); - - -#define NINED3D_SM1_VS 0xfffe -#define NINED3D_SM1_PS 0xffff - -#define NINE_MAX_COND_DEPTH 64 -#define NINE_MAX_LOOP_DEPTH 64 - -#define NINED3DSP_END 0x0000ffff - -#define NINED3DSPTYPE_FLOAT4 0 -#define NINED3DSPTYPE_INT4 1 -#define NINED3DSPTYPE_BOOL 2 - -#define NINED3DSPR_IMMEDIATE (D3DSPR_PREDICATE + 1) - -#define NINED3DSP_WRITEMASK_MASK D3DSP_WRITEMASK_ALL -#define NINED3DSP_WRITEMASK_SHIFT 16 - -#define NINED3DSHADER_INST_PREDICATED (1 << 28) - -#define NINED3DSHADER_REL_OP_GT 1 -#define NINED3DSHADER_REL_OP_EQ 2 -#define NINED3DSHADER_REL_OP_GE 3 -#define NINED3DSHADER_REL_OP_LT 4 -#define NINED3DSHADER_REL_OP_NE 5 -#define NINED3DSHADER_REL_OP_LE 6 - -#define NINED3DSIO_OPCODE_FLAGS_SHIFT 16 -#define NINED3DSIO_OPCODE_FLAGS_MASK (0xff << NINED3DSIO_OPCODE_FLAGS_SHIFT) - -#define NINED3DSI_TEXLD_PROJECT 0x1 -#define NINED3DSI_TEXLD_BIAS 0x2 - -#define NINED3DSP_WRITEMASK_0 0x1 -#define NINED3DSP_WRITEMASK_1 0x2 -#define NINED3DSP_WRITEMASK_2 0x4 -#define NINED3DSP_WRITEMASK_3 0x8 -#define NINED3DSP_WRITEMASK_ALL 0xf - -#define NINED3DSP_NOSWIZZLE ((0 << 0) | (1 << 2) | (2 << 4) | (3 << 6)) - -#define NINE_SWIZZLE4(x,y,z,w) \ - TGSI_SWIZZLE_##x, TGSI_SWIZZLE_##y, TGSI_SWIZZLE_##z, TGSI_SWIZZLE_##w - -#define NINE_APPLY_SWIZZLE(src, s) \ - ureg_swizzle(src, NINE_SWIZZLE4(s, s, s, s)) - -#define NINED3DSPDM_SATURATE (D3DSPDM_SATURATE >> D3DSP_DSTMOD_SHIFT) -#define NINED3DSPDM_PARTIALP (D3DSPDM_PARTIALPRECISION >> D3DSP_DSTMOD_SHIFT) -#define NINED3DSPDM_CENTROID (D3DSPDM_MSAMPCENTROID >> D3DSP_DSTMOD_SHIFT) - -/* - * NEG all, not ps: m3x2, m3x3, m3x4, m4x3, m4x4 - * BIAS <= PS 1.4 (x-0.5) - * BIASNEG <= PS 1.4 (-(x-0.5)) - * SIGN <= PS 1.4 (2(x-0.5)) - * SIGNNEG <= PS 1.4 (-2(x-0.5)) - * COMP <= PS 1.4 (1-x) - * X2 = PS 1.4 (2x) - * X2NEG = PS 1.4 (-2x) - * DZ <= PS 1.4, tex{ld,crd} (.xy/.z), z=0 => .11 - * DW <= PS 1.4, tex{ld,crd} (.xy/.w), w=0 => .11 - * ABS >= SM 3.0 (abs(x)) - * ABSNEG >= SM 3.0 (-abs(x)) - * NOT >= SM 2.0 pedication only - */ -#define NINED3DSPSM_NONE (D3DSPSM_NONE >> D3DSP_SRCMOD_SHIFT) -#define NINED3DSPSM_NEG (D3DSPSM_NEG >> D3DSP_SRCMOD_SHIFT) -#define NINED3DSPSM_BIAS (D3DSPSM_BIAS >> D3DSP_SRCMOD_SHIFT) -#define NINED3DSPSM_BIASNEG (D3DSPSM_BIASNEG >> D3DSP_SRCMOD_SHIFT) -#define NINED3DSPSM_SIGN (D3DSPSM_SIGN >> D3DSP_SRCMOD_SHIFT) -#define NINED3DSPSM_SIGNNEG (D3DSPSM_SIGNNEG >> D3DSP_SRCMOD_SHIFT) -#define NINED3DSPSM_COMP (D3DSPSM_COMP >> D3DSP_SRCMOD_SHIFT) -#define NINED3DSPSM_X2 (D3DSPSM_X2 >> D3DSP_SRCMOD_SHIFT) -#define NINED3DSPSM_X2NEG (D3DSPSM_X2NEG >> D3DSP_SRCMOD_SHIFT) -#define NINED3DSPSM_DZ (D3DSPSM_DZ >> D3DSP_SRCMOD_SHIFT) -#define NINED3DSPSM_DW (D3DSPSM_DW >> D3DSP_SRCMOD_SHIFT) -#define NINED3DSPSM_ABS (D3DSPSM_ABS >> D3DSP_SRCMOD_SHIFT) -#define NINED3DSPSM_ABSNEG (D3DSPSM_ABSNEG >> D3DSP_SRCMOD_SHIFT) -#define NINED3DSPSM_NOT (D3DSPSM_NOT >> D3DSP_SRCMOD_SHIFT) - -static const char *sm1_mod_str[] = -{ - [NINED3DSPSM_NONE] = "", - [NINED3DSPSM_NEG] = "-", - [NINED3DSPSM_BIAS] = "bias", - [NINED3DSPSM_BIASNEG] = "biasneg", - [NINED3DSPSM_SIGN] = "sign", - [NINED3DSPSM_SIGNNEG] = "signneg", - [NINED3DSPSM_COMP] = "comp", - [NINED3DSPSM_X2] = "x2", - [NINED3DSPSM_X2NEG] = "x2neg", - [NINED3DSPSM_DZ] = "dz", - [NINED3DSPSM_DW] = "dw", - [NINED3DSPSM_ABS] = "abs", - [NINED3DSPSM_ABSNEG] = "-abs", - [NINED3DSPSM_NOT] = "not" -}; - -static void -sm1_dump_writemask(BYTE mask) -{ - if (mask & 1) DUMP("x"); else DUMP("_"); - if (mask & 2) DUMP("y"); else DUMP("_"); - if (mask & 4) DUMP("z"); else DUMP("_"); - if (mask & 8) DUMP("w"); else DUMP("_"); -} - -static void -sm1_dump_swizzle(BYTE s) -{ - char c[4] = { 'x', 'y', 'z', 'w' }; - DUMP("%c%c%c%c", - c[(s >> 0) & 3], c[(s >> 2) & 3], c[(s >> 4) & 3], c[(s >> 6) & 3]); -} - -static const char sm1_file_char[] = -{ - [D3DSPR_TEMP] = 'r', - [D3DSPR_INPUT] = 'v', - [D3DSPR_CONST] = 'c', - [D3DSPR_ADDR] = 'A', - [D3DSPR_RASTOUT] = 'R', - [D3DSPR_ATTROUT] = 'D', - [D3DSPR_OUTPUT] = 'o', - [D3DSPR_CONSTINT] = 'I', - [D3DSPR_COLOROUT] = 'C', - [D3DSPR_DEPTHOUT] = 'D', - [D3DSPR_SAMPLER] = 's', - [D3DSPR_CONST2] = 'c', - [D3DSPR_CONST3] = 'c', - [D3DSPR_CONST4] = 'c', - [D3DSPR_CONSTBOOL] = 'B', - [D3DSPR_LOOP] = 'L', - [D3DSPR_TEMPFLOAT16] = 'h', - [D3DSPR_MISCTYPE] = 'M', - [D3DSPR_LABEL] = 'X', - [D3DSPR_PREDICATE] = 'p' -}; - -static void -sm1_dump_reg(BYTE file, INT index) -{ - switch (file) { - case D3DSPR_LOOP: - DUMP("aL"); - break; - case D3DSPR_COLOROUT: - DUMP("oC%i", index); - break; - case D3DSPR_DEPTHOUT: - DUMP("oDepth"); - break; - case D3DSPR_RASTOUT: - DUMP("oRast%i", index); - break; - case D3DSPR_CONSTINT: - DUMP("iconst[%i]", index); - break; - case D3DSPR_CONSTBOOL: - DUMP("bconst[%i]", index); - break; - default: - DUMP("%c%i", sm1_file_char[file], index); - break; - } -} - -struct sm1_src_param -{ - INT idx; - struct sm1_src_param *rel; - BYTE file; - BYTE swizzle; - BYTE mod; - BYTE type; - union { - DWORD d[4]; - float f[4]; - int i[4]; - BOOL b; - } imm; -}; -static void -sm1_parse_immediate(struct shader_translator *, struct sm1_src_param *); - -struct sm1_dst_param -{ - INT idx; - struct sm1_src_param *rel; - BYTE file; - BYTE mask; - BYTE mod; - int8_t shift; /* sint4 */ - BYTE type; -}; - -static inline void -assert_replicate_swizzle(const struct ureg_src *reg) -{ - assert(reg->SwizzleY == reg->SwizzleX && - reg->SwizzleZ == reg->SwizzleX && - reg->SwizzleW == reg->SwizzleX); -} - -static void -sm1_dump_immediate(const struct sm1_src_param *param) -{ - switch (param->type) { - case NINED3DSPTYPE_FLOAT4: - DUMP("{ %f %f %f %f }", - param->imm.f[0], param->imm.f[1], - param->imm.f[2], param->imm.f[3]); - break; - case NINED3DSPTYPE_INT4: - DUMP("{ %i %i %i %i }", - param->imm.i[0], param->imm.i[1], - param->imm.i[2], param->imm.i[3]); - break; - case NINED3DSPTYPE_BOOL: - DUMP("%s", param->imm.b ? "TRUE" : "FALSE"); - break; - default: - assert(0); - break; - } -} - -static void -sm1_dump_src_param(const struct sm1_src_param *param) -{ - if (param->file == NINED3DSPR_IMMEDIATE) { - assert(!param->mod && - !param->rel && - param->swizzle == NINED3DSP_NOSWIZZLE); - sm1_dump_immediate(param); - return; - } - - if (param->mod) - DUMP("%s(", sm1_mod_str[param->mod]); - if (param->rel) { - DUMP("%c[", sm1_file_char[param->file]); - sm1_dump_src_param(param->rel); - DUMP("+%i]", param->idx); - } else { - sm1_dump_reg(param->file, param->idx); - } - if (param->mod) - DUMP(")"); - if (param->swizzle != NINED3DSP_NOSWIZZLE) { - DUMP("."); - sm1_dump_swizzle(param->swizzle); - } -} - -static void -sm1_dump_dst_param(const struct sm1_dst_param *param) -{ - if (param->mod & NINED3DSPDM_SATURATE) - DUMP("sat "); - if (param->mod & NINED3DSPDM_PARTIALP) - DUMP("pp "); - if (param->mod & NINED3DSPDM_CENTROID) - DUMP("centroid "); - if (param->shift < 0) - DUMP("/%u ", 1 << -param->shift); - if (param->shift > 0) - DUMP("*%u ", 1 << param->shift); - - if (param->rel) { - DUMP("%c[", sm1_file_char[param->file]); - sm1_dump_src_param(param->rel); - DUMP("+%i]", param->idx); - } else { - sm1_dump_reg(param->file, param->idx); - } - if (param->mask != NINED3DSP_WRITEMASK_ALL) { - DUMP("."); - sm1_dump_writemask(param->mask); - } -} - -struct sm1_semantic -{ - struct sm1_dst_param reg; - BYTE sampler_type; - D3DDECLUSAGE usage; - BYTE usage_idx; -}; - -struct sm1_op_info -{ - /* NOTE: 0 is a valid TGSI opcode, but if handler is set, this parameter - * should be ignored completely */ - unsigned sio; - unsigned opcode; /* TGSI_OPCODE_x */ - - /* versions are still set even handler is set */ - struct { - unsigned min; - unsigned max; - } vert_version, frag_version; - - /* number of regs parsed outside of special handler */ - unsigned ndst; - unsigned nsrc; - - /* some instructions don't map perfectly, so use a special handler */ - translate_instruction_func handler; -}; - -struct sm1_instruction -{ - D3DSHADER_INSTRUCTION_OPCODE_TYPE opcode; - BYTE flags; - BOOL coissue; - BOOL predicated; - BYTE ndst; - BYTE nsrc; - struct sm1_src_param src[4]; - struct sm1_src_param src_rel[4]; - struct sm1_src_param pred; - struct sm1_src_param dst_rel[1]; - struct sm1_dst_param dst[1]; - - const struct sm1_op_info *info; -}; - -static void -sm1_dump_instruction(struct sm1_instruction *insn, unsigned indent) -{ - unsigned i; - - /* no info stored for these: */ - if (insn->opcode == D3DSIO_DCL) - return; - for (i = 0; i < indent; ++i) - DUMP(" "); - - if (insn->predicated) { - DUMP("@"); - sm1_dump_src_param(&insn->pred); - DUMP(" "); - } - DUMP("%s", d3dsio_to_string(insn->opcode)); - if (insn->flags) { - switch (insn->opcode) { - case D3DSIO_TEX: - DUMP(insn->flags == NINED3DSI_TEXLD_PROJECT ? "p" : "b"); - break; - default: - DUMP("_%x", insn->flags); - break; - } - } - if (insn->coissue) - DUMP("_co"); - DUMP(" "); - - for (i = 0; i < insn->ndst && i < ARRAY_SIZE(insn->dst); ++i) { - sm1_dump_dst_param(&insn->dst[i]); - DUMP(" "); - } - - for (i = 0; i < insn->nsrc && i < ARRAY_SIZE(insn->src); ++i) { - sm1_dump_src_param(&insn->src[i]); - DUMP(" "); - } - if (insn->opcode == D3DSIO_DEF || - insn->opcode == D3DSIO_DEFI || - insn->opcode == D3DSIO_DEFB) - sm1_dump_immediate(&insn->src[0]); - - DUMP("\n"); -} - -struct sm1_local_const -{ - INT idx; - struct ureg_src reg; - float f[4]; /* for indirect addressing of float constants */ -}; - -struct shader_translator -{ - const DWORD *byte_code; - const DWORD *parse; - const DWORD *parse_next; - - struct ureg_program *ureg; - - /* shader version */ - struct { - BYTE major; - BYTE minor; - } version; - unsigned processor; /* PIPE_SHADER_VERTEX/FRAMGENT */ - unsigned num_constf_allowed; - unsigned num_consti_allowed; - unsigned num_constb_allowed; - - boolean native_integers; - boolean inline_subroutines; - boolean want_texcoord; - boolean shift_wpos; - boolean wpos_is_sysval; - boolean face_is_sysval_integer; - boolean mul_zero_wins; - unsigned texcoord_sn; - - struct sm1_instruction insn; /* current instruction */ - - struct { - struct ureg_dst *r; - struct ureg_dst oPos; - struct ureg_dst oPos_out; /* the real output when doing streamout */ - struct ureg_dst oFog; - struct ureg_dst oPts; - struct ureg_dst oCol[4]; - struct ureg_dst o[PIPE_MAX_SHADER_OUTPUTS]; - struct ureg_dst oDepth; - struct ureg_src v[PIPE_MAX_SHADER_INPUTS]; - struct ureg_src v_consecutive; /* copy in temp array of ps inputs for rel addressing */ - struct ureg_src vPos; - struct ureg_src vFace; - struct ureg_src s; - struct ureg_dst p; - struct ureg_dst address; - struct ureg_dst a0; - struct ureg_dst predicate; - struct ureg_dst predicate_tmp; - struct ureg_dst predicate_dst; - struct ureg_dst tS[8]; /* texture stage registers */ - struct ureg_dst tdst; /* scratch dst if we need extra modifiers */ - struct ureg_dst t[8]; /* scratch TEMPs */ - struct ureg_src vC[2]; /* PS color in */ - struct ureg_src vT[8]; /* PS texcoord in */ - struct ureg_dst rL[NINE_MAX_LOOP_DEPTH]; /* loop ctr */ - } regs; - unsigned num_temp; /* ARRAY_SIZE(regs.r) */ - unsigned num_scratch; - unsigned loop_depth; - unsigned loop_depth_max; - unsigned cond_depth; - unsigned loop_labels[NINE_MAX_LOOP_DEPTH]; - unsigned cond_labels[NINE_MAX_COND_DEPTH]; - boolean loop_or_rep[NINE_MAX_LOOP_DEPTH]; /* true: loop, false: rep */ - boolean predicated_activated; - - unsigned *inst_labels; /* LABEL op */ - unsigned num_inst_labels; - - unsigned sampler_targets[NINE_MAX_SAMPLERS]; /* TGSI_TEXTURE_x */ - - struct sm1_local_const *lconstf; - unsigned num_lconstf; - struct sm1_local_const *lconsti; - unsigned num_lconsti; - struct sm1_local_const *lconstb; - unsigned num_lconstb; - - boolean slots_used[NINE_MAX_CONST_ALL]; - unsigned *slot_map; - unsigned num_slots; - - boolean indirect_const_access; - boolean failure; - - struct nine_vs_output_info output_info[16]; - int num_outputs; - - struct nine_shader_info *info; - - int16_t op_info_map[D3DSIO_BREAKP + 1]; -}; - -#define IS_VS (tx->processor == PIPE_SHADER_VERTEX) -#define IS_PS (tx->processor == PIPE_SHADER_FRAGMENT) - -#define FAILURE_VOID(cond) if ((cond)) {tx->failure=1;return;} - -static void -sm1_read_semantic(struct shader_translator *, struct sm1_semantic *); - -static void -sm1_instruction_check(const struct sm1_instruction *insn) -{ - if (insn->opcode == D3DSIO_CRS) - { - if (insn->dst[0].mask & NINED3DSP_WRITEMASK_3) - { - DBG("CRS.mask.w\n"); - } - } -} - -static void -nine_record_outputs(struct shader_translator *tx, BYTE Usage, BYTE UsageIndex, - int mask, int output_index) -{ - tx->output_info[tx->num_outputs].output_semantic = Usage; - tx->output_info[tx->num_outputs].output_semantic_index = UsageIndex; - tx->output_info[tx->num_outputs].mask = mask; - tx->output_info[tx->num_outputs].output_index = output_index; - tx->num_outputs++; -} - -static struct ureg_src nine_float_constant_src(struct shader_translator *tx, int idx) -{ - struct ureg_src src; - - if (tx->slot_map) - idx = tx->slot_map[idx]; - /* vswp constant handling: we use two buffers - * to fit all the float constants. The special handling - * doesn't need to be elsewhere, because all the instructions - * accessing the constants directly are VS1, and swvp - * is VS >= 2 */ - if (tx->info->swvp_on && idx >= 4096) { - /* TODO: swvp rel is broken if many constants are used */ - src = ureg_src_register(TGSI_FILE_CONSTANT, idx - 4096); - src = ureg_src_dimension(src, 1); - } else { - src = ureg_src_register(TGSI_FILE_CONSTANT, idx); - src = ureg_src_dimension(src, 0); - } - - if (!tx->info->swvp_on) - tx->slots_used[idx] = TRUE; - if (tx->info->const_float_slots < (idx + 1)) - tx->info->const_float_slots = idx + 1; - if (tx->num_slots < (idx + 1)) - tx->num_slots = idx + 1; - - return src; -} - -static struct ureg_src nine_integer_constant_src(struct shader_translator *tx, int idx) -{ - struct ureg_src src; - - if (tx->info->swvp_on) { - src = ureg_src_register(TGSI_FILE_CONSTANT, idx); - src = ureg_src_dimension(src, 2); - } else { - unsigned slot_idx = tx->info->const_i_base + idx; - if (tx->slot_map) - slot_idx = tx->slot_map[slot_idx]; - src = ureg_src_register(TGSI_FILE_CONSTANT, slot_idx); - src = ureg_src_dimension(src, 0); - tx->slots_used[slot_idx] = TRUE; - tx->info->int_slots_used[idx] = TRUE; - if (tx->num_slots < (slot_idx + 1)) - tx->num_slots = slot_idx + 1; - } - - if (tx->info->const_int_slots < (idx + 1)) - tx->info->const_int_slots = idx + 1; - - return src; -} - -static struct ureg_src nine_boolean_constant_src(struct shader_translator *tx, int idx) -{ - struct ureg_src src; - - char r = idx / 4; - char s = idx & 3; - - if (tx->info->swvp_on) { - src = ureg_src_register(TGSI_FILE_CONSTANT, r); - src = ureg_src_dimension(src, 3); - } else { - unsigned slot_idx = tx->info->const_b_base + r; - if (tx->slot_map) - slot_idx = tx->slot_map[slot_idx]; - src = ureg_src_register(TGSI_FILE_CONSTANT, slot_idx); - src = ureg_src_dimension(src, 0); - tx->slots_used[slot_idx] = TRUE; - tx->info->bool_slots_used[idx] = TRUE; - if (tx->num_slots < (slot_idx + 1)) - tx->num_slots = slot_idx + 1; - } - src = ureg_swizzle(src, s, s, s, s); - - if (tx->info->const_bool_slots < (idx + 1)) - tx->info->const_bool_slots = idx + 1; - - return src; -} - -static boolean -tx_lconstf(struct shader_translator *tx, struct ureg_src *src, INT index) -{ - INT i; - - if (index < 0 || index >= tx->num_constf_allowed) { - tx->failure = TRUE; - return FALSE; - } - for (i = 0; i < tx->num_lconstf; ++i) { - if (tx->lconstf[i].idx == index) { - *src = tx->lconstf[i].reg; - return TRUE; - } - } - return FALSE; -} -static boolean -tx_lconsti(struct shader_translator *tx, struct ureg_src *src, INT index) -{ - int i; - - if (index < 0 || index >= tx->num_consti_allowed) { - tx->failure = TRUE; - return FALSE; - } - for (i = 0; i < tx->num_lconsti; ++i) { - if (tx->lconsti[i].idx == index) { - *src = tx->lconsti[i].reg; - return TRUE; - } - } - return FALSE; -} -static boolean -tx_lconstb(struct shader_translator *tx, struct ureg_src *src, INT index) -{ - int i; - - if (index < 0 || index >= tx->num_constb_allowed) { - tx->failure = TRUE; - return FALSE; - } - for (i = 0; i < tx->num_lconstb; ++i) { - if (tx->lconstb[i].idx == index) { - *src = tx->lconstb[i].reg; - return TRUE; - } - } - return FALSE; -} - -static void -tx_set_lconstf(struct shader_translator *tx, INT index, float f[4]) -{ - unsigned n; - - FAILURE_VOID(index < 0 || index >= tx->num_constf_allowed) - - for (n = 0; n < tx->num_lconstf; ++n) - if (tx->lconstf[n].idx == index) - break; - if (n == tx->num_lconstf) { - if ((n % 8) == 0) { - tx->lconstf = REALLOC(tx->lconstf, - (n + 0) * sizeof(tx->lconstf[0]), - (n + 8) * sizeof(tx->lconstf[0])); - assert(tx->lconstf); - } - tx->num_lconstf++; - } - tx->lconstf[n].idx = index; - tx->lconstf[n].reg = ureg_imm4f(tx->ureg, f[0], f[1], f[2], f[3]); - - memcpy(tx->lconstf[n].f, f, sizeof(tx->lconstf[n].f)); -} -static void -tx_set_lconsti(struct shader_translator *tx, INT index, int i[4]) -{ - unsigned n; - - FAILURE_VOID(index < 0 || index >= tx->num_consti_allowed) - - for (n = 0; n < tx->num_lconsti; ++n) - if (tx->lconsti[n].idx == index) - break; - if (n == tx->num_lconsti) { - if ((n % 8) == 0) { - tx->lconsti = REALLOC(tx->lconsti, - (n + 0) * sizeof(tx->lconsti[0]), - (n + 8) * sizeof(tx->lconsti[0])); - assert(tx->lconsti); - } - tx->num_lconsti++; - } - - tx->lconsti[n].idx = index; - tx->lconsti[n].reg = tx->native_integers ? - ureg_imm4i(tx->ureg, i[0], i[1], i[2], i[3]) : - ureg_imm4f(tx->ureg, i[0], i[1], i[2], i[3]); -} -static void -tx_set_lconstb(struct shader_translator *tx, INT index, BOOL b) -{ - unsigned n; - - FAILURE_VOID(index < 0 || index >= tx->num_constb_allowed) - - for (n = 0; n < tx->num_lconstb; ++n) - if (tx->lconstb[n].idx == index) - break; - if (n == tx->num_lconstb) { - if ((n % 8) == 0) { - tx->lconstb = REALLOC(tx->lconstb, - (n + 0) * sizeof(tx->lconstb[0]), - (n + 8) * sizeof(tx->lconstb[0])); - assert(tx->lconstb); - } - tx->num_lconstb++; - } - - tx->lconstb[n].idx = index; - tx->lconstb[n].reg = tx->native_integers ? - ureg_imm1u(tx->ureg, b ? 0xffffffff : 0) : - ureg_imm1f(tx->ureg, b ? 1.0f : 0.0f); -} - -static inline struct ureg_dst -tx_scratch(struct shader_translator *tx) -{ - if (tx->num_scratch >= ARRAY_SIZE(tx->regs.t)) { - tx->failure = TRUE; - return tx->regs.t[0]; - } - if (ureg_dst_is_undef(tx->regs.t[tx->num_scratch])) - tx->regs.t[tx->num_scratch] = ureg_DECL_local_temporary(tx->ureg); - return tx->regs.t[tx->num_scratch++]; -} - -static inline struct ureg_dst -tx_scratch_scalar(struct shader_translator *tx) -{ - return ureg_writemask(tx_scratch(tx), TGSI_WRITEMASK_X); -} - -static inline struct ureg_src -tx_src_scalar(struct ureg_dst dst) -{ - struct ureg_src src = ureg_src(dst); - int c = ffs(dst.WriteMask) - 1; - if (dst.WriteMask == (1 << c)) - src = ureg_scalar(src, c); - return src; -} - -static inline void -tx_temp_alloc(struct shader_translator *tx, INT idx) -{ - assert(idx >= 0); - if (idx >= tx->num_temp) { - unsigned k = tx->num_temp; - unsigned n = idx + 1; - tx->regs.r = REALLOC(tx->regs.r, - k * sizeof(tx->regs.r[0]), - n * sizeof(tx->regs.r[0])); - for (; k < n; ++k) - tx->regs.r[k] = ureg_dst_undef(); - tx->num_temp = n; - } - if (ureg_dst_is_undef(tx->regs.r[idx])) - tx->regs.r[idx] = ureg_DECL_temporary(tx->ureg); -} - -static inline void -tx_addr_alloc(struct shader_translator *tx, INT idx) -{ - assert(idx == 0); - if (ureg_dst_is_undef(tx->regs.address)) - tx->regs.address = ureg_DECL_address(tx->ureg); - if (ureg_dst_is_undef(tx->regs.a0)) - tx->regs.a0 = ureg_DECL_temporary(tx->ureg); -} - -/* NOTE: It's not very clear on which ps1.1-ps1.3 instructions - * the projection should be applied on the texture. It doesn't - * apply on texkill. - * The doc is very imprecise here (it says the projection is done - * before rasterization, thus in vs, which seems wrong since ps instructions - * are affected differently) - * For now we only apply to the ps TEX instruction and TEXBEM. - * Perhaps some other instructions would need it */ -static inline void -apply_ps1x_projection(struct shader_translator *tx, struct ureg_dst dst, - struct ureg_src src, INT idx) -{ - struct ureg_dst tmp; - unsigned dim = 1 + ((tx->info->projected >> (2 * idx)) & 3); - - /* no projection */ - if (dim == 1) { - ureg_MOV(tx->ureg, dst, src); - } else { - tmp = tx_scratch_scalar(tx); - ureg_RCP(tx->ureg, tmp, ureg_scalar(src, dim-1)); - ureg_MUL(tx->ureg, dst, tx_src_scalar(tmp), src); - } -} - -static inline void -TEX_with_ps1x_projection(struct shader_translator *tx, struct ureg_dst dst, - unsigned target, struct ureg_src src0, - struct ureg_src src1, INT idx) -{ - unsigned dim = 1 + ((tx->info->projected >> (2 * idx)) & 3); - struct ureg_dst tmp; - boolean shadow = !!(tx->info->sampler_mask_shadow & (1 << idx)); - - /* dim == 1: no projection - * Looks like must be disabled when it makes no - * sense according the texture dimensions - */ - if (dim == 1 || (dim <= target && !shadow)) { - ureg_TEX(tx->ureg, dst, target, src0, src1); - } else if (dim == 4) { - ureg_TXP(tx->ureg, dst, target, src0, src1); - } else { - tmp = tx_scratch(tx); - apply_ps1x_projection(tx, tmp, src0, idx); - ureg_TEX(tx->ureg, dst, target, ureg_src(tmp), src1); - } -} - -static inline void -tx_texcoord_alloc(struct shader_translator *tx, INT idx) -{ - assert(IS_PS); - assert(idx >= 0 && idx < ARRAY_SIZE(tx->regs.vT)); - if (ureg_src_is_undef(tx->regs.vT[idx])) - tx->regs.vT[idx] = ureg_DECL_fs_input(tx->ureg, tx->texcoord_sn, idx, - TGSI_INTERPOLATE_PERSPECTIVE); -} - -static inline unsigned * -tx_bgnloop(struct shader_translator *tx) -{ - tx->loop_depth++; - if (tx->loop_depth_max < tx->loop_depth) - tx->loop_depth_max = tx->loop_depth; - assert(tx->loop_depth < NINE_MAX_LOOP_DEPTH); - return &tx->loop_labels[tx->loop_depth - 1]; -} - -static inline unsigned * -tx_endloop(struct shader_translator *tx) -{ - assert(tx->loop_depth); - tx->loop_depth--; - ureg_fixup_label(tx->ureg, tx->loop_labels[tx->loop_depth], - ureg_get_instruction_number(tx->ureg)); - return &tx->loop_labels[tx->loop_depth]; -} - -static struct ureg_dst -tx_get_loopctr(struct shader_translator *tx, boolean loop_or_rep) -{ - const unsigned l = tx->loop_depth - 1; - - if (!tx->loop_depth) - { - DBG("loop counter requested outside of loop\n"); - return ureg_dst_undef(); - } - - if (ureg_dst_is_undef(tx->regs.rL[l])) { - /* loop or rep ctr creation */ - tx->regs.rL[l] = ureg_DECL_local_temporary(tx->ureg); - tx->loop_or_rep[l] = loop_or_rep; - } - /* loop - rep - endloop - endrep not allowed */ - assert(tx->loop_or_rep[l] == loop_or_rep); - - return tx->regs.rL[l]; -} - -static struct ureg_src -tx_get_loopal(struct shader_translator *tx) -{ - int loop_level = tx->loop_depth - 1; - - while (loop_level >= 0) { - /* handle loop - rep - endrep - endloop case */ - if (tx->loop_or_rep[loop_level]) - /* the value is in the loop counter y component (nine implementation) */ - return ureg_scalar(ureg_src(tx->regs.rL[loop_level]), TGSI_SWIZZLE_Y); - loop_level--; - } - - DBG("aL counter requested outside of loop\n"); - return ureg_src_undef(); -} - -static inline unsigned * -tx_cond(struct shader_translator *tx) -{ - assert(tx->cond_depth <= NINE_MAX_COND_DEPTH); - tx->cond_depth++; - return &tx->cond_labels[tx->cond_depth - 1]; -} - -static inline unsigned * -tx_elsecond(struct shader_translator *tx) -{ - assert(tx->cond_depth); - return &tx->cond_labels[tx->cond_depth - 1]; -} - -static inline void -tx_endcond(struct shader_translator *tx) -{ - assert(tx->cond_depth); - tx->cond_depth--; - ureg_fixup_label(tx->ureg, tx->cond_labels[tx->cond_depth], - ureg_get_instruction_number(tx->ureg)); -} - -static inline struct ureg_dst -nine_ureg_dst_register(unsigned file, int index) -{ - return ureg_dst(ureg_src_register(file, index)); -} - -static inline struct ureg_src -nine_get_position_input(struct shader_translator *tx) -{ - struct ureg_program *ureg = tx->ureg; - - if (tx->wpos_is_sysval) - return ureg_DECL_system_value(ureg, TGSI_SEMANTIC_POSITION, 0); - else - return ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_POSITION, - 0, TGSI_INTERPOLATE_LINEAR); -} - -static struct ureg_src -tx_src_param(struct shader_translator *tx, const struct sm1_src_param *param) -{ - struct ureg_program *ureg = tx->ureg; - struct ureg_src src; - struct ureg_dst tmp; - - assert(!param->rel || (IS_VS && param->file == D3DSPR_CONST) || - (D3DSPR_ADDR && tx->version.major == 3)); - - switch (param->file) - { - case D3DSPR_TEMP: - tx_temp_alloc(tx, param->idx); - src = ureg_src(tx->regs.r[param->idx]); - break; - /* case D3DSPR_TEXTURE: == D3DSPR_ADDR */ - case D3DSPR_ADDR: - if (IS_VS) { - assert(param->idx == 0); - /* the address register (vs only) must be - * assigned before use */ - assert(!ureg_dst_is_undef(tx->regs.a0)); - /* Round to lowest for vs1.1 (contrary to the doc), else - * round to nearest */ - if (tx->version.major < 2 && tx->version.minor < 2) - ureg_ARL(ureg, tx->regs.address, ureg_src(tx->regs.a0)); - else - ureg_ARR(ureg, tx->regs.address, ureg_src(tx->regs.a0)); - src = ureg_src(tx->regs.address); - } else { - if (tx->version.major < 2 && tx->version.minor < 4) { - /* no subroutines, so should be defined */ - src = ureg_src(tx->regs.tS[param->idx]); - } else { - tx_texcoord_alloc(tx, param->idx); - src = tx->regs.vT[param->idx]; - } - } - break; - case D3DSPR_INPUT: - if (IS_VS) { - src = ureg_src_register(TGSI_FILE_INPUT, param->idx); - } else { - if (tx->version.major < 3) { - src = ureg_DECL_fs_input_cyl_centroid( - ureg, TGSI_SEMANTIC_COLOR, param->idx, - TGSI_INTERPOLATE_COLOR, 0, - tx->info->force_color_in_centroid ? - TGSI_INTERPOLATE_LOC_CENTROID : 0, - 0, 1); - } else { - if(param->rel) { - /* Copy all inputs (non consecutive) - * to temp array (consecutive). - * This is not good for performance. - * A better way would be to have inputs - * consecutive (would need implement alternative - * way to match vs outputs and ps inputs). - * However even with the better way, the temp array - * copy would need to be used if some inputs - * are not GENERIC or if they have different - * interpolation flag. */ - if (ureg_src_is_undef(tx->regs.v_consecutive)) { - int i; - tx->regs.v_consecutive = ureg_src(ureg_DECL_array_temporary(ureg, 10, 0)); - for (i = 0; i < 10; i++) { - if (!ureg_src_is_undef(tx->regs.v[i])) - ureg_MOV(ureg, ureg_dst_array_offset(ureg_dst(tx->regs.v_consecutive), i), tx->regs.v[i]); - else - ureg_MOV(ureg, ureg_dst_array_offset(ureg_dst(tx->regs.v_consecutive), i), ureg_imm4f(ureg, 0.0f, 0.0f, 0.0f, 1.0f)); - } - } - src = ureg_src_array_offset(tx->regs.v_consecutive, param->idx); - } else { - assert(param->idx < ARRAY_SIZE(tx->regs.v)); - src = tx->regs.v[param->idx]; - } - } - } - if (param->rel) - src = ureg_src_indirect(src, tx_src_param(tx, param->rel)); - break; - case D3DSPR_PREDICATE: - if (ureg_dst_is_undef(tx->regs.predicate)) { - /* Forbidden to use the predicate register before being set */ - tx->failure = TRUE; - tx->regs.predicate = ureg_DECL_temporary(tx->ureg); - } - src = ureg_src(tx->regs.predicate); - break; - case D3DSPR_SAMPLER: - assert(param->mod == NINED3DSPSM_NONE); - assert(param->swizzle == NINED3DSP_NOSWIZZLE); - src = ureg_DECL_sampler(ureg, param->idx); - break; - case D3DSPR_CONST: - if (param->rel || !tx_lconstf(tx, &src, param->idx)) { - src = nine_float_constant_src(tx, param->idx); - if (param->rel) { - tx->indirect_const_access = TRUE; - src = ureg_src_indirect(src, tx_src_param(tx, param->rel)); - } - } - if (!IS_VS && tx->version.major < 2) { - /* ps 1.X clamps constants */ - tmp = tx_scratch(tx); - ureg_MIN(ureg, tmp, src, ureg_imm1f(ureg, 1.0f)); - ureg_MAX(ureg, tmp, ureg_src(tmp), ureg_imm1f(ureg, -1.0f)); - src = ureg_src(tmp); - } - break; - case D3DSPR_CONST2: - case D3DSPR_CONST3: - case D3DSPR_CONST4: - DBG("CONST2/3/4 should have been collapsed into D3DSPR_CONST !\n"); - assert(!"CONST2/3/4"); - src = ureg_imm1f(ureg, 0.0f); - break; - case D3DSPR_CONSTINT: - /* relative adressing only possible for float constants in vs */ - if (!tx_lconsti(tx, &src, param->idx)) - src = nine_integer_constant_src(tx, param->idx); - break; - case D3DSPR_CONSTBOOL: - if (!tx_lconstb(tx, &src, param->idx)) - src = nine_boolean_constant_src(tx, param->idx); - break; - case D3DSPR_LOOP: - if (ureg_dst_is_undef(tx->regs.address)) - tx->regs.address = ureg_DECL_address(ureg); - if (!tx->native_integers) - ureg_ARR(ureg, tx->regs.address, tx_get_loopal(tx)); - else - ureg_UARL(ureg, tx->regs.address, tx_get_loopal(tx)); - src = ureg_src(tx->regs.address); - break; - case D3DSPR_MISCTYPE: - switch (param->idx) { - case D3DSMO_POSITION: - if (ureg_src_is_undef(tx->regs.vPos)) - tx->regs.vPos = nine_get_position_input(tx); - if (tx->shift_wpos) { - /* TODO: do this only once */ - struct ureg_dst wpos = tx_scratch(tx); - ureg_ADD(ureg, wpos, tx->regs.vPos, - ureg_imm4f(ureg, -0.5f, -0.5f, 0.0f, 0.0f)); - src = ureg_src(wpos); - } else { - src = tx->regs.vPos; - } - break; - case D3DSMO_FACE: - if (ureg_src_is_undef(tx->regs.vFace)) { - if (tx->face_is_sysval_integer) { - tmp = ureg_DECL_temporary(ureg); - tx->regs.vFace = - ureg_DECL_system_value(ureg, TGSI_SEMANTIC_FACE, 0); - - /* convert bool to float */ - ureg_UCMP(ureg, tmp, ureg_scalar(tx->regs.vFace, TGSI_SWIZZLE_X), - ureg_imm1f(ureg, 1), ureg_imm1f(ureg, -1)); - tx->regs.vFace = ureg_src(tmp); - } else { - tx->regs.vFace = ureg_DECL_fs_input(ureg, - TGSI_SEMANTIC_FACE, 0, - TGSI_INTERPOLATE_CONSTANT); - } - tx->regs.vFace = ureg_scalar(tx->regs.vFace, TGSI_SWIZZLE_X); - } - src = tx->regs.vFace; - break; - default: - assert(!"invalid src D3DSMO"); - break; - } - break; - case D3DSPR_TEMPFLOAT16: - break; - default: - assert(!"invalid src D3DSPR"); - } - - switch (param->mod) { - case NINED3DSPSM_DW: - tmp = tx_scratch(tx); - /* NOTE: app is not allowed to read w with this modifier */ - ureg_RCP(ureg, ureg_writemask(tmp, NINED3DSP_WRITEMASK_3), ureg_scalar(src, TGSI_SWIZZLE_W)); - ureg_MUL(ureg, tmp, src, ureg_swizzle(ureg_src(tmp), NINE_SWIZZLE4(W,W,W,W))); - src = ureg_src(tmp); - break; - case NINED3DSPSM_DZ: - tmp = tx_scratch(tx); - /* NOTE: app is not allowed to read z with this modifier */ - ureg_RCP(ureg, ureg_writemask(tmp, NINED3DSP_WRITEMASK_2), ureg_scalar(src, TGSI_SWIZZLE_Z)); - ureg_MUL(ureg, tmp, src, ureg_swizzle(ureg_src(tmp), NINE_SWIZZLE4(Z,Z,Z,Z))); - src = ureg_src(tmp); - break; - default: - break; - } - - if (param->swizzle != NINED3DSP_NOSWIZZLE) - src = ureg_swizzle(src, - (param->swizzle >> 0) & 0x3, - (param->swizzle >> 2) & 0x3, - (param->swizzle >> 4) & 0x3, - (param->swizzle >> 6) & 0x3); - - switch (param->mod) { - case NINED3DSPSM_ABS: - src = ureg_abs(src); - break; - case NINED3DSPSM_ABSNEG: - src = ureg_negate(ureg_abs(src)); - break; - case NINED3DSPSM_NEG: - src = ureg_negate(src); - break; - case NINED3DSPSM_BIAS: - tmp = tx_scratch(tx); - ureg_ADD(ureg, tmp, src, ureg_imm1f(ureg, -0.5f)); - src = ureg_src(tmp); - break; - case NINED3DSPSM_BIASNEG: - tmp = tx_scratch(tx); - ureg_ADD(ureg, tmp, ureg_imm1f(ureg, 0.5f), ureg_negate(src)); - src = ureg_src(tmp); - break; - case NINED3DSPSM_NOT: - if (tx->native_integers && param->file == D3DSPR_CONSTBOOL) { - tmp = tx_scratch(tx); - ureg_NOT(ureg, tmp, src); - src = ureg_src(tmp); - break; - } else { /* predicate */ - tmp = tx_scratch(tx); - ureg_ADD(ureg, tmp, ureg_imm1f(ureg, 1.0f), ureg_negate(src)); - src = ureg_src(tmp); - } - /* fall through */ - case NINED3DSPSM_COMP: - tmp = tx_scratch(tx); - ureg_ADD(ureg, tmp, ureg_imm1f(ureg, 1.0f), ureg_negate(src)); - src = ureg_src(tmp); - break; - case NINED3DSPSM_DZ: - case NINED3DSPSM_DW: - /* Already handled*/ - break; - case NINED3DSPSM_SIGN: - tmp = tx_scratch(tx); - ureg_MAD(ureg, tmp, src, ureg_imm1f(ureg, 2.0f), ureg_imm1f(ureg, -1.0f)); - src = ureg_src(tmp); - break; - case NINED3DSPSM_SIGNNEG: - tmp = tx_scratch(tx); - ureg_MAD(ureg, tmp, src, ureg_imm1f(ureg, -2.0f), ureg_imm1f(ureg, 1.0f)); - src = ureg_src(tmp); - break; - case NINED3DSPSM_X2: - tmp = tx_scratch(tx); - ureg_ADD(ureg, tmp, src, src); - src = ureg_src(tmp); - break; - case NINED3DSPSM_X2NEG: - tmp = tx_scratch(tx); - ureg_ADD(ureg, tmp, src, src); - src = ureg_negate(ureg_src(tmp)); - break; - default: - assert(param->mod == NINED3DSPSM_NONE); - break; - } - - return src; -} - -static struct ureg_dst -_tx_dst_param(struct shader_translator *tx, const struct sm1_dst_param *param) -{ - struct ureg_dst dst; - - switch (param->file) - { - case D3DSPR_TEMP: - assert(!param->rel); - tx_temp_alloc(tx, param->idx); - dst = tx->regs.r[param->idx]; - break; - /* case D3DSPR_TEXTURE: == D3DSPR_ADDR */ - case D3DSPR_ADDR: - assert(!param->rel); - if (tx->version.major < 2 && !IS_VS) { - if (ureg_dst_is_undef(tx->regs.tS[param->idx])) - tx->regs.tS[param->idx] = ureg_DECL_temporary(tx->ureg); - dst = tx->regs.tS[param->idx]; - } else - if (!IS_VS && tx->insn.opcode == D3DSIO_TEXKILL) { /* maybe others, too */ - tx_texcoord_alloc(tx, param->idx); - dst = ureg_dst(tx->regs.vT[param->idx]); - } else { - tx_addr_alloc(tx, param->idx); - dst = tx->regs.a0; - } - break; - case D3DSPR_RASTOUT: - assert(!param->rel); - switch (param->idx) { - case 0: - if (ureg_dst_is_undef(tx->regs.oPos)) - tx->regs.oPos = - ureg_DECL_output(tx->ureg, TGSI_SEMANTIC_POSITION, 0); - dst = tx->regs.oPos; - break; - case 1: - if (ureg_dst_is_undef(tx->regs.oFog)) - tx->regs.oFog = - ureg_saturate(ureg_DECL_output(tx->ureg, TGSI_SEMANTIC_GENERIC, 16)); - dst = tx->regs.oFog; - break; - case 2: - if (ureg_dst_is_undef(tx->regs.oPts)) - tx->regs.oPts = ureg_DECL_temporary(tx->ureg); - dst = tx->regs.oPts; - break; - default: - assert(0); - break; - } - break; - /* case D3DSPR_TEXCRDOUT: == D3DSPR_OUTPUT */ - case D3DSPR_OUTPUT: - if (tx->version.major < 3) { - assert(!param->rel); - dst = ureg_DECL_output(tx->ureg, tx->texcoord_sn, param->idx); - } else { - assert(!param->rel); /* TODO */ - assert(param->idx < ARRAY_SIZE(tx->regs.o)); - dst = tx->regs.o[param->idx]; - } - break; - case D3DSPR_ATTROUT: /* VS */ - case D3DSPR_COLOROUT: /* PS */ - assert(param->idx >= 0 && param->idx < 4); - assert(!param->rel); - tx->info->rt_mask |= 1 << param->idx; - if (ureg_dst_is_undef(tx->regs.oCol[param->idx])) { - /* ps < 3: oCol[0] will have fog blending afterward */ - if (!IS_VS && tx->version.major < 3 && param->idx == 0) { - tx->regs.oCol[0] = ureg_DECL_temporary(tx->ureg); - } else { - tx->regs.oCol[param->idx] = - ureg_DECL_output(tx->ureg, TGSI_SEMANTIC_COLOR, param->idx); - } - } - dst = tx->regs.oCol[param->idx]; - if (IS_VS && tx->version.major < 3) - dst = ureg_saturate(dst); - break; - case D3DSPR_DEPTHOUT: - assert(!param->rel); - if (ureg_dst_is_undef(tx->regs.oDepth)) - tx->regs.oDepth = - ureg_DECL_output_masked(tx->ureg, TGSI_SEMANTIC_POSITION, 0, - TGSI_WRITEMASK_Z, 0, 1); - dst = tx->regs.oDepth; /* XXX: must write .z component */ - break; - case D3DSPR_PREDICATE: - if (ureg_dst_is_undef(tx->regs.predicate)) - tx->regs.predicate = ureg_DECL_temporary(tx->ureg); - dst = tx->regs.predicate; - break; - case D3DSPR_TEMPFLOAT16: - DBG("unhandled D3DSPR: %u\n", param->file); - break; - default: - assert(!"invalid dst D3DSPR"); - break; - } - if (param->rel) - dst = ureg_dst_indirect(dst, tx_src_param(tx, param->rel)); - - if (param->mask != NINED3DSP_WRITEMASK_ALL) - dst = ureg_writemask(dst, param->mask); - if (param->mod & NINED3DSPDM_SATURATE) - dst = ureg_saturate(dst); - - if (tx->predicated_activated) { - tx->regs.predicate_dst = dst; - dst = tx->regs.predicate_tmp; - } - - return dst; -} - -static struct ureg_dst -tx_dst_param(struct shader_translator *tx, const struct sm1_dst_param *param) -{ - if (param->shift) { - tx->regs.tdst = ureg_writemask(tx_scratch(tx), param->mask); - return tx->regs.tdst; - } - return _tx_dst_param(tx, param); -} - -static void -tx_apply_dst0_modifiers(struct shader_translator *tx) -{ - struct ureg_dst rdst; - float f; - - if (!tx->insn.ndst || !tx->insn.dst[0].shift || tx->insn.opcode == D3DSIO_TEXKILL) - return; - rdst = _tx_dst_param(tx, &tx->insn.dst[0]); - - assert(rdst.File != TGSI_FILE_ADDRESS); /* this probably isn't possible */ - - if (tx->insn.dst[0].shift < 0) - f = 1.0f / (1 << -tx->insn.dst[0].shift); - else - f = 1 << tx->insn.dst[0].shift; - - ureg_MUL(tx->ureg, rdst, ureg_src(tx->regs.tdst), ureg_imm1f(tx->ureg, f)); -} - -static struct ureg_src -tx_dst_param_as_src(struct shader_translator *tx, const struct sm1_dst_param *param) -{ - struct ureg_src src; - - assert(!param->shift); - assert(!(param->mod & NINED3DSPDM_SATURATE)); - - switch (param->file) { - case D3DSPR_INPUT: - if (IS_VS) { - src = ureg_src_register(TGSI_FILE_INPUT, param->idx); - } else { - assert(!param->rel); - assert(param->idx < ARRAY_SIZE(tx->regs.v)); - src = tx->regs.v[param->idx]; - } - break; - default: - src = ureg_src(tx_dst_param(tx, param)); - break; - } - if (param->rel) - src = ureg_src_indirect(src, tx_src_param(tx, param->rel)); - - if (!param->mask) - WARN("mask is 0, using identity swizzle\n"); - - if (param->mask && param->mask != NINED3DSP_WRITEMASK_ALL) { - char s[4]; - int n; - int c; - for (n = 0, c = 0; c < 4; ++c) - if (param->mask & (1 << c)) - s[n++] = c; - assert(n); - for (c = n; c < 4; ++c) - s[c] = s[n - 1]; - src = ureg_swizzle(src, s[0], s[1], s[2], s[3]); - } - return src; -} - -static HRESULT -NineTranslateInstruction_Mkxn(struct shader_translator *tx, const unsigned k, const unsigned n) -{ - struct ureg_program *ureg = tx->ureg; - struct ureg_dst dst; - struct ureg_src src[2]; - struct sm1_src_param *src_mat = &tx->insn.src[1]; - unsigned i; - - dst = tx_dst_param(tx, &tx->insn.dst[0]); - src[0] = tx_src_param(tx, &tx->insn.src[0]); - - for (i = 0; i < n; i++) - { - const unsigned m = (1 << i); - - src[1] = tx_src_param(tx, src_mat); - src_mat->idx++; - - if (!(dst.WriteMask & m)) - continue; - - /* XXX: src == dst case ? */ - - switch (k) { - case 3: - ureg_DP3(ureg, ureg_writemask(dst, m), src[0], src[1]); - break; - case 4: - ureg_DP4(ureg, ureg_writemask(dst, m), src[0], src[1]); - break; - default: - DBG("invalid operation: M%ux%u\n", m, n); - break; - } - } - - return D3D_OK; -} - -#define VNOTSUPPORTED 0, 0 -#define V(maj, min) (((maj) << 8) | (min)) - -static inline const char * -d3dsio_to_string( unsigned opcode ) -{ - static const char *names[] = { - "NOP", - "MOV", - "ADD", - "SUB", - "MAD", - "MUL", - "RCP", - "RSQ", - "DP3", - "DP4", - "MIN", - "MAX", - "SLT", - "SGE", - "EXP", - "LOG", - "LIT", - "DST", - "LRP", - "FRC", - "M4x4", - "M4x3", - "M3x4", - "M3x3", - "M3x2", - "CALL", - "CALLNZ", - "LOOP", - "RET", - "ENDLOOP", - "LABEL", - "DCL", - "POW", - "CRS", - "SGN", - "ABS", - "NRM", - "SINCOS", - "REP", - "ENDREP", - "IF", - "IFC", - "ELSE", - "ENDIF", - "BREAK", - "BREAKC", - "MOVA", - "DEFB", - "DEFI", - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - "TEXCOORD", - "TEXKILL", - "TEX", - "TEXBEM", - "TEXBEML", - "TEXREG2AR", - "TEXREG2GB", - "TEXM3x2PAD", - "TEXM3x2TEX", - "TEXM3x3PAD", - "TEXM3x3TEX", - NULL, - "TEXM3x3SPEC", - "TEXM3x3VSPEC", - "EXPP", - "LOGP", - "CND", - "DEF", - "TEXREG2RGB", - "TEXDP3TEX", - "TEXM3x2DEPTH", - "TEXDP3", - "TEXM3x3", - "TEXDEPTH", - "CMP", - "BEM", - "DP2ADD", - "DSX", - "DSY", - "TEXLDD", - "SETP", - "TEXLDL", - "BREAKP" - }; - - if (opcode < ARRAY_SIZE(names)) return names[opcode]; - - switch (opcode) { - case D3DSIO_PHASE: return "PHASE"; - case D3DSIO_COMMENT: return "COMMENT"; - case D3DSIO_END: return "END"; - default: - return NULL; - } -} - -#define NULL_INSTRUCTION { 0, { 0, 0 }, { 0, 0 }, 0, 0, NULL } -#define IS_VALID_INSTRUCTION(inst) ((inst).vert_version.min | \ - (inst).vert_version.max | \ - (inst).frag_version.min | \ - (inst).frag_version.max) - -#define SPECIAL(name) \ - NineTranslateInstruction_##name - -#define DECL_SPECIAL(name) \ - static HRESULT \ - NineTranslateInstruction_##name( struct shader_translator *tx ) - -static HRESULT -NineTranslateInstruction_Generic(struct shader_translator *); - -DECL_SPECIAL(NOP) -{ - /* Nothing to do. NOP was used to avoid hangs - * with very old d3d drivers. */ - return D3D_OK; -} - -DECL_SPECIAL(SUB) -{ - struct ureg_program *ureg = tx->ureg; - struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); - struct ureg_src src0 = tx_src_param(tx, &tx->insn.src[0]); - struct ureg_src src1 = tx_src_param(tx, &tx->insn.src[1]); - - ureg_ADD(ureg, dst, src0, ureg_negate(src1)); - return D3D_OK; -} - -DECL_SPECIAL(ABS) -{ - struct ureg_program *ureg = tx->ureg; - struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); - struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]); - - ureg_MOV(ureg, dst, ureg_abs(src)); - return D3D_OK; -} - -DECL_SPECIAL(XPD) -{ - struct ureg_program *ureg = tx->ureg; - struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); - struct ureg_src src0 = tx_src_param(tx, &tx->insn.src[0]); - struct ureg_src src1 = tx_src_param(tx, &tx->insn.src[1]); - - ureg_MUL(ureg, ureg_writemask(dst, TGSI_WRITEMASK_XYZ), - ureg_swizzle(src0, TGSI_SWIZZLE_Y, TGSI_SWIZZLE_Z, - TGSI_SWIZZLE_X, 0), - ureg_swizzle(src1, TGSI_SWIZZLE_Z, TGSI_SWIZZLE_X, - TGSI_SWIZZLE_Y, 0)); - ureg_MAD(ureg, ureg_writemask(dst, TGSI_WRITEMASK_XYZ), - ureg_swizzle(src0, TGSI_SWIZZLE_Z, TGSI_SWIZZLE_X, - TGSI_SWIZZLE_Y, 0), - ureg_negate(ureg_swizzle(src1, TGSI_SWIZZLE_Y, - TGSI_SWIZZLE_Z, TGSI_SWIZZLE_X, 0)), - ureg_src(dst)); - ureg_MOV(ureg, ureg_writemask(dst, TGSI_WRITEMASK_W), - ureg_imm1f(ureg, 1)); - return D3D_OK; -} - -DECL_SPECIAL(M4x4) -{ - return NineTranslateInstruction_Mkxn(tx, 4, 4); -} - -DECL_SPECIAL(M4x3) -{ - return NineTranslateInstruction_Mkxn(tx, 4, 3); -} - -DECL_SPECIAL(M3x4) -{ - return NineTranslateInstruction_Mkxn(tx, 3, 4); -} - -DECL_SPECIAL(M3x3) -{ - return NineTranslateInstruction_Mkxn(tx, 3, 3); -} - -DECL_SPECIAL(M3x2) -{ - return NineTranslateInstruction_Mkxn(tx, 3, 2); -} - -DECL_SPECIAL(CMP) -{ - ureg_CMP(tx->ureg, tx_dst_param(tx, &tx->insn.dst[0]), - tx_src_param(tx, &tx->insn.src[0]), - tx_src_param(tx, &tx->insn.src[2]), - tx_src_param(tx, &tx->insn.src[1])); - return D3D_OK; -} - -DECL_SPECIAL(CND) -{ - struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); - struct ureg_dst cgt; - struct ureg_src cnd; - - /* the coissue flag was a tip for compilers to advise to - * execute two operations at the same time, in cases - * the two executions had same dst with different channels. - * It has no effect on current hw. However it seems CND - * is affected. The handling of this very specific case - * handled below mimick wine behaviour */ - if (tx->insn.coissue && tx->version.major == 1 && tx->version.minor < 4 && tx->insn.dst[0].mask != NINED3DSP_WRITEMASK_3) { - ureg_MOV(tx->ureg, - dst, tx_src_param(tx, &tx->insn.src[1])); - return D3D_OK; - } - - cnd = tx_src_param(tx, &tx->insn.src[0]); - cgt = tx_scratch(tx); - - if (tx->version.major == 1 && tx->version.minor < 4) - cnd = ureg_scalar(cnd, TGSI_SWIZZLE_W); - - ureg_SGT(tx->ureg, cgt, cnd, ureg_imm1f(tx->ureg, 0.5f)); - - ureg_CMP(tx->ureg, dst, ureg_negate(ureg_src(cgt)), - tx_src_param(tx, &tx->insn.src[1]), - tx_src_param(tx, &tx->insn.src[2])); - return D3D_OK; -} - -DECL_SPECIAL(CALL) -{ - assert(tx->insn.src[0].idx < tx->num_inst_labels); - ureg_CAL(tx->ureg, &tx->inst_labels[tx->insn.src[0].idx]); - return D3D_OK; -} - -DECL_SPECIAL(CALLNZ) -{ - struct ureg_program *ureg = tx->ureg; - struct ureg_src src = tx_src_param(tx, &tx->insn.src[1]); - - if (!tx->native_integers) - ureg_IF(ureg, src, tx_cond(tx)); - else - ureg_UIF(ureg, src, tx_cond(tx)); - ureg_CAL(ureg, &tx->inst_labels[tx->insn.src[0].idx]); - tx_endcond(tx); - ureg_ENDIF(ureg); - return D3D_OK; -} - -DECL_SPECIAL(LOOP) -{ - struct ureg_program *ureg = tx->ureg; - unsigned *label; - struct ureg_src src = tx_src_param(tx, &tx->insn.src[1]); - struct ureg_dst ctr; - struct ureg_dst tmp; - struct ureg_src ctrx; - - label = tx_bgnloop(tx); - ctr = tx_get_loopctr(tx, TRUE); - ctrx = ureg_scalar(ureg_src(ctr), TGSI_SWIZZLE_X); - - /* src: num_iterations - start_value of al - step for al - 0 */ - ureg_MOV(ureg, ctr, src); - ureg_BGNLOOP(tx->ureg, label); - tmp = tx_scratch_scalar(tx); - /* Initially ctr.x contains the number of iterations. - * ctr.y will contain the updated value of al. - * We decrease ctr.x at the end of every iteration, - * and stop when it reaches 0. */ - - if (!tx->native_integers) { - /* case src and ctr contain floats */ - /* to avoid precision issue, we stop when ctr <= 0.5 */ - ureg_SGE(ureg, tmp, ureg_imm1f(ureg, 0.5f), ctrx); - ureg_IF(ureg, tx_src_scalar(tmp), tx_cond(tx)); - } else { - /* case src and ctr contain integers */ - ureg_ISGE(ureg, tmp, ureg_imm1i(ureg, 0), ctrx); - ureg_UIF(ureg, tx_src_scalar(tmp), tx_cond(tx)); - } - ureg_BRK(ureg); - tx_endcond(tx); - ureg_ENDIF(ureg); - return D3D_OK; -} - -DECL_SPECIAL(RET) -{ - /* RET as a last instruction could be safely ignored. - * Remove it to prevent crashes/warnings in case underlying - * driver doesn't implement arbitrary returns. - */ - if (*(tx->parse_next) != NINED3DSP_END) { - ureg_RET(tx->ureg); - } - return D3D_OK; -} - -DECL_SPECIAL(ENDLOOP) -{ - struct ureg_program *ureg = tx->ureg; - struct ureg_dst ctr = tx_get_loopctr(tx, TRUE); - struct ureg_dst dst_ctrx, dst_al; - struct ureg_src src_ctr, al_counter; - - dst_ctrx = ureg_writemask(ctr, NINED3DSP_WRITEMASK_0); - dst_al = ureg_writemask(ctr, NINED3DSP_WRITEMASK_1); - src_ctr = ureg_src(ctr); - al_counter = ureg_scalar(src_ctr, TGSI_SWIZZLE_Z); - - /* ctr.x -= 1 - * ctr.y (aL) += step */ - if (!tx->native_integers) { - ureg_ADD(ureg, dst_ctrx, src_ctr, ureg_imm1f(ureg, -1.0f)); - ureg_ADD(ureg, dst_al, src_ctr, al_counter); - } else { - ureg_UADD(ureg, dst_ctrx, src_ctr, ureg_imm1i(ureg, -1)); - ureg_UADD(ureg, dst_al, src_ctr, al_counter); - } - ureg_ENDLOOP(tx->ureg, tx_endloop(tx)); - return D3D_OK; -} - -DECL_SPECIAL(LABEL) -{ - unsigned k = tx->num_inst_labels; - unsigned n = tx->insn.src[0].idx; - assert(n < 2048); - if (n >= k) - tx->inst_labels = REALLOC(tx->inst_labels, - k * sizeof(tx->inst_labels[0]), - n * sizeof(tx->inst_labels[0])); - - tx->inst_labels[n] = ureg_get_instruction_number(tx->ureg); - return D3D_OK; -} - -DECL_SPECIAL(SINCOS) -{ - struct ureg_program *ureg = tx->ureg; - struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); - struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]); - struct ureg_dst tmp = tx_scratch_scalar(tx); - - assert(!(dst.WriteMask & 0xc)); - - /* Copying to a temporary register avoids src/dst aliasing. - * src is supposed to have replicated swizzle. */ - ureg_MOV(ureg, tmp, src); - - /* z undefined, w untouched */ - ureg_COS(ureg, ureg_writemask(dst, TGSI_WRITEMASK_X), - tx_src_scalar(tmp)); - ureg_SIN(ureg, ureg_writemask(dst, TGSI_WRITEMASK_Y), - tx_src_scalar(tmp)); - return D3D_OK; -} - -DECL_SPECIAL(SGN) -{ - ureg_SSG(tx->ureg, - tx_dst_param(tx, &tx->insn.dst[0]), - tx_src_param(tx, &tx->insn.src[0])); - return D3D_OK; -} - -DECL_SPECIAL(REP) -{ - struct ureg_program *ureg = tx->ureg; - unsigned *label; - struct ureg_src rep = tx_src_param(tx, &tx->insn.src[0]); - struct ureg_dst ctr; - struct ureg_dst tmp; - struct ureg_src ctrx; - - label = tx_bgnloop(tx); - ctr = ureg_writemask(tx_get_loopctr(tx, FALSE), NINED3DSP_WRITEMASK_0); - ctrx = ureg_scalar(ureg_src(ctr), TGSI_SWIZZLE_X); - - /* NOTE: rep must be constant, so we don't have to save the count */ - assert(rep.File == TGSI_FILE_CONSTANT || rep.File == TGSI_FILE_IMMEDIATE); - - /* rep: num_iterations - 0 - 0 - 0 */ - ureg_MOV(ureg, ctr, rep); - ureg_BGNLOOP(ureg, label); - tmp = tx_scratch_scalar(tx); - /* Initially ctr.x contains the number of iterations. - * We decrease ctr.x at the end of every iteration, - * and stop when it reaches 0. */ - - if (!tx->native_integers) { - /* case src and ctr contain floats */ - /* to avoid precision issue, we stop when ctr <= 0.5 */ - ureg_SGE(ureg, tmp, ureg_imm1f(ureg, 0.5f), ctrx); - ureg_IF(ureg, tx_src_scalar(tmp), tx_cond(tx)); - } else { - /* case src and ctr contain integers */ - ureg_ISGE(ureg, tmp, ureg_imm1i(ureg, 0), ctrx); - ureg_UIF(ureg, tx_src_scalar(tmp), tx_cond(tx)); - } - ureg_BRK(ureg); - tx_endcond(tx); - ureg_ENDIF(ureg); - - return D3D_OK; -} - -DECL_SPECIAL(ENDREP) -{ - struct ureg_program *ureg = tx->ureg; - struct ureg_dst ctr = tx_get_loopctr(tx, FALSE); - struct ureg_dst dst_ctrx = ureg_writemask(ctr, NINED3DSP_WRITEMASK_0); - struct ureg_src src_ctr = ureg_src(ctr); - - /* ctr.x -= 1 */ - if (!tx->native_integers) - ureg_ADD(ureg, dst_ctrx, src_ctr, ureg_imm1f(ureg, -1.0f)); - else - ureg_UADD(ureg, dst_ctrx, src_ctr, ureg_imm1i(ureg, -1)); - - ureg_ENDLOOP(tx->ureg, tx_endloop(tx)); - return D3D_OK; -} - -DECL_SPECIAL(ENDIF) -{ - tx_endcond(tx); - ureg_ENDIF(tx->ureg); - return D3D_OK; -} - -DECL_SPECIAL(IF) -{ - struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]); - - if (tx->native_integers && tx->insn.src[0].file == D3DSPR_CONSTBOOL) - ureg_UIF(tx->ureg, src, tx_cond(tx)); - else - ureg_IF(tx->ureg, src, tx_cond(tx)); - - return D3D_OK; -} - -static inline unsigned -sm1_insn_flags_to_tgsi_setop(BYTE flags) -{ - switch (flags) { - case NINED3DSHADER_REL_OP_GT: return TGSI_OPCODE_SGT; - case NINED3DSHADER_REL_OP_EQ: return TGSI_OPCODE_SEQ; - case NINED3DSHADER_REL_OP_GE: return TGSI_OPCODE_SGE; - case NINED3DSHADER_REL_OP_LT: return TGSI_OPCODE_SLT; - case NINED3DSHADER_REL_OP_NE: return TGSI_OPCODE_SNE; - case NINED3DSHADER_REL_OP_LE: return TGSI_OPCODE_SLE; - default: - assert(!"invalid comparison flags"); - return TGSI_OPCODE_SGT; - } -} - -DECL_SPECIAL(IFC) -{ - const unsigned cmp_op = sm1_insn_flags_to_tgsi_setop(tx->insn.flags); - struct ureg_src src[2]; - struct ureg_dst tmp = ureg_writemask(tx_scratch(tx), TGSI_WRITEMASK_X); - src[0] = tx_src_param(tx, &tx->insn.src[0]); - src[1] = tx_src_param(tx, &tx->insn.src[1]); - ureg_insn(tx->ureg, cmp_op, &tmp, 1, src, 2, 0); - ureg_IF(tx->ureg, ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X), tx_cond(tx)); - return D3D_OK; -} - -DECL_SPECIAL(ELSE) -{ - ureg_ELSE(tx->ureg, tx_elsecond(tx)); - return D3D_OK; -} - -DECL_SPECIAL(BREAKC) -{ - const unsigned cmp_op = sm1_insn_flags_to_tgsi_setop(tx->insn.flags); - struct ureg_src src[2]; - struct ureg_dst tmp = ureg_writemask(tx_scratch(tx), TGSI_WRITEMASK_X); - src[0] = tx_src_param(tx, &tx->insn.src[0]); - src[1] = tx_src_param(tx, &tx->insn.src[1]); - ureg_insn(tx->ureg, cmp_op, &tmp, 1, src, 2, 0); - ureg_IF(tx->ureg, ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X), tx_cond(tx)); - ureg_BRK(tx->ureg); - tx_endcond(tx); - ureg_ENDIF(tx->ureg); - return D3D_OK; -} - -static const char *sm1_declusage_names[] = -{ - [D3DDECLUSAGE_POSITION] = "POSITION", - [D3DDECLUSAGE_BLENDWEIGHT] = "BLENDWEIGHT", - [D3DDECLUSAGE_BLENDINDICES] = "BLENDINDICES", - [D3DDECLUSAGE_NORMAL] = "NORMAL", - [D3DDECLUSAGE_PSIZE] = "PSIZE", - [D3DDECLUSAGE_TEXCOORD] = "TEXCOORD", - [D3DDECLUSAGE_TANGENT] = "TANGENT", - [D3DDECLUSAGE_BINORMAL] = "BINORMAL", - [D3DDECLUSAGE_TESSFACTOR] = "TESSFACTOR", - [D3DDECLUSAGE_POSITIONT] = "POSITIONT", - [D3DDECLUSAGE_COLOR] = "COLOR", - [D3DDECLUSAGE_FOG] = "FOG", - [D3DDECLUSAGE_DEPTH] = "DEPTH", - [D3DDECLUSAGE_SAMPLE] = "SAMPLE" -}; - -static inline unsigned -sm1_to_nine_declusage(struct sm1_semantic *dcl) -{ - return nine_d3d9_to_nine_declusage(dcl->usage, dcl->usage_idx); -} - -static void -sm1_declusage_to_tgsi(struct tgsi_declaration_semantic *sem, - boolean tc, - struct sm1_semantic *dcl) -{ - BYTE index = dcl->usage_idx; - - /* For everything that is not matching to a TGSI_SEMANTIC_****, - * we match to a TGSI_SEMANTIC_GENERIC with index. - * - * The index can be anything UINT16 and usage_idx is BYTE, - * so we can fit everything. It doesn't matter if indices - * are close together or low. - * - * - * POSITION >= 1: 10 * index + 7 - * COLOR >= 2: 10 * (index-1) + 8 - * FOG: 16 - * TEXCOORD[0..15]: index - * BLENDWEIGHT: 10 * index + 19 - * BLENDINDICES: 10 * index + 20 - * NORMAL: 10 * index + 21 - * TANGENT: 10 * index + 22 - * BINORMAL: 10 * index + 23 - * TESSFACTOR: 10 * index + 24 - */ - - switch (dcl->usage) { - case D3DDECLUSAGE_POSITION: - case D3DDECLUSAGE_POSITIONT: - case D3DDECLUSAGE_DEPTH: - if (index == 0) { - sem->Name = TGSI_SEMANTIC_POSITION; - sem->Index = 0; - } else { - sem->Name = TGSI_SEMANTIC_GENERIC; - sem->Index = 10 * index + 7; - } - break; - case D3DDECLUSAGE_COLOR: - if (index < 2) { - sem->Name = TGSI_SEMANTIC_COLOR; - sem->Index = index; - } else { - sem->Name = TGSI_SEMANTIC_GENERIC; - sem->Index = 10 * (index-1) + 8; - } - break; - case D3DDECLUSAGE_FOG: - assert(index == 0); - sem->Name = TGSI_SEMANTIC_GENERIC; - sem->Index = 16; - break; - case D3DDECLUSAGE_PSIZE: - assert(index == 0); - sem->Name = TGSI_SEMANTIC_PSIZE; - sem->Index = 0; - break; - case D3DDECLUSAGE_TEXCOORD: - assert(index < 16); - if (index < 8 && tc) - sem->Name = TGSI_SEMANTIC_TEXCOORD; - else - sem->Name = TGSI_SEMANTIC_GENERIC; - sem->Index = index; - break; - case D3DDECLUSAGE_BLENDWEIGHT: - sem->Name = TGSI_SEMANTIC_GENERIC; - sem->Index = 10 * index + 19; - break; - case D3DDECLUSAGE_BLENDINDICES: - sem->Name = TGSI_SEMANTIC_GENERIC; - sem->Index = 10 * index + 20; - break; - case D3DDECLUSAGE_NORMAL: - sem->Name = TGSI_SEMANTIC_GENERIC; - sem->Index = 10 * index + 21; - break; - case D3DDECLUSAGE_TANGENT: - sem->Name = TGSI_SEMANTIC_GENERIC; - sem->Index = 10 * index + 22; - break; - case D3DDECLUSAGE_BINORMAL: - sem->Name = TGSI_SEMANTIC_GENERIC; - sem->Index = 10 * index + 23; - break; - case D3DDECLUSAGE_TESSFACTOR: - sem->Name = TGSI_SEMANTIC_GENERIC; - sem->Index = 10 * index + 24; - break; - case D3DDECLUSAGE_SAMPLE: - sem->Name = TGSI_SEMANTIC_COUNT; - sem->Index = 0; - break; - default: - unreachable("Invalid DECLUSAGE."); - break; - } -} - -#define NINED3DSTT_1D (D3DSTT_1D >> D3DSP_TEXTURETYPE_SHIFT) -#define NINED3DSTT_2D (D3DSTT_2D >> D3DSP_TEXTURETYPE_SHIFT) -#define NINED3DSTT_VOLUME (D3DSTT_VOLUME >> D3DSP_TEXTURETYPE_SHIFT) -#define NINED3DSTT_CUBE (D3DSTT_CUBE >> D3DSP_TEXTURETYPE_SHIFT) -static inline unsigned -d3dstt_to_tgsi_tex(BYTE sampler_type) -{ - switch (sampler_type) { - case NINED3DSTT_1D: return TGSI_TEXTURE_1D; - case NINED3DSTT_2D: return TGSI_TEXTURE_2D; - case NINED3DSTT_VOLUME: return TGSI_TEXTURE_3D; - case NINED3DSTT_CUBE: return TGSI_TEXTURE_CUBE; - default: - assert(0); - return TGSI_TEXTURE_UNKNOWN; - } -} -static inline unsigned -d3dstt_to_tgsi_tex_shadow(BYTE sampler_type) -{ - switch (sampler_type) { - case NINED3DSTT_1D: return TGSI_TEXTURE_SHADOW1D; - case NINED3DSTT_2D: return TGSI_TEXTURE_SHADOW2D; - case NINED3DSTT_VOLUME: - case NINED3DSTT_CUBE: - default: - assert(0); - return TGSI_TEXTURE_UNKNOWN; - } -} -static inline unsigned -ps1x_sampler_type(const struct nine_shader_info *info, unsigned stage) -{ - boolean shadow = !!(info->sampler_mask_shadow & (1 << stage)); - switch ((info->sampler_ps1xtypes >> (stage * 2)) & 0x3) { - case 1: return shadow ? TGSI_TEXTURE_SHADOW1D : TGSI_TEXTURE_1D; - case 0: return shadow ? TGSI_TEXTURE_SHADOW2D : TGSI_TEXTURE_2D; - case 3: return TGSI_TEXTURE_3D; - default: - return TGSI_TEXTURE_CUBE; - } -} - -static const char * -sm1_sampler_type_name(BYTE sampler_type) -{ - switch (sampler_type) { - case NINED3DSTT_1D: return "1D"; - case NINED3DSTT_2D: return "2D"; - case NINED3DSTT_VOLUME: return "VOLUME"; - case NINED3DSTT_CUBE: return "CUBE"; - default: - return "(D3DSTT_?)"; - } -} - -static inline unsigned -nine_tgsi_to_interp_mode(struct tgsi_declaration_semantic *sem) -{ - switch (sem->Name) { - case TGSI_SEMANTIC_POSITION: - case TGSI_SEMANTIC_NORMAL: - return TGSI_INTERPOLATE_LINEAR; - case TGSI_SEMANTIC_BCOLOR: - case TGSI_SEMANTIC_COLOR: - return TGSI_INTERPOLATE_COLOR; - case TGSI_SEMANTIC_FOG: - case TGSI_SEMANTIC_GENERIC: - case TGSI_SEMANTIC_TEXCOORD: - case TGSI_SEMANTIC_CLIPDIST: - case TGSI_SEMANTIC_CLIPVERTEX: - return TGSI_INTERPOLATE_PERSPECTIVE; - case TGSI_SEMANTIC_EDGEFLAG: - case TGSI_SEMANTIC_FACE: - case TGSI_SEMANTIC_INSTANCEID: - case TGSI_SEMANTIC_PCOORD: - case TGSI_SEMANTIC_PRIMID: - case TGSI_SEMANTIC_PSIZE: - case TGSI_SEMANTIC_VERTEXID: - return TGSI_INTERPOLATE_CONSTANT; - default: - assert(0); - return TGSI_INTERPOLATE_CONSTANT; - } -} - -DECL_SPECIAL(DCL) -{ - struct ureg_program *ureg = tx->ureg; - boolean is_input; - boolean is_sampler; - struct tgsi_declaration_semantic tgsi; - struct sm1_semantic sem; - sm1_read_semantic(tx, &sem); - - is_input = sem.reg.file == D3DSPR_INPUT; - is_sampler = - sem.usage == D3DDECLUSAGE_SAMPLE || sem.reg.file == D3DSPR_SAMPLER; - - DUMP("DCL "); - sm1_dump_dst_param(&sem.reg); - if (is_sampler) - DUMP(" %s\n", sm1_sampler_type_name(sem.sampler_type)); - else - if (tx->version.major >= 3) - DUMP(" %s%i\n", sm1_declusage_names[sem.usage], sem.usage_idx); - else - if (sem.usage | sem.usage_idx) - DUMP(" %u[%u]\n", sem.usage, sem.usage_idx); - else - DUMP("\n"); - - if (is_sampler) { - const unsigned m = 1 << sem.reg.idx; - ureg_DECL_sampler(ureg, sem.reg.idx); - tx->info->sampler_mask |= m; - tx->sampler_targets[sem.reg.idx] = (tx->info->sampler_mask_shadow & m) ? - d3dstt_to_tgsi_tex_shadow(sem.sampler_type) : - d3dstt_to_tgsi_tex(sem.sampler_type); - return D3D_OK; - } - - sm1_declusage_to_tgsi(&tgsi, tx->want_texcoord, &sem); - if (IS_VS) { - if (is_input) { - /* linkage outside of shader with vertex declaration */ - ureg_DECL_vs_input(ureg, sem.reg.idx); - assert(sem.reg.idx < ARRAY_SIZE(tx->info->input_map)); - tx->info->input_map[sem.reg.idx] = sm1_to_nine_declusage(&sem); - tx->info->num_inputs = MAX2(tx->info->num_inputs, sem.reg.idx + 1); - /* NOTE: preserving order in case of indirect access */ - } else - if (tx->version.major >= 3) { - /* SM2 output semantic determined by file */ - assert(sem.reg.mask != 0); - if (sem.usage == D3DDECLUSAGE_POSITIONT) - tx->info->position_t = TRUE; - assert(sem.reg.idx < ARRAY_SIZE(tx->regs.o)); - assert(ureg_dst_is_undef(tx->regs.o[sem.reg.idx]) && "Nine doesn't support yet packing"); - tx->regs.o[sem.reg.idx] = ureg_DECL_output_masked( - ureg, tgsi.Name, tgsi.Index, sem.reg.mask, 0, 1); - nine_record_outputs(tx, sem.usage, sem.usage_idx, sem.reg.mask, sem.reg.idx); - if (tx->info->process_vertices && sem.usage == D3DDECLUSAGE_POSITION && sem.usage_idx == 0) { - tx->regs.oPos_out = tx->regs.o[sem.reg.idx]; - tx->regs.o[sem.reg.idx] = ureg_DECL_temporary(ureg); - tx->regs.oPos = tx->regs.o[sem.reg.idx]; - } - - if (tgsi.Name == TGSI_SEMANTIC_PSIZE) { - tx->regs.o[sem.reg.idx] = ureg_DECL_temporary(ureg); - tx->regs.oPts = tx->regs.o[sem.reg.idx]; - } - } - } else { - if (is_input && tx->version.major >= 3) { - unsigned interp_location = 0; - /* SM3 only, SM2 input semantic determined by file */ - assert(sem.reg.idx < ARRAY_SIZE(tx->regs.v)); - assert(ureg_src_is_undef(tx->regs.v[sem.reg.idx]) && "Nine doesn't support yet packing"); - /* PositionT and tessfactor forbidden */ - if (sem.usage == D3DDECLUSAGE_POSITIONT || sem.usage == D3DDECLUSAGE_TESSFACTOR) - return D3DERR_INVALIDCALL; - - if (tgsi.Name == TGSI_SEMANTIC_POSITION) { - /* Position0 is forbidden (likely because vPos already does that) */ - if (sem.usage == D3DDECLUSAGE_POSITION) - return D3DERR_INVALIDCALL; - /* Following code is for depth */ - tx->regs.v[sem.reg.idx] = nine_get_position_input(tx); - return D3D_OK; - } - - if (sem.reg.mod & NINED3DSPDM_CENTROID || - (tgsi.Name == TGSI_SEMANTIC_COLOR && tx->info->force_color_in_centroid)) - interp_location = TGSI_INTERPOLATE_LOC_CENTROID; - - tx->regs.v[sem.reg.idx] = ureg_DECL_fs_input_cyl_centroid( - ureg, tgsi.Name, tgsi.Index, - nine_tgsi_to_interp_mode(&tgsi), - 0, /* cylwrap */ - interp_location, 0, 1); - } else - if (!is_input && 0) { /* declare in COLOROUT/DEPTHOUT case */ - /* FragColor or FragDepth */ - assert(sem.reg.mask != 0); - ureg_DECL_output_masked(ureg, tgsi.Name, tgsi.Index, sem.reg.mask, - 0, 1); - } - } - return D3D_OK; -} - -DECL_SPECIAL(DEF) -{ - tx_set_lconstf(tx, tx->insn.dst[0].idx, tx->insn.src[0].imm.f); - return D3D_OK; -} - -DECL_SPECIAL(DEFB) -{ - tx_set_lconstb(tx, tx->insn.dst[0].idx, tx->insn.src[0].imm.b); - return D3D_OK; -} - -DECL_SPECIAL(DEFI) -{ - tx_set_lconsti(tx, tx->insn.dst[0].idx, tx->insn.src[0].imm.i); - return D3D_OK; -} - -DECL_SPECIAL(POW) -{ - struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); - struct ureg_src src[2] = { - tx_src_param(tx, &tx->insn.src[0]), - tx_src_param(tx, &tx->insn.src[1]) - }; - ureg_POW(tx->ureg, dst, ureg_abs(src[0]), src[1]); - return D3D_OK; -} - -/* Tests results on Win 10: - * NV (NVIDIA GeForce GT 635M) - * AMD (AMD Radeon HD 7730M) - * INTEL (Intel(R) HD Graphics 4000) - * PS2 and PS3: - * RCP and RSQ can generate inf on NV and AMD. - * RCP and RSQ are clamped on INTEL (+- FLT_MAX), - * NV: log not clamped - * AMD: log(0) is -FLT_MAX (but log(inf) is inf) - * INTEL: log(0) is -FLT_MAX and log(inf) is 127 - * All devices have 0*anything = 0 - * - * INTEL VS2 and VS3: same behaviour. - * Some differences VS2 and VS3 for constants defined with inf/NaN. - * While PS3, VS3 and PS2 keep NaN and Inf shader constants without change, - * VS2 seems to clamp to zero (may be test failure). - * AMD VS2: unknown, VS3: very likely behaviour of PS3 - * NV VS2 and VS3: very likely behaviour of PS3 - * For both, Inf in VS becomes NaN is PS - * "Very likely" because the test was less extensive. - * - * Thus all clamping can be removed for shaders 2 and 3, - * as long as 0*anything = 0. - * Else clamps to enforce 0*anything = 0 (anything being then - * neither inf or NaN, the user being unlikely to pass them - * as constant). - * The status for VS1 and PS1 is unknown. - */ - -DECL_SPECIAL(RCP) -{ - struct ureg_program *ureg = tx->ureg; - struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); - struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]); - struct ureg_dst tmp = tx->mul_zero_wins ? dst : tx_scratch(tx); - ureg_RCP(ureg, tmp, src); - if (!tx->mul_zero_wins) { - /* FLT_MAX has issues with Rayman */ - ureg_MIN(ureg, tmp, ureg_imm1f(ureg, FLT_MAX/2.f), ureg_src(tmp)); - ureg_MAX(ureg, dst, ureg_imm1f(ureg, -FLT_MAX/2.f), ureg_src(tmp)); - } - return D3D_OK; -} - -DECL_SPECIAL(RSQ) -{ - struct ureg_program *ureg = tx->ureg; - struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); - struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]); - struct ureg_dst tmp = tx->mul_zero_wins ? dst : tx_scratch(tx); - ureg_RSQ(ureg, tmp, ureg_abs(src)); - if (!tx->mul_zero_wins) - ureg_MIN(ureg, dst, ureg_imm1f(ureg, FLT_MAX), ureg_src(tmp)); - return D3D_OK; -} - -DECL_SPECIAL(LOG) -{ - struct ureg_program *ureg = tx->ureg; - struct ureg_dst tmp = tx_scratch_scalar(tx); - struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); - struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]); - ureg_LG2(ureg, tmp, ureg_abs(src)); - if (tx->mul_zero_wins) { - ureg_MOV(ureg, dst, tx_src_scalar(tmp)); - } else { - ureg_MAX(ureg, dst, ureg_imm1f(ureg, -FLT_MAX), tx_src_scalar(tmp)); - } - return D3D_OK; -} - -DECL_SPECIAL(LIT) -{ - struct ureg_program *ureg = tx->ureg; - struct ureg_dst tmp = tx_scratch(tx); - struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); - struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]); - ureg_LIT(ureg, tmp, src); - /* d3d9 LIT is the same than gallium LIT. One difference is that d3d9 - * states that dst.z is 0 when src.y <= 0. Gallium definition can assign - * it 0^0 if src.w=0, which value is driver dependent. */ - ureg_CMP(ureg, ureg_writemask(dst, TGSI_WRITEMASK_Z), - ureg_negate(ureg_scalar(src, TGSI_SWIZZLE_Y)), - ureg_src(tmp), ureg_imm1f(ureg, 0.0f)); - ureg_MOV(ureg, ureg_writemask(dst, TGSI_WRITEMASK_XYW), ureg_src(tmp)); - return D3D_OK; -} - -DECL_SPECIAL(NRM) -{ - struct ureg_program *ureg = tx->ureg; - struct ureg_dst tmp = tx_scratch_scalar(tx); - struct ureg_src nrm = tx_src_scalar(tmp); - struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); - struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]); - ureg_DP3(ureg, tmp, src, src); - ureg_RSQ(ureg, tmp, nrm); - if (!tx->mul_zero_wins) - ureg_MIN(ureg, tmp, ureg_imm1f(ureg, FLT_MAX), nrm); - ureg_MUL(ureg, dst, src, nrm); - return D3D_OK; -} - -DECL_SPECIAL(DP2ADD) -{ - struct ureg_dst tmp = tx_scratch_scalar(tx); - struct ureg_src dp2 = tx_src_scalar(tmp); - struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); - struct ureg_src src[3]; - int i; - for (i = 0; i < 3; ++i) - src[i] = tx_src_param(tx, &tx->insn.src[i]); - assert_replicate_swizzle(&src[2]); - - ureg_DP2(tx->ureg, tmp, src[0], src[1]); - ureg_ADD(tx->ureg, dst, src[2], dp2); - - return D3D_OK; -} - -DECL_SPECIAL(TEXCOORD) -{ - struct ureg_program *ureg = tx->ureg; - const unsigned s = tx->insn.dst[0].idx; - struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); - - tx_texcoord_alloc(tx, s); - ureg_MOV(ureg, ureg_writemask(ureg_saturate(dst), TGSI_WRITEMASK_XYZ), tx->regs.vT[s]); - ureg_MOV(ureg, ureg_writemask(dst, TGSI_WRITEMASK_W), ureg_imm1f(tx->ureg, 1.0f)); - - return D3D_OK; -} - -DECL_SPECIAL(TEXCOORD_ps14) -{ - struct ureg_program *ureg = tx->ureg; - struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]); - struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); - - assert(tx->insn.src[0].file == D3DSPR_TEXTURE); - - ureg_MOV(ureg, dst, src); - - return D3D_OK; -} - -DECL_SPECIAL(TEXKILL) -{ - struct ureg_src reg; - - if (tx->version.major > 1 || tx->version.minor > 3) { - reg = tx_dst_param_as_src(tx, &tx->insn.dst[0]); - } else { - tx_texcoord_alloc(tx, tx->insn.dst[0].idx); - reg = tx->regs.vT[tx->insn.dst[0].idx]; - } - if (tx->version.major < 2) - reg = ureg_swizzle(reg, NINE_SWIZZLE4(X,Y,Z,Z)); - ureg_KILL_IF(tx->ureg, reg); - - return D3D_OK; -} - -DECL_SPECIAL(TEXBEM) -{ - struct ureg_program *ureg = tx->ureg; - struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); - struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]); /* t[n] */ - struct ureg_dst tmp, tmp2, texcoord; - struct ureg_src sample, m00, m01, m10, m11, c8m, c16m2; - struct ureg_src bumpenvlscale, bumpenvloffset; - const int m = tx->insn.dst[0].idx; - - assert(tx->version.major == 1); - - sample = ureg_DECL_sampler(ureg, m); - tx->info->sampler_mask |= 1 << m; - - tx_texcoord_alloc(tx, m); - - tmp = tx_scratch(tx); - tmp2 = tx_scratch(tx); - texcoord = tx_scratch(tx); - /* - * Bump-env-matrix: - * 00 is X - * 01 is Y - * 10 is Z - * 11 is W - */ - c8m = nine_float_constant_src(tx, 8+m); - c16m2 = nine_float_constant_src(tx, 8+8+m/2); - - m00 = NINE_APPLY_SWIZZLE(c8m, X); - m01 = NINE_APPLY_SWIZZLE(c8m, Y); - m10 = NINE_APPLY_SWIZZLE(c8m, Z); - m11 = NINE_APPLY_SWIZZLE(c8m, W); - - /* These two attributes are packed as X=scale0 Y=offset0 Z=scale1 W=offset1 etc */ - if (m % 2 == 0) { - bumpenvlscale = NINE_APPLY_SWIZZLE(c16m2, X); - bumpenvloffset = NINE_APPLY_SWIZZLE(c16m2, Y); - } else { - bumpenvlscale = NINE_APPLY_SWIZZLE(c16m2, Z); - bumpenvloffset = NINE_APPLY_SWIZZLE(c16m2, W); - } - - apply_ps1x_projection(tx, texcoord, tx->regs.vT[m], m); - - /* u' = TextureCoordinates(stage m)u + D3DTSS_BUMPENVMAT00(stage m)*t(n)R */ - ureg_MAD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), m00, - NINE_APPLY_SWIZZLE(src, X), ureg_src(texcoord)); - /* u' = u' + D3DTSS_BUMPENVMAT10(stage m)*t(n)G */ - ureg_MAD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), m10, - NINE_APPLY_SWIZZLE(src, Y), - NINE_APPLY_SWIZZLE(ureg_src(tmp), X)); - - /* v' = TextureCoordinates(stage m)v + D3DTSS_BUMPENVMAT01(stage m)*t(n)R */ - ureg_MAD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Y), m01, - NINE_APPLY_SWIZZLE(src, X), ureg_src(texcoord)); - /* v' = v' + D3DTSS_BUMPENVMAT11(stage m)*t(n)G*/ - ureg_MAD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Y), m11, - NINE_APPLY_SWIZZLE(src, Y), - NINE_APPLY_SWIZZLE(ureg_src(tmp), Y)); - - /* Now the texture coordinates are in tmp.xy */ - - if (tx->insn.opcode == D3DSIO_TEXBEM) { - ureg_TEX(ureg, dst, ps1x_sampler_type(tx->info, m), ureg_src(tmp), sample); - } else if (tx->insn.opcode == D3DSIO_TEXBEML) { - /* t(m)RGBA = t(m)RGBA * [(t(n)B * D3DTSS_BUMPENVLSCALE(stage m)) + D3DTSS_BUMPENVLOFFSET(stage m)] */ - ureg_TEX(ureg, tmp, ps1x_sampler_type(tx->info, m), ureg_src(tmp), sample); - ureg_MAD(ureg, tmp2, NINE_APPLY_SWIZZLE(src, Z), - bumpenvlscale, bumpenvloffset); - ureg_MUL(ureg, dst, ureg_src(tmp), ureg_src(tmp2)); - } - - tx->info->bumpenvmat_needed = 1; - - return D3D_OK; -} - -DECL_SPECIAL(TEXREG2AR) -{ - struct ureg_program *ureg = tx->ureg; - struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); - struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]); /* t[n] */ - struct ureg_src sample; - const int m = tx->insn.dst[0].idx; - ASSERTED const int n = tx->insn.src[0].idx; - assert(m >= 0 && m > n); - - sample = ureg_DECL_sampler(ureg, m); - tx->info->sampler_mask |= 1 << m; - ureg_TEX(ureg, dst, ps1x_sampler_type(tx->info, m), ureg_swizzle(src, NINE_SWIZZLE4(W,X,X,X)), sample); - - return D3D_OK; -} - -DECL_SPECIAL(TEXREG2GB) -{ - struct ureg_program *ureg = tx->ureg; - struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); - struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]); /* t[n] */ - struct ureg_src sample; - const int m = tx->insn.dst[0].idx; - ASSERTED const int n = tx->insn.src[0].idx; - assert(m >= 0 && m > n); - - sample = ureg_DECL_sampler(ureg, m); - tx->info->sampler_mask |= 1 << m; - ureg_TEX(ureg, dst, ps1x_sampler_type(tx->info, m), ureg_swizzle(src, NINE_SWIZZLE4(Y,Z,Z,Z)), sample); - - return D3D_OK; -} - -DECL_SPECIAL(TEXM3x2PAD) -{ - return D3D_OK; /* this is just padding */ -} - -DECL_SPECIAL(TEXM3x2TEX) -{ - struct ureg_program *ureg = tx->ureg; - struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); - struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]); /* t[n] */ - struct ureg_src sample; - const int m = tx->insn.dst[0].idx - 1; - ASSERTED const int n = tx->insn.src[0].idx; - assert(m >= 0 && m > n); - - tx_texcoord_alloc(tx, m); - tx_texcoord_alloc(tx, m+1); - - /* performs the matrix multiplication */ - ureg_DP3(ureg, ureg_writemask(dst, TGSI_WRITEMASK_X), tx->regs.vT[m], src); - ureg_DP3(ureg, ureg_writemask(dst, TGSI_WRITEMASK_Y), tx->regs.vT[m+1], src); - - sample = ureg_DECL_sampler(ureg, m + 1); - tx->info->sampler_mask |= 1 << (m + 1); - ureg_TEX(ureg, dst, ps1x_sampler_type(tx->info, m + 1), ureg_src(dst), sample); - - return D3D_OK; -} - -DECL_SPECIAL(TEXM3x3PAD) -{ - return D3D_OK; /* this is just padding */ -} - -DECL_SPECIAL(TEXM3x3SPEC) -{ - struct ureg_program *ureg = tx->ureg; - struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); - struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]); /* t[n] */ - struct ureg_src E = tx_src_param(tx, &tx->insn.src[1]); - struct ureg_src sample; - struct ureg_dst tmp; - const int m = tx->insn.dst[0].idx - 2; - ASSERTED const int n = tx->insn.src[0].idx; - assert(m >= 0 && m > n); - - tx_texcoord_alloc(tx, m); - tx_texcoord_alloc(tx, m+1); - tx_texcoord_alloc(tx, m+2); - - ureg_DP3(ureg, ureg_writemask(dst, TGSI_WRITEMASK_X), tx->regs.vT[m], src); - ureg_DP3(ureg, ureg_writemask(dst, TGSI_WRITEMASK_Y), tx->regs.vT[m+1], src); - ureg_DP3(ureg, ureg_writemask(dst, TGSI_WRITEMASK_Z), tx->regs.vT[m+2], src); - - sample = ureg_DECL_sampler(ureg, m + 2); - tx->info->sampler_mask |= 1 << (m + 2); - tmp = ureg_writemask(tx_scratch(tx), TGSI_WRITEMASK_XYZ); - - /* At this step, dst = N = (u', w', z'). - * We want dst to be the texture sampled at (u'', w'', z''), with - * (u'', w'', z'') = 2 * (N.E / N.N) * N - E */ - ureg_DP3(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), ureg_src(dst), ureg_src(dst)); - ureg_RCP(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X)); - /* at this step tmp.x = 1/N.N */ - ureg_DP3(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Y), ureg_src(dst), E); - /* at this step tmp.y = N.E */ - ureg_MUL(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X), ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_Y)); - /* at this step tmp.x = N.E/N.N */ - ureg_MUL(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X), ureg_imm1f(ureg, 2.0f)); - ureg_MUL(ureg, tmp, ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X), ureg_src(dst)); - /* at this step tmp.xyz = 2 * (N.E / N.N) * N */ - ureg_ADD(ureg, tmp, ureg_src(tmp), ureg_negate(E)); - ureg_TEX(ureg, dst, ps1x_sampler_type(tx->info, m + 2), ureg_src(tmp), sample); - - return D3D_OK; -} - -DECL_SPECIAL(TEXREG2RGB) -{ - struct ureg_program *ureg = tx->ureg; - struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); - struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]); /* t[n] */ - struct ureg_src sample; - const int m = tx->insn.dst[0].idx; - ASSERTED const int n = tx->insn.src[0].idx; - assert(m >= 0 && m > n); - - sample = ureg_DECL_sampler(ureg, m); - tx->info->sampler_mask |= 1 << m; - ureg_TEX(ureg, dst, ps1x_sampler_type(tx->info, m), src, sample); - - return D3D_OK; -} - -DECL_SPECIAL(TEXDP3TEX) -{ - struct ureg_program *ureg = tx->ureg; - struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); - struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]); /* t[n] */ - struct ureg_dst tmp; - struct ureg_src sample; - const int m = tx->insn.dst[0].idx; - ASSERTED const int n = tx->insn.src[0].idx; - assert(m >= 0 && m > n); - - tx_texcoord_alloc(tx, m); - - tmp = tx_scratch(tx); - ureg_DP3(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), tx->regs.vT[m], src); - ureg_MOV(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_YZ), ureg_imm1f(ureg, 0.0f)); - - sample = ureg_DECL_sampler(ureg, m); - tx->info->sampler_mask |= 1 << m; - ureg_TEX(ureg, dst, ps1x_sampler_type(tx->info, m), ureg_src(tmp), sample); - - return D3D_OK; -} - -DECL_SPECIAL(TEXM3x2DEPTH) -{ - struct ureg_program *ureg = tx->ureg; - struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]); /* t[n] */ - struct ureg_dst tmp; - const int m = tx->insn.dst[0].idx - 1; - ASSERTED const int n = tx->insn.src[0].idx; - assert(m >= 0 && m > n); - - tx_texcoord_alloc(tx, m); - tx_texcoord_alloc(tx, m+1); - - tmp = tx_scratch(tx); - - /* performs the matrix multiplication */ - ureg_DP3(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), tx->regs.vT[m], src); - ureg_DP3(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Y), tx->regs.vT[m+1], src); - - ureg_RCP(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Z), ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_Y)); - /* tmp.x = 'z', tmp.y = 'w', tmp.z = 1/'w'. */ - ureg_MUL(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X), ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_Z)); - /* res = 'w' == 0 ? 1.0 : z/w */ - ureg_CMP(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), ureg_negate(ureg_abs(ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_Y))), - ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X), ureg_imm1f(ureg, 1.0f)); - /* replace the depth for depth testing with the result */ - tx->regs.oDepth = ureg_DECL_output_masked(ureg, TGSI_SEMANTIC_POSITION, 0, - TGSI_WRITEMASK_Z, 0, 1); - ureg_MOV(ureg, tx->regs.oDepth, ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X)); - /* note that we write nothing to the destination, since it's disallowed to use it afterward */ - return D3D_OK; -} - -DECL_SPECIAL(TEXDP3) -{ - struct ureg_program *ureg = tx->ureg; - struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); - struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]); /* t[n] */ - const int m = tx->insn.dst[0].idx; - ASSERTED const int n = tx->insn.src[0].idx; - assert(m >= 0 && m > n); - - tx_texcoord_alloc(tx, m); - - ureg_DP3(ureg, dst, tx->regs.vT[m], src); - - return D3D_OK; -} - -DECL_SPECIAL(TEXM3x3) -{ - struct ureg_program *ureg = tx->ureg; - struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); - struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]); /* t[n] */ - struct ureg_src sample; - struct ureg_dst E, tmp; - const int m = tx->insn.dst[0].idx - 2; - ASSERTED const int n = tx->insn.src[0].idx; - assert(m >= 0 && m > n); - - tx_texcoord_alloc(tx, m); - tx_texcoord_alloc(tx, m+1); - tx_texcoord_alloc(tx, m+2); - - ureg_DP3(ureg, ureg_writemask(dst, TGSI_WRITEMASK_X), tx->regs.vT[m], src); - ureg_DP3(ureg, ureg_writemask(dst, TGSI_WRITEMASK_Y), tx->regs.vT[m+1], src); - ureg_DP3(ureg, ureg_writemask(dst, TGSI_WRITEMASK_Z), tx->regs.vT[m+2], src); - - switch (tx->insn.opcode) { - case D3DSIO_TEXM3x3: - ureg_MOV(ureg, ureg_writemask(dst, TGSI_WRITEMASK_W), ureg_imm1f(ureg, 1.0f)); - break; - case D3DSIO_TEXM3x3TEX: - sample = ureg_DECL_sampler(ureg, m + 2); - tx->info->sampler_mask |= 1 << (m + 2); - ureg_TEX(ureg, dst, ps1x_sampler_type(tx->info, m + 2), ureg_src(dst), sample); - break; - case D3DSIO_TEXM3x3VSPEC: - sample = ureg_DECL_sampler(ureg, m + 2); - tx->info->sampler_mask |= 1 << (m + 2); - E = tx_scratch(tx); - tmp = ureg_writemask(tx_scratch(tx), TGSI_WRITEMASK_XYZ); - ureg_MOV(ureg, ureg_writemask(E, TGSI_WRITEMASK_X), ureg_scalar(tx->regs.vT[m], TGSI_SWIZZLE_W)); - ureg_MOV(ureg, ureg_writemask(E, TGSI_WRITEMASK_Y), ureg_scalar(tx->regs.vT[m+1], TGSI_SWIZZLE_W)); - ureg_MOV(ureg, ureg_writemask(E, TGSI_WRITEMASK_Z), ureg_scalar(tx->regs.vT[m+2], TGSI_SWIZZLE_W)); - /* At this step, dst = N = (u', w', z'). - * We want dst to be the texture sampled at (u'', w'', z''), with - * (u'', w'', z'') = 2 * (N.E / N.N) * N - E */ - ureg_DP3(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), ureg_src(dst), ureg_src(dst)); - ureg_RCP(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X)); - /* at this step tmp.x = 1/N.N */ - ureg_DP3(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Y), ureg_src(dst), ureg_src(E)); - /* at this step tmp.y = N.E */ - ureg_MUL(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X), ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_Y)); - /* at this step tmp.x = N.E/N.N */ - ureg_MUL(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X), ureg_imm1f(ureg, 2.0f)); - ureg_MUL(ureg, tmp, ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X), ureg_src(dst)); - /* at this step tmp.xyz = 2 * (N.E / N.N) * N */ - ureg_ADD(ureg, tmp, ureg_src(tmp), ureg_negate(ureg_src(E))); - ureg_TEX(ureg, dst, ps1x_sampler_type(tx->info, m + 2), ureg_src(tmp), sample); - break; - default: - return D3DERR_INVALIDCALL; - } - return D3D_OK; -} - -DECL_SPECIAL(TEXDEPTH) -{ - struct ureg_program *ureg = tx->ureg; - struct ureg_dst r5; - struct ureg_src r5r, r5g; - - assert(tx->insn.dst[0].idx == 5); /* instruction must get r5 here */ - - /* we must replace the depth by r5.g == 0 ? 1.0f : r5.r/r5.g. - * r5 won't be used afterward, thus we can use r5.ba */ - r5 = tx->regs.r[5]; - r5r = ureg_scalar(ureg_src(r5), TGSI_SWIZZLE_X); - r5g = ureg_scalar(ureg_src(r5), TGSI_SWIZZLE_Y); - - ureg_RCP(ureg, ureg_writemask(r5, TGSI_WRITEMASK_Z), r5g); - ureg_MUL(ureg, ureg_writemask(r5, TGSI_WRITEMASK_X), r5r, ureg_scalar(ureg_src(r5), TGSI_SWIZZLE_Z)); - /* r5.r = r/g */ - ureg_CMP(ureg, ureg_writemask(r5, TGSI_WRITEMASK_X), ureg_negate(ureg_abs(r5g)), - r5r, ureg_imm1f(ureg, 1.0f)); - /* replace the depth for depth testing with the result */ - tx->regs.oDepth = ureg_DECL_output_masked(ureg, TGSI_SEMANTIC_POSITION, 0, - TGSI_WRITEMASK_Z, 0, 1); - ureg_MOV(ureg, tx->regs.oDepth, r5r); - - return D3D_OK; -} - -DECL_SPECIAL(BEM) -{ - struct ureg_program *ureg = tx->ureg; - struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); - struct ureg_src src0 = tx_src_param(tx, &tx->insn.src[0]); - struct ureg_src src1 = tx_src_param(tx, &tx->insn.src[1]); - struct ureg_src m00, m01, m10, m11, c8m; - const int m = tx->insn.dst[0].idx; - struct ureg_dst tmp; - /* - * Bump-env-matrix: - * 00 is X - * 01 is Y - * 10 is Z - * 11 is W - */ - c8m = nine_float_constant_src(tx, 8+m); - m00 = NINE_APPLY_SWIZZLE(c8m, X); - m01 = NINE_APPLY_SWIZZLE(c8m, Y); - m10 = NINE_APPLY_SWIZZLE(c8m, Z); - m11 = NINE_APPLY_SWIZZLE(c8m, W); - /* dest.r = src0.r + D3DTSS_BUMPENVMAT00(stage n) * src1.r */ - ureg_MAD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), m00, - NINE_APPLY_SWIZZLE(src1, X), NINE_APPLY_SWIZZLE(src0, X)); - /* dest.r = dest.r + D3DTSS_BUMPENVMAT10(stage n) * src1.g; */ - ureg_MAD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), m10, - NINE_APPLY_SWIZZLE(src1, Y), NINE_APPLY_SWIZZLE(ureg_src(tmp), X)); - - /* dest.g = src0.g + D3DTSS_BUMPENVMAT01(stage n) * src1.r */ - ureg_MAD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Y), m01, - NINE_APPLY_SWIZZLE(src1, X), src0); - /* dest.g = dest.g + D3DTSS_BUMPENVMAT11(stage n) * src1.g */ - ureg_MAD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Y), m11, - NINE_APPLY_SWIZZLE(src1, Y), NINE_APPLY_SWIZZLE(ureg_src(tmp), Y)); - ureg_MOV(ureg, ureg_writemask(dst, TGSI_WRITEMASK_XY), ureg_src(tmp)); - - tx->info->bumpenvmat_needed = 1; - - return D3D_OK; -} - -DECL_SPECIAL(TEXLD) -{ - struct ureg_program *ureg = tx->ureg; - unsigned target; - struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); - struct ureg_src src[2] = { - tx_src_param(tx, &tx->insn.src[0]), - tx_src_param(tx, &tx->insn.src[1]) - }; - assert(tx->insn.src[1].idx >= 0 && - tx->insn.src[1].idx < ARRAY_SIZE(tx->sampler_targets)); - target = tx->sampler_targets[tx->insn.src[1].idx]; - - switch (tx->insn.flags) { - case 0: - ureg_TEX(ureg, dst, target, src[0], src[1]); - break; - case NINED3DSI_TEXLD_PROJECT: - ureg_TXP(ureg, dst, target, src[0], src[1]); - break; - case NINED3DSI_TEXLD_BIAS: - ureg_TXB(ureg, dst, target, src[0], src[1]); - break; - default: - assert(0); - return D3DERR_INVALIDCALL; - } - return D3D_OK; -} - -DECL_SPECIAL(TEXLD_14) -{ - struct ureg_program *ureg = tx->ureg; - struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); - struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]); - const unsigned s = tx->insn.dst[0].idx; - const unsigned t = ps1x_sampler_type(tx->info, s); - - tx->info->sampler_mask |= 1 << s; - ureg_TEX(ureg, dst, t, src, ureg_DECL_sampler(ureg, s)); - - return D3D_OK; -} - -DECL_SPECIAL(TEX) -{ - struct ureg_program *ureg = tx->ureg; - const unsigned s = tx->insn.dst[0].idx; - const unsigned t = ps1x_sampler_type(tx->info, s); - struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); - struct ureg_src src[2]; - - tx_texcoord_alloc(tx, s); - - src[0] = tx->regs.vT[s]; - src[1] = ureg_DECL_sampler(ureg, s); - tx->info->sampler_mask |= 1 << s; - - TEX_with_ps1x_projection(tx, dst, t, src[0], src[1], s); - - return D3D_OK; -} - -DECL_SPECIAL(TEXLDD) -{ - unsigned target; - struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); - struct ureg_src src[4] = { - tx_src_param(tx, &tx->insn.src[0]), - tx_src_param(tx, &tx->insn.src[1]), - tx_src_param(tx, &tx->insn.src[2]), - tx_src_param(tx, &tx->insn.src[3]) - }; - assert(tx->insn.src[1].idx >= 0 && - tx->insn.src[1].idx < ARRAY_SIZE(tx->sampler_targets)); - target = tx->sampler_targets[tx->insn.src[1].idx]; - - ureg_TXD(tx->ureg, dst, target, src[0], src[2], src[3], src[1]); - return D3D_OK; -} - -DECL_SPECIAL(TEXLDL) -{ - unsigned target; - struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); - struct ureg_src src[2] = { - tx_src_param(tx, &tx->insn.src[0]), - tx_src_param(tx, &tx->insn.src[1]) - }; - assert(tx->insn.src[1].idx >= 0 && - tx->insn.src[1].idx < ARRAY_SIZE(tx->sampler_targets)); - target = tx->sampler_targets[tx->insn.src[1].idx]; - - ureg_TXL(tx->ureg, dst, target, src[0], src[1]); - return D3D_OK; -} - -DECL_SPECIAL(SETP) -{ - const unsigned cmp_op = sm1_insn_flags_to_tgsi_setop(tx->insn.flags); - struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]); - struct ureg_src src[2] = { - tx_src_param(tx, &tx->insn.src[0]), - tx_src_param(tx, &tx->insn.src[1]) - }; - ureg_insn(tx->ureg, cmp_op, &dst, 1, src, 2, 0); - return D3D_OK; -} - -DECL_SPECIAL(BREAKP) -{ - struct ureg_src src = tx_src_param(tx, &tx->insn.src[0]); - ureg_IF(tx->ureg, src, tx_cond(tx)); - ureg_BRK(tx->ureg); - tx_endcond(tx); - ureg_ENDIF(tx->ureg); - return D3D_OK; -} - -DECL_SPECIAL(PHASE) -{ - return D3D_OK; /* we don't care about phase */ -} - -DECL_SPECIAL(COMMENT) -{ - return D3D_OK; /* nothing to do */ -} - - -#define _OPI(o,t,vv1,vv2,pv1,pv2,d,s,h) \ - { D3DSIO_##o, TGSI_OPCODE_##t, { vv1, vv2 }, { pv1, pv2, }, d, s, h } - -static const struct sm1_op_info inst_table[] = -{ - _OPI(NOP, NOP, V(0,0), V(3,0), V(0,0), V(3,0), 0, 0, SPECIAL(NOP)), /* 0 */ - _OPI(MOV, MOV, V(0,0), V(3,0), V(0,0), V(3,0), 1, 1, NULL), - _OPI(ADD, ADD, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, NULL), /* 2 */ - _OPI(SUB, NOP, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, SPECIAL(SUB)), /* 3 */ - _OPI(MAD, MAD, V(0,0), V(3,0), V(0,0), V(3,0), 1, 3, NULL), /* 4 */ - _OPI(MUL, MUL, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, NULL), /* 5 */ - _OPI(RCP, RCP, V(0,0), V(3,0), V(0,0), V(3,0), 1, 1, SPECIAL(RCP)), /* 6 */ - _OPI(RSQ, RSQ, V(0,0), V(3,0), V(0,0), V(3,0), 1, 1, SPECIAL(RSQ)), /* 7 */ - _OPI(DP3, DP3, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, NULL), /* 8 */ - _OPI(DP4, DP4, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, NULL), /* 9 */ - _OPI(MIN, MIN, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, NULL), /* 10 */ - _OPI(MAX, MAX, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, NULL), /* 11 */ - _OPI(SLT, SLT, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, NULL), /* 12 */ - _OPI(SGE, SGE, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, NULL), /* 13 */ - _OPI(EXP, EX2, V(0,0), V(3,0), V(0,0), V(3,0), 1, 1, NULL), /* 14 */ - _OPI(LOG, LG2, V(0,0), V(3,0), V(0,0), V(3,0), 1, 1, SPECIAL(LOG)), /* 15 */ - _OPI(LIT, LIT, V(0,0), V(3,0), V(0,0), V(0,0), 1, 1, SPECIAL(LIT)), /* 16 */ - _OPI(DST, DST, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, NULL), /* 17 */ - _OPI(LRP, LRP, V(0,0), V(3,0), V(0,0), V(3,0), 1, 3, NULL), /* 18 */ - _OPI(FRC, FRC, V(0,0), V(3,0), V(0,0), V(3,0), 1, 1, NULL), /* 19 */ - - _OPI(M4x4, NOP, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, SPECIAL(M4x4)), - _OPI(M4x3, NOP, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, SPECIAL(M4x3)), - _OPI(M3x4, NOP, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, SPECIAL(M3x4)), - _OPI(M3x3, NOP, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, SPECIAL(M3x3)), - _OPI(M3x2, NOP, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, SPECIAL(M3x2)), - - _OPI(CALL, CAL, V(2,0), V(3,0), V(2,1), V(3,0), 0, 1, SPECIAL(CALL)), - _OPI(CALLNZ, CAL, V(2,0), V(3,0), V(2,1), V(3,0), 0, 2, SPECIAL(CALLNZ)), - _OPI(LOOP, BGNLOOP, V(2,0), V(3,0), V(3,0), V(3,0), 0, 2, SPECIAL(LOOP)), - _OPI(RET, RET, V(2,0), V(3,0), V(2,1), V(3,0), 0, 0, SPECIAL(RET)), - _OPI(ENDLOOP, ENDLOOP, V(2,0), V(3,0), V(3,0), V(3,0), 0, 0, SPECIAL(ENDLOOP)), - _OPI(LABEL, NOP, V(2,0), V(3,0), V(2,1), V(3,0), 0, 1, SPECIAL(LABEL)), - - _OPI(DCL, NOP, V(0,0), V(3,0), V(0,0), V(3,0), 0, 0, SPECIAL(DCL)), - - _OPI(POW, POW, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, SPECIAL(POW)), - _OPI(CRS, NOP, V(0,0), V(3,0), V(0,0), V(3,0), 1, 2, SPECIAL(XPD)), /* XXX: .w */ - _OPI(SGN, SSG, V(2,0), V(3,0), V(0,0), V(0,0), 1, 3, SPECIAL(SGN)), /* ignore src1,2 */ - _OPI(ABS, NOP, V(0,0), V(3,0), V(0,0), V(3,0), 1, 1, SPECIAL(ABS)), - _OPI(NRM, NOP, V(0,0), V(3,0), V(0,0), V(3,0), 1, 1, SPECIAL(NRM)), /* NRM doesn't fit */ - - _OPI(SINCOS, NOP, V(2,0), V(2,1), V(2,0), V(2,1), 1, 3, SPECIAL(SINCOS)), - _OPI(SINCOS, NOP, V(3,0), V(3,0), V(3,0), V(3,0), 1, 1, SPECIAL(SINCOS)), - - /* More flow control */ - _OPI(REP, NOP, V(2,0), V(3,0), V(2,1), V(3,0), 0, 1, SPECIAL(REP)), - _OPI(ENDREP, NOP, V(2,0), V(3,0), V(2,1), V(3,0), 0, 0, SPECIAL(ENDREP)), - _OPI(IF, IF, V(2,0), V(3,0), V(2,1), V(3,0), 0, 1, SPECIAL(IF)), - _OPI(IFC, IF, V(2,1), V(3,0), V(2,1), V(3,0), 0, 2, SPECIAL(IFC)), - _OPI(ELSE, ELSE, V(2,0), V(3,0), V(2,1), V(3,0), 0, 0, SPECIAL(ELSE)), - _OPI(ENDIF, ENDIF, V(2,0), V(3,0), V(2,1), V(3,0), 0, 0, SPECIAL(ENDIF)), - _OPI(BREAK, BRK, V(2,1), V(3,0), V(2,1), V(3,0), 0, 0, NULL), - _OPI(BREAKC, NOP, V(2,1), V(3,0), V(2,1), V(3,0), 0, 2, SPECIAL(BREAKC)), - /* we don't write to the address register, but a normal register (copied - * when needed to the address register), thus we don't use ARR */ - _OPI(MOVA, MOV, V(2,0), V(3,0), V(0,0), V(0,0), 1, 1, NULL), - - _OPI(DEFB, NOP, V(0,0), V(3,0) , V(0,0), V(3,0) , 1, 0, SPECIAL(DEFB)), - _OPI(DEFI, NOP, V(0,0), V(3,0) , V(0,0), V(3,0) , 1, 0, SPECIAL(DEFI)), - - _OPI(TEXCOORD, NOP, V(0,0), V(0,0), V(0,0), V(1,3), 1, 0, SPECIAL(TEXCOORD)), - _OPI(TEXCOORD, MOV, V(0,0), V(0,0), V(1,4), V(1,4), 1, 1, SPECIAL(TEXCOORD_ps14)), - _OPI(TEXKILL, KILL_IF, V(0,0), V(0,0), V(0,0), V(3,0), 1, 0, SPECIAL(TEXKILL)), - _OPI(TEX, TEX, V(0,0), V(0,0), V(0,0), V(1,3), 1, 0, SPECIAL(TEX)), - _OPI(TEX, TEX, V(0,0), V(0,0), V(1,4), V(1,4), 1, 1, SPECIAL(TEXLD_14)), - _OPI(TEX, TEX, V(0,0), V(0,0), V(2,0), V(3,0), 1, 2, SPECIAL(TEXLD)), - _OPI(TEXBEM, TEX, V(0,0), V(0,0), V(0,0), V(1,3), 1, 1, SPECIAL(TEXBEM)), - _OPI(TEXBEML, TEX, V(0,0), V(0,0), V(0,0), V(1,3), 1, 1, SPECIAL(TEXBEM)), - _OPI(TEXREG2AR, TEX, V(0,0), V(0,0), V(0,0), V(1,3), 1, 1, SPECIAL(TEXREG2AR)), - _OPI(TEXREG2GB, TEX, V(0,0), V(0,0), V(0,0), V(1,3), 1, 1, SPECIAL(TEXREG2GB)), - _OPI(TEXM3x2PAD, TEX, V(0,0), V(0,0), V(0,0), V(1,3), 1, 1, SPECIAL(TEXM3x2PAD)), - _OPI(TEXM3x2TEX, TEX, V(0,0), V(0,0), V(0,0), V(1,3), 1, 1, SPECIAL(TEXM3x2TEX)), - _OPI(TEXM3x3PAD, TEX, V(0,0), V(0,0), V(0,0), V(1,3), 1, 1, SPECIAL(TEXM3x3PAD)), - _OPI(TEXM3x3TEX, TEX, V(0,0), V(0,0), V(0,0), V(1,3), 1, 1, SPECIAL(TEXM3x3)), - _OPI(TEXM3x3SPEC, TEX, V(0,0), V(0,0), V(0,0), V(1,3), 1, 2, SPECIAL(TEXM3x3SPEC)), - _OPI(TEXM3x3VSPEC, TEX, V(0,0), V(0,0), V(0,0), V(1,3), 1, 1, SPECIAL(TEXM3x3)), - - _OPI(EXPP, EXP, V(0,0), V(1,1), V(0,0), V(0,0), 1, 1, NULL), - _OPI(EXPP, EX2, V(2,0), V(3,0), V(0,0), V(0,0), 1, 1, NULL), - _OPI(LOGP, LG2, V(0,0), V(3,0), V(0,0), V(0,0), 1, 1, SPECIAL(LOG)), - _OPI(CND, NOP, V(0,0), V(0,0), V(0,0), V(1,4), 1, 3, SPECIAL(CND)), - - _OPI(DEF, NOP, V(0,0), V(3,0), V(0,0), V(3,0), 1, 0, SPECIAL(DEF)), - - /* More tex stuff */ - _OPI(TEXREG2RGB, TEX, V(0,0), V(0,0), V(1,2), V(1,3), 1, 1, SPECIAL(TEXREG2RGB)), - _OPI(TEXDP3TEX, TEX, V(0,0), V(0,0), V(1,2), V(1,3), 1, 1, SPECIAL(TEXDP3TEX)), - _OPI(TEXM3x2DEPTH, TEX, V(0,0), V(0,0), V(1,3), V(1,3), 1, 1, SPECIAL(TEXM3x2DEPTH)), - _OPI(TEXDP3, TEX, V(0,0), V(0,0), V(1,2), V(1,3), 1, 1, SPECIAL(TEXDP3)), - _OPI(TEXM3x3, TEX, V(0,0), V(0,0), V(1,2), V(1,3), 1, 1, SPECIAL(TEXM3x3)), - _OPI(TEXDEPTH, TEX, V(0,0), V(0,0), V(1,4), V(1,4), 1, 0, SPECIAL(TEXDEPTH)), - - /* Misc */ - _OPI(CMP, CMP, V(0,0), V(0,0), V(1,2), V(3,0), 1, 3, SPECIAL(CMP)), /* reversed */ - _OPI(BEM, NOP, V(0,0), V(0,0), V(1,4), V(1,4), 1, 2, SPECIAL(BEM)), - _OPI(DP2ADD, NOP, V(0,0), V(0,0), V(2,0), V(3,0), 1, 3, SPECIAL(DP2ADD)), - _OPI(DSX, DDX, V(0,0), V(0,0), V(2,1), V(3,0), 1, 1, NULL), - _OPI(DSY, DDY, V(0,0), V(0,0), V(2,1), V(3,0), 1, 1, NULL), - _OPI(TEXLDD, TXD, V(0,0), V(0,0), V(2,1), V(3,0), 1, 4, SPECIAL(TEXLDD)), - _OPI(SETP, NOP, V(0,0), V(3,0), V(2,1), V(3,0), 1, 2, SPECIAL(SETP)), - _OPI(TEXLDL, TXL, V(3,0), V(3,0), V(3,0), V(3,0), 1, 2, SPECIAL(TEXLDL)), - _OPI(BREAKP, BRK, V(0,0), V(3,0), V(2,1), V(3,0), 0, 1, SPECIAL(BREAKP)) -}; - -static const struct sm1_op_info inst_phase = - _OPI(PHASE, NOP, V(0,0), V(0,0), V(1,4), V(1,4), 0, 0, SPECIAL(PHASE)); - -static const struct sm1_op_info inst_comment = - _OPI(COMMENT, NOP, V(0,0), V(3,0), V(0,0), V(3,0), 0, 0, SPECIAL(COMMENT)); - -static void -create_op_info_map(struct shader_translator *tx) -{ - const unsigned version = (tx->version.major << 8) | tx->version.minor; - unsigned i; - - for (i = 0; i < ARRAY_SIZE(tx->op_info_map); ++i) - tx->op_info_map[i] = -1; - - if (tx->processor == PIPE_SHADER_VERTEX) { - for (i = 0; i < ARRAY_SIZE(inst_table); ++i) { - assert(inst_table[i].sio < ARRAY_SIZE(tx->op_info_map)); - if (inst_table[i].vert_version.min <= version && - inst_table[i].vert_version.max >= version) - tx->op_info_map[inst_table[i].sio] = i; - } - } else { - for (i = 0; i < ARRAY_SIZE(inst_table); ++i) { - assert(inst_table[i].sio < ARRAY_SIZE(tx->op_info_map)); - if (inst_table[i].frag_version.min <= version && - inst_table[i].frag_version.max >= version) - tx->op_info_map[inst_table[i].sio] = i; - } - } -} - -static inline HRESULT -NineTranslateInstruction_Generic(struct shader_translator *tx) -{ - struct ureg_dst dst[1]; - struct ureg_src src[4]; - unsigned i; - - for (i = 0; i < tx->insn.ndst && i < ARRAY_SIZE(dst); ++i) - dst[i] = tx_dst_param(tx, &tx->insn.dst[i]); - for (i = 0; i < tx->insn.nsrc && i < ARRAY_SIZE(src); ++i) - src[i] = tx_src_param(tx, &tx->insn.src[i]); - - ureg_insn(tx->ureg, tx->insn.info->opcode, - dst, tx->insn.ndst, - src, tx->insn.nsrc, 0); - return D3D_OK; -} - -static inline DWORD -TOKEN_PEEK(struct shader_translator *tx) -{ - return *(tx->parse); -} - -static inline DWORD -TOKEN_NEXT(struct shader_translator *tx) -{ - return *(tx->parse)++; -} - -static inline void -TOKEN_JUMP(struct shader_translator *tx) -{ - if (tx->parse_next && tx->parse != tx->parse_next) { - WARN("parse(%p) != parse_next(%p) !\n", tx->parse, tx->parse_next); - tx->parse = tx->parse_next; - } -} - -static inline boolean -sm1_parse_eof(struct shader_translator *tx) -{ - return TOKEN_PEEK(tx) == NINED3DSP_END; -} - -static void -sm1_read_version(struct shader_translator *tx) -{ - const DWORD tok = TOKEN_NEXT(tx); - - tx->version.major = D3DSHADER_VERSION_MAJOR(tok); - tx->version.minor = D3DSHADER_VERSION_MINOR(tok); - - switch (tok >> 16) { - case NINED3D_SM1_VS: tx->processor = PIPE_SHADER_VERTEX; break; - case NINED3D_SM1_PS: tx->processor = PIPE_SHADER_FRAGMENT; break; - default: - DBG("Invalid shader type: %x\n", tok); - tx->processor = ~0; - break; - } -} - -/* This is just to check if we parsed the instruction properly. */ -static void -sm1_parse_get_skip(struct shader_translator *tx) -{ - const DWORD tok = TOKEN_PEEK(tx); - - if (tx->version.major >= 2) { - tx->parse_next = tx->parse + 1 /* this */ + - ((tok & D3DSI_INSTLENGTH_MASK) >> D3DSI_INSTLENGTH_SHIFT); - } else { - tx->parse_next = NULL; /* TODO: determine from param count */ - } -} - -static void -sm1_print_comment(const char *comment, UINT size) -{ - if (!size) - return; - /* TODO */ -} - -static void -sm1_parse_comments(struct shader_translator *tx, BOOL print) -{ - DWORD tok = TOKEN_PEEK(tx); - - while ((tok & D3DSI_OPCODE_MASK) == D3DSIO_COMMENT) - { - const char *comment = ""; - UINT size = (tok & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT; - tx->parse += size + 1; - - if (print) - sm1_print_comment(comment, size); - - tok = TOKEN_PEEK(tx); - } -} - -static void -sm1_parse_get_param(struct shader_translator *tx, DWORD *reg, DWORD *rel) -{ - *reg = TOKEN_NEXT(tx); - - if (*reg & D3DSHADER_ADDRMODE_RELATIVE) - { - if (tx->version.major < 2) - *rel = (1 << 31) | - ((D3DSPR_ADDR << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2) | - ((D3DSPR_ADDR << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK) | - D3DSP_NOSWIZZLE; - else - *rel = TOKEN_NEXT(tx); - } -} - -static void -sm1_parse_dst_param(struct sm1_dst_param *dst, DWORD tok) -{ - int8_t shift; - dst->file = - (tok & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT | - (tok & D3DSP_REGTYPE_MASK2) >> D3DSP_REGTYPE_SHIFT2; - dst->type = TGSI_RETURN_TYPE_FLOAT; - dst->idx = tok & D3DSP_REGNUM_MASK; - dst->rel = NULL; - dst->mask = (tok & NINED3DSP_WRITEMASK_MASK) >> NINED3DSP_WRITEMASK_SHIFT; - dst->mod = (tok & D3DSP_DSTMOD_MASK) >> D3DSP_DSTMOD_SHIFT; - shift = (tok & D3DSP_DSTSHIFT_MASK) >> D3DSP_DSTSHIFT_SHIFT; - dst->shift = (shift & 0x7) - (shift & 0x8); -} - -static void -sm1_parse_src_param(struct sm1_src_param *src, DWORD tok) -{ - src->file = - ((tok & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT) | - ((tok & D3DSP_REGTYPE_MASK2) >> D3DSP_REGTYPE_SHIFT2); - src->type = TGSI_RETURN_TYPE_FLOAT; - src->idx = tok & D3DSP_REGNUM_MASK; - src->rel = NULL; - src->swizzle = (tok & D3DSP_SWIZZLE_MASK) >> D3DSP_SWIZZLE_SHIFT; - src->mod = (tok & D3DSP_SRCMOD_MASK) >> D3DSP_SRCMOD_SHIFT; - - switch (src->file) { - case D3DSPR_CONST2: src->file = D3DSPR_CONST; src->idx += 2048; break; - case D3DSPR_CONST3: src->file = D3DSPR_CONST; src->idx += 4096; break; - case D3DSPR_CONST4: src->file = D3DSPR_CONST; src->idx += 6144; break; - default: - break; - } -} - -static void -sm1_parse_immediate(struct shader_translator *tx, - struct sm1_src_param *imm) -{ - imm->file = NINED3DSPR_IMMEDIATE; - imm->idx = INT_MIN; - imm->rel = NULL; - imm->swizzle = NINED3DSP_NOSWIZZLE; - imm->mod = 0; - switch (tx->insn.opcode) { - case D3DSIO_DEF: - imm->type = NINED3DSPTYPE_FLOAT4; - memcpy(&imm->imm.d[0], tx->parse, 4 * sizeof(DWORD)); - tx->parse += 4; - break; - case D3DSIO_DEFI: - imm->type = NINED3DSPTYPE_INT4; - memcpy(&imm->imm.d[0], tx->parse, 4 * sizeof(DWORD)); - tx->parse += 4; - break; - case D3DSIO_DEFB: - imm->type = NINED3DSPTYPE_BOOL; - memcpy(&imm->imm.d[0], tx->parse, 1 * sizeof(DWORD)); - tx->parse += 1; - break; - default: - assert(0); - break; - } -} - -static void -sm1_read_dst_param(struct shader_translator *tx, - struct sm1_dst_param *dst, - struct sm1_src_param *rel) -{ - DWORD tok_dst, tok_rel = 0; - - sm1_parse_get_param(tx, &tok_dst, &tok_rel); - sm1_parse_dst_param(dst, tok_dst); - if (tok_dst & D3DSHADER_ADDRMODE_RELATIVE) { - sm1_parse_src_param(rel, tok_rel); - dst->rel = rel; - } -} - -static void -sm1_read_src_param(struct shader_translator *tx, - struct sm1_src_param *src, - struct sm1_src_param *rel) -{ - DWORD tok_src, tok_rel = 0; - - sm1_parse_get_param(tx, &tok_src, &tok_rel); - sm1_parse_src_param(src, tok_src); - if (tok_src & D3DSHADER_ADDRMODE_RELATIVE) { - assert(rel); - sm1_parse_src_param(rel, tok_rel); - src->rel = rel; - } -} - -static void -sm1_read_semantic(struct shader_translator *tx, - struct sm1_semantic *sem) -{ - const DWORD tok_usg = TOKEN_NEXT(tx); - const DWORD tok_dst = TOKEN_NEXT(tx); - - sem->sampler_type = (tok_usg & D3DSP_TEXTURETYPE_MASK) >> D3DSP_TEXTURETYPE_SHIFT; - sem->usage = (tok_usg & D3DSP_DCL_USAGE_MASK) >> D3DSP_DCL_USAGE_SHIFT; - sem->usage_idx = (tok_usg & D3DSP_DCL_USAGEINDEX_MASK) >> D3DSP_DCL_USAGEINDEX_SHIFT; - - sm1_parse_dst_param(&sem->reg, tok_dst); -} - -static void -sm1_parse_instruction(struct shader_translator *tx) -{ - struct sm1_instruction *insn = &tx->insn; - HRESULT hr; - DWORD tok; - const struct sm1_op_info *info = NULL; - unsigned i; - - sm1_parse_comments(tx, TRUE); - sm1_parse_get_skip(tx); - - tok = TOKEN_NEXT(tx); - - insn->opcode = tok & D3DSI_OPCODE_MASK; - insn->flags = (tok & NINED3DSIO_OPCODE_FLAGS_MASK) >> NINED3DSIO_OPCODE_FLAGS_SHIFT; - insn->coissue = !!(tok & D3DSI_COISSUE); - insn->predicated = !!(tok & NINED3DSHADER_INST_PREDICATED); - - if (insn->opcode < ARRAY_SIZE(tx->op_info_map)) { - int k = tx->op_info_map[insn->opcode]; - if (k >= 0) { - assert(k < ARRAY_SIZE(inst_table)); - info = &inst_table[k]; - } - } else { - if (insn->opcode == D3DSIO_PHASE) info = &inst_phase; - if (insn->opcode == D3DSIO_COMMENT) info = &inst_comment; - } - if (!info) { - DBG("illegal or unhandled opcode: %08x\n", insn->opcode); - TOKEN_JUMP(tx); - return; - } - insn->info = info; - insn->ndst = info->ndst; - insn->nsrc = info->nsrc; - - /* check version */ - { - unsigned min = IS_VS ? info->vert_version.min : info->frag_version.min; - unsigned max = IS_VS ? info->vert_version.max : info->frag_version.max; - unsigned ver = (tx->version.major << 8) | tx->version.minor; - if (ver < min || ver > max) { - DBG("opcode not supported in this shader version: %x <= %x <= %x\n", - min, ver, max); - return; - } - } - - for (i = 0; i < insn->ndst; ++i) - sm1_read_dst_param(tx, &insn->dst[i], &insn->dst_rel[i]); - if (insn->predicated) - sm1_read_src_param(tx, &insn->pred, NULL); - for (i = 0; i < insn->nsrc; ++i) - sm1_read_src_param(tx, &insn->src[i], &insn->src_rel[i]); - - /* parse here so we can dump them before processing */ - if (insn->opcode == D3DSIO_DEF || - insn->opcode == D3DSIO_DEFI || - insn->opcode == D3DSIO_DEFB) - sm1_parse_immediate(tx, &tx->insn.src[0]); - - sm1_dump_instruction(insn, tx->cond_depth + tx->loop_depth); - sm1_instruction_check(insn); - - if (insn->predicated) { - tx->predicated_activated = true; - if (ureg_dst_is_undef(tx->regs.predicate_tmp)) { - tx->regs.predicate_tmp = ureg_DECL_temporary(tx->ureg); - tx->regs.predicate_dst = ureg_DECL_temporary(tx->ureg); - } - } - - if (info->handler) - hr = info->handler(tx); - else - hr = NineTranslateInstruction_Generic(tx); - tx_apply_dst0_modifiers(tx); - - if (insn->predicated) { - tx->predicated_activated = false; - /* TODO: predicate might be allowed on outputs, - * which cannot be src. Workaround it. */ - ureg_CMP(tx->ureg, tx->regs.predicate_dst, - ureg_negate(tx_src_param(tx, &insn->pred)), - ureg_src(tx->regs.predicate_tmp), - ureg_src(tx->regs.predicate_dst)); - } - - if (hr != D3D_OK) - tx->failure = TRUE; - tx->num_scratch = 0; /* reset */ - - TOKEN_JUMP(tx); -} - -#define GET_CAP(n) screen->get_param( \ - screen, PIPE_CAP_##n) -#define GET_SHADER_CAP(n) screen->get_shader_param( \ - screen, info->type, PIPE_SHADER_CAP_##n) - -static HRESULT -tx_ctor(struct shader_translator *tx, struct pipe_screen *screen, struct nine_shader_info *info) -{ - unsigned i; - - memset(tx, 0, sizeof(*tx)); - - tx->info = info; - - tx->byte_code = info->byte_code; - tx->parse = info->byte_code; - - for (i = 0; i < ARRAY_SIZE(info->input_map); ++i) - info->input_map[i] = NINE_DECLUSAGE_NONE; - info->num_inputs = 0; - - info->position_t = FALSE; - info->point_size = FALSE; - - memset(tx->slots_used, 0, sizeof(tx->slots_used)); - memset(info->int_slots_used, 0, sizeof(info->int_slots_used)); - memset(info->bool_slots_used, 0, sizeof(info->bool_slots_used)); - - tx->info->const_float_slots = 0; - tx->info->const_int_slots = 0; - tx->info->const_bool_slots = 0; - - info->sampler_mask = 0x0; - info->rt_mask = 0x0; - - info->lconstf.data = NULL; - info->lconstf.ranges = NULL; - - info->bumpenvmat_needed = 0; - - for (i = 0; i < ARRAY_SIZE(tx->regs.rL); ++i) { - tx->regs.rL[i] = ureg_dst_undef(); - } - tx->regs.address = ureg_dst_undef(); - tx->regs.a0 = ureg_dst_undef(); - tx->regs.p = ureg_dst_undef(); - tx->regs.oDepth = ureg_dst_undef(); - tx->regs.vPos = ureg_src_undef(); - tx->regs.vFace = ureg_src_undef(); - for (i = 0; i < ARRAY_SIZE(tx->regs.o); ++i) - tx->regs.o[i] = ureg_dst_undef(); - for (i = 0; i < ARRAY_SIZE(tx->regs.oCol); ++i) - tx->regs.oCol[i] = ureg_dst_undef(); - for (i = 0; i < ARRAY_SIZE(tx->regs.vC); ++i) - tx->regs.vC[i] = ureg_src_undef(); - for (i = 0; i < ARRAY_SIZE(tx->regs.vT); ++i) - tx->regs.vT[i] = ureg_src_undef(); - - sm1_read_version(tx); - - info->version = (tx->version.major << 4) | tx->version.minor; - - tx->num_outputs = 0; - - create_op_info_map(tx); - - tx->ureg = ureg_create(info->type); - if (!tx->ureg) { - return E_OUTOFMEMORY; - } - - tx->native_integers = GET_SHADER_CAP(INTEGERS); - tx->inline_subroutines = !GET_SHADER_CAP(SUBROUTINES); - tx->want_texcoord = GET_CAP(TGSI_TEXCOORD); - tx->shift_wpos = !GET_CAP(TGSI_FS_COORD_PIXEL_CENTER_INTEGER); - tx->texcoord_sn = tx->want_texcoord ? - TGSI_SEMANTIC_TEXCOORD : TGSI_SEMANTIC_GENERIC; - tx->wpos_is_sysval = GET_CAP(TGSI_FS_POSITION_IS_SYSVAL); - tx->face_is_sysval_integer = GET_CAP(TGSI_FS_FACE_IS_INTEGER_SYSVAL); - - if (IS_VS) { - tx->num_constf_allowed = NINE_MAX_CONST_F; - } else if (tx->version.major < 2) {/* IS_PS v1 */ - tx->num_constf_allowed = 8; - } else if (tx->version.major == 2) {/* IS_PS v2 */ - tx->num_constf_allowed = 32; - } else {/* IS_PS v3 */ - tx->num_constf_allowed = NINE_MAX_CONST_F_PS3; - } - - if (tx->version.major < 2) { - tx->num_consti_allowed = 0; - tx->num_constb_allowed = 0; - } else { - tx->num_consti_allowed = NINE_MAX_CONST_I; - tx->num_constb_allowed = NINE_MAX_CONST_B; - } - - if (info->swvp_on && tx->version.major >= 2) { - tx->num_constf_allowed = 8192; - tx->num_consti_allowed = 2048; - tx->num_constb_allowed = 2048; - } - - /* VS must always write position. Declare it here to make it the 1st output. - * (Some drivers like nv50 are buggy and rely on that.) - */ - if (IS_VS) { - tx->regs.oPos = ureg_DECL_output(tx->ureg, TGSI_SEMANTIC_POSITION, 0); - } else { - ureg_property(tx->ureg, TGSI_PROPERTY_FS_COORD_ORIGIN, TGSI_FS_COORD_ORIGIN_UPPER_LEFT); - if (!tx->shift_wpos) - ureg_property(tx->ureg, TGSI_PROPERTY_FS_COORD_PIXEL_CENTER, TGSI_FS_COORD_PIXEL_CENTER_INTEGER); - } - - tx->mul_zero_wins = GET_CAP(TGSI_MUL_ZERO_WINS); - if (tx->mul_zero_wins) - ureg_property(tx->ureg, TGSI_PROPERTY_MUL_ZERO_WINS, 1); - - /* Add additional definition of constants */ - if (info->add_constants_defs.c_combination) { - unsigned i; - - assert(info->add_constants_defs.int_const_added); - assert(info->add_constants_defs.bool_const_added); - /* We only add constants that are used by the shader - * and that are not defined in the shader */ - for (i = 0; i < NINE_MAX_CONST_I; ++i) { - if ((*info->add_constants_defs.int_const_added)[i]) { - DBG("Defining const i%i : { %i %i %i %i }\n", i, - info->add_constants_defs.c_combination->const_i[i][0], - info->add_constants_defs.c_combination->const_i[i][1], - info->add_constants_defs.c_combination->const_i[i][2], - info->add_constants_defs.c_combination->const_i[i][3]); - tx_set_lconsti(tx, i, info->add_constants_defs.c_combination->const_i[i]); - } - } - for (i = 0; i < NINE_MAX_CONST_B; ++i) { - if ((*info->add_constants_defs.bool_const_added)[i]) { - DBG("Defining const b%i : %i\n", i, (int)(info->add_constants_defs.c_combination->const_b[i] != 0)); - tx_set_lconstb(tx, i, info->add_constants_defs.c_combination->const_b[i]); - } - } - } - return D3D_OK; -} - -static void -tx_dtor(struct shader_translator *tx) -{ - if (tx->slot_map) - FREE(tx->slot_map); - if (tx->num_inst_labels) - FREE(tx->inst_labels); - FREE(tx->lconstf); - FREE(tx->regs.r); - FREE(tx); -} - -/* CONST[0].xyz = width/2, -height/2, zmax-zmin - * CONST[1].xyz = x+width/2, y+height/2, zmin */ -static void -shader_add_vs_viewport_transform(struct shader_translator *tx) -{ - struct ureg_program *ureg = tx->ureg; - struct ureg_src c0 = ureg_src_register(TGSI_FILE_CONSTANT, 0); - struct ureg_src c1 = ureg_src_register(TGSI_FILE_CONSTANT, 1); - /* struct ureg_dst pos_tmp = ureg_DECL_temporary(ureg);*/ - - c0 = ureg_src_dimension(c0, 4); - c1 = ureg_src_dimension(c1, 4); - /* TODO: find out when we need to apply the viewport transformation or not. - * Likely will be XYZ vs XYZRHW in vdecl_out - * ureg_MUL(ureg, ureg_writemask(pos_tmp, TGSI_WRITEMASK_XYZ), ureg_src(tx->regs.oPos), c0); - * ureg_ADD(ureg, ureg_writemask(tx->regs.oPos_out, TGSI_WRITEMASK_XYZ), ureg_src(pos_tmp), c1); - */ - ureg_MOV(ureg, ureg_writemask(tx->regs.oPos_out, TGSI_WRITEMASK_XYZ), ureg_src(tx->regs.oPos)); -} - -static void -shader_add_ps_fog_stage(struct shader_translator *tx, struct ureg_src src_col) -{ - struct ureg_program *ureg = tx->ureg; - struct ureg_dst oCol0 = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0); - struct ureg_src fog_end, fog_coeff, fog_density, fog_params; - struct ureg_src fog_vs, fog_color; - struct ureg_dst fog_factor, depth; - - if (!tx->info->fog_enable) { - ureg_MOV(ureg, oCol0, src_col); - return; - } - - if (tx->info->fog_mode != D3DFOG_NONE) { - depth = tx_scratch_scalar(tx); - /* Depth used for fog is perspective interpolated */ - ureg_RCP(ureg, depth, ureg_scalar(nine_get_position_input(tx), TGSI_SWIZZLE_W)); - ureg_MUL(ureg, depth, ureg_src(depth), ureg_scalar(nine_get_position_input(tx), TGSI_SWIZZLE_Z)); - } - - fog_color = nine_float_constant_src(tx, 32); - fog_params = nine_float_constant_src(tx, 33); - fog_factor = tx_scratch_scalar(tx); - - if (tx->info->fog_mode == D3DFOG_LINEAR) { - fog_end = NINE_APPLY_SWIZZLE(fog_params, X); - fog_coeff = NINE_APPLY_SWIZZLE(fog_params, Y); - ureg_ADD(ureg, fog_factor, fog_end, ureg_negate(ureg_src(depth))); - ureg_MUL(ureg, ureg_saturate(fog_factor), tx_src_scalar(fog_factor), fog_coeff); - } else if (tx->info->fog_mode == D3DFOG_EXP) { - fog_density = NINE_APPLY_SWIZZLE(fog_params, X); - ureg_MUL(ureg, fog_factor, ureg_src(depth), fog_density); - ureg_MUL(ureg, fog_factor, tx_src_scalar(fog_factor), ureg_imm1f(ureg, -1.442695f)); - ureg_EX2(ureg, fog_factor, tx_src_scalar(fog_factor)); - } else if (tx->info->fog_mode == D3DFOG_EXP2) { - fog_density = NINE_APPLY_SWIZZLE(fog_params, X); - ureg_MUL(ureg, fog_factor, ureg_src(depth), fog_density); - ureg_MUL(ureg, fog_factor, tx_src_scalar(fog_factor), tx_src_scalar(fog_factor)); - ureg_MUL(ureg, fog_factor, tx_src_scalar(fog_factor), ureg_imm1f(ureg, -1.442695f)); - ureg_EX2(ureg, fog_factor, tx_src_scalar(fog_factor)); - } else { - fog_vs = ureg_scalar(ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_GENERIC, 16, - TGSI_INTERPOLATE_PERSPECTIVE), - TGSI_SWIZZLE_X); - ureg_MOV(ureg, fog_factor, fog_vs); - } - - ureg_LRP(ureg, ureg_writemask(oCol0, TGSI_WRITEMASK_XYZ), - tx_src_scalar(fog_factor), src_col, fog_color); - ureg_MOV(ureg, ureg_writemask(oCol0, TGSI_WRITEMASK_W), src_col); -} - -static void parse_shader(struct shader_translator *tx) -{ - struct nine_shader_info *info = tx->info; - - while (!sm1_parse_eof(tx) && !tx->failure) - sm1_parse_instruction(tx); - tx->parse++; /* for byte_size */ - - if (tx->failure) - return; - - if (IS_PS && tx->version.major < 3) { - if (tx->version.major < 2) { - assert(tx->num_temp); /* there must be color output */ - info->rt_mask |= 0x1; - shader_add_ps_fog_stage(tx, ureg_src(tx->regs.r[0])); - } else { - shader_add_ps_fog_stage(tx, ureg_src(tx->regs.oCol[0])); - } - } - - if (IS_VS && tx->version.major < 3 && ureg_dst_is_undef(tx->regs.oFog) && info->fog_enable) { - tx->regs.oFog = ureg_DECL_output(tx->ureg, TGSI_SEMANTIC_GENERIC, 16); - ureg_MOV(tx->ureg, ureg_writemask(tx->regs.oFog, TGSI_WRITEMASK_X), ureg_imm1f(tx->ureg, 0.0f)); - } - - if (info->position_t) - ureg_property(tx->ureg, TGSI_PROPERTY_VS_WINDOW_SPACE_POSITION, TRUE); - - if (IS_VS && !ureg_dst_is_undef(tx->regs.oPts)) { - struct ureg_dst oPts = ureg_DECL_output(tx->ureg, TGSI_SEMANTIC_PSIZE, 0); - ureg_MAX(tx->ureg, tx->regs.oPts, ureg_src(tx->regs.oPts), ureg_imm1f(tx->ureg, info->point_size_min)); - ureg_MIN(tx->ureg, oPts, ureg_src(tx->regs.oPts), ureg_imm1f(tx->ureg, info->point_size_max)); - info->point_size = TRUE; - } - - if (info->process_vertices) - shader_add_vs_viewport_transform(tx); - - ureg_END(tx->ureg); -} - -#define NINE_SHADER_DEBUG_OPTION_NIR_VS (1 << 0) -#define NINE_SHADER_DEBUG_OPTION_NIR_PS (1 << 1) -#define NINE_SHADER_DEBUG_OPTION_NO_NIR_VS (1 << 2) -#define NINE_SHADER_DEBUG_OPTION_NO_NIR_PS (1 << 3) -#define NINE_SHADER_DEBUG_OPTION_DUMP_NIR (1 << 4) -#define NINE_SHADER_DEBUG_OPTION_DUMP_TGSI (1 << 5) - -static const struct debug_named_value nine_shader_debug_options[] = { - { "nir_vs", NINE_SHADER_DEBUG_OPTION_NIR_VS, "Use NIR for vertex shaders even if the driver doesn't prefer it." }, - { "nir_ps", NINE_SHADER_DEBUG_OPTION_NIR_PS, "Use NIR for pixel shaders even if the driver doesn't prefer it." }, - { "no_nir_vs", NINE_SHADER_DEBUG_OPTION_NO_NIR_VS, "Never use NIR for vertex shaders even if the driver prefers it." }, - { "no_nir_ps", NINE_SHADER_DEBUG_OPTION_NO_NIR_PS, "Never use NIR for pixel shaders even if the driver prefers it." }, - { "dump_nir", NINE_SHADER_DEBUG_OPTION_DUMP_NIR, "Print translated NIR shaders." }, - { "dump_tgsi", NINE_SHADER_DEBUG_OPTION_DUMP_TGSI, "Print TGSI shaders." }, - DEBUG_NAMED_VALUE_END /* must be last */ -}; - -static inline boolean -nine_shader_get_debug_flag(uint64_t flag) -{ - static uint64_t flags = 0; - static boolean first_run = TRUE; - - if (unlikely(first_run)) { - first_run = FALSE; - flags = debug_get_flags_option("NINE_SHADER", nine_shader_debug_options, 0); - - // Check old TGSI dump envvar too - if (debug_get_bool_option("NINE_TGSI_DUMP", FALSE)) { - flags |= NINE_SHADER_DEBUG_OPTION_DUMP_TGSI; - } - } - - return !!(flags & flag); -} - -static void -nine_pipe_nir_shader_state_from_tgsi(struct pipe_shader_state *state, const struct tgsi_token *tgsi_tokens, - struct pipe_screen *screen) -{ - struct nir_shader *nir = tgsi_to_nir(tgsi_tokens, screen); - - if (unlikely(nine_shader_get_debug_flag(NINE_SHADER_DEBUG_OPTION_DUMP_NIR))) { - nir_print_shader(nir, stdout); - } - - state->type = PIPE_SHADER_IR_NIR; - state->tokens = NULL; - state->ir.nir = nir; - memset(&state->stream_output, 0, sizeof(state->stream_output)); -} - -static void * -nine_ureg_create_shader(struct ureg_program *ureg, - struct pipe_context *pipe, - const struct pipe_stream_output_info *so) -{ - struct pipe_shader_state state; - const struct tgsi_token *tgsi_tokens; - struct pipe_screen *screen = pipe->screen; - - tgsi_tokens = ureg_finalize(ureg); - if (!tgsi_tokens) - return NULL; - - assert(((struct tgsi_header *) &tgsi_tokens[0])->HeaderSize >= 2); - enum pipe_shader_type shader_type = ((struct tgsi_processor *) &tgsi_tokens[1])->Processor; - - int preferred_ir = screen->get_shader_param(screen, shader_type, PIPE_SHADER_CAP_PREFERRED_IR); - bool prefer_nir = (preferred_ir == PIPE_SHADER_IR_NIR); - bool use_nir = prefer_nir || - ((shader_type == PIPE_SHADER_VERTEX) && nine_shader_get_debug_flag(NINE_SHADER_DEBUG_OPTION_NIR_VS)) || - ((shader_type == PIPE_SHADER_FRAGMENT) && nine_shader_get_debug_flag(NINE_SHADER_DEBUG_OPTION_NIR_PS)); - - /* Allow user to override preferred IR, this is very useful for debugging */ - if (unlikely(shader_type == PIPE_SHADER_VERTEX && nine_shader_get_debug_flag(NINE_SHADER_DEBUG_OPTION_NO_NIR_VS))) - use_nir = false; - if (unlikely(shader_type == PIPE_SHADER_FRAGMENT && nine_shader_get_debug_flag(NINE_SHADER_DEBUG_OPTION_NO_NIR_PS))) - use_nir = false; - - DUMP("shader type: %s, preferred IR: %s, selected IR: %s\n", - shader_type == PIPE_SHADER_VERTEX ? "VS" : "PS", - prefer_nir ? "NIR" : "TGSI", - use_nir ? "NIR" : "TGSI"); - - if (use_nir) { - nine_pipe_nir_shader_state_from_tgsi(&state, tgsi_tokens, screen); - } else { - pipe_shader_state_from_tgsi(&state, tgsi_tokens); - } - - assert(state.tokens || state.ir.nir); - - if (so) - state.stream_output = *so; - - switch (shader_type) { - case PIPE_SHADER_VERTEX: - return pipe->create_vs_state(pipe, &state); - case PIPE_SHADER_FRAGMENT: - return pipe->create_fs_state(pipe, &state); - default: - unreachable("unsupported shader type"); - } -} - - -void * -nine_create_shader_with_so_and_destroy(struct ureg_program *p, - struct pipe_context *pipe, - const struct pipe_stream_output_info *so) -{ - void *result = nine_ureg_create_shader(p, pipe, so); - ureg_destroy(p); - return result; -} - -HRESULT -nine_translate_shader(struct NineDevice9 *device, struct nine_shader_info *info, struct pipe_context *pipe) -{ - struct shader_translator *tx; - HRESULT hr = D3D_OK; - const unsigned processor = info->type; - struct pipe_screen *screen = info->process_vertices ? device->screen_sw : device->screen; - unsigned *const_ranges = NULL; - - user_assert(processor != ~0, D3DERR_INVALIDCALL); - - tx = MALLOC_STRUCT(shader_translator); - if (!tx) - return E_OUTOFMEMORY; - - if (tx_ctor(tx, screen, info) == E_OUTOFMEMORY) { - hr = E_OUTOFMEMORY; - goto out; - } - - assert(IS_VS || !info->swvp_on); - - if (((tx->version.major << 16) | tx->version.minor) > 0x00030000) { - hr = D3DERR_INVALIDCALL; - DBG("Unsupported shader version: %u.%u !\n", - tx->version.major, tx->version.minor); - goto out; - } - if (tx->processor != processor) { - hr = D3DERR_INVALIDCALL; - DBG("Shader type mismatch: %u / %u !\n", tx->processor, processor); - goto out; - } - DUMP("%s%u.%u\n", processor == PIPE_SHADER_VERTEX ? "VS" : "PS", - tx->version.major, tx->version.minor); - - parse_shader(tx); - - if (tx->failure) { - /* For VS shaders, we print the warning later, - * we first try with swvp. */ - if (IS_PS) - ERR("Encountered buggy shader\n"); - ureg_destroy(tx->ureg); - hr = D3DERR_INVALIDCALL; - goto out; - } - - /* Recompile after compacting constant slots if possible */ - if (!tx->indirect_const_access && !info->swvp_on && tx->num_slots > 0) { - unsigned *slot_map; - unsigned c; - int i, j, num_ranges, prev; - - DBG("Recompiling shader for constant compaction\n"); - ureg_destroy(tx->ureg); - - if (tx->num_inst_labels) - FREE(tx->inst_labels); - FREE(tx->lconstf); - FREE(tx->regs.r); - - num_ranges = 0; - prev = -2; - for (i = 0; i < NINE_MAX_CONST_ALL; i++) { - if (tx->slots_used[i]) { - if (prev != i - 1) - num_ranges++; - prev = i; - } - } - slot_map = MALLOC(NINE_MAX_CONST_ALL * sizeof(unsigned)); - const_ranges = CALLOC(num_ranges + 1, 2 * sizeof(unsigned)); /* ranges stop when last is of size 0 */ - if (!slot_map || !const_ranges) { - hr = E_OUTOFMEMORY; - goto out; - } - c = 0; - j = -1; - prev = -2; - for (i = 0; i < NINE_MAX_CONST_ALL; i++) { - if (tx->slots_used[i]) { - if (prev != i - 1) - j++; - /* Initialize first slot of the range */ - if (!const_ranges[2*j+1]) - const_ranges[2*j] = i; - const_ranges[2*j+1]++; - prev = i; - slot_map[i] = c++; - } - } - - if (tx_ctor(tx, screen, info) == E_OUTOFMEMORY) { - hr = E_OUTOFMEMORY; - goto out; - } - tx->slot_map = slot_map; - parse_shader(tx); - assert(!tx->failure); -#if !defined(NDEBUG) - i = 0; - j = 0; - while (const_ranges[i*2+1] != 0) { - j += const_ranges[i*2+1]; - i++; - } - assert(j == tx->num_slots); -#endif - } - - /* record local constants */ - if (tx->num_lconstf && tx->indirect_const_access) { - struct nine_range *ranges; - float *data; - int *indices; - unsigned i, k, n; - - hr = E_OUTOFMEMORY; - - data = MALLOC(tx->num_lconstf * 4 * sizeof(float)); - if (!data) - goto out; - info->lconstf.data = data; - - indices = MALLOC(tx->num_lconstf * sizeof(indices[0])); - if (!indices) - goto out; - - /* lazy sort, num_lconstf should be small */ - for (n = 0; n < tx->num_lconstf; ++n) { - for (k = 0, i = 0; i < tx->num_lconstf; ++i) { - if (tx->lconstf[i].idx < tx->lconstf[k].idx) - k = i; - } - indices[n] = tx->lconstf[k].idx; - memcpy(&data[n * 4], &tx->lconstf[k].f[0], 4 * sizeof(float)); - tx->lconstf[k].idx = INT_MAX; - } - - /* count ranges */ - for (n = 1, i = 1; i < tx->num_lconstf; ++i) - if (indices[i] != indices[i - 1] + 1) - ++n; - ranges = MALLOC(n * sizeof(ranges[0])); - if (!ranges) { - FREE(indices); - goto out; - } - info->lconstf.ranges = ranges; - - k = 0; - ranges[k].bgn = indices[0]; - for (i = 1; i < tx->num_lconstf; ++i) { - if (indices[i] != indices[i - 1] + 1) { - ranges[k].next = &ranges[k + 1]; - ranges[k].end = indices[i - 1] + 1; - ++k; - ranges[k].bgn = indices[i]; - } - } - ranges[k].end = indices[i - 1] + 1; - ranges[k].next = NULL; - assert(n == (k + 1)); - - FREE(indices); - hr = D3D_OK; - } - - /* r500 */ - if (info->const_float_slots > device->max_vs_const_f && - (info->const_int_slots || info->const_bool_slots) && - !info->swvp_on) - ERR("Overlapping constant slots. The shader is likely to be buggy\n"); - - - if (tx->indirect_const_access) { /* vs only */ - info->const_float_slots = device->max_vs_const_f; - tx->num_slots = MAX2(tx->num_slots, device->max_vs_const_f); - } - - if (!info->swvp_on) { - info->const_used_size = sizeof(float[4]) * tx->num_slots; - if (tx->num_slots) - ureg_DECL_constant2D(tx->ureg, 0, tx->num_slots-1, 0); - } else { - ureg_DECL_constant2D(tx->ureg, 0, 4095, 0); - ureg_DECL_constant2D(tx->ureg, 0, 4095, 1); - ureg_DECL_constant2D(tx->ureg, 0, 2047, 2); - ureg_DECL_constant2D(tx->ureg, 0, 511, 3); - } - - if (info->process_vertices) - ureg_DECL_constant2D(tx->ureg, 0, 2, 4); /* Viewport data */ - - if (unlikely(nine_shader_get_debug_flag(NINE_SHADER_DEBUG_OPTION_DUMP_TGSI))) { - const struct tgsi_token *toks = ureg_get_tokens(tx->ureg, NULL); - tgsi_dump(toks, 0); - ureg_free_tokens(toks); - } - - if (info->process_vertices) { - NineVertexDeclaration9_FillStreamOutputInfo(info->vdecl_out, - tx->output_info, - tx->num_outputs, - &(info->so)); - info->cso = nine_create_shader_with_so_and_destroy(tx->ureg, pipe, &(info->so)); - } else - info->cso = nine_create_shader_with_so_and_destroy(tx->ureg, pipe, NULL); - if (!info->cso) { - hr = D3DERR_DRIVERINTERNALERROR; - FREE(info->lconstf.data); - FREE(info->lconstf.ranges); - goto out; - } - - info->const_ranges = const_ranges; - const_ranges = NULL; - info->byte_size = (tx->parse - tx->byte_code) * sizeof(DWORD); -out: - if (const_ranges) - FREE(const_ranges); - tx_dtor(tx); - return hr; -} diff --git a/src/gallium/state_trackers/nine/nine_shader.h b/src/gallium/state_trackers/nine/nine_shader.h deleted file mode 100644 index 5abdbe24472..00000000000 --- a/src/gallium/state_trackers/nine/nine_shader.h +++ /dev/null @@ -1,327 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef _NINE_SHADER_H_ -#define _NINE_SHADER_H_ - -#include "d3d9types.h" -#include "d3d9caps.h" -#include "nine_defines.h" -#include "nine_helpers.h" -#include "nine_state.h" -#include "pipe/p_state.h" /* PIPE_MAX_ATTRIBS */ -#include "util/u_memory.h" - -struct NineDevice9; -struct NineVertexDeclaration9; -struct ureg_program; - -struct nine_lconstf /* NOTE: both pointers should be FREE'd by the user */ -{ - struct nine_range *ranges; /* single MALLOC, but next-pointers valid */ - float *data; -}; - -struct nine_shader_constant_combination; - -struct nine_shader_info -{ - unsigned type; /* in, PIPE_SHADER_x */ - - uint8_t version; /* (major << 4) | minor */ - - const DWORD *byte_code; /* in, pointer to shader tokens */ - DWORD byte_size; /* out, size of data at byte_code */ - - void *cso; /* out, pipe cso for bind_vs,fs_state */ - - uint16_t input_map[PIPE_MAX_ATTRIBS]; /* VS input -> NINE_DECLUSAGE_x */ - uint8_t num_inputs; /* there may be unused inputs (NINE_DECLUSAGE_NONE) */ - - boolean position_t; /* out, true if VP writes pre-transformed position */ - boolean point_size; /* out, true if VP writes point size */ - float point_size_min; - float point_size_max; - - uint32_t sampler_ps1xtypes; /* 2 bits per sampler */ - uint16_t sampler_mask; /* out, which samplers are being used */ - uint16_t sampler_mask_shadow; /* in, which samplers use depth compare */ - uint8_t rt_mask; /* out, which render targets are being written */ - - uint8_t fog_enable; - uint8_t fog_mode; - uint8_t force_color_in_centroid; - uint8_t projected; /* ps 1.1 to 1.3 */ - - unsigned const_i_base; /* in vec4 (16 byte) units */ - unsigned const_b_base; /* in vec4 (16 byte) units */ - unsigned const_used_size; - - boolean int_slots_used[NINE_MAX_CONST_I]; - boolean bool_slots_used[NINE_MAX_CONST_B]; - - unsigned const_float_slots; - unsigned const_int_slots; - unsigned const_bool_slots; - - unsigned *const_ranges; - - struct nine_lconstf lconstf; /* out, NOTE: members to be free'd by user */ - uint8_t bumpenvmat_needed; - - struct { - struct nine_shader_constant_combination* c_combination; - boolean (*int_const_added)[NINE_MAX_CONST_I]; - boolean (*bool_const_added)[NINE_MAX_CONST_B]; - } add_constants_defs; - - boolean swvp_on; - - boolean process_vertices; - struct NineVertexDeclaration9 *vdecl_out; - struct pipe_stream_output_info so; -}; - -struct nine_vs_output_info -{ - BYTE output_semantic; - int output_semantic_index; - int mask; - int output_index; -}; - -void * -nine_create_shader_with_so_and_destroy(struct ureg_program *p, - struct pipe_context *pipe, - const struct pipe_stream_output_info *so); - -HRESULT -nine_translate_shader(struct NineDevice9 *device, - struct nine_shader_info *, - struct pipe_context *); - - -struct nine_shader_variant -{ - struct nine_shader_variant *next; - void *cso; - unsigned *const_ranges; - unsigned const_used_size; - uint64_t key; -}; - -static inline void * -nine_shader_variant_get(struct nine_shader_variant *list, - unsigned **const_ranges, - unsigned *const_used_size, - uint64_t key) -{ - while (list->key != key && list->next) - list = list->next; - if (list->key == key) { - *const_ranges = list->const_ranges; - *const_used_size = list->const_used_size; - return list->cso; - } - return NULL; -} - -static inline boolean -nine_shader_variant_add(struct nine_shader_variant *list, - uint64_t key, void *cso, - unsigned *const_ranges, - unsigned const_used_size) -{ - while (list->next) { - assert(list->key != key); - list = list->next; - } - list->next = MALLOC_STRUCT(nine_shader_variant); - if (!list->next) - return FALSE; - list->next->next = NULL; - list->next->key = key; - list->next->cso = cso; - list->next->const_ranges = const_ranges; - list->next->const_used_size = const_used_size; - return TRUE; -} - -static inline void -nine_shader_variants_free(struct nine_shader_variant *list) -{ - while (list->next) { - struct nine_shader_variant *ptr = list->next; - list->next = ptr->next; - FREE(ptr); - } -} - -struct nine_shader_variant_so -{ - struct nine_shader_variant_so *next; - struct NineVertexDeclaration9 *vdecl; - struct pipe_stream_output_info so; - void *cso; -}; - -static inline void * -nine_shader_variant_so_get(struct nine_shader_variant_so *list, - struct NineVertexDeclaration9 *vdecl, - struct pipe_stream_output_info *so) -{ - while (list->vdecl != vdecl && list->next) - list = list->next; - if (list->vdecl == vdecl) { - *so = list->so; - return list->cso; - } - return NULL; -} - -static inline boolean -nine_shader_variant_so_add(struct nine_shader_variant_so *list, - struct NineVertexDeclaration9 *vdecl, - struct pipe_stream_output_info *so, void *cso) -{ - if (list->vdecl == NULL) { /* first shader */ - list->next = NULL; - nine_bind(&list->vdecl, vdecl); - list->so = *so; - list->cso = cso; - return TRUE; - } - while (list->next) { - assert(list->vdecl != vdecl); - list = list->next; - } - list->next = MALLOC_STRUCT(nine_shader_variant_so); - if (!list->next) - return FALSE; - list->next->next = NULL; - nine_bind(&list->vdecl, vdecl); - list->next->so = *so; - list->next->cso = cso; - return TRUE; -} - -static inline void -nine_shader_variants_so_free(struct nine_shader_variant_so *list) -{ - while (list->next) { - struct nine_shader_variant_so *ptr = list->next; - list->next = ptr->next; - nine_bind(&ptr->vdecl, NULL); - FREE(ptr); - } - if (list->vdecl) - nine_bind(&list->vdecl, NULL); -} - -struct nine_shader_constant_combination -{ - struct nine_shader_constant_combination *next; - int const_i[NINE_MAX_CONST_I][4]; - BOOL const_b[NINE_MAX_CONST_B]; -}; - -#define NINE_MAX_CONSTANT_COMBINATION_VARIANTS 32 - -static inline uint8_t -nine_shader_constant_combination_key(struct nine_shader_constant_combination **list, - boolean *int_slots_used, - boolean *bool_slots_used, - int *const_i, - BOOL *const_b) -{ - int i; - uint8_t index = 0; - boolean match; - struct nine_shader_constant_combination **next_allocate = list, *current = *list; - - assert(int_slots_used); - assert(bool_slots_used); - assert(const_i); - assert(const_b); - - while (current) { - index++; /* start at 1. 0 is for the variant without constant replacement */ - match = TRUE; - for (i = 0; i < NINE_MAX_CONST_I; ++i) { - if (int_slots_used[i]) - match &= !memcmp(const_i + 4*i, current->const_i[i], sizeof(current->const_i[0])); - } - for (i = 0; i < NINE_MAX_CONST_B; ++i) { - if (bool_slots_used[i]) - match &= const_b[i] == current->const_b[i]; - } - if (match) - return index; - next_allocate = ¤t->next; - current = current->next; - } - - if (index < NINE_MAX_CONSTANT_COMBINATION_VARIANTS) { - *next_allocate = MALLOC_STRUCT(nine_shader_constant_combination); - current = *next_allocate; - index++; - current->next = NULL; - memcpy(current->const_i, const_i, sizeof(current->const_i)); - memcpy(current->const_b, const_b, sizeof(current->const_b)); - return index; - } - - return 0; /* Too many variants, revert to no replacement */ -} - -static inline struct nine_shader_constant_combination * -nine_shader_constant_combination_get(struct nine_shader_constant_combination *list, uint8_t index) -{ - if (index == 0) - return NULL; - while (index) { - assert(list != NULL); - index--; - if (index == 0) - return list; - list = list->next; - } - assert(FALSE); - return NULL; -} - -static inline void -nine_shader_constant_combination_free(struct nine_shader_constant_combination *list) -{ - if (!list) - return; - - while (list->next) { - struct nine_shader_constant_combination *ptr = list->next; - list->next = ptr->next; - FREE(ptr); - } - - FREE(list); -} - -#endif /* _NINE_SHADER_H_ */ diff --git a/src/gallium/state_trackers/nine/nine_state.c b/src/gallium/state_trackers/nine/nine_state.c deleted file mode 100644 index 8724ec87c81..00000000000 --- a/src/gallium/state_trackers/nine/nine_state.c +++ /dev/null @@ -1,3710 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * Copyright 2013 Christoph Bumiller - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#define NINE_STATE - -#include "device9.h" -#include "swapchain9.h" -#include "basetexture9.h" -#include "buffer9.h" -#include "indexbuffer9.h" -#include "surface9.h" -#include "vertexbuffer9.h" -#include "vertexdeclaration9.h" -#include "vertexshader9.h" -#include "pixelshader9.h" -#include "nine_pipe.h" -#include "nine_ff.h" -#include "nine_limits.h" -#include "pipe/p_context.h" -#include "pipe/p_state.h" -#include "cso_cache/cso_context.h" -#include "util/u_atomic.h" -#include "util/u_upload_mgr.h" -#include "util/u_math.h" -#include "util/u_box.h" -#include "util/u_simple_shaders.h" -#include "util/u_gen_mipmap.h" - -/* CSMT headers */ -#include "nine_queue.h" -#include "nine_csmt_helper.h" -#include "os/os_thread.h" - -#define DBG_CHANNEL DBG_DEVICE - -/* Nine CSMT */ - -struct csmt_instruction { - int (* func)(struct NineDevice9 *This, struct csmt_instruction *instr); -}; - -struct csmt_context { - thrd_t worker; - struct nine_queue_pool* pool; - BOOL terminate; - cnd_t event_processed; - mtx_t mutex_processed; - struct NineDevice9 *device; - BOOL processed; - BOOL toPause; - BOOL hasPaused; - mtx_t thread_running; - mtx_t thread_resume; -}; - -/* Wait for instruction to be processed. - * Caller has to ensure that only one thread waits at time. - */ -static void -nine_csmt_wait_processed(struct csmt_context *ctx) -{ - mtx_lock(&ctx->mutex_processed); - while (!p_atomic_read(&ctx->processed)) { - cnd_wait(&ctx->event_processed, &ctx->mutex_processed); - } - mtx_unlock(&ctx->mutex_processed); -} - -/* CSMT worker thread */ -static -int -nine_csmt_worker(void *arg) -{ - struct csmt_context *ctx = arg; - struct csmt_instruction *instr; - DBG("CSMT worker spawned\n"); - - u_thread_setname("CSMT-Worker"); - - while (1) { - nine_queue_wait_flush(ctx->pool); - mtx_lock(&ctx->thread_running); - - /* Get instruction. NULL on empty cmdbuf. */ - while (!p_atomic_read(&ctx->terminate) && - (instr = (struct csmt_instruction *)nine_queue_get(ctx->pool))) { - - /* decode */ - if (instr->func(ctx->device, instr)) { - mtx_lock(&ctx->mutex_processed); - p_atomic_set(&ctx->processed, TRUE); - cnd_signal(&ctx->event_processed); - mtx_unlock(&ctx->mutex_processed); - } - if (p_atomic_read(&ctx->toPause)) { - mtx_unlock(&ctx->thread_running); - /* will wait here the thread can be resumed */ - mtx_lock(&ctx->thread_resume); - mtx_lock(&ctx->thread_running); - mtx_unlock(&ctx->thread_resume); - } - } - - mtx_unlock(&ctx->thread_running); - if (p_atomic_read(&ctx->terminate)) { - mtx_lock(&ctx->mutex_processed); - p_atomic_set(&ctx->processed, TRUE); - cnd_signal(&ctx->event_processed); - mtx_unlock(&ctx->mutex_processed); - break; - } - } - - DBG("CSMT worker destroyed\n"); - return 0; -} - -/* Create a CSMT context. - * Spawns a worker thread. - */ -struct csmt_context * -nine_csmt_create( struct NineDevice9 *This ) -{ - struct csmt_context *ctx; - - ctx = CALLOC_STRUCT(csmt_context); - if (!ctx) - return NULL; - - ctx->pool = nine_queue_create(); - if (!ctx->pool) { - FREE(ctx); - return NULL; - } - cnd_init(&ctx->event_processed); - (void) mtx_init(&ctx->mutex_processed, mtx_plain); - (void) mtx_init(&ctx->thread_running, mtx_plain); - (void) mtx_init(&ctx->thread_resume, mtx_plain); - -#if defined(DEBUG) || !defined(NDEBUG) - u_thread_setname("Main thread"); -#endif - - ctx->device = This; - - ctx->worker = u_thread_create(nine_csmt_worker, ctx); - if (!ctx->worker) { - nine_queue_delete(ctx->pool); - FREE(ctx); - return NULL; - } - - DBG("Returning context %p\n", ctx); - - return ctx; -} - -static int -nop_func( struct NineDevice9 *This, struct csmt_instruction *instr ) -{ - (void) This; - (void) instr; - - return 1; -} - -/* Push nop instruction and flush the queue. - * Waits for the worker to complete. */ -void -nine_csmt_process( struct NineDevice9 *device ) -{ - struct csmt_instruction* instr; - struct csmt_context *ctx = device->csmt_ctx; - - if (!device->csmt_active) - return; - - if (nine_queue_isempty(ctx->pool)) - return; - - DBG("device=%p\n", device); - - /* NOP */ - instr = nine_queue_alloc(ctx->pool, sizeof(struct csmt_instruction)); - assert(instr); - instr->func = nop_func; - - p_atomic_set(&ctx->processed, FALSE); - nine_queue_flush(ctx->pool); - - nine_csmt_wait_processed(ctx); -} - -/* Destroys a CSMT context. - * Waits for the worker thread to terminate. - */ -void -nine_csmt_destroy( struct NineDevice9 *device, struct csmt_context *ctx ) -{ - struct csmt_instruction* instr; - thrd_t render_thread = ctx->worker; - - DBG("device=%p ctx=%p\n", device, ctx); - - /* Push nop and flush the queue. */ - instr = nine_queue_alloc(ctx->pool, sizeof(struct csmt_instruction)); - assert(instr); - instr->func = nop_func; - - p_atomic_set(&ctx->processed, FALSE); - /* Signal worker to terminate. */ - p_atomic_set(&ctx->terminate, TRUE); - nine_queue_flush(ctx->pool); - - nine_csmt_wait_processed(ctx); - nine_queue_delete(ctx->pool); - - mtx_destroy(&ctx->thread_resume); - mtx_destroy(&ctx->thread_running); - - mtx_destroy(&ctx->mutex_processed); - cnd_destroy(&ctx->event_processed); - - FREE(ctx); - - thrd_join(render_thread, NULL); -} - -static void -nine_csmt_pause( struct NineDevice9 *device ) -{ - struct csmt_context *ctx = device->csmt_ctx; - - if (!device->csmt_active) - return; - - /* No need to pause the thread */ - if (nine_queue_no_flushed_work(ctx->pool)) - return; - - mtx_lock(&ctx->thread_resume); - p_atomic_set(&ctx->toPause, TRUE); - - /* Wait the thread is paused */ - mtx_lock(&ctx->thread_running); - ctx->hasPaused = TRUE; - p_atomic_set(&ctx->toPause, FALSE); -} - -static void -nine_csmt_resume( struct NineDevice9 *device ) -{ - struct csmt_context *ctx = device->csmt_ctx; - - if (!device->csmt_active) - return; - - if (!ctx->hasPaused) - return; - - ctx->hasPaused = FALSE; - mtx_unlock(&ctx->thread_running); - mtx_unlock(&ctx->thread_resume); -} - -struct pipe_context * -nine_context_get_pipe( struct NineDevice9 *device ) -{ - nine_csmt_process(device); - return device->context.pipe; -} - -struct pipe_context * -nine_context_get_pipe_multithread( struct NineDevice9 *device ) -{ - struct csmt_context *ctx = device->csmt_ctx; - - if (!device->csmt_active) - return device->context.pipe; - - if (!u_thread_is_self(ctx->worker)) - nine_csmt_process(device); - - return device->context.pipe; -} - -struct pipe_context * -nine_context_get_pipe_acquire( struct NineDevice9 *device ) -{ - nine_csmt_pause(device); - return device->context.pipe; -} - -void -nine_context_get_pipe_release( struct NineDevice9 *device ) -{ - nine_csmt_resume(device); -} - -/* Nine state functions */ - -/* Check if some states need to be set dirty */ - -static inline DWORD -check_multisample(struct NineDevice9 *device) -{ - DWORD *rs = device->context.rs; - DWORD new_value = (rs[D3DRS_ZENABLE] || rs[D3DRS_STENCILENABLE]) && - device->context.rt[0]->desc.MultiSampleType >= 1 && - rs[D3DRS_MULTISAMPLEANTIALIAS]; - if (rs[NINED3DRS_MULTISAMPLE] != new_value) { - rs[NINED3DRS_MULTISAMPLE] = new_value; - return NINE_STATE_RASTERIZER; - } - return 0; -} - -/* State preparation only */ - -static inline void -prepare_blend(struct NineDevice9 *device) -{ - nine_convert_blend_state(&device->context.pipe_data.blend, device->context.rs); - device->context.commit |= NINE_STATE_COMMIT_BLEND; -} - -static inline void -prepare_dsa(struct NineDevice9 *device) -{ - nine_convert_dsa_state(&device->context.pipe_data.dsa, device->context.rs); - device->context.commit |= NINE_STATE_COMMIT_DSA; -} - -static inline void -prepare_rasterizer(struct NineDevice9 *device) -{ - nine_convert_rasterizer_state(device, &device->context.pipe_data.rast, device->context.rs); - device->context.commit |= NINE_STATE_COMMIT_RASTERIZER; -} - -static void -prepare_vs_constants_userbuf_swvp(struct NineDevice9 *device) -{ - struct nine_context *context = &device->context; - - if (context->changed.vs_const_f || context->changed.group & NINE_STATE_SWVP) { - struct pipe_constant_buffer cb; - - cb.buffer_offset = 0; - cb.buffer_size = 4096 * sizeof(float[4]); - cb.user_buffer = context->vs_const_f_swvp; - - if (context->vs->lconstf.ranges) { - const struct nine_lconstf *lconstf = &(context->vs->lconstf); - const struct nine_range *r = lconstf->ranges; - unsigned n = 0; - float *dst = context->vs_lconstf_temp; - float *src = (float *)cb.user_buffer; - memcpy(dst, src, cb.buffer_size); - while (r) { - unsigned p = r->bgn; - unsigned c = r->end - r->bgn; - memcpy(&dst[p * 4], &lconstf->data[n * 4], c * 4 * sizeof(float)); - n += c; - r = r->next; - } - cb.user_buffer = dst; - } - - context->pipe_data.cb0_swvp.buffer_offset = cb.buffer_offset; - context->pipe_data.cb0_swvp.buffer_size = cb.buffer_size; - context->pipe_data.cb0_swvp.user_buffer = cb.user_buffer; - - cb.user_buffer = (char *)cb.user_buffer + 4096 * sizeof(float[4]); - context->pipe_data.cb1_swvp.buffer_offset = cb.buffer_offset; - context->pipe_data.cb1_swvp.buffer_size = cb.buffer_size; - context->pipe_data.cb1_swvp.user_buffer = cb.user_buffer; - - context->changed.vs_const_f = 0; - } - - if (context->changed.vs_const_i || context->changed.group & NINE_STATE_SWVP) { - struct pipe_constant_buffer cb; - - cb.buffer_offset = 0; - cb.buffer_size = 2048 * sizeof(float[4]); - cb.user_buffer = context->vs_const_i; - - context->pipe_data.cb2_swvp.buffer_offset = cb.buffer_offset; - context->pipe_data.cb2_swvp.buffer_size = cb.buffer_size; - context->pipe_data.cb2_swvp.user_buffer = cb.user_buffer; - context->changed.vs_const_i = 0; - } - - if (context->changed.vs_const_b || context->changed.group & NINE_STATE_SWVP) { - struct pipe_constant_buffer cb; - - cb.buffer_offset = 0; - cb.buffer_size = 512 * sizeof(float[4]); - cb.user_buffer = context->vs_const_b; - - context->pipe_data.cb3_swvp.buffer_offset = cb.buffer_offset; - context->pipe_data.cb3_swvp.buffer_size = cb.buffer_size; - context->pipe_data.cb3_swvp.user_buffer = cb.user_buffer; - context->changed.vs_const_b = 0; - } - - context->changed.group &= ~NINE_STATE_VS_CONST; - context->commit |= NINE_STATE_COMMIT_CONST_VS; -} - -static void -prepare_vs_constants_userbuf(struct NineDevice9 *device) -{ - struct nine_context *context = &device->context; - uint8_t *upload_ptr = NULL; - struct pipe_constant_buffer cb; - cb.buffer = NULL; - cb.buffer_offset = 0; - cb.buffer_size = context->cso_shader.vs_const_used_size; - cb.user_buffer = context->vs_const_f; - - if (context->swvp) { - prepare_vs_constants_userbuf_swvp(device); - return; - } - - if (context->changed.vs_const_i || context->changed.group & NINE_STATE_SWVP) { - int *idst = (int *)&context->vs_const_f[4 * device->max_vs_const_f]; - memcpy(idst, context->vs_const_i, NINE_MAX_CONST_I * sizeof(int[4])); - context->changed.vs_const_i = 0; - } - - if (context->changed.vs_const_b || context->changed.group & NINE_STATE_SWVP) { - int *idst = (int *)&context->vs_const_f[4 * device->max_vs_const_f]; - uint32_t *bdst = (uint32_t *)&idst[4 * NINE_MAX_CONST_I]; - memcpy(bdst, context->vs_const_b, NINE_MAX_CONST_B * sizeof(BOOL)); - context->changed.vs_const_b = 0; - } - - if (!cb.buffer_size) - return; - - if (context->vs->lconstf.ranges) { - /* TODO: Can we make it so that we don't have to copy everything ? */ - const struct nine_lconstf *lconstf = &(context->vs->lconstf); - const struct nine_range *r = lconstf->ranges; - unsigned n = 0; - float *dst = context->vs_lconstf_temp; - float *src = (float *)cb.user_buffer; - memcpy(dst, src, cb.buffer_size); - while (r) { - unsigned p = r->bgn; - unsigned c = r->end - r->bgn; - memcpy(&dst[p * 4], &lconstf->data[n * 4], c * 4 * sizeof(float)); - n += c; - r = r->next; - } - cb.user_buffer = dst; - } - - /* Note: We probably don't want to do separate memcpy to - * upload_ptr directly, if we have to copy some constants - * at random locations (context->vs->lconstf.ranges), - * to have efficient WC. Thus for this case we really want - * that intermediate buffer. */ - - u_upload_alloc(context->pipe->const_uploader, - 0, - cb.buffer_size, - 256, /* Be conservative about alignment */ - &(cb.buffer_offset), - &(cb.buffer), - (void**)&upload_ptr); - - assert(cb.buffer && upload_ptr); - - if (!context->cso_shader.vs_const_ranges) { - memcpy(upload_ptr, cb.user_buffer, cb.buffer_size); - } else { - unsigned i = 0; - unsigned offset = 0; - while (context->cso_shader.vs_const_ranges[i*2+1] != 0) { - memcpy(upload_ptr+offset, - &((float*)cb.user_buffer)[4*context->cso_shader.vs_const_ranges[i*2]], - context->cso_shader.vs_const_ranges[i*2+1] * sizeof(float[4])); - offset += context->cso_shader.vs_const_ranges[i*2+1] * sizeof(float[4]); - i++; - } - } - - u_upload_unmap(context->pipe->const_uploader); - cb.user_buffer = NULL; - - /* Free previous resource */ - pipe_resource_reference(&context->pipe_data.cb_vs.buffer, NULL); - - context->pipe_data.cb_vs = cb; - context->changed.vs_const_f = 0; - - context->changed.group &= ~NINE_STATE_VS_CONST; - context->commit |= NINE_STATE_COMMIT_CONST_VS; -} - -static void -prepare_ps_constants_userbuf(struct NineDevice9 *device) -{ - struct nine_context *context = &device->context; - uint8_t *upload_ptr = NULL; - struct pipe_constant_buffer cb; - cb.buffer = NULL; - cb.buffer_offset = 0; - cb.buffer_size = context->cso_shader.ps_const_used_size; - cb.user_buffer = context->ps_const_f; - - if (context->changed.ps_const_i) { - int *idst = (int *)&context->ps_const_f[4 * device->max_ps_const_f]; - memcpy(idst, context->ps_const_i, sizeof(context->ps_const_i)); - context->changed.ps_const_i = 0; - } - if (context->changed.ps_const_b) { - int *idst = (int *)&context->ps_const_f[4 * device->max_ps_const_f]; - uint32_t *bdst = (uint32_t *)&idst[4 * NINE_MAX_CONST_I]; - memcpy(bdst, context->ps_const_b, sizeof(context->ps_const_b)); - context->changed.ps_const_b = 0; - } - - /* Upload special constants needed to implement PS1.x instructions like TEXBEM,TEXBEML and BEM */ - if (context->ps->bumpenvmat_needed) { - memcpy(context->ps_lconstf_temp, cb.user_buffer, 8 * sizeof(float[4])); - memcpy(&context->ps_lconstf_temp[4 * 8], &device->context.bumpmap_vars, sizeof(device->context.bumpmap_vars)); - - cb.user_buffer = context->ps_lconstf_temp; - } - - if (context->ps->byte_code.version < 0x30 && - context->rs[D3DRS_FOGENABLE]) { - float *dst = &context->ps_lconstf_temp[4 * 32]; - if (cb.user_buffer != context->ps_lconstf_temp) { - memcpy(context->ps_lconstf_temp, cb.user_buffer, 32 * sizeof(float[4])); - cb.user_buffer = context->ps_lconstf_temp; - } - - d3dcolor_to_rgba(dst, context->rs[D3DRS_FOGCOLOR]); - if (context->rs[D3DRS_FOGTABLEMODE] == D3DFOG_LINEAR) { - dst[4] = asfloat(context->rs[D3DRS_FOGEND]); - dst[5] = 1.0f / (asfloat(context->rs[D3DRS_FOGEND]) - asfloat(context->rs[D3DRS_FOGSTART])); - } else if (context->rs[D3DRS_FOGTABLEMODE] != D3DFOG_NONE) { - dst[4] = asfloat(context->rs[D3DRS_FOGDENSITY]); - } - } - - if (!cb.buffer_size) - return; - - u_upload_alloc(context->pipe->const_uploader, - 0, - cb.buffer_size, - 256, /* Be conservative about alignment */ - &(cb.buffer_offset), - &(cb.buffer), - (void**)&upload_ptr); - - assert(cb.buffer && upload_ptr); - - if (!context->cso_shader.ps_const_ranges) { - memcpy(upload_ptr, cb.user_buffer, cb.buffer_size); - } else { - unsigned i = 0; - unsigned offset = 0; - while (context->cso_shader.ps_const_ranges[i*2+1] != 0) { - memcpy(upload_ptr+offset, - &((float*)cb.user_buffer)[4*context->cso_shader.ps_const_ranges[i*2]], - context->cso_shader.ps_const_ranges[i*2+1] * sizeof(float[4])); - offset += context->cso_shader.ps_const_ranges[i*2+1] * sizeof(float[4]); - i++; - } - } - - u_upload_unmap(context->pipe->const_uploader); - cb.user_buffer = NULL; - - /* Free previous resource */ - pipe_resource_reference(&context->pipe_data.cb_ps.buffer, NULL); - - context->pipe_data.cb_ps = cb; - context->changed.ps_const_f = 0; - - context->changed.group &= ~NINE_STATE_PS_CONST; - context->commit |= NINE_STATE_COMMIT_CONST_PS; -} - -static inline uint32_t -prepare_vs(struct NineDevice9 *device, uint8_t shader_changed) -{ - struct nine_context *context = &device->context; - struct NineVertexShader9 *vs = context->vs; - uint32_t changed_group = 0; - int has_key_changed = 0; - - if (likely(context->programmable_vs)) - has_key_changed = NineVertexShader9_UpdateKey(vs, device); - - if (!shader_changed && !has_key_changed) - return 0; - - /* likely because we dislike FF */ - if (likely(context->programmable_vs)) { - context->cso_shader.vs = NineVertexShader9_GetVariant(vs, - &context->cso_shader.vs_const_ranges, - &context->cso_shader.vs_const_used_size); - } else { - vs = device->ff.vs; - context->cso_shader.vs = vs->ff_cso; - } - - if (context->rs[NINED3DRS_VSPOINTSIZE] != vs->point_size) { - context->rs[NINED3DRS_VSPOINTSIZE] = vs->point_size; - changed_group |= NINE_STATE_RASTERIZER; - } - - if ((context->bound_samplers_mask_vs & vs->sampler_mask) != vs->sampler_mask) - /* Bound dummy sampler. */ - changed_group |= NINE_STATE_SAMPLER; - - context->commit |= NINE_STATE_COMMIT_VS; - return changed_group; -} - -static inline uint32_t -prepare_ps(struct NineDevice9 *device, uint8_t shader_changed) -{ - struct nine_context *context = &device->context; - struct NinePixelShader9 *ps = context->ps; - uint32_t changed_group = 0; - int has_key_changed = 0; - - if (likely(ps)) - has_key_changed = NinePixelShader9_UpdateKey(ps, context); - - if (!shader_changed && !has_key_changed) - return 0; - - if (likely(ps)) { - context->cso_shader.ps = NinePixelShader9_GetVariant(ps, - &context->cso_shader.ps_const_ranges, - &context->cso_shader.ps_const_used_size); - } else { - ps = device->ff.ps; - context->cso_shader.ps = ps->ff_cso; - } - - if ((context->bound_samplers_mask_ps & ps->sampler_mask) != ps->sampler_mask) - /* Bound dummy sampler. */ - changed_group |= NINE_STATE_SAMPLER; - - context->commit |= NINE_STATE_COMMIT_PS; - return changed_group; -} - -/* State preparation incremental */ - -/* State preparation + State commit */ - -static void -update_framebuffer(struct NineDevice9 *device, bool is_clear) -{ - struct nine_context *context = &device->context; - struct pipe_context *pipe = context->pipe; - struct pipe_framebuffer_state *fb = &context->pipe_data.fb; - unsigned i; - struct NineSurface9 *rt0 = context->rt[0]; - unsigned w = rt0->desc.Width; - unsigned h = rt0->desc.Height; - unsigned nr_samples = rt0->base.info.nr_samples; - unsigned ps_mask = context->ps ? context->ps->rt_mask : 1; - unsigned mask = is_clear ? 0xf : ps_mask; - const int sRGB = context->rs[D3DRS_SRGBWRITEENABLE] ? 1 : 0; - - DBG("\n"); - - context->rt_mask = 0x0; - fb->nr_cbufs = 0; - - /* all render targets must have the same size and the depth buffer must be - * bigger. Multisample has to match, according to spec. But some apps do - * things wrong there, and no error is returned. The behaviour they get - * apparently is that depth buffer is disabled if it doesn't match. - * Surely the same for render targets. */ - - /* Special case: D3DFMT_NULL is used to bound no real render target, - * but render to depth buffer. We have to not take into account the render - * target info. TODO: know what should happen when there are several render targers - * and the first one is D3DFMT_NULL */ - if (rt0->desc.Format == D3DFMT_NULL && context->ds) { - w = context->ds->desc.Width; - h = context->ds->desc.Height; - nr_samples = context->ds->base.info.nr_samples; - } - - for (i = 0; i < device->caps.NumSimultaneousRTs; ++i) { - struct NineSurface9 *rt = context->rt[i]; - - if (rt && rt->desc.Format != D3DFMT_NULL && (mask & (1 << i)) && - rt->desc.Width == w && rt->desc.Height == h && - rt->base.info.nr_samples == nr_samples) { - fb->cbufs[i] = NineSurface9_GetSurface(rt, sRGB); - context->rt_mask |= 1 << i; - fb->nr_cbufs = i + 1; - } else { - /* Color outputs must match RT slot, - * drivers will have to handle NULL entries for GL, too. - */ - fb->cbufs[i] = NULL; - } - } - - if (context->ds && context->ds->desc.Width >= w && - context->ds->desc.Height >= h && - context->ds->base.info.nr_samples == nr_samples) { - fb->zsbuf = NineSurface9_GetSurface(context->ds, 0); - } else { - fb->zsbuf = NULL; - } - - fb->width = w; - fb->height = h; - - pipe->set_framebuffer_state(pipe, fb); /* XXX: cso ? */ - - if (is_clear && context->rt_mask == ps_mask) - context->changed.group &= ~NINE_STATE_FB; -} - -static void -update_viewport(struct NineDevice9 *device) -{ - struct nine_context *context = &device->context; - const D3DVIEWPORT9 *vport = &context->viewport; - struct pipe_viewport_state pvport; - - /* D3D coordinates are: - * -1 .. +1 for X,Y and - * 0 .. +1 for Z (we use pipe_rasterizer_state.clip_halfz) - */ - pvport.scale[0] = (float)vport->Width * 0.5f; - pvport.scale[1] = (float)vport->Height * -0.5f; - pvport.scale[2] = vport->MaxZ - vport->MinZ; - pvport.translate[0] = (float)vport->Width * 0.5f + (float)vport->X; - pvport.translate[1] = (float)vport->Height * 0.5f + (float)vport->Y; - pvport.translate[2] = vport->MinZ; - - /* We found R600 and SI cards have some imprecision - * on the barycentric coordinates used for interpolation. - * Some shaders rely on having something precise. - * We found that the proprietary driver has the imprecision issue, - * except when the render target width and height are powers of two. - * It is using some sort of workaround for these cases - * which covers likely all the cases the applications rely - * on something precise. - * We haven't found the workaround, but it seems like it's better - * for applications if the imprecision is biased towards infinity - * instead of -infinity (which is what measured). So shift slightly - * the viewport: not enough to change rasterization result (in particular - * for multisampling), but enough to make the imprecision biased - * towards infinity. We do this shift only if render target width and - * height are powers of two. - * Solves 'red shadows' bug on UE3 games. - */ - if (device->driver_bugs.buggy_barycentrics && - ((vport->Width & (vport->Width-1)) == 0) && - ((vport->Height & (vport->Height-1)) == 0)) { - pvport.translate[0] -= 1.0f / 128.0f; - pvport.translate[1] -= 1.0f / 128.0f; - } - - cso_set_viewport(context->cso, &pvport); -} - -/* Loop through VS inputs and pick the vertex elements with the declared - * usage from the vertex declaration, then insert the instance divisor from - * the stream source frequency setting. - */ -static void -update_vertex_elements(struct NineDevice9 *device) -{ - struct nine_context *context = &device->context; - const struct NineVertexDeclaration9 *vdecl = device->context.vdecl; - const struct NineVertexShader9 *vs; - unsigned n, b, i; - int index; - char vdecl_index_map[16]; /* vs->num_inputs <= 16 */ - char used_streams[device->caps.MaxStreams]; - int dummy_vbo_stream = -1; - BOOL need_dummy_vbo = FALSE; - struct cso_velems_state ve; - - context->stream_usage_mask = 0; - memset(vdecl_index_map, -1, 16); - memset(used_streams, 0, device->caps.MaxStreams); - vs = context->programmable_vs ? context->vs : device->ff.vs; - - if (vdecl) { - for (n = 0; n < vs->num_inputs; ++n) { - DBG("looking up input %u (usage %u) from vdecl(%p)\n", - n, vs->input_map[n].ndecl, vdecl); - - for (i = 0; i < vdecl->nelems; i++) { - if (vdecl->usage_map[i] == vs->input_map[n].ndecl) { - vdecl_index_map[n] = i; - used_streams[vdecl->elems[i].vertex_buffer_index] = 1; - break; - } - } - if (vdecl_index_map[n] < 0) - need_dummy_vbo = TRUE; - } - } else { - /* No vertex declaration. Likely will never happen in practice, - * but we need not crash on this */ - need_dummy_vbo = TRUE; - } - - if (need_dummy_vbo) { - for (i = 0; i < device->caps.MaxStreams; i++ ) { - if (!used_streams[i]) { - dummy_vbo_stream = i; - break; - } - } - } - /* there are less vertex shader inputs than stream slots, - * so if we need a slot for the dummy vbo, we should have found one */ - assert (!need_dummy_vbo || dummy_vbo_stream != -1); - - for (n = 0; n < vs->num_inputs; ++n) { - index = vdecl_index_map[n]; - if (index >= 0) { - ve.velems[n] = vdecl->elems[index]; - b = ve.velems[n].vertex_buffer_index; - context->stream_usage_mask |= 1 << b; - /* XXX wine just uses 1 here: */ - if (context->stream_freq[b] & D3DSTREAMSOURCE_INSTANCEDATA) - ve.velems[n].instance_divisor = context->stream_freq[b] & 0x7FFFFF; - } else { - /* if the vertex declaration is incomplete compared to what the - * vertex shader needs, we bind a dummy vbo with 0 0 0 0. - * This is not precised by the spec, but is the behaviour - * tested on win */ - ve.velems[n].vertex_buffer_index = dummy_vbo_stream; - ve.velems[n].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; - ve.velems[n].src_offset = 0; - ve.velems[n].instance_divisor = 0; - } - } - - if (context->dummy_vbo_bound_at != dummy_vbo_stream) { - if (context->dummy_vbo_bound_at >= 0) - context->changed.vtxbuf |= 1 << context->dummy_vbo_bound_at; - if (dummy_vbo_stream >= 0) { - context->changed.vtxbuf |= 1 << dummy_vbo_stream; - context->vbo_bound_done = FALSE; - } - context->dummy_vbo_bound_at = dummy_vbo_stream; - } - - ve.count = vs->num_inputs; - cso_set_vertex_elements(context->cso, &ve); -} - -static void -update_vertex_buffers(struct NineDevice9 *device) -{ - struct nine_context *context = &device->context; - struct pipe_context *pipe = context->pipe; - struct pipe_vertex_buffer dummy_vtxbuf; - uint32_t mask = context->changed.vtxbuf; - unsigned i; - - DBG("mask=%x\n", mask); - - if (context->dummy_vbo_bound_at >= 0) { - if (!context->vbo_bound_done) { - dummy_vtxbuf.buffer.resource = device->dummy_vbo; - dummy_vtxbuf.stride = 0; - dummy_vtxbuf.is_user_buffer = false; - dummy_vtxbuf.buffer_offset = 0; - pipe->set_vertex_buffers(pipe, context->dummy_vbo_bound_at, - 1, &dummy_vtxbuf); - context->vbo_bound_done = TRUE; - } - mask &= ~(1 << context->dummy_vbo_bound_at); - } - - for (i = 0; mask; mask >>= 1, ++i) { - if (mask & 1) { - if (context->vtxbuf[i].buffer.resource) - pipe->set_vertex_buffers(pipe, i, 1, &context->vtxbuf[i]); - else - pipe->set_vertex_buffers(pipe, i, 1, NULL); - } - } - - context->changed.vtxbuf = 0; -} - -static inline boolean -update_sampler_derived(struct nine_context *context, unsigned s) -{ - boolean changed = FALSE; - - if (context->samp[s][NINED3DSAMP_SHADOW] != context->texture[s].shadow) { - changed = TRUE; - context->samp[s][NINED3DSAMP_SHADOW] = context->texture[s].shadow; - } - - if (context->samp[s][NINED3DSAMP_CUBETEX] != - (context->texture[s].type == D3DRTYPE_CUBETEXTURE)) { - changed = TRUE; - context->samp[s][NINED3DSAMP_CUBETEX] = - context->texture[s].type == D3DRTYPE_CUBETEXTURE; - } - - if (context->samp[s][D3DSAMP_MIPFILTER] != D3DTEXF_NONE) { - int lod = context->samp[s][D3DSAMP_MAXMIPLEVEL] - context->texture[s].lod; - if (lod < 0) - lod = 0; - if (context->samp[s][NINED3DSAMP_MINLOD] != lod) { - changed = TRUE; - context->samp[s][NINED3DSAMP_MINLOD] = lod; - } - } else { - context->changed.sampler[s] &= ~0x300; /* lod changes irrelevant */ - } - - return changed; -} - -/* TODO: add sRGB override to pipe_sampler_state ? */ -static void -update_textures_and_samplers(struct NineDevice9 *device) -{ - struct nine_context *context = &device->context; - struct pipe_sampler_view *view[NINE_MAX_SAMPLERS]; - unsigned num_textures; - unsigned i; - boolean commit_samplers; - uint16_t sampler_mask = context->ps ? context->ps->sampler_mask : - device->ff.ps->sampler_mask; - - /* TODO: Can we reduce iterations here ? */ - - commit_samplers = FALSE; - context->bound_samplers_mask_ps = 0; - for (num_textures = 0, i = 0; i < NINE_MAX_SAMPLERS_PS; ++i) { - const unsigned s = NINE_SAMPLER_PS(i); - int sRGB; - - if (!context->texture[s].enabled && !(sampler_mask & (1 << i))) { - view[i] = NULL; - continue; - } - - if (context->texture[s].enabled) { - sRGB = context->samp[s][D3DSAMP_SRGBTEXTURE] ? 1 : 0; - - view[i] = context->texture[s].view[sRGB]; - num_textures = i + 1; - - if (update_sampler_derived(context, s) || (context->changed.sampler[s] & 0x05fe)) { - context->changed.sampler[s] = 0; - commit_samplers = TRUE; - nine_convert_sampler_state(context->cso, s, context->samp[s]); - } - } else { - /* Bind dummy sampler. We do not bind dummy sampler when - * it is not needed because it could add overhead. The - * dummy sampler should have r=g=b=0 and a=1. We do not - * unbind dummy sampler directly when they are not needed - * anymore, but they're going to be removed as long as texture - * or sampler states are changed. */ - view[i] = device->dummy_sampler_view; - num_textures = i + 1; - - cso_single_sampler(context->cso, PIPE_SHADER_FRAGMENT, - s - NINE_SAMPLER_PS(0), &device->dummy_sampler_state); - - commit_samplers = TRUE; - context->changed.sampler[s] = ~0; - } - - context->bound_samplers_mask_ps |= (1 << s); - } - - cso_set_sampler_views(context->cso, PIPE_SHADER_FRAGMENT, num_textures, view); - - if (commit_samplers) - cso_single_sampler_done(context->cso, PIPE_SHADER_FRAGMENT); - - commit_samplers = FALSE; - sampler_mask = context->programmable_vs ? context->vs->sampler_mask : 0; - context->bound_samplers_mask_vs = 0; - for (num_textures = 0, i = 0; i < NINE_MAX_SAMPLERS_VS; ++i) { - const unsigned s = NINE_SAMPLER_VS(i); - int sRGB; - - if (!context->texture[s].enabled && !(sampler_mask & (1 << i))) { - view[i] = NULL; - continue; - } - - if (context->texture[s].enabled) { - sRGB = context->samp[s][D3DSAMP_SRGBTEXTURE] ? 1 : 0; - - view[i] = context->texture[s].view[sRGB]; - num_textures = i + 1; - - if (update_sampler_derived(context, s) || (context->changed.sampler[s] & 0x05fe)) { - context->changed.sampler[s] = 0; - commit_samplers = TRUE; - nine_convert_sampler_state(context->cso, s, context->samp[s]); - } - } else { - /* Bind dummy sampler. We do not bind dummy sampler when - * it is not needed because it could add overhead. The - * dummy sampler should have r=g=b=0 and a=1. We do not - * unbind dummy sampler directly when they are not needed - * anymore, but they're going to be removed as long as texture - * or sampler states are changed. */ - view[i] = device->dummy_sampler_view; - num_textures = i + 1; - - cso_single_sampler(context->cso, PIPE_SHADER_VERTEX, - s - NINE_SAMPLER_VS(0), &device->dummy_sampler_state); - - commit_samplers = TRUE; - context->changed.sampler[s] = ~0; - } - - context->bound_samplers_mask_vs |= (1 << i); - } - - cso_set_sampler_views(context->cso, PIPE_SHADER_VERTEX, num_textures, view); - - if (commit_samplers) - cso_single_sampler_done(context->cso, PIPE_SHADER_VERTEX); -} - -/* State commit only */ - -static inline void -commit_blend(struct NineDevice9 *device) -{ - struct nine_context *context = &device->context; - - cso_set_blend(context->cso, &context->pipe_data.blend); -} - -static inline void -commit_dsa(struct NineDevice9 *device) -{ - struct nine_context *context = &device->context; - - cso_set_depth_stencil_alpha(context->cso, &context->pipe_data.dsa); -} - -static inline void -commit_scissor(struct NineDevice9 *device) -{ - struct nine_context *context = &device->context; - struct pipe_context *pipe = context->pipe; - - pipe->set_scissor_states(pipe, 0, 1, &context->scissor); -} - -static inline void -commit_rasterizer(struct NineDevice9 *device) -{ - struct nine_context *context = &device->context; - - cso_set_rasterizer(context->cso, &context->pipe_data.rast); -} - -static inline void -commit_vs_constants(struct NineDevice9 *device) -{ - struct nine_context *context = &device->context; - struct pipe_context *pipe = context->pipe; - - if (unlikely(!context->programmable_vs)) - pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 0, &context->pipe_data.cb_vs_ff); - else { - if (context->swvp) { - pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 0, &context->pipe_data.cb0_swvp); - pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 1, &context->pipe_data.cb1_swvp); - pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 2, &context->pipe_data.cb2_swvp); - pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 3, &context->pipe_data.cb3_swvp); - } else { - pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 0, &context->pipe_data.cb_vs); - } - } -} - -static inline void -commit_ps_constants(struct NineDevice9 *device) -{ - struct nine_context *context = &device->context; - struct pipe_context *pipe = context->pipe; - - if (unlikely(!context->ps)) - pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, 0, &context->pipe_data.cb_ps_ff); - else - pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, 0, &context->pipe_data.cb_ps); -} - -static inline void -commit_vs(struct NineDevice9 *device) -{ - struct nine_context *context = &device->context; - - context->pipe->bind_vs_state(context->pipe, context->cso_shader.vs); -} - - -static inline void -commit_ps(struct NineDevice9 *device) -{ - struct nine_context *context = &device->context; - - context->pipe->bind_fs_state(context->pipe, context->cso_shader.ps); -} -/* State Update */ - -#define NINE_STATE_SHADER_CHANGE_VS \ - (NINE_STATE_VS | \ - NINE_STATE_TEXTURE | \ - NINE_STATE_VS_PARAMS_MISC | \ - NINE_STATE_SWVP) - -#define NINE_STATE_SHADER_CHANGE_PS \ - (NINE_STATE_PS | \ - NINE_STATE_TEXTURE | \ - NINE_STATE_PS_PARAMS_MISC) - -#define NINE_STATE_FREQUENT \ - (NINE_STATE_RASTERIZER | \ - NINE_STATE_TEXTURE | \ - NINE_STATE_SAMPLER | \ - NINE_STATE_VS_CONST | \ - NINE_STATE_PS_CONST | \ - NINE_STATE_MULTISAMPLE) - -#define NINE_STATE_COMMON \ - (NINE_STATE_FB | \ - NINE_STATE_BLEND | \ - NINE_STATE_DSA | \ - NINE_STATE_VIEWPORT | \ - NINE_STATE_VDECL | \ - NINE_STATE_IDXBUF | \ - NINE_STATE_STREAMFREQ) - -#define NINE_STATE_RARE \ - (NINE_STATE_SCISSOR | \ - NINE_STATE_BLEND_COLOR | \ - NINE_STATE_STENCIL_REF | \ - NINE_STATE_SAMPLE_MASK) - -static void -nine_update_state(struct NineDevice9 *device) -{ - struct nine_context *context = &device->context; - struct pipe_context *pipe = context->pipe; - uint32_t group; - - DBG("changed state groups: %x\n", context->changed.group); - - /* NOTE: We may want to use the cso cache for everything, or let - * NineDevice9.RestoreNonCSOState actually set the states, then we wouldn't - * have to care about state being clobbered here and could merge this back - * into update_textures. Except, we also need to re-validate textures that - * may be dirty anyway, even if no texture bindings changed. - */ - - /* ff_update may change VS/PS dirty bits */ - if (unlikely(!context->programmable_vs || !context->ps)) - nine_ff_update(device); - group = context->changed.group; - - if (group & (NINE_STATE_SHADER_CHANGE_VS | NINE_STATE_SHADER_CHANGE_PS)) { - if (group & NINE_STATE_SHADER_CHANGE_VS) - group |= prepare_vs(device, (group & NINE_STATE_VS) != 0); /* may set NINE_STATE_RASTERIZER and NINE_STATE_SAMPLER*/ - if (group & NINE_STATE_SHADER_CHANGE_PS) - group |= prepare_ps(device, (group & NINE_STATE_PS) != 0); - } - - if (group & (NINE_STATE_COMMON | NINE_STATE_VS)) { - if (group & NINE_STATE_FB) - update_framebuffer(device, FALSE); - if (group & NINE_STATE_BLEND) - prepare_blend(device); - if (group & NINE_STATE_DSA) - prepare_dsa(device); - if (group & NINE_STATE_VIEWPORT) - update_viewport(device); - if (group & (NINE_STATE_VDECL | NINE_STATE_VS | NINE_STATE_STREAMFREQ)) - update_vertex_elements(device); - } - - if (likely(group & (NINE_STATE_FREQUENT | NINE_STATE_VS | NINE_STATE_PS | NINE_STATE_SWVP))) { - if (group & NINE_STATE_MULTISAMPLE) - group |= check_multisample(device); - if (group & NINE_STATE_RASTERIZER) - prepare_rasterizer(device); - if (group & (NINE_STATE_TEXTURE | NINE_STATE_SAMPLER)) - update_textures_and_samplers(device); - if ((group & (NINE_STATE_VS_CONST | NINE_STATE_VS | NINE_STATE_SWVP)) && context->programmable_vs) - prepare_vs_constants_userbuf(device); - if ((group & (NINE_STATE_PS_CONST | NINE_STATE_PS)) && context->ps) - prepare_ps_constants_userbuf(device); - } - - if (context->changed.vtxbuf) - update_vertex_buffers(device); - - if (context->commit & NINE_STATE_COMMIT_BLEND) - commit_blend(device); - if (context->commit & NINE_STATE_COMMIT_DSA) - commit_dsa(device); - if (context->commit & NINE_STATE_COMMIT_RASTERIZER) - commit_rasterizer(device); - if (context->commit & NINE_STATE_COMMIT_CONST_VS) - commit_vs_constants(device); - if (context->commit & NINE_STATE_COMMIT_CONST_PS) - commit_ps_constants(device); - if (context->commit & NINE_STATE_COMMIT_VS) - commit_vs(device); - if (context->commit & NINE_STATE_COMMIT_PS) - commit_ps(device); - - context->commit = 0; - - if (unlikely(context->changed.ucp)) { - pipe->set_clip_state(pipe, &context->clip); - context->changed.ucp = FALSE; - } - - if (unlikely(group & NINE_STATE_RARE)) { - if (group & NINE_STATE_SCISSOR) - commit_scissor(device); - if (group & NINE_STATE_BLEND_COLOR) { - struct pipe_blend_color color; - d3dcolor_to_rgba(&color.color[0], context->rs[D3DRS_BLENDFACTOR]); - pipe->set_blend_color(pipe, &color); - } - if (group & NINE_STATE_SAMPLE_MASK) { - if (context->rt[0]->desc.MultiSampleType <= D3DMULTISAMPLE_NONMASKABLE) { - pipe->set_sample_mask(pipe, ~0); - } else { - pipe->set_sample_mask(pipe, context->rs[D3DRS_MULTISAMPLEMASK]); - } - } - if (group & NINE_STATE_STENCIL_REF) { - struct pipe_stencil_ref ref; - ref.ref_value[0] = context->rs[D3DRS_STENCILREF]; - ref.ref_value[1] = ref.ref_value[0]; - pipe->set_stencil_ref(pipe, &ref); - } - } - - context->changed.group &= - (NINE_STATE_FF | NINE_STATE_VS_CONST | NINE_STATE_PS_CONST); - - DBG("finished\n"); -} - -#define RESZ_CODE 0x7fa05000 - -static void -NineDevice9_ResolveZ( struct NineDevice9 *device ) -{ - struct nine_context *context = &device->context; - const struct util_format_description *desc; - struct NineSurface9 *source = context->ds; - struct pipe_resource *src, *dst; - struct pipe_blit_info blit; - - DBG("RESZ resolve\n"); - - if (!source || !context->texture[0].enabled || - context->texture[0].type != D3DRTYPE_TEXTURE) - return; - - src = source->base.resource; - dst = context->texture[0].resource; - - if (!src || !dst) - return; - - /* check dst is depth format. we know already for src */ - desc = util_format_description(dst->format); - if (desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS) - return; - - memset(&blit, 0, sizeof(blit)); - blit.src.resource = src; - blit.src.level = 0; - blit.src.format = src->format; - blit.src.box.z = 0; - blit.src.box.depth = 1; - blit.src.box.x = 0; - blit.src.box.y = 0; - blit.src.box.width = src->width0; - blit.src.box.height = src->height0; - - blit.dst.resource = dst; - blit.dst.level = 0; - blit.dst.format = dst->format; - blit.dst.box.z = 0; - blit.dst.box.depth = 1; - blit.dst.box.x = 0; - blit.dst.box.y = 0; - blit.dst.box.width = dst->width0; - blit.dst.box.height = dst->height0; - - blit.mask = PIPE_MASK_ZS; - blit.filter = PIPE_TEX_FILTER_NEAREST; - blit.scissor_enable = FALSE; - - context->pipe->blit(context->pipe, &blit); -} - -#define ALPHA_TO_COVERAGE_ENABLE MAKEFOURCC('A', '2', 'M', '1') -#define ALPHA_TO_COVERAGE_DISABLE MAKEFOURCC('A', '2', 'M', '0') - -/* Nine_context functions. - * Serialized through CSMT macros. - */ - -static void -nine_context_set_texture_apply(struct NineDevice9 *device, - DWORD stage, - BOOL enabled, - BOOL shadow, - DWORD lod, - D3DRESOURCETYPE type, - uint8_t pstype, - struct pipe_resource *res, - struct pipe_sampler_view *view0, - struct pipe_sampler_view *view1); -static void -nine_context_set_stream_source_apply(struct NineDevice9 *device, - UINT StreamNumber, - struct pipe_resource *res, - UINT OffsetInBytes, - UINT Stride); - -static void -nine_context_set_indices_apply(struct NineDevice9 *device, - struct pipe_resource *res, - UINT IndexSize, - UINT OffsetInBytes); - -static void -nine_context_set_pixel_shader_constant_i_transformed(struct NineDevice9 *device, - UINT StartRegister, - const int *pConstantData, - unsigned pConstantData_size, - UINT Vector4iCount); - -CSMT_ITEM_NO_WAIT(nine_context_set_render_state, - ARG_VAL(D3DRENDERSTATETYPE, State), - ARG_VAL(DWORD, Value)) -{ - struct nine_context *context = &device->context; - - /* Amd hacks (equivalent to GL extensions) */ - if (unlikely(State == D3DRS_POINTSIZE)) { - if (Value == RESZ_CODE) { - NineDevice9_ResolveZ(device); - return; - } - - if (Value == ALPHA_TO_COVERAGE_ENABLE || - Value == ALPHA_TO_COVERAGE_DISABLE) { - context->rs[NINED3DRS_ALPHACOVERAGE] = (Value == ALPHA_TO_COVERAGE_ENABLE); - context->changed.group |= NINE_STATE_BLEND; - return; - } - } - - /* NV hack */ - if (unlikely(State == D3DRS_ADAPTIVETESS_Y)) { - if (Value == D3DFMT_ATOC || (Value == D3DFMT_UNKNOWN && context->rs[NINED3DRS_ALPHACOVERAGE])) { - context->rs[NINED3DRS_ALPHACOVERAGE] = (Value == D3DFMT_ATOC) ? 3 : 0; - context->rs[NINED3DRS_ALPHACOVERAGE] &= context->rs[D3DRS_ALPHATESTENABLE] ? 3 : 2; - context->changed.group |= NINE_STATE_BLEND; - return; - } - } - if (unlikely(State == D3DRS_ALPHATESTENABLE && (context->rs[NINED3DRS_ALPHACOVERAGE] & 2))) { - DWORD alphacoverage_prev = context->rs[NINED3DRS_ALPHACOVERAGE]; - context->rs[NINED3DRS_ALPHACOVERAGE] = (Value ? 3 : 2); - if (context->rs[NINED3DRS_ALPHACOVERAGE] != alphacoverage_prev) - context->changed.group |= NINE_STATE_BLEND; - } - - context->rs[State] = nine_fix_render_state_value(State, Value); - context->changed.group |= nine_render_state_group[State]; -} - -CSMT_ITEM_NO_WAIT(nine_context_set_texture_apply, - ARG_VAL(DWORD, stage), - ARG_VAL(BOOL, enabled), - ARG_VAL(BOOL, shadow), - ARG_VAL(DWORD, lod), - ARG_VAL(D3DRESOURCETYPE, type), - ARG_VAL(uint8_t, pstype), - ARG_BIND_RES(struct pipe_resource, res), - ARG_BIND_VIEW(struct pipe_sampler_view, view0), - ARG_BIND_VIEW(struct pipe_sampler_view, view1)) -{ - struct nine_context *context = &device->context; - - context->texture[stage].enabled = enabled; - context->samplers_shadow &= ~(1 << stage); - context->samplers_shadow |= shadow << stage; - context->texture[stage].shadow = shadow; - context->texture[stage].lod = lod; - context->texture[stage].type = type; - context->texture[stage].pstype = pstype; - pipe_resource_reference(&context->texture[stage].resource, res); - pipe_sampler_view_reference(&context->texture[stage].view[0], view0); - pipe_sampler_view_reference(&context->texture[stage].view[1], view1); - - context->changed.group |= NINE_STATE_TEXTURE; -} - -void -nine_context_set_texture(struct NineDevice9 *device, - DWORD Stage, - struct NineBaseTexture9 *tex) -{ - BOOL enabled = FALSE; - BOOL shadow = FALSE; - DWORD lod = 0; - D3DRESOURCETYPE type = D3DRTYPE_TEXTURE; - uint8_t pstype = 0; - struct pipe_resource *res = NULL; - struct pipe_sampler_view *view0 = NULL, *view1 = NULL; - - /* For managed pool, the data can be initially incomplete. - * In that case, the texture is rebound later - * (in NineBaseTexture9_Validate/NineBaseTexture9_UploadSelf). */ - if (tex && tex->base.resource) { - enabled = TRUE; - shadow = tex->shadow; - lod = tex->managed.lod; - type = tex->base.type; - pstype = tex->pstype; - res = tex->base.resource; - view0 = NineBaseTexture9_GetSamplerView(tex, 0); - view1 = NineBaseTexture9_GetSamplerView(tex, 1); - } - - nine_context_set_texture_apply(device, Stage, enabled, - shadow, lod, type, pstype, - res, view0, view1); -} - -CSMT_ITEM_NO_WAIT(nine_context_set_sampler_state, - ARG_VAL(DWORD, Sampler), - ARG_VAL(D3DSAMPLERSTATETYPE, Type), - ARG_VAL(DWORD, Value)) -{ - struct nine_context *context = &device->context; - - if (unlikely(!nine_check_sampler_state_value(Type, Value))) - return; - - context->samp[Sampler][Type] = Value; - context->changed.group |= NINE_STATE_SAMPLER; - context->changed.sampler[Sampler] |= 1 << Type; -} - -CSMT_ITEM_NO_WAIT(nine_context_set_stream_source_apply, - ARG_VAL(UINT, StreamNumber), - ARG_BIND_RES(struct pipe_resource, res), - ARG_VAL(UINT, OffsetInBytes), - ARG_VAL(UINT, Stride)) -{ - struct nine_context *context = &device->context; - const unsigned i = StreamNumber; - - context->vtxbuf[i].stride = Stride; - context->vtxbuf[i].buffer_offset = OffsetInBytes; - pipe_resource_reference(&context->vtxbuf[i].buffer.resource, res); - - context->changed.vtxbuf |= 1 << StreamNumber; -} - -void -nine_context_set_stream_source(struct NineDevice9 *device, - UINT StreamNumber, - struct NineVertexBuffer9 *pVBuf9, - UINT OffsetInBytes, - UINT Stride) -{ - struct pipe_resource *res = NULL; - unsigned offset = 0; - - if (pVBuf9) - res = NineVertexBuffer9_GetResource(pVBuf9, &offset); - /* in the future when there is internal offset, add it - * to OffsetInBytes */ - - nine_context_set_stream_source_apply(device, StreamNumber, - res, offset + OffsetInBytes, - Stride); -} - -CSMT_ITEM_NO_WAIT(nine_context_set_stream_source_freq, - ARG_VAL(UINT, StreamNumber), - ARG_VAL(UINT, Setting)) -{ - struct nine_context *context = &device->context; - - context->stream_freq[StreamNumber] = Setting; - - if (Setting & D3DSTREAMSOURCE_INSTANCEDATA) - context->stream_instancedata_mask |= 1 << StreamNumber; - else - context->stream_instancedata_mask &= ~(1 << StreamNumber); - - if (StreamNumber != 0) - context->changed.group |= NINE_STATE_STREAMFREQ; -} - -CSMT_ITEM_NO_WAIT(nine_context_set_indices_apply, - ARG_BIND_RES(struct pipe_resource, res), - ARG_VAL(UINT, IndexSize), - ARG_VAL(UINT, OffsetInBytes)) -{ - struct nine_context *context = &device->context; - - context->index_size = IndexSize; - context->index_offset = OffsetInBytes; - pipe_resource_reference(&context->idxbuf, res); - - context->changed.group |= NINE_STATE_IDXBUF; -} - -void -nine_context_set_indices(struct NineDevice9 *device, - struct NineIndexBuffer9 *idxbuf) -{ - struct pipe_resource *res = NULL; - UINT IndexSize = 0; - unsigned OffsetInBytes = 0; - - if (idxbuf) { - res = NineIndexBuffer9_GetBuffer(idxbuf, &OffsetInBytes); - IndexSize = idxbuf->index_size; - } - - nine_context_set_indices_apply(device, res, IndexSize, OffsetInBytes); -} - -CSMT_ITEM_NO_WAIT(nine_context_set_vertex_declaration, - ARG_BIND_REF(struct NineVertexDeclaration9, vdecl)) -{ - struct nine_context *context = &device->context; - BOOL was_programmable_vs = context->programmable_vs; - - nine_bind(&context->vdecl, vdecl); - - context->programmable_vs = context->vs && !(context->vdecl && context->vdecl->position_t); - if (was_programmable_vs != context->programmable_vs) { - context->commit |= NINE_STATE_COMMIT_CONST_VS; - context->changed.group |= NINE_STATE_VS; - } - - context->changed.group |= NINE_STATE_VDECL; -} - -CSMT_ITEM_NO_WAIT(nine_context_set_vertex_shader, - ARG_BIND_REF(struct NineVertexShader9, pShader)) -{ - struct nine_context *context = &device->context; - BOOL was_programmable_vs = context->programmable_vs; - - nine_bind(&context->vs, pShader); - - context->programmable_vs = context->vs && !(context->vdecl && context->vdecl->position_t); - - /* ff -> non-ff: commit back non-ff constants */ - if (!was_programmable_vs && context->programmable_vs) - context->commit |= NINE_STATE_COMMIT_CONST_VS; - - context->changed.group |= NINE_STATE_VS; -} - -CSMT_ITEM_NO_WAIT(nine_context_set_vertex_shader_constant_f, - ARG_VAL(UINT, StartRegister), - ARG_MEM(float, pConstantData), - ARG_MEM_SIZE(unsigned, pConstantData_size), - ARG_VAL(UINT, Vector4fCount)) -{ - struct nine_context *context = &device->context; - float *vs_const_f = device->may_swvp ? context->vs_const_f_swvp : context->vs_const_f; - - memcpy(&vs_const_f[StartRegister * 4], - pConstantData, - pConstantData_size); - - if (device->may_swvp) { - Vector4fCount = MIN2(StartRegister + Vector4fCount, NINE_MAX_CONST_F) - StartRegister; - if (StartRegister < NINE_MAX_CONST_F) - memcpy(&context->vs_const_f[StartRegister * 4], - pConstantData, - Vector4fCount * 4 * sizeof(context->vs_const_f[0])); - } - - context->changed.vs_const_f = TRUE; - context->changed.group |= NINE_STATE_VS_CONST; -} - -CSMT_ITEM_NO_WAIT(nine_context_set_vertex_shader_constant_i, - ARG_VAL(UINT, StartRegister), - ARG_MEM(int, pConstantData), - ARG_MEM_SIZE(unsigned, pConstantData_size), - ARG_VAL(UINT, Vector4iCount)) -{ - struct nine_context *context = &device->context; - int i; - - if (device->driver_caps.vs_integer) { - memcpy(&context->vs_const_i[4 * StartRegister], - pConstantData, - pConstantData_size); - } else { - for (i = 0; i < Vector4iCount; i++) { - context->vs_const_i[4 * (StartRegister + i)] = fui((float)(pConstantData[4 * i])); - context->vs_const_i[4 * (StartRegister + i) + 1] = fui((float)(pConstantData[4 * i + 1])); - context->vs_const_i[4 * (StartRegister + i) + 2] = fui((float)(pConstantData[4 * i + 2])); - context->vs_const_i[4 * (StartRegister + i) + 3] = fui((float)(pConstantData[4 * i + 3])); - } - } - - context->changed.vs_const_i = TRUE; - context->changed.group |= NINE_STATE_VS_CONST | NINE_STATE_VS_PARAMS_MISC; -} - -CSMT_ITEM_NO_WAIT(nine_context_set_vertex_shader_constant_b, - ARG_VAL(UINT, StartRegister), - ARG_MEM(BOOL, pConstantData), - ARG_MEM_SIZE(unsigned, pConstantData_size), - ARG_VAL(UINT, BoolCount)) -{ - struct nine_context *context = &device->context; - int i; - uint32_t bool_true = device->driver_caps.vs_integer ? 0xFFFFFFFF : fui(1.0f); - - (void) pConstantData_size; - - for (i = 0; i < BoolCount; i++) - context->vs_const_b[StartRegister + i] = pConstantData[i] ? bool_true : 0; - - context->changed.vs_const_b = TRUE; - context->changed.group |= NINE_STATE_VS_CONST | NINE_STATE_VS_PARAMS_MISC; -} - -CSMT_ITEM_NO_WAIT(nine_context_set_pixel_shader, - ARG_BIND_REF(struct NinePixelShader9, ps)) -{ - struct nine_context *context = &device->context; - unsigned old_mask = context->ps ? context->ps->rt_mask : 1; - unsigned mask; - - /* ff -> non-ff: commit back non-ff constants */ - if (!context->ps && ps) - context->commit |= NINE_STATE_COMMIT_CONST_PS; - - nine_bind(&context->ps, ps); - - context->changed.group |= NINE_STATE_PS; - - mask = context->ps ? context->ps->rt_mask : 1; - /* We need to update cbufs if the pixel shader would - * write to different render targets */ - if (mask != old_mask) - context->changed.group |= NINE_STATE_FB; -} - -CSMT_ITEM_NO_WAIT(nine_context_set_pixel_shader_constant_f, - ARG_VAL(UINT, StartRegister), - ARG_MEM(float, pConstantData), - ARG_MEM_SIZE(unsigned, pConstantData_size), - ARG_VAL(UINT, Vector4fCount)) -{ - struct nine_context *context = &device->context; - - memcpy(&context->ps_const_f[StartRegister * 4], - pConstantData, - pConstantData_size); - - context->changed.ps_const_f = TRUE; - context->changed.group |= NINE_STATE_PS_CONST; -} - -/* For stateblocks */ -CSMT_ITEM_NO_WAIT(nine_context_set_pixel_shader_constant_i_transformed, - ARG_VAL(UINT, StartRegister), - ARG_MEM(int, pConstantData), - ARG_MEM_SIZE(unsigned, pConstantData_size), - ARG_VAL(UINT, Vector4iCount)) -{ - struct nine_context *context = &device->context; - - memcpy(&context->ps_const_i[StartRegister][0], - pConstantData, - Vector4iCount * sizeof(context->ps_const_i[0])); - - context->changed.ps_const_i = TRUE; - context->changed.group |= NINE_STATE_PS_CONST | NINE_STATE_PS_PARAMS_MISC; -} - -CSMT_ITEM_NO_WAIT(nine_context_set_pixel_shader_constant_i, - ARG_VAL(UINT, StartRegister), - ARG_MEM(int, pConstantData), - ARG_MEM_SIZE(unsigned, pConstantData_size), - ARG_VAL(UINT, Vector4iCount)) -{ - struct nine_context *context = &device->context; - int i; - - if (device->driver_caps.ps_integer) { - memcpy(&context->ps_const_i[StartRegister][0], - pConstantData, - pConstantData_size); - } else { - for (i = 0; i < Vector4iCount; i++) { - context->ps_const_i[StartRegister+i][0] = fui((float)(pConstantData[4*i])); - context->ps_const_i[StartRegister+i][1] = fui((float)(pConstantData[4*i+1])); - context->ps_const_i[StartRegister+i][2] = fui((float)(pConstantData[4*i+2])); - context->ps_const_i[StartRegister+i][3] = fui((float)(pConstantData[4*i+3])); - } - } - context->changed.ps_const_i = TRUE; - context->changed.group |= NINE_STATE_PS_CONST | NINE_STATE_PS_PARAMS_MISC; -} - -CSMT_ITEM_NO_WAIT(nine_context_set_pixel_shader_constant_b, - ARG_VAL(UINT, StartRegister), - ARG_MEM(BOOL, pConstantData), - ARG_MEM_SIZE(unsigned, pConstantData_size), - ARG_VAL(UINT, BoolCount)) -{ - struct nine_context *context = &device->context; - int i; - uint32_t bool_true = device->driver_caps.ps_integer ? 0xFFFFFFFF : fui(1.0f); - - (void) pConstantData_size; - - for (i = 0; i < BoolCount; i++) - context->ps_const_b[StartRegister + i] = pConstantData[i] ? bool_true : 0; - - context->changed.ps_const_b = TRUE; - context->changed.group |= NINE_STATE_PS_CONST | NINE_STATE_PS_PARAMS_MISC; -} - -/* XXX: use resource, as resource might change */ -CSMT_ITEM_NO_WAIT(nine_context_set_render_target, - ARG_VAL(DWORD, RenderTargetIndex), - ARG_BIND_REF(struct NineSurface9, rt)) -{ - struct nine_context *context = &device->context; - const unsigned i = RenderTargetIndex; - - if (i == 0) { - context->viewport.X = 0; - context->viewport.Y = 0; - context->viewport.Width = rt->desc.Width; - context->viewport.Height = rt->desc.Height; - context->viewport.MinZ = 0.0f; - context->viewport.MaxZ = 1.0f; - - context->scissor.minx = 0; - context->scissor.miny = 0; - context->scissor.maxx = rt->desc.Width; - context->scissor.maxy = rt->desc.Height; - - context->changed.group |= NINE_STATE_VIEWPORT | NINE_STATE_SCISSOR | NINE_STATE_MULTISAMPLE; - - if (context->rt[0] && - (context->rt[0]->desc.MultiSampleType <= D3DMULTISAMPLE_NONMASKABLE) != - (rt->desc.MultiSampleType <= D3DMULTISAMPLE_NONMASKABLE)) - context->changed.group |= NINE_STATE_SAMPLE_MASK; - } - - if (context->rt[i] != rt) { - nine_bind(&context->rt[i], rt); - context->changed.group |= NINE_STATE_FB; - } -} - -/* XXX: use resource instead of ds, as resource might change */ -CSMT_ITEM_NO_WAIT(nine_context_set_depth_stencil, - ARG_BIND_REF(struct NineSurface9, ds)) -{ - struct nine_context *context = &device->context; - - nine_bind(&context->ds, ds); - context->changed.group |= NINE_STATE_FB; -} - -CSMT_ITEM_NO_WAIT(nine_context_set_viewport, - ARG_COPY_REF(D3DVIEWPORT9, viewport)) -{ - struct nine_context *context = &device->context; - - context->viewport = *viewport; - context->changed.group |= NINE_STATE_VIEWPORT; -} - -CSMT_ITEM_NO_WAIT(nine_context_set_scissor, - ARG_COPY_REF(struct pipe_scissor_state, scissor)) -{ - struct nine_context *context = &device->context; - - context->scissor = *scissor; - context->changed.group |= NINE_STATE_SCISSOR; -} - -CSMT_ITEM_NO_WAIT(nine_context_set_transform, - ARG_VAL(D3DTRANSFORMSTATETYPE, State), - ARG_COPY_REF(D3DMATRIX, pMatrix)) -{ - struct nine_context *context = &device->context; - D3DMATRIX *M = nine_state_access_transform(&context->ff, State, TRUE); - - *M = *pMatrix; - context->ff.changed.transform[State / 32] |= 1 << (State % 32); - context->changed.group |= NINE_STATE_FF; -} - -CSMT_ITEM_NO_WAIT(nine_context_set_material, - ARG_COPY_REF(D3DMATERIAL9, pMaterial)) -{ - struct nine_context *context = &device->context; - - context->ff.material = *pMaterial; - context->changed.group |= NINE_STATE_FF_MATERIAL; -} - -CSMT_ITEM_NO_WAIT(nine_context_set_light, - ARG_VAL(DWORD, Index), - ARG_COPY_REF(D3DLIGHT9, pLight)) -{ - struct nine_context *context = &device->context; - - (void)nine_state_set_light(&context->ff, Index, pLight); - context->changed.group |= NINE_STATE_FF_LIGHTING; -} - - -/* For stateblocks */ -static void -nine_context_light_enable_stateblock(struct NineDevice9 *device, - const uint16_t active_light[NINE_MAX_LIGHTS_ACTIVE], /* TODO: use pointer that convey size for csmt */ - unsigned int num_lights_active) -{ - struct nine_context *context = &device->context; - - /* TODO: Use CSMT_* to avoid calling nine_csmt_process */ - nine_csmt_process(device); - memcpy(context->ff.active_light, active_light, NINE_MAX_LIGHTS_ACTIVE * sizeof(context->ff.active_light[0])); - context->ff.num_lights_active = num_lights_active; - context->changed.group |= NINE_STATE_FF_LIGHTING; -} - -CSMT_ITEM_NO_WAIT(nine_context_light_enable, - ARG_VAL(DWORD, Index), - ARG_VAL(BOOL, Enable)) -{ - struct nine_context *context = &device->context; - - nine_state_light_enable(&context->ff, Index, Enable); - context->changed.group |= NINE_STATE_FF_LIGHTING; -} - -CSMT_ITEM_NO_WAIT(nine_context_set_texture_stage_state, - ARG_VAL(DWORD, Stage), - ARG_VAL(D3DTEXTURESTAGESTATETYPE, Type), - ARG_VAL(DWORD, Value)) -{ - struct nine_context *context = &device->context; - int bumpmap_index = -1; - - context->ff.tex_stage[Stage][Type] = Value; - switch (Type) { - case D3DTSS_BUMPENVMAT00: - bumpmap_index = 4 * Stage; - break; - case D3DTSS_BUMPENVMAT01: - bumpmap_index = 4 * Stage + 1; - break; - case D3DTSS_BUMPENVMAT10: - bumpmap_index = 4 * Stage + 2; - break; - case D3DTSS_BUMPENVMAT11: - bumpmap_index = 4 * Stage + 3; - break; - case D3DTSS_BUMPENVLSCALE: - bumpmap_index = 4 * 8 + 2 * Stage; - break; - case D3DTSS_BUMPENVLOFFSET: - bumpmap_index = 4 * 8 + 2 * Stage + 1; - break; - case D3DTSS_TEXTURETRANSFORMFLAGS: - context->changed.group |= NINE_STATE_PS_PARAMS_MISC; - break; - default: - break; - } - - if (bumpmap_index >= 0) { - context->bumpmap_vars[bumpmap_index] = Value; - context->changed.group |= NINE_STATE_PS_CONST; - } - - context->changed.group |= NINE_STATE_FF_PS_CONSTS; - context->ff.changed.tex_stage[Stage][Type / 32] |= 1 << (Type % 32); -} - -CSMT_ITEM_NO_WAIT(nine_context_set_clip_plane, - ARG_VAL(DWORD, Index), - ARG_COPY_REF(struct nine_clipplane, pPlane)) -{ - struct nine_context *context = &device->context; - - memcpy(&context->clip.ucp[Index][0], pPlane, sizeof(context->clip.ucp[0])); - context->changed.ucp = TRUE; -} - -CSMT_ITEM_NO_WAIT(nine_context_set_swvp, - ARG_VAL(boolean, swvp)) -{ - struct nine_context *context = &device->context; - - context->swvp = swvp; - context->changed.group |= NINE_STATE_SWVP; -} - -/* Do not write to nine_context directly. Slower, - * but works with csmt. TODO: write a special csmt version that - * would record the list of commands as much as possible, - * and use the version above else. - */ -void -nine_context_apply_stateblock(struct NineDevice9 *device, - const struct nine_state *src) -{ - int i; - - /* No need to apply src->changed.group, since all calls do - * set context->changed.group */ - - for (i = 0; i < ARRAY_SIZE(src->changed.rs); ++i) { - uint32_t m = src->changed.rs[i]; - while (m) { - const int r = ffs(m) - 1; - m &= ~(1 << r); - nine_context_set_render_state(device, i * 32 + r, src->rs_advertised[i * 32 + r]); - } - } - - /* Textures */ - if (src->changed.texture) { - uint32_t m = src->changed.texture; - unsigned s; - - for (s = 0; m; ++s, m >>= 1) { - struct NineBaseTexture9 *tex = src->texture[s]; - if (!(m & 1)) - continue; - nine_context_set_texture(device, s, tex); - } - } - - /* Sampler state */ - if (src->changed.group & NINE_STATE_SAMPLER) { - unsigned s; - - for (s = 0; s < NINE_MAX_SAMPLERS; ++s) { - uint32_t m = src->changed.sampler[s]; - while (m) { - const int i = ffs(m) - 1; - m &= ~(1 << i); - nine_context_set_sampler_state(device, s, i, src->samp_advertised[s][i]); - } - } - } - - /* Vertex buffers */ - if (src->changed.vtxbuf | src->changed.stream_freq) { - uint32_t m = src->changed.vtxbuf | src->changed.stream_freq; - for (i = 0; m; ++i, m >>= 1) { - if (src->changed.vtxbuf & (1 << i)) - nine_context_set_stream_source(device, i, src->stream[i], src->vtxbuf[i].buffer_offset, src->vtxbuf[i].stride); - if (src->changed.stream_freq & (1 << i)) - nine_context_set_stream_source_freq(device, i, src->stream_freq[i]); - } - } - - /* Index buffer */ - if (src->changed.group & NINE_STATE_IDXBUF) - nine_context_set_indices(device, src->idxbuf); - - /* Vertex declaration */ - if ((src->changed.group & NINE_STATE_VDECL) && src->vdecl) - nine_context_set_vertex_declaration(device, src->vdecl); - - /* Vertex shader */ - if (src->changed.group & NINE_STATE_VS) - nine_context_set_vertex_shader(device, src->vs); - - /* Pixel shader */ - if (src->changed.group & NINE_STATE_PS) - nine_context_set_pixel_shader(device, src->ps); - - /* Vertex constants */ - if (src->changed.group & NINE_STATE_VS_CONST) { - struct nine_range *r; - for (r = src->changed.vs_const_f; r; r = r->next) - nine_context_set_vertex_shader_constant_f(device, r->bgn, - &src->vs_const_f[r->bgn * 4], - sizeof(float[4]) * (r->end - r->bgn), - r->end - r->bgn); - for (r = src->changed.vs_const_i; r; r = r->next) - nine_context_set_vertex_shader_constant_i(device, r->bgn, - &src->vs_const_i[r->bgn * 4], - sizeof(int[4]) * (r->end - r->bgn), - r->end - r->bgn); - for (r = src->changed.vs_const_b; r; r = r->next) - nine_context_set_vertex_shader_constant_b(device, r->bgn, - &src->vs_const_b[r->bgn * 4], - sizeof(BOOL) * (r->end - r->bgn), - r->end - r->bgn); - } - - /* Pixel constants */ - if (src->changed.group & NINE_STATE_PS_CONST) { - struct nine_range *r; - for (r = src->changed.ps_const_f; r; r = r->next) - nine_context_set_pixel_shader_constant_f(device, r->bgn, - &src->ps_const_f[r->bgn * 4], - sizeof(float[4]) * (r->end - r->bgn), - r->end - r->bgn); - if (src->changed.ps_const_i) { - uint16_t m = src->changed.ps_const_i; - for (i = ffs(m) - 1, m >>= i; m; ++i, m >>= 1) - if (m & 1) - nine_context_set_pixel_shader_constant_i_transformed(device, i, - src->ps_const_i[i], sizeof(int[4]), 1); - } - if (src->changed.ps_const_b) { - uint16_t m = src->changed.ps_const_b; - for (i = ffs(m) - 1, m >>= i; m; ++i, m >>= 1) - if (m & 1) - nine_context_set_pixel_shader_constant_b(device, i, - &src->ps_const_b[i], sizeof(BOOL), 1); - } - } - - /* Viewport */ - if (src->changed.group & NINE_STATE_VIEWPORT) - nine_context_set_viewport(device, &src->viewport); - - /* Scissor */ - if (src->changed.group & NINE_STATE_SCISSOR) - nine_context_set_scissor(device, &src->scissor); - - /* User Clip Planes */ - if (src->changed.ucp) - for (i = 0; i < PIPE_MAX_CLIP_PLANES; ++i) - if (src->changed.ucp & (1 << i)) - nine_context_set_clip_plane(device, i, (struct nine_clipplane*)&src->clip.ucp[i][0]); - - if (!(src->changed.group & NINE_STATE_FF)) - return; - - /* Fixed function state. */ - - if (src->changed.group & NINE_STATE_FF_MATERIAL) - nine_context_set_material(device, &src->ff.material); - - if (src->changed.group & NINE_STATE_FF_PS_CONSTS) { - unsigned s; - for (s = 0; s < NINE_MAX_TEXTURE_STAGES; ++s) { - for (i = 0; i < NINED3DTSS_COUNT; ++i) - if (src->ff.changed.tex_stage[s][i / 32] & (1 << (i % 32))) - nine_context_set_texture_stage_state(device, s, i, src->ff.tex_stage[s][i]); - } - } - if (src->changed.group & NINE_STATE_FF_LIGHTING) { - for (i = 0; i < src->ff.num_lights; ++i) - if (src->ff.light[i].Type != NINED3DLIGHT_INVALID) - nine_context_set_light(device, i, &src->ff.light[i]); - - nine_context_light_enable_stateblock(device, src->ff.active_light, src->ff.num_lights_active); - } - if (src->changed.group & NINE_STATE_FF_VSTRANSF) { - for (i = 0; i < ARRAY_SIZE(src->ff.changed.transform); ++i) { - unsigned s; - if (!src->ff.changed.transform[i]) - continue; - for (s = i * 32; s < (i * 32 + 32); ++s) { - if (!(src->ff.changed.transform[i] & (1 << (s % 32)))) - continue; - /* MaxVertexBlendMatrixIndex is 8, which means - * we don't read past index D3DTS_WORLDMATRIX(8). - * swvp is supposed to allow all 256, but we don't - * implement it for now. */ - if (s > D3DTS_WORLDMATRIX(8)) - break; - nine_context_set_transform(device, s, - nine_state_access_transform( - (struct nine_ff_state *)&src->ff, - s, FALSE)); - } - } - } -} - -static void -nine_update_state_framebuffer_clear(struct NineDevice9 *device) -{ - struct nine_context *context = &device->context; - - if (context->changed.group & NINE_STATE_FB) - update_framebuffer(device, TRUE); -} - -CSMT_ITEM_NO_WAIT(nine_context_clear_fb, - ARG_VAL(DWORD, Count), - ARG_COPY_REF(D3DRECT, pRects), - ARG_VAL(DWORD, Flags), - ARG_VAL(D3DCOLOR, Color), - ARG_VAL(float, Z), - ARG_VAL(DWORD, Stencil)) -{ - struct nine_context *context = &device->context; - const int sRGB = context->rs[D3DRS_SRGBWRITEENABLE] ? 1 : 0; - struct pipe_surface *cbuf, *zsbuf; - struct pipe_context *pipe = context->pipe; - struct NineSurface9 *zsbuf_surf = context->ds; - struct NineSurface9 *rt; - unsigned bufs = 0; - unsigned r, i; - union pipe_color_union rgba; - unsigned rt_mask = 0; - D3DRECT rect; - - nine_update_state_framebuffer_clear(device); - - if (Flags & D3DCLEAR_TARGET) bufs |= PIPE_CLEAR_COLOR; - /* Ignore Z buffer if not bound */ - if (context->pipe_data.fb.zsbuf != NULL) { - if (Flags & D3DCLEAR_ZBUFFER) bufs |= PIPE_CLEAR_DEPTH; - if (Flags & D3DCLEAR_STENCIL) bufs |= PIPE_CLEAR_STENCIL; - } - if (!bufs) - return; - d3dcolor_to_pipe_color_union(&rgba, Color); - - rect.x1 = context->viewport.X; - rect.y1 = context->viewport.Y; - rect.x2 = context->viewport.Width + rect.x1; - rect.y2 = context->viewport.Height + rect.y1; - - /* Both rectangles apply, which is weird, but that's D3D9. */ - if (context->rs[D3DRS_SCISSORTESTENABLE]) { - rect.x1 = MAX2(rect.x1, context->scissor.minx); - rect.y1 = MAX2(rect.y1, context->scissor.miny); - rect.x2 = MIN2(rect.x2, context->scissor.maxx); - rect.y2 = MIN2(rect.y2, context->scissor.maxy); - } - - if (Count) { - /* Maybe apps like to specify a large rect ? */ - if (pRects[0].x1 <= rect.x1 && pRects[0].x2 >= rect.x2 && - pRects[0].y1 <= rect.y1 && pRects[0].y2 >= rect.y2) { - DBG("First rect covers viewport.\n"); - Count = 0; - pRects = NULL; - } - } - - if (rect.x1 >= context->pipe_data.fb.width || rect.y1 >= context->pipe_data.fb.height) - return; - - for (i = 0; i < device->caps.NumSimultaneousRTs; ++i) { - if (context->rt[i] && context->rt[i]->desc.Format != D3DFMT_NULL) - rt_mask |= 1 << i; - } - - /* fast path, clears everything at once */ - if (!Count && - (!(bufs & PIPE_CLEAR_COLOR) || (rt_mask == context->rt_mask)) && - rect.x1 == 0 && rect.y1 == 0 && - /* Case we clear only render target. Check clear region vs rt. */ - ((!(bufs & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL)) && - rect.x2 >= context->pipe_data.fb.width && - rect.y2 >= context->pipe_data.fb.height) || - /* Case we clear depth buffer (and eventually rt too). - * depth buffer size is always >= rt size. Compare to clear region */ - ((bufs & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL)) && - rect.x2 >= zsbuf_surf->desc.Width && - rect.y2 >= zsbuf_surf->desc.Height))) { - DBG("Clear fast path\n"); - pipe->clear(pipe, bufs, NULL, &rgba, Z, Stencil); - return; - } - - if (!Count) { - Count = 1; - pRects = ▭ - } - - for (i = 0; i < device->caps.NumSimultaneousRTs; ++i) { - rt = context->rt[i]; - if (!rt || rt->desc.Format == D3DFMT_NULL || - !(bufs & PIPE_CLEAR_COLOR)) - continue; /* save space, compiler should hoist this */ - cbuf = NineSurface9_GetSurface(rt, sRGB); - for (r = 0; r < Count; ++r) { - /* Don't trust users to pass these in the right order. */ - unsigned x1 = MIN2(pRects[r].x1, pRects[r].x2); - unsigned y1 = MIN2(pRects[r].y1, pRects[r].y2); - unsigned x2 = MAX2(pRects[r].x1, pRects[r].x2); - unsigned y2 = MAX2(pRects[r].y1, pRects[r].y2); -#ifndef NINE_LAX - /* Drop negative rectangles (like wine expects). */ - if (pRects[r].x1 > pRects[r].x2) continue; - if (pRects[r].y1 > pRects[r].y2) continue; -#endif - - x1 = MAX2(x1, rect.x1); - y1 = MAX2(y1, rect.y1); - x2 = MIN3(x2, rect.x2, rt->desc.Width); - y2 = MIN3(y2, rect.y2, rt->desc.Height); - - DBG("Clearing (%u..%u)x(%u..%u)\n", x1, x2, y1, y2); - pipe->clear_render_target(pipe, cbuf, &rgba, - x1, y1, x2 - x1, y2 - y1, false); - } - } - if (!(bufs & PIPE_CLEAR_DEPTHSTENCIL)) - return; - - bufs &= PIPE_CLEAR_DEPTHSTENCIL; - - for (r = 0; r < Count; ++r) { - unsigned x1 = MIN2(pRects[r].x1, pRects[r].x2); - unsigned y1 = MIN2(pRects[r].y1, pRects[r].y2); - unsigned x2 = MAX2(pRects[r].x1, pRects[r].x2); - unsigned y2 = MAX2(pRects[r].y1, pRects[r].y2); -#ifndef NINE_LAX - /* Drop negative rectangles. */ - if (pRects[r].x1 > pRects[r].x2) continue; - if (pRects[r].y1 > pRects[r].y2) continue; -#endif - - x1 = MIN2(x1, rect.x1); - y1 = MIN2(y1, rect.y1); - x2 = MIN3(x2, rect.x2, zsbuf_surf->desc.Width); - y2 = MIN3(y2, rect.y2, zsbuf_surf->desc.Height); - - zsbuf = NineSurface9_GetSurface(zsbuf_surf, 0); - assert(zsbuf); - pipe->clear_depth_stencil(pipe, zsbuf, bufs, Z, Stencil, - x1, y1, x2 - x1, y2 - y1, false); - } - return; -} - - -static inline void -init_draw_info(struct pipe_draw_info *info, - struct NineDevice9 *dev, D3DPRIMITIVETYPE type, UINT count) -{ - info->mode = d3dprimitivetype_to_pipe_prim(type); - info->count = prim_count_to_vertex_count(type, count); - info->start_instance = 0; - info->instance_count = 1; - if (dev->context.stream_instancedata_mask & dev->context.stream_usage_mask) - info->instance_count = MAX2(dev->context.stream_freq[0] & 0x7FFFFF, 1); - info->primitive_restart = FALSE; - info->has_user_indices = FALSE; - info->restart_index = 0; - info->count_from_stream_output = NULL; - info->indirect = NULL; -} - -CSMT_ITEM_NO_WAIT(nine_context_draw_primitive, - ARG_VAL(D3DPRIMITIVETYPE, PrimitiveType), - ARG_VAL(UINT, StartVertex), - ARG_VAL(UINT, PrimitiveCount)) -{ - struct nine_context *context = &device->context; - struct pipe_draw_info info; - - nine_update_state(device); - - init_draw_info(&info, device, PrimitiveType, PrimitiveCount); - info.index_size = 0; - info.start = StartVertex; - info.index_bias = 0; - info.min_index = info.start; - info.max_index = info.count - 1; - info.index.resource = NULL; - - context->pipe->draw_vbo(context->pipe, &info); -} - -CSMT_ITEM_NO_WAIT(nine_context_draw_indexed_primitive, - ARG_VAL(D3DPRIMITIVETYPE, PrimitiveType), - ARG_VAL(INT, BaseVertexIndex), - ARG_VAL(UINT, MinVertexIndex), - ARG_VAL(UINT, NumVertices), - ARG_VAL(UINT, StartIndex), - ARG_VAL(UINT, PrimitiveCount)) -{ - struct nine_context *context = &device->context; - struct pipe_draw_info info; - - nine_update_state(device); - - init_draw_info(&info, device, PrimitiveType, PrimitiveCount); - info.index_size = context->index_size; - info.start = context->index_offset / context->index_size + StartIndex; - info.index_bias = BaseVertexIndex; - /* These don't include index bias: */ - info.min_index = MinVertexIndex; - info.max_index = MinVertexIndex + NumVertices - 1; - info.index.resource = context->idxbuf; - - context->pipe->draw_vbo(context->pipe, &info); -} - -CSMT_ITEM_NO_WAIT(nine_context_draw_primitive_from_vtxbuf, - ARG_VAL(D3DPRIMITIVETYPE, PrimitiveType), - ARG_VAL(UINT, PrimitiveCount), - ARG_BIND_VBUF(struct pipe_vertex_buffer, vtxbuf)) -{ - struct nine_context *context = &device->context; - struct pipe_draw_info info; - - nine_update_state(device); - - init_draw_info(&info, device, PrimitiveType, PrimitiveCount); - info.index_size = 0; - info.start = 0; - info.index_bias = 0; - info.min_index = 0; - info.max_index = info.count - 1; - info.index.resource = NULL; - - context->pipe->set_vertex_buffers(context->pipe, 0, 1, vtxbuf); - - context->pipe->draw_vbo(context->pipe, &info); -} - -CSMT_ITEM_NO_WAIT(nine_context_draw_indexed_primitive_from_vtxbuf_idxbuf, - ARG_VAL(D3DPRIMITIVETYPE, PrimitiveType), - ARG_VAL(UINT, MinVertexIndex), - ARG_VAL(UINT, NumVertices), - ARG_VAL(UINT, PrimitiveCount), - ARG_BIND_VBUF(struct pipe_vertex_buffer, vbuf), - ARG_BIND_RES(struct pipe_resource, ibuf), - ARG_VAL(void *, user_ibuf), - ARG_VAL(UINT, index_offset), - ARG_VAL(UINT, index_size)) -{ - struct nine_context *context = &device->context; - struct pipe_draw_info info; - - nine_update_state(device); - - init_draw_info(&info, device, PrimitiveType, PrimitiveCount); - info.index_size = index_size; - info.start = index_offset / info.index_size; - info.index_bias = 0; - info.min_index = MinVertexIndex; - info.max_index = MinVertexIndex + NumVertices - 1; - info.has_user_indices = ibuf == NULL; - if (ibuf) - info.index.resource = ibuf; - else - info.index.user = user_ibuf; - - context->pipe->set_vertex_buffers(context->pipe, 0, 1, vbuf); - - context->pipe->draw_vbo(context->pipe, &info); -} - -CSMT_ITEM_NO_WAIT(nine_context_resource_copy_region, - ARG_BIND_REF(struct NineUnknown, dst), - ARG_BIND_REF(struct NineUnknown, src), - ARG_BIND_RES(struct pipe_resource, dst_res), - ARG_VAL(unsigned, dst_level), - ARG_COPY_REF(struct pipe_box, dst_box), - ARG_BIND_RES(struct pipe_resource, src_res), - ARG_VAL(unsigned, src_level), - ARG_COPY_REF(struct pipe_box, src_box)) -{ - struct nine_context *context = &device->context; - - (void) dst; - (void) src; - - context->pipe->resource_copy_region(context->pipe, - dst_res, dst_level, - dst_box->x, dst_box->y, dst_box->z, - src_res, src_level, - src_box); -} - -CSMT_ITEM_NO_WAIT(nine_context_blit, - ARG_BIND_REF(struct NineUnknown, dst), - ARG_BIND_REF(struct NineUnknown, src), - ARG_BIND_BLIT(struct pipe_blit_info, blit)) -{ - struct nine_context *context = &device->context; - - (void) dst; - (void) src; - - context->pipe->blit(context->pipe, blit); -} - -CSMT_ITEM_NO_WAIT(nine_context_clear_render_target, - ARG_BIND_REF(struct NineSurface9, surface), - ARG_VAL(D3DCOLOR, color), - ARG_VAL(UINT, x), - ARG_VAL(UINT, y), - ARG_VAL(UINT, width), - ARG_VAL(UINT, height)) -{ - struct nine_context *context = &device->context; - struct pipe_surface *surf; - union pipe_color_union rgba; - - d3dcolor_to_pipe_color_union(&rgba, color); - surf = NineSurface9_GetSurface(surface, 0); - context->pipe->clear_render_target(context->pipe, surf, &rgba, x, y, width, height, false); -} - -CSMT_ITEM_NO_WAIT(nine_context_gen_mipmap, - ARG_BIND_REF(struct NineUnknown, dst), - ARG_BIND_RES(struct pipe_resource, res), - ARG_VAL(UINT, base_level), - ARG_VAL(UINT, last_level), - ARG_VAL(UINT, first_layer), - ARG_VAL(UINT, last_layer), - ARG_VAL(UINT, filter)) -{ - struct nine_context *context = &device->context; - - /* We just bind dst for the bind count */ - (void)dst; - - util_gen_mipmap(context->pipe, res, res->format, base_level, - last_level, first_layer, last_layer, filter); -} - -CSMT_ITEM_NO_WAIT_WITH_COUNTER(nine_context_range_upload, - ARG_BIND_REF(struct NineUnknown, src_ref), - ARG_BIND_RES(struct pipe_resource, res), - ARG_VAL(unsigned, offset), - ARG_VAL(unsigned, size), - ARG_VAL(const void *, data)) -{ - struct nine_context *context = &device->context; - - /* Binding src_ref avoids release before upload */ - (void)src_ref; - - context->pipe->buffer_subdata(context->pipe, res, 0, offset, size, data); -} - -CSMT_ITEM_NO_WAIT_WITH_COUNTER(nine_context_box_upload, - ARG_BIND_REF(struct NineUnknown, src_ref), - ARG_BIND_RES(struct pipe_resource, res), - ARG_VAL(unsigned, level), - ARG_COPY_REF(struct pipe_box, dst_box), - ARG_VAL(enum pipe_format, src_format), - ARG_VAL(const void *, src), - ARG_VAL(unsigned, src_stride), - ARG_VAL(unsigned, src_layer_stride), - ARG_COPY_REF(struct pipe_box, src_box)) -{ - struct nine_context *context = &device->context; - struct pipe_context *pipe = context->pipe; - struct pipe_transfer *transfer = NULL; - uint8_t *map; - - /* Binding src_ref avoids release before upload */ - (void)src_ref; - - map = pipe->transfer_map(pipe, - res, - level, - PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE, - dst_box, &transfer); - if (!map) - return; - - /* Note: if formats are the sames, it will revert - * to normal memcpy */ - (void) util_format_translate_3d(res->format, - map, transfer->stride, - transfer->layer_stride, - 0, 0, 0, - src_format, - src, src_stride, - src_layer_stride, - src_box->x, src_box->y, src_box->z, - dst_box->width, dst_box->height, - dst_box->depth); - - pipe_transfer_unmap(pipe, transfer); -} - -struct pipe_query * -nine_context_create_query(struct NineDevice9 *device, unsigned query_type) -{ - struct pipe_context *pipe; - struct pipe_query *res; - - pipe = nine_context_get_pipe_acquire(device); - res = pipe->create_query(pipe, query_type, 0); - nine_context_get_pipe_release(device); - return res; -} - -CSMT_ITEM_DO_WAIT(nine_context_destroy_query, - ARG_REF(struct pipe_query, query)) -{ - struct nine_context *context = &device->context; - - context->pipe->destroy_query(context->pipe, query); -} - -CSMT_ITEM_NO_WAIT_WITH_COUNTER(nine_context_begin_query, - ARG_REF(struct pipe_query, query)) -{ - struct nine_context *context = &device->context; - - (void) context->pipe->begin_query(context->pipe, query); -} - -CSMT_ITEM_NO_WAIT_WITH_COUNTER(nine_context_end_query, - ARG_REF(struct pipe_query, query)) -{ - struct nine_context *context = &device->context; - - (void) context->pipe->end_query(context->pipe, query); -} - -boolean -nine_context_get_query_result(struct NineDevice9 *device, struct pipe_query *query, - unsigned *counter, boolean flush, boolean wait, - union pipe_query_result *result) -{ - struct pipe_context *pipe; - boolean ret; - - if (wait) - nine_csmt_process(device); - else if (p_atomic_read(counter) > 0) { - if (flush && device->csmt_active) - nine_queue_flush(device->csmt_ctx->pool); - DBG("Pending begin/end. Returning\n"); - return false; - } - - pipe = nine_context_get_pipe_acquire(device); - ret = pipe->get_query_result(pipe, query, wait, result); - nine_context_get_pipe_release(device); - - DBG("Query result %s\n", ret ? "found" : "not yet available"); - return ret; -} - -/* State defaults */ - -static const DWORD nine_render_state_defaults[NINED3DRS_LAST + 1] = -{ - /* [D3DRS_ZENABLE] = D3DZB_TRUE; wine: auto_depth_stencil */ - [D3DRS_ZENABLE] = D3DZB_FALSE, - [D3DRS_FILLMODE] = D3DFILL_SOLID, - [D3DRS_SHADEMODE] = D3DSHADE_GOURAUD, -/* [D3DRS_LINEPATTERN] = 0x00000000, */ - [D3DRS_ZWRITEENABLE] = TRUE, - [D3DRS_ALPHATESTENABLE] = FALSE, - [D3DRS_LASTPIXEL] = TRUE, - [D3DRS_SRCBLEND] = D3DBLEND_ONE, - [D3DRS_DESTBLEND] = D3DBLEND_ZERO, - [D3DRS_CULLMODE] = D3DCULL_CCW, - [D3DRS_ZFUNC] = D3DCMP_LESSEQUAL, - [D3DRS_ALPHAFUNC] = D3DCMP_ALWAYS, - [D3DRS_ALPHAREF] = 0, - [D3DRS_DITHERENABLE] = FALSE, - [D3DRS_ALPHABLENDENABLE] = FALSE, - [D3DRS_FOGENABLE] = FALSE, - [D3DRS_SPECULARENABLE] = FALSE, -/* [D3DRS_ZVISIBLE] = 0, */ - [D3DRS_FOGCOLOR] = 0, - [D3DRS_FOGTABLEMODE] = D3DFOG_NONE, - [D3DRS_FOGSTART] = 0x00000000, - [D3DRS_FOGEND] = 0x3F800000, - [D3DRS_FOGDENSITY] = 0x3F800000, -/* [D3DRS_EDGEANTIALIAS] = FALSE, */ - [D3DRS_RANGEFOGENABLE] = FALSE, - [D3DRS_STENCILENABLE] = FALSE, - [D3DRS_STENCILFAIL] = D3DSTENCILOP_KEEP, - [D3DRS_STENCILZFAIL] = D3DSTENCILOP_KEEP, - [D3DRS_STENCILPASS] = D3DSTENCILOP_KEEP, - [D3DRS_STENCILREF] = 0, - [D3DRS_STENCILMASK] = 0xFFFFFFFF, - [D3DRS_STENCILFUNC] = D3DCMP_ALWAYS, - [D3DRS_STENCILWRITEMASK] = 0xFFFFFFFF, - [D3DRS_TEXTUREFACTOR] = 0xFFFFFFFF, - [D3DRS_WRAP0] = 0, - [D3DRS_WRAP1] = 0, - [D3DRS_WRAP2] = 0, - [D3DRS_WRAP3] = 0, - [D3DRS_WRAP4] = 0, - [D3DRS_WRAP5] = 0, - [D3DRS_WRAP6] = 0, - [D3DRS_WRAP7] = 0, - [D3DRS_CLIPPING] = TRUE, - [D3DRS_LIGHTING] = TRUE, - [D3DRS_AMBIENT] = 0, - [D3DRS_FOGVERTEXMODE] = D3DFOG_NONE, - [D3DRS_COLORVERTEX] = TRUE, - [D3DRS_LOCALVIEWER] = TRUE, - [D3DRS_NORMALIZENORMALS] = FALSE, - [D3DRS_DIFFUSEMATERIALSOURCE] = D3DMCS_COLOR1, - [D3DRS_SPECULARMATERIALSOURCE] = D3DMCS_COLOR2, - [D3DRS_AMBIENTMATERIALSOURCE] = D3DMCS_MATERIAL, - [D3DRS_EMISSIVEMATERIALSOURCE] = D3DMCS_MATERIAL, - [D3DRS_VERTEXBLEND] = D3DVBF_DISABLE, - [D3DRS_CLIPPLANEENABLE] = 0, -/* [D3DRS_SOFTWAREVERTEXPROCESSING] = FALSE, */ - [D3DRS_POINTSIZE] = 0x3F800000, - [D3DRS_POINTSIZE_MIN] = 0x3F800000, - [D3DRS_POINTSPRITEENABLE] = FALSE, - [D3DRS_POINTSCALEENABLE] = FALSE, - [D3DRS_POINTSCALE_A] = 0x3F800000, - [D3DRS_POINTSCALE_B] = 0x00000000, - [D3DRS_POINTSCALE_C] = 0x00000000, - [D3DRS_MULTISAMPLEANTIALIAS] = TRUE, - [D3DRS_MULTISAMPLEMASK] = 0xFFFFFFFF, - [D3DRS_PATCHEDGESTYLE] = D3DPATCHEDGE_DISCRETE, -/* [D3DRS_PATCHSEGMENTS] = 0x3F800000, */ - [D3DRS_DEBUGMONITORTOKEN] = 0xDEADCAFE, - [D3DRS_POINTSIZE_MAX] = 0x3F800000, /* depends on cap */ - [D3DRS_INDEXEDVERTEXBLENDENABLE] = FALSE, - [D3DRS_COLORWRITEENABLE] = 0x0000000f, - [D3DRS_TWEENFACTOR] = 0x00000000, - [D3DRS_BLENDOP] = D3DBLENDOP_ADD, - [D3DRS_POSITIONDEGREE] = D3DDEGREE_CUBIC, - [D3DRS_NORMALDEGREE] = D3DDEGREE_LINEAR, - [D3DRS_SCISSORTESTENABLE] = FALSE, - [D3DRS_SLOPESCALEDEPTHBIAS] = 0, - [D3DRS_MINTESSELLATIONLEVEL] = 0x3F800000, - [D3DRS_MAXTESSELLATIONLEVEL] = 0x3F800000, - [D3DRS_ANTIALIASEDLINEENABLE] = FALSE, - [D3DRS_ADAPTIVETESS_X] = 0x00000000, - [D3DRS_ADAPTIVETESS_Y] = 0x00000000, - [D3DRS_ADAPTIVETESS_Z] = 0x3F800000, - [D3DRS_ADAPTIVETESS_W] = 0x00000000, - [D3DRS_ENABLEADAPTIVETESSELLATION] = FALSE, - [D3DRS_TWOSIDEDSTENCILMODE] = FALSE, - [D3DRS_CCW_STENCILFAIL] = D3DSTENCILOP_KEEP, - [D3DRS_CCW_STENCILZFAIL] = D3DSTENCILOP_KEEP, - [D3DRS_CCW_STENCILPASS] = D3DSTENCILOP_KEEP, - [D3DRS_CCW_STENCILFUNC] = D3DCMP_ALWAYS, - [D3DRS_COLORWRITEENABLE1] = 0x0000000F, - [D3DRS_COLORWRITEENABLE2] = 0x0000000F, - [D3DRS_COLORWRITEENABLE3] = 0x0000000F, - [D3DRS_BLENDFACTOR] = 0xFFFFFFFF, - [D3DRS_SRGBWRITEENABLE] = 0, - [D3DRS_DEPTHBIAS] = 0, - [D3DRS_WRAP8] = 0, - [D3DRS_WRAP9] = 0, - [D3DRS_WRAP10] = 0, - [D3DRS_WRAP11] = 0, - [D3DRS_WRAP12] = 0, - [D3DRS_WRAP13] = 0, - [D3DRS_WRAP14] = 0, - [D3DRS_WRAP15] = 0, - [D3DRS_SEPARATEALPHABLENDENABLE] = FALSE, - [D3DRS_SRCBLENDALPHA] = D3DBLEND_ONE, - [D3DRS_DESTBLENDALPHA] = D3DBLEND_ZERO, - [D3DRS_BLENDOPALPHA] = D3DBLENDOP_ADD, - [NINED3DRS_VSPOINTSIZE] = FALSE, - [NINED3DRS_RTMASK] = 0xf, - [NINED3DRS_ALPHACOVERAGE] = FALSE, - [NINED3DRS_MULTISAMPLE] = FALSE -}; -static const DWORD nine_tex_stage_state_defaults[NINED3DTSS_LAST + 1] = -{ - [D3DTSS_COLOROP] = D3DTOP_DISABLE, - [D3DTSS_ALPHAOP] = D3DTOP_DISABLE, - [D3DTSS_COLORARG1] = D3DTA_TEXTURE, - [D3DTSS_COLORARG2] = D3DTA_CURRENT, - [D3DTSS_COLORARG0] = D3DTA_CURRENT, - [D3DTSS_ALPHAARG1] = D3DTA_TEXTURE, - [D3DTSS_ALPHAARG2] = D3DTA_CURRENT, - [D3DTSS_ALPHAARG0] = D3DTA_CURRENT, - [D3DTSS_RESULTARG] = D3DTA_CURRENT, - [D3DTSS_BUMPENVMAT00] = 0, - [D3DTSS_BUMPENVMAT01] = 0, - [D3DTSS_BUMPENVMAT10] = 0, - [D3DTSS_BUMPENVMAT11] = 0, - [D3DTSS_BUMPENVLSCALE] = 0, - [D3DTSS_BUMPENVLOFFSET] = 0, - [D3DTSS_TEXCOORDINDEX] = 0, - [D3DTSS_TEXTURETRANSFORMFLAGS] = D3DTTFF_DISABLE, -}; -static const DWORD nine_samp_state_defaults[NINED3DSAMP_LAST + 1] = -{ - [D3DSAMP_ADDRESSU] = D3DTADDRESS_WRAP, - [D3DSAMP_ADDRESSV] = D3DTADDRESS_WRAP, - [D3DSAMP_ADDRESSW] = D3DTADDRESS_WRAP, - [D3DSAMP_BORDERCOLOR] = 0, - [D3DSAMP_MAGFILTER] = D3DTEXF_POINT, - [D3DSAMP_MINFILTER] = D3DTEXF_POINT, - [D3DSAMP_MIPFILTER] = D3DTEXF_NONE, - [D3DSAMP_MIPMAPLODBIAS] = 0, - [D3DSAMP_MAXMIPLEVEL] = 0, - [D3DSAMP_MAXANISOTROPY] = 1, - [D3DSAMP_SRGBTEXTURE] = 0, - [D3DSAMP_ELEMENTINDEX] = 0, - [D3DSAMP_DMAPOFFSET] = 0, - [NINED3DSAMP_MINLOD] = 0, - [NINED3DSAMP_SHADOW] = 0, - [NINED3DSAMP_CUBETEX] = 0 -}; - -/* Note: The following 4 functions assume there is no - * pending commands */ - -void nine_state_restore_non_cso(struct NineDevice9 *device) -{ - struct nine_context *context = &device->context; - - context->changed.group = NINE_STATE_ALL; - context->changed.vtxbuf = (1ULL << device->caps.MaxStreams) - 1; - context->changed.ucp = TRUE; - context->commit |= NINE_STATE_COMMIT_CONST_VS | NINE_STATE_COMMIT_CONST_PS; -} - -void -nine_state_set_defaults(struct NineDevice9 *device, const D3DCAPS9 *caps, - boolean is_reset) -{ - struct nine_state *state = &device->state; - struct nine_context *context = &device->context; - unsigned s; - - /* Initialize defaults. - */ - memcpy(context->rs, nine_render_state_defaults, sizeof(context->rs)); - - for (s = 0; s < ARRAY_SIZE(state->ff.tex_stage); ++s) { - memcpy(&state->ff.tex_stage[s], nine_tex_stage_state_defaults, - sizeof(state->ff.tex_stage[s])); - state->ff.tex_stage[s][D3DTSS_TEXCOORDINDEX] = s; - } - state->ff.tex_stage[0][D3DTSS_COLOROP] = D3DTOP_MODULATE; - state->ff.tex_stage[0][D3DTSS_ALPHAOP] = D3DTOP_SELECTARG1; - - for (s = 0; s < ARRAY_SIZE(state->ff.tex_stage); ++s) - memcpy(&context->ff.tex_stage[s], state->ff.tex_stage[s], - sizeof(state->ff.tex_stage[s])); - - memset(&context->bumpmap_vars, 0, sizeof(context->bumpmap_vars)); - - for (s = 0; s < NINE_MAX_SAMPLERS; ++s) { - memcpy(&context->samp[s], nine_samp_state_defaults, - sizeof(context->samp[s])); - memcpy(&state->samp_advertised[s], nine_samp_state_defaults, - sizeof(state->samp_advertised[s])); - } - - memset(state->vs_const_f, 0, VS_CONST_F_SIZE(device)); - memset(context->vs_const_f, 0, device->vs_const_size); - if (context->vs_const_f_swvp) - memset(context->vs_const_f_swvp, 0, NINE_MAX_CONST_F_SWVP * sizeof(float[4])); - memset(state->vs_const_i, 0, VS_CONST_I_SIZE(device)); - memset(context->vs_const_i, 0, VS_CONST_I_SIZE(device)); - memset(state->vs_const_b, 0, VS_CONST_B_SIZE(device)); - memset(context->vs_const_b, 0, VS_CONST_B_SIZE(device)); - memset(state->ps_const_f, 0, device->ps_const_size); - memset(context->ps_const_f, 0, device->ps_const_size); - memset(state->ps_const_i, 0, sizeof(state->ps_const_i)); - memset(context->ps_const_i, 0, sizeof(context->ps_const_i)); - memset(state->ps_const_b, 0, sizeof(state->ps_const_b)); - memset(context->ps_const_b, 0, sizeof(context->ps_const_b)); - - /* Cap dependent initial state: - */ - context->rs[D3DRS_POINTSIZE_MAX] = fui(caps->MaxPointSize); - - memcpy(state->rs_advertised, context->rs, sizeof(context->rs)); - - /* Set changed flags to initialize driver. - */ - context->changed.group = NINE_STATE_ALL; - context->changed.vtxbuf = (1ULL << device->caps.MaxStreams) - 1; - context->changed.ucp = TRUE; - - context->ff.changed.transform[0] = ~0; - context->ff.changed.transform[D3DTS_WORLD / 32] |= 1 << (D3DTS_WORLD % 32); - - if (!is_reset) { - state->viewport.MinZ = context->viewport.MinZ = 0.0f; - state->viewport.MaxZ = context->viewport.MaxZ = 1.0f; - } - - for (s = 0; s < NINE_MAX_SAMPLERS; ++s) - context->changed.sampler[s] = ~0; - - if (!is_reset) { - context->dummy_vbo_bound_at = -1; - context->vbo_bound_done = FALSE; - } -} - -void -nine_device_state_clear(struct NineDevice9 *device) -{ - struct nine_state *state = &device->state; - unsigned i; - - for (i = 0; i < ARRAY_SIZE(state->rt); ++i) - nine_bind(&state->rt[i], NULL); - nine_bind(&state->ds, NULL); - nine_bind(&state->vs, NULL); - nine_bind(&state->ps, NULL); - nine_bind(&state->vdecl, NULL); - for (i = 0; i < PIPE_MAX_ATTRIBS; ++i) - NineBindBufferToDevice(device, - (struct NineBuffer9 **)&state->stream[i], - NULL); - NineBindBufferToDevice(device, - (struct NineBuffer9 **)&state->idxbuf, - NULL); - - for (i = 0; i < NINE_MAX_SAMPLERS; ++i) - NineBindTextureToDevice(device, &state->texture[i], NULL); -} - -void -nine_context_clear(struct NineDevice9 *device) -{ - struct nine_context *context = &device->context; - struct pipe_context *pipe = context->pipe; - struct cso_context *cso = context->cso; - unsigned i; - - /* Early device ctor failure. Nothing to do */ - if (!pipe || !cso) - return; - - pipe->bind_vs_state(pipe, NULL); - pipe->bind_fs_state(pipe, NULL); - - /* Don't unbind constant buffers, they're device-private and - * do not change on Reset. - */ - - cso_set_samplers(cso, PIPE_SHADER_VERTEX, 0, NULL); - cso_set_samplers(cso, PIPE_SHADER_FRAGMENT, 0, NULL); - - cso_set_sampler_views(cso, PIPE_SHADER_VERTEX, 0, NULL); - cso_set_sampler_views(cso, PIPE_SHADER_FRAGMENT, 0, NULL); - - pipe->set_vertex_buffers(pipe, 0, device->caps.MaxStreams, NULL); - - for (i = 0; i < ARRAY_SIZE(context->rt); ++i) - nine_bind(&context->rt[i], NULL); - nine_bind(&context->ds, NULL); - nine_bind(&context->vs, NULL); - nine_bind(&context->ps, NULL); - nine_bind(&context->vdecl, NULL); - for (i = 0; i < PIPE_MAX_ATTRIBS; ++i) - pipe_vertex_buffer_unreference(&context->vtxbuf[i]); - pipe_resource_reference(&context->idxbuf, NULL); - pipe_resource_reference(&context->pipe_data.cb_vs.buffer, NULL); - pipe_resource_reference(&context->pipe_data.cb_ps.buffer, NULL); - - for (i = 0; i < NINE_MAX_SAMPLERS; ++i) { - context->texture[i].enabled = FALSE; - pipe_resource_reference(&context->texture[i].resource, - NULL); - pipe_sampler_view_reference(&context->texture[i].view[0], - NULL); - pipe_sampler_view_reference(&context->texture[i].view[1], - NULL); - } -} - -void -nine_state_init_sw(struct NineDevice9 *device) -{ - struct pipe_context *pipe_sw = device->pipe_sw; - struct pipe_rasterizer_state rast; - struct pipe_blend_state blend; - struct pipe_depth_stencil_alpha_state dsa; - struct pipe_framebuffer_state fb; - - /* Only used with Streamout */ - memset(&rast, 0, sizeof(rast)); - rast.rasterizer_discard = true; - rast.point_quad_rasterization = 1; /* to make llvmpipe happy */ - cso_set_rasterizer(device->cso_sw, &rast); - - /* dummy settings */ - memset(&blend, 0, sizeof(blend)); - memset(&dsa, 0, sizeof(dsa)); - memset(&fb, 0, sizeof(fb)); - cso_set_blend(device->cso_sw, &blend); - cso_set_depth_stencil_alpha(device->cso_sw, &dsa); - cso_set_framebuffer(device->cso_sw, &fb); - cso_set_viewport_dims(device->cso_sw, 1.0, 1.0, false); - cso_set_fragment_shader_handle(device->cso_sw, util_make_empty_fragment_shader(pipe_sw)); -} - -/* There is duplication with update_vertex_elements. - * TODO: Share the code */ - -static void -update_vertex_elements_sw(struct NineDevice9 *device) -{ - struct nine_state *state = &device->state; - const struct NineVertexDeclaration9 *vdecl = device->state.vdecl; - const struct NineVertexShader9 *vs; - unsigned n, b, i; - int index; - char vdecl_index_map[16]; /* vs->num_inputs <= 16 */ - char used_streams[device->caps.MaxStreams]; - int dummy_vbo_stream = -1; - BOOL need_dummy_vbo = FALSE; - struct cso_velems_state ve; - bool programmable_vs = state->vs && !(state->vdecl && state->vdecl->position_t); - - memset(vdecl_index_map, -1, 16); - memset(used_streams, 0, device->caps.MaxStreams); - vs = programmable_vs ? device->state.vs : device->ff.vs; - - if (vdecl) { - for (n = 0; n < vs->num_inputs; ++n) { - DBG("looking up input %u (usage %u) from vdecl(%p)\n", - n, vs->input_map[n].ndecl, vdecl); - - for (i = 0; i < vdecl->nelems; i++) { - if (vdecl->usage_map[i] == vs->input_map[n].ndecl) { - vdecl_index_map[n] = i; - used_streams[vdecl->elems[i].vertex_buffer_index] = 1; - break; - } - } - if (vdecl_index_map[n] < 0) - need_dummy_vbo = TRUE; - } - } else { - /* No vertex declaration. Likely will never happen in practice, - * but we need not crash on this */ - need_dummy_vbo = TRUE; - } - - if (need_dummy_vbo) { - for (i = 0; i < device->caps.MaxStreams; i++ ) { - if (!used_streams[i]) { - dummy_vbo_stream = i; - break; - } - } - } - /* TODO handle dummy_vbo */ - assert (!need_dummy_vbo); - - for (n = 0; n < vs->num_inputs; ++n) { - index = vdecl_index_map[n]; - if (index >= 0) { - ve.velems[n] = vdecl->elems[index]; - b = ve.velems[n].vertex_buffer_index; - /* XXX wine just uses 1 here: */ - if (state->stream_freq[b] & D3DSTREAMSOURCE_INSTANCEDATA) - ve.velems[n].instance_divisor = state->stream_freq[b] & 0x7FFFFF; - } else { - /* if the vertex declaration is incomplete compared to what the - * vertex shader needs, we bind a dummy vbo with 0 0 0 0. - * This is not precised by the spec, but is the behaviour - * tested on win */ - ve.velems[n].vertex_buffer_index = dummy_vbo_stream; - ve.velems[n].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; - ve.velems[n].src_offset = 0; - ve.velems[n].instance_divisor = 0; - } - } - - ve.count = vs->num_inputs; - cso_set_vertex_elements(device->cso_sw, &ve); -} - -static void -update_vertex_buffers_sw(struct NineDevice9 *device, int start_vertice, int num_vertices) -{ - struct pipe_context *pipe = nine_context_get_pipe_acquire(device); - struct pipe_context *pipe_sw = device->pipe_sw; - struct nine_state *state = &device->state; - struct nine_state_sw_internal *sw_internal = &device->state_sw_internal; - struct pipe_vertex_buffer vtxbuf; - uint32_t mask = 0xf; - unsigned i; - - DBG("mask=%x\n", mask); - - /* TODO: handle dummy_vbo_bound_at */ - - for (i = 0; mask; mask >>= 1, ++i) { - if (mask & 1) { - if (state->stream[i]) { - unsigned offset; - struct pipe_resource *buf; - struct pipe_box box; - void *userbuf; - - vtxbuf = state->vtxbuf[i]; - buf = NineVertexBuffer9_GetResource(state->stream[i], &offset); - - DBG("Locking %p (offset %d, length %d)\n", buf, - vtxbuf.buffer_offset, num_vertices * vtxbuf.stride); - - u_box_1d(vtxbuf.buffer_offset + offset + start_vertice * vtxbuf.stride, - num_vertices * vtxbuf.stride, &box); - - userbuf = pipe->transfer_map(pipe, buf, 0, PIPE_TRANSFER_READ, &box, - &(sw_internal->transfers_so[i])); - vtxbuf.is_user_buffer = true; - vtxbuf.buffer.user = userbuf; - - if (!device->driver_caps.user_sw_vbufs) { - vtxbuf.buffer.resource = NULL; - vtxbuf.is_user_buffer = false; - u_upload_data(device->pipe_sw->stream_uploader, - 0, - box.width, - 16, - userbuf, - &(vtxbuf.buffer_offset), - &(vtxbuf.buffer.resource)); - u_upload_unmap(device->pipe_sw->stream_uploader); - } - pipe_sw->set_vertex_buffers(pipe_sw, i, 1, &vtxbuf); - pipe_vertex_buffer_unreference(&vtxbuf); - } else - pipe_sw->set_vertex_buffers(pipe_sw, i, 1, NULL); - } - } - nine_context_get_pipe_release(device); -} - -static void -update_vs_constants_sw(struct NineDevice9 *device) -{ - struct nine_state *state = &device->state; - struct pipe_context *pipe_sw = device->pipe_sw; - - DBG("updating\n"); - - { - struct pipe_constant_buffer cb; - const void *buf; - - cb.buffer = NULL; - cb.buffer_offset = 0; - cb.buffer_size = 4096 * sizeof(float[4]); - cb.user_buffer = state->vs_const_f; - - if (state->vs->lconstf.ranges) { - const struct nine_lconstf *lconstf = &device->state.vs->lconstf; - const struct nine_range *r = lconstf->ranges; - unsigned n = 0; - float *dst = device->state.vs_lconstf_temp; - float *src = (float *)cb.user_buffer; - memcpy(dst, src, 8192 * sizeof(float[4])); - while (r) { - unsigned p = r->bgn; - unsigned c = r->end - r->bgn; - memcpy(&dst[p * 4], &lconstf->data[n * 4], c * 4 * sizeof(float)); - n += c; - r = r->next; - } - cb.user_buffer = dst; - } - - buf = cb.user_buffer; - - pipe_sw->set_constant_buffer(pipe_sw, PIPE_SHADER_VERTEX, 0, &cb); - if (cb.buffer) - pipe_resource_reference(&cb.buffer, NULL); - - cb.user_buffer = (char *)buf + 4096 * sizeof(float[4]); - - pipe_sw->set_constant_buffer(pipe_sw, PIPE_SHADER_VERTEX, 1, &cb); - if (cb.buffer) - pipe_resource_reference(&cb.buffer, NULL); - } - - { - struct pipe_constant_buffer cb; - - cb.buffer = NULL; - cb.buffer_offset = 0; - cb.buffer_size = 2048 * sizeof(float[4]); - cb.user_buffer = state->vs_const_i; - - pipe_sw->set_constant_buffer(pipe_sw, PIPE_SHADER_VERTEX, 2, &cb); - if (cb.buffer) - pipe_resource_reference(&cb.buffer, NULL); - } - - { - struct pipe_constant_buffer cb; - - cb.buffer = NULL; - cb.buffer_offset = 0; - cb.buffer_size = 512 * sizeof(float[4]); - cb.user_buffer = state->vs_const_b; - - pipe_sw->set_constant_buffer(pipe_sw, PIPE_SHADER_VERTEX, 3, &cb); - if (cb.buffer) - pipe_resource_reference(&cb.buffer, NULL); - } - - { - struct pipe_constant_buffer cb; - const D3DVIEWPORT9 *vport = &device->state.viewport; - float viewport_data[8] = {(float)vport->Width * 0.5f, - (float)vport->Height * -0.5f, vport->MaxZ - vport->MinZ, 0.f, - (float)vport->Width * 0.5f + (float)vport->X, - (float)vport->Height * 0.5f + (float)vport->Y, - vport->MinZ, 0.f}; - - cb.buffer = NULL; - cb.buffer_offset = 0; - cb.buffer_size = 2 * sizeof(float[4]); - cb.user_buffer = viewport_data; - - { - u_upload_data(device->pipe_sw->const_uploader, - 0, - cb.buffer_size, - 16, - cb.user_buffer, - &(cb.buffer_offset), - &(cb.buffer)); - u_upload_unmap(device->pipe_sw->const_uploader); - cb.user_buffer = NULL; - } - - pipe_sw->set_constant_buffer(pipe_sw, PIPE_SHADER_VERTEX, 4, &cb); - if (cb.buffer) - pipe_resource_reference(&cb.buffer, NULL); - } - -} - -void -nine_state_prepare_draw_sw(struct NineDevice9 *device, struct NineVertexDeclaration9 *vdecl_out, - int start_vertice, int num_vertices, struct pipe_stream_output_info *so) -{ - struct nine_state *state = &device->state; - bool programmable_vs = state->vs && !(state->vdecl && state->vdecl->position_t); - struct NineVertexShader9 *vs = programmable_vs ? device->state.vs : device->ff.vs; - - assert(programmable_vs); - - DBG("Preparing draw\n"); - cso_set_vertex_shader_handle(device->cso_sw, - NineVertexShader9_GetVariantProcessVertices(vs, vdecl_out, so)); - update_vertex_elements_sw(device); - update_vertex_buffers_sw(device, start_vertice, num_vertices); - update_vs_constants_sw(device); - DBG("Preparation succeeded\n"); -} - -void -nine_state_after_draw_sw(struct NineDevice9 *device) -{ - struct nine_state_sw_internal *sw_internal = &device->state_sw_internal; - struct pipe_context *pipe = nine_context_get_pipe_acquire(device); - struct pipe_context *pipe_sw = device->pipe_sw; - int i; - - for (i = 0; i < 4; i++) { - pipe_sw->set_vertex_buffers(pipe_sw, i, 1, NULL); - if (sw_internal->transfers_so[i]) - pipe->transfer_unmap(pipe, sw_internal->transfers_so[i]); - sw_internal->transfers_so[i] = NULL; - } - nine_context_get_pipe_release(device); -} - -void -nine_state_destroy_sw(struct NineDevice9 *device) -{ - (void) device; - /* Everything destroyed with cso */ -} - -/* -static const DWORD nine_render_states_pixel[] = -{ - D3DRS_ALPHABLENDENABLE, - D3DRS_ALPHAFUNC, - D3DRS_ALPHAREF, - D3DRS_ALPHATESTENABLE, - D3DRS_ANTIALIASEDLINEENABLE, - D3DRS_BLENDFACTOR, - D3DRS_BLENDOP, - D3DRS_BLENDOPALPHA, - D3DRS_CCW_STENCILFAIL, - D3DRS_CCW_STENCILPASS, - D3DRS_CCW_STENCILZFAIL, - D3DRS_COLORWRITEENABLE, - D3DRS_COLORWRITEENABLE1, - D3DRS_COLORWRITEENABLE2, - D3DRS_COLORWRITEENABLE3, - D3DRS_DEPTHBIAS, - D3DRS_DESTBLEND, - D3DRS_DESTBLENDALPHA, - D3DRS_DITHERENABLE, - D3DRS_FILLMODE, - D3DRS_FOGDENSITY, - D3DRS_FOGEND, - D3DRS_FOGSTART, - D3DRS_LASTPIXEL, - D3DRS_SCISSORTESTENABLE, - D3DRS_SEPARATEALPHABLENDENABLE, - D3DRS_SHADEMODE, - D3DRS_SLOPESCALEDEPTHBIAS, - D3DRS_SRCBLEND, - D3DRS_SRCBLENDALPHA, - D3DRS_SRGBWRITEENABLE, - D3DRS_STENCILENABLE, - D3DRS_STENCILFAIL, - D3DRS_STENCILFUNC, - D3DRS_STENCILMASK, - D3DRS_STENCILPASS, - D3DRS_STENCILREF, - D3DRS_STENCILWRITEMASK, - D3DRS_STENCILZFAIL, - D3DRS_TEXTUREFACTOR, - D3DRS_TWOSIDEDSTENCILMODE, - D3DRS_WRAP0, - D3DRS_WRAP1, - D3DRS_WRAP10, - D3DRS_WRAP11, - D3DRS_WRAP12, - D3DRS_WRAP13, - D3DRS_WRAP14, - D3DRS_WRAP15, - D3DRS_WRAP2, - D3DRS_WRAP3, - D3DRS_WRAP4, - D3DRS_WRAP5, - D3DRS_WRAP6, - D3DRS_WRAP7, - D3DRS_WRAP8, - D3DRS_WRAP9, - D3DRS_ZENABLE, - D3DRS_ZFUNC, - D3DRS_ZWRITEENABLE -}; -*/ -const uint32_t nine_render_states_pixel[(NINED3DRS_LAST + 31) / 32] = -{ - 0x0f99c380, 0x1ff00070, 0x00000000, 0x00000000, - 0x000000ff, 0xde01c900, 0x0003ffcf -}; - -/* -static const DWORD nine_render_states_vertex[] = -{ - D3DRS_ADAPTIVETESS_W, - D3DRS_ADAPTIVETESS_X, - D3DRS_ADAPTIVETESS_Y, - D3DRS_ADAPTIVETESS_Z, - D3DRS_AMBIENT, - D3DRS_AMBIENTMATERIALSOURCE, - D3DRS_CLIPPING, - D3DRS_CLIPPLANEENABLE, - D3DRS_COLORVERTEX, - D3DRS_CULLMODE, - D3DRS_DIFFUSEMATERIALSOURCE, - D3DRS_EMISSIVEMATERIALSOURCE, - D3DRS_ENABLEADAPTIVETESSELLATION, - D3DRS_FOGCOLOR, - D3DRS_FOGDENSITY, - D3DRS_FOGENABLE, - D3DRS_FOGEND, - D3DRS_FOGSTART, - D3DRS_FOGTABLEMODE, - D3DRS_FOGVERTEXMODE, - D3DRS_INDEXEDVERTEXBLENDENABLE, - D3DRS_LIGHTING, - D3DRS_LOCALVIEWER, - D3DRS_MAXTESSELLATIONLEVEL, - D3DRS_MINTESSELLATIONLEVEL, - D3DRS_MULTISAMPLEANTIALIAS, - D3DRS_MULTISAMPLEMASK, - D3DRS_NORMALDEGREE, - D3DRS_NORMALIZENORMALS, - D3DRS_PATCHEDGESTYLE, - D3DRS_POINTSCALE_A, - D3DRS_POINTSCALE_B, - D3DRS_POINTSCALE_C, - D3DRS_POINTSCALEENABLE, - D3DRS_POINTSIZE, - D3DRS_POINTSIZE_MAX, - D3DRS_POINTSIZE_MIN, - D3DRS_POINTSPRITEENABLE, - D3DRS_POSITIONDEGREE, - D3DRS_RANGEFOGENABLE, - D3DRS_SHADEMODE, - D3DRS_SPECULARENABLE, - D3DRS_SPECULARMATERIALSOURCE, - D3DRS_TWEENFACTOR, - D3DRS_VERTEXBLEND -}; -*/ -const uint32_t nine_render_states_vertex[(NINED3DRS_LAST + 31) / 32] = -{ - 0x30400200, 0x0001007c, 0x00000000, 0x00000000, - 0xfd9efb00, 0x01fc34cf, 0x00000000 -}; - -/* TODO: put in the right values */ -const uint32_t nine_render_state_group[NINED3DRS_LAST + 1] = -{ - [D3DRS_ZENABLE] = NINE_STATE_DSA | NINE_STATE_MULTISAMPLE, - [D3DRS_FILLMODE] = NINE_STATE_RASTERIZER, - [D3DRS_SHADEMODE] = NINE_STATE_RASTERIZER, - [D3DRS_ZWRITEENABLE] = NINE_STATE_DSA, - [D3DRS_ALPHATESTENABLE] = NINE_STATE_DSA, - [D3DRS_LASTPIXEL] = NINE_STATE_RASTERIZER, - [D3DRS_SRCBLEND] = NINE_STATE_BLEND, - [D3DRS_DESTBLEND] = NINE_STATE_BLEND, - [D3DRS_CULLMODE] = NINE_STATE_RASTERIZER, - [D3DRS_ZFUNC] = NINE_STATE_DSA, - [D3DRS_ALPHAREF] = NINE_STATE_DSA, - [D3DRS_ALPHAFUNC] = NINE_STATE_DSA, - [D3DRS_DITHERENABLE] = NINE_STATE_BLEND, - [D3DRS_ALPHABLENDENABLE] = NINE_STATE_BLEND, - [D3DRS_FOGENABLE] = NINE_STATE_FF_SHADER | NINE_STATE_VS_PARAMS_MISC | NINE_STATE_PS_PARAMS_MISC | NINE_STATE_PS_CONST, - [D3DRS_SPECULARENABLE] = NINE_STATE_FF_LIGHTING, - [D3DRS_FOGCOLOR] = NINE_STATE_FF_PS_CONSTS | NINE_STATE_PS_CONST, - [D3DRS_FOGTABLEMODE] = NINE_STATE_FF_SHADER | NINE_STATE_PS_PARAMS_MISC | NINE_STATE_PS_CONST, - [D3DRS_FOGSTART] = NINE_STATE_FF_VS_OTHER | NINE_STATE_FF_PS_CONSTS | NINE_STATE_PS_CONST, - [D3DRS_FOGEND] = NINE_STATE_FF_VS_OTHER | NINE_STATE_FF_PS_CONSTS | NINE_STATE_PS_CONST, - [D3DRS_FOGDENSITY] = NINE_STATE_FF_VS_OTHER | NINE_STATE_FF_PS_CONSTS | NINE_STATE_PS_CONST, - [D3DRS_RANGEFOGENABLE] = NINE_STATE_FF_SHADER, - [D3DRS_STENCILENABLE] = NINE_STATE_DSA | NINE_STATE_MULTISAMPLE, - [D3DRS_STENCILFAIL] = NINE_STATE_DSA, - [D3DRS_STENCILZFAIL] = NINE_STATE_DSA, - [D3DRS_STENCILPASS] = NINE_STATE_DSA, - [D3DRS_STENCILFUNC] = NINE_STATE_DSA, - [D3DRS_STENCILREF] = NINE_STATE_STENCIL_REF, - [D3DRS_STENCILMASK] = NINE_STATE_DSA, - [D3DRS_STENCILWRITEMASK] = NINE_STATE_DSA, - [D3DRS_TEXTUREFACTOR] = NINE_STATE_FF_PS_CONSTS, - [D3DRS_WRAP0] = NINE_STATE_UNHANDLED, /* cylindrical wrap is crazy */ - [D3DRS_WRAP1] = NINE_STATE_UNHANDLED, - [D3DRS_WRAP2] = NINE_STATE_UNHANDLED, - [D3DRS_WRAP3] = NINE_STATE_UNHANDLED, - [D3DRS_WRAP4] = NINE_STATE_UNHANDLED, - [D3DRS_WRAP5] = NINE_STATE_UNHANDLED, - [D3DRS_WRAP6] = NINE_STATE_UNHANDLED, - [D3DRS_WRAP7] = NINE_STATE_UNHANDLED, - [D3DRS_CLIPPING] = 0, /* software vertex processing only */ - [D3DRS_LIGHTING] = NINE_STATE_FF_LIGHTING, - [D3DRS_AMBIENT] = NINE_STATE_FF_LIGHTING | NINE_STATE_FF_MATERIAL, - [D3DRS_FOGVERTEXMODE] = NINE_STATE_FF_SHADER, - [D3DRS_COLORVERTEX] = NINE_STATE_FF_LIGHTING, - [D3DRS_LOCALVIEWER] = NINE_STATE_FF_LIGHTING, - [D3DRS_NORMALIZENORMALS] = NINE_STATE_FF_SHADER, - [D3DRS_DIFFUSEMATERIALSOURCE] = NINE_STATE_FF_LIGHTING, - [D3DRS_SPECULARMATERIALSOURCE] = NINE_STATE_FF_LIGHTING, - [D3DRS_AMBIENTMATERIALSOURCE] = NINE_STATE_FF_LIGHTING, - [D3DRS_EMISSIVEMATERIALSOURCE] = NINE_STATE_FF_LIGHTING, - [D3DRS_VERTEXBLEND] = NINE_STATE_FF_SHADER, - [D3DRS_CLIPPLANEENABLE] = NINE_STATE_RASTERIZER, - [D3DRS_POINTSIZE] = NINE_STATE_RASTERIZER | NINE_STATE_FF_VS_OTHER, - [D3DRS_POINTSIZE_MIN] = NINE_STATE_RASTERIZER | NINE_STATE_FF_VS_OTHER | NINE_STATE_VS_PARAMS_MISC, - [D3DRS_POINTSPRITEENABLE] = NINE_STATE_RASTERIZER, - [D3DRS_POINTSCALEENABLE] = NINE_STATE_FF_SHADER, - [D3DRS_POINTSCALE_A] = NINE_STATE_FF_VS_OTHER, - [D3DRS_POINTSCALE_B] = NINE_STATE_FF_VS_OTHER, - [D3DRS_POINTSCALE_C] = NINE_STATE_FF_VS_OTHER, - [D3DRS_MULTISAMPLEANTIALIAS] = NINE_STATE_MULTISAMPLE, - [D3DRS_MULTISAMPLEMASK] = NINE_STATE_SAMPLE_MASK, - [D3DRS_PATCHEDGESTYLE] = NINE_STATE_UNHANDLED, - [D3DRS_DEBUGMONITORTOKEN] = NINE_STATE_UNHANDLED, - [D3DRS_POINTSIZE_MAX] = NINE_STATE_RASTERIZER | NINE_STATE_FF_VS_OTHER | NINE_STATE_VS_PARAMS_MISC, - [D3DRS_INDEXEDVERTEXBLENDENABLE] = NINE_STATE_FF_SHADER, - [D3DRS_COLORWRITEENABLE] = NINE_STATE_BLEND, - [D3DRS_TWEENFACTOR] = NINE_STATE_FF_VS_OTHER, - [D3DRS_BLENDOP] = NINE_STATE_BLEND, - [D3DRS_POSITIONDEGREE] = NINE_STATE_UNHANDLED, - [D3DRS_NORMALDEGREE] = NINE_STATE_UNHANDLED, - [D3DRS_SCISSORTESTENABLE] = NINE_STATE_RASTERIZER, - [D3DRS_SLOPESCALEDEPTHBIAS] = NINE_STATE_RASTERIZER, - [D3DRS_ANTIALIASEDLINEENABLE] = NINE_STATE_RASTERIZER, - [D3DRS_MINTESSELLATIONLEVEL] = NINE_STATE_UNHANDLED, - [D3DRS_MAXTESSELLATIONLEVEL] = NINE_STATE_UNHANDLED, - [D3DRS_ADAPTIVETESS_X] = NINE_STATE_UNHANDLED, - [D3DRS_ADAPTIVETESS_Y] = NINE_STATE_UNHANDLED, - [D3DRS_ADAPTIVETESS_Z] = NINE_STATE_UNHANDLED, - [D3DRS_ADAPTIVETESS_W] = NINE_STATE_UNHANDLED, - [D3DRS_ENABLEADAPTIVETESSELLATION] = NINE_STATE_UNHANDLED, - [D3DRS_TWOSIDEDSTENCILMODE] = NINE_STATE_DSA, - [D3DRS_CCW_STENCILFAIL] = NINE_STATE_DSA, - [D3DRS_CCW_STENCILZFAIL] = NINE_STATE_DSA, - [D3DRS_CCW_STENCILPASS] = NINE_STATE_DSA, - [D3DRS_CCW_STENCILFUNC] = NINE_STATE_DSA, - [D3DRS_COLORWRITEENABLE1] = NINE_STATE_BLEND, - [D3DRS_COLORWRITEENABLE2] = NINE_STATE_BLEND, - [D3DRS_COLORWRITEENABLE3] = NINE_STATE_BLEND, - [D3DRS_BLENDFACTOR] = NINE_STATE_BLEND_COLOR, - [D3DRS_SRGBWRITEENABLE] = NINE_STATE_FB, - [D3DRS_DEPTHBIAS] = NINE_STATE_RASTERIZER, - [D3DRS_WRAP8] = NINE_STATE_UNHANDLED, /* cylwrap has to be done via GP */ - [D3DRS_WRAP9] = NINE_STATE_UNHANDLED, - [D3DRS_WRAP10] = NINE_STATE_UNHANDLED, - [D3DRS_WRAP11] = NINE_STATE_UNHANDLED, - [D3DRS_WRAP12] = NINE_STATE_UNHANDLED, - [D3DRS_WRAP13] = NINE_STATE_UNHANDLED, - [D3DRS_WRAP14] = NINE_STATE_UNHANDLED, - [D3DRS_WRAP15] = NINE_STATE_UNHANDLED, - [D3DRS_SEPARATEALPHABLENDENABLE] = NINE_STATE_BLEND, - [D3DRS_SRCBLENDALPHA] = NINE_STATE_BLEND, - [D3DRS_DESTBLENDALPHA] = NINE_STATE_BLEND, - [D3DRS_BLENDOPALPHA] = NINE_STATE_BLEND -}; - -/* Misc */ - -static D3DMATRIX nine_state_identity = { .m[0] = { 1, 0, 0, 0 }, - .m[1] = { 0, 1, 0, 0 }, - .m[2] = { 0, 0, 1, 0 }, - .m[3] = { 0, 0, 0, 1 } }; - -void -nine_state_resize_transform(struct nine_ff_state *ff_state, unsigned N) -{ - unsigned n = ff_state->num_transforms; - - if (N <= n) - return; - - ff_state->transform = REALLOC(ff_state->transform, - n * sizeof(D3DMATRIX), - N * sizeof(D3DMATRIX)); - for (; n < N; ++n) - ff_state->transform[n] = nine_state_identity; - ff_state->num_transforms = N; -} - -D3DMATRIX * -nine_state_access_transform(struct nine_ff_state *ff_state, D3DTRANSFORMSTATETYPE t, - boolean alloc) -{ - unsigned index; - - switch (t) { - case D3DTS_VIEW: index = 0; break; - case D3DTS_PROJECTION: index = 1; break; - case D3DTS_TEXTURE0: index = 2; break; - case D3DTS_TEXTURE1: index = 3; break; - case D3DTS_TEXTURE2: index = 4; break; - case D3DTS_TEXTURE3: index = 5; break; - case D3DTS_TEXTURE4: index = 6; break; - case D3DTS_TEXTURE5: index = 7; break; - case D3DTS_TEXTURE6: index = 8; break; - case D3DTS_TEXTURE7: index = 9; break; - default: - if (!(t >= D3DTS_WORLDMATRIX(0) && t <= D3DTS_WORLDMATRIX(255))) - return NULL; - index = 10 + (t - D3DTS_WORLDMATRIX(0)); - break; - } - - if (index >= ff_state->num_transforms) { - if (!alloc) - return &nine_state_identity; - nine_state_resize_transform(ff_state, index + 1); - } - return &ff_state->transform[index]; -} - -HRESULT -nine_state_set_light(struct nine_ff_state *ff_state, DWORD Index, - const D3DLIGHT9 *pLight) -{ - if (Index >= ff_state->num_lights) { - unsigned n = ff_state->num_lights; - unsigned N = Index + 1; - - ff_state->light = REALLOC(ff_state->light, n * sizeof(D3DLIGHT9), - N * sizeof(D3DLIGHT9)); - if (!ff_state->light) - return E_OUTOFMEMORY; - ff_state->num_lights = N; - - for (; n < Index; ++n) { - memset(&ff_state->light[n], 0, sizeof(D3DLIGHT9)); - ff_state->light[n].Type = (D3DLIGHTTYPE)NINED3DLIGHT_INVALID; - } - } - ff_state->light[Index] = *pLight; - - if (pLight->Type == D3DLIGHT_SPOT && pLight->Theta >= pLight->Phi) { - DBG("Warning: clamping D3DLIGHT9.Theta\n"); - ff_state->light[Index].Theta = ff_state->light[Index].Phi; - } - return D3D_OK; -} - -HRESULT -nine_state_light_enable(struct nine_ff_state *ff_state, - DWORD Index, BOOL Enable) -{ - unsigned i; - - user_assert(Index < ff_state->num_lights, D3DERR_INVALIDCALL); - - for (i = 0; i < ff_state->num_lights_active; ++i) { - if (ff_state->active_light[i] == Index) - break; - } - - if (Enable) { - if (i < ff_state->num_lights_active) - return D3D_OK; - /* XXX wine thinks this should still succeed: - */ - user_assert(i < NINE_MAX_LIGHTS_ACTIVE, D3DERR_INVALIDCALL); - - ff_state->active_light[i] = Index; - ff_state->num_lights_active++; - } else { - if (i == ff_state->num_lights_active) - return D3D_OK; - --ff_state->num_lights_active; - for (; i < ff_state->num_lights_active; ++i) - ff_state->active_light[i] = ff_state->active_light[i + 1]; - } - - return D3D_OK; -} - -#define D3DRS_TO_STRING_CASE(n) case D3DRS_##n: return "D3DRS_"#n -const char *nine_d3drs_to_string(DWORD State) -{ - switch (State) { - D3DRS_TO_STRING_CASE(ZENABLE); - D3DRS_TO_STRING_CASE(FILLMODE); - D3DRS_TO_STRING_CASE(SHADEMODE); - D3DRS_TO_STRING_CASE(ZWRITEENABLE); - D3DRS_TO_STRING_CASE(ALPHATESTENABLE); - D3DRS_TO_STRING_CASE(LASTPIXEL); - D3DRS_TO_STRING_CASE(SRCBLEND); - D3DRS_TO_STRING_CASE(DESTBLEND); - D3DRS_TO_STRING_CASE(CULLMODE); - D3DRS_TO_STRING_CASE(ZFUNC); - D3DRS_TO_STRING_CASE(ALPHAREF); - D3DRS_TO_STRING_CASE(ALPHAFUNC); - D3DRS_TO_STRING_CASE(DITHERENABLE); - D3DRS_TO_STRING_CASE(ALPHABLENDENABLE); - D3DRS_TO_STRING_CASE(FOGENABLE); - D3DRS_TO_STRING_CASE(SPECULARENABLE); - D3DRS_TO_STRING_CASE(FOGCOLOR); - D3DRS_TO_STRING_CASE(FOGTABLEMODE); - D3DRS_TO_STRING_CASE(FOGSTART); - D3DRS_TO_STRING_CASE(FOGEND); - D3DRS_TO_STRING_CASE(FOGDENSITY); - D3DRS_TO_STRING_CASE(RANGEFOGENABLE); - D3DRS_TO_STRING_CASE(STENCILENABLE); - D3DRS_TO_STRING_CASE(STENCILFAIL); - D3DRS_TO_STRING_CASE(STENCILZFAIL); - D3DRS_TO_STRING_CASE(STENCILPASS); - D3DRS_TO_STRING_CASE(STENCILFUNC); - D3DRS_TO_STRING_CASE(STENCILREF); - D3DRS_TO_STRING_CASE(STENCILMASK); - D3DRS_TO_STRING_CASE(STENCILWRITEMASK); - D3DRS_TO_STRING_CASE(TEXTUREFACTOR); - D3DRS_TO_STRING_CASE(WRAP0); - D3DRS_TO_STRING_CASE(WRAP1); - D3DRS_TO_STRING_CASE(WRAP2); - D3DRS_TO_STRING_CASE(WRAP3); - D3DRS_TO_STRING_CASE(WRAP4); - D3DRS_TO_STRING_CASE(WRAP5); - D3DRS_TO_STRING_CASE(WRAP6); - D3DRS_TO_STRING_CASE(WRAP7); - D3DRS_TO_STRING_CASE(CLIPPING); - D3DRS_TO_STRING_CASE(LIGHTING); - D3DRS_TO_STRING_CASE(AMBIENT); - D3DRS_TO_STRING_CASE(FOGVERTEXMODE); - D3DRS_TO_STRING_CASE(COLORVERTEX); - D3DRS_TO_STRING_CASE(LOCALVIEWER); - D3DRS_TO_STRING_CASE(NORMALIZENORMALS); - D3DRS_TO_STRING_CASE(DIFFUSEMATERIALSOURCE); - D3DRS_TO_STRING_CASE(SPECULARMATERIALSOURCE); - D3DRS_TO_STRING_CASE(AMBIENTMATERIALSOURCE); - D3DRS_TO_STRING_CASE(EMISSIVEMATERIALSOURCE); - D3DRS_TO_STRING_CASE(VERTEXBLEND); - D3DRS_TO_STRING_CASE(CLIPPLANEENABLE); - D3DRS_TO_STRING_CASE(POINTSIZE); - D3DRS_TO_STRING_CASE(POINTSIZE_MIN); - D3DRS_TO_STRING_CASE(POINTSPRITEENABLE); - D3DRS_TO_STRING_CASE(POINTSCALEENABLE); - D3DRS_TO_STRING_CASE(POINTSCALE_A); - D3DRS_TO_STRING_CASE(POINTSCALE_B); - D3DRS_TO_STRING_CASE(POINTSCALE_C); - D3DRS_TO_STRING_CASE(MULTISAMPLEANTIALIAS); - D3DRS_TO_STRING_CASE(MULTISAMPLEMASK); - D3DRS_TO_STRING_CASE(PATCHEDGESTYLE); - D3DRS_TO_STRING_CASE(DEBUGMONITORTOKEN); - D3DRS_TO_STRING_CASE(POINTSIZE_MAX); - D3DRS_TO_STRING_CASE(INDEXEDVERTEXBLENDENABLE); - D3DRS_TO_STRING_CASE(COLORWRITEENABLE); - D3DRS_TO_STRING_CASE(TWEENFACTOR); - D3DRS_TO_STRING_CASE(BLENDOP); - D3DRS_TO_STRING_CASE(POSITIONDEGREE); - D3DRS_TO_STRING_CASE(NORMALDEGREE); - D3DRS_TO_STRING_CASE(SCISSORTESTENABLE); - D3DRS_TO_STRING_CASE(SLOPESCALEDEPTHBIAS); - D3DRS_TO_STRING_CASE(ANTIALIASEDLINEENABLE); - D3DRS_TO_STRING_CASE(MINTESSELLATIONLEVEL); - D3DRS_TO_STRING_CASE(MAXTESSELLATIONLEVEL); - D3DRS_TO_STRING_CASE(ADAPTIVETESS_X); - D3DRS_TO_STRING_CASE(ADAPTIVETESS_Y); - D3DRS_TO_STRING_CASE(ADAPTIVETESS_Z); - D3DRS_TO_STRING_CASE(ADAPTIVETESS_W); - D3DRS_TO_STRING_CASE(ENABLEADAPTIVETESSELLATION); - D3DRS_TO_STRING_CASE(TWOSIDEDSTENCILMODE); - D3DRS_TO_STRING_CASE(CCW_STENCILFAIL); - D3DRS_TO_STRING_CASE(CCW_STENCILZFAIL); - D3DRS_TO_STRING_CASE(CCW_STENCILPASS); - D3DRS_TO_STRING_CASE(CCW_STENCILFUNC); - D3DRS_TO_STRING_CASE(COLORWRITEENABLE1); - D3DRS_TO_STRING_CASE(COLORWRITEENABLE2); - D3DRS_TO_STRING_CASE(COLORWRITEENABLE3); - D3DRS_TO_STRING_CASE(BLENDFACTOR); - D3DRS_TO_STRING_CASE(SRGBWRITEENABLE); - D3DRS_TO_STRING_CASE(DEPTHBIAS); - D3DRS_TO_STRING_CASE(WRAP8); - D3DRS_TO_STRING_CASE(WRAP9); - D3DRS_TO_STRING_CASE(WRAP10); - D3DRS_TO_STRING_CASE(WRAP11); - D3DRS_TO_STRING_CASE(WRAP12); - D3DRS_TO_STRING_CASE(WRAP13); - D3DRS_TO_STRING_CASE(WRAP14); - D3DRS_TO_STRING_CASE(WRAP15); - D3DRS_TO_STRING_CASE(SEPARATEALPHABLENDENABLE); - D3DRS_TO_STRING_CASE(SRCBLENDALPHA); - D3DRS_TO_STRING_CASE(DESTBLENDALPHA); - D3DRS_TO_STRING_CASE(BLENDOPALPHA); - default: - return "(invalid)"; - } -} diff --git a/src/gallium/state_trackers/nine/nine_state.h b/src/gallium/state_trackers/nine/nine_state.h deleted file mode 100644 index d8fa2f80c4d..00000000000 --- a/src/gallium/state_trackers/nine/nine_state.h +++ /dev/null @@ -1,672 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef _NINE_STATE_H_ -#define _NINE_STATE_H_ - -#include "d3d9.h" -#include "nine_defines.h" -#include "pipe/p_state.h" -#include "util/list.h" - -#define NINED3DSAMP_MINLOD (D3DSAMP_DMAPOFFSET + 1) -#define NINED3DSAMP_SHADOW (D3DSAMP_DMAPOFFSET + 2) -#define NINED3DSAMP_CUBETEX (D3DSAMP_DMAPOFFSET + 3) - -#define NINED3DRS_VSPOINTSIZE (D3DRS_BLENDOPALPHA + 1) -#define NINED3DRS_RTMASK (D3DRS_BLENDOPALPHA + 2) -/* ALPHACOVERAGE: - * bit 0: enable alpha coverage - * bit 1: ATOC is on - */ -#define NINED3DRS_ALPHACOVERAGE (D3DRS_BLENDOPALPHA + 3) -#define NINED3DRS_MULTISAMPLE (D3DRS_BLENDOPALPHA + 4) - -#define D3DRS_LAST D3DRS_BLENDOPALPHA -#define D3DSAMP_LAST D3DSAMP_DMAPOFFSET -#define NINED3DRS_LAST NINED3DRS_MULTISAMPLE /* 214 */ -#define NINED3DSAMP_LAST NINED3DSAMP_CUBETEX /* 16 */ -#define NINED3DTSS_LAST D3DTSS_CONSTANT -#define NINED3DTS_LAST D3DTS_WORLDMATRIX(255) - -#define D3DRS_COUNT (D3DRS_LAST + 1) -#define D3DSAMP_COUNT (D3DSAMP_LAST + 1) -#define NINED3DRS_COUNT (NINED3DRS_LAST + 1) -#define NINED3DSAMP_COUNT (NINED3DSAMP_LAST + 1) -#define NINED3DTSS_COUNT (NINED3DTSS_LAST + 1) -#define NINED3DTS_COUNT (NINED3DTS_LAST + 1) - -#define NINE_STATE_FB (1 << 0) -#define NINE_STATE_VIEWPORT (1 << 1) -#define NINE_STATE_SCISSOR (1 << 2) -#define NINE_STATE_RASTERIZER (1 << 3) -#define NINE_STATE_BLEND (1 << 4) -#define NINE_STATE_DSA (1 << 5) -#define NINE_STATE_VS (1 << 6) -#define NINE_STATE_VS_CONST (1 << 7) -#define NINE_STATE_PS (1 << 8) -#define NINE_STATE_PS_CONST (1 << 9) -#define NINE_STATE_TEXTURE (1 << 10) -#define NINE_STATE_SAMPLER (1 << 11) -#define NINE_STATE_VDECL (1 << 12) -#define NINE_STATE_IDXBUF (1 << 13) -#define NINE_STATE_STREAMFREQ (1 << 14) -#define NINE_STATE_BLEND_COLOR (1 << 17) -#define NINE_STATE_STENCIL_REF (1 << 18) -#define NINE_STATE_SAMPLE_MASK (1 << 19) -#define NINE_STATE_FF (0x1f << 20) -#define NINE_STATE_FF_VS (0x17 << 20) -#define NINE_STATE_FF_PS (0x08 << 20) -#define NINE_STATE_FF_LIGHTING (1 << 20) -#define NINE_STATE_FF_MATERIAL (1 << 21) -#define NINE_STATE_FF_VSTRANSF (1 << 22) -#define NINE_STATE_FF_PS_CONSTS (1 << 23) -#define NINE_STATE_FF_VS_OTHER (1 << 24) -#define NINE_STATE_VS_PARAMS_MISC (1 << 25) -#define NINE_STATE_PS_PARAMS_MISC (1 << 26) -#define NINE_STATE_MULTISAMPLE (1 << 27) -#define NINE_STATE_SWVP (1 << 28) -#define NINE_STATE_ALL 0x1fffffff -#define NINE_STATE_UNHANDLED (1 << 29) - -/* These states affect the ff shader key, - * which we recompute everytime. */ -#define NINE_STATE_FF_SHADER 0 - -#define NINE_STATE_COMMIT_DSA (1 << 0) -#define NINE_STATE_COMMIT_RASTERIZER (1 << 1) -#define NINE_STATE_COMMIT_BLEND (1 << 2) -#define NINE_STATE_COMMIT_CONST_VS (1 << 3) -#define NINE_STATE_COMMIT_CONST_PS (1 << 4) -#define NINE_STATE_COMMIT_VS (1 << 5) -#define NINE_STATE_COMMIT_PS (1 << 6) - - -#define NINE_MAX_SIMULTANEOUS_RENDERTARGETS 4 -#define NINE_MAX_CONST_F_PS3 224 -#define NINE_MAX_CONST_F 256 -#define NINE_MAX_CONST_I 16 -#define NINE_MAX_CONST_B 16 -#define NINE_MAX_CONST_F_SWVP 8192 -#define NINE_MAX_CONST_I_SWVP 2048 -#define NINE_MAX_CONST_B_SWVP 2048 -#define NINE_MAX_CONST_ALL 276 /* B consts count only 1/4 th */ - -#define NINE_CONST_I_BASE(nconstf) \ - ((nconstf) * 4 * sizeof(float)) -#define NINE_CONST_B_BASE(nconstf) \ - ((nconstf) * 4 * sizeof(float) + \ - NINE_MAX_CONST_I * 4 * sizeof(int)) - -#define VS_CONST_F_SIZE(device) (device->may_swvp ? (NINE_MAX_CONST_F_SWVP * sizeof(float[4])) : (NINE_MAX_CONST_F * sizeof(float[4]))) -#define VS_CONST_I_SIZE(device) (device->may_swvp ? (NINE_MAX_CONST_I_SWVP * sizeof(int[4])) : (NINE_MAX_CONST_I * sizeof(int[4]))) -#define VS_CONST_B_SIZE(device) (device->may_swvp ? (NINE_MAX_CONST_B_SWVP * sizeof(BOOL)) : (NINE_MAX_CONST_B * sizeof(BOOL))) - - -#define NINE_MAX_TEXTURE_STAGES 8 - -#define NINE_MAX_LIGHTS 65536 -#define NINE_MAX_LIGHTS_ACTIVE 8 - -#define NINED3DLIGHT_INVALID (D3DLIGHT_DIRECTIONAL + 1) - -#define NINE_MAX_SAMPLERS_PS 16 -#define NINE_MAX_SAMPLERS_VS 4 -#define NINE_MAX_SAMPLERS 21 /* PS + DMAP + VS */ -#define NINE_SAMPLER_PS(s) ( 0 + (s)) -#define NINE_SAMPLER_DMAP 16 -#define NINE_SAMPLER_VS(s) (17 + (s)) -#define NINE_PS_SAMPLERS_MASK 0x00ffff -#define NINE_VS_SAMPLERS_MASK 0x1e0000 - -struct nine_ff_state { - struct { - uint32_t tex_stage[NINE_MAX_TEXTURE_STAGES][(NINED3DTSS_COUNT + 31) / 32]; /* stateblocks only */ - uint32_t transform[(NINED3DTS_COUNT + 31) / 32]; - } changed; - - D3DMATRIX *transform; /* access only via nine_state_access_transform */ - unsigned num_transforms; - - /* XXX: Do state blocks just change the set of active lights or do we - * have to store which lights have been disabled, too ? - */ - D3DLIGHT9 *light; - uint16_t active_light[NINE_MAX_LIGHTS_ACTIVE]; /* 8 */ - unsigned num_lights; - unsigned num_lights_active; - - D3DMATERIAL9 material; - - DWORD tex_stage[NINE_MAX_TEXTURE_STAGES][NINED3DTSS_COUNT]; -}; - -struct nine_state -{ - struct { - uint32_t group; - uint32_t rs[(NINED3DRS_COUNT + 31) / 32]; - uint32_t vtxbuf; - uint32_t stream_freq; - uint32_t texture; - uint16_t sampler[NINE_MAX_SAMPLERS]; - struct nine_range *vs_const_f; - struct nine_range *ps_const_f; - struct nine_range *vs_const_i; - uint16_t ps_const_i; /* NINE_MAX_CONST_I == 16 */ - struct nine_range *vs_const_b; - uint16_t ps_const_b; /* NINE_MAX_CONST_B == 16 */ - uint8_t ucp; - } changed; /* stateblocks only */ - - struct NineSurface9 *rt[NINE_MAX_SIMULTANEOUS_RENDERTARGETS]; - struct NineSurface9 *ds; - - D3DVIEWPORT9 viewport; - - struct pipe_scissor_state scissor; - - /* NOTE: vs, ps will be NULL for FF and are set in device->ff.vs,ps instead - * (XXX: or is it better to reference FF shaders here, too ?) - * NOTE: const_f contains extra space for const_i,b to use as user constbuf - */ - struct NineVertexShader9 *vs; - float *vs_const_f; - int *vs_const_i; - BOOL *vs_const_b; - float *vs_lconstf_temp; /* ProcessVertices */ - - struct NinePixelShader9 *ps; - float *ps_const_f; - int ps_const_i[NINE_MAX_CONST_I][4]; - BOOL ps_const_b[NINE_MAX_CONST_B]; - - struct NineVertexDeclaration9 *vdecl; - - struct NineIndexBuffer9 *idxbuf; - struct NineVertexBuffer9 *stream[PIPE_MAX_ATTRIBS]; - struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS]; /* vtxbuf.buffer unused */ - UINT stream_freq[PIPE_MAX_ATTRIBS]; - - struct pipe_clip_state clip; - - DWORD rs_advertised[NINED3DRS_COUNT]; /* the ones apps get with GetRenderState */ - - struct NineBaseTexture9 *texture[NINE_MAX_SAMPLERS]; /* PS, DMAP, VS */ - - DWORD samp_advertised[NINE_MAX_SAMPLERS][D3DSAMP_COUNT]; - - struct nine_ff_state ff; -}; - -struct nine_context { - struct { - uint32_t group; - uint16_t sampler[NINE_MAX_SAMPLERS]; - uint32_t vtxbuf; - BOOL vs_const_f; - BOOL vs_const_i; - BOOL vs_const_b; - BOOL ps_const_f; - BOOL ps_const_i; - BOOL ps_const_b; - BOOL ucp; - } changed; - - uint32_t bumpmap_vars[6 * NINE_MAX_TEXTURE_STAGES]; - - struct NineSurface9 *rt[NINE_MAX_SIMULTANEOUS_RENDERTARGETS]; - struct NineSurface9 *ds; - - struct { - void *vs; - unsigned *vs_const_ranges; - unsigned vs_const_used_size; - void *ps; - unsigned *ps_const_ranges; - unsigned ps_const_used_size; - } cso_shader; - - struct pipe_context *pipe; - struct cso_context *cso; - - uint8_t rt_mask; - - D3DVIEWPORT9 viewport; - - struct pipe_scissor_state scissor; - - struct NineVertexShader9 *vs; - BOOL programmable_vs; - float *vs_const_f; - float *vs_const_f_swvp; - int *vs_const_i; - BOOL *vs_const_b; - float *vs_lconstf_temp; - - struct NinePixelShader9 *ps; - float *ps_const_f; - int ps_const_i[NINE_MAX_CONST_I][4]; - BOOL ps_const_b[NINE_MAX_CONST_B]; - float *ps_lconstf_temp; - - struct NineVertexDeclaration9 *vdecl; - - struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS]; - UINT stream_freq[PIPE_MAX_ATTRIBS]; - uint32_t stream_instancedata_mask; /* derived from stream_freq */ - uint32_t stream_usage_mask; /* derived from VS and vdecl */ - - struct pipe_resource *idxbuf; - unsigned index_offset; - unsigned index_size; - - struct pipe_clip_state clip; - - DWORD rs[NINED3DRS_COUNT]; - - struct { - BOOL enabled; - BOOL shadow; - DWORD lod; - D3DRESOURCETYPE type; - struct pipe_resource *resource; - struct pipe_sampler_view *view[2]; - uint8_t pstype; - } texture[NINE_MAX_SAMPLERS]; - - DWORD samp[NINE_MAX_SAMPLERS][NINED3DSAMP_COUNT]; - - uint32_t samplers_shadow; - - uint8_t bound_samplers_mask_vs; - uint16_t bound_samplers_mask_ps; - - int dummy_vbo_bound_at; /* -1 = not bound , >= 0 = bound index */ - boolean vbo_bound_done; - - boolean inline_constants; - - struct nine_ff_state ff; - - /* software vertex processing */ - boolean swvp; - - uint32_t commit; - struct { - struct pipe_framebuffer_state fb; - struct pipe_depth_stencil_alpha_state dsa; - struct pipe_rasterizer_state rast; - struct pipe_blend_state blend; - struct pipe_constant_buffer cb_vs; - struct pipe_constant_buffer cb0_swvp; - struct pipe_constant_buffer cb1_swvp; - struct pipe_constant_buffer cb2_swvp; - struct pipe_constant_buffer cb3_swvp; - struct pipe_constant_buffer cb_ps; - struct pipe_constant_buffer cb_vs_ff; - struct pipe_constant_buffer cb_ps_ff; - } pipe_data; -}; - -struct nine_state_sw_internal { - struct pipe_transfer *transfers_so[4]; -}; - -struct nine_clipplane { - float plane[4]; -}; -/* map D3DRS -> NINE_STATE_x - */ -extern const uint32_t nine_render_state_group[NINED3DRS_COUNT]; - -/* for D3DSBT_PIXEL/VERTEX: - */ -extern const uint32_t nine_render_states_pixel[(NINED3DRS_COUNT + 31) / 32]; -extern const uint32_t nine_render_states_vertex[(NINED3DRS_COUNT + 31) / 32]; - -struct NineDevice9; - -/* Internal multithreading: When enabled, the nine_context functions - * will append work to a worker thread when possible. Only the worker - * thread can access struct nine_context. */ - -void -nine_context_set_render_state(struct NineDevice9 *device, - D3DRENDERSTATETYPE State, - DWORD Value); - -void -nine_context_set_texture(struct NineDevice9 *device, - DWORD Stage, - struct NineBaseTexture9 *tex); - -void -nine_context_set_sampler_state(struct NineDevice9 *device, - DWORD Sampler, - D3DSAMPLERSTATETYPE Type, - DWORD Value); - -void -nine_context_set_stream_source(struct NineDevice9 *device, - UINT StreamNumber, - struct NineVertexBuffer9 *pVBuf9, - UINT OffsetInBytes, - UINT Stride); - -void -nine_context_set_stream_source_freq(struct NineDevice9 *device, - UINT StreamNumber, - UINT Setting); - -void -nine_context_set_indices(struct NineDevice9 *device, - struct NineIndexBuffer9 *idxbuf); - -void -nine_context_set_vertex_declaration(struct NineDevice9 *device, - struct NineVertexDeclaration9 *vdecl); - -void -nine_context_set_vertex_shader(struct NineDevice9 *device, - struct NineVertexShader9 *pShader); - -void -nine_context_set_vertex_shader_constant_f(struct NineDevice9 *device, - UINT StartRegister, - const float *pConstantData, - const unsigned pConstantData_size, - UINT Vector4fCount); - -void -nine_context_set_vertex_shader_constant_i(struct NineDevice9 *device, - UINT StartRegister, - const int *pConstantData, - const unsigned pConstantData_size, - UINT Vector4iCount); - -void -nine_context_set_vertex_shader_constant_b(struct NineDevice9 *device, - UINT StartRegister, - const BOOL *pConstantData, - const unsigned pConstantData_size, - UINT BoolCount); - -void -nine_context_set_pixel_shader(struct NineDevice9 *device, - struct NinePixelShader9* ps); - -void -nine_context_set_pixel_shader_constant_f(struct NineDevice9 *device, - UINT StartRegister, - const float *pConstantData, - const unsigned pConstantData_size, - UINT Vector4fCount); - -void -nine_context_set_pixel_shader_constant_i(struct NineDevice9 *device, - UINT StartRegister, - const int *pConstantData, - const unsigned pConstantData_size, - UINT Vector4iCount); - -void -nine_context_set_pixel_shader_constant_b(struct NineDevice9 *device, - UINT StartRegister, - const BOOL *pConstantData, - const unsigned pConstantData_size, - UINT BoolCount); - -void -nine_context_set_viewport(struct NineDevice9 *device, - const D3DVIEWPORT9 *viewport); - -void -nine_context_set_scissor(struct NineDevice9 *device, - const struct pipe_scissor_state *scissor); - -void -nine_context_set_transform(struct NineDevice9 *device, - D3DTRANSFORMSTATETYPE State, - const D3DMATRIX *pMatrix); - -void -nine_context_set_material(struct NineDevice9 *device, - const D3DMATERIAL9 *pMaterial); - -void -nine_context_set_light(struct NineDevice9 *device, - DWORD Index, - const D3DLIGHT9 *pLight); - -void -nine_context_light_enable(struct NineDevice9 *device, - DWORD Index, - BOOL Enable); - -void -nine_context_set_texture_stage_state(struct NineDevice9 *device, - DWORD Stage, - D3DTEXTURESTAGESTATETYPE Type, - DWORD Value); - -void -nine_context_set_render_target(struct NineDevice9 *device, - DWORD RenderTargetIndex, - struct NineSurface9 *rt); - -void -nine_context_set_depth_stencil(struct NineDevice9 *device, - struct NineSurface9 *ds); - -void -nine_context_set_clip_plane(struct NineDevice9 *device, - DWORD Index, - const struct nine_clipplane *pPlane); - -void -nine_context_set_swvp(struct NineDevice9 *device, - boolean swvp); - -void -nine_context_apply_stateblock(struct NineDevice9 *device, - const struct nine_state *src); - -void -nine_context_clear_fb(struct NineDevice9 *device, DWORD Count, - const D3DRECT *pRects, DWORD Flags, - D3DCOLOR Color, float Z, DWORD Stencil); - -void -nine_context_draw_primitive(struct NineDevice9 *device, - D3DPRIMITIVETYPE PrimitiveType, - UINT StartVertex, - UINT PrimitiveCount); - -void -nine_context_draw_indexed_primitive(struct NineDevice9 *device, - D3DPRIMITIVETYPE PrimitiveType, - INT BaseVertexIndex, - UINT MinVertexIndex, - UINT NumVertices, - UINT StartIndex, - UINT PrimitiveCount); - -void -nine_context_draw_primitive_from_vtxbuf(struct NineDevice9 *device, - D3DPRIMITIVETYPE PrimitiveType, - UINT PrimitiveCount, - struct pipe_vertex_buffer *vtxbuf); - -void -nine_context_draw_indexed_primitive_from_vtxbuf_idxbuf(struct NineDevice9 *device, - D3DPRIMITIVETYPE PrimitiveType, - UINT MinVertexIndex, - UINT NumVertices, - UINT PrimitiveCount, - struct pipe_vertex_buffer *vbuf, - struct pipe_resource *ibuf, - void *user_ibuf, - unsigned index_offset, - unsigned index_size); - -void -nine_context_resource_copy_region(struct NineDevice9 *device, - struct NineUnknown *dst, - struct NineUnknown *src, - struct pipe_resource* dst_res, - unsigned dst_level, - const struct pipe_box *dst_box, - struct pipe_resource* src_res, - unsigned src_level, - const struct pipe_box *src_box); - -void -nine_context_blit(struct NineDevice9 *device, - struct NineUnknown *dst, - struct NineUnknown *src, - struct pipe_blit_info *blit); - -void -nine_context_clear_render_target(struct NineDevice9 *device, - struct NineSurface9 *surface, - D3DCOLOR color, - UINT x, - UINT y, - UINT width, - UINT height); - -void -nine_context_gen_mipmap(struct NineDevice9 *device, - struct NineUnknown *dst, - struct pipe_resource *res, - UINT base_level, UINT last_level, - UINT first_layer, UINT last_layer, - UINT filter); - -void -nine_context_range_upload(struct NineDevice9 *device, - unsigned *counter, - struct NineUnknown *src_ref, - struct pipe_resource *res, - unsigned offset, - unsigned size, - const void *data); - -void -nine_context_box_upload(struct NineDevice9 *device, - unsigned *counter, - struct NineUnknown *src_ref, - struct pipe_resource *res, - unsigned level, - const struct pipe_box *dst_box, - enum pipe_format src_format, - const void *src, unsigned src_stride, - unsigned src_layer_stride, - const struct pipe_box *src_box); - -struct pipe_query * -nine_context_create_query(struct NineDevice9 *device, unsigned query_type); - -void -nine_context_destroy_query(struct NineDevice9 *device, struct pipe_query *query); - -void -nine_context_begin_query(struct NineDevice9 *device, unsigned *counter, struct pipe_query *query); - -void -nine_context_end_query(struct NineDevice9 *device, unsigned *counter, struct pipe_query *query); - -boolean -nine_context_get_query_result(struct NineDevice9 *device, struct pipe_query *query, - unsigned *counter, boolean flush, boolean wait, - union pipe_query_result *result); - -void nine_state_restore_non_cso(struct NineDevice9 *device); -void nine_state_set_defaults(struct NineDevice9 *, const D3DCAPS9 *, - boolean is_reset); -void nine_device_state_clear(struct NineDevice9 *); -void nine_context_clear(struct NineDevice9 *); - -void nine_state_init_sw(struct NineDevice9 *device); -void nine_state_prepare_draw_sw(struct NineDevice9 *device, - struct NineVertexDeclaration9 *vdecl_out, - int start_vertice, - int num_vertices, - struct pipe_stream_output_info *so); -void nine_state_after_draw_sw(struct NineDevice9 *device); -void nine_state_destroy_sw(struct NineDevice9 *device); - -void -nine_state_resize_transform(struct nine_ff_state *ff_state, unsigned N); - -/* If @alloc is FALSE, the return value may be a const identity matrix. - * Therefore, do not modify if you set alloc to FALSE ! - */ -D3DMATRIX * -nine_state_access_transform(struct nine_ff_state *, D3DTRANSFORMSTATETYPE, - boolean alloc); - -HRESULT -nine_state_set_light(struct nine_ff_state *, DWORD, const D3DLIGHT9 *); - -HRESULT -nine_state_light_enable(struct nine_ff_state *, - DWORD, BOOL); - -const char *nine_d3drs_to_string(DWORD State); - -/* CSMT functions */ -struct csmt_context; - -struct csmt_context * -nine_csmt_create( struct NineDevice9 *This ); - -void -nine_csmt_destroy( struct NineDevice9 *This, struct csmt_context *ctx ); - -void -nine_csmt_process( struct NineDevice9 *This ); - - -/* Get the pipe_context (should not be called from the worker thread). - * All the work in the worker thread is finished before returning. */ -struct pipe_context * -nine_context_get_pipe( struct NineDevice9 *device ); - -/* Can be called from all threads */ -struct pipe_context * -nine_context_get_pipe_multithread( struct NineDevice9 *device ); - - -/* Get the pipe_context (should not be called from the worker thread). - * All the work in the worker thread is paused before returning. - * It is neccessary to release in order to restart the thread. - * This is intended for use of the nine_context pipe_context that don't - * need the worker thread to finish all queued job. */ -struct pipe_context * -nine_context_get_pipe_acquire( struct NineDevice9 *device ); - -void -nine_context_get_pipe_release( struct NineDevice9 *device ); - -#endif /* _NINE_STATE_H_ */ diff --git a/src/gallium/state_trackers/nine/nineexoverlayextension.c b/src/gallium/state_trackers/nine/nineexoverlayextension.c deleted file mode 100644 index 6a4f287e9a3..00000000000 --- a/src/gallium/state_trackers/nine/nineexoverlayextension.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "nineexoverlayextension.h" - -#define DBG_CHANNEL DBG_OVERLAYEXTENSION - -HRESULT NINE_WINAPI -Nine9ExOverlayExtension_CheckDeviceOverlayType( struct Nine9ExOverlayExtension *This, - UINT Adapter, - D3DDEVTYPE DevType, - UINT OverlayWidth, - UINT OverlayHeight, - D3DFORMAT OverlayFormat, - D3DDISPLAYMODEEX *pDisplayMode, - D3DDISPLAYROTATION DisplayRotation, - D3DOVERLAYCAPS *pOverlayCaps ) -{ - STUB(D3DERR_INVALIDCALL); -} - -IDirect3D9ExOverlayExtensionVtbl Nine9ExOverlayExtension_vtable = { - (void *)NineUnknown_QueryInterface, - (void *)NineUnknown_AddRef, - (void *)NineUnknown_Release, - (void *)Nine9ExOverlayExtension_CheckDeviceOverlayType -}; diff --git a/src/gallium/state_trackers/nine/nineexoverlayextension.h b/src/gallium/state_trackers/nine/nineexoverlayextension.h deleted file mode 100644 index f528f1d3ca9..00000000000 --- a/src/gallium/state_trackers/nine/nineexoverlayextension.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef _NINE_NINEEXOVERLAYEXTENSION_H_ -#define _NINE_NINEEXOVERLAYEXTENSION_H_ - -#include "iunknown.h" - -struct Nine9ExOverlayExtension -{ - struct NineUnknown base; -}; -static inline struct Nine9ExOverlayExtension * -Nine9ExOverlayExtension( void *data ) -{ - return (struct Nine9ExOverlayExtension *)data; -} - -HRESULT NINE_WINAPI -Nine9ExOverlayExtension_CheckDeviceOverlayType( struct Nine9ExOverlayExtension *This, - UINT Adapter, - D3DDEVTYPE DevType, - UINT OverlayWidth, - UINT OverlayHeight, - D3DFORMAT OverlayFormat, - D3DDISPLAYMODEEX *pDisplayMode, - D3DDISPLAYROTATION DisplayRotation, - D3DOVERLAYCAPS *pOverlayCaps ); - -#endif /* _NINE_NINEEXOVERLAYEXTENSION_H_ */ diff --git a/src/gallium/state_trackers/nine/pixelshader9.c b/src/gallium/state_trackers/nine/pixelshader9.c deleted file mode 100644 index 4b85c738f79..00000000000 --- a/src/gallium/state_trackers/nine/pixelshader9.c +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "nine_helpers.h" -#include "nine_shader.h" - -#include "pixelshader9.h" - -#include "device9.h" -#include "pipe/p_context.h" - -#define DBG_CHANNEL DBG_PIXELSHADER - -HRESULT -NinePixelShader9_ctor( struct NinePixelShader9 *This, - struct NineUnknownParams *pParams, - const DWORD *pFunction, void *cso ) -{ - struct NineDevice9 *device; - struct nine_shader_info info; - struct pipe_context *pipe; - HRESULT hr; - - DBG("This=%p pParams=%p pFunction=%p cso=%p\n", This, pParams, pFunction, cso); - - hr = NineUnknown_ctor(&This->base, pParams); - if (FAILED(hr)) - return hr; - - if (cso) { - This->ff_cso = cso; - return D3D_OK; - } - device = This->base.device; - - info.type = PIPE_SHADER_FRAGMENT; - info.byte_code = pFunction; - info.const_i_base = NINE_CONST_I_BASE(device->max_ps_const_f) / 16; - info.const_b_base = NINE_CONST_B_BASE(device->max_ps_const_f) / 16; - info.sampler_mask_shadow = 0x0; - info.sampler_ps1xtypes = 0x0; - info.fog_enable = 0; - info.projected = 0; - info.add_constants_defs.c_combination = NULL; - info.add_constants_defs.int_const_added = NULL; - info.add_constants_defs.bool_const_added = NULL; - info.process_vertices = false; - info.swvp_on = false; - - pipe = nine_context_get_pipe_acquire(device); - hr = nine_translate_shader(device, &info, pipe); - nine_context_get_pipe_release(device); - if (FAILED(hr)) - return hr; - This->byte_code.version = info.version; - - This->byte_code.tokens = mem_dup(pFunction, info.byte_size); - if (!This->byte_code.tokens) - return E_OUTOFMEMORY; - This->byte_code.size = info.byte_size; - - This->variant.cso = info.cso; - This->variant.const_ranges = info.const_ranges; - This->variant.const_used_size = info.const_used_size; - This->last_cso = info.cso; - This->last_const_ranges = info.const_ranges; - This->last_const_used_size = info.const_used_size; - This->last_key = 0; - - This->sampler_mask = info.sampler_mask; - This->rt_mask = info.rt_mask; - This->bumpenvmat_needed = info.bumpenvmat_needed; - - memcpy(This->int_slots_used, info.int_slots_used, sizeof(This->int_slots_used)); - memcpy(This->bool_slots_used, info.bool_slots_used, sizeof(This->bool_slots_used)); - - This->const_int_slots = info.const_int_slots; - This->const_bool_slots = info.const_bool_slots; - - This->c_combinations = NULL; - - /* no constant relative addressing for ps */ - assert(info.lconstf.data == NULL); - assert(info.lconstf.ranges == NULL); - - return D3D_OK; -} - -void -NinePixelShader9_dtor( struct NinePixelShader9 *This ) -{ - DBG("This=%p\n", This); - - if (This->base.device) { - struct pipe_context *pipe = nine_context_get_pipe_multithread(This->base.device); - struct nine_shader_variant *var = &This->variant; - - do { - if (var->cso) { - if (This->base.device->context.cso_shader.ps == var->cso) - pipe->bind_fs_state(pipe, NULL); - pipe->delete_fs_state(pipe, var->cso); - FREE(var->const_ranges); - } - var = var->next; - } while (var); - - if (This->ff_cso) { - if (This->ff_cso == This->base.device->context.cso_shader.ps) - pipe->bind_fs_state(pipe, NULL); - pipe->delete_fs_state(pipe, This->ff_cso); - } - } - nine_shader_variants_free(&This->variant); - - nine_shader_constant_combination_free(This->c_combinations); - - FREE((void *)This->byte_code.tokens); /* const_cast */ - - NineUnknown_dtor(&This->base); -} - -HRESULT NINE_WINAPI -NinePixelShader9_GetFunction( struct NinePixelShader9 *This, - void *pData, - UINT *pSizeOfData ) -{ - DBG("This=%p pData=%p pSizeOfData=%p\n", This, pData, pSizeOfData); - - user_assert(pSizeOfData, D3DERR_INVALIDCALL); - - if (!pData) { - *pSizeOfData = This->byte_code.size; - return D3D_OK; - } - user_assert(*pSizeOfData >= This->byte_code.size, D3DERR_INVALIDCALL); - - memcpy(pData, This->byte_code.tokens, This->byte_code.size); - - return D3D_OK; -} - -void * -NinePixelShader9_GetVariant( struct NinePixelShader9 *This, - unsigned **const_ranges, - unsigned *const_used_size ) -{ - /* GetVariant is called from nine_context, thus we can - * get pipe directly */ - struct pipe_context *pipe = This->base.device->context.pipe; - void *cso; - uint64_t key; - - key = This->next_key; - if (key == This->last_key) { - *const_ranges = This->last_const_ranges; - *const_used_size = This->last_const_used_size; - return This->last_cso; - } - - cso = nine_shader_variant_get(&This->variant, const_ranges, const_used_size, key); - if (!cso) { - struct NineDevice9 *device = This->base.device; - struct nine_shader_info info; - HRESULT hr; - - info.type = PIPE_SHADER_FRAGMENT; - info.const_i_base = NINE_CONST_I_BASE(device->max_ps_const_f) / 16; - info.const_b_base = NINE_CONST_B_BASE(device->max_ps_const_f) / 16; - info.byte_code = This->byte_code.tokens; - info.sampler_mask_shadow = key & 0xffff; - /* intended overlap with sampler_mask_shadow */ - if (unlikely(This->byte_code.version < 0x20)) { - if (This->byte_code.version < 0x14) { - info.sampler_ps1xtypes = (key >> 4) & 0xff; - info.projected = (key >> 12) & 0xff; - } else { - info.sampler_ps1xtypes = (key >> 6) & 0xfff; - info.projected = 0; - } - } else { - info.sampler_ps1xtypes = 0; - info.projected = 0; - } - info.fog_enable = device->context.rs[D3DRS_FOGENABLE]; - info.fog_mode = device->context.rs[D3DRS_FOGTABLEMODE]; - info.force_color_in_centroid = (key >> 22) & 1; - info.add_constants_defs.c_combination = - nine_shader_constant_combination_get(This->c_combinations, (key >> 24) & 0xff); - info.add_constants_defs.int_const_added = &This->int_slots_used; - info.add_constants_defs.bool_const_added = &This->bool_slots_used; - info.process_vertices = false; - info.swvp_on = false; - - hr = nine_translate_shader(This->base.device, &info, pipe); - if (FAILED(hr)) - return NULL; - nine_shader_variant_add(&This->variant, key, info.cso, - info.const_ranges, info.const_used_size); - cso = info.cso; - *const_ranges = info.const_ranges; - *const_used_size = info.const_used_size; - } - - This->last_key = key; - This->last_cso = cso; - This->last_const_ranges = *const_ranges; - This->last_const_used_size = *const_used_size; - - return cso; -} - -IDirect3DPixelShader9Vtbl NinePixelShader9_vtable = { - (void *)NineUnknown_QueryInterface, - (void *)NineUnknown_AddRef, - (void *)NineUnknown_Release, - (void *)NineUnknown_GetDevice, - (void *)NinePixelShader9_GetFunction -}; - -static const GUID *NinePixelShader9_IIDs[] = { - &IID_IDirect3DPixelShader9, - &IID_IUnknown, - NULL -}; - -HRESULT -NinePixelShader9_new( struct NineDevice9 *pDevice, - struct NinePixelShader9 **ppOut, - const DWORD *pFunction, void *cso ) -{ - if (cso) { /* ff shader. Needs to start with bind count */ - NINE_DEVICE_CHILD_BIND_NEW(PixelShader9, ppOut, pDevice, pFunction, cso); - } else { - NINE_DEVICE_CHILD_NEW(PixelShader9, ppOut, pDevice, pFunction, cso); - } -} diff --git a/src/gallium/state_trackers/nine/pixelshader9.h b/src/gallium/state_trackers/nine/pixelshader9.h deleted file mode 100644 index 6bac90be7a9..00000000000 --- a/src/gallium/state_trackers/nine/pixelshader9.h +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef _NINE_PIXELSHADER9_H_ -#define _NINE_PIXELSHADER9_H_ - -#include "iunknown.h" -#include "nine_shader.h" -#include "nine_state.h" -#include "basetexture9.h" -#include "nine_ff.h" -#include "surface9.h" - -struct nine_lconstf; - -struct NinePixelShader9 -{ - struct NineUnknown base; - struct nine_shader_variant variant; - - struct { - const DWORD *tokens; - DWORD size; - uint8_t version; /* (major << 4) | minor */ - } byte_code; - - uint8_t bumpenvmat_needed; - uint16_t sampler_mask; - uint8_t rt_mask; - - boolean int_slots_used[NINE_MAX_CONST_I]; - boolean bool_slots_used[NINE_MAX_CONST_B]; - - unsigned const_int_slots; - unsigned const_bool_slots; - - struct nine_shader_constant_combination *c_combinations; - - uint64_t ff_key[6]; - void *ff_cso; - - uint64_t last_key; - void *last_cso; - unsigned *last_const_ranges; - unsigned last_const_used_size; /* in bytes */ - - uint64_t next_key; -}; -static inline struct NinePixelShader9 * -NinePixelShader9( void *data ) -{ - return (struct NinePixelShader9 *)data; -} - -static inline BOOL -NinePixelShader9_UpdateKey( struct NinePixelShader9 *ps, - struct nine_context *context ) -{ - uint16_t samplers_shadow; - uint16_t samplers_ps1_types; - uint8_t projected; - uint64_t key; - BOOL res; - - samplers_shadow = (uint16_t)((context->samplers_shadow & NINE_PS_SAMPLERS_MASK) >> NINE_SAMPLER_PS(0)); - key = samplers_shadow & ps->sampler_mask; - - if (unlikely(ps->byte_code.version < 0x20)) { - /* variable targets */ - uint32_t m = ps->sampler_mask; - samplers_ps1_types = 0; - while (m) { - int s = ffs(m) - 1; - m &= ~(1 << s); - samplers_ps1_types |= (context->texture[s].enabled ? context->texture[s].pstype : 1) << (s * 2); - } - /* Note: For ps 1.X, only samplers 0 1 2 and 3 are available (except 1.4 where 4 and 5 are available). - * ps < 1.4: samplers_shadow 4b, samplers_ps1_types 8b, projected 8b - * ps 1.4: samplers_shadow 6b, samplers_ps1_types 12b - * Tot ps X.X samplers_shadow + extra: 20b */ - assert((ps->byte_code.version < 0x14 && !(ps->sampler_mask & 0xFFF0)) || !(ps->sampler_mask & 0xFFC0)); - - if (unlikely(ps->byte_code.version < 0x14)) { - key |= samplers_ps1_types << 4; - projected = nine_ff_get_projected_key_programmable(context); - key |= ((uint64_t) projected) << 12; - } else { - key |= samplers_ps1_types << 6; - } - } - - if (ps->byte_code.version < 0x30) { - key |= ((uint64_t)context->rs[D3DRS_FOGENABLE]) << 20; - key |= ((uint64_t)context->rs[D3DRS_FOGTABLEMODE]) << 21; - } - - /* centroid interpolation automatically used for color ps inputs */ - if (context->rt[0]->base.info.nr_samples) - key |= ((uint64_t)1) << 22; - - if ((ps->const_int_slots > 0 || ps->const_bool_slots > 0) && context->inline_constants) - key |= ((uint64_t)nine_shader_constant_combination_key(&ps->c_combinations, - ps->int_slots_used, - ps->bool_slots_used, - (void *)context->ps_const_i, - context->ps_const_b)) << 24; - - res = ps->last_key != key; - if (res) - ps->next_key = key; - return res; -} - -void * -NinePixelShader9_GetVariant( struct NinePixelShader9 *ps, - unsigned **const_ranges, - unsigned *const_used_size ); - -/*** public ***/ - -HRESULT -NinePixelShader9_new( struct NineDevice9 *pDevice, - struct NinePixelShader9 **ppOut, - const DWORD *pFunction, void *cso ); - -HRESULT -NinePixelShader9_ctor( struct NinePixelShader9 *, - struct NineUnknownParams *pParams, - const DWORD *pFunction, void *cso ); - -void -NinePixelShader9_dtor( struct NinePixelShader9 * ); - -HRESULT NINE_WINAPI -NinePixelShader9_GetFunction( struct NinePixelShader9 *This, - void *pData, - UINT *pSizeOfData ); - -#endif /* _NINE_PIXELSHADER9_H_ */ diff --git a/src/gallium/state_trackers/nine/query9.c b/src/gallium/state_trackers/nine/query9.c deleted file mode 100644 index d98db9eba7e..00000000000 --- a/src/gallium/state_trackers/nine/query9.c +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "device9.h" -#include "nine_state.h" -#include "query9.h" -#include "nine_helpers.h" -#include "pipe/p_screen.h" -#include "pipe/p_context.h" -#include "util/u_math.h" -#include "nine_dump.h" - -#define DBG_CHANNEL DBG_QUERY - -static inline unsigned -d3dquerytype_to_pipe_query(struct pipe_screen *screen, D3DQUERYTYPE type) -{ - switch (type) { - case D3DQUERYTYPE_EVENT: - return PIPE_QUERY_GPU_FINISHED; - case D3DQUERYTYPE_OCCLUSION: - return screen->get_param(screen, PIPE_CAP_OCCLUSION_QUERY) ? - PIPE_QUERY_OCCLUSION_COUNTER : PIPE_QUERY_TYPES; - case D3DQUERYTYPE_TIMESTAMP: - return screen->get_param(screen, PIPE_CAP_QUERY_TIMESTAMP) ? - PIPE_QUERY_TIMESTAMP : PIPE_QUERY_TYPES; - case D3DQUERYTYPE_TIMESTAMPDISJOINT: - case D3DQUERYTYPE_TIMESTAMPFREQ: - return screen->get_param(screen, PIPE_CAP_QUERY_TIMESTAMP) ? - PIPE_QUERY_TIMESTAMP_DISJOINT : PIPE_QUERY_TYPES; - case D3DQUERYTYPE_VERTEXSTATS: - return screen->get_param(screen, - PIPE_CAP_QUERY_PIPELINE_STATISTICS) ? - PIPE_QUERY_PIPELINE_STATISTICS : PIPE_QUERY_TYPES; - default: - return PIPE_QUERY_TYPES; /* Query not supported */ - } -} - -#define GET_DATA_SIZE_CASE2(a, b) case D3DQUERYTYPE_##a: return sizeof(D3DDEVINFO_##b) -#define GET_DATA_SIZE_CASET(a, b) case D3DQUERYTYPE_##a: return sizeof(b) -static inline DWORD -nine_query_result_size(D3DQUERYTYPE type) -{ - switch (type) { - GET_DATA_SIZE_CASE2(VERTEXSTATS, D3DVERTEXSTATS); - GET_DATA_SIZE_CASET(EVENT, BOOL); - GET_DATA_SIZE_CASET(OCCLUSION, DWORD); - GET_DATA_SIZE_CASET(TIMESTAMP, UINT64); - GET_DATA_SIZE_CASET(TIMESTAMPDISJOINT, BOOL); - GET_DATA_SIZE_CASET(TIMESTAMPFREQ, UINT64); - default: - assert(0); - return 0; - } -} - -HRESULT -nine_is_query_supported(struct pipe_screen *screen, D3DQUERYTYPE type) -{ - const unsigned ptype = d3dquerytype_to_pipe_query(screen, type); - - user_assert(ptype != ~0, D3DERR_INVALIDCALL); - - if (ptype == PIPE_QUERY_TYPES) { - DBG("Query type %u (%s) not supported.\n", - type, nine_D3DQUERYTYPE_to_str(type)); - return D3DERR_NOTAVAILABLE; - } - return D3D_OK; -} - -HRESULT -NineQuery9_ctor( struct NineQuery9 *This, - struct NineUnknownParams *pParams, - D3DQUERYTYPE Type ) -{ - struct NineDevice9 *device = pParams->device; - const unsigned ptype = d3dquerytype_to_pipe_query(device->screen, Type); - HRESULT hr; - - DBG("This=%p pParams=%p Type=%d\n", This, pParams, Type); - - hr = NineUnknown_ctor(&This->base, pParams); - if (FAILED(hr)) - return hr; - - This->state = NINE_QUERY_STATE_FRESH; - This->type = Type; - - user_assert(ptype != ~0, D3DERR_INVALIDCALL); - - if (ptype < PIPE_QUERY_TYPES) { - This->pq = nine_context_create_query(device, ptype); - if (!This->pq) - return E_OUTOFMEMORY; - } else { - assert(0); /* we have checked this case before */ - } - - This->instant = - Type == D3DQUERYTYPE_EVENT || - Type == D3DQUERYTYPE_RESOURCEMANAGER || - Type == D3DQUERYTYPE_TIMESTAMP || - Type == D3DQUERYTYPE_TIMESTAMPFREQ || - Type == D3DQUERYTYPE_VCACHE || - Type == D3DQUERYTYPE_VERTEXSTATS; - - This->result_size = nine_query_result_size(Type); - - return D3D_OK; -} - -void -NineQuery9_dtor( struct NineQuery9 *This ) -{ - struct NineDevice9 *device = This->base.device; - - DBG("This=%p\n", This); - - if (This->pq) { - if (This->state == NINE_QUERY_STATE_RUNNING) - nine_context_end_query(device, &This->counter, This->pq); - nine_context_destroy_query(device, This->pq); - } - - NineUnknown_dtor(&This->base); -} - -D3DQUERYTYPE NINE_WINAPI -NineQuery9_GetType( struct NineQuery9 *This ) -{ - return This->type; -} - -DWORD NINE_WINAPI -NineQuery9_GetDataSize( struct NineQuery9 *This ) -{ - return This->result_size; -} - -HRESULT NINE_WINAPI -NineQuery9_Issue( struct NineQuery9 *This, - DWORD dwIssueFlags ) -{ - struct NineDevice9 *device = This->base.device; - - DBG("This=%p dwIssueFlags=%d\n", This, dwIssueFlags); - - user_assert((dwIssueFlags == D3DISSUE_BEGIN) || - (dwIssueFlags == 0) || - (dwIssueFlags == D3DISSUE_END), D3DERR_INVALIDCALL); - - /* Wine tests: always return D3D_OK on D3DISSUE_BEGIN - * even when the call is supposed to be forbidden */ - if (dwIssueFlags == D3DISSUE_BEGIN && This->instant) - return D3D_OK; - - if (dwIssueFlags == D3DISSUE_BEGIN) { - if (This->state == NINE_QUERY_STATE_RUNNING) - nine_context_end_query(device, &This->counter, This->pq); - nine_context_begin_query(device, &This->counter, This->pq); - This->state = NINE_QUERY_STATE_RUNNING; - } else { - if (This->state != NINE_QUERY_STATE_RUNNING && - This->type != D3DQUERYTYPE_EVENT && - This->type != D3DQUERYTYPE_TIMESTAMP) - nine_context_begin_query(device, &This->counter, This->pq); - nine_context_end_query(device, &This->counter, This->pq); - This->state = NINE_QUERY_STATE_ENDED; - } - return D3D_OK; -} - -union nine_query_result -{ - D3DDEVINFO_D3DVERTEXSTATS vertexstats; - DWORD dw; - BOOL b; - UINT64 u64; -}; - -HRESULT NINE_WINAPI -NineQuery9_GetData( struct NineQuery9 *This, - void *pData, - DWORD dwSize, - DWORD dwGetDataFlags ) -{ - struct NineDevice9 *device = This->base.device; - boolean ok, wait_query_result = FALSE; - union pipe_query_result presult; - union nine_query_result nresult; - - DBG("This=%p pData=%p dwSize=%d dwGetDataFlags=%d\n", - This, pData, dwSize, dwGetDataFlags); - - /* according to spec we should return D3DERR_INVALIDCALL here, but - * wine returns S_FALSE because it is apparently the behaviour - * on windows */ - user_assert(This->state != NINE_QUERY_STATE_RUNNING, S_FALSE); - user_assert(dwSize == 0 || pData, D3DERR_INVALIDCALL); - user_assert(dwGetDataFlags == 0 || - dwGetDataFlags == D3DGETDATA_FLUSH, D3DERR_INVALIDCALL); - - if (This->state == NINE_QUERY_STATE_FRESH) { - /* App forgot calling Issue. call it for it. - * However Wine states that return value should - * be S_OK, so wait for the result to return S_OK. */ - NineQuery9_Issue(This, D3DISSUE_END); - wait_query_result = TRUE; - } - - /* The documention mentions no special case for D3DQUERYTYPE_TIMESTAMP. - * However Windows tests show that the query always succeeds when - * D3DGETDATA_FLUSH is specified. */ - if (This->type == D3DQUERYTYPE_TIMESTAMP && - (dwGetDataFlags & D3DGETDATA_FLUSH)) - wait_query_result = TRUE; - - - /* Note: We ignore dwGetDataFlags, because get_query_result will - * flush automatically if needed */ - - ok = nine_context_get_query_result(device, This->pq, &This->counter, - !!(dwGetDataFlags & D3DGETDATA_FLUSH), - wait_query_result, &presult); - - if (!ok) return S_FALSE; - - if (!dwSize) - return S_OK; - - switch (This->type) { - case D3DQUERYTYPE_EVENT: - nresult.b = presult.b; - break; - case D3DQUERYTYPE_OCCLUSION: - nresult.dw = presult.u64; - break; - case D3DQUERYTYPE_TIMESTAMP: - nresult.u64 = presult.u64; - break; - case D3DQUERYTYPE_TIMESTAMPDISJOINT: - nresult.b = presult.timestamp_disjoint.disjoint; - break; - case D3DQUERYTYPE_TIMESTAMPFREQ: - /* Applications use it to convert the TIMESTAMP value to time. - AMD drivers on win seem to return the actual hardware clock - resolution and corresponding values in TIMESTAMP. - However, this behaviour is not easy to replicate here. - So instead we do what wine and opengl do, and use - nanoseconds TIMESTAMPs. - (Which is also the unit used by PIPE_QUERY_TIMESTAMP.) - */ - nresult.u64 = 1000000000; - break; - case D3DQUERYTYPE_VERTEXSTATS: - nresult.vertexstats.NumRenderedTriangles = - presult.pipeline_statistics.c_invocations; - nresult.vertexstats.NumExtraClippingTriangles = - presult.pipeline_statistics.c_primitives; - break; - default: - assert(0); - break; - } - memcpy(pData, &nresult, MIN2(sizeof(nresult), dwSize)); - - return S_OK; -} - -IDirect3DQuery9Vtbl NineQuery9_vtable = { - (void *)NineUnknown_QueryInterface, - (void *)NineUnknown_AddRef, - (void *)NineUnknown_Release, - (void *)NineUnknown_GetDevice, /* actually part of Query9 iface */ - (void *)NineQuery9_GetType, - (void *)NineQuery9_GetDataSize, - (void *)NineQuery9_Issue, - (void *)NineQuery9_GetData -}; - -static const GUID *NineQuery9_IIDs[] = { - &IID_IDirect3DQuery9, - &IID_IUnknown, - NULL -}; - -HRESULT -NineQuery9_new( struct NineDevice9 *pDevice, - struct NineQuery9 **ppOut, - D3DQUERYTYPE Type ) -{ - NINE_DEVICE_CHILD_NEW(Query9, ppOut, pDevice, Type); -} diff --git a/src/gallium/state_trackers/nine/query9.h b/src/gallium/state_trackers/nine/query9.h deleted file mode 100644 index cc6c717390d..00000000000 --- a/src/gallium/state_trackers/nine/query9.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef _NINE_QUERY9_H_ -#define _NINE_QUERY9_H_ - -#include "iunknown.h" - -enum nine_query_state -{ - NINE_QUERY_STATE_FRESH = 0, - NINE_QUERY_STATE_RUNNING, - NINE_QUERY_STATE_ENDED, -}; - -struct NineQuery9 -{ - struct NineUnknown base; - struct pipe_query *pq; - DWORD result_size; - D3DQUERYTYPE type; - enum nine_query_state state; - boolean instant; /* true if D3DISSUE_BEGIN is not needed / invalid */ - unsigned counter; /* Number of pending Begin/End (0 if internal multithreading off) */ -}; -static inline struct NineQuery9 * -NineQuery9( void *data ) -{ - return (struct NineQuery9 *)data; -} - -HRESULT -nine_is_query_supported(struct pipe_screen *screen, D3DQUERYTYPE); - -HRESULT -NineQuery9_new( struct NineDevice9 *Device, - struct NineQuery9 **ppOut, - D3DQUERYTYPE); - -HRESULT -NineQuery9_ctor( struct NineQuery9 *, - struct NineUnknownParams *pParams, - D3DQUERYTYPE Type ); - -void -NineQuery9_dtor( struct NineQuery9 * ); - -D3DQUERYTYPE NINE_WINAPI -NineQuery9_GetType( struct NineQuery9 *This ); - -DWORD NINE_WINAPI -NineQuery9_GetDataSize( struct NineQuery9 *This ); - -HRESULT NINE_WINAPI -NineQuery9_Issue( struct NineQuery9 *This, - DWORD dwIssueFlags ); - -HRESULT NINE_WINAPI -NineQuery9_GetData( struct NineQuery9 *This, - void *pData, - DWORD dwSize, - DWORD dwGetDataFlags ); - -#endif /* _NINE_QUERY9_H_ */ diff --git a/src/gallium/state_trackers/nine/resource9.c b/src/gallium/state_trackers/nine/resource9.c deleted file mode 100644 index 852801624a9..00000000000 --- a/src/gallium/state_trackers/nine/resource9.c +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "resource9.h" -#include "device9.h" -#include "nine_helpers.h" -#include "nine_defines.h" - -#include "util/u_inlines.h" -#include "util/u_resource.h" - -#include "pipe/p_screen.h" - -#define DBG_CHANNEL DBG_RESOURCE - -HRESULT -NineResource9_ctor( struct NineResource9 *This, - struct NineUnknownParams *pParams, - struct pipe_resource *initResource, - BOOL Allocate, - D3DRESOURCETYPE Type, - D3DPOOL Pool, - DWORD Usage) -{ - struct pipe_screen *screen; - HRESULT hr; - - DBG("This=%p pParams=%p initResource=%p Allocate=%d " - "Type=%d Pool=%d Usage=%d\n", - This, pParams, initResource, (int) Allocate, - Type, Pool, Usage); - - hr = NineUnknown_ctor(&This->base, pParams); - if (FAILED(hr)) - return hr; - - This->info.screen = screen = This->base.device->screen; - if (initResource) - pipe_resource_reference(&This->resource, initResource); - - if (Allocate) { - assert(!initResource); - - /* On Windows it is possible allocation fails when - * IDirect3DDevice9::GetAvailableTextureMem() still reports - * enough free space. - * - * Some games allocate surfaces - * in a loop until they receive D3DERR_OUTOFVIDEOMEMORY to measure - * the available texture memory size. - * - * We are not using the drivers VRAM statistics because: - * * This would add overhead to each resource allocation. - * * Freeing memory is lazy and takes some time, but applications - * expects the memory counter to change immediately after allocating - * or freeing memory. - * - * Vertexbuffers and indexbuffers are not accounted ! - */ - if (This->info.target != PIPE_BUFFER) { - This->size = util_resource_size(&This->info); - - p_atomic_add(&This->base.device->available_texture_mem, -This->size); - if (This->base.device->available_texture_mem <= - This->base.device->available_texture_limit) { - return D3DERR_OUTOFVIDEOMEMORY; - } - } - - DBG("(%p) Creating pipe_resource.\n", This); - This->resource = screen->resource_create(screen, &This->info); - if (!This->resource) - return D3DERR_OUTOFVIDEOMEMORY; - } - - This->type = Type; - This->pool = Pool; - This->usage = Usage; - This->priority = 0; - - return D3D_OK; -} - -void -NineResource9_dtor( struct NineResource9 *This ) -{ - DBG("This=%p\n", This); - - /* NOTE: We do have to use refcounting, the driver might - * still hold a reference. */ - pipe_resource_reference(&This->resource, NULL); - - /* NOTE: size is 0, unless something has actually been allocated */ - if (This->base.device) - p_atomic_add(&This->base.device->available_texture_mem, This->size); - - NineUnknown_dtor(&This->base); -} - -struct pipe_resource * -NineResource9_GetResource( struct NineResource9 *This ) -{ - return This->resource; -} - -D3DPOOL -NineResource9_GetPool( struct NineResource9 *This ) -{ - return This->pool; -} - -DWORD NINE_WINAPI -NineResource9_SetPriority( struct NineResource9 *This, - DWORD PriorityNew ) -{ - DWORD prev; - DBG("This=%p, PriorityNew=%d\n", This, PriorityNew); - - if (This->pool != D3DPOOL_MANAGED || This->type == D3DRTYPE_SURFACE) - return 0; - - prev = This->priority; - This->priority = PriorityNew; - return prev; -} - -DWORD NINE_WINAPI -NineResource9_GetPriority( struct NineResource9 *This ) -{ - if (This->pool != D3DPOOL_MANAGED || This->type == D3DRTYPE_SURFACE) - return 0; - - return This->priority; -} - -/* NOTE: Don't forget to adjust locked vtable if you change this ! */ -void NINE_WINAPI -NineResource9_PreLoad( struct NineResource9 *This ) -{ - if (This->pool != D3DPOOL_MANAGED) - return; - /* We don't treat managed vertex or index buffers different from - * default ones (are managed vertex buffers even allowed ?), and - * the PreLoad for textures is overridden by superclass. - */ -} - -D3DRESOURCETYPE NINE_WINAPI -NineResource9_GetType( struct NineResource9 *This ) -{ - return This->type; -} diff --git a/src/gallium/state_trackers/nine/resource9.h b/src/gallium/state_trackers/nine/resource9.h deleted file mode 100644 index 9fed45476fb..00000000000 --- a/src/gallium/state_trackers/nine/resource9.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef _NINE_RESOURCE9_H_ -#define _NINE_RESOURCE9_H_ - -#include "iunknown.h" -#include "pipe/p_state.h" - -struct pipe_screen; -struct hash_table; -struct NineDevice9; - -struct NineResource9 -{ - struct NineUnknown base; - - struct pipe_resource *resource; /* device resource */ - - D3DRESOURCETYPE type; - D3DPOOL pool; - DWORD priority; - DWORD usage; - - struct pipe_resource info; /* resource configuration */ - - long long size; -}; -static inline struct NineResource9 * -NineResource9( void *data ) -{ - return (struct NineResource9 *)data; -} - -HRESULT -NineResource9_ctor( struct NineResource9 *This, - struct NineUnknownParams *pParams, - struct pipe_resource *initResource, - BOOL Allocate, - D3DRESOURCETYPE Type, - D3DPOOL Pool, - DWORD Usage); - -void -NineResource9_dtor( struct NineResource9 *This ); - -/*** Nine private methods ***/ - -struct pipe_resource * -NineResource9_GetResource( struct NineResource9 *This ); - -D3DPOOL -NineResource9_GetPool( struct NineResource9 *This ); - -/*** Direct3D public methods ***/ - -DWORD NINE_WINAPI -NineResource9_SetPriority( struct NineResource9 *This, - DWORD PriorityNew ); - -DWORD NINE_WINAPI -NineResource9_GetPriority( struct NineResource9 *This ); - -void NINE_WINAPI -NineResource9_PreLoad( struct NineResource9 *This ); - -D3DRESOURCETYPE NINE_WINAPI -NineResource9_GetType( struct NineResource9 *This ); - -#endif /* _NINE_RESOURCE9_H_ */ diff --git a/src/gallium/state_trackers/nine/stateblock9.c b/src/gallium/state_trackers/nine/stateblock9.c deleted file mode 100644 index c7bdc86e9d0..00000000000 --- a/src/gallium/state_trackers/nine/stateblock9.c +++ /dev/null @@ -1,602 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "stateblock9.h" -#include "device9.h" -#include "basetexture9.h" -#include "nine_helpers.h" -#include "vertexdeclaration9.h" -#include "vertexbuffer9.h" -#include "indexbuffer9.h" - -#define DBG_CHANNEL DBG_STATEBLOCK - -/* XXX TODO: handling of lights is broken */ - -HRESULT -NineStateBlock9_ctor( struct NineStateBlock9 *This, - struct NineUnknownParams *pParams, - enum nine_stateblock_type type ) -{ - HRESULT hr = NineUnknown_ctor(&This->base, pParams); - - DBG("This=%p pParams=%p type=%d\n", This, pParams, type); - - if (FAILED(hr)) - return hr; - - This->type = type; - - This->state.vs_const_f = MALLOC(VS_CONST_F_SIZE(This->base.device)); - This->state.ps_const_f = MALLOC(This->base.device->ps_const_size); - This->state.vs_const_i = MALLOC(VS_CONST_I_SIZE(This->base.device)); - This->state.vs_const_b = MALLOC(VS_CONST_B_SIZE(This->base.device)); - if (!This->state.vs_const_f || !This->state.ps_const_f || - !This->state.vs_const_i || !This->state.vs_const_b) - return E_OUTOFMEMORY; - - return D3D_OK; -} - -void -NineStateBlock9_dtor( struct NineStateBlock9 *This ) -{ - struct nine_state *state = &This->state; - struct nine_range *r; - struct nine_range_pool *pool = &This->base.device->range_pool; - unsigned i; - - for (i = 0; i < ARRAY_SIZE(state->rt); ++i) - nine_bind(&state->rt[i], NULL); - nine_bind(&state->ds, NULL); - nine_bind(&state->vs, NULL); - nine_bind(&state->ps, NULL); - nine_bind(&state->vdecl, NULL); - for (i = 0; i < PIPE_MAX_ATTRIBS; ++i) - nine_bind(&state->stream[i], NULL); - - nine_bind(&state->idxbuf, NULL); - for (i = 0; i < NINE_MAX_SAMPLERS; ++i) - nine_bind(&state->texture[i], NULL); - - FREE(state->vs_const_f); - FREE(state->ps_const_f); - FREE(state->vs_const_i); - FREE(state->vs_const_b); - - FREE(state->ff.light); - - FREE(state->ff.transform); - - if (This->state.changed.ps_const_f) { - for (r = This->state.changed.ps_const_f; r->next; r = r->next); - nine_range_pool_put_chain(pool, This->state.changed.ps_const_f, r); - } - if (This->state.changed.vs_const_f) { - for (r = This->state.changed.vs_const_f; r->next; r = r->next); - nine_range_pool_put_chain(pool, This->state.changed.vs_const_f, r); - } - if (This->state.changed.vs_const_i) { - for (r = This->state.changed.vs_const_i; r->next; r = r->next); - nine_range_pool_put_chain(pool, This->state.changed.vs_const_i, r); - } - if (This->state.changed.vs_const_b) { - for (r = This->state.changed.vs_const_b; r->next; r = r->next); - nine_range_pool_put_chain(pool, This->state.changed.vs_const_b, r); - } - - NineUnknown_dtor(&This->base); -} - -static void -NineStateBlock9_BindBuffer( struct NineDevice9 *device, - boolean applyToDevice, - struct NineBuffer9 **slot, - struct NineBuffer9 *buf ) -{ - if (applyToDevice) - NineBindBufferToDevice(device, slot, buf); - else - nine_bind(slot, buf); -} - -static void -NineStateBlock9_BindTexture( struct NineDevice9 *device, - boolean applyToDevice, - struct NineBaseTexture9 **slot, - struct NineBaseTexture9 *tex ) -{ - if (applyToDevice) - NineBindTextureToDevice(device, slot, tex); - else - nine_bind(slot, tex); -} - -/* Copy state marked changed in @mask from @src to @dst. - * If @apply is false, updating dst->changed can be omitted. - * TODO: compare ? - */ -static void -nine_state_copy_common(struct NineDevice9 *device, - struct nine_state *dst, - struct nine_state *src, - struct nine_state *mask, /* aliases either src or dst */ - const boolean apply, - struct nine_range_pool *pool) -{ - unsigned i, s; - - DBG("apply:%d changed.group: %x\n", (int)apply, (int)mask->changed.group ); - - /* device changed.* are unused. - * Instead nine_context_apply_stateblock is used and will - * internally set the right context->changed fields. - * Uncomment these only if we want to apply a stateblock onto a stateblock. - * - * if (apply) - * dst->changed.group |= mask->changed.group; - */ - - if (mask->changed.group & NINE_STATE_VIEWPORT) - dst->viewport = src->viewport; - if (mask->changed.group & NINE_STATE_SCISSOR) - dst->scissor = src->scissor; - - if (mask->changed.group & NINE_STATE_VS) - nine_bind(&dst->vs, src->vs); - if (mask->changed.group & NINE_STATE_PS) - nine_bind(&dst->ps, src->ps); - - /* Vertex constants. - * - * Various possibilities for optimization here, like creating a per-SB - * constant buffer, or memcmp'ing for changes. - * Will do that later depending on what works best for specific apps. - * - * Note: Currently when we apply stateblocks, it's always on the device state. - * Should it affect recording stateblocks ? Since it's on device state, there - * is no need to copy which ranges are dirty. If it turns out we should affect - * recording stateblocks, the info should be copied. - */ - if (mask->changed.group & NINE_STATE_VS_CONST) { - struct nine_range *r; - for (r = mask->changed.vs_const_f; r; r = r->next) { - memcpy(&dst->vs_const_f[r->bgn * 4], - &src->vs_const_f[r->bgn * 4], - (r->end - r->bgn) * 4 * sizeof(float)); - } - for (r = mask->changed.vs_const_i; r; r = r->next) { - memcpy(&dst->vs_const_i[r->bgn * 4], - &src->vs_const_i[r->bgn * 4], - (r->end - r->bgn) * 4 * sizeof(int)); - } - for (r = mask->changed.vs_const_b; r; r = r->next) { - memcpy(&dst->vs_const_b[r->bgn], - &src->vs_const_b[r->bgn], - (r->end - r->bgn) * sizeof(int)); - } - } - - /* Pixel constants. */ - if (mask->changed.group & NINE_STATE_PS_CONST) { - struct nine_range *r; - for (r = mask->changed.ps_const_f; r; r = r->next) { - memcpy(&dst->ps_const_f[r->bgn * 4], - &src->ps_const_f[r->bgn * 4], - (r->end - r->bgn) * 4 * sizeof(float)); - } - if (mask->changed.ps_const_i) { - uint16_t m = mask->changed.ps_const_i; - for (i = ffs(m) - 1, m >>= i; m; ++i, m >>= 1) - if (m & 1) - memcpy(dst->ps_const_i[i], src->ps_const_i[i], 4 * sizeof(int)); - } - if (mask->changed.ps_const_b) { - uint16_t m = mask->changed.ps_const_b; - for (i = ffs(m) - 1, m >>= i; m; ++i, m >>= 1) - if (m & 1) - dst->ps_const_b[i] = src->ps_const_b[i]; - } - } - - /* Render states. - * TODO: Maybe build a list ? - */ - for (i = 0; i < ARRAY_SIZE(mask->changed.rs); ++i) { - uint32_t m = mask->changed.rs[i]; - /* if (apply) - * dst->changed.rs[i] |= m; */ - while (m) { - const int r = ffs(m) - 1; - m &= ~(1 << r); - DBG("State %d %s = %d\n", i * 32 + r, nine_d3drs_to_string(i * 32 + r), (int)src->rs_advertised[i * 32 + r]); - dst->rs_advertised[i * 32 + r] = src->rs_advertised[i * 32 + r]; - } - } - - - /* Clip planes. */ - if (mask->changed.ucp) { - DBG("ucp: %x\n", mask->changed.ucp); - for (i = 0; i < PIPE_MAX_CLIP_PLANES; ++i) - if (mask->changed.ucp & (1 << i)) - memcpy(dst->clip.ucp[i], - src->clip.ucp[i], sizeof(src->clip.ucp[0])); - /* if (apply) - * dst->changed.ucp |= mask->changed.ucp;*/ - } - - /* Sampler state. */ - if (mask->changed.group & NINE_STATE_SAMPLER) { - for (s = 0; s < NINE_MAX_SAMPLERS; ++s) { - if (mask->changed.sampler[s] == 0x3ffe) { - memcpy(&dst->samp_advertised[s], &src->samp_advertised[s], sizeof(dst->samp_advertised[s])); - } else { - uint32_t m = mask->changed.sampler[s]; - DBG("samp %d: changed = %x\n", i, (int)m); - while (m) { - const int i = ffs(m) - 1; - m &= ~(1 << i); - dst->samp_advertised[s][i] = src->samp_advertised[s][i]; - } - } - /* if (apply) - * dst->changed.sampler[s] |= mask->changed.sampler[s];*/ - } - } - - /* Index buffer. */ - if (mask->changed.group & NINE_STATE_IDXBUF) - NineStateBlock9_BindBuffer(device, - apply, - (struct NineBuffer9 **)&dst->idxbuf, - (struct NineBuffer9 *)src->idxbuf); - - /* Vertex streams. */ - if (mask->changed.vtxbuf | mask->changed.stream_freq) { - DBG("vtxbuf/stream_freq: %x/%x\n", mask->changed.vtxbuf, mask->changed.stream_freq); - uint32_t m = mask->changed.vtxbuf | mask->changed.stream_freq; - for (i = 0; m; ++i, m >>= 1) { - if (mask->changed.vtxbuf & (1 << i)) { - NineStateBlock9_BindBuffer(device, - apply, - (struct NineBuffer9 **)&dst->stream[i], - (struct NineBuffer9 *)src->stream[i]); - if (src->stream[i]) { - dst->vtxbuf[i].buffer_offset = src->vtxbuf[i].buffer_offset; - dst->vtxbuf[i].stride = src->vtxbuf[i].stride; - } - } - if (mask->changed.stream_freq & (1 << i)) - dst->stream_freq[i] = src->stream_freq[i]; - } - /* - * if (apply) { - * dst->changed.vtxbuf |= mask->changed.vtxbuf; - * dst->changed.stream_freq |= mask->changed.stream_freq; - * }*/ - } - - /* Textures */ - if (mask->changed.texture) { - uint32_t m = mask->changed.texture; - for (s = 0; m; ++s, m >>= 1) - if (m & 1) - NineStateBlock9_BindTexture(device, apply, &dst->texture[s], src->texture[s]); - } - - if (!(mask->changed.group & NINE_STATE_FF)) - return; - WARN_ONCE("Fixed function state not handled properly by StateBlocks.\n"); - - /* Fixed function state. */ - - if (mask->changed.group & NINE_STATE_FF_MATERIAL) - dst->ff.material = src->ff.material; - - if (mask->changed.group & NINE_STATE_FF_PS_CONSTS) { - for (s = 0; s < NINE_MAX_TEXTURE_STAGES; ++s) { - for (i = 0; i < NINED3DTSS_COUNT; ++i) - if (mask->ff.changed.tex_stage[s][i / 32] & (1 << (i % 32))) - dst->ff.tex_stage[s][i] = src->ff.tex_stage[s][i]; - /* - * if (apply) { - * TODO: it's 32 exactly, just offset by 1 as 0 is unused - * dst->ff.changed.tex_stage[s][0] |= - * mask->ff.changed.tex_stage[s][0]; - * dst->ff.changed.tex_stage[s][1] |= - * mask->ff.changed.tex_stage[s][1]; - * }*/ - } - } - if (mask->changed.group & NINE_STATE_FF_LIGHTING) { - unsigned num_lights = MAX2(dst->ff.num_lights, src->ff.num_lights); - /* Can happen in Capture() if device state has created new lights after - * the stateblock was created. - * Can happen in Apply() if the stateblock had recorded the creation of - * new lights. */ - if (dst->ff.num_lights < num_lights) { - dst->ff.light = REALLOC(dst->ff.light, - dst->ff.num_lights * sizeof(D3DLIGHT9), - num_lights * sizeof(D3DLIGHT9)); - memset(&dst->ff.light[dst->ff.num_lights], 0, (num_lights - dst->ff.num_lights) * sizeof(D3DLIGHT9)); - /* if mask == dst, a Type of 0 will trigger - * "dst->ff.light[i] = src->ff.light[i];" later, - * which is what we want in that case. */ - if (mask != dst) { - for (i = dst->ff.num_lights; i < num_lights; ++i) - dst->ff.light[i].Type = (D3DLIGHTTYPE)NINED3DLIGHT_INVALID; - } - dst->ff.num_lights = num_lights; - } - /* Can happen in Capture() if the stateblock had recorded the creation of - * new lights. - * Can happen in Apply() if device state has created new lights after - * the stateblock was created. */ - if (src->ff.num_lights < num_lights) { - src->ff.light = REALLOC(src->ff.light, - src->ff.num_lights * sizeof(D3DLIGHT9), - num_lights * sizeof(D3DLIGHT9)); - memset(&src->ff.light[src->ff.num_lights], 0, (num_lights - src->ff.num_lights) * sizeof(D3DLIGHT9)); - for (i = src->ff.num_lights; i < num_lights; ++i) - src->ff.light[i].Type = (D3DLIGHTTYPE)NINED3DLIGHT_INVALID; - src->ff.num_lights = num_lights; - } - /* Note: mask is either src or dst, so at this point src, dst and mask - * have num_lights lights. */ - for (i = 0; i < num_lights; ++i) - if (mask->ff.light[i].Type != NINED3DLIGHT_INVALID) - dst->ff.light[i] = src->ff.light[i]; - - memcpy(dst->ff.active_light, src->ff.active_light, sizeof(src->ff.active_light) ); - dst->ff.num_lights_active = src->ff.num_lights_active; - } - if (mask->changed.group & NINE_STATE_FF_VSTRANSF) { - for (i = 0; i < ARRAY_SIZE(mask->ff.changed.transform); ++i) { - if (!mask->ff.changed.transform[i]) - continue; - for (s = i * 32; s < (i * 32 + 32); ++s) { - if (!(mask->ff.changed.transform[i] & (1 << (s % 32)))) - continue; - *nine_state_access_transform(&dst->ff, s, TRUE) = - *nine_state_access_transform(&src->ff, s, FALSE); - } - /* if (apply) - * dst->ff.changed.transform[i] |= mask->ff.changed.transform[i];*/ - } - } -} - -static void -nine_state_copy_common_all(struct NineDevice9 *device, - struct nine_state *dst, - struct nine_state *src, - struct nine_state *help, - const boolean apply, - struct nine_range_pool *pool, - const int MaxStreams) -{ - unsigned i; - - /* if (apply) - * dst->changed.group |= src->changed.group; - */ - - dst->viewport = src->viewport; - dst->scissor = src->scissor; - - nine_bind(&dst->vs, src->vs); - nine_bind(&dst->ps, src->ps); - - /* Vertex constants. - * - * Various possibilities for optimization here, like creating a per-SB - * constant buffer, or memcmp'ing for changes. - * Will do that later depending on what works best for specific apps. - */ - if (1) { - memcpy(&dst->vs_const_f[0], - &src->vs_const_f[0], VS_CONST_F_SIZE(device)); - - memcpy(dst->vs_const_i, src->vs_const_i, VS_CONST_I_SIZE(device)); - memcpy(dst->vs_const_b, src->vs_const_b, VS_CONST_B_SIZE(device)); - } - - /* Pixel constants. */ - if (1) { - struct nine_range *r = help->changed.ps_const_f; - memcpy(&dst->ps_const_f[0], - &src->ps_const_f[0], (r->end - r->bgn) * 4 * sizeof(float)); - - memcpy(dst->ps_const_i, src->ps_const_i, sizeof(dst->ps_const_i)); - memcpy(dst->ps_const_b, src->ps_const_b, sizeof(dst->ps_const_b)); - } - - /* Render states. */ - memcpy(dst->rs_advertised, src->rs_advertised, sizeof(dst->rs_advertised)); - /* if (apply) - * memcpy(dst->changed.rs, src->changed.rs, sizeof(dst->changed.rs));*/ - - - /* Clip planes. */ - memcpy(&dst->clip, &src->clip, sizeof(dst->clip)); - /* if (apply) - * dst->changed.ucp = src->changed.ucp;*/ - - /* Sampler state. */ - memcpy(dst->samp_advertised, src->samp_advertised, sizeof(dst->samp_advertised)); - /* if (apply) - * memcpy(dst->changed.sampler, - * src->changed.sampler, sizeof(dst->changed.sampler));*/ - - /* Index buffer. */ - NineStateBlock9_BindBuffer(device, - apply, - (struct NineBuffer9 **)&dst->idxbuf, - (struct NineBuffer9 *)src->idxbuf); - - /* Vertex streams. */ - if (1) { - for (i = 0; i < ARRAY_SIZE(dst->stream); ++i) { - NineStateBlock9_BindBuffer(device, - apply, - (struct NineBuffer9 **)&dst->stream[i], - (struct NineBuffer9 *)src->stream[i]); - if (src->stream[i]) { - dst->vtxbuf[i].buffer_offset = src->vtxbuf[i].buffer_offset; - dst->vtxbuf[i].stride = src->vtxbuf[i].stride; - } - dst->stream_freq[i] = src->stream_freq[i]; - } - /* if (apply) { - * dst->changed.vtxbuf = (1ULL << MaxStreams) - 1; - * dst->changed.stream_freq = (1ULL << MaxStreams) - 1; - * }*/ - } - - /* Textures */ - if (1) { - for (i = 0; i < NINE_MAX_SAMPLERS; i++) - NineStateBlock9_BindTexture(device, apply, &dst->texture[i], src->texture[i]); - } - - /* keep this check in case we want to disable FF */ - if (!(help->changed.group & NINE_STATE_FF)) - return; - WARN_ONCE("Fixed function state not handled properly by StateBlocks.\n"); - - /* Fixed function state. */ - dst->ff.material = src->ff.material; - - memcpy(dst->ff.tex_stage, src->ff.tex_stage, sizeof(dst->ff.tex_stage)); - /* if (apply) TODO: memset - * memcpy(dst->ff.changed.tex_stage, - * src->ff.changed.tex_stage, sizeof(dst->ff.changed.tex_stage));*/ - - /* Lights. */ - if (1) { - if (dst->ff.num_lights < src->ff.num_lights) { - dst->ff.light = REALLOC(dst->ff.light, - dst->ff.num_lights * sizeof(D3DLIGHT9), - src->ff.num_lights * sizeof(D3DLIGHT9)); - dst->ff.num_lights = src->ff.num_lights; - } - memcpy(dst->ff.light, - src->ff.light, src->ff.num_lights * sizeof(dst->ff.light[0])); - - memcpy(dst->ff.active_light, src->ff.active_light, sizeof(src->ff.active_light) ); - dst->ff.num_lights_active = src->ff.num_lights_active; - } - - /* Transforms. */ - if (1) { - /* Increase dst size if required (to copy the new states). - * Increase src size if required (to initialize missing transforms). - */ - if (dst->ff.num_transforms != src->ff.num_transforms) { - int num_transforms = MAX2(src->ff.num_transforms, dst->ff.num_transforms); - nine_state_resize_transform(&src->ff, num_transforms); - nine_state_resize_transform(&dst->ff, num_transforms); - } - memcpy(dst->ff.transform, - src->ff.transform, dst->ff.num_transforms * sizeof(D3DMATRIX)); - /* Apply is always used on device state. - * src is then the D3DSBT_ALL stateblock which - * ff.changed.transform indicates all matrices are dirty. - * - * if (apply) - * memcpy(dst->ff.changed.transform, - * src->ff.changed.transform, sizeof(dst->ff.changed.transform));*/ - } -} - -/* Capture those bits of current device state that have been changed between - * BeginStateBlock and EndStateBlock. - */ -HRESULT NINE_WINAPI -NineStateBlock9_Capture( struct NineStateBlock9 *This ) -{ - struct NineDevice9 *device = This->base.device; - struct nine_state *dst = &This->state; - struct nine_state *src = &device->state; - const int MaxStreams = device->caps.MaxStreams; - - DBG("This=%p\n", This); - - if (This->type == NINESBT_ALL) - nine_state_copy_common_all(device, dst, src, dst, FALSE, NULL, MaxStreams); - else - nine_state_copy_common(device, dst, src, dst, FALSE, NULL); - - if (dst->changed.group & NINE_STATE_VDECL) - nine_bind(&dst->vdecl, src->vdecl); - - return D3D_OK; -} - -/* Set state managed by this StateBlock as current device state. */ -HRESULT NINE_WINAPI -NineStateBlock9_Apply( struct NineStateBlock9 *This ) -{ - struct NineDevice9 *device = This->base.device; - struct nine_state *dst = &device->state; - struct nine_state *src = &This->state; - struct nine_range_pool *pool = &device->range_pool; - const int MaxStreams = device->caps.MaxStreams; - - DBG("This=%p\n", This); - - if (This->type == NINESBT_ALL) - nine_state_copy_common_all(device, dst, src, src, TRUE, pool, MaxStreams); - else - nine_state_copy_common(device, dst, src, src, TRUE, pool); - - nine_context_apply_stateblock(device, src); - - if ((src->changed.group & NINE_STATE_VDECL) && src->vdecl) - nine_bind(&dst->vdecl, src->vdecl); - - return D3D_OK; -} - -IDirect3DStateBlock9Vtbl NineStateBlock9_vtable = { - (void *)NineUnknown_QueryInterface, - (void *)NineUnknown_AddRef, - (void *)NineUnknown_Release, - (void *)NineUnknown_GetDevice, /* actually part of StateBlock9 iface */ - (void *)NineStateBlock9_Capture, - (void *)NineStateBlock9_Apply -}; - -static const GUID *NineStateBlock9_IIDs[] = { - &IID_IDirect3DStateBlock9, - &IID_IUnknown, - NULL -}; - -HRESULT -NineStateBlock9_new( struct NineDevice9 *pDevice, - struct NineStateBlock9 **ppOut, - enum nine_stateblock_type type) -{ - NINE_DEVICE_CHILD_NEW(StateBlock9, ppOut, pDevice, type); -} diff --git a/src/gallium/state_trackers/nine/stateblock9.h b/src/gallium/state_trackers/nine/stateblock9.h deleted file mode 100644 index ffcc2d99a53..00000000000 --- a/src/gallium/state_trackers/nine/stateblock9.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef _NINE_STATEBLOCK9_H_ -#define _NINE_STATEBLOCK9_H_ - -#include "iunknown.h" - -#include "nine_state.h" - -enum nine_stateblock_type -{ - NINESBT_ALL, - NINESBT_VERTEXSTATE, - NINESBT_PIXELSTATE, - NINESBT_CUSTOM -}; - -struct NineStateBlock9 -{ - struct NineUnknown base; - - struct nine_state state; - - enum nine_stateblock_type type; -}; -static inline struct NineStateBlock9 * -NineStateBlock9( void *data ) -{ - return (struct NineStateBlock9 *)data; -} - -HRESULT -NineStateBlock9_new( struct NineDevice9 *, - struct NineStateBlock9 **ppOut, - enum nine_stateblock_type); - -HRESULT -NineStateBlock9_ctor( struct NineStateBlock9 *, - struct NineUnknownParams *pParams, - enum nine_stateblock_type type ); - -void -NineStateBlock9_dtor( struct NineStateBlock9 * ); - -HRESULT NINE_WINAPI -NineStateBlock9_Capture( struct NineStateBlock9 *This ); - -HRESULT NINE_WINAPI -NineStateBlock9_Apply( struct NineStateBlock9 *This ); - -#endif /* _NINE_STATEBLOCK9_H_ */ diff --git a/src/gallium/state_trackers/nine/surface9.c b/src/gallium/state_trackers/nine/surface9.c deleted file mode 100644 index db74de2823a..00000000000 --- a/src/gallium/state_trackers/nine/surface9.c +++ /dev/null @@ -1,863 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "iunknown.h" -#include "surface9.h" -#include "device9.h" - -/* for marking dirty */ -#include "basetexture9.h" -#include "texture9.h" -#include "cubetexture9.h" - -#include "nine_helpers.h" -#include "nine_pipe.h" -#include "nine_dump.h" -#include "nine_state.h" - -#include "pipe/p_context.h" -#include "pipe/p_screen.h" -#include "pipe/p_state.h" - -#include "util/u_math.h" -#include "util/u_inlines.h" -#include "util/u_surface.h" - -#define DBG_CHANNEL DBG_SURFACE - -static void -NineSurface9_CreatePipeSurfaces( struct NineSurface9 *This ); - -HRESULT -NineSurface9_ctor( struct NineSurface9 *This, - struct NineUnknownParams *pParams, - struct NineUnknown *pContainer, - struct pipe_resource *pResource, - void *user_buffer, - uint8_t TextureType, - unsigned Level, - unsigned Layer, - D3DSURFACE_DESC *pDesc ) -{ - HRESULT hr; - bool allocate = !pContainer && pDesc->Format != D3DFMT_NULL; - D3DMULTISAMPLE_TYPE multisample_type; - - DBG("This=%p pDevice=%p pResource=%p Level=%u Layer=%u pDesc=%p\n", - This, pParams->device, pResource, Level, Layer, pDesc); - - /* Mark this as a special surface held by another internal resource. */ - pParams->container = pContainer; - /* Make sure there's a Desc */ - assert(pDesc); - - assert(allocate || pResource || user_buffer || - pDesc->Format == D3DFMT_NULL); - assert(!allocate || (!pResource && !user_buffer)); - assert(!pResource || !user_buffer); - assert(!user_buffer || pDesc->Pool != D3DPOOL_DEFAULT); - assert(!pResource || pDesc->Pool == D3DPOOL_DEFAULT); - /* Allocation only from create_zs_or_rt_surface with params 0 0 0 */ - assert(!allocate || (Level == 0 && Layer == 0 && TextureType == 0)); - - This->data = (uint8_t *)user_buffer; - - multisample_type = pDesc->MultiSampleType; - - /* Map MultiSampleQuality to MultiSampleType */ - hr = d3dmultisample_type_check(pParams->device->screen, - pDesc->Format, - &multisample_type, - pDesc->MultiSampleQuality, - NULL); - if (FAILED(hr)) { - return hr; - } - - /* TODO: this is (except width and height) duplicate from - * container info (in the pContainer case). Some refactoring is - * needed to avoid duplication */ - This->base.info.screen = pParams->device->screen; - This->base.info.target = PIPE_TEXTURE_2D; - This->base.info.width0 = pDesc->Width; - This->base.info.height0 = pDesc->Height; - This->base.info.depth0 = 1; - This->base.info.last_level = 0; - This->base.info.array_size = 1; - This->base.info.nr_samples = multisample_type; - This->base.info.nr_storage_samples = multisample_type; - This->base.info.usage = PIPE_USAGE_DEFAULT; - This->base.info.bind = PIPE_BIND_SAMPLER_VIEW; /* StretchRect */ - - if (pDesc->Usage & D3DUSAGE_RENDERTARGET) { - This->base.info.bind |= PIPE_BIND_RENDER_TARGET; - } else if (pDesc->Usage & D3DUSAGE_DEPTHSTENCIL) { - if (!depth_stencil_format(pDesc->Format)) - return D3DERR_INVALIDCALL; - This->base.info.bind = d3d9_get_pipe_depth_format_bindings(pDesc->Format); - if (TextureType) - This->base.info.bind |= PIPE_BIND_SAMPLER_VIEW; - } - - This->base.info.flags = 0; - This->base.info.format = d3d9_to_pipe_format_checked(This->base.info.screen, - pDesc->Format, - This->base.info.target, - This->base.info.nr_samples, - This->base.info.bind, - FALSE, - pDesc->Pool == D3DPOOL_SCRATCH); - - if (This->base.info.format == PIPE_FORMAT_NONE && pDesc->Format != D3DFMT_NULL) - return D3DERR_INVALIDCALL; - - if (allocate && compressed_format(pDesc->Format)) { - const unsigned w = util_format_get_blockwidth(This->base.info.format); - const unsigned h = util_format_get_blockheight(This->base.info.format); - - /* Note: In the !allocate case, the test could fail (lower levels of a texture) */ - user_assert(!(pDesc->Width % w) && !(pDesc->Height % h), D3DERR_INVALIDCALL); - } - - /* Get true format */ - This->format_internal = d3d9_to_pipe_format_checked(This->base.info.screen, - pDesc->Format, - This->base.info.target, - This->base.info.nr_samples, - This->base.info.bind, - FALSE, - TRUE); - if (This->base.info.format != This->format_internal || - /* DYNAMIC Textures requires same stride as ram buffers. - * Do not use workaround by default as it eats more virtual space */ - (pParams->device->workarounds.dynamic_texture_workaround && - pDesc->Pool == D3DPOOL_DEFAULT && pDesc->Usage & D3DUSAGE_DYNAMIC)) { - This->data_internal = align_calloc( - nine_format_get_level_alloc_size(This->format_internal, - pDesc->Width, - pDesc->Height, - 0), 32); - if (!This->data_internal) - return E_OUTOFMEMORY; - This->stride_internal = nine_format_get_stride(This->format_internal, - pDesc->Width); - } - - if ((allocate && pDesc->Pool != D3DPOOL_DEFAULT) || pDesc->Format == D3DFMT_NULL) { - /* Ram buffer with no parent. Has to allocate the resource itself */ - assert(!user_buffer); - This->data = align_calloc( - nine_format_get_level_alloc_size(This->base.info.format, - pDesc->Width, - pDesc->Height, - 0), 32); - if (!This->data) - return E_OUTOFMEMORY; - } - - hr = NineResource9_ctor(&This->base, pParams, pResource, - allocate && (pDesc->Pool == D3DPOOL_DEFAULT), - D3DRTYPE_SURFACE, pDesc->Pool, pDesc->Usage); - - if (FAILED(hr)) - return hr; - - This->transfer = NULL; - - This->texture = TextureType; - This->level = Level; - This->level_actual = Level; - This->layer = Layer; - This->desc = *pDesc; - - This->stride = nine_format_get_stride(This->base.info.format, pDesc->Width); - - if (This->base.resource && (pDesc->Usage & D3DUSAGE_DYNAMIC)) - This->base.resource->flags |= NINE_RESOURCE_FLAG_LOCKABLE; - - if (This->base.resource && (pDesc->Usage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL))) - NineSurface9_CreatePipeSurfaces(This); - - /* TODO: investigate what else exactly needs to be cleared */ - if (This->base.resource && (pDesc->Usage & D3DUSAGE_RENDERTARGET)) - nine_context_clear_render_target(pParams->device, This, 0, 0, 0, pDesc->Width, pDesc->Height); - - NineSurface9_Dump(This); - - return D3D_OK; -} - -void -NineSurface9_dtor( struct NineSurface9 *This ) -{ - DBG("This=%p\n", This); - - if (This->transfer) { - struct pipe_context *pipe = nine_context_get_pipe_multithread(This->base.base.device); - pipe->transfer_unmap(pipe, This->transfer); - This->transfer = NULL; - } - - /* Note: Following condition cannot happen currently, since we - * refcount the surface in the functions increasing - * pending_uploads_counter. */ - if (p_atomic_read(&This->pending_uploads_counter)) - nine_csmt_process(This->base.base.device); - - pipe_surface_reference(&This->surface[0], NULL); - pipe_surface_reference(&This->surface[1], NULL); - - /* Release system memory when we have to manage it (no parent) */ - if (!This->base.base.container && This->data) - align_free(This->data); - if (This->data_internal) - align_free(This->data_internal); - NineResource9_dtor(&This->base); -} - -static void -NineSurface9_CreatePipeSurfaces( struct NineSurface9 *This ) -{ - struct pipe_context *pipe; - struct pipe_screen *screen = NineDevice9_GetScreen(This->base.base.device); - struct pipe_resource *resource = This->base.resource; - struct pipe_surface templ; - enum pipe_format srgb_format; - - assert(This->desc.Pool == D3DPOOL_DEFAULT); - assert(resource); - - srgb_format = util_format_srgb(resource->format); - if (srgb_format == PIPE_FORMAT_NONE || - !screen->is_format_supported(screen, srgb_format, - resource->target, 0, 0, resource->bind)) - srgb_format = resource->format; - - memset(&templ, 0, sizeof(templ)); - templ.format = resource->format; - templ.u.tex.level = This->level; - templ.u.tex.first_layer = This->layer; - templ.u.tex.last_layer = This->layer; - - pipe = nine_context_get_pipe_acquire(This->base.base.device); - - This->surface[0] = pipe->create_surface(pipe, resource, &templ); - - memset(&templ, 0, sizeof(templ)); - templ.format = srgb_format; - templ.u.tex.level = This->level; - templ.u.tex.first_layer = This->layer; - templ.u.tex.last_layer = This->layer; - - This->surface[1] = pipe->create_surface(pipe, resource, &templ); - - nine_context_get_pipe_release(This->base.base.device); - - assert(This->surface[0]); /* TODO: Handle failure */ - assert(This->surface[1]); -} - -#if defined(DEBUG) || !defined(NDEBUG) -void -NineSurface9_Dump( struct NineSurface9 *This ) -{ - struct NineBaseTexture9 *tex; - GUID id = IID_IDirect3DBaseTexture9; - REFIID ref = &id; - - DBG("\nNineSurface9(%p->%p/%p): Pool=%s Type=%s Usage=%s\n" - "Dims=%ux%u Format=%s Stride=%u Lockable=%i\n" - "Level=%u(%u), Layer=%u\n", This, This->base.resource, This->data, - nine_D3DPOOL_to_str(This->desc.Pool), - nine_D3DRTYPE_to_str(This->desc.Type), - nine_D3DUSAGE_to_str(This->desc.Usage), - This->desc.Width, This->desc.Height, - d3dformat_to_string(This->desc.Format), This->stride, - This->base.resource && - (This->base.resource->flags & NINE_RESOURCE_FLAG_LOCKABLE), - This->level, This->level_actual, This->layer); - - if (!This->base.base.container) - return; - NineUnknown_QueryInterface(This->base.base.container, ref, (void **)&tex); - if (tex) { - NineBaseTexture9_Dump(tex); - NineUnknown_Release(NineUnknown(tex)); - } -} -#endif /* DEBUG || !NDEBUG */ - -HRESULT NINE_WINAPI -NineSurface9_GetContainer( struct NineSurface9 *This, - REFIID riid, - void **ppContainer ) -{ - HRESULT hr; - char guid_str[64]; - - DBG("This=%p riid=%p id=%s ppContainer=%p\n", - This, riid, riid ? GUID_sprintf(guid_str, riid) : "", ppContainer); - - (void)guid_str; - - if (!ppContainer) return E_POINTER; - - /* Return device for OffscreenPlainSurface, DepthStencilSurface and RenderTarget */ - if (!NineUnknown(This)->container) { - *ppContainer = NineUnknown(This)->device; - NineUnknown_AddRef(NineUnknown(*ppContainer)); - - return D3D_OK; - } - - hr = NineUnknown_QueryInterface(NineUnknown(This)->container, riid, ppContainer); - if (FAILED(hr)) - DBG("QueryInterface FAILED!\n"); - return hr; -} - -void -NineSurface9_MarkContainerDirty( struct NineSurface9 *This ) -{ - if (This->texture) { - struct NineBaseTexture9 *tex = - NineBaseTexture9(This->base.base.container); - assert(tex); - assert(This->texture == D3DRTYPE_TEXTURE || - This->texture == D3DRTYPE_CUBETEXTURE); - if (This->base.pool == D3DPOOL_MANAGED) - tex->managed.dirty = TRUE; - else - if (This->base.usage & D3DUSAGE_AUTOGENMIPMAP) - tex->dirty_mip = TRUE; - - BASETEX_REGISTER_UPDATE(tex); - } -} - -HRESULT NINE_WINAPI -NineSurface9_GetDesc( struct NineSurface9 *This, - D3DSURFACE_DESC *pDesc ) -{ - user_assert(pDesc != NULL, E_POINTER); - *pDesc = This->desc; - return D3D_OK; -} - -/* Add the dirty rects to the source texture */ -inline void -NineSurface9_AddDirtyRect( struct NineSurface9 *This, - const struct pipe_box *box ) -{ - RECT dirty_rect; - - DBG("This=%p box=%p\n", This, box); - - assert (This->base.pool != D3DPOOL_MANAGED || - This->texture == D3DRTYPE_CUBETEXTURE || - This->texture == D3DRTYPE_TEXTURE); - - if (This->base.pool == D3DPOOL_DEFAULT) - return; - - /* Add a dirty rect to level 0 of the parent texture */ - dirty_rect.left = box->x << This->level_actual; - dirty_rect.right = dirty_rect.left + (box->width << This->level_actual); - dirty_rect.top = box->y << This->level_actual; - dirty_rect.bottom = dirty_rect.top + (box->height << This->level_actual); - - if (This->texture == D3DRTYPE_TEXTURE) { - struct NineTexture9 *tex = - NineTexture9(This->base.base.container); - - NineTexture9_AddDirtyRect(tex, &dirty_rect); - } else if (This->texture == D3DRTYPE_CUBETEXTURE) { - struct NineCubeTexture9 *ctex = - NineCubeTexture9(This->base.base.container); - - NineCubeTexture9_AddDirtyRect(ctex, This->layer, &dirty_rect); - } -} - -static inline unsigned -NineSurface9_GetSystemMemOffset(enum pipe_format format, unsigned stride, - int x, int y) -{ - unsigned x_offset = util_format_get_stride(format, x); - - y = util_format_get_nblocksy(format, y); - - return y * stride + x_offset; -} - -HRESULT NINE_WINAPI -NineSurface9_LockRect( struct NineSurface9 *This, - D3DLOCKED_RECT *pLockedRect, - const RECT *pRect, - DWORD Flags ) -{ - struct pipe_resource *resource = This->base.resource; - struct pipe_context *pipe; - struct pipe_box box; - unsigned usage; - - DBG("This=%p pLockedRect=%p pRect=%p[%u..%u,%u..%u] Flags=%s\n", This, - pLockedRect, pRect, - pRect ? pRect->left : 0, pRect ? pRect->right : 0, - pRect ? pRect->top : 0, pRect ? pRect->bottom : 0, - nine_D3DLOCK_to_str(Flags)); - NineSurface9_Dump(This); - - /* check if it's already locked */ - user_assert(This->lock_count == 0, D3DERR_INVALIDCALL); - - /* set pBits to NULL after lock_count check */ - user_assert(pLockedRect, E_POINTER); - pLockedRect->pBits = NULL; - -#ifdef NINE_STRICT - user_assert(This->base.pool != D3DPOOL_DEFAULT || - (resource && (resource->flags & NINE_RESOURCE_FLAG_LOCKABLE)), - D3DERR_INVALIDCALL); -#endif - user_assert(!(Flags & ~(D3DLOCK_DISCARD | - D3DLOCK_DONOTWAIT | - D3DLOCK_NO_DIRTY_UPDATE | - D3DLOCK_NOOVERWRITE | - D3DLOCK_NOSYSLOCK | /* ignored */ - D3DLOCK_READONLY)), D3DERR_INVALIDCALL); - user_assert(!((Flags & D3DLOCK_DISCARD) && (Flags & D3DLOCK_READONLY)), - D3DERR_INVALIDCALL); - - user_assert(This->desc.MultiSampleType == D3DMULTISAMPLE_NONE, - D3DERR_INVALIDCALL); - - if (pRect && This->desc.Pool == D3DPOOL_DEFAULT && - util_format_is_compressed(This->base.info.format)) { - const unsigned w = util_format_get_blockwidth(This->base.info.format); - const unsigned h = util_format_get_blockheight(This->base.info.format); - user_assert((pRect->left == 0 && pRect->right == This->desc.Width && - pRect->top == 0 && pRect->bottom == This->desc.Height) || - (!(pRect->left % w) && !(pRect->right % w) && - !(pRect->top % h) && !(pRect->bottom % h)), - D3DERR_INVALIDCALL); - } - - if (Flags & D3DLOCK_DISCARD) { - usage = PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE; - } else { - usage = (Flags & D3DLOCK_READONLY) ? - PIPE_TRANSFER_READ : PIPE_TRANSFER_READ_WRITE; - } - if (Flags & D3DLOCK_DONOTWAIT) - usage |= PIPE_TRANSFER_DONTBLOCK; - - if (pRect) { - /* Windows XP accepts invalid locking rectangles, Windows 7 rejects - * them. Use Windows XP behaviour for now. */ - rect_to_pipe_box(&box, pRect); - } else { - u_box_origin_2d(This->desc.Width, This->desc.Height, &box); - } - box.z = This->layer; - - user_warn(This->desc.Format == D3DFMT_NULL); - - if (p_atomic_read(&This->pending_uploads_counter)) - nine_csmt_process(This->base.base.device); - - if (This->data_internal || This->data) { - enum pipe_format format = This->base.info.format; - unsigned stride = This->stride; - uint8_t *data = This->data; - if (This->data_internal) { - format = This->format_internal; - stride = This->stride_internal; - data = This->data_internal; - } - DBG("returning system memory\n"); - /* ATI1 and ATI2 need special handling, because of d3d9 bug. - * We must advertise to the application as if it is uncompressed - * and bpp 8, and the app has a workaround to work with the fact - * that it is actually compressed. */ - if (is_ATI1_ATI2(format)) { - pLockedRect->Pitch = This->desc.Width; - pLockedRect->pBits = data + box.y * This->desc.Width + box.x; - } else { - pLockedRect->Pitch = stride; - pLockedRect->pBits = data + - NineSurface9_GetSystemMemOffset(format, - stride, - box.x, - box.y); - } - } else { - bool no_refs = !p_atomic_read(&This->base.base.bind) && - !(This->base.base.container && p_atomic_read(&This->base.base.container->bind)); - DBG("mapping pipe_resource %p (level=%u usage=%x)\n", - resource, This->level, usage); - - /* if the object is not bound internally, there can't be any pending - * operation with the surface in the queue */ - if (no_refs) - pipe = nine_context_get_pipe_acquire(This->base.base.device); - else - pipe = NineDevice9_GetPipe(This->base.base.device); - pLockedRect->pBits = pipe->transfer_map(pipe, resource, - This->level, usage, &box, - &This->transfer); - if (no_refs) - nine_context_get_pipe_release(This->base.base.device); - if (!This->transfer) { - DBG("transfer_map failed\n"); - if (Flags & D3DLOCK_DONOTWAIT) - return D3DERR_WASSTILLDRAWING; - return D3DERR_INVALIDCALL; - } - pLockedRect->Pitch = This->transfer->stride; - } - - if (!(Flags & (D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_READONLY))) { - NineSurface9_MarkContainerDirty(This); - NineSurface9_AddDirtyRect(This, &box); - } - - ++This->lock_count; - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineSurface9_UnlockRect( struct NineSurface9 *This ) -{ - struct pipe_box dst_box, src_box; - struct pipe_context *pipe; - DBG("This=%p lock_count=%u\n", This, This->lock_count); - user_assert(This->lock_count, D3DERR_INVALIDCALL); - if (This->transfer) { - pipe = nine_context_get_pipe_acquire(This->base.base.device); - pipe->transfer_unmap(pipe, This->transfer); - nine_context_get_pipe_release(This->base.base.device); - This->transfer = NULL; - } - --This->lock_count; - - if (This->data_internal) { - if (This->data) { - (void) util_format_translate(This->base.info.format, - This->data, This->stride, - 0, 0, - This->format_internal, - This->data_internal, - This->stride_internal, - 0, 0, - This->desc.Width, This->desc.Height); - } else { - u_box_2d_zslice(0, 0, This->layer, - This->desc.Width, This->desc.Height, &dst_box); - u_box_2d_zslice(0, 0, 0, - This->desc.Width, This->desc.Height, &src_box); - - nine_context_box_upload(This->base.base.device, - &This->pending_uploads_counter, - (struct NineUnknown *)This, - This->base.resource, - This->level, - &dst_box, - This->format_internal, - This->data_internal, - This->stride_internal, - 0, /* depth = 1 */ - &src_box); - } - } - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineSurface9_GetDC( struct NineSurface9 *This, - HDC *phdc ) -{ - STUB(D3DERR_INVALIDCALL); -} - -HRESULT NINE_WINAPI -NineSurface9_ReleaseDC( struct NineSurface9 *This, - HDC hdc ) -{ - STUB(D3DERR_INVALIDCALL); -} - -IDirect3DSurface9Vtbl NineSurface9_vtable = { - (void *)NineUnknown_QueryInterface, - (void *)NineUnknown_AddRef, - (void *)NineUnknown_Release, - (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */ - (void *)NineUnknown_SetPrivateData, - (void *)NineUnknown_GetPrivateData, - (void *)NineUnknown_FreePrivateData, - (void *)NineResource9_SetPriority, - (void *)NineResource9_GetPriority, - (void *)NineResource9_PreLoad, - (void *)NineResource9_GetType, - (void *)NineSurface9_GetContainer, - (void *)NineSurface9_GetDesc, - (void *)NineSurface9_LockRect, - (void *)NineSurface9_UnlockRect, - (void *)NineSurface9_GetDC, - (void *)NineSurface9_ReleaseDC -}; - -/* When this function is called, we have already checked - * The copy regions fit the surfaces */ -void -NineSurface9_CopyMemToDefault( struct NineSurface9 *This, - struct NineSurface9 *From, - const POINT *pDestPoint, - const RECT *pSourceRect ) -{ - struct pipe_resource *r_dst = This->base.resource; - struct pipe_box dst_box, src_box; - int src_x, src_y, dst_x, dst_y, copy_width, copy_height; - - assert(This->base.pool == D3DPOOL_DEFAULT && - From->base.pool == D3DPOOL_SYSTEMMEM); - - if (pDestPoint) { - dst_x = pDestPoint->x; - dst_y = pDestPoint->y; - } else { - dst_x = 0; - dst_y = 0; - } - - if (pSourceRect) { - src_x = pSourceRect->left; - src_y = pSourceRect->top; - copy_width = pSourceRect->right - pSourceRect->left; - copy_height = pSourceRect->bottom - pSourceRect->top; - } else { - src_x = 0; - src_y = 0; - copy_width = From->desc.Width; - copy_height = From->desc.Height; - } - - u_box_2d_zslice(dst_x, dst_y, This->layer, - copy_width, copy_height, &dst_box); - u_box_2d_zslice(src_x, src_y, 0, - copy_width, copy_height, &src_box); - - nine_context_box_upload(This->base.base.device, - &From->pending_uploads_counter, - (struct NineUnknown *)From, - r_dst, - This->level, - &dst_box, - From->base.info.format, - From->data, From->stride, - 0, /* depth = 1 */ - &src_box); - if (From->texture == D3DRTYPE_TEXTURE) { - struct NineTexture9 *tex = - NineTexture9(From->base.base.container); - /* D3DPOOL_SYSTEMMEM with buffer content passed - * from the user: execute the upload right now. - * It is possible it is enough to delay upload - * until the surface refcount is 0, but the - * bind refcount may not be 0, and thus the dtor - * is not executed (and doesn't trigger the - * pending_uploads_counter check). */ - if (!tex->managed_buffer) - nine_csmt_process(This->base.base.device); - } - - if (This->data_internal) - (void) util_format_translate(This->format_internal, - This->data_internal, - This->stride_internal, - dst_x, dst_y, - From->base.info.format, - From->data, From->stride, - src_x, src_y, - copy_width, copy_height); - - NineSurface9_MarkContainerDirty(This); -} - -void -NineSurface9_CopyDefaultToMem( struct NineSurface9 *This, - struct NineSurface9 *From ) -{ - struct pipe_context *pipe; - struct pipe_resource *r_src = From->base.resource; - struct pipe_transfer *transfer; - struct pipe_box src_box; - uint8_t *p_dst; - const uint8_t *p_src; - - assert(This->base.pool == D3DPOOL_SYSTEMMEM && - From->base.pool == D3DPOOL_DEFAULT); - - assert(This->desc.Width == From->desc.Width); - assert(This->desc.Height == From->desc.Height); - - u_box_origin_2d(This->desc.Width, This->desc.Height, &src_box); - src_box.z = From->layer; - - if (p_atomic_read(&This->pending_uploads_counter)) - nine_csmt_process(This->base.base.device); - - pipe = NineDevice9_GetPipe(This->base.base.device); - p_src = pipe->transfer_map(pipe, r_src, From->level, - PIPE_TRANSFER_READ, - &src_box, &transfer); - p_dst = This->data; - - assert (p_src && p_dst); - - util_copy_rect(p_dst, This->base.info.format, - This->stride, 0, 0, - This->desc.Width, This->desc.Height, - p_src, - transfer->stride, 0, 0); - - pipe->transfer_unmap(pipe, transfer); -} - - -/* Gladly, rendering to a MANAGED surface is not permitted, so we will - * never have to do the reverse, i.e. download the surface. - */ -HRESULT -NineSurface9_UploadSelf( struct NineSurface9 *This, - const struct pipe_box *damaged ) -{ - struct pipe_resource *res = This->base.resource; - struct pipe_box box; - - DBG("This=%p damaged=%p\n", This, damaged); - - assert(This->base.pool == D3DPOOL_MANAGED); - - if (damaged) { - box = *damaged; - box.z = This->layer; - box.depth = 1; - } else { - box.x = 0; - box.y = 0; - box.z = This->layer; - box.width = This->desc.Width; - box.height = This->desc.Height; - box.depth = 1; - } - - nine_context_box_upload(This->base.base.device, - &This->pending_uploads_counter, - (struct NineUnknown *)This, - res, - This->level, - &box, - res->format, - This->data, This->stride, - 0, /* depth = 1 */ - &box); - - return D3D_OK; -} - -/* Currently nine_context uses the NineSurface9 - * fields when it is render target. Any modification requires - * pending commands with the surface to be executed. If the bind - * count is 0, there is no pending commands. */ -#define PROCESS_IF_BOUND(surf) \ - if (surf->base.base.bind) \ - nine_csmt_process(surf->base.base.device); - -void -NineSurface9_SetResource( struct NineSurface9 *This, - struct pipe_resource *resource, unsigned level ) -{ - /* No need to call PROCESS_IF_BOUND, because SetResource is used only - * for MANAGED textures, and they are not render targets. */ - assert(This->base.pool == D3DPOOL_MANAGED); - This->level = level; - pipe_resource_reference(&This->base.resource, resource); -} - -void -NineSurface9_SetMultiSampleType( struct NineSurface9 *This, - D3DMULTISAMPLE_TYPE mst ) -{ - PROCESS_IF_BOUND(This); - This->desc.MultiSampleType = mst; -} - -void -NineSurface9_SetResourceResize( struct NineSurface9 *This, - struct pipe_resource *resource ) -{ - assert(This->level == 0 && This->level_actual == 0); - assert(!This->lock_count); - assert(This->desc.Pool == D3DPOOL_DEFAULT); - assert(!This->texture); - - PROCESS_IF_BOUND(This); - pipe_resource_reference(&This->base.resource, resource); - - This->desc.Width = This->base.info.width0 = resource->width0; - This->desc.Height = This->base.info.height0 = resource->height0; - This->base.info.nr_samples = resource->nr_samples; - This->base.info.nr_storage_samples = resource->nr_storage_samples; - - This->stride = nine_format_get_stride(This->base.info.format, - This->desc.Width); - - pipe_surface_reference(&This->surface[0], NULL); - pipe_surface_reference(&This->surface[1], NULL); - if (resource) - NineSurface9_CreatePipeSurfaces(This); -} - - -static const GUID *NineSurface9_IIDs[] = { - &IID_IDirect3DSurface9, - &IID_IDirect3DResource9, - &IID_IUnknown, - NULL -}; - -HRESULT -NineSurface9_new( struct NineDevice9 *pDevice, - struct NineUnknown *pContainer, - struct pipe_resource *pResource, - void *user_buffer, - uint8_t TextureType, - unsigned Level, - unsigned Layer, - D3DSURFACE_DESC *pDesc, - struct NineSurface9 **ppOut ) -{ - NINE_DEVICE_CHILD_NEW(Surface9, ppOut, pDevice, /* args */ - pContainer, pResource, user_buffer, - TextureType, Level, Layer, pDesc); -} diff --git a/src/gallium/state_trackers/nine/surface9.h b/src/gallium/state_trackers/nine/surface9.h deleted file mode 100644 index ee700603bd8..00000000000 --- a/src/gallium/state_trackers/nine/surface9.h +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef _NINE_SURFACE9_H_ -#define _NINE_SURFACE9_H_ - -#include "resource9.h" - -#include "pipe/p_state.h" -#include "util/list.h" -#include "util/u_rect.h" -#include "util/u_inlines.h" - -struct NineSurface9 -{ - struct NineResource9 base; - - /* G3D state */ - struct pipe_transfer *transfer; - struct pipe_surface *surface[2]; /* created on-demand (linear, sRGB) */ - int lock_count; - uint8_t texture; /* rtype of container BaseTex or 0 */ - - /* resource description */ - unsigned level; /* refers to the pipe_resource (SetLOD !) */ - unsigned level_actual; /* refers to the NineTexture */ - unsigned layer; - D3DSURFACE_DESC desc; - - uint8_t *data; /* system memory backing */ - uint8_t *data_internal; /* for conversions */ - enum pipe_format format_internal; - unsigned stride; /* for system memory backing */ - unsigned stride_internal; - - unsigned pending_uploads_counter; /* pending uploads */ -}; -static inline struct NineSurface9 * -NineSurface9( void *data ) -{ - return (struct NineSurface9 *)data; -} - -HRESULT -NineSurface9_new( struct NineDevice9 *pDevice, - struct NineUnknown *pContainer, - struct pipe_resource *pResource, - void *user_buffer, - uint8_t TextureType, /* 0 if pContainer isn't BaseTexure9 */ - unsigned Level, - unsigned Layer, - D3DSURFACE_DESC *pDesc, - struct NineSurface9 **ppOut ); - -HRESULT -NineSurface9_ctor( struct NineSurface9 *This, - struct NineUnknownParams *pParams, - struct NineUnknown *pContainer, - struct pipe_resource *pResource, - void *user_buffer, - uint8_t TextureType, - unsigned Level, - unsigned Layer, - D3DSURFACE_DESC *pDesc ); - -void -NineSurface9_dtor( struct NineSurface9 *This ); - -/*** Nine private ***/ - -void -NineSurface9_MarkContainerDirty( struct NineSurface9 *This ); - -static inline struct pipe_surface * -NineSurface9_GetSurface( struct NineSurface9 *This, int sRGB ) -{ - assert(This->surface[sRGB]); - return This->surface[sRGB]; -} - -static inline struct pipe_resource * -NineSurface9_GetResource( struct NineSurface9 *This ) -{ - return This->base.resource; -} - -void -NineSurface9_SetResource( struct NineSurface9 *This, - struct pipe_resource *resource, unsigned level ); - -void -NineSurface9_SetMultiSampleType( struct NineSurface9 *This, - D3DMULTISAMPLE_TYPE mst ); - -void -NineSurface9_SetResourceResize( struct NineSurface9 *This, - struct pipe_resource *resource ); - -void -NineSurface9_AddDirtyRect( struct NineSurface9 *This, - const struct pipe_box *box ); - -HRESULT -NineSurface9_UploadSelf( struct NineSurface9 *This, - const struct pipe_box *damaged ); - -void -NineSurface9_CopyMemToDefault( struct NineSurface9 *This, - struct NineSurface9 *From, - const POINT *pDestPoint, - const RECT *pSourceRect ); - -void -NineSurface9_CopyDefaultToMem( struct NineSurface9 *This, - struct NineSurface9 *From ); - -static inline boolean -NineSurface9_IsOffscreenPlain (struct NineSurface9 *This ) -{ - return This->base.usage == 0 && !This->texture; -} - -#if defined(DEBUG) || !defined(NDEBUG) -void -NineSurface9_Dump( struct NineSurface9 *This ); -#else -static inline void -NineSurface9_Dump( struct NineSurface9 *This ) { } -#endif - -/*** Direct3D public ***/ - -HRESULT NINE_WINAPI -NineSurface9_GetContainer( struct NineSurface9 *This, - REFIID riid, - void **ppContainer ); - -HRESULT NINE_WINAPI -NineSurface9_GetDesc( struct NineSurface9 *This, - D3DSURFACE_DESC *pDesc ); - -HRESULT NINE_WINAPI -NineSurface9_LockRect( struct NineSurface9 *This, - D3DLOCKED_RECT *pLockedRect, - const RECT *pRect, - DWORD Flags ); - -HRESULT NINE_WINAPI -NineSurface9_UnlockRect( struct NineSurface9 *This ); - -HRESULT NINE_WINAPI -NineSurface9_GetDC( struct NineSurface9 *This, - HDC *phdc ); - -HRESULT NINE_WINAPI -NineSurface9_ReleaseDC( struct NineSurface9 *This, - HDC hdc ); - -#endif /* _NINE_SURFACE9_H_ */ diff --git a/src/gallium/state_trackers/nine/swapchain9.c b/src/gallium/state_trackers/nine/swapchain9.c deleted file mode 100644 index 8a1b1bf145a..00000000000 --- a/src/gallium/state_trackers/nine/swapchain9.c +++ /dev/null @@ -1,1300 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "swapchain9.h" -#include "surface9.h" -#include "device9.h" - -#include "nine_helpers.h" -#include "nine_pipe.h" -#include "nine_dump.h" - -#include "util/u_atomic.h" -#include "util/u_inlines.h" -#include "util/u_surface.h" -#include "hud/hud_context.h" -#include "state_tracker/drm_driver.h" - -#include "threadpool.h" - -#define DBG_CHANNEL DBG_SWAPCHAIN - -#define UNTESTED(n) DBG("UNTESTED point %d. Please tell if it worked\n", n) - -HRESULT -NineSwapChain9_ctor( struct NineSwapChain9 *This, - struct NineUnknownParams *pParams, - BOOL implicit, - ID3DPresent *pPresent, - D3DPRESENT_PARAMETERS *pPresentationParameters, - struct d3dadapter9_context *pCTX, - HWND hFocusWindow, - D3DDISPLAYMODEEX *mode ) -{ - HRESULT hr; - int i; - - DBG("This=%p pDevice=%p pPresent=%p pCTX=%p hFocusWindow=%p\n", - This, pParams->device, pPresent, pCTX, hFocusWindow); - - hr = NineUnknown_ctor(&This->base, pParams); - if (FAILED(hr)) - return hr; - - This->screen = NineDevice9_GetScreen(This->base.device); - This->implicit = implicit; - This->actx = pCTX; - This->present = pPresent; - This->mode = NULL; - - ID3DPresent_AddRef(pPresent); - if (This->base.device->minor_version_num > 2) { - D3DPRESENT_PARAMETERS2 params2; - - memset(¶ms2, 0, sizeof(D3DPRESENT_PARAMETERS2)); - params2.AllowDISCARDDelayedRelease = This->actx->discard_delayed_release; - params2.TearFreeDISCARD = This->actx->tearfree_discard; - ID3DPresent_SetPresentParameters2(pPresent, ¶ms2); - } - - if (!pPresentationParameters->hDeviceWindow) - pPresentationParameters->hDeviceWindow = hFocusWindow; - - This->rendering_done = FALSE; - This->pool = NULL; - for (i = 0; i < D3DPRESENT_BACK_BUFFERS_MAX_EX + 1; i++) { - This->pending_presentation[i] = calloc(1, sizeof(BOOL)); - if (!This->pending_presentation[i]) - return E_OUTOFMEMORY; - } - return NineSwapChain9_Resize(This, pPresentationParameters, mode); -} - -static D3DWindowBuffer * -D3DWindowBuffer_create(struct NineSwapChain9 *This, - struct pipe_resource *resource, - int depth, - int for_frontbuffer_reading) -{ - D3DWindowBuffer *ret; - struct pipe_context *pipe = nine_context_get_pipe_acquire(This->base.device); - struct winsys_handle whandle; - int stride, dmaBufFd; - HRESULT hr; - - memset(&whandle, 0, sizeof(whandle)); - whandle.type = WINSYS_HANDLE_TYPE_FD; - This->screen->resource_get_handle(This->screen, pipe, resource, - &whandle, - for_frontbuffer_reading ? - PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE : - PIPE_HANDLE_USAGE_EXPLICIT_FLUSH); - nine_context_get_pipe_release(This->base.device); - stride = whandle.stride; - dmaBufFd = whandle.handle; - hr = ID3DPresent_NewD3DWindowBufferFromDmaBuf(This->present, - dmaBufFd, - resource->width0, - resource->height0, - stride, - depth, - 32, - &ret); - assert (SUCCEEDED(hr)); - - if (FAILED(hr)) { - ERR("Failed to create new D3DWindowBufferFromDmaBuf\n"); - return NULL; - } - return ret; -} - -static void -D3DWindowBuffer_release(struct NineSwapChain9 *This, - D3DWindowBuffer *present_handle) -{ - int i; - - /* IsBufferReleased API not available */ - if (This->base.device->minor_version_num <= 2) { - ID3DPresent_DestroyD3DWindowBuffer(This->present, present_handle); - return; - } - - /* Add it to the 'pending release' list */ - for (i = 0; i < D3DPRESENT_BACK_BUFFERS_MAX_EX + 1; i++) { - if (!This->present_handles_pending_release[i]) { - This->present_handles_pending_release[i] = present_handle; - break; - } - } - if (i == (D3DPRESENT_BACK_BUFFERS_MAX_EX + 1)) { - ERR("Server not releasing buffers...\n"); - assert(false); - } - - /* Destroy elements of the list released by the server */ - for (i = 0; i < D3DPRESENT_BACK_BUFFERS_MAX_EX + 1; i++) { - if (This->present_handles_pending_release[i] && - ID3DPresent_IsBufferReleased(This->present, This->present_handles_pending_release[i])) { - /* WaitBufferReleased also waits the presentation feedback - * (which should arrive at about the same time), - * while IsBufferReleased doesn't. DestroyD3DWindowBuffer unfortunately - * checks it to release immediately all data, else the release - * is postponed for This->present release. To avoid leaks (we may handle - * a lot of resize), call WaitBufferReleased. */ - ID3DPresent_WaitBufferReleased(This->present, This->present_handles_pending_release[i]); - ID3DPresent_DestroyD3DWindowBuffer(This->present, This->present_handles_pending_release[i]); - This->present_handles_pending_release[i] = NULL; - } - } -} - -static int -NineSwapChain9_GetBackBufferCountForParams( struct NineSwapChain9 *This, - D3DPRESENT_PARAMETERS *pParams ); - -HRESULT -NineSwapChain9_Resize( struct NineSwapChain9 *This, - D3DPRESENT_PARAMETERS *pParams, - D3DDISPLAYMODEEX *mode ) -{ - struct NineDevice9 *pDevice = This->base.device; - D3DSURFACE_DESC desc; - HRESULT hr; - struct pipe_resource *resource, tmplt; - enum pipe_format pf; - BOOL has_present_buffers = FALSE; - int depth; - unsigned i, oldBufferCount, newBufferCount; - D3DMULTISAMPLE_TYPE multisample_type; - - DBG("This=%p pParams=%p\n", This, pParams); - user_assert(pParams != NULL, E_POINTER); - user_assert(pParams->SwapEffect, D3DERR_INVALIDCALL); - user_assert((pParams->SwapEffect != D3DSWAPEFFECT_COPY) || - (pParams->BackBufferCount <= 1), D3DERR_INVALIDCALL); - user_assert(pDevice->ex || pParams->BackBufferCount <= - D3DPRESENT_BACK_BUFFERS_MAX, D3DERR_INVALIDCALL); - user_assert(!pDevice->ex || pParams->BackBufferCount <= - D3DPRESENT_BACK_BUFFERS_MAX_EX, D3DERR_INVALIDCALL); - user_assert(pDevice->ex || - (pParams->SwapEffect == D3DSWAPEFFECT_FLIP) || - (pParams->SwapEffect == D3DSWAPEFFECT_COPY) || - (pParams->SwapEffect == D3DSWAPEFFECT_DISCARD), D3DERR_INVALIDCALL); - - DBG("pParams(%p):\n" - "BackBufferWidth: %u\n" - "BackBufferHeight: %u\n" - "BackBufferFormat: %s\n" - "BackBufferCount: %u\n" - "MultiSampleType: %u\n" - "MultiSampleQuality: %u\n" - "SwapEffect: %u\n" - "hDeviceWindow: %p\n" - "Windowed: %i\n" - "EnableAutoDepthStencil: %i\n" - "AutoDepthStencilFormat: %s\n" - "Flags: %s\n" - "FullScreen_RefreshRateInHz: %u\n" - "PresentationInterval: %x\n", pParams, - pParams->BackBufferWidth, pParams->BackBufferHeight, - d3dformat_to_string(pParams->BackBufferFormat), - pParams->BackBufferCount, - pParams->MultiSampleType, pParams->MultiSampleQuality, - pParams->SwapEffect, pParams->hDeviceWindow, pParams->Windowed, - pParams->EnableAutoDepthStencil, - d3dformat_to_string(pParams->AutoDepthStencilFormat), - nine_D3DPRESENTFLAG_to_str(pParams->Flags), - pParams->FullScreen_RefreshRateInHz, - pParams->PresentationInterval); - - if (pParams->BackBufferCount == 0) { - pParams->BackBufferCount = 1; - } - - if (pParams->BackBufferFormat == D3DFMT_UNKNOWN) { - pParams->BackBufferFormat = D3DFMT_A8R8G8B8; - } - - This->desired_fences = This->actx->throttling ? This->actx->throttling_value + 1 : 0; - /* +1 because we add the fence of the current buffer before popping an old one */ - if (This->desired_fences > DRI_SWAP_FENCES_MAX) - This->desired_fences = DRI_SWAP_FENCES_MAX; - - if (This->actx->vblank_mode == 0) - pParams->PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; - else if (This->actx->vblank_mode == 3) - pParams->PresentationInterval = D3DPRESENT_INTERVAL_ONE; - - if (mode && This->mode) { - *(This->mode) = *mode; - } else if (mode) { - This->mode = malloc(sizeof(D3DDISPLAYMODEEX)); - memcpy(This->mode, mode, sizeof(D3DDISPLAYMODEEX)); - } else { - free(This->mode); - This->mode = NULL; - } - - /* Note: It is the role of the backend to fill if necessary - * BackBufferWidth and BackBufferHeight */ - hr = ID3DPresent_SetPresentParameters(This->present, pParams, This->mode); - if (hr != D3D_OK) - return hr; - - oldBufferCount = This->num_back_buffers; - newBufferCount = NineSwapChain9_GetBackBufferCountForParams(This, pParams); - - multisample_type = pParams->MultiSampleType; - - /* Map MultiSampleQuality to MultiSampleType */ - hr = d3dmultisample_type_check(This->screen, pParams->BackBufferFormat, - &multisample_type, - pParams->MultiSampleQuality, - NULL); - if (FAILED(hr)) { - return hr; - } - - pf = d3d9_to_pipe_format_checked(This->screen, pParams->BackBufferFormat, - PIPE_TEXTURE_2D, multisample_type, - PIPE_BIND_RENDER_TARGET, FALSE, FALSE); - - if (This->actx->linear_framebuffer || - (pf != PIPE_FORMAT_B8G8R8X8_UNORM && - pf != PIPE_FORMAT_B8G8R8A8_UNORM) || - pParams->SwapEffect != D3DSWAPEFFECT_DISCARD || - multisample_type >= 2 || - (This->actx->ref && This->actx->ref == This->screen)) - has_present_buffers = TRUE; - - /* Note: the buffer depth has to match the window depth. - * In practice, ARGB buffers can be used with windows - * of depth 24. Windows of depth 32 are extremely rare. - * So even if the buffer is ARGB, say it is depth 24. - * It is common practice, for example that's how - * glamor implements depth 24. - * TODO: handle windows with other depths. Not possible in the short term. - * For example 16 bits.*/ - depth = 24; - - memset(&tmplt, 0, sizeof(tmplt)); - tmplt.target = PIPE_TEXTURE_2D; - tmplt.width0 = pParams->BackBufferWidth; - tmplt.height0 = pParams->BackBufferHeight; - tmplt.depth0 = 1; - tmplt.last_level = 0; - tmplt.array_size = 1; - tmplt.usage = PIPE_USAGE_DEFAULT; - tmplt.flags = 0; - - desc.Type = D3DRTYPE_SURFACE; - desc.Pool = D3DPOOL_DEFAULT; - desc.MultiSampleType = pParams->MultiSampleType; - desc.MultiSampleQuality = pParams->MultiSampleQuality; - desc.Width = pParams->BackBufferWidth; - desc.Height = pParams->BackBufferHeight; - - for (i = 0; i < oldBufferCount; i++) { - if (This->tasks[i]) - _mesa_threadpool_wait_for_task(This->pool, &(This->tasks[i])); - } - memset(This->tasks, 0, sizeof(This->tasks)); - - if (This->pool) { - _mesa_threadpool_destroy(This, This->pool); - This->pool = NULL; - } - This->enable_threadpool = This->actx->thread_submit && (pParams->SwapEffect != D3DSWAPEFFECT_COPY); - if (This->enable_threadpool) - This->pool = _mesa_threadpool_create(This); - if (!This->pool) - This->enable_threadpool = FALSE; - - for (i = 0; i < oldBufferCount; i++) { - D3DWindowBuffer_release(This, This->present_handles[i]); - This->present_handles[i] = NULL; - if (This->present_buffers[i]) - pipe_resource_reference(&(This->present_buffers[i]), NULL); - } - - if (newBufferCount != oldBufferCount) { - for (i = newBufferCount; i < oldBufferCount; - ++i) - NineUnknown_Detach(NineUnknown(This->buffers[i])); - - for (i = oldBufferCount; i < newBufferCount; ++i) { - This->buffers[i] = NULL; - This->present_handles[i] = NULL; - } - } - This->num_back_buffers = newBufferCount; - - for (i = 0; i < newBufferCount; ++i) { - tmplt.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; - tmplt.nr_samples = multisample_type; - tmplt.nr_storage_samples = multisample_type; - if (!has_present_buffers) - tmplt.bind |= NINE_BIND_PRESENTBUFFER_FLAGS; - tmplt.format = d3d9_to_pipe_format_checked(This->screen, - pParams->BackBufferFormat, - PIPE_TEXTURE_2D, - tmplt.nr_samples, - tmplt.bind, FALSE, FALSE); - if (tmplt.format == PIPE_FORMAT_NONE) - return D3DERR_INVALIDCALL; - resource = This->screen->resource_create(This->screen, &tmplt); - if (!resource) { - DBG("Failed to create pipe_resource.\n"); - return D3DERR_OUTOFVIDEOMEMORY; - } - if (pParams->Flags & D3DPRESENTFLAG_LOCKABLE_BACKBUFFER) - resource->flags |= NINE_RESOURCE_FLAG_LOCKABLE; - if (This->buffers[i]) { - NineSurface9_SetMultiSampleType(This->buffers[i], desc.MultiSampleType); - NineSurface9_SetResourceResize(This->buffers[i], resource); - if (has_present_buffers) - pipe_resource_reference(&resource, NULL); - } else { - desc.Format = pParams->BackBufferFormat; - desc.Usage = D3DUSAGE_RENDERTARGET; - hr = NineSurface9_new(pDevice, NineUnknown(This), resource, NULL, 0, - 0, 0, &desc, &This->buffers[i]); - if (has_present_buffers) - pipe_resource_reference(&resource, NULL); - if (FAILED(hr)) { - DBG("Failed to create RT surface.\n"); - return hr; - } - This->buffers[i]->base.base.forward = FALSE; - } - if (has_present_buffers) { - tmplt.format = PIPE_FORMAT_B8G8R8X8_UNORM; - tmplt.bind = NINE_BIND_PRESENTBUFFER_FLAGS; - tmplt.nr_samples = 0; - tmplt.nr_storage_samples = 0; - if (This->actx->linear_framebuffer) - tmplt.bind |= PIPE_BIND_LINEAR; - if (pParams->SwapEffect != D3DSWAPEFFECT_DISCARD) - tmplt.bind |= PIPE_BIND_RENDER_TARGET; - resource = This->screen->resource_create(This->screen, &tmplt); - pipe_resource_reference(&(This->present_buffers[i]), resource); - } - This->present_handles[i] = D3DWindowBuffer_create(This, resource, depth, false); - pipe_resource_reference(&resource, NULL); - if (!This->present_handles[i]) { - return D3DERR_DRIVERINTERNALERROR; - } - } - if (pParams->EnableAutoDepthStencil) { - tmplt.bind = d3d9_get_pipe_depth_format_bindings(pParams->AutoDepthStencilFormat); - tmplt.nr_samples = multisample_type; - tmplt.nr_storage_samples = multisample_type; - tmplt.format = d3d9_to_pipe_format_checked(This->screen, - pParams->AutoDepthStencilFormat, - PIPE_TEXTURE_2D, - tmplt.nr_samples, - tmplt.bind, - FALSE, FALSE); - - if (tmplt.format == PIPE_FORMAT_NONE) - return D3DERR_INVALIDCALL; - - if (This->zsbuf) { - resource = This->screen->resource_create(This->screen, &tmplt); - if (!resource) { - DBG("Failed to create pipe_resource for depth buffer.\n"); - return D3DERR_OUTOFVIDEOMEMORY; - } - - NineSurface9_SetMultiSampleType(This->zsbuf, desc.MultiSampleType); - NineSurface9_SetResourceResize(This->zsbuf, resource); - pipe_resource_reference(&resource, NULL); - } else { - hr = NineDevice9_CreateDepthStencilSurface(pDevice, - pParams->BackBufferWidth, - pParams->BackBufferHeight, - pParams->AutoDepthStencilFormat, - pParams->MultiSampleType, - pParams->MultiSampleQuality, - 0, - (IDirect3DSurface9 **)&This->zsbuf, - NULL); - if (FAILED(hr)) { - DBG("Failed to create ZS surface.\n"); - return hr; - } - NineUnknown_ConvertRefToBind(NineUnknown(This->zsbuf)); - } - } - - This->params = *pParams; - - return D3D_OK; -} - -/* Throttling: code adapted from the dri state tracker */ - -/** - * swap_fences_pop_front - pull a fence from the throttle queue - * - * If the throttle queue is filled to the desired number of fences, - * pull fences off the queue until the number is less than the desired - * number of fences, and return the last fence pulled. - */ -static struct pipe_fence_handle * -swap_fences_pop_front(struct NineSwapChain9 *This) -{ - struct pipe_screen *screen = This->screen; - struct pipe_fence_handle *fence = NULL; - - if (This->desired_fences == 0) - return NULL; - - if (This->cur_fences >= This->desired_fences) { - screen->fence_reference(screen, &fence, This->swap_fences[This->tail]); - screen->fence_reference(screen, &This->swap_fences[This->tail++], NULL); - This->tail &= DRI_SWAP_FENCES_MASK; - --This->cur_fences; - } - return fence; -} - - -/** - * swap_fences_see_front - same than swap_fences_pop_front without - * pulling - * - */ - -static struct pipe_fence_handle * -swap_fences_see_front(struct NineSwapChain9 *This) -{ - struct pipe_screen *screen = This->screen; - struct pipe_fence_handle *fence = NULL; - - if (This->desired_fences == 0) - return NULL; - - if (This->cur_fences >= This->desired_fences) { - screen->fence_reference(screen, &fence, This->swap_fences[This->tail]); - } - return fence; -} - - -/** - * swap_fences_push_back - push a fence onto the throttle queue at the back - * - * push a fence onto the throttle queue and pull fences of the queue - * so that the desired number of fences are on the queue. - */ -static void -swap_fences_push_back(struct NineSwapChain9 *This, - struct pipe_fence_handle *fence) -{ - struct pipe_screen *screen = This->screen; - - if (!fence || This->desired_fences == 0) - return; - - while(This->cur_fences == This->desired_fences) - swap_fences_pop_front(This); - - This->cur_fences++; - screen->fence_reference(screen, &This->swap_fences[This->head++], - fence); - This->head &= DRI_SWAP_FENCES_MASK; -} - - -/** - * swap_fences_unref - empty the throttle queue - * - * pulls fences of the throttle queue until it is empty. - */ -static void -swap_fences_unref(struct NineSwapChain9 *This) -{ - struct pipe_screen *screen = This->screen; - - while(This->cur_fences) { - screen->fence_reference(screen, &This->swap_fences[This->tail++], NULL); - This->tail &= DRI_SWAP_FENCES_MASK; - --This->cur_fences; - } -} - -void -NineSwapChain9_dtor( struct NineSwapChain9 *This ) -{ - unsigned i; - - DBG("This=%p\n", This); - - if (This->pool) - _mesa_threadpool_destroy(This, This->pool); - - for (i = 0; i < D3DPRESENT_BACK_BUFFERS_MAX_EX + 1; i++) { - if (This->pending_presentation[i]) - FREE(This->pending_presentation[i]); - } - - for (i = 0; i < D3DPRESENT_BACK_BUFFERS_MAX_EX + 1; i++) { - if (This->present_handles_pending_release[i]) - ID3DPresent_DestroyD3DWindowBuffer(This->present, This->present_handles_pending_release[i]); - } - - for (i = 0; i < This->num_back_buffers; i++) { - if (This->buffers[i]) - NineUnknown_Detach(NineUnknown(This->buffers[i])); - if (This->present_handles[i]) - ID3DPresent_DestroyD3DWindowBuffer(This->present, This->present_handles[i]); - if (This->present_buffers[i]) - pipe_resource_reference(&(This->present_buffers[i]), NULL); - } - if (This->zsbuf) - NineUnknown_Unbind(NineUnknown(This->zsbuf)); - - if (This->present) - ID3DPresent_Release(This->present); - - swap_fences_unref(This); - NineUnknown_dtor(&This->base); -} - -static void -create_present_buffer( struct NineSwapChain9 *This, - unsigned int width, unsigned int height, - struct pipe_resource **resource, - D3DWindowBuffer **present_handle) -{ - struct pipe_resource tmplt; - - memset(&tmplt, 0, sizeof(tmplt)); - tmplt.target = PIPE_TEXTURE_2D; - tmplt.width0 = width; - tmplt.height0 = height; - tmplt.depth0 = 1; - tmplt.last_level = 0; - tmplt.array_size = 1; - tmplt.usage = PIPE_USAGE_DEFAULT; - tmplt.flags = 0; - tmplt.format = PIPE_FORMAT_B8G8R8X8_UNORM; - tmplt.bind = NINE_BIND_BACKBUFFER_FLAGS | - NINE_BIND_PRESENTBUFFER_FLAGS; - tmplt.nr_samples = 0; - if (This->actx->linear_framebuffer) - tmplt.bind |= PIPE_BIND_LINEAR; - *resource = This->screen->resource_create(This->screen, &tmplt); - - *present_handle = D3DWindowBuffer_create(This, *resource, 24, true); - - if (!*present_handle) { - pipe_resource_reference(resource, NULL); - } -} - -static void -handle_draw_cursor_and_hud( struct NineSwapChain9 *This, struct pipe_resource *resource) -{ - struct NineDevice9 *device = This->base.device; - struct pipe_blit_info blit; - struct pipe_context *pipe; - - if (device->cursor.software && device->cursor.visible && device->cursor.w) { - memset(&blit, 0, sizeof(blit)); - blit.src.resource = device->cursor.image; - blit.src.level = 0; - blit.src.format = device->cursor.image->format; - blit.src.box.x = 0; - blit.src.box.y = 0; - blit.src.box.z = 0; - blit.src.box.depth = 1; - blit.src.box.width = device->cursor.w; - blit.src.box.height = device->cursor.h; - - blit.dst.resource = resource; - blit.dst.level = 0; - blit.dst.format = resource->format; - blit.dst.box.z = 0; - blit.dst.box.depth = 1; - - blit.mask = PIPE_MASK_RGBA; - blit.filter = PIPE_TEX_FILTER_NEAREST; - blit.scissor_enable = FALSE; - - /* NOTE: blit messes up when box.x + box.width < 0, fix driver - * NOTE2: device->cursor.pos contains coordinates relative to the screen. - * This happens to be also the position of the cursor when we are fullscreen. - * We don't use sw cursor for Windowed mode */ - blit.dst.box.x = MAX2(device->cursor.pos.x, 0) - device->cursor.hotspot.x; - blit.dst.box.y = MAX2(device->cursor.pos.y, 0) - device->cursor.hotspot.y; - blit.dst.box.width = blit.src.box.width; - blit.dst.box.height = blit.src.box.height; - - DBG("Blitting cursor(%ux%u) to (%i,%i).\n", - blit.src.box.width, blit.src.box.height, - blit.dst.box.x, blit.dst.box.y); - - blit.alpha_blend = TRUE; - pipe = NineDevice9_GetPipe(This->base.device); - pipe->blit(pipe, &blit); - } - - if (device->hud && resource) { - /* Implicit use of context pipe */ - (void)NineDevice9_GetPipe(This->base.device); - hud_run(device->hud, NULL, resource); /* XXX: no offset */ - /* HUD doesn't clobber stipple */ - nine_state_restore_non_cso(device); - } -} - -struct end_present_struct { - struct pipe_screen *screen; - struct pipe_fence_handle *fence_to_wait; - ID3DPresent *present; - D3DWindowBuffer *present_handle; - BOOL *pending_presentation; - HWND hDestWindowOverride; -}; - -static void work_present(void *data) -{ - struct end_present_struct *work = data; - if (work->fence_to_wait) { - (void) work->screen->fence_finish(work->screen, NULL, work->fence_to_wait, PIPE_TIMEOUT_INFINITE); - work->screen->fence_reference(work->screen, &(work->fence_to_wait), NULL); - } - ID3DPresent_PresentBuffer(work->present, work->present_handle, work->hDestWindowOverride, NULL, NULL, NULL, 0); - p_atomic_set(work->pending_presentation, FALSE); - free(work); -} - -static void pend_present(struct NineSwapChain9 *This, - struct pipe_fence_handle *fence, - HWND hDestWindowOverride) -{ - struct end_present_struct *work = calloc(1, sizeof(struct end_present_struct)); - - work->screen = This->screen; - This->screen->fence_reference(This->screen, &work->fence_to_wait, fence); - work->present = This->present; - work->present_handle = This->present_handles[0]; - work->hDestWindowOverride = hDestWindowOverride; - work->pending_presentation = This->pending_presentation[0]; - p_atomic_set(work->pending_presentation, TRUE); - This->tasks[0] = _mesa_threadpool_queue_task(This->pool, work_present, work); - - return; -} - -static inline HRESULT -present( struct NineSwapChain9 *This, - const RECT *pSourceRect, - const RECT *pDestRect, - HWND hDestWindowOverride, - const RGNDATA *pDirtyRegion, - DWORD dwFlags ) -{ - struct pipe_context *pipe; - struct pipe_resource *resource; - struct pipe_fence_handle *fence; - HRESULT hr; - struct pipe_blit_info blit; - int target_width, target_height, target_depth, i; - - DBG("present: This=%p pSourceRect=%p pDestRect=%p " - "pDirtyRegion=%p hDestWindowOverride=%p" - "dwFlags=%d resource=%p\n", - This, pSourceRect, pDestRect, pDirtyRegion, - hDestWindowOverride, (int)dwFlags, This->buffers[0]->base.resource); - - if (pSourceRect) - DBG("pSourceRect = (%u..%u)x(%u..%u)\n", - pSourceRect->left, pSourceRect->right, - pSourceRect->top, pSourceRect->bottom); - if (pDestRect) - DBG("pDestRect = (%u..%u)x(%u..%u)\n", - pDestRect->left, pDestRect->right, - pDestRect->top, pDestRect->bottom); - - /* TODO: in the case the source and destination rect have different size: - * We need to allocate a new buffer, and do a blit to it to resize. - * We can't use the present_buffer for that since when we created it, - * we couldn't guess which size would have been needed. - * If pDestRect or pSourceRect is null, we have to check the sizes - * from the source size, and the destination window size. - * In this case, either resize rngdata, or pass NULL instead - */ - /* Note: This->buffers[0]->level should always be 0 */ - - if (This->rendering_done) - goto bypass_rendering; - - resource = This->buffers[0]->base.resource; - - if (This->params.SwapEffect == D3DSWAPEFFECT_DISCARD) - handle_draw_cursor_and_hud(This, resource); - - hr = ID3DPresent_GetWindowInfo(This->present, hDestWindowOverride, &target_width, &target_height, &target_depth); - (void)target_depth; - - /* Can happen with old Wine (presentation can still succeed), - * or at window destruction. - * Also disable for very old wine as D3DWindowBuffer_release - * cannot do the DestroyD3DWindowBuffer workaround. */ - if (FAILED(hr) || target_width == 0 || target_height == 0 || - This->base.device->minor_version_num <= 2) { - target_width = resource->width0; - target_height = resource->height0; - } - - /* Switch to using presentation buffers on window resize. - * Note: Most apps should resize the d3d back buffers when - * a window resize is detected, which will result in a call to - * NineSwapChain9_Resize. Thus everything will get released, - * and it will switch back to not using separate presentation - * buffers. */ - if (!This->present_buffers[0] && - (target_width != resource->width0 || target_height != resource->height0)) { - BOOL failure = false; - struct pipe_resource *new_resource[This->num_back_buffers]; - D3DWindowBuffer *new_handles[This->num_back_buffers]; - for (i = 0; i < This->num_back_buffers; i++) { - /* Note: if (!new_handles[i]), new_resource[i] - * gets released and contains NULL */ - create_present_buffer(This, target_width, target_height, &new_resource[i], &new_handles[i]); - if (!new_handles[i]) - failure = true; - } - if (failure) { - for (i = 0; i < This->num_back_buffers; i++) { - if (new_resource[i]) - pipe_resource_reference(&new_resource[i], NULL); - if (new_handles[i]) - D3DWindowBuffer_release(This, new_handles[i]); - } - } else { - for (i = 0; i < This->num_back_buffers; i++) { - D3DWindowBuffer_release(This, This->present_handles[i]); - This->present_handles[i] = new_handles[i]; - pipe_resource_reference(&This->present_buffers[i], new_resource[i]); - pipe_resource_reference(&new_resource[i], NULL); - } - } - } - - pipe = NineDevice9_GetPipe(This->base.device); - - if (This->present_buffers[0]) { - memset(&blit, 0, sizeof(blit)); - blit.src.resource = resource; - blit.src.level = 0; - blit.src.format = resource->format; - blit.src.box.z = 0; - blit.src.box.depth = 1; - blit.src.box.x = 0; - blit.src.box.y = 0; - blit.src.box.width = resource->width0; - blit.src.box.height = resource->height0; - - /* Reallocate a new presentation buffer if the target window - * size has changed */ - if (target_width != This->present_buffers[0]->width0 || - target_height != This->present_buffers[0]->height0) { - struct pipe_resource *new_resource; - D3DWindowBuffer *new_handle; - - create_present_buffer(This, target_width, target_height, &new_resource, &new_handle); - /* Switch to the new buffer */ - if (new_handle) { - D3DWindowBuffer_release(This, This->present_handles[0]); - This->present_handles[0] = new_handle; - pipe_resource_reference(&This->present_buffers[0], new_resource); - pipe_resource_reference(&new_resource, NULL); - } - } - - resource = This->present_buffers[0]; - - blit.dst.resource = resource; - blit.dst.level = 0; - blit.dst.format = resource->format; - blit.dst.box.z = 0; - blit.dst.box.depth = 1; - blit.dst.box.x = 0; - blit.dst.box.y = 0; - blit.dst.box.width = resource->width0; - blit.dst.box.height = resource->height0; - - blit.mask = PIPE_MASK_RGBA; - blit.filter = (blit.dst.box.width == blit.src.box.width && - blit.dst.box.height == blit.src.box.height) ? - PIPE_TEX_FILTER_NEAREST : PIPE_TEX_FILTER_LINEAR; - blit.scissor_enable = FALSE; - blit.alpha_blend = FALSE; - - pipe->blit(pipe, &blit); - } - - /* The resource we present has to resolve fast clears - * if needed (and other things) */ - pipe->flush_resource(pipe, resource); - - if (This->params.SwapEffect != D3DSWAPEFFECT_DISCARD) - handle_draw_cursor_and_hud(This, resource); - - fence = NULL; - pipe->flush(pipe, &fence, PIPE_FLUSH_END_OF_FRAME); - - /* Present now for thread_submit, because we have the fence. - * It's possible we return WASSTILLDRAWING and still Present, - * but it should be fine. */ - if (This->enable_threadpool) - pend_present(This, fence, hDestWindowOverride); - if (fence) { - swap_fences_push_back(This, fence); - This->screen->fence_reference(This->screen, &fence, NULL); - } - - This->rendering_done = TRUE; -bypass_rendering: - - if (dwFlags & D3DPRESENT_DONOTWAIT) { - UNTESTED(2); - BOOL still_draw = FALSE; - fence = swap_fences_see_front(This); - if (fence) { - still_draw = !This->screen->fence_finish(This->screen, NULL, fence, 0); - This->screen->fence_reference(This->screen, &fence, NULL); - } - if (still_draw) - return D3DERR_WASSTILLDRAWING; - } - - /* Throttle rendering if needed */ - fence = swap_fences_pop_front(This); - if (fence) { - (void) This->screen->fence_finish(This->screen, NULL, fence, PIPE_TIMEOUT_INFINITE); - This->screen->fence_reference(This->screen, &fence, NULL); - } - - This->rendering_done = FALSE; - - if (!This->enable_threadpool) { - This->tasks[0]=NULL; - - hr = ID3DPresent_PresentBuffer(This->present, This->present_handles[0], hDestWindowOverride, pSourceRect, pDestRect, pDirtyRegion, dwFlags); - - if (FAILED(hr)) { UNTESTED(3);return hr; } - } - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineSwapChain9_Present( struct NineSwapChain9 *This, - const RECT *pSourceRect, - const RECT *pDestRect, - HWND hDestWindowOverride, - const RGNDATA *pDirtyRegion, - DWORD dwFlags ) -{ - struct pipe_resource *res = NULL; - D3DWindowBuffer *handle_temp; - struct threadpool_task *task_temp; - BOOL *pending_presentation_temp; - int i; - HRESULT hr; - - DBG("This=%p pSourceRect=%p pDestRect=%p hDestWindowOverride=%p " - "pDirtyRegion=%p dwFlags=%d\n", - This, pSourceRect, pDestRect, hDestWindowOverride, - pDirtyRegion,dwFlags); - - if (This->base.device->ex) { - if (NineSwapChain9_GetOccluded(This)) { - DBG("Present is occluded. Returning S_PRESENT_OCCLUDED.\n"); - return S_PRESENT_OCCLUDED; - } - } else { - if (NineSwapChain9_GetOccluded(This) || - NineSwapChain9_ResolutionMismatch(This)) { - This->base.device->device_needs_reset = TRUE; - } - if (This->base.device->device_needs_reset) { - DBG("Device is lost. Returning D3DERR_DEVICELOST.\n"); - return D3DERR_DEVICELOST; - } - } - - nine_csmt_process(This->base.device); - - hr = present(This, pSourceRect, pDestRect, - hDestWindowOverride, pDirtyRegion, dwFlags); - if (hr == D3DERR_WASSTILLDRAWING) - return hr; - - if (This->base.device->minor_version_num > 2 && - This->actx->discard_delayed_release && - This->params.SwapEffect == D3DSWAPEFFECT_DISCARD && - This->params.PresentationInterval == D3DPRESENT_INTERVAL_IMMEDIATE) { - int next_buffer = -1; - - while (next_buffer == -1) { - /* Find a free backbuffer */ - for (i = 1; i < This->num_back_buffers; i++) { - if (!p_atomic_read(This->pending_presentation[i]) && - ID3DPresent_IsBufferReleased(This->present, This->present_handles[i])) { - DBG("Found buffer released: %d\n", i); - next_buffer = i; - break; - } - } - if (next_buffer == -1) { - DBG("Found no buffer released. Waiting for event\n"); - ID3DPresent_WaitBufferReleaseEvent(This->present); - } - } - - /* Free the task (we already checked it is finished) */ - if (This->tasks[next_buffer]) - _mesa_threadpool_wait_for_task(This->pool, &(This->tasks[next_buffer])); - assert(!*This->pending_presentation[next_buffer] && !This->tasks[next_buffer]); - This->tasks[next_buffer] = This->tasks[0]; - This->tasks[0] = NULL; - pending_presentation_temp = This->pending_presentation[next_buffer]; - This->pending_presentation[next_buffer] = This->pending_presentation[0]; - This->pending_presentation[0] = pending_presentation_temp; - - /* Switch with the released buffer */ - pipe_resource_reference(&res, This->buffers[0]->base.resource); - NineSurface9_SetResourceResize( - This->buffers[0], This->buffers[next_buffer]->base.resource); - NineSurface9_SetResourceResize( - This->buffers[next_buffer], res); - pipe_resource_reference(&res, NULL); - - if (This->present_buffers[0]) { - pipe_resource_reference(&res, This->present_buffers[0]); - pipe_resource_reference(&This->present_buffers[0], This->present_buffers[next_buffer]); - pipe_resource_reference(&This->present_buffers[next_buffer], res); - pipe_resource_reference(&res, NULL); - } - - handle_temp = This->present_handles[0]; - This->present_handles[0] = This->present_handles[next_buffer]; - This->present_handles[next_buffer] = handle_temp; - } else { - switch (This->params.SwapEffect) { - case D3DSWAPEFFECT_OVERLAY: /* Not implemented, fallback to FLIP */ - case D3DSWAPEFFECT_FLIPEX: /* Allows optimizations over FLIP for windowed mode. */ - case D3DSWAPEFFECT_DISCARD: /* Allows optimizations over FLIP */ - case D3DSWAPEFFECT_FLIP: - /* rotate the queue */ - pipe_resource_reference(&res, This->buffers[0]->base.resource); - for (i = 1; i < This->num_back_buffers; i++) { - NineSurface9_SetResourceResize(This->buffers[i - 1], - This->buffers[i]->base.resource); - } - NineSurface9_SetResourceResize( - This->buffers[This->num_back_buffers - 1], res); - pipe_resource_reference(&res, NULL); - - if (This->present_buffers[0]) { - pipe_resource_reference(&res, This->present_buffers[0]); - for (i = 1; i < This->num_back_buffers; i++) - pipe_resource_reference(&(This->present_buffers[i-1]), This->present_buffers[i]); - pipe_resource_reference(&(This->present_buffers[This->num_back_buffers - 1]), res); - pipe_resource_reference(&res, NULL); - } - - handle_temp = This->present_handles[0]; - for (i = 1; i < This->num_back_buffers; i++) { - This->present_handles[i-1] = This->present_handles[i]; - } - This->present_handles[This->num_back_buffers - 1] = handle_temp; - task_temp = This->tasks[0]; - for (i = 1; i < This->num_back_buffers; i++) { - This->tasks[i-1] = This->tasks[i]; - } - This->tasks[This->num_back_buffers - 1] = task_temp; - pending_presentation_temp = This->pending_presentation[0]; - for (i = 1; i < This->num_back_buffers; i++) { - This->pending_presentation[i-1] = This->pending_presentation[i]; - } - This->pending_presentation[This->num_back_buffers - 1] = pending_presentation_temp; - break; - - case D3DSWAPEFFECT_COPY: - /* do nothing */ - break; - } - - if (This->tasks[0]) - _mesa_threadpool_wait_for_task(This->pool, &(This->tasks[0])); - assert(!*This->pending_presentation[0]); - - ID3DPresent_WaitBufferReleased(This->present, This->present_handles[0]); - } - - This->base.device->context.changed.group |= NINE_STATE_FB; - - return hr; -} - -HRESULT NINE_WINAPI -NineSwapChain9_GetFrontBufferData( struct NineSwapChain9 *This, - IDirect3DSurface9 *pDestSurface ) -{ - struct NineSurface9 *dest_surface = NineSurface9(pDestSurface); - struct NineDevice9 *pDevice = This->base.device; - unsigned int width, height; - struct pipe_resource *temp_resource; - struct NineSurface9 *temp_surface; - D3DWindowBuffer *temp_handle; - D3DSURFACE_DESC desc; - HRESULT hr; - - DBG("GetFrontBufferData: This=%p pDestSurface=%p\n", - This, pDestSurface); - - user_assert(dest_surface->base.pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL); - - width = dest_surface->desc.Width; - height = dest_surface->desc.Height; - - /* Note: front window size and destination size are supposed - * to match. However it's not very clear what should get taken in Windowed - * mode. It may need a fix */ - create_present_buffer(This, width, height, &temp_resource, &temp_handle); - - if (!temp_resource || !temp_handle) { - return D3DERR_INVALIDCALL; - } - - desc.Type = D3DRTYPE_SURFACE; - desc.Pool = D3DPOOL_DEFAULT; - desc.MultiSampleType = D3DMULTISAMPLE_NONE; - desc.MultiSampleQuality = 0; - desc.Width = width; - desc.Height = height; - /* NineSurface9_CopyDefaultToMem needs same format. */ - desc.Format = dest_surface->desc.Format; - desc.Usage = D3DUSAGE_RENDERTARGET; - hr = NineSurface9_new(pDevice, NineUnknown(This), temp_resource, NULL, 0, - 0, 0, &desc, &temp_surface); - pipe_resource_reference(&temp_resource, NULL); - if (FAILED(hr)) { - DBG("Failed to create temp FrontBuffer surface.\n"); - return hr; - } - - ID3DPresent_FrontBufferCopy(This->present, temp_handle); - - NineSurface9_CopyDefaultToMem(dest_surface, temp_surface); - - ID3DPresent_DestroyD3DWindowBuffer(This->present, temp_handle); - NineUnknown_Destroy(NineUnknown(temp_surface)); - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineSwapChain9_GetBackBuffer( struct NineSwapChain9 *This, - UINT iBackBuffer, - D3DBACKBUFFER_TYPE Type, - IDirect3DSurface9 **ppBackBuffer ) -{ - DBG("GetBackBuffer: This=%p iBackBuffer=%d Type=%d ppBackBuffer=%p\n", - This, iBackBuffer, Type, ppBackBuffer); - (void)user_error(Type == D3DBACKBUFFER_TYPE_MONO); - /* don't touch ppBackBuffer on error */ - user_assert(ppBackBuffer != NULL, D3DERR_INVALIDCALL); - user_assert(iBackBuffer < This->params.BackBufferCount, D3DERR_INVALIDCALL); - - NineUnknown_AddRef(NineUnknown(This->buffers[iBackBuffer])); - *ppBackBuffer = (IDirect3DSurface9 *)This->buffers[iBackBuffer]; - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineSwapChain9_GetRasterStatus( struct NineSwapChain9 *This, - D3DRASTER_STATUS *pRasterStatus ) -{ - DBG("GetRasterStatus: This=%p pRasterStatus=%p\n", - This, pRasterStatus); - user_assert(pRasterStatus != NULL, E_POINTER); - return ID3DPresent_GetRasterStatus(This->present, pRasterStatus); -} - -HRESULT NINE_WINAPI -NineSwapChain9_GetDisplayMode( struct NineSwapChain9 *This, - D3DDISPLAYMODE *pMode ) -{ - D3DDISPLAYMODEEX mode; - D3DDISPLAYROTATION rot; - HRESULT hr; - - DBG("GetDisplayMode: This=%p pMode=%p\n", - This, pMode); - user_assert(pMode != NULL, E_POINTER); - - hr = ID3DPresent_GetDisplayMode(This->present, &mode, &rot); - if (SUCCEEDED(hr)) { - pMode->Width = mode.Width; - pMode->Height = mode.Height; - pMode->RefreshRate = mode.RefreshRate; - pMode->Format = mode.Format; - } - return hr; -} - -HRESULT NINE_WINAPI -NineSwapChain9_GetPresentParameters( struct NineSwapChain9 *This, - D3DPRESENT_PARAMETERS *pPresentationParameters ) -{ - DBG("GetPresentParameters: This=%p pPresentationParameters=%p\n", - This, pPresentationParameters); - user_assert(pPresentationParameters != NULL, E_POINTER); - *pPresentationParameters = This->params; - return D3D_OK; -} - -IDirect3DSwapChain9Vtbl NineSwapChain9_vtable = { - (void *)NineUnknown_QueryInterface, - (void *)NineUnknown_AddRef, - (void *)NineUnknown_Release, - (void *)NineSwapChain9_Present, - (void *)NineSwapChain9_GetFrontBufferData, - (void *)NineSwapChain9_GetBackBuffer, - (void *)NineSwapChain9_GetRasterStatus, - (void *)NineSwapChain9_GetDisplayMode, - (void *)NineUnknown_GetDevice, /* actually part of SwapChain9 iface */ - (void *)NineSwapChain9_GetPresentParameters -}; - -static const GUID *NineSwapChain9_IIDs[] = { - &IID_IDirect3DSwapChain9, - &IID_IUnknown, - NULL -}; - -HRESULT -NineSwapChain9_new( struct NineDevice9 *pDevice, - BOOL implicit, - ID3DPresent *pPresent, - D3DPRESENT_PARAMETERS *pPresentationParameters, - struct d3dadapter9_context *pCTX, - HWND hFocusWindow, - struct NineSwapChain9 **ppOut ) -{ - NINE_DEVICE_CHILD_NEW(SwapChain9, ppOut, pDevice, /* args */ - implicit, pPresent, pPresentationParameters, - pCTX, hFocusWindow, NULL); -} - -BOOL -NineSwapChain9_GetOccluded( struct NineSwapChain9 *This ) -{ - if (This->base.device->minor_version_num > 0) { - return ID3DPresent_GetWindowOccluded(This->present); - } - - return FALSE; -} - -BOOL -NineSwapChain9_ResolutionMismatch( struct NineSwapChain9 *This ) -{ - if (This->base.device->minor_version_num > 1) { - return ID3DPresent_ResolutionMismatch(This->present); - } - - return FALSE; -} - -HANDLE -NineSwapChain9_CreateThread( struct NineSwapChain9 *This, - void *pFuncAddress, - void *pParam ) -{ - if (This->base.device->minor_version_num > 1) { - return ID3DPresent_CreateThread(This->present, pFuncAddress, pParam); - } - - return NULL; -} - -void -NineSwapChain9_WaitForThread( struct NineSwapChain9 *This, - HANDLE thread ) -{ - if (This->base.device->minor_version_num > 1) { - (void) ID3DPresent_WaitForThread(This->present, thread); - } -} - -static int -NineSwapChain9_GetBackBufferCountForParams( struct NineSwapChain9 *This, - D3DPRESENT_PARAMETERS *pParams ) -{ - int count = pParams->BackBufferCount; - - /* When we have flip behaviour, d3d9 expects we get back the screen buffer when we flip. - * Here we don't get back the initial content of the screen. To emulate the behaviour - * we allocate an additional buffer */ - if (pParams->SwapEffect != D3DSWAPEFFECT_COPY) - count++; - /* With DISCARD, as there is no guarantee about the buffer contents, we can use - * an arbitrary number of buffers */ - if (pParams->SwapEffect == D3DSWAPEFFECT_DISCARD) { - /* thread_submit's can have maximum count or This->actx->throttling_value + 1 - * frames in flight being rendered and not shown. - * Do not let count decrease that number */ - if (This->actx->thread_submit && count < This->desired_fences) - count = This->desired_fences; - /* When we enable AllowDISCARDDelayedRelease, we must ensure - * to have at least 4 buffers to meet INTERVAL_IMMEDIATE, - * since the display server/compositor can hold 3 buffers - * without releasing them: - * . Buffer on screen. - * . Buffer scheduled kernel side to be next on screen. - * . Last buffer sent. */ - if (This->base.device->minor_version_num > 2 && - This->actx->discard_delayed_release && - pParams->PresentationInterval == D3DPRESENT_INTERVAL_IMMEDIATE) { - if (This->actx->thread_submit && count < 4) - count = 4; - /* When thread_submit is not used, 5 buffers are actually needed, - * because in case a pageflip is missed because rendering wasn't finished, - * the Xserver will hold 4 buffers. */ - else if (!This->actx->thread_submit && count < 5) - count = 5; - } - } - - return count; -} diff --git a/src/gallium/state_trackers/nine/swapchain9.h b/src/gallium/state_trackers/nine/swapchain9.h deleted file mode 100644 index a6146445bdd..00000000000 --- a/src/gallium/state_trackers/nine/swapchain9.h +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef _NINE_SWAPCHAIN9_H_ -#define _NINE_SWAPCHAIN9_H_ - -#include "iunknown.h" -#include "adapter9.h" - -#include "d3dadapter/d3dadapter9.h" - -#include "threadpool.h" - -struct NineDevice9; -struct NineSurface9; -struct nine_winsys_swapchain; -struct blit_state; - -#define DRI_SWAP_FENCES_MAX 4 -#define DRI_SWAP_FENCES_MASK 3 - -struct NineSwapChain9 -{ - struct NineUnknown base; - - /* G3D stuff */ - struct pipe_screen *screen; - - /* presentation backend */ - ID3DPresent *present; - D3DPRESENT_PARAMETERS params; - D3DDISPLAYMODEEX *mode; - struct d3dadapter9_context *actx; - BOOL implicit; - unsigned num_back_buffers; - - /* buffer handles */ - struct NineSurface9 *buffers[D3DPRESENT_BACK_BUFFERS_MAX_EX + 1]; /* 0 to BackBufferCount-1 : the back buffers. BackBufferCount : additional buffer */ - struct pipe_resource *present_buffers[D3DPRESENT_BACK_BUFFERS_MAX_EX + 1]; - D3DWindowBuffer *present_handles[D3DPRESENT_BACK_BUFFERS_MAX_EX + 1]; - D3DWindowBuffer *present_handles_pending_release[D3DPRESENT_BACK_BUFFERS_MAX_EX + 1]; - - struct pipe_fence_handle *swap_fences[DRI_SWAP_FENCES_MAX]; - unsigned int cur_fences; - unsigned int head; - unsigned int tail; - unsigned int desired_fences; - - BOOL rendering_done; - - struct NineSurface9 *zsbuf; - - D3DGAMMARAMP gamma; - - struct threadpool *pool; - struct threadpool_task *tasks[D3DPRESENT_BACK_BUFFERS_MAX_EX + 1]; - BOOL *pending_presentation[D3DPRESENT_BACK_BUFFERS_MAX_EX + 1]; - BOOL enable_threadpool; -}; - -static inline struct NineSwapChain9 * -NineSwapChain9( void *data ) -{ - return (struct NineSwapChain9 *)data; -} - -HRESULT -NineSwapChain9_new( struct NineDevice9 *pDevice, - BOOL implicit, - ID3DPresent *pPresent, - D3DPRESENT_PARAMETERS *pPresentationParameters, - struct d3dadapter9_context *pCTX, - HWND hFocusWindow, - struct NineSwapChain9 **ppOut ); - -HRESULT -NineSwapChain9_ctor( struct NineSwapChain9 *This, - struct NineUnknownParams *pParams, - BOOL implicit, - ID3DPresent *pPresent, - D3DPRESENT_PARAMETERS *pPresentationParameters, - struct d3dadapter9_context *pCTX, - HWND hFocusWindow, - D3DDISPLAYMODEEX *mode ); - -void -NineSwapChain9_dtor( struct NineSwapChain9 *This ); - -HRESULT -NineSwapChain9_Resize( struct NineSwapChain9 *This, - D3DPRESENT_PARAMETERS *pParams, - D3DDISPLAYMODEEX *mode ); - -HRESULT NINE_WINAPI -NineSwapChain9_Present( struct NineSwapChain9 *This, - const RECT *pSourceRect, - const RECT *pDestRect, - HWND hDestWindowOverride, - const RGNDATA *pDirtyRegion, - DWORD dwFlags ); - -HRESULT NINE_WINAPI -NineSwapChain9_GetFrontBufferData( struct NineSwapChain9 *This, - IDirect3DSurface9 *pDestSurface ); - -HRESULT NINE_WINAPI -NineSwapChain9_GetBackBuffer( struct NineSwapChain9 *This, - UINT iBackBuffer, - D3DBACKBUFFER_TYPE Type, - IDirect3DSurface9 **ppBackBuffer ); - -HRESULT NINE_WINAPI -NineSwapChain9_GetRasterStatus( struct NineSwapChain9 *This, - D3DRASTER_STATUS *pRasterStatus ); - -HRESULT NINE_WINAPI -NineSwapChain9_GetDisplayMode( struct NineSwapChain9 *This, - D3DDISPLAYMODE *pMode ); - -HRESULT NINE_WINAPI -NineSwapChain9_GetPresentParameters( struct NineSwapChain9 *This, - D3DPRESENT_PARAMETERS *pPresentationParameters ); - -BOOL -NineSwapChain9_GetOccluded( struct NineSwapChain9 *This ); - -BOOL -NineSwapChain9_ResolutionMismatch( struct NineSwapChain9 *This ); - -HANDLE -NineSwapChain9_CreateThread( struct NineSwapChain9 *This, - void *pFuncAddress, - void *pParam ); - -void -NineSwapChain9_WaitForThread( struct NineSwapChain9 *This, - HANDLE thread ); - -#endif /* _NINE_SWAPCHAIN9_H_ */ diff --git a/src/gallium/state_trackers/nine/swapchain9ex.c b/src/gallium/state_trackers/nine/swapchain9ex.c deleted file mode 100644 index 309402cbb7b..00000000000 --- a/src/gallium/state_trackers/nine/swapchain9ex.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "swapchain9ex.h" -#include "device9.h" - -#include "nine_helpers.h" - -#define DBG_CHANNEL DBG_SWAPCHAIN - -static HRESULT -NineSwapChain9Ex_ctor( struct NineSwapChain9Ex *This, - struct NineUnknownParams *pParams, - BOOL implicit, - ID3DPresent *pPresent, - D3DPRESENT_PARAMETERS *pPresentationParameters, - struct d3dadapter9_context *pCTX, - HWND hFocusWindow, - D3DDISPLAYMODEEX *mode ) -{ - DBG("This=%p pParams=%p implicit=%d pPresent=%p pPresentationParameters=%p " - "pCTX=%p hFocusWindow=%p mode=%p", - This, pParams, (int) implicit, pPresent, pPresentationParameters, pCTX, hFocusWindow, mode); - - return NineSwapChain9_ctor(&This->base, pParams, implicit, pPresent, - pPresentationParameters, pCTX, hFocusWindow, mode); -} - -static void -NineSwapChain9Ex_dtor( struct NineSwapChain9Ex *This ) -{ - NineSwapChain9_dtor(&This->base); -} - -HRESULT NINE_WINAPI -NineSwapChain9Ex_GetLastPresentCount( struct NineSwapChain9Ex *This, - UINT *pLastPresentCount ) -{ - STUB(D3DERR_INVALIDCALL); -} - -HRESULT NINE_WINAPI -NineSwapChain9Ex_GetPresentStats( struct NineSwapChain9Ex *This, - D3DPRESENTSTATS *pPresentationStatistics ) -{ - STUB(D3DERR_INVALIDCALL); -} - -HRESULT NINE_WINAPI -NineSwapChain9Ex_GetDisplayModeEx( struct NineSwapChain9Ex *This, - D3DDISPLAYMODEEX *pMode, - D3DDISPLAYROTATION *pRotation ) -{ - D3DDISPLAYROTATION rot; - - user_assert(pMode != NULL, E_POINTER); - if (!pRotation) { pRotation = &rot; } - - return ID3DPresent_GetDisplayMode(This->base.present, pMode, pRotation); -} - -IDirect3DSwapChain9ExVtbl NineSwapChain9Ex_vtable = { - (void *)NineUnknown_QueryInterface, - (void *)NineUnknown_AddRef, - (void *)NineUnknown_Release, - (void *)NineSwapChain9_Present, - (void *)NineSwapChain9_GetFrontBufferData, - (void *)NineSwapChain9_GetBackBuffer, - (void *)NineSwapChain9_GetRasterStatus, - (void *)NineSwapChain9_GetDisplayMode, - (void *)NineUnknown_GetDevice, /* actually part of NineSwapChain9 iface */ - (void *)NineSwapChain9_GetPresentParameters, - (void *)NineSwapChain9Ex_GetLastPresentCount, - (void *)NineSwapChain9Ex_GetPresentStats, - (void *)NineSwapChain9Ex_GetDisplayModeEx -}; - -static const GUID *NineSwapChain9Ex_IIDs[] = { - &IID_IDirect3DSwapChain9Ex, - &IID_IDirect3DSwapChain9, - &IID_IUnknown, - NULL -}; - -HRESULT -NineSwapChain9Ex_new( struct NineDevice9 *pDevice, - BOOL implicit, - ID3DPresent *pPresent, - D3DPRESENT_PARAMETERS *pPresentationParameters, - struct d3dadapter9_context *pCTX, - HWND hFocusWindow, - D3DDISPLAYMODEEX *mode, - struct NineSwapChain9Ex **ppOut ) -{ - NINE_DEVICE_CHILD_NEW(SwapChain9Ex, ppOut, pDevice, /* args */ - implicit, pPresent, pPresentationParameters, - pCTX, hFocusWindow, mode); -} diff --git a/src/gallium/state_trackers/nine/swapchain9ex.h b/src/gallium/state_trackers/nine/swapchain9ex.h deleted file mode 100644 index a15d9d2c01e..00000000000 --- a/src/gallium/state_trackers/nine/swapchain9ex.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef _NINE_SWAPCHAIN9EX_H_ -#define _NINE_SWAPCHAIN9EX_H_ - -#include "swapchain9.h" - -struct NineSwapChain9Ex -{ - struct NineSwapChain9 base; -}; -static inline struct NineSwapChain9Ex * -NineSwapChain9Ex( void *data ) -{ - return (struct NineSwapChain9Ex *)data; -} - -HRESULT -NineSwapChain9Ex_new( struct NineDevice9 *pDevice, - BOOL implicit, - ID3DPresent *pPresent, - D3DPRESENT_PARAMETERS *pPresentationParameters, - struct d3dadapter9_context *pCTX, - HWND hFocusWindow, - D3DDISPLAYMODEEX *mode, - struct NineSwapChain9Ex **ppOut ); - -HRESULT NINE_WINAPI -NineSwapChain9Ex_GetLastPresentCount( struct NineSwapChain9Ex *This, - UINT *pLastPresentCount ); - -HRESULT NINE_WINAPI -NineSwapChain9Ex_GetPresentStats( struct NineSwapChain9Ex *This, - D3DPRESENTSTATS *pPresentationStatistics ); - -HRESULT NINE_WINAPI -NineSwapChain9Ex_GetDisplayModeEx( struct NineSwapChain9Ex *This, - D3DDISPLAYMODEEX *pMode, - D3DDISPLAYROTATION *pRotation ); - -#endif /* _NINE_SWAPCHAIN9EX_H_ */ diff --git a/src/gallium/state_trackers/nine/texture9.c b/src/gallium/state_trackers/nine/texture9.c deleted file mode 100644 index fca5e603230..00000000000 --- a/src/gallium/state_trackers/nine/texture9.c +++ /dev/null @@ -1,393 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "c99_alloca.h" - -#include "device9.h" -#include "surface9.h" -#include "texture9.h" -#include "nine_helpers.h" -#include "nine_pipe.h" -#include "nine_dump.h" - -#include "pipe/p_state.h" -#include "pipe/p_context.h" -#include "pipe/p_screen.h" -#include "util/u_inlines.h" -#include "util/u_resource.h" - -#define DBG_CHANNEL DBG_TEXTURE - -static HRESULT -NineTexture9_ctor( struct NineTexture9 *This, - struct NineUnknownParams *pParams, - UINT Width, UINT Height, UINT Levels, - DWORD Usage, - D3DFORMAT Format, - D3DPOOL Pool, - HANDLE *pSharedHandle ) -{ - struct pipe_screen *screen = pParams->device->screen; - struct pipe_resource *info = &This->base.base.info; - enum pipe_format pf; - unsigned *level_offsets; - unsigned l; - D3DSURFACE_DESC sfdesc; - HRESULT hr; - void *user_buffer = NULL, *user_buffer_for_level; - - DBG("(%p) Width=%u Height=%u Levels=%u Usage=%s Format=%s Pool=%s " - "pSharedHandle=%p\n", This, Width, Height, Levels, - nine_D3DUSAGE_to_str(Usage), - d3dformat_to_string(Format), nine_D3DPOOL_to_str(Pool), pSharedHandle); - - user_assert(Width && Height, D3DERR_INVALIDCALL); - - /* pSharedHandle: can be non-null for ex only. - * D3DPOOL_SYSTEMMEM: Levels must be 1 - * D3DPOOL_DEFAULT: no restriction for Levels - * Other Pools are forbidden. */ - user_assert(!pSharedHandle || pParams->device->ex, D3DERR_INVALIDCALL); - user_assert(!pSharedHandle || - (Pool == D3DPOOL_SYSTEMMEM && Levels == 1) || - Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); - - user_assert(!(Usage & D3DUSAGE_AUTOGENMIPMAP) || - (Pool != D3DPOOL_SYSTEMMEM && Pool != D3DPOOL_SCRATCH && Levels <= 1), - D3DERR_INVALIDCALL); - - /* TODO: implement pSharedHandle for D3DPOOL_DEFAULT (cross process - * buffer sharing). - * - * Gem names may have fit but they're depreciated and won't work on render-nodes. - * One solution is to use shm buffers. We would use a /dev/shm file, fill the first - * values to tell it is a nine buffer, the size, which function created it, etc, - * and then it would contain the data. The handle would be a number, corresponding to - * the file to read (/dev/shm/nine-share-4 for example would be 4). - * - * Wine just ignores the argument, which works only if the app creates the handle - * and won't use it. Instead of failing, we support that situation by putting an - * invalid handle, that we would fail to import. Please note that we don't advertise - * the flag indicating the support for that feature, but apps seem to not care. - */ - - if (pSharedHandle && Pool == D3DPOOL_DEFAULT) { - if (!*pSharedHandle) { - DBG("Creating Texture with invalid handle. Importing will fail\n."); - *pSharedHandle = (HANDLE)1; /* Wine would keep it NULL */ - pSharedHandle = NULL; - } else { - ERR("Application tries to use cross-process sharing feature. Nine " - "doesn't support it"); - return D3DERR_INVALIDCALL; - } - } - - if (Usage & D3DUSAGE_AUTOGENMIPMAP) - Levels = 0; - - pf = d3d9_to_pipe_format_checked(screen, Format, PIPE_TEXTURE_2D, 0, - PIPE_BIND_SAMPLER_VIEW, FALSE, - Pool == D3DPOOL_SCRATCH); - - if (Format != D3DFMT_NULL && pf == PIPE_FORMAT_NONE) - return D3DERR_INVALIDCALL; - - if (compressed_format(Format)) { - const unsigned w = util_format_get_blockwidth(pf); - const unsigned h = util_format_get_blockheight(pf); - - user_assert(!(Width % w) && !(Height % h), D3DERR_INVALIDCALL); - } - - info->screen = screen; - info->target = PIPE_TEXTURE_2D; - info->format = pf; - info->width0 = Width; - info->height0 = Height; - info->depth0 = 1; - if (Levels) - info->last_level = Levels - 1; - else - info->last_level = util_logbase2(MAX2(Width, Height)); - info->array_size = 1; - info->nr_samples = 0; - info->nr_storage_samples = 0; - info->bind = PIPE_BIND_SAMPLER_VIEW; - info->usage = PIPE_USAGE_DEFAULT; - info->flags = 0; - - if (Usage & D3DUSAGE_RENDERTARGET) - info->bind |= PIPE_BIND_RENDER_TARGET; - if (Usage & D3DUSAGE_DEPTHSTENCIL) - info->bind |= PIPE_BIND_DEPTH_STENCIL; - - if (Usage & D3DUSAGE_DYNAMIC) { - info->usage = PIPE_USAGE_DYNAMIC; - } - - if (Usage & D3DUSAGE_SOFTWAREPROCESSING) - DBG("Application asked for Software Vertex Processing, " - "but this is unimplemented\n"); - - if (pSharedHandle && *pSharedHandle) { /* Pool == D3DPOOL_SYSTEMMEM */ - user_buffer = (void *)*pSharedHandle; - level_offsets = alloca(sizeof(unsigned) * (info->last_level + 1)); - (void) nine_format_get_size_and_offsets(pf, level_offsets, - Width, Height, - info->last_level); - } else if (Pool != D3DPOOL_DEFAULT) { - /* TODO: For D3DUSAGE_AUTOGENMIPMAP, it is likely we only have to - * allocate only for the first level, since it is the only lockable - * level. Check apps don't crash if we allocate smaller buffer (some - * apps access sublevels of texture even if they locked only first - * level) */ - level_offsets = alloca(sizeof(unsigned) * (info->last_level + 1)); - user_buffer = align_calloc( - nine_format_get_size_and_offsets(pf, level_offsets, - Width, Height, - info->last_level), 32); - This->managed_buffer = user_buffer; - if (!This->managed_buffer) - return E_OUTOFMEMORY; - } - - This->surfaces = CALLOC(info->last_level + 1, sizeof(*This->surfaces)); - if (!This->surfaces) - return E_OUTOFMEMORY; - - hr = NineBaseTexture9_ctor(&This->base, pParams, NULL, D3DRTYPE_TEXTURE, Format, Pool, Usage); - if (FAILED(hr)) - return hr; - This->base.pstype = (Height == 1) ? 1 : 0; - - /* Create all the surfaces right away. - * They manage backing storage, and transfers (LockRect) are deferred - * to them. - */ - sfdesc.Format = Format; - sfdesc.Type = D3DRTYPE_SURFACE; - sfdesc.Usage = Usage; - sfdesc.Pool = Pool; - sfdesc.MultiSampleType = D3DMULTISAMPLE_NONE; - sfdesc.MultiSampleQuality = 0; - - for (l = 0; l <= info->last_level; ++l) { - sfdesc.Width = u_minify(Width, l); - sfdesc.Height = u_minify(Height, l); - /* Some apps expect the memory to be allocated in - * continous blocks */ - user_buffer_for_level = user_buffer ? user_buffer + - level_offsets[l] : NULL; - - hr = NineSurface9_new(This->base.base.base.device, NineUnknown(This), - This->base.base.resource, user_buffer_for_level, - D3DRTYPE_TEXTURE, l, 0, - &sfdesc, &This->surfaces[l]); - if (FAILED(hr)) - return hr; - } - - /* Textures start initially dirty */ - This->dirty_rect.width = Width; - This->dirty_rect.height = Height; - This->dirty_rect.depth = 1; /* widht == 0 means empty, depth stays 1 */ - - if (pSharedHandle && !*pSharedHandle) {/* Pool == D3DPOOL_SYSTEMMEM */ - *pSharedHandle = This->surfaces[0]->data; - } - - return D3D_OK; -} - -static void -NineTexture9_dtor( struct NineTexture9 *This ) -{ - unsigned l; - - DBG("This=%p\n", This); - - if (This->surfaces) { - /* The surfaces should have 0 references and be unbound now. */ - for (l = 0; l <= This->base.base.info.last_level; ++l) - if (This->surfaces[l]) - NineUnknown_Destroy(&This->surfaces[l]->base.base); - FREE(This->surfaces); - } - - if (This->managed_buffer) - align_free(This->managed_buffer); - - NineBaseTexture9_dtor(&This->base); -} - -HRESULT NINE_WINAPI -NineTexture9_GetLevelDesc( struct NineTexture9 *This, - UINT Level, - D3DSURFACE_DESC *pDesc ) -{ - DBG("This=%p Level=%d pDesc=%p\n", This, Level, pDesc); - - user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); - user_assert(Level == 0 || !(This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP), - D3DERR_INVALIDCALL); - - *pDesc = This->surfaces[Level]->desc; - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineTexture9_GetSurfaceLevel( struct NineTexture9 *This, - UINT Level, - IDirect3DSurface9 **ppSurfaceLevel ) -{ - DBG("This=%p Level=%d ppSurfaceLevel=%p\n", This, Level, ppSurfaceLevel); - - user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); - user_assert(Level == 0 || !(This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP), - D3DERR_INVALIDCALL); - - NineUnknown_AddRef(NineUnknown(This->surfaces[Level])); - *ppSurfaceLevel = (IDirect3DSurface9 *)This->surfaces[Level]; - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineTexture9_LockRect( struct NineTexture9 *This, - UINT Level, - D3DLOCKED_RECT *pLockedRect, - const RECT *pRect, - DWORD Flags ) -{ - DBG("This=%p Level=%u pLockedRect=%p pRect=%p Flags=%d\n", - This, Level, pLockedRect, pRect, Flags); - - user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); - user_assert(Level == 0 || !(This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP), - D3DERR_INVALIDCALL); - - return NineSurface9_LockRect(This->surfaces[Level], pLockedRect, - pRect, Flags); -} - -HRESULT NINE_WINAPI -NineTexture9_UnlockRect( struct NineTexture9 *This, - UINT Level ) -{ - DBG("This=%p Level=%u\n", This, Level); - - user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); - - return NineSurface9_UnlockRect(This->surfaces[Level]); -} - -HRESULT NINE_WINAPI -NineTexture9_AddDirtyRect( struct NineTexture9 *This, - const RECT *pDirtyRect ) -{ - DBG("This=%p pDirtyRect=%p[(%u,%u)-(%u,%u)]\n", This, pDirtyRect, - pDirtyRect ? pDirtyRect->left : 0, pDirtyRect ? pDirtyRect->top : 0, - pDirtyRect ? pDirtyRect->right : 0, pDirtyRect ? pDirtyRect->bottom : 0); - - /* Tracking dirty regions on DEFAULT resources is pointless, - * because we always write to the final storage. Just marked it dirty in - * case we need to generate mip maps. - */ - if (This->base.base.pool == D3DPOOL_DEFAULT) { - if (This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP) { - This->base.dirty_mip = TRUE; - BASETEX_REGISTER_UPDATE(&This->base); - } - return D3D_OK; - } - - if (This->base.base.pool == D3DPOOL_MANAGED) { - This->base.managed.dirty = TRUE; - BASETEX_REGISTER_UPDATE(&This->base); - } - - if (!pDirtyRect) { - u_box_origin_2d(This->base.base.info.width0, - This->base.base.info.height0, &This->dirty_rect); - } else { - if (This->dirty_rect.width == 0) { - rect_to_pipe_box_clamp(&This->dirty_rect, pDirtyRect); - } else { - struct pipe_box box; - rect_to_pipe_box_clamp(&box, pDirtyRect); - u_box_union_2d(&This->dirty_rect, &This->dirty_rect, &box); - } - (void) u_box_clip_2d(&This->dirty_rect, &This->dirty_rect, - This->base.base.info.width0, - This->base.base.info.height0); - } - return D3D_OK; -} - -IDirect3DTexture9Vtbl NineTexture9_vtable = { - (void *)NineUnknown_QueryInterface, - (void *)NineUnknown_AddRef, - (void *)NineUnknown_Release, - (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */ - (void *)NineUnknown_SetPrivateData, - (void *)NineUnknown_GetPrivateData, - (void *)NineUnknown_FreePrivateData, - (void *)NineResource9_SetPriority, - (void *)NineResource9_GetPriority, - (void *)NineBaseTexture9_PreLoad, - (void *)NineResource9_GetType, - (void *)NineBaseTexture9_SetLOD, - (void *)NineBaseTexture9_GetLOD, - (void *)NineBaseTexture9_GetLevelCount, - (void *)NineBaseTexture9_SetAutoGenFilterType, - (void *)NineBaseTexture9_GetAutoGenFilterType, - (void *)NineBaseTexture9_GenerateMipSubLevels, - (void *)NineTexture9_GetLevelDesc, - (void *)NineTexture9_GetSurfaceLevel, - (void *)NineTexture9_LockRect, - (void *)NineTexture9_UnlockRect, - (void *)NineTexture9_AddDirtyRect -}; - -static const GUID *NineTexture9_IIDs[] = { - &IID_IDirect3DTexture9, - &IID_IDirect3DBaseTexture9, - &IID_IDirect3DResource9, - &IID_IUnknown, - NULL -}; - -HRESULT -NineTexture9_new( struct NineDevice9 *pDevice, - UINT Width, UINT Height, UINT Levels, - DWORD Usage, - D3DFORMAT Format, - D3DPOOL Pool, - struct NineTexture9 **ppOut, - HANDLE *pSharedHandle ) -{ - NINE_DEVICE_CHILD_NEW(Texture9, ppOut, pDevice, - Width, Height, Levels, - Usage, Format, Pool, pSharedHandle); -} diff --git a/src/gallium/state_trackers/nine/texture9.h b/src/gallium/state_trackers/nine/texture9.h deleted file mode 100644 index 3911f26d468..00000000000 --- a/src/gallium/state_trackers/nine/texture9.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef _NINE_TEXTURE9_H_ -#define _NINE_TEXTURE9_H_ - -#include "basetexture9.h" -#include "surface9.h" - -struct NineTexture9 -{ - struct NineBaseTexture9 base; - struct NineSurface9 **surfaces; - struct pipe_box dirty_rect; /* covers all mip levels */ - uint8_t *managed_buffer; -}; -static inline struct NineTexture9 * -NineTexture9( void *data ) -{ - return (struct NineTexture9 *)data; -} - -HRESULT -NineTexture9_new( struct NineDevice9 *pDevice, - UINT Width, UINT Height, UINT Levels, - DWORD Usage, - D3DFORMAT Format, - D3DPOOL Pool, - struct NineTexture9 **ppOut, - HANDLE *pSharedHandle ); - -HRESULT NINE_WINAPI -NineTexture9_GetLevelDesc( struct NineTexture9 *This, - UINT Level, - D3DSURFACE_DESC *pDesc ); - -HRESULT NINE_WINAPI -NineTexture9_GetSurfaceLevel( struct NineTexture9 *This, - UINT Level, - IDirect3DSurface9 **ppSurfaceLevel ); - -HRESULT NINE_WINAPI -NineTexture9_LockRect( struct NineTexture9 *This, - UINT Level, - D3DLOCKED_RECT *pLockedRect, - const RECT *pRect, - DWORD Flags ); - -HRESULT NINE_WINAPI -NineTexture9_UnlockRect( struct NineTexture9 *This, - UINT Level ); - -HRESULT NINE_WINAPI -NineTexture9_AddDirtyRect( struct NineTexture9 *This, - const RECT *pDirtyRect ); - -#endif /* _NINE_TEXTURE9_H_ */ diff --git a/src/gallium/state_trackers/nine/threadpool.c b/src/gallium/state_trackers/nine/threadpool.c deleted file mode 100644 index 3ce6cd57524..00000000000 --- a/src/gallium/state_trackers/nine/threadpool.c +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright © 2012 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "swapchain9.h" -#include "surface9.h" -#include "device9.h" - -#include "nine_helpers.h" -#include "nine_pipe.h" -#include "nine_dump.h" - -#include "util/u_inlines.h" -#include "util/u_surface.h" -#include "hud/hud_context.h" -#include "state_tracker/drm_driver.h" - -#include "os/os_thread.h" -#include "threadpool.h" - -/* POSIX thread function */ -static void * -threadpool_worker(void *data) -{ - struct threadpool *pool = data; - - pthread_mutex_lock(&pool->m); - - while (!pool->shutdown) { - struct threadpool_task *task; - - /* Block (dropping the lock) until new work arrives for us. */ - while (!pool->workqueue && !pool->shutdown) - pthread_cond_wait(&pool->new_work, &pool->m); - - if (pool->shutdown) - break; - - /* Pull the first task from the list. We don't free it -- it now lacks - * a reference other than the worker creator's, whose responsibility it - * is to call threadpool_wait_for_work() to free it. - */ - task = pool->workqueue; - pool->workqueue = task->next; - - /* Call the task's work func. */ - pthread_mutex_unlock(&pool->m); - task->work(task->data); - pthread_mutex_lock(&pool->m); - task->finished = TRUE; - pthread_cond_broadcast(&task->finish); - } - - pthread_mutex_unlock(&pool->m); - - return NULL; -} - -/* Windows thread function */ -static DWORD NINE_WINAPI -wthreadpool_worker(void *data) -{ - threadpool_worker(data); - - return 0; -} - -struct threadpool * -_mesa_threadpool_create(struct NineSwapChain9 *swapchain) -{ - struct threadpool *pool = calloc(1, sizeof(*pool)); - - if (!pool) - return NULL; - - pthread_mutex_init(&pool->m, NULL); - pthread_cond_init(&pool->new_work, NULL); - - /* This uses WINE's CreateThread, so the thread function needs to use - * the Windows ABI */ - pool->wthread = NineSwapChain9_CreateThread(swapchain, wthreadpool_worker, pool); - if (!pool->wthread) { - /* using pthread as fallback */ - pthread_create(&pool->pthread, NULL, threadpool_worker, pool); - } - return pool; -} - -void -_mesa_threadpool_destroy(struct NineSwapChain9 *swapchain, struct threadpool *pool) -{ - if (!pool) - return; - - pthread_mutex_lock(&pool->m); - pool->shutdown = TRUE; - pthread_cond_broadcast(&pool->new_work); - pthread_mutex_unlock(&pool->m); - - if (pool->wthread) { - NineSwapChain9_WaitForThread(swapchain, pool->wthread); - } else { - pthread_join(pool->pthread, NULL); - } - - pthread_cond_destroy(&pool->new_work); - pthread_mutex_destroy(&pool->m); - free(pool); -} - -/** - * Queues a request for the work function to be asynchronously executed by the - * thread pool. - * - * The work func will get the "data" argument as its parameter -- any - * communication between the caller and the work function will occur through - * that. - * - * If there is an error, the work function is called immediately and NULL is - * returned. - */ -struct threadpool_task * -_mesa_threadpool_queue_task(struct threadpool *pool, - threadpool_task_func work, void *data) -{ - struct threadpool_task *task, *previous; - - if (!pool) { - work(data); - return NULL; - } - - task = calloc(1, sizeof(*task)); - if (!task) { - work(data); - return NULL; - } - - task->work = work; - task->data = data; - task->next = NULL; - pthread_cond_init(&task->finish, NULL); - - pthread_mutex_lock(&pool->m); - - if (!pool->workqueue) { - pool->workqueue = task; - } else { - previous = pool->workqueue; - while (previous && previous->next) - previous = previous->next; - - previous->next = task; - } - pthread_cond_signal(&pool->new_work); - pthread_mutex_unlock(&pool->m); - - return task; -} - -/** - * Blocks on the completion of the given task and frees the task. - */ -void -_mesa_threadpool_wait_for_task(struct threadpool *pool, - struct threadpool_task **task_handle) -{ - struct threadpool_task *task = *task_handle; - - if (!pool || !task) - return; - - pthread_mutex_lock(&pool->m); - while (!task->finished) - pthread_cond_wait(&task->finish, &pool->m); - pthread_mutex_unlock(&pool->m); - - pthread_cond_destroy(&task->finish); - free(task); - *task_handle = NULL; -} diff --git a/src/gallium/state_trackers/nine/threadpool.h b/src/gallium/state_trackers/nine/threadpool.h deleted file mode 100644 index 6f8f8c455d0..00000000000 --- a/src/gallium/state_trackers/nine/threadpool.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright © 2012 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef _THREADPOOL_H_ -#define _THREADPOOL_H_ - -#include - -struct NineSwapChain9; - -#define MAXTHREADS 1 - -struct threadpool { - pthread_mutex_t m; - pthread_cond_t new_work; - - HANDLE wthread; - pthread_t pthread; - struct threadpool_task *workqueue; - BOOL shutdown; -}; - -typedef void (*threadpool_task_func)(void *data); - -struct threadpool_task { - threadpool_task_func work; - void *data; - struct threadpool_task *next; - pthread_cond_t finish; - BOOL finished; -}; - -struct threadpool *_mesa_threadpool_create(struct NineSwapChain9 *swapchain); -void _mesa_threadpool_destroy(struct NineSwapChain9 *swapchain, struct threadpool *pool); -struct threadpool_task *_mesa_threadpool_queue_task(struct threadpool *pool, - threadpool_task_func func, - void *data); -void _mesa_threadpool_wait_for_task(struct threadpool *pool, - struct threadpool_task **task); -#endif diff --git a/src/gallium/state_trackers/nine/vertexbuffer9.c b/src/gallium/state_trackers/nine/vertexbuffer9.c deleted file mode 100644 index df1d1717539..00000000000 --- a/src/gallium/state_trackers/nine/vertexbuffer9.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "vertexbuffer9.h" -#include "device9.h" -#include "nine_helpers.h" -#include "nine_pipe.h" - -#include "pipe/p_screen.h" -#include "pipe/p_context.h" -#include "pipe/p_state.h" -#include "pipe/p_defines.h" -#include "pipe/p_format.h" -#include "util/u_box.h" - -#define DBG_CHANNEL DBG_VERTEXBUFFER - -HRESULT -NineVertexBuffer9_ctor( struct NineVertexBuffer9 *This, - struct NineUnknownParams *pParams, - D3DVERTEXBUFFER_DESC *pDesc ) -{ - HRESULT hr; - - DBG("This=%p Size=0x%x Usage=%x Pool=%u\n", This, - pDesc->Size, pDesc->Usage, pDesc->Pool); - - hr = NineBuffer9_ctor(&This->base, pParams, D3DRTYPE_VERTEXBUFFER, - pDesc->Usage, pDesc->Size, pDesc->Pool); - if (FAILED(hr)) - return hr; - - pDesc->Type = D3DRTYPE_VERTEXBUFFER; - pDesc->Format = D3DFMT_VERTEXDATA; - This->desc = *pDesc; - - return D3D_OK; -} - -void -NineVertexBuffer9_dtor( struct NineVertexBuffer9 *This ) -{ - NineBuffer9_dtor(&This->base); -} - -struct pipe_resource * -NineVertexBuffer9_GetResource( struct NineVertexBuffer9 *This, unsigned *offset ) -{ - return NineBuffer9_GetResource(&This->base, offset); -} - -HRESULT NINE_WINAPI -NineVertexBuffer9_Lock( struct NineVertexBuffer9 *This, - UINT OffsetToLock, - UINT SizeToLock, - void **ppbData, - DWORD Flags ) -{ - return NineBuffer9_Lock(&This->base, OffsetToLock, SizeToLock, ppbData, Flags); -} - -HRESULT NINE_WINAPI -NineVertexBuffer9_Unlock( struct NineVertexBuffer9 *This ) -{ - return NineBuffer9_Unlock(&This->base); -} - -HRESULT NINE_WINAPI -NineVertexBuffer9_GetDesc( struct NineVertexBuffer9 *This, - D3DVERTEXBUFFER_DESC *pDesc ) -{ - user_assert(pDesc, E_POINTER); - *pDesc = This->desc; - return D3D_OK; -} - -IDirect3DVertexBuffer9Vtbl NineVertexBuffer9_vtable = { - (void *)NineUnknown_QueryInterface, - (void *)NineUnknown_AddRef, - (void *)NineUnknown_Release, - (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */ - (void *)NineUnknown_SetPrivateData, - (void *)NineUnknown_GetPrivateData, - (void *)NineUnknown_FreePrivateData, - (void *)NineResource9_SetPriority, - (void *)NineResource9_GetPriority, - (void *)NineResource9_PreLoad, - (void *)NineResource9_GetType, - (void *)NineVertexBuffer9_Lock, - (void *)NineVertexBuffer9_Unlock, - (void *)NineVertexBuffer9_GetDesc -}; - -static const GUID *NineVertexBuffer9_IIDs[] = { - &IID_IDirect3DVertexBuffer9, - &IID_IDirect3DResource9, - &IID_IUnknown, - NULL -}; - -HRESULT -NineVertexBuffer9_new( struct NineDevice9 *pDevice, - D3DVERTEXBUFFER_DESC *pDesc, - struct NineVertexBuffer9 **ppOut ) -{ - NINE_DEVICE_CHILD_NEW(VertexBuffer9, ppOut, /* args */ pDevice, pDesc); -} diff --git a/src/gallium/state_trackers/nine/vertexbuffer9.h b/src/gallium/state_trackers/nine/vertexbuffer9.h deleted file mode 100644 index 2991dbadd07..00000000000 --- a/src/gallium/state_trackers/nine/vertexbuffer9.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef _NINE_VERTEXBUFFER9_H_ -#define _NINE_VERTEXBUFFER9_H_ -#include "resource9.h" -#include "buffer9.h" - -struct pipe_screen; -struct pipe_context; -struct pipe_transfer; - -struct NineVertexBuffer9 -{ - struct NineBuffer9 base; - - /* G3D */ - struct pipe_context *pipe; - D3DVERTEXBUFFER_DESC desc; -}; -static inline struct NineVertexBuffer9 * -NineVertexBuffer9( void *data ) -{ - return (struct NineVertexBuffer9 *)data; -} - -HRESULT -NineVertexBuffer9_new( struct NineDevice9 *pDevice, - D3DVERTEXBUFFER_DESC *pDesc, - struct NineVertexBuffer9 **ppOut ); - -HRESULT -NineVertexBuffer9_ctor( struct NineVertexBuffer9 *This, - struct NineUnknownParams *pParams, - D3DVERTEXBUFFER_DESC *pDesc ); - -void -NineVertexBuffer9_dtor( struct NineVertexBuffer9 *This ); -/*** Nine private ***/ - -struct pipe_resource * -NineVertexBuffer9_GetResource( struct NineVertexBuffer9 *This, unsigned *offset ); - -/*** Direct3D public ***/ - -HRESULT NINE_WINAPI -NineVertexBuffer9_Lock( struct NineVertexBuffer9 *This, - UINT OffsetToLock, - UINT SizeToLock, - void **ppbData, - DWORD Flags ); - -HRESULT NINE_WINAPI -NineVertexBuffer9_Unlock( struct NineVertexBuffer9 *This ); - -HRESULT NINE_WINAPI -NineVertexBuffer9_GetDesc( struct NineVertexBuffer9 *This, - D3DVERTEXBUFFER_DESC *pDesc ); - -#endif /* _NINE_VERTEXBUFFER9_H_ */ diff --git a/src/gallium/state_trackers/nine/vertexdeclaration9.c b/src/gallium/state_trackers/nine/vertexdeclaration9.c deleted file mode 100644 index 9beeff290b3..00000000000 --- a/src/gallium/state_trackers/nine/vertexdeclaration9.c +++ /dev/null @@ -1,531 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "vertexdeclaration9.h" -#include "vertexbuffer9.h" -#include "device9.h" -#include "nine_helpers.h" -#include "nine_shader.h" - -#include "pipe/p_format.h" -#include "pipe/p_context.h" -#include "util/u_math.h" -#include "util/format/u_format.h" -#include "translate/translate.h" - -#define DBG_CHANNEL DBG_VERTEXDECLARATION - -static inline enum pipe_format decltype_format(BYTE type) -{ - switch (type) { - case D3DDECLTYPE_FLOAT1: return PIPE_FORMAT_R32_FLOAT; - case D3DDECLTYPE_FLOAT2: return PIPE_FORMAT_R32G32_FLOAT; - case D3DDECLTYPE_FLOAT3: return PIPE_FORMAT_R32G32B32_FLOAT; - case D3DDECLTYPE_FLOAT4: return PIPE_FORMAT_R32G32B32A32_FLOAT; - case D3DDECLTYPE_D3DCOLOR: return PIPE_FORMAT_B8G8R8A8_UNORM; - case D3DDECLTYPE_UBYTE4: return PIPE_FORMAT_R8G8B8A8_USCALED; - case D3DDECLTYPE_SHORT2: return PIPE_FORMAT_R16G16_SSCALED; - case D3DDECLTYPE_SHORT4: return PIPE_FORMAT_R16G16B16A16_SSCALED; - case D3DDECLTYPE_UBYTE4N: return PIPE_FORMAT_R8G8B8A8_UNORM; - case D3DDECLTYPE_SHORT2N: return PIPE_FORMAT_R16G16_SNORM; - case D3DDECLTYPE_SHORT4N: return PIPE_FORMAT_R16G16B16A16_SNORM; - case D3DDECLTYPE_USHORT2N: return PIPE_FORMAT_R16G16_UNORM; - case D3DDECLTYPE_USHORT4N: return PIPE_FORMAT_R16G16B16A16_UNORM; - case D3DDECLTYPE_UDEC3: return PIPE_FORMAT_R10G10B10X2_USCALED; - case D3DDECLTYPE_DEC3N: return PIPE_FORMAT_R10G10B10X2_SNORM; - case D3DDECLTYPE_FLOAT16_2: return PIPE_FORMAT_R16G16_FLOAT; - case D3DDECLTYPE_FLOAT16_4: return PIPE_FORMAT_R16G16B16A16_FLOAT; - default: - assert(!"Implementation error !"); - } - return PIPE_FORMAT_NONE; -} - -static inline unsigned decltype_size(BYTE type) -{ - switch (type) { - case D3DDECLTYPE_FLOAT1: return 1 * sizeof(float); - case D3DDECLTYPE_FLOAT2: return 2 * sizeof(float); - case D3DDECLTYPE_FLOAT3: return 3 * sizeof(float); - case D3DDECLTYPE_FLOAT4: return 4 * sizeof(float); - case D3DDECLTYPE_D3DCOLOR: return 1 * sizeof(DWORD); - case D3DDECLTYPE_UBYTE4: return 4 * sizeof(BYTE); - case D3DDECLTYPE_SHORT2: return 2 * sizeof(short); - case D3DDECLTYPE_SHORT4: return 4 * sizeof(short); - case D3DDECLTYPE_UBYTE4N: return 4 * sizeof(BYTE); - case D3DDECLTYPE_SHORT2N: return 2 * sizeof(short); - case D3DDECLTYPE_SHORT4N: return 4 * sizeof(short); - case D3DDECLTYPE_USHORT2N: return 2 * sizeof(short); - case D3DDECLTYPE_USHORT4N: return 4 * sizeof(short); - case D3DDECLTYPE_UDEC3: return 4; - case D3DDECLTYPE_DEC3N: return 4; - case D3DDECLTYPE_FLOAT16_2: return 2 * 2; - case D3DDECLTYPE_FLOAT16_4: return 4 * 2; - default: - assert(!"Implementation error !"); - } - return 0; -} - -/* Actually, arbitrary usage index values are permitted, but a - * simple lookup table won't work in that case. Let's just wait - * with making this more generic until we need it. - */ -static inline boolean -nine_d3ddeclusage_check(unsigned usage, unsigned usage_idx) -{ - switch (usage) { - case D3DDECLUSAGE_POSITIONT: - case D3DDECLUSAGE_TESSFACTOR: - case D3DDECLUSAGE_DEPTH: - case D3DDECLUSAGE_NORMAL: - case D3DDECLUSAGE_TANGENT: - case D3DDECLUSAGE_BINORMAL: - case D3DDECLUSAGE_POSITION: - case D3DDECLUSAGE_BLENDWEIGHT: - case D3DDECLUSAGE_BLENDINDICES: - case D3DDECLUSAGE_COLOR: - return TRUE; - case D3DDECLUSAGE_PSIZE: - case D3DDECLUSAGE_FOG: - case D3DDECLUSAGE_SAMPLE: - return usage_idx <= 0; - case D3DDECLUSAGE_TEXCOORD: - return usage_idx <= 15; - default: - return FALSE; - } -} - -#define NINE_DECLUSAGE_CASE0(n) case D3DDECLUSAGE_##n: return NINE_DECLUSAGE_##n -#define NINE_DECLUSAGE_CASEi(n) case D3DDECLUSAGE_##n: return NINE_DECLUSAGE_i(n, usage_idx) -uint16_t -nine_d3d9_to_nine_declusage(unsigned usage, unsigned usage_idx) -{ - if (!nine_d3ddeclusage_check(usage, usage_idx)) - ERR("D3DDECLUSAGE_%u[%u]\n",usage,usage_idx); - assert(nine_d3ddeclusage_check(usage, usage_idx)); - switch (usage) { - NINE_DECLUSAGE_CASEi(POSITION); - NINE_DECLUSAGE_CASEi(BLENDWEIGHT); - NINE_DECLUSAGE_CASEi(BLENDINDICES); - NINE_DECLUSAGE_CASEi(NORMAL); - NINE_DECLUSAGE_CASE0(PSIZE); - NINE_DECLUSAGE_CASEi(TEXCOORD); - NINE_DECLUSAGE_CASEi(TANGENT); - NINE_DECLUSAGE_CASEi(BINORMAL); - NINE_DECLUSAGE_CASE0(TESSFACTOR); - NINE_DECLUSAGE_CASEi(POSITIONT); - NINE_DECLUSAGE_CASEi(COLOR); - NINE_DECLUSAGE_CASE0(DEPTH); - NINE_DECLUSAGE_CASE0(FOG); - NINE_DECLUSAGE_CASE0(SAMPLE); - default: - assert(!"Invalid DECLUSAGE."); - return NINE_DECLUSAGE_NONE; - } -} - -static const char *nine_declusage_names[] = -{ - [NINE_DECLUSAGE_POSITION] = "POSITION", - [NINE_DECLUSAGE_BLENDWEIGHT] = "BLENDWEIGHT", - [NINE_DECLUSAGE_BLENDINDICES] = "BLENDINDICES", - [NINE_DECLUSAGE_NORMAL] = "NORMAL", - [NINE_DECLUSAGE_PSIZE] = "PSIZE", - [NINE_DECLUSAGE_TEXCOORD] = "TEXCOORD", - [NINE_DECLUSAGE_TANGENT] = "TANGENT", - [NINE_DECLUSAGE_BINORMAL] = "BINORMAL", - [NINE_DECLUSAGE_TESSFACTOR] = "TESSFACTOR", - [NINE_DECLUSAGE_POSITIONT] = "POSITIONT", - [NINE_DECLUSAGE_COLOR] = "DIFFUSE", - [NINE_DECLUSAGE_DEPTH] = "DEPTH", - [NINE_DECLUSAGE_FOG] = "FOG", - [NINE_DECLUSAGE_NONE] = "(NONE)", -}; -static inline const char * -nine_declusage_name(unsigned ndcl) -{ - return nine_declusage_names[ndcl % NINE_DECLUSAGE_COUNT]; -} - -HRESULT -NineVertexDeclaration9_ctor( struct NineVertexDeclaration9 *This, - struct NineUnknownParams *pParams, - const D3DVERTEXELEMENT9 *pElements ) -{ - const D3DCAPS9 *caps; - unsigned i, nelems; - DBG("This=%p pParams=%p pElements=%p\n", This, pParams, pElements); - - /* wine */ - for (nelems = 0; - pElements[nelems].Stream != 0xFF; - ++nelems) { - user_assert(pElements[nelems].Type != D3DDECLTYPE_UNUSED, E_FAIL); - user_assert(!(pElements[nelems].Offset & 3), E_FAIL); - } - - caps = NineDevice9_GetCaps(pParams->device); - user_assert(nelems <= caps->MaxStreams, D3DERR_INVALIDCALL); - - HRESULT hr = NineUnknown_ctor(&This->base, pParams); - if (FAILED(hr)) { return hr; } - - This->nelems = nelems; - This->decls = CALLOC(This->nelems+1, sizeof(D3DVERTEXELEMENT9)); - This->elems = CALLOC(This->nelems, sizeof(struct pipe_vertex_element)); - This->usage_map = CALLOC(This->nelems, sizeof(uint16_t)); - if (!This->decls || !This->elems || !This->usage_map) { return E_OUTOFMEMORY; } - memcpy(This->decls, pElements, sizeof(D3DVERTEXELEMENT9)*(This->nelems+1)); - - for (i = 0; i < This->nelems; ++i) { - uint16_t usage = nine_d3d9_to_nine_declusage(This->decls[i].Usage, - This->decls[i].UsageIndex); - This->usage_map[i] = usage; - - if (This->decls[i].Usage == D3DDECLUSAGE_POSITIONT) - This->position_t = TRUE; - - This->elems[i].src_offset = This->decls[i].Offset; - This->elems[i].instance_divisor = 0; - This->elems[i].vertex_buffer_index = This->decls[i].Stream; - This->elems[i].src_format = decltype_format(This->decls[i].Type); - /* XXX Remember Method (tesselation), Usage, UsageIndex */ - - DBG("VERTEXELEMENT[%u]: Stream=%u Offset=%u Type=%s DeclUsage=%s%d\n", i, - This->decls[i].Stream, - This->decls[i].Offset, - util_format_name(This->elems[i].src_format), - nine_declusage_name(usage), - usage / NINE_DECLUSAGE_COUNT); - } - - return D3D_OK; -} - -void -NineVertexDeclaration9_dtor( struct NineVertexDeclaration9 *This ) -{ - DBG("This=%p\n", This); - - FREE(This->decls); - FREE(This->elems); - FREE(This->usage_map); - - NineUnknown_dtor(&This->base); -} - -HRESULT NINE_WINAPI -NineVertexDeclaration9_GetDeclaration( struct NineVertexDeclaration9 *This, - D3DVERTEXELEMENT9 *pElement, - UINT *pNumElements ) -{ - if (!pElement) { - user_assert(pNumElements, D3DERR_INVALIDCALL); - *pNumElements = This->nelems+1; - return D3D_OK; - } - if (pNumElements) { *pNumElements = This->nelems+1; } - memcpy(pElement, This->decls, sizeof(D3DVERTEXELEMENT9)*(This->nelems+1)); - return D3D_OK; -} - -IDirect3DVertexDeclaration9Vtbl NineVertexDeclaration9_vtable = { - (void *)NineUnknown_QueryInterface, - (void *)NineUnknown_AddRef, - (void *)NineUnknown_Release, - (void *)NineUnknown_GetDevice, /* actually part of VertexDecl9 iface */ - (void *)NineVertexDeclaration9_GetDeclaration -}; - -static const GUID *NineVertexDeclaration9_IIDs[] = { - &IID_IDirect3DVertexDeclaration9, - &IID_IUnknown, - NULL -}; - -HRESULT -NineVertexDeclaration9_new( struct NineDevice9 *pDevice, - const D3DVERTEXELEMENT9 *pElements, - struct NineVertexDeclaration9 **ppOut ) -{ - NINE_DEVICE_CHILD_NEW(VertexDeclaration9, ppOut, /* args */ pDevice, pElements); -} - -HRESULT -NineVertexDeclaration9_new_from_fvf( struct NineDevice9 *pDevice, - DWORD FVF, - struct NineVertexDeclaration9 **ppOut ) -{ - D3DVERTEXELEMENT9 elems[16], decl_end = D3DDECL_END(); - unsigned texcount, i, betas, nelems = 0; - BYTE beta_index = 0xFF; - - switch (FVF & D3DFVF_POSITION_MASK) { - case D3DFVF_XYZ: /* simple XYZ */ - case D3DFVF_XYZB1: - case D3DFVF_XYZB2: - case D3DFVF_XYZB3: - case D3DFVF_XYZB4: - case D3DFVF_XYZB5: /* XYZ with beta values */ - elems[nelems].Type = D3DDECLTYPE_FLOAT3; - elems[nelems].Usage = D3DDECLUSAGE_POSITION; - elems[nelems].UsageIndex = 0; - ++nelems; - /* simple XYZ has no beta values. break. */ - if ((FVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) { break; } - - betas = (((FVF & D3DFVF_XYZB5)-D3DFVF_XYZB1)>>1)+1; - if (FVF & D3DFVF_LASTBETA_D3DCOLOR) { - beta_index = D3DDECLTYPE_D3DCOLOR; - } else if (FVF & D3DFVF_LASTBETA_UBYTE4) { - beta_index = D3DDECLTYPE_UBYTE4; - } else if ((FVF & D3DFVF_XYZB5) == D3DFVF_XYZB5) { - beta_index = D3DDECLTYPE_FLOAT1; - } - if (beta_index != 0xFF) { --betas; } - - if (betas > 0) { - switch (betas) { - case 1: elems[nelems].Type = D3DDECLTYPE_FLOAT1; break; - case 2: elems[nelems].Type = D3DDECLTYPE_FLOAT2; break; - case 3: elems[nelems].Type = D3DDECLTYPE_FLOAT3; break; - case 4: elems[nelems].Type = D3DDECLTYPE_FLOAT4; break; - default: - assert(!"Implementation error!"); - } - elems[nelems].Usage = D3DDECLUSAGE_BLENDWEIGHT; - elems[nelems].UsageIndex = 0; - ++nelems; - } - - if (beta_index != 0xFF) { - elems[nelems].Type = beta_index; - elems[nelems].Usage = D3DDECLUSAGE_BLENDINDICES; - elems[nelems].UsageIndex = 0; - ++nelems; - } - break; - - case D3DFVF_XYZW: /* simple XYZW */ - case D3DFVF_XYZRHW: /* pretransformed XYZW */ - elems[nelems].Type = D3DDECLTYPE_FLOAT4; - elems[nelems].Usage = - ((FVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZW) ? - D3DDECLUSAGE_POSITION : D3DDECLUSAGE_POSITIONT; - elems[nelems].UsageIndex = 0; - ++nelems; - break; - - default: - (void)user_error(!"Position doesn't match any known combination"); - } - - /* normals, psize and colors */ - if (FVF & D3DFVF_NORMAL) { - elems[nelems].Type = D3DDECLTYPE_FLOAT3; - elems[nelems].Usage = D3DDECLUSAGE_NORMAL; - elems[nelems].UsageIndex = 0; - ++nelems; - } - if (FVF & D3DFVF_PSIZE) { - elems[nelems].Type = D3DDECLTYPE_FLOAT1; - elems[nelems].Usage = D3DDECLUSAGE_PSIZE; - elems[nelems].UsageIndex = 0; - ++nelems; - } - if (FVF & D3DFVF_DIFFUSE) { - elems[nelems].Type = D3DDECLTYPE_D3DCOLOR; - elems[nelems].Usage = D3DDECLUSAGE_COLOR; - elems[nelems].UsageIndex = 0; - ++nelems; - } - if (FVF & D3DFVF_SPECULAR) { - elems[nelems].Type = D3DDECLTYPE_D3DCOLOR; - elems[nelems].Usage = D3DDECLUSAGE_COLOR; - elems[nelems].UsageIndex = 1; - ++nelems; - } - - /* textures */ - texcount = (FVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT; - if (user_error(texcount <= 8)) { texcount = 8; } - - for (i = 0; i < texcount; ++i) { - switch ((FVF >> (16+i*2)) & 0x3) { - case D3DFVF_TEXTUREFORMAT1: - elems[nelems].Type = D3DDECLTYPE_FLOAT1; - break; - - case D3DFVF_TEXTUREFORMAT2: - elems[nelems].Type = D3DDECLTYPE_FLOAT2; - break; - - case D3DFVF_TEXTUREFORMAT3: - elems[nelems].Type = D3DDECLTYPE_FLOAT3; - break; - - case D3DFVF_TEXTUREFORMAT4: - elems[nelems].Type = D3DDECLTYPE_FLOAT4; - break; - - default: - assert(!"Implementation error!"); - } - elems[nelems].Usage = D3DDECLUSAGE_TEXCOORD; - elems[nelems].UsageIndex = i; - ++nelems; - } - - /* fill out remaining data */ - for (i = 0; i < nelems; ++i) { - elems[i].Stream = 0; - elems[i].Offset = (i == 0) ? 0 : (elems[i-1].Offset + - decltype_size(elems[i-1].Type)); - elems[i].Method = D3DDECLMETHOD_DEFAULT; - } - elems[nelems++] = decl_end; - - NINE_DEVICE_CHILD_NEW(VertexDeclaration9, ppOut, /* args */ pDevice, elems); -} - -void -NineVertexDeclaration9_FillStreamOutputInfo( - struct NineVertexDeclaration9 *This, - struct nine_vs_output_info *ShaderOutputsInfo, - unsigned numOutputs, - struct pipe_stream_output_info *so ) -{ - unsigned so_outputs = 0; - int i, j; - - memset(so, 0, sizeof(struct pipe_stream_output_info)); - - for (i = 0; i < numOutputs; i++) { - BYTE output_semantic = ShaderOutputsInfo[i].output_semantic; - unsigned output_semantic_index = ShaderOutputsInfo[i].output_semantic_index; - - for (j = 0; j < This->nelems; j++) { - if ((This->decls[j].Usage == output_semantic || - (output_semantic == D3DDECLUSAGE_POSITION && - This->decls[j].Usage == D3DDECLUSAGE_POSITIONT)) && - This->decls[j].UsageIndex == output_semantic_index) { - DBG("Matching %s %d: o%d -> %d\n", - nine_declusage_name(nine_d3d9_to_nine_declusage(This->decls[j].Usage, 0)), - This->decls[j].UsageIndex, i, j); - so->output[so_outputs].register_index = ShaderOutputsInfo[i].output_index; - so->output[so_outputs].start_component = 0; - if (ShaderOutputsInfo[i].mask & 8) - so->output[so_outputs].num_components = 4; - else if (ShaderOutputsInfo[i].mask & 4) - so->output[so_outputs].num_components = 3; - else if (ShaderOutputsInfo[i].mask & 2) - so->output[so_outputs].num_components = 2; - else - so->output[so_outputs].num_components = 1; - so->output[so_outputs].output_buffer = 0; - so->output[so_outputs].dst_offset = so_outputs * sizeof(float[4])/4; - so->output[so_outputs].stream = 0; - so_outputs++; - break; - } - } - } - - so->num_outputs = so_outputs; - so->stride[0] = so_outputs * sizeof(float[4])/4; -} - -/* ProcessVertices runs stream output into a temporary buffer to capture - * all outputs. - * Now we have to convert them to the format and order set by the vertex - * declaration, for which we use u_translate. - * This is necessary if the vertex declaration contains elements using a - * non float32 format, because stream output only supports f32/u32/s32. - */ -HRESULT -NineVertexDeclaration9_ConvertStreamOutput( - struct NineVertexDeclaration9 *This, - struct NineVertexBuffer9 *pDstBuf, - UINT DestIndex, - UINT VertexCount, - void *pSrcBuf, - const struct pipe_stream_output_info *so ) -{ - struct translate *translate; - struct translate_key transkey; - HRESULT hr; - unsigned i; - void *dst_map; - - DBG("This=%p pDstBuf=%p DestIndex=%u VertexCount=%u pSrcBuf=%p so=%p\n", - This, pDstBuf, DestIndex, VertexCount, pSrcBuf, so); - - transkey.output_stride = 0; - for (i = 0; i < This->nelems; ++i) { - enum pipe_format format; - - switch (so->output[i].num_components) { - case 1: format = PIPE_FORMAT_R32_FLOAT; break; - case 2: format = PIPE_FORMAT_R32G32_FLOAT; break; - case 3: format = PIPE_FORMAT_R32G32B32_FLOAT; break; - default: - assert(so->output[i].num_components == 4); - format = PIPE_FORMAT_R32G32B32A32_FLOAT; - break; - } - transkey.element[i].type = TRANSLATE_ELEMENT_NORMAL; - transkey.element[i].input_format = format; - transkey.element[i].input_buffer = 0; - transkey.element[i].input_offset = so->output[i].dst_offset * 4; - transkey.element[i].instance_divisor = 0; - - transkey.element[i].output_format = This->elems[i].src_format; - transkey.element[i].output_offset = This->elems[i].src_offset; - transkey.output_stride += - util_format_get_blocksize(This->elems[i].src_format); - - assert(!(transkey.output_stride & 3)); - } - transkey.nr_elements = This->nelems; - - translate = translate_create(&transkey); - if (!translate) - return E_OUTOFMEMORY; - - hr = NineVertexBuffer9_Lock(pDstBuf, - transkey.output_stride * DestIndex, - transkey.output_stride * VertexCount, - &dst_map, D3DLOCK_DISCARD); - if (FAILED(hr)) - goto out; - - translate->set_buffer(translate, 0, pSrcBuf, so->stride[0] * 4, ~0); - - translate->run(translate, 0, VertexCount, 0, 0, dst_map); - - NineVertexBuffer9_Unlock(pDstBuf); -out: - translate->release(translate); /* TODO: cache these */ - return hr; -} diff --git a/src/gallium/state_trackers/nine/vertexdeclaration9.h b/src/gallium/state_trackers/nine/vertexdeclaration9.h deleted file mode 100644 index 7b94f846fe7..00000000000 --- a/src/gallium/state_trackers/nine/vertexdeclaration9.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef _NINE_VERTEXDECLARATION9_H_ -#define _NINE_VERTEXDECLARATION9_H_ - -#include "nine_defines.h" -#include "iunknown.h" - -struct pipe_resource; -struct pipe_vertex_element; -struct pipe_stream_output_info; -struct NineDevice9; -struct NineVertexBuffer9; -struct nine_vs_output_info; - -struct NineVertexDeclaration9 -{ - struct NineUnknown base; - - /* G3D state */ - struct pipe_vertex_element *elems; - unsigned nelems; - - /* index -> DECLUSAGE, for selecting the vertex element - * for each VS input */ - uint16_t *usage_map; - - D3DVERTEXELEMENT9 *decls; - DWORD fvf; - - BOOL position_t; -}; -static inline struct NineVertexDeclaration9 * -NineVertexDeclaration9( void *data ) -{ - return (struct NineVertexDeclaration9 *)data; -} - -HRESULT -NineVertexDeclaration9_new( struct NineDevice9 *pDevice, - const D3DVERTEXELEMENT9 *pElements, - struct NineVertexDeclaration9 **ppOut ); - -HRESULT -NineVertexDeclaration9_new_from_fvf( struct NineDevice9 *pDevice, - DWORD FVF, - struct NineVertexDeclaration9 **ppOut ); - -HRESULT -NineVertexDeclaration9_ctor( struct NineVertexDeclaration9 *This, - struct NineUnknownParams *pParams, - const D3DVERTEXELEMENT9 *pElements ); - -void -NineVertexDeclaration9_dtor( struct NineVertexDeclaration9 *This ); - -HRESULT NINE_WINAPI -NineVertexDeclaration9_GetDeclaration( struct NineVertexDeclaration9 *This, - D3DVERTEXELEMENT9 *pElement, - UINT *pNumElements ); - -void -NineVertexDeclaration9_FillStreamOutputInfo( - struct NineVertexDeclaration9 *This, - struct nine_vs_output_info *ShaderOutputsInfo, - unsigned numOutputs, - struct pipe_stream_output_info *so ); - -/* Convert stream output data to the vertex declaration's format. */ -HRESULT -NineVertexDeclaration9_ConvertStreamOutput( - struct NineVertexDeclaration9 *This, - struct NineVertexBuffer9 *pDstBuf, - UINT DestIndex, - UINT VertexCount, - void *pSrcBuf, - const struct pipe_stream_output_info *so ); - -#endif /* _NINE_VERTEXDECLARATION9_H_ */ diff --git a/src/gallium/state_trackers/nine/vertexshader9.c b/src/gallium/state_trackers/nine/vertexshader9.c deleted file mode 100644 index 600e298a393..00000000000 --- a/src/gallium/state_trackers/nine/vertexshader9.c +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "nine_helpers.h" -#include "nine_shader.h" - -#include "vertexdeclaration9.h" -#include "vertexshader9.h" - -#include "device9.h" -#include "pipe/p_context.h" -#include "cso_cache/cso_context.h" - -#define DBG_CHANNEL DBG_VERTEXSHADER - -HRESULT -NineVertexShader9_ctor( struct NineVertexShader9 *This, - struct NineUnknownParams *pParams, - const DWORD *pFunction, void *cso ) -{ - struct NineDevice9 *device; - struct nine_shader_info info; - struct pipe_context *pipe; - HRESULT hr; - unsigned i; - - DBG("This=%p pParams=%p pFunction=%p cso=%p\n", - This, pParams, pFunction, cso); - - hr = NineUnknown_ctor(&This->base, pParams); - if (FAILED(hr)) - return hr; - - if (cso) { - This->ff_cso = cso; - return D3D_OK; - } - - device = This->base.device; - - info.type = PIPE_SHADER_VERTEX; - info.byte_code = pFunction; - info.const_i_base = NINE_CONST_I_BASE(device->max_vs_const_f) / 16; - info.const_b_base = NINE_CONST_B_BASE(device->max_vs_const_f) / 16; - info.sampler_mask_shadow = 0x0; - info.sampler_ps1xtypes = 0x0; - info.fog_enable = 0; - info.point_size_min = 0; - info.point_size_max = 0; - info.add_constants_defs.c_combination = NULL; - info.add_constants_defs.int_const_added = NULL; - info.add_constants_defs.bool_const_added = NULL; - info.swvp_on = !!(device->params.BehaviorFlags & D3DCREATE_SOFTWARE_VERTEXPROCESSING); - info.process_vertices = false; - - pipe = nine_context_get_pipe_acquire(device); - hr = nine_translate_shader(device, &info, pipe); - if (hr == D3DERR_INVALIDCALL && - (device->params.BehaviorFlags & D3DCREATE_MIXED_VERTEXPROCESSING)) { - /* Retry with a swvp shader. It will require swvp to be on. */ - info.swvp_on = true; - hr = nine_translate_shader(device, &info, pipe); - } - nine_context_get_pipe_release(device); - if (hr == D3DERR_INVALIDCALL) - ERR("Encountered buggy shader\n"); - if (FAILED(hr)) - return hr; - This->byte_code.version = info.version; - This->swvp_only = info.swvp_on; - - This->byte_code.tokens = mem_dup(pFunction, info.byte_size); - if (!This->byte_code.tokens) - return E_OUTOFMEMORY; - This->byte_code.size = info.byte_size; - - This->variant.cso = info.cso; - This->variant.const_ranges = info.const_ranges; - This->variant.const_used_size = info.const_used_size; - This->last_cso = info.cso; - This->last_const_ranges = info.const_ranges; - This->last_const_used_size = info.const_used_size; - This->last_key = (uint32_t) (info.swvp_on << 9); - - This->lconstf = info.lconstf; - This->sampler_mask = info.sampler_mask; - This->position_t = info.position_t; - This->point_size = info.point_size; - - memcpy(This->int_slots_used, info.int_slots_used, sizeof(This->int_slots_used)); - memcpy(This->bool_slots_used, info.bool_slots_used, sizeof(This->bool_slots_used)); - - This->const_int_slots = info.const_int_slots; - This->const_bool_slots = info.const_bool_slots; - - This->c_combinations = NULL; - - for (i = 0; i < info.num_inputs && i < ARRAY_SIZE(This->input_map); ++i) - This->input_map[i].ndecl = info.input_map[i]; - This->num_inputs = i; - - return D3D_OK; -} - -void -NineVertexShader9_dtor( struct NineVertexShader9 *This ) -{ - DBG("This=%p\n", This); - - if (This->base.device) { - struct pipe_context *pipe = nine_context_get_pipe_multithread(This->base.device); - struct nine_shader_variant *var = &This->variant; - struct nine_shader_variant_so *var_so = &This->variant_so; - - do { - if (var->cso) { - if (This->base.device->context.cso_shader.vs == var->cso) - pipe->bind_vs_state(pipe, NULL); - pipe->delete_vs_state(pipe, var->cso); - FREE(var->const_ranges); - } - var = var->next; - } while (var); - - while (var_so && var_so->vdecl) { - if (var_so->cso) { - This->base.device->pipe_sw->delete_vs_state(This->base.device->pipe_sw, var_so->cso); - } - var_so = var_so->next; - } - - if (This->ff_cso) { - if (This->ff_cso == This->base.device->context.cso_shader.vs) - pipe->bind_vs_state(pipe, NULL); - pipe->delete_vs_state(pipe, This->ff_cso); - } - } - nine_shader_variants_free(&This->variant); - nine_shader_variants_so_free(&This->variant_so); - - nine_shader_constant_combination_free(This->c_combinations); - - FREE((void *)This->byte_code.tokens); /* const_cast */ - - FREE(This->lconstf.data); - FREE(This->lconstf.ranges); - - NineUnknown_dtor(&This->base); -} - -HRESULT NINE_WINAPI -NineVertexShader9_GetFunction( struct NineVertexShader9 *This, - void *pData, - UINT *pSizeOfData ) -{ - user_assert(pSizeOfData, D3DERR_INVALIDCALL); - - if (!pData) { - *pSizeOfData = This->byte_code.size; - return D3D_OK; - } - user_assert(*pSizeOfData >= This->byte_code.size, D3DERR_INVALIDCALL); - - memcpy(pData, This->byte_code.tokens, This->byte_code.size); - - return D3D_OK; -} - -void * -NineVertexShader9_GetVariant( struct NineVertexShader9 *This, - unsigned **const_ranges, - unsigned *const_used_size ) -{ - /* GetVariant is called from nine_context, thus we can - * get pipe directly */ - struct pipe_context *pipe = This->base.device->context.pipe; - void *cso; - uint64_t key; - - key = This->next_key; - if (key == This->last_key) { - *const_ranges = This->last_const_ranges; - *const_used_size = This->last_const_used_size; - return This->last_cso; - } - - cso = nine_shader_variant_get(&This->variant, const_ranges, const_used_size, key); - if (!cso) { - struct NineDevice9 *device = This->base.device; - struct nine_shader_info info; - HRESULT hr; - - info.type = PIPE_SHADER_VERTEX; - info.const_i_base = NINE_CONST_I_BASE(device->max_vs_const_f) / 16; - info.const_b_base = NINE_CONST_B_BASE(device->max_vs_const_f) / 16; - info.byte_code = This->byte_code.tokens; - info.sampler_mask_shadow = key & 0xf; - info.fog_enable = device->context.rs[D3DRS_FOGENABLE]; - info.point_size_min = asfloat(device->context.rs[D3DRS_POINTSIZE_MIN]); - info.point_size_max = asfloat(device->context.rs[D3DRS_POINTSIZE_MAX]); - info.add_constants_defs.c_combination = - nine_shader_constant_combination_get(This->c_combinations, (key >> 16) & 0xff); - info.add_constants_defs.int_const_added = &This->int_slots_used; - info.add_constants_defs.bool_const_added = &This->bool_slots_used; - info.swvp_on = device->context.swvp; - info.process_vertices = false; - - hr = nine_translate_shader(This->base.device, &info, pipe); - if (FAILED(hr)) - return NULL; - nine_shader_variant_add(&This->variant, key, info.cso, - info.const_ranges, info.const_used_size); - cso = info.cso; - *const_ranges = info.const_ranges; - *const_used_size = info.const_used_size; - } - - This->last_key = key; - This->last_cso = cso; - This->last_const_ranges = *const_ranges; - This->last_const_used_size = *const_used_size; - - return cso; -} - -void * -NineVertexShader9_GetVariantProcessVertices( struct NineVertexShader9 *This, - struct NineVertexDeclaration9 *vdecl_out, - struct pipe_stream_output_info *so ) -{ - struct nine_shader_info info; - HRESULT hr; - void *cso; - - cso = nine_shader_variant_so_get(&This->variant_so, vdecl_out, so); - if (cso) - return cso; - - info.type = PIPE_SHADER_VERTEX; - info.const_i_base = 0; - info.const_b_base = 0; - info.byte_code = This->byte_code.tokens; - info.sampler_mask_shadow = 0; - info.fog_enable = false; - info.point_size_min = 0; - info.point_size_max = 0; - info.add_constants_defs.c_combination = NULL; - info.add_constants_defs.int_const_added = NULL; - info.add_constants_defs.bool_const_added = NULL; - info.swvp_on = true; - info.vdecl_out = vdecl_out; - info.process_vertices = true; - hr = nine_translate_shader(This->base.device, &info, This->base.device->pipe_sw); - if (FAILED(hr)) - return NULL; - *so = info.so; - nine_shader_variant_so_add(&This->variant_so, vdecl_out, so, info.cso); - return info.cso; -} - -IDirect3DVertexShader9Vtbl NineVertexShader9_vtable = { - (void *)NineUnknown_QueryInterface, - (void *)NineUnknown_AddRef, - (void *)NineUnknown_Release, - (void *)NineUnknown_GetDevice, - (void *)NineVertexShader9_GetFunction -}; - -static const GUID *NineVertexShader9_IIDs[] = { - &IID_IDirect3DVertexShader9, - &IID_IUnknown, - NULL -}; - -HRESULT -NineVertexShader9_new( struct NineDevice9 *pDevice, - struct NineVertexShader9 **ppOut, - const DWORD *pFunction, void *cso ) -{ - if (cso) { - NINE_DEVICE_CHILD_BIND_NEW(VertexShader9, ppOut, pDevice, pFunction, cso); - } else { - NINE_DEVICE_CHILD_NEW(VertexShader9, ppOut, pDevice, pFunction, cso); - } -} diff --git a/src/gallium/state_trackers/nine/vertexshader9.h b/src/gallium/state_trackers/nine/vertexshader9.h deleted file mode 100644 index cbbd34979c9..00000000000 --- a/src/gallium/state_trackers/nine/vertexshader9.h +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef _NINE_VERTEXSHADER9_H_ -#define _NINE_VERTEXSHADER9_H_ - -#include "util/u_half.h" - -#include "iunknown.h" -#include "device9.h" -#include "nine_helpers.h" -#include "nine_shader.h" -#include "nine_state.h" - -struct NineVertexDeclaration9; - -struct NineVertexShader9 -{ - struct NineUnknown base; - struct nine_shader_variant variant; - - struct { - uint16_t ndecl; /* NINE_DECLUSAGE_x */ - } input_map[PIPE_MAX_ATTRIBS]; - unsigned num_inputs; - - struct { - const DWORD *tokens; - DWORD size; - uint8_t version; /* (major << 4) | minor */ - } byte_code; - - uint8_t sampler_mask; - - boolean position_t; /* if true, disable vport transform */ - boolean point_size; /* if true, set rasterizer.point_size_per_vertex to 1 */ - boolean swvp_only; - - struct nine_lconstf lconstf; - - boolean int_slots_used[NINE_MAX_CONST_I]; - boolean bool_slots_used[NINE_MAX_CONST_B]; - - unsigned const_int_slots; - unsigned const_bool_slots; - - struct nine_shader_constant_combination *c_combinations; - - uint64_t ff_key[3]; - void *ff_cso; - - uint64_t last_key; - void *last_cso; - unsigned *last_const_ranges; - unsigned last_const_used_size; /* in bytes */ - - uint64_t next_key; - - /* so */ - struct nine_shader_variant_so variant_so; -}; -static inline struct NineVertexShader9 * -NineVertexShader9( void *data ) -{ - return (struct NineVertexShader9 *)data; -} - -static inline BOOL -NineVertexShader9_UpdateKey( struct NineVertexShader9 *vs, - struct NineDevice9 *device ) -{ - struct nine_context *context = &(device->context); - uint8_t samplers_shadow; - uint64_t key; - BOOL res; - - samplers_shadow = (uint8_t)((context->samplers_shadow & NINE_VS_SAMPLERS_MASK) >> NINE_SAMPLER_VS(0)); - samplers_shadow &= vs->sampler_mask; - key = samplers_shadow; - - if (vs->byte_code.version < 0x30) - key |= (uint32_t) ((!!context->rs[D3DRS_FOGENABLE]) << 8); - key |= (uint32_t) (context->swvp << 9); - - if ((vs->const_int_slots > 0 || vs->const_bool_slots > 0) && context->inline_constants && !context->swvp) - key |= ((uint64_t)nine_shader_constant_combination_key(&vs->c_combinations, - vs->int_slots_used, - vs->bool_slots_used, - context->vs_const_i, - context->vs_const_b)) << 16; - - /* We want to use a 64 bits key for performance. - * Use compressed float16 values for the pointsize min/max in the key. - * Shaders do not usually output psize.*/ - if (vs->point_size) { - key |= ((uint64_t)util_float_to_half(asfloat(context->rs[D3DRS_POINTSIZE_MIN]))) << 32; - key |= ((uint64_t)util_float_to_half(asfloat(context->rs[D3DRS_POINTSIZE_MAX]))) << 48; - } - - res = vs->last_key != key; - if (res) - vs->next_key = key; - return res; -} - -void * -NineVertexShader9_GetVariant( struct NineVertexShader9 *vs, - unsigned **const_ranges, - unsigned *const_used_size ); - -void * -NineVertexShader9_GetVariantProcessVertices( struct NineVertexShader9 *vs, - struct NineVertexDeclaration9 *vdecl_out, - struct pipe_stream_output_info *so ); - -/*** public ***/ - -HRESULT -NineVertexShader9_new( struct NineDevice9 *pDevice, - struct NineVertexShader9 **ppOut, - const DWORD *pFunction, void *cso ); - -HRESULT -NineVertexShader9_ctor( struct NineVertexShader9 *, - struct NineUnknownParams *pParams, - const DWORD *pFunction, void *cso ); - -void -NineVertexShader9_dtor( struct NineVertexShader9 * ); - -HRESULT NINE_WINAPI -NineVertexShader9_GetFunction( struct NineVertexShader9 *This, - void *pData, - UINT *pSizeOfData ); - -#endif /* _NINE_VERTEXSHADER9_H_ */ diff --git a/src/gallium/state_trackers/nine/volume9.c b/src/gallium/state_trackers/nine/volume9.c deleted file mode 100644 index 4a3d0c88f10..00000000000 --- a/src/gallium/state_trackers/nine/volume9.c +++ /dev/null @@ -1,558 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "device9.h" -#include "volume9.h" -#include "basetexture9.h" /* for marking dirty */ -#include "volumetexture9.h" -#include "nine_helpers.h" -#include "nine_pipe.h" -#include "nine_dump.h" - -#include "util/format/u_format.h" -#include "util/u_surface.h" - -#define DBG_CHANNEL DBG_VOLUME - - -static HRESULT -NineVolume9_AllocateData( struct NineVolume9 *This ) -{ - unsigned size = This->layer_stride * This->desc.Depth; - - DBG("(%p(This=%p),level=%u) Allocating 0x%x bytes of system memory.\n", - This->base.container, This, This->level, size); - - This->data = (uint8_t *)align_calloc(size, 32); - if (!This->data) - return E_OUTOFMEMORY; - return D3D_OK; -} - -static HRESULT -NineVolume9_ctor( struct NineVolume9 *This, - struct NineUnknownParams *pParams, - struct NineUnknown *pContainer, - struct pipe_resource *pResource, - unsigned Level, - D3DVOLUME_DESC *pDesc ) -{ - HRESULT hr; - - assert(pContainer); /* stand-alone volumes can't be created */ - - DBG("This=%p pContainer=%p pDevice=%p pResource=%p Level=%u pDesc=%p\n", - This, pContainer, pParams->device, pResource, Level, pDesc); - - /* Mark this as a special surface held by another internal resource. */ - pParams->container = pContainer; - - user_assert(!(pDesc->Usage & D3DUSAGE_DYNAMIC) || - (pDesc->Pool != D3DPOOL_MANAGED), D3DERR_INVALIDCALL); - - assert(pResource || pDesc->Pool != D3DPOOL_DEFAULT); - - hr = NineUnknown_ctor(&This->base, pParams); - if (FAILED(hr)) - return hr; - - pipe_resource_reference(&This->resource, pResource); - - This->transfer = NULL; - This->lock_count = 0; - - This->level = Level; - This->level_actual = Level; - This->desc = *pDesc; - - This->info.screen = pParams->device->screen; - This->info.target = PIPE_TEXTURE_3D; - This->info.width0 = pDesc->Width; - This->info.height0 = pDesc->Height; - This->info.depth0 = pDesc->Depth; - This->info.last_level = 0; - This->info.array_size = 1; - This->info.nr_samples = 0; - This->info.nr_storage_samples = 0; - This->info.usage = PIPE_USAGE_DEFAULT; - This->info.bind = PIPE_BIND_SAMPLER_VIEW; - This->info.flags = 0; - This->info.format = d3d9_to_pipe_format_checked(This->info.screen, - pDesc->Format, - This->info.target, - This->info.nr_samples, - This->info.bind, FALSE, - pDesc->Pool == D3DPOOL_SCRATCH); - - if (This->info.format == PIPE_FORMAT_NONE) - return D3DERR_DRIVERINTERNALERROR; - - This->stride = util_format_get_stride(This->info.format, pDesc->Width); - This->stride = align(This->stride, 4); - This->layer_stride = util_format_get_2d_size(This->info.format, - This->stride, pDesc->Height); - - /* Get true format */ - This->format_internal = d3d9_to_pipe_format_checked(This->info.screen, - pDesc->Format, - This->info.target, - This->info.nr_samples, - This->info.bind, FALSE, - TRUE); - if (This->info.format != This->format_internal || - /* DYNAMIC Textures requires same stride as ram buffers. - * Do not use workaround by default as it eats more virtual space */ - (pParams->device->workarounds.dynamic_texture_workaround && - pDesc->Pool == D3DPOOL_DEFAULT && pDesc->Usage & D3DUSAGE_DYNAMIC)) { - This->stride_internal = nine_format_get_stride(This->format_internal, - pDesc->Width); - This->layer_stride_internal = util_format_get_2d_size(This->format_internal, - This->stride_internal, - pDesc->Height); - This->data_internal = align_calloc(This->layer_stride_internal * - This->desc.Depth, 32); - if (!This->data_internal) - return E_OUTOFMEMORY; - } - - if (!This->resource) { - hr = NineVolume9_AllocateData(This); - if (FAILED(hr)) - return hr; - } - return D3D_OK; -} - -static void -NineVolume9_dtor( struct NineVolume9 *This ) -{ - DBG("This=%p\n", This); - - if (This->transfer) { - struct pipe_context *pipe = nine_context_get_pipe_multithread(This->base.device); - pipe->transfer_unmap(pipe, This->transfer); - This->transfer = NULL; - } - - /* Note: Following condition cannot happen currently, since we - * refcount the volume in the functions increasing - * pending_uploads_counter. */ - if (p_atomic_read(&This->pending_uploads_counter)) - nine_csmt_process(This->base.device); - - if (This->data) - align_free(This->data); - if (This->data_internal) - align_free(This->data_internal); - - pipe_resource_reference(&This->resource, NULL); - - NineUnknown_dtor(&This->base); -} - -HRESULT NINE_WINAPI -NineVolume9_GetContainer( struct NineVolume9 *This, - REFIID riid, - void **ppContainer ) -{ - char guid_str[64]; - - DBG("This=%p riid=%p id=%s ppContainer=%p\n", - This, riid, riid ? GUID_sprintf(guid_str, riid) : "", ppContainer); - - (void)guid_str; - - if (!NineUnknown(This)->container) - return E_NOINTERFACE; - return NineUnknown_QueryInterface(NineUnknown(This)->container, riid, ppContainer); -} - -static inline void -NineVolume9_MarkContainerDirty( struct NineVolume9 *This ) -{ - struct NineBaseTexture9 *tex; -#if defined(DEBUG) || !defined(NDEBUG) - /* This is always contained by a NineVolumeTexture9. */ - GUID id = IID_IDirect3DVolumeTexture9; - REFIID ref = &id; - assert(NineUnknown_QueryInterface(This->base.container, ref, (void **)&tex) - == S_OK); - assert(NineUnknown_Release(NineUnknown(tex)) != 0); -#endif - - tex = NineBaseTexture9(This->base.container); - assert(tex); - if (This->desc.Pool == D3DPOOL_MANAGED) - tex->managed.dirty = TRUE; - - BASETEX_REGISTER_UPDATE(tex); -} - -HRESULT NINE_WINAPI -NineVolume9_GetDesc( struct NineVolume9 *This, - D3DVOLUME_DESC *pDesc ) -{ - user_assert(pDesc != NULL, E_POINTER); - *pDesc = This->desc; - return D3D_OK; -} - -inline void -NineVolume9_AddDirtyRegion( struct NineVolume9 *This, - const struct pipe_box *box ) -{ - D3DBOX dirty_region; - struct NineVolumeTexture9 *tex = NineVolumeTexture9(This->base.container); - - if (!box) { - NineVolumeTexture9_AddDirtyBox(tex, NULL); - } else { - dirty_region.Left = box->x << This->level_actual; - dirty_region.Top = box->y << This->level_actual; - dirty_region.Front = box->z << This->level_actual; - dirty_region.Right = dirty_region.Left + (box->width << This->level_actual); - dirty_region.Bottom = dirty_region.Top + (box->height << This->level_actual); - dirty_region.Back = dirty_region.Front + (box->depth << This->level_actual); - NineVolumeTexture9_AddDirtyBox(tex, &dirty_region); - } -} - -static inline unsigned -NineVolume9_GetSystemMemOffset(enum pipe_format format, unsigned stride, - unsigned layer_stride, - int x, int y, int z) -{ - unsigned x_offset = util_format_get_stride(format, x); - - y = util_format_get_nblocksy(format, y); - - return z * layer_stride + y * stride + x_offset; -} - -HRESULT NINE_WINAPI -NineVolume9_LockBox( struct NineVolume9 *This, - D3DLOCKED_BOX *pLockedVolume, - const D3DBOX *pBox, - DWORD Flags ) -{ - struct pipe_context *pipe; - struct pipe_resource *resource = This->resource; - struct pipe_box box; - unsigned usage; - - DBG("This=%p(%p) pLockedVolume=%p pBox=%p[%u..%u,%u..%u,%u..%u] Flags=%s\n", - This, This->base.container, pLockedVolume, pBox, - pBox ? pBox->Left : 0, pBox ? pBox->Right : 0, - pBox ? pBox->Top : 0, pBox ? pBox->Bottom : 0, - pBox ? pBox->Front : 0, pBox ? pBox->Back : 0, - nine_D3DLOCK_to_str(Flags)); - - /* check if it's already locked */ - user_assert(This->lock_count == 0, D3DERR_INVALIDCALL); - - /* set pBits to NULL after lock_count check */ - user_assert(pLockedVolume, E_POINTER); - pLockedVolume->pBits = NULL; - - user_assert(This->desc.Pool != D3DPOOL_DEFAULT || - (This->desc.Usage & D3DUSAGE_DYNAMIC), D3DERR_INVALIDCALL); - - user_assert(!((Flags & D3DLOCK_DISCARD) && (Flags & D3DLOCK_READONLY)), - D3DERR_INVALIDCALL); - - if (pBox && compressed_format (This->desc.Format)) { /* For volume all pools are checked */ - const unsigned w = util_format_get_blockwidth(This->info.format); - const unsigned h = util_format_get_blockheight(This->info.format); - user_assert((pBox->Left == 0 && pBox->Right == This->desc.Width && - pBox->Top == 0 && pBox->Bottom == This->desc.Height) || - (!(pBox->Left % w) && !(pBox->Right % w) && - !(pBox->Top % h) && !(pBox->Bottom % h)), - D3DERR_INVALIDCALL); - } - - if (Flags & D3DLOCK_DISCARD) { - usage = PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE; - } else { - usage = (Flags & D3DLOCK_READONLY) ? - PIPE_TRANSFER_READ : PIPE_TRANSFER_READ_WRITE; - } - if (Flags & D3DLOCK_DONOTWAIT) - usage |= PIPE_TRANSFER_DONTBLOCK; - - if (pBox) { - user_assert(pBox->Right > pBox->Left, D3DERR_INVALIDCALL); - user_assert(pBox->Bottom > pBox->Top, D3DERR_INVALIDCALL); - user_assert(pBox->Back > pBox->Front, D3DERR_INVALIDCALL); - user_assert(pBox->Right <= This->desc.Width, D3DERR_INVALIDCALL); - user_assert(pBox->Bottom <= This->desc.Height, D3DERR_INVALIDCALL); - user_assert(pBox->Back <= This->desc.Depth, D3DERR_INVALIDCALL); - - d3dbox_to_pipe_box(&box, pBox); - if (u_box_clip_2d(&box, &box, This->desc.Width, This->desc.Height) < 0) { - DBG("Locked volume intersection empty.\n"); - return D3DERR_INVALIDCALL; - } - } else { - u_box_3d(0, 0, 0, This->desc.Width, This->desc.Height, This->desc.Depth, - &box); - } - - if (p_atomic_read(&This->pending_uploads_counter)) - nine_csmt_process(This->base.device); - - if (This->data_internal || This->data) { - enum pipe_format format = This->info.format; - unsigned stride = This->stride; - unsigned layer_stride = This->layer_stride; - uint8_t *data = This->data; - if (This->data_internal) { - format = This->format_internal; - stride = This->stride_internal; - layer_stride = This->layer_stride_internal; - data = This->data_internal; - } - pLockedVolume->RowPitch = stride; - pLockedVolume->SlicePitch = layer_stride; - pLockedVolume->pBits = data + - NineVolume9_GetSystemMemOffset(format, stride, - layer_stride, - box.x, box.y, box.z); - } else { - bool no_refs = !p_atomic_read(&This->base.bind) && - !p_atomic_read(&This->base.container->bind); - if (no_refs) - pipe = nine_context_get_pipe_acquire(This->base.device); - else - pipe = NineDevice9_GetPipe(This->base.device); - pLockedVolume->pBits = - pipe->transfer_map(pipe, resource, This->level, usage, - &box, &This->transfer); - if (no_refs) - nine_context_get_pipe_release(This->base.device); - if (!This->transfer) { - if (Flags & D3DLOCK_DONOTWAIT) - return D3DERR_WASSTILLDRAWING; - return D3DERR_DRIVERINTERNALERROR; - } - pLockedVolume->RowPitch = This->transfer->stride; - pLockedVolume->SlicePitch = This->transfer->layer_stride; - } - - if (!(Flags & (D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_READONLY))) { - NineVolume9_MarkContainerDirty(This); - NineVolume9_AddDirtyRegion(This, &box); - } - - ++This->lock_count; - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineVolume9_UnlockBox( struct NineVolume9 *This ) -{ - struct pipe_context *pipe; - - DBG("This=%p lock_count=%u\n", This, This->lock_count); - user_assert(This->lock_count, D3DERR_INVALIDCALL); - if (This->transfer) { - pipe = nine_context_get_pipe_acquire(This->base.device); - pipe->transfer_unmap(pipe, This->transfer); - This->transfer = NULL; - nine_context_get_pipe_release(This->base.device); - } - --This->lock_count; - - if (This->data_internal) { - struct pipe_box box; - - u_box_3d(0, 0, 0, This->desc.Width, This->desc.Height, This->desc.Depth, - &box); - - - if (This->data) { - (void) util_format_translate_3d(This->info.format, - This->data, This->stride, - This->layer_stride, - 0, 0, 0, - This->format_internal, - This->data_internal, - This->stride_internal, - This->layer_stride_internal, - 0, 0, 0, - This->desc.Width, This->desc.Height, - This->desc.Depth); - } else { - nine_context_box_upload(This->base.device, - &This->pending_uploads_counter, - (struct NineUnknown *)This, - This->resource, - This->level, - &box, - This->format_internal, - This->data_internal, - This->stride_internal, - This->layer_stride_internal, - &box); - } - } - - return D3D_OK; -} - -/* When this function is called, we have already checked - * The copy regions fit the volumes */ -void -NineVolume9_CopyMemToDefault( struct NineVolume9 *This, - struct NineVolume9 *From, - unsigned dstx, unsigned dsty, unsigned dstz, - struct pipe_box *pSrcBox ) -{ - struct pipe_resource *r_dst = This->resource; - struct pipe_box src_box; - struct pipe_box dst_box; - - DBG("This=%p From=%p dstx=%u dsty=%u dstz=%u pSrcBox=%p\n", - This, From, dstx, dsty, dstz, pSrcBox); - - assert(This->desc.Pool == D3DPOOL_DEFAULT && - From->desc.Pool == D3DPOOL_SYSTEMMEM); - - dst_box.x = dstx; - dst_box.y = dsty; - dst_box.z = dstz; - - if (pSrcBox) { - src_box = *pSrcBox; - } else { - src_box.x = 0; - src_box.y = 0; - src_box.z = 0; - src_box.width = From->desc.Width; - src_box.height = From->desc.Height; - src_box.depth = From->desc.Depth; - } - - dst_box.width = src_box.width; - dst_box.height = src_box.height; - dst_box.depth = src_box.depth; - - nine_context_box_upload(This->base.device, - &From->pending_uploads_counter, - (struct NineUnknown *)From, - r_dst, - This->level, - &dst_box, - From->info.format, - From->data, From->stride, - From->layer_stride, - &src_box); - - if (This->data_internal) - (void) util_format_translate_3d(This->format_internal, - This->data_internal, - This->stride_internal, - This->layer_stride_internal, - dstx, dsty, dstz, - From->info.format, - From->data, From->stride, - From->layer_stride, - src_box.x, src_box.y, - src_box.z, - src_box.width, - src_box.height, - src_box.depth); - - NineVolume9_MarkContainerDirty(This); - - return; -} - -HRESULT -NineVolume9_UploadSelf( struct NineVolume9 *This, - const struct pipe_box *damaged ) -{ - struct pipe_resource *res = This->resource; - struct pipe_box box; - - DBG("This=%p damaged=%p data=%p res=%p\n", This, damaged, - This->data, res); - - assert(This->desc.Pool == D3DPOOL_MANAGED); - assert(res); - - if (damaged) { - box = *damaged; - } else { - box.x = 0; - box.y = 0; - box.z = 0; - box.width = This->desc.Width; - box.height = This->desc.Height; - box.depth = This->desc.Depth; - } - - nine_context_box_upload(This->base.device, - &This->pending_uploads_counter, - (struct NineUnknown *)This, - res, - This->level, - &box, - res->format, - This->data, This->stride, - This->layer_stride, - &box); - - return D3D_OK; -} - - -IDirect3DVolume9Vtbl NineVolume9_vtable = { - (void *)NineUnknown_QueryInterface, - (void *)NineUnknown_AddRef, - (void *)NineUnknown_Release, - (void *)NineUnknown_GetDevice, /* actually part of Volume9 iface */ - (void *)NineUnknown_SetPrivateData, - (void *)NineUnknown_GetPrivateData, - (void *)NineUnknown_FreePrivateData, - (void *)NineVolume9_GetContainer, - (void *)NineVolume9_GetDesc, - (void *)NineVolume9_LockBox, - (void *)NineVolume9_UnlockBox -}; - -static const GUID *NineVolume9_IIDs[] = { - &IID_IDirect3DVolume9, - &IID_IUnknown, - NULL -}; - -HRESULT -NineVolume9_new( struct NineDevice9 *pDevice, - struct NineUnknown *pContainer, - struct pipe_resource *pResource, - unsigned Level, - D3DVOLUME_DESC *pDesc, - struct NineVolume9 **ppOut ) -{ - NINE_DEVICE_CHILD_NEW(Volume9, ppOut, pDevice, /* args */ - pContainer, pResource, Level, pDesc); -} diff --git a/src/gallium/state_trackers/nine/volume9.h b/src/gallium/state_trackers/nine/volume9.h deleted file mode 100644 index 77060f22112..00000000000 --- a/src/gallium/state_trackers/nine/volume9.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef _NINE_VOLUME9_H_ -#define _NINE_VOLUME9_H_ - -#include "iunknown.h" - -#include "pipe/p_state.h" -#include "util/u_inlines.h" - -struct hash_table; - -struct NineDevice9; - -struct NineVolume9 -{ - struct NineUnknown base; - - struct pipe_resource *resource; - unsigned level; - unsigned level_actual; - - uint8_t *data; /* system memory backing */ - uint8_t *data_internal; /* for conversions */ - - D3DVOLUME_DESC desc; - struct pipe_resource info; - enum pipe_format format_internal; - unsigned stride; - unsigned stride_internal; - unsigned layer_stride; - unsigned layer_stride_internal; - - struct pipe_transfer *transfer; - unsigned lock_count; - - unsigned pending_uploads_counter; /* pending uploads */ -}; -static inline struct NineVolume9 * -NineVolume9( void *data ) -{ - return (struct NineVolume9 *)data; -} - -HRESULT -NineVolume9_new( struct NineDevice9 *pDevice, - struct NineUnknown *pContainer, - struct pipe_resource *pResource, - unsigned Level, - D3DVOLUME_DESC *pDesc, - struct NineVolume9 **ppOut ); - -/*** Nine private ***/ - -static inline void -NineVolume9_SetResource( struct NineVolume9 *This, - struct pipe_resource *resource, unsigned level ) -{ - This->level = level; - pipe_resource_reference(&This->resource, resource); -} - -void -NineVolume9_AddDirtyRegion( struct NineVolume9 *This, - const struct pipe_box *box ); - -void -NineVolume9_CopyMemToDefault( struct NineVolume9 *This, - struct NineVolume9 *From, - unsigned dstx, unsigned dsty, unsigned dstz, - struct pipe_box *pSrcBox ); - -HRESULT -NineVolume9_UploadSelf( struct NineVolume9 *This, - const struct pipe_box *damaged ); - - -/*** Direct3D public ***/ - -HRESULT NINE_WINAPI -NineVolume9_GetContainer( struct NineVolume9 *This, - REFIID riid, - void **ppContainer ); - -HRESULT NINE_WINAPI -NineVolume9_GetDesc( struct NineVolume9 *This, - D3DVOLUME_DESC *pDesc ); - -HRESULT NINE_WINAPI -NineVolume9_LockBox( struct NineVolume9 *This, - D3DLOCKED_BOX *pLockedVolume, - const D3DBOX *pBox, - DWORD Flags ); - -HRESULT NINE_WINAPI -NineVolume9_UnlockBox( struct NineVolume9 *This ); - -#endif /* _NINE_VOLUME9_H_ */ diff --git a/src/gallium/state_trackers/nine/volumetexture9.c b/src/gallium/state_trackers/nine/volumetexture9.c deleted file mode 100644 index c7191bce688..00000000000 --- a/src/gallium/state_trackers/nine/volumetexture9.c +++ /dev/null @@ -1,293 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "device9.h" -#include "volumetexture9.h" -#include "nine_helpers.h" -#include "nine_pipe.h" - -#define DBG_CHANNEL DBG_VOLUMETEXTURE - -static HRESULT -NineVolumeTexture9_ctor( struct NineVolumeTexture9 *This, - struct NineUnknownParams *pParams, - UINT Width, UINT Height, UINT Depth, UINT Levels, - DWORD Usage, - D3DFORMAT Format, - D3DPOOL Pool, - HANDLE *pSharedHandle ) -{ - struct pipe_resource *info = &This->base.base.info; - struct pipe_screen *screen = pParams->device->screen; - enum pipe_format pf; - unsigned l; - D3DVOLUME_DESC voldesc; - HRESULT hr; - - DBG("This=%p pParams=%p Width=%u Height=%u Depth=%u Levels=%u " - "Usage=%d Format=%d Pool=%d pSharedHandle=%p\n", - This, pParams, Width, Height, Depth, Levels, - Usage, Format, Pool, pSharedHandle); - - user_assert(Width && Height && Depth, D3DERR_INVALIDCALL); - - /* user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); */ - user_assert(!pSharedHandle, D3DERR_INVALIDCALL); /* TODO */ - - /* An IDirect3DVolume9 cannot be bound as a render target can it ? */ - user_assert(!(Usage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL)), - D3DERR_INVALIDCALL); - user_assert(!(Usage & D3DUSAGE_AUTOGENMIPMAP), D3DERR_INVALIDCALL); - - pf = d3d9_to_pipe_format_checked(screen, Format, PIPE_TEXTURE_3D, 0, - PIPE_BIND_SAMPLER_VIEW, FALSE, - Pool == D3DPOOL_SCRATCH); - - if (pf == PIPE_FORMAT_NONE) - return D3DERR_INVALIDCALL; - - /* We support ATI1 and ATI2 hacks only for 2D and Cube textures */ - if (Format == D3DFMT_ATI1 || Format == D3DFMT_ATI2) - return D3DERR_INVALIDCALL; - - if (compressed_format(Format)) { - const unsigned w = util_format_get_blockwidth(pf); - const unsigned h = util_format_get_blockheight(pf); - /* Compressed formats are not compressed on depth component */ - user_assert(!(Width % w) && !(Height % h), D3DERR_INVALIDCALL); - } - - info->screen = pParams->device->screen; - info->target = PIPE_TEXTURE_3D; - info->format = pf; - info->width0 = Width; - info->height0 = Height; - info->depth0 = Depth; - if (Levels) - info->last_level = Levels - 1; - else - info->last_level = util_logbase2(MAX2(MAX2(Width, Height), Depth)); - info->array_size = 1; - info->nr_samples = 0; - info->nr_storage_samples = 0; - info->bind = PIPE_BIND_SAMPLER_VIEW; - info->usage = PIPE_USAGE_DEFAULT; - info->flags = 0; - - if (Usage & D3DUSAGE_DYNAMIC) { - info->usage = PIPE_USAGE_DYNAMIC; - } - if (Usage & D3DUSAGE_SOFTWAREPROCESSING) - DBG("Application asked for Software Vertex Processing, " - "but this is unimplemented\n"); - - This->volumes = CALLOC(info->last_level + 1, sizeof(*This->volumes)); - if (!This->volumes) - return E_OUTOFMEMORY; - This->base.pstype = 3; - - hr = NineBaseTexture9_ctor(&This->base, pParams, NULL, - D3DRTYPE_VOLUMETEXTURE, Format, Pool, Usage); - if (FAILED(hr)) - return hr; - - voldesc.Format = Format; - voldesc.Type = D3DRTYPE_VOLUME; - voldesc.Usage = Usage; - voldesc.Pool = Pool; - for (l = 0; l <= info->last_level; ++l) { - voldesc.Width = u_minify(Width, l); - voldesc.Height = u_minify(Height, l); - voldesc.Depth = u_minify(Depth, l); - - hr = NineVolume9_new(This->base.base.base.device, NineUnknown(This), - This->base.base.resource, l, - &voldesc, &This->volumes[l]); - if (FAILED(hr)) - return hr; - } - - /* Textures start initially dirty */ - NineVolumeTexture9_AddDirtyBox(This, NULL); - - return D3D_OK; -} - -static void -NineVolumeTexture9_dtor( struct NineVolumeTexture9 *This ) -{ - unsigned l; - - DBG("This=%p\n", This); - - if (This->volumes) { - for (l = 0; l <= This->base.base.info.last_level; ++l) - if (This->volumes[l]) - NineUnknown_Destroy(&This->volumes[l]->base); - FREE(This->volumes); - } - - NineBaseTexture9_dtor(&This->base); -} - -HRESULT NINE_WINAPI -NineVolumeTexture9_GetLevelDesc( struct NineVolumeTexture9 *This, - UINT Level, - D3DVOLUME_DESC *pDesc ) -{ - user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); - - *pDesc = This->volumes[Level]->desc; - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineVolumeTexture9_GetVolumeLevel( struct NineVolumeTexture9 *This, - UINT Level, - IDirect3DVolume9 **ppVolumeLevel ) -{ - user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); - - NineUnknown_AddRef(NineUnknown(This->volumes[Level])); - *ppVolumeLevel = (IDirect3DVolume9 *)This->volumes[Level]; - - return D3D_OK; -} - -HRESULT NINE_WINAPI -NineVolumeTexture9_LockBox( struct NineVolumeTexture9 *This, - UINT Level, - D3DLOCKED_BOX *pLockedVolume, - const D3DBOX *pBox, - DWORD Flags ) -{ - DBG("This=%p Level=%u pLockedVolume=%p pBox=%p Flags=%d\n", - This, Level, pLockedVolume, pBox, Flags); - - user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); - - return NineVolume9_LockBox(This->volumes[Level], pLockedVolume, pBox, - Flags); -} - -HRESULT NINE_WINAPI -NineVolumeTexture9_UnlockBox( struct NineVolumeTexture9 *This, - UINT Level ) -{ - DBG("This=%p Level=%u\n", This, Level); - - user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); - - return NineVolume9_UnlockBox(This->volumes[Level]); -} - -HRESULT NINE_WINAPI -NineVolumeTexture9_AddDirtyBox( struct NineVolumeTexture9 *This, - const D3DBOX *pDirtyBox ) -{ - DBG("This=%p pDirtybox=%p\n", This, pDirtyBox); - - if (This->base.base.pool == D3DPOOL_DEFAULT) { - return D3D_OK; - } - - if (This->base.base.pool == D3DPOOL_MANAGED) { - This->base.managed.dirty = TRUE; - BASETEX_REGISTER_UPDATE(&This->base); - } - - if (!pDirtyBox) { - This->dirty_box.x = 0; - This->dirty_box.y = 0; - This->dirty_box.z = 0; - This->dirty_box.width = This->base.base.info.width0; - This->dirty_box.height = This->base.base.info.height0; - This->dirty_box.depth = This->base.base.info.depth0; - } else { - if (This->dirty_box.width == 0) { - d3dbox_to_pipe_box(&This->dirty_box, pDirtyBox); - } else { - struct pipe_box box; - d3dbox_to_pipe_box(&box, pDirtyBox); - u_box_union_3d(&This->dirty_box, &This->dirty_box, &box); - } - This->dirty_box.x = MAX2(This->dirty_box.x, 0); - This->dirty_box.y = MAX2(This->dirty_box.y, 0); - This->dirty_box.z = MAX2(This->dirty_box.z, 0); - This->dirty_box.width = MIN2(This->dirty_box.width, - This->base.base.info.width0 - This->dirty_box.x); - This->dirty_box.height = MIN2(This->dirty_box.height, - This->base.base.info.height0 - This->dirty_box.y); - This->dirty_box.depth = MIN2(This->dirty_box.depth, - This->base.base.info.depth0 - This->dirty_box.z); - } - return D3D_OK; -} - -IDirect3DVolumeTexture9Vtbl NineVolumeTexture9_vtable = { - (void *)NineUnknown_QueryInterface, - (void *)NineUnknown_AddRef, - (void *)NineUnknown_Release, - (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */ - (void *)NineUnknown_SetPrivateData, - (void *)NineUnknown_GetPrivateData, - (void *)NineUnknown_FreePrivateData, - (void *)NineResource9_SetPriority, - (void *)NineResource9_GetPriority, - (void *)NineBaseTexture9_PreLoad, - (void *)NineResource9_GetType, - (void *)NineBaseTexture9_SetLOD, - (void *)NineBaseTexture9_GetLOD, - (void *)NineBaseTexture9_GetLevelCount, - (void *)NineBaseTexture9_SetAutoGenFilterType, - (void *)NineBaseTexture9_GetAutoGenFilterType, - (void *)NineBaseTexture9_GenerateMipSubLevels, - (void *)NineVolumeTexture9_GetLevelDesc, - (void *)NineVolumeTexture9_GetVolumeLevel, - (void *)NineVolumeTexture9_LockBox, - (void *)NineVolumeTexture9_UnlockBox, - (void *)NineVolumeTexture9_AddDirtyBox -}; - -static const GUID *NineVolumeTexture9_IIDs[] = { - &IID_IDirect3DVolumeTexture9, - &IID_IDirect3DBaseTexture9, - &IID_IDirect3DResource9, - &IID_IUnknown, - NULL -}; - -HRESULT -NineVolumeTexture9_new( struct NineDevice9 *pDevice, - UINT Width, UINT Height, UINT Depth, UINT Levels, - DWORD Usage, - D3DFORMAT Format, - D3DPOOL Pool, - struct NineVolumeTexture9 **ppOut, - HANDLE *pSharedHandle ) -{ - NINE_DEVICE_CHILD_NEW(VolumeTexture9, ppOut, pDevice, - Width, Height, Depth, Levels, - Usage, Format, Pool, pSharedHandle); -} - diff --git a/src/gallium/state_trackers/nine/volumetexture9.h b/src/gallium/state_trackers/nine/volumetexture9.h deleted file mode 100644 index dfe564cfc18..00000000000 --- a/src/gallium/state_trackers/nine/volumetexture9.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2011 Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef _NINE_VOLUMETEXTURE9_H_ -#define _NINE_VOLUMETEXTURE9_H_ - -#include "basetexture9.h" -#include "volume9.h" - -struct NineVolumeTexture9 -{ - struct NineBaseTexture9 base; - struct NineVolume9 **volumes; - struct pipe_box dirty_box; -}; -static inline struct NineVolumeTexture9 * -NineVolumeTexture9( void *data ) -{ - return (struct NineVolumeTexture9 *)data; -} - -HRESULT -NineVolumeTexture9_new( struct NineDevice9 *pDevice, - UINT Width, UINT Height, UINT Depth, UINT Levels, - DWORD Usage, - D3DFORMAT Format, - D3DPOOL Pool, - struct NineVolumeTexture9 **ppOut, - HANDLE *pSharedHandle ); - -HRESULT NINE_WINAPI -NineVolumeTexture9_GetLevelDesc( struct NineVolumeTexture9 *This, - UINT Level, - D3DVOLUME_DESC *pDesc ); - -HRESULT NINE_WINAPI -NineVolumeTexture9_GetVolumeLevel( struct NineVolumeTexture9 *This, - UINT Level, - IDirect3DVolume9 **ppVolumeLevel ); - -HRESULT NINE_WINAPI -NineVolumeTexture9_LockBox( struct NineVolumeTexture9 *This, - UINT Level, - D3DLOCKED_BOX *pLockedVolume, - const D3DBOX *pBox, - DWORD Flags ); - -HRESULT NINE_WINAPI -NineVolumeTexture9_UnlockBox( struct NineVolumeTexture9 *This, - UINT Level ); - -HRESULT NINE_WINAPI -NineVolumeTexture9_AddDirtyBox( struct NineVolumeTexture9 *This, - const D3DBOX *pDirtyBox ); - -#endif /* _NINE_VOLUMETEXTURE9_H_ */ diff --git a/src/gallium/state_trackers/omx/Makefile.sources b/src/gallium/state_trackers/omx/Makefile.sources deleted file mode 100644 index 0fb1d9a4d76..00000000000 --- a/src/gallium/state_trackers/omx/Makefile.sources +++ /dev/null @@ -1,9 +0,0 @@ -C_SOURCES := \ - vid_dec_common.c \ - vid_dec_common.h \ - vid_dec_h264_common.c \ - vid_dec_h264_common.h \ - vid_omx_common.c \ - vid_omx_common.h \ - vid_enc_common.c \ - vid_enc_common.h diff --git a/src/gallium/state_trackers/omx/bellagio/Makefile.sources b/src/gallium/state_trackers/omx/bellagio/Makefile.sources deleted file mode 100644 index ab60ce803cb..00000000000 --- a/src/gallium/state_trackers/omx/bellagio/Makefile.sources +++ /dev/null @@ -1,10 +0,0 @@ -C_SOURCES := \ - entrypoint.c \ - entrypoint.h \ - vid_dec.c \ - vid_dec.h \ - vid_dec_mpeg12.c \ - vid_dec_h264.c \ - vid_dec_h265.c \ - vid_enc.c \ - vid_enc.h diff --git a/src/gallium/state_trackers/omx/bellagio/entrypoint.c b/src/gallium/state_trackers/omx/bellagio/entrypoint.c deleted file mode 100644 index 5c75e8dadaa..00000000000 --- a/src/gallium/state_trackers/omx/bellagio/entrypoint.c +++ /dev/null @@ -1,69 +0,0 @@ -/************************************************************************** - * - * Copyright 2013 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/* - * Authors: - * Christian König - * - */ - -#include "entrypoint.h" -#include "vid_dec.h" -#include "vid_enc.h" - -int omx_component_library_Setup(stLoaderComponentType **stComponents) -{ - OMX_ERRORTYPE r; - - if (stComponents == NULL) - return 2; - - /* component 0 - video decoder */ - r = vid_dec_LoaderComponent(stComponents[0]); - if (r != OMX_ErrorNone) - return OMX_ErrorInsufficientResources; - - /* component 1 - video encoder */ - r = vid_enc_LoaderComponent(stComponents[1]); - if (r != OMX_ErrorNone) - return OMX_ErrorInsufficientResources; - - return 2; -} - -OMX_ERRORTYPE omx_workaround_Destructor(OMX_COMPONENTTYPE *comp) -{ - omx_base_component_PrivateType* priv = (omx_base_component_PrivateType*)comp->pComponentPrivate; - - priv->state = OMX_StateInvalid; - tsem_up(priv->messageSem); - - /* wait for thread to exit */ - pthread_join(priv->messageHandlerThread, NULL); - - return omx_base_component_Destructor(comp); -} diff --git a/src/gallium/state_trackers/omx/bellagio/entrypoint.h b/src/gallium/state_trackers/omx/bellagio/entrypoint.h deleted file mode 100644 index d566d1eb5a3..00000000000 --- a/src/gallium/state_trackers/omx/bellagio/entrypoint.h +++ /dev/null @@ -1,45 +0,0 @@ -/************************************************************************** - * - * Copyright 2013 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/* - * Authors: - * Christian König - * - */ - -#ifndef OMX_ENTRYPOINT_H -#define OMX_ENTRYPOINT_H - -#include - -#include "vl/vl_winsys.h" - -PUBLIC extern int omx_component_library_Setup(stLoaderComponentType **stComponents); - -OMX_ERRORTYPE omx_workaround_Destructor(OMX_COMPONENTTYPE *comp); - -#endif diff --git a/src/gallium/state_trackers/omx/bellagio/vid_dec.c b/src/gallium/state_trackers/omx/bellagio/vid_dec.c deleted file mode 100644 index 2eedf937cd9..00000000000 --- a/src/gallium/state_trackers/omx/bellagio/vid_dec.c +++ /dev/null @@ -1,508 +0,0 @@ -/************************************************************************** - * - * Copyright 2013 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/* - * Authors: - * Christian König - * - */ - - -#include - -#include - -/* bellagio defines a DEBUG macro that we don't want */ -#ifndef DEBUG -#include -#undef DEBUG -#else -#include -#endif - -#include "pipe/p_screen.h" -#include "pipe/p_video_codec.h" -#include "util/u_memory.h" -#include "util/u_surface.h" -#include "vl/vl_video_buffer.h" -#include "vl/vl_vlc.h" - -#include "entrypoint.h" -#include "vid_dec.h" -#include "vid_omx_common.h" -#include "vid_dec_h264_common.h" - -static OMX_ERRORTYPE vid_dec_Constructor(OMX_COMPONENTTYPE *comp, OMX_STRING name); -static OMX_ERRORTYPE vid_dec_Destructor(OMX_COMPONENTTYPE *comp); -static OMX_ERRORTYPE vid_dec_SetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param); -static OMX_ERRORTYPE vid_dec_GetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param); -static OMX_ERRORTYPE vid_dec_MessageHandler(OMX_COMPONENTTYPE *comp, internalRequestMessageType *msg); -static OMX_ERRORTYPE vid_dec_DecodeBuffer(omx_base_PortType *port, OMX_BUFFERHEADERTYPE *buf); -static OMX_ERRORTYPE vid_dec_FreeDecBuffer(omx_base_PortType *port, OMX_U32 idx, OMX_BUFFERHEADERTYPE *buf); -static void vid_dec_FrameDecoded(OMX_COMPONENTTYPE *comp, OMX_BUFFERHEADERTYPE* input, OMX_BUFFERHEADERTYPE* output); - -OMX_ERRORTYPE vid_dec_LoaderComponent(stLoaderComponentType *comp) -{ - comp->componentVersion.s.nVersionMajor = 0; - comp->componentVersion.s.nVersionMinor = 0; - comp->componentVersion.s.nRevision = 0; - comp->componentVersion.s.nStep = 1; - comp->name_specific_length = 3; - - comp->name = CALLOC(1, OMX_MAX_STRINGNAME_SIZE); - if (comp->name == NULL) - goto error; - - comp->name_specific = CALLOC(comp->name_specific_length, sizeof(char *)); - if (comp->name_specific == NULL) - goto error; - - comp->role_specific = CALLOC(comp->name_specific_length, sizeof(char *)); - if (comp->role_specific == NULL) - goto error; - - comp->name_specific[0] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE); - if (comp->name_specific[0] == NULL) - goto error_specific; - - comp->name_specific[1] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE); - if (comp->name_specific[1] == NULL) - goto error_specific; - - comp->name_specific[2] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE); - if (comp->name_specific[2] == NULL) - goto error_specific; - - comp->role_specific[0] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE); - if (comp->role_specific[0] == NULL) - goto error_specific; - - comp->role_specific[1] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE); - if (comp->role_specific[1] == NULL) - goto error_specific; - - comp->role_specific[2] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE); - if (comp->role_specific[2] == NULL) - goto error_specific; - - strcpy(comp->name, OMX_VID_DEC_BASE_NAME); - strcpy(comp->name_specific[0], OMX_VID_DEC_MPEG2_NAME); - strcpy(comp->name_specific[1], OMX_VID_DEC_AVC_NAME); - strcpy(comp->name_specific[2], OMX_VID_DEC_HEVC_NAME); - - strcpy(comp->role_specific[0], OMX_VID_DEC_MPEG2_ROLE); - strcpy(comp->role_specific[1], OMX_VID_DEC_AVC_ROLE); - strcpy(comp->role_specific[2], OMX_VID_DEC_HEVC_ROLE); - - comp->constructor = vid_dec_Constructor; - - return OMX_ErrorNone; - -error_specific: - FREE(comp->role_specific[2]); - FREE(comp->role_specific[1]); - FREE(comp->role_specific[0]); - FREE(comp->name_specific[2]); - FREE(comp->name_specific[1]); - FREE(comp->name_specific[0]); - -error: - FREE(comp->role_specific); - FREE(comp->name_specific); - - FREE(comp->name); - - return OMX_ErrorInsufficientResources; -} - -static OMX_ERRORTYPE vid_dec_Constructor(OMX_COMPONENTTYPE *comp, OMX_STRING name) -{ - vid_dec_PrivateType *priv; - omx_base_video_PortType *port; - struct pipe_screen *screen; - OMX_ERRORTYPE r; - int i; - - assert(!comp->pComponentPrivate); - - priv = comp->pComponentPrivate = CALLOC(1, sizeof(vid_dec_PrivateType)); - if (!priv) - return OMX_ErrorInsufficientResources; - - r = omx_base_filter_Constructor(comp, name); - if (r) - return r; - - priv->profile = PIPE_VIDEO_PROFILE_UNKNOWN; - - if (!strcmp(name, OMX_VID_DEC_MPEG2_NAME)) - priv->profile = PIPE_VIDEO_PROFILE_MPEG2_MAIN; - - if (!strcmp(name, OMX_VID_DEC_AVC_NAME)) - priv->profile = PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH; - - if (!strcmp(name, OMX_VID_DEC_HEVC_NAME)) - priv->profile = PIPE_VIDEO_PROFILE_HEVC_MAIN; - - priv->BufferMgmtCallback = vid_dec_FrameDecoded; - priv->messageHandler = vid_dec_MessageHandler; - priv->destructor = vid_dec_Destructor; - - comp->SetParameter = vid_dec_SetParameter; - comp->GetParameter = vid_dec_GetParameter; - - priv->screen = omx_get_screen(); - if (!priv->screen) - return OMX_ErrorInsufficientResources; - - screen = priv->screen->pscreen; - priv->pipe = pipe_create_multimedia_context(screen); - if (!priv->pipe) - return OMX_ErrorInsufficientResources; - - if (!vl_compositor_init(&priv->compositor, priv->pipe)) { - priv->pipe->destroy(priv->pipe); - priv->pipe = NULL; - return OMX_ErrorInsufficientResources; - } - - if (!vl_compositor_init_state(&priv->cstate, priv->pipe)) { - vl_compositor_cleanup(&priv->compositor); - priv->pipe->destroy(priv->pipe); - priv->pipe = NULL; - return OMX_ErrorInsufficientResources; - } - - priv->sPortTypesParam[OMX_PortDomainVideo].nStartPortNumber = 0; - priv->sPortTypesParam[OMX_PortDomainVideo].nPorts = 2; - priv->ports = CALLOC(2, sizeof(omx_base_PortType *)); - if (!priv->ports) - return OMX_ErrorInsufficientResources; - - for (i = 0; i < 2; ++i) { - priv->ports[i] = CALLOC(1, sizeof(omx_base_video_PortType)); - if (!priv->ports[i]) - return OMX_ErrorInsufficientResources; - - base_video_port_Constructor(comp, &priv->ports[i], i, i == 0); - } - - port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; - strcpy(port->sPortParam.format.video.cMIMEType,"video/MPEG2"); - port->sPortParam.nBufferCountMin = 8; - port->sPortParam.nBufferCountActual = 8; - port->sPortParam.nBufferSize = DEFAULT_OUT_BUFFER_SIZE; - port->sPortParam.format.video.nFrameWidth = 176; - port->sPortParam.format.video.nFrameHeight = 144; - port->sPortParam.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG2; - port->sVideoParam.eCompressionFormat = OMX_VIDEO_CodingMPEG2; - port->Port_SendBufferFunction = vid_dec_DecodeBuffer; - port->Port_FreeBuffer = vid_dec_FreeDecBuffer; - - port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]; - port->sPortParam.nBufferCountActual = 8; - port->sPortParam.nBufferCountMin = 4; - port->sPortParam.format.video.nFrameWidth = 176; - port->sPortParam.format.video.nFrameHeight = 144; - port->sPortParam.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; - port->sVideoParam.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; - - return OMX_ErrorNone; -} - -static OMX_ERRORTYPE vid_dec_Destructor(OMX_COMPONENTTYPE *comp) -{ - vid_dec_PrivateType* priv = comp->pComponentPrivate; - int i; - - if (priv->ports) { - for (i = 0; i < priv->sPortTypesParam[OMX_PortDomainVideo].nPorts; ++i) { - if(priv->ports[i]) - priv->ports[i]->PortDestructor(priv->ports[i]); - } - FREE(priv->ports); - priv->ports=NULL; - } - - if (priv->pipe) { - vl_compositor_cleanup_state(&priv->cstate); - vl_compositor_cleanup(&priv->compositor); - priv->pipe->destroy(priv->pipe); - } - - if (priv->screen) - omx_put_screen(); - - return omx_workaround_Destructor(comp); -} - -static OMX_ERRORTYPE vid_dec_SetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param) -{ - OMX_COMPONENTTYPE *comp = handle; - vid_dec_PrivateType *priv = comp->pComponentPrivate; - OMX_ERRORTYPE r; - - if (!param) - return OMX_ErrorBadParameter; - - switch(idx) { - case OMX_IndexParamPortDefinition: { - OMX_PARAM_PORTDEFINITIONTYPE *def = param; - - r = omx_base_component_SetParameter(handle, idx, param); - if (r) - return r; - - if (def->nPortIndex == OMX_BASE_FILTER_INPUTPORT_INDEX) { - omx_base_video_PortType *port; - unsigned framesize = def->format.video.nFrameWidth * def->format.video.nFrameHeight; - - port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; - port->sPortParam.nBufferSize = framesize * 512 / (16*16); - - port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]; - port->sPortParam.format.video.nFrameWidth = def->format.video.nFrameWidth; - port->sPortParam.format.video.nFrameHeight = def->format.video.nFrameHeight; - port->sPortParam.format.video.nStride = def->format.video.nFrameWidth; - port->sPortParam.format.video.nSliceHeight = def->format.video.nFrameHeight; - port->sPortParam.nBufferSize = framesize*3/2; - - priv->callbacks->EventHandler(comp, priv->callbackData, OMX_EventPortSettingsChanged, - OMX_BASE_FILTER_OUTPUTPORT_INDEX, 0, NULL); - } - break; - } - case OMX_IndexParamStandardComponentRole: { - OMX_PARAM_COMPONENTROLETYPE *role = param; - - r = checkHeader(param, sizeof(OMX_PARAM_COMPONENTROLETYPE)); - if (r) - return r; - - if (!strcmp((char *)role->cRole, OMX_VID_DEC_MPEG2_ROLE)) { - priv->profile = PIPE_VIDEO_PROFILE_MPEG2_MAIN; - } else if (!strcmp((char *)role->cRole, OMX_VID_DEC_AVC_ROLE)) { - priv->profile = PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH; - } else if (!strcmp((char *)role->cRole, OMX_VID_DEC_HEVC_ROLE)) { - priv->profile = PIPE_VIDEO_PROFILE_HEVC_MAIN; - } else { - return OMX_ErrorBadParameter; - } - - break; - } - case OMX_IndexParamVideoPortFormat: { - OMX_VIDEO_PARAM_PORTFORMATTYPE *format = param; - omx_base_video_PortType *port; - - r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); - if (r) - return r; - - if (format->nPortIndex > 1) - return OMX_ErrorBadPortIndex; - - port = (omx_base_video_PortType *)priv->ports[format->nPortIndex]; - memcpy(&port->sVideoParam, format, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); - break; - } - default: - return omx_base_component_SetParameter(handle, idx, param); - } - return OMX_ErrorNone; -} - -static OMX_ERRORTYPE vid_dec_GetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param) -{ - OMX_COMPONENTTYPE *comp = handle; - vid_dec_PrivateType *priv = comp->pComponentPrivate; - OMX_ERRORTYPE r; - - if (!param) - return OMX_ErrorBadParameter; - - switch(idx) { - case OMX_IndexParamStandardComponentRole: { - OMX_PARAM_COMPONENTROLETYPE *role = param; - - r = checkHeader(param, sizeof(OMX_PARAM_COMPONENTROLETYPE)); - if (r) - return r; - - if (priv->profile == PIPE_VIDEO_PROFILE_MPEG2_MAIN) - strcpy((char *)role->cRole, OMX_VID_DEC_MPEG2_ROLE); - else if (priv->profile == PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH) - strcpy((char *)role->cRole, OMX_VID_DEC_AVC_ROLE); - else if (priv->profile == PIPE_VIDEO_PROFILE_HEVC_MAIN) - strcpy((char *)role->cRole, OMX_VID_DEC_HEVC_ROLE); - - break; - } - - case OMX_IndexParamVideoInit: - r = checkHeader(param, sizeof(OMX_PORT_PARAM_TYPE)); - if (r) - return r; - - memcpy(param, &priv->sPortTypesParam[OMX_PortDomainVideo], sizeof(OMX_PORT_PARAM_TYPE)); - break; - - case OMX_IndexParamVideoPortFormat: { - OMX_VIDEO_PARAM_PORTFORMATTYPE *format = param; - omx_base_video_PortType *port; - - r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); - if (r) - return r; - - if (format->nPortIndex > 1) - return OMX_ErrorBadPortIndex; - - port = (omx_base_video_PortType *)priv->ports[format->nPortIndex]; - memcpy(format, &port->sVideoParam, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); - break; - } - - default: - return omx_base_component_GetParameter(handle, idx, param); - - } - return OMX_ErrorNone; -} - -static OMX_ERRORTYPE vid_dec_MessageHandler(OMX_COMPONENTTYPE* comp, internalRequestMessageType *msg) -{ - vid_dec_PrivateType* priv = comp->pComponentPrivate; - - if (msg->messageType == OMX_CommandStateSet) { - if ((msg->messageParam == OMX_StateIdle ) && (priv->state == OMX_StateLoaded)) { - if (priv->profile == PIPE_VIDEO_PROFILE_MPEG2_MAIN) - vid_dec_mpeg12_Init(priv); - else if (priv->profile == PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH) - vid_dec_h264_Init(priv); - else if (priv->profile == PIPE_VIDEO_PROFILE_HEVC_MAIN) - vid_dec_h265_Init(priv); - - } else if ((msg->messageParam == OMX_StateLoaded) && (priv->state == OMX_StateIdle)) { - if (priv->shadow) { - priv->shadow->destroy(priv->shadow); - priv->shadow = NULL; - } - if (priv->codec) { - priv->codec->destroy(priv->codec); - priv->codec = NULL; - } - } - } - - return omx_base_component_MessageHandler(comp, msg); -} - -static OMX_ERRORTYPE vid_dec_DecodeBuffer(omx_base_PortType *port, OMX_BUFFERHEADERTYPE *buf) -{ - OMX_COMPONENTTYPE* comp = port->standCompContainer; - vid_dec_PrivateType *priv = comp->pComponentPrivate; - unsigned i = priv->num_in_buffers++; - OMX_ERRORTYPE r; - - priv->in_buffers[i] = buf; - priv->sizes[i] = buf->nFilledLen; - priv->inputs[i] = buf->pBuffer; - priv->timestamps[i] = buf->nTimeStamp; - - while (priv->num_in_buffers > (!!(buf->nFlags & OMX_BUFFERFLAG_EOS) ? 0 : 1)) { - bool eos = !!(priv->in_buffers[0]->nFlags & OMX_BUFFERFLAG_EOS); - unsigned min_bits_left = eos ? 32 : MAX2(buf->nFilledLen * 8, 32); - struct vl_vlc vlc; - - vl_vlc_init(&vlc, priv->num_in_buffers, priv->inputs, priv->sizes); - - if (priv->slice) - priv->bytes_left = vl_vlc_bits_left(&vlc) / 8; - - while (vl_vlc_bits_left(&vlc) > min_bits_left) { - priv->Decode(priv, &vlc, min_bits_left); - vl_vlc_fillbits(&vlc); - } - - if (priv->slice) { - unsigned bytes = priv->bytes_left - vl_vlc_bits_left(&vlc) / 8; - - priv->codec->decode_bitstream(priv->codec, priv->target, &priv->picture.base, - 1, &priv->slice, &bytes); - - if (priv->num_in_buffers) - priv->slice = priv->inputs[1]; - else - priv->slice = NULL; - } - - if (eos && priv->frame_started) - priv->EndFrame(priv); - - if (priv->frame_finished) { - priv->frame_finished = false; - priv->in_buffers[0]->nFilledLen = priv->in_buffers[0]->nAllocLen; - r = base_port_SendBufferFunction(port, priv->in_buffers[0]); - } else if (eos) { - vid_dec_FreeInputPortPrivate(priv->in_buffers[0]); - priv->in_buffers[0]->nFilledLen = priv->in_buffers[0]->nAllocLen; - r = base_port_SendBufferFunction(port, priv->in_buffers[0]); - } else { - priv->in_buffers[0]->nFilledLen = 0; - r = port->ReturnBufferFunction(port, priv->in_buffers[0]); - } - - if (--priv->num_in_buffers) { - unsigned delta = MIN2((min_bits_left - vl_vlc_bits_left(&vlc)) / 8, priv->sizes[1]); - - priv->in_buffers[0] = priv->in_buffers[1]; - priv->sizes[0] = priv->sizes[1] - delta; - priv->inputs[0] = priv->inputs[1] + delta; - priv->timestamps[0] = priv->timestamps[1]; - } - - if (r) - return r; - } - - return OMX_ErrorNone; -} - -static OMX_ERRORTYPE vid_dec_FreeDecBuffer(omx_base_PortType *port, OMX_U32 idx, OMX_BUFFERHEADERTYPE *buf) -{ - vid_dec_FreeInputPortPrivate(buf); - return base_port_FreeBuffer(port, idx, buf); -} - -static void vid_dec_FrameDecoded(OMX_COMPONENTTYPE *comp, OMX_BUFFERHEADERTYPE* input, - OMX_BUFFERHEADERTYPE* output) -{ - vid_dec_PrivateType *priv = comp->pComponentPrivate; - - vid_dec_FrameDecoded_common(priv, input, output); -} diff --git a/src/gallium/state_trackers/omx/bellagio/vid_dec.h b/src/gallium/state_trackers/omx/bellagio/vid_dec.h deleted file mode 100644 index 247217810b5..00000000000 --- a/src/gallium/state_trackers/omx/bellagio/vid_dec.h +++ /dev/null @@ -1,70 +0,0 @@ -/************************************************************************** - * - * Copyright 2013 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/* - * Authors: - * Christian König - * - */ - -#ifndef OMX_VID_DEC_H -#define OMX_VID_DEC_H - -#include - -#include -#include - -#include "os/os_thread.h" - -#include "vid_dec_common.h" - -#define OMX_VID_DEC_BASE_NAME "OMX.mesa.video_decoder" - -#define OMX_VID_DEC_MPEG2_NAME "OMX.mesa.video_decoder.mpeg2" -#define OMX_VID_DEC_MPEG2_ROLE "video_decoder.mpeg2" - -#define OMX_VID_DEC_AVC_NAME "OMX.mesa.video_decoder.avc" -#define OMX_VID_DEC_AVC_ROLE "video_decoder.avc" - -#define OMX_VID_DEC_HEVC_NAME "OMX.mesa.video_decoder.hevc" -#define OMX_VID_DEC_HEVC_ROLE "video_decoder.hevc" - -#define OMX_VID_DEC_TIMESTAMP_INVALID ((OMX_TICKS) -1) - -OMX_ERRORTYPE vid_dec_LoaderComponent(stLoaderComponentType *comp); - -/* vid_dec_mpeg12.c */ -void vid_dec_mpeg12_Init(vid_dec_PrivateType *priv); - -/* vid_dec_h264.c */ -void vid_dec_h264_Init(vid_dec_PrivateType *priv); - -/* vid_dec_h265.c */ -void vid_dec_h265_Init(vid_dec_PrivateType *priv); - -#endif diff --git a/src/gallium/state_trackers/omx/bellagio/vid_dec_h264.c b/src/gallium/state_trackers/omx/bellagio/vid_dec_h264.c deleted file mode 100644 index 1a198a97e96..00000000000 --- a/src/gallium/state_trackers/omx/bellagio/vid_dec_h264.c +++ /dev/null @@ -1,55 +0,0 @@ -/************************************************************************** - * - * Copyright 2013 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/* - * Authors: - * Christian König - * - */ - -#include "pipe/p_video_codec.h" -#include "util/u_memory.h" -#include "util/u_video.h" -#include "vl/vl_rbsp.h" -#include "vl/vl_zscan.h" - -#include "entrypoint.h" -#include "vid_dec.h" -#include "vid_dec_h264_common.h" - -void vid_dec_h264_Init(vid_dec_PrivateType *priv) -{ - priv->picture.base.profile = PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH; - - priv->Decode = vid_dec_h264_Decode; - priv->EndFrame = vid_dec_h264_EndFrame; - priv->Flush = vid_dec_h264_Flush; - - list_inithead(&priv->codec_data.h264.dpb_list); - priv->picture.h264.field_order_cnt[0] = priv->picture.h264.field_order_cnt[1] = INT_MAX; - priv->first_buf_in_frame = true; -} diff --git a/src/gallium/state_trackers/omx/bellagio/vid_dec_h265.c b/src/gallium/state_trackers/omx/bellagio/vid_dec_h265.c deleted file mode 100644 index c50be7804cb..00000000000 --- a/src/gallium/state_trackers/omx/bellagio/vid_dec_h265.c +++ /dev/null @@ -1,1013 +0,0 @@ -/************************************************************************** - * - * Copyright 2016 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include "pipe/p_video_codec.h" -#include "util/u_memory.h" -#include "util/u_video.h" -#include "vl/vl_rbsp.h" - -#include "entrypoint.h" -#include "vid_dec.h" - -#define DPB_MAX_SIZE 32 -#define MAX_NUM_REF_PICS 16 - -enum { - NAL_UNIT_TYPE_TRAIL_N = 0, - NAL_UNIT_TYPE_TRAIL_R = 1, - NAL_UNIT_TYPE_TSA_N = 2, - NAL_UNIT_TYPE_TSA_R = 3, - NAL_UNIT_TYPE_STSA_N = 4, - NAL_UNIT_TYPE_STSA_R = 5, - NAL_UNIT_TYPE_RADL_N = 6, - NAL_UNIT_TYPE_RADL_R = 7, - NAL_UNIT_TYPE_RASL_N = 8, - NAL_UNIT_TYPE_RASL_R = 9, - NAL_UNIT_TYPE_BLA_W_LP = 16, - NAL_UNIT_TYPE_BLA_W_RADL = 17, - NAL_UNIT_TYPE_BLA_N_LP = 18, - NAL_UNIT_TYPE_IDR_W_RADL = 19, - NAL_UNIT_TYPE_IDR_N_LP = 20, - NAL_UNIT_TYPE_CRA = 21, - NAL_UNIT_TYPE_SPS = 33, - NAL_UNIT_TYPE_PPS = 34, -}; - -static const uint8_t Default_8x8_Intra[64] = { - 16, 16, 16, 16, 17, 18, 21, 24, - 16, 16, 16, 16, 17, 19, 22, 25, - 16, 16, 17, 18, 20, 22, 25, 29, - 16, 16, 18, 21, 24, 27, 31, 36, - 17, 17, 20, 24, 30, 35, 41, 47, - 18, 19, 22, 27, 35, 44, 54, 65, - 21, 22, 25, 31, 41, 54, 70, 88, - 24, 25, 29, 36, 47, 65, 88, 115 -}; - -static const uint8_t Default_8x8_Inter[64] = { - 16, 16, 16, 16, 17, 18, 20, 24, - 16, 16, 16, 17, 18, 20, 24, 25, - 16, 16, 17, 18, 20, 24, 25, 28, - 16, 17, 18, 20, 24, 25, 28, 33, - 17, 18, 20, 24, 25, 28, 33, 41, - 18, 20, 24, 25, 28, 33, 41, 54, - 20, 24, 25, 28, 33, 41, 54, 71, - 24, 25, 28, 33, 41, 54, 71, 91 -}; - -struct dpb_list { - struct list_head list; - struct pipe_video_buffer *buffer; - OMX_TICKS timestamp; - unsigned poc; -}; - -struct ref_pic_set { - unsigned num_pics; - unsigned num_neg_pics; - unsigned num_pos_pics; - unsigned num_delta_poc; - int delta_poc[MAX_NUM_REF_PICS]; - bool used[MAX_NUM_REF_PICS]; -}; - -static bool is_idr_picture(unsigned nal_unit_type) -{ - return (nal_unit_type == NAL_UNIT_TYPE_IDR_W_RADL || - nal_unit_type == NAL_UNIT_TYPE_IDR_N_LP); -} - -/* broken link access picture */ -static bool is_bla_picture(unsigned nal_unit_type) -{ - return (nal_unit_type == NAL_UNIT_TYPE_BLA_W_LP || - nal_unit_type == NAL_UNIT_TYPE_BLA_W_RADL || - nal_unit_type == NAL_UNIT_TYPE_BLA_N_LP); -} - -/* random access point picture */ -static bool is_rap_picture(unsigned nal_unit_type) -{ - return (nal_unit_type >= NAL_UNIT_TYPE_BLA_W_LP && - nal_unit_type <= NAL_UNIT_TYPE_CRA); -} - -static bool is_slice_picture(unsigned nal_unit_type) -{ - return (nal_unit_type <= NAL_UNIT_TYPE_RASL_R || - is_rap_picture(nal_unit_type)); -} - -static void set_poc(vid_dec_PrivateType *priv, - unsigned nal_unit_type, int i) -{ - priv->picture.h265.CurrPicOrderCntVal = i; - - if (priv->codec_data.h265.temporal_id == 0 && - (nal_unit_type == NAL_UNIT_TYPE_TRAIL_R || - nal_unit_type == NAL_UNIT_TYPE_TSA_R || - nal_unit_type == NAL_UNIT_TYPE_STSA_R || - is_rap_picture(nal_unit_type))) - priv->codec_data.h265.slice_prev_poc = i; -} - -static unsigned get_poc(vid_dec_PrivateType *priv) -{ - return priv->picture.h265.CurrPicOrderCntVal; -} - -static void profile_tier(struct vl_rbsp *rbsp) -{ - int i; - - /* general_profile_space */ - vl_rbsp_u(rbsp, 2); - - /* general_tier_flag */ - vl_rbsp_u(rbsp, 1); - - /* general_profile_idc */ - vl_rbsp_u(rbsp, 5); - - /* general_profile_compatibility_flag */ - for(i = 0; i < 32; ++i) - vl_rbsp_u(rbsp, 1); - - /* general_progressive_source_flag */ - vl_rbsp_u(rbsp, 1); - - /* general_interlaced_source_flag */ - vl_rbsp_u(rbsp, 1); - - /* general_non_packed_constraint_flag */ - vl_rbsp_u(rbsp, 1); - - /* general_frame_only_constraint_flag */ - vl_rbsp_u(rbsp, 1); - - /* general_reserved_zero_44bits */ - vl_rbsp_u(rbsp, 16); - vl_rbsp_u(rbsp, 16); - vl_rbsp_u(rbsp, 12); -} - -static unsigned profile_tier_level(struct vl_rbsp *rbsp, - int max_sublayers_minus1) -{ - bool sub_layer_profile_present_flag[6]; - bool sub_layer_level_present_flag[6]; - unsigned level_idc; - int i; - - profile_tier(rbsp); - - /* general_level_idc */ - level_idc = vl_rbsp_u(rbsp, 8); - - for (i = 0; i < max_sublayers_minus1; ++i) { - sub_layer_profile_present_flag[i] = vl_rbsp_u(rbsp, 1); - sub_layer_level_present_flag[i] = vl_rbsp_u(rbsp, 1); - } - - if (max_sublayers_minus1 > 0) - for (i = max_sublayers_minus1; i < 8; ++i) - /* reserved_zero_2bits */ - vl_rbsp_u(rbsp, 2); - - for (i = 0; i < max_sublayers_minus1; ++i) { - if (sub_layer_profile_present_flag[i]) - profile_tier(rbsp); - - if (sub_layer_level_present_flag[i]) - /* sub_layer_level_idc */ - vl_rbsp_u(rbsp, 8); - } - - return level_idc; -} - -static void scaling_list_data(vid_dec_PrivateType *priv, - struct vl_rbsp *rbsp, struct pipe_h265_sps *sps) -{ - unsigned size_id, matrix_id; - unsigned scaling_list_len[4] = { 16, 64, 64, 64 }; - uint8_t scaling_list4x4[6][64] = { }; - int i; - - uint8_t (*scaling_list_data[4])[6][64] = { - (uint8_t (*)[6][64])scaling_list4x4, - (uint8_t (*)[6][64])sps->ScalingList8x8, - (uint8_t (*)[6][64])sps->ScalingList16x16, - (uint8_t (*)[6][64])sps->ScalingList32x32 - }; - uint8_t (*scaling_list_dc_coeff[2])[6] = { - (uint8_t (*)[6])sps->ScalingListDCCoeff16x16, - (uint8_t (*)[6])sps->ScalingListDCCoeff32x32 - }; - - for (size_id = 0; size_id < 4; ++size_id) { - - for (matrix_id = 0; matrix_id < ((size_id == 3) ? 2 : 6); ++matrix_id) { - bool scaling_list_pred_mode_flag = vl_rbsp_u(rbsp, 1); - - if (!scaling_list_pred_mode_flag) { - /* scaling_list_pred_matrix_id_delta */; - unsigned matrix_id_with_delta = matrix_id - vl_rbsp_ue(rbsp); - - if (matrix_id != matrix_id_with_delta) { - memcpy((*scaling_list_data[size_id])[matrix_id], - (*scaling_list_data[size_id])[matrix_id_with_delta], - scaling_list_len[size_id]); - if (size_id > 1) - (*scaling_list_dc_coeff[size_id - 2])[matrix_id] = - (*scaling_list_dc_coeff[size_id - 2])[matrix_id_with_delta]; - } else { - const uint8_t *d; - - if (size_id == 0) - memset((*scaling_list_data[0])[matrix_id], 16, 16); - else { - if (size_id < 3) - d = (matrix_id < 3) ? Default_8x8_Intra : Default_8x8_Inter; - else - d = (matrix_id < 1) ? Default_8x8_Intra : Default_8x8_Inter; - memcpy((*scaling_list_data[size_id])[matrix_id], d, - scaling_list_len[size_id]); - } - if (size_id > 1) - (*scaling_list_dc_coeff[size_id - 2])[matrix_id] = 16; - } - } else { - int next_coef = 8; - int coef_num = MIN2(64, (1 << (4 + (size_id << 1)))); - - if (size_id > 1) { - /* scaling_list_dc_coef_minus8 */ - next_coef = vl_rbsp_se(rbsp) + 8; - (*scaling_list_dc_coeff[size_id - 2])[matrix_id] = next_coef; - } - - for (i = 0; i < coef_num; ++i) { - /* scaling_list_delta_coef */ - next_coef = (next_coef + vl_rbsp_se(rbsp) + 256) % 256; - (*scaling_list_data[size_id])[matrix_id][i] = next_coef; - } - } - } - } - - for (i = 0; i < 6; ++i) - memcpy(sps->ScalingList4x4[i], scaling_list4x4[i], 16); - - return; -} - -static void st_ref_pic_set(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp, - struct ref_pic_set *rps, struct pipe_h265_sps *sps, - unsigned idx) -{ - bool inter_rps_pred_flag; - unsigned delta_idx_minus1; - int delta_poc; - int i; - - inter_rps_pred_flag = (idx != 0) ? (vl_rbsp_u(rbsp, 1)) : false; - - if (inter_rps_pred_flag) { - struct ref_pic_set *ref_rps; - unsigned sign, abs; - int delta_rps; - bool used; - int j; - - if (idx == sps->num_short_term_ref_pic_sets) - delta_idx_minus1 = vl_rbsp_ue(rbsp); - else - delta_idx_minus1 = 0; - - ref_rps = (struct ref_pic_set *) - priv->codec_data.h265.ref_pic_set_list + idx - (delta_idx_minus1 + 1); - - /* delta_rps_sign */ - sign = vl_rbsp_u(rbsp, 1); - /* abs_delta_rps_minus1 */ - abs = vl_rbsp_ue(rbsp); - delta_rps = (1 - 2 * sign) * (abs + 1); - - rps->num_neg_pics = 0; - rps->num_pos_pics = 0; - rps->num_pics = 0; - - for(i = 0 ; i <= ref_rps->num_pics; ++i) { - /* used_by_curr_pic_flag */ - if (!vl_rbsp_u(rbsp, 1)) - /* use_delta_flag */ - vl_rbsp_u(rbsp, 1); - else { - delta_poc = delta_rps + - ((i < ref_rps->num_pics)? ref_rps->delta_poc[i] : 0); - rps->delta_poc[rps->num_pics] = delta_poc; - rps->used[rps->num_pics] = true; - if (delta_poc < 0) - rps->num_neg_pics++; - else - rps->num_pos_pics++; - rps->num_pics++; - } - } - - rps->num_delta_poc = ref_rps->num_pics; - - /* sort delta poc */ - for (i = 1; i < rps->num_pics; ++i) { - delta_poc = rps->delta_poc[i]; - used = rps->used[i]; - for (j = i - 1; j >= 0; j--) { - if (delta_poc < rps->delta_poc[j]) { - rps->delta_poc[j + 1] = rps->delta_poc[j]; - rps->used[j + 1] = rps->used[j]; - rps->delta_poc[j] = delta_poc; - rps->used[j] = used; - } - } - } - - for (i = 0 , j = rps->num_neg_pics - 1; - i < rps->num_neg_pics >> 1; i++, j--) { - delta_poc = rps->delta_poc[i]; - used = rps->used[i]; - rps->delta_poc[i] = rps->delta_poc[j]; - rps->used[i] = rps->used[j]; - rps->delta_poc[j] = delta_poc; - rps->used[j] = used; - } - } else { - /* num_negative_pics */ - rps->num_neg_pics = vl_rbsp_ue(rbsp); - /* num_positive_pics */ - rps->num_pos_pics = vl_rbsp_ue(rbsp); - rps->num_pics = rps->num_neg_pics + rps->num_pos_pics; - - delta_poc = 0; - for(i = 0 ; i < rps->num_neg_pics; ++i) { - /* delta_poc_s0_minus1 */ - delta_poc -= (vl_rbsp_ue(rbsp) + 1); - rps->delta_poc[i] = delta_poc; - /* used_by_curr_pic_s0_flag */ - rps->used[i] = vl_rbsp_u(rbsp, 1); - } - - delta_poc = 0; - for(i = rps->num_neg_pics; i < rps->num_pics; ++i) { - /* delta_poc_s1_minus1 */ - delta_poc += (vl_rbsp_ue(rbsp) + 1); - rps->delta_poc[i] = delta_poc; - /* used_by_curr_pic_s1_flag */ - rps->used[i] = vl_rbsp_u(rbsp, 1); - } - } -} - -static struct pipe_h265_sps *seq_parameter_set_id(vid_dec_PrivateType *priv, - struct vl_rbsp *rbsp) -{ - unsigned id = vl_rbsp_ue(rbsp); - - if (id >= ARRAY_SIZE(priv->codec_data.h265.sps)) - return NULL; - - return &priv->codec_data.h265.sps[id]; -} - -static void seq_parameter_set(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp) -{ - struct pipe_h265_sps *sps; - int sps_max_sub_layers_minus1; - unsigned i; - - /* sps_video_parameter_set_id */ - vl_rbsp_u(rbsp, 4); - - /* sps_max_sub_layers_minus1 */ - sps_max_sub_layers_minus1 = vl_rbsp_u(rbsp, 3); - - assert(sps_max_sub_layers_minus1 <= 6); - - /* sps_temporal_id_nesting_flag */ - vl_rbsp_u(rbsp, 1); - - priv->codec_data.h265.level_idc = - profile_tier_level(rbsp, sps_max_sub_layers_minus1); - - sps = seq_parameter_set_id(priv, rbsp); - if (!sps) - return; - - memset(sps, 0, sizeof(*sps)); - - sps->chroma_format_idc = vl_rbsp_ue(rbsp); - - if (sps->chroma_format_idc == 3) - sps->separate_colour_plane_flag = vl_rbsp_u(rbsp, 1); - - priv->codec_data.h265.pic_width_in_luma_samples = - sps->pic_width_in_luma_samples = vl_rbsp_ue(rbsp); - - priv->codec_data.h265.pic_height_in_luma_samples = - sps->pic_height_in_luma_samples = vl_rbsp_ue(rbsp); - - /* conformance_window_flag */ - if (vl_rbsp_u(rbsp, 1)) { - /* conf_win_left_offset */ - vl_rbsp_ue(rbsp); - /* conf_win_right_offset */ - vl_rbsp_ue(rbsp); - /* conf_win_top_offset */ - vl_rbsp_ue(rbsp); - /* conf_win_bottom_offset */ - vl_rbsp_ue(rbsp); - } - - sps->bit_depth_luma_minus8 = vl_rbsp_ue(rbsp); - sps->bit_depth_chroma_minus8 = vl_rbsp_ue(rbsp); - sps->log2_max_pic_order_cnt_lsb_minus4 = vl_rbsp_ue(rbsp); - - /* sps_sub_layer_ordering_info_present_flag */ - i = vl_rbsp_u(rbsp, 1) ? 0 : sps_max_sub_layers_minus1; - for (; i <= sps_max_sub_layers_minus1; ++i) { - sps->sps_max_dec_pic_buffering_minus1 = vl_rbsp_ue(rbsp); - /* sps_max_num_reorder_pics */ - vl_rbsp_ue(rbsp); - /* sps_max_latency_increase_plus */ - vl_rbsp_ue(rbsp); - } - - sps->log2_min_luma_coding_block_size_minus3 = vl_rbsp_ue(rbsp); - sps->log2_diff_max_min_luma_coding_block_size = vl_rbsp_ue(rbsp); - sps->log2_min_transform_block_size_minus2 = vl_rbsp_ue(rbsp); - sps->log2_diff_max_min_transform_block_size = vl_rbsp_ue(rbsp); - sps->max_transform_hierarchy_depth_inter = vl_rbsp_ue(rbsp); - sps->max_transform_hierarchy_depth_intra = vl_rbsp_ue(rbsp); - - sps->scaling_list_enabled_flag = vl_rbsp_u(rbsp, 1); - if (sps->scaling_list_enabled_flag) - /* sps_scaling_list_data_present_flag */ - if (vl_rbsp_u(rbsp, 1)) - scaling_list_data(priv, rbsp, sps); - - sps->amp_enabled_flag = vl_rbsp_u(rbsp, 1); - sps->sample_adaptive_offset_enabled_flag = vl_rbsp_u(rbsp, 1); - sps->pcm_enabled_flag = vl_rbsp_u(rbsp, 1); - if (sps->pcm_enabled_flag) { - sps->pcm_sample_bit_depth_luma_minus1 = vl_rbsp_u(rbsp, 4); - sps->pcm_sample_bit_depth_chroma_minus1 = vl_rbsp_u(rbsp, 4); - sps->log2_min_pcm_luma_coding_block_size_minus3 = vl_rbsp_ue(rbsp); - sps->log2_diff_max_min_pcm_luma_coding_block_size = vl_rbsp_ue(rbsp); - sps->pcm_loop_filter_disabled_flag = vl_rbsp_u(rbsp, 1); - } - - sps->num_short_term_ref_pic_sets = vl_rbsp_ue(rbsp); - - for (i = 0; i < sps->num_short_term_ref_pic_sets; ++i) { - struct ref_pic_set *rps; - - rps = (struct ref_pic_set *) - priv->codec_data.h265.ref_pic_set_list + i; - st_ref_pic_set(priv, rbsp, rps, sps, i); - } - - sps->long_term_ref_pics_present_flag = vl_rbsp_u(rbsp, 1); - if (sps->long_term_ref_pics_present_flag) { - sps->num_long_term_ref_pics_sps = vl_rbsp_ue(rbsp); - for (i = 0; i < sps->num_long_term_ref_pics_sps; ++i) { - /* lt_ref_pic_poc_lsb_sps */ - vl_rbsp_u(rbsp, sps->log2_max_pic_order_cnt_lsb_minus4 + 4); - /* used_by_curr_pic_lt_sps_flag */ - vl_rbsp_u(rbsp, 1); - } - } - - sps->sps_temporal_mvp_enabled_flag = vl_rbsp_u(rbsp, 1); - sps->strong_intra_smoothing_enabled_flag = vl_rbsp_u(rbsp, 1); -} - -static struct pipe_h265_pps *pic_parameter_set_id(vid_dec_PrivateType *priv, - struct vl_rbsp *rbsp) -{ - unsigned id = vl_rbsp_ue(rbsp); - - if (id >= ARRAY_SIZE(priv->codec_data.h265.pps)) - return NULL; - - return &priv->codec_data.h265.pps[id]; -} - -static void picture_parameter_set(vid_dec_PrivateType *priv, - struct vl_rbsp *rbsp) -{ - struct pipe_h265_sps *sps; - struct pipe_h265_pps *pps; - int i; - - pps = pic_parameter_set_id(priv, rbsp); - if (!pps) - return; - - memset(pps, 0, sizeof(*pps)); - sps = pps->sps = seq_parameter_set_id(priv, rbsp); - if (!sps) - return; - - pps->dependent_slice_segments_enabled_flag = vl_rbsp_u(rbsp, 1); - pps->output_flag_present_flag = vl_rbsp_u(rbsp, 1); - pps->num_extra_slice_header_bits = vl_rbsp_u(rbsp, 3); - pps->sign_data_hiding_enabled_flag = vl_rbsp_u(rbsp, 1); - pps->cabac_init_present_flag = vl_rbsp_u(rbsp, 1); - - pps->num_ref_idx_l0_default_active_minus1 = vl_rbsp_ue(rbsp); - pps->num_ref_idx_l1_default_active_minus1 = vl_rbsp_ue(rbsp); - pps->init_qp_minus26 = vl_rbsp_se(rbsp); - pps->constrained_intra_pred_flag = vl_rbsp_u(rbsp, 1); - pps->transform_skip_enabled_flag = vl_rbsp_u(rbsp, 1); - - pps->cu_qp_delta_enabled_flag = vl_rbsp_u(rbsp, 1); - if (pps->cu_qp_delta_enabled_flag) - pps->diff_cu_qp_delta_depth = vl_rbsp_ue(rbsp); - - pps->pps_cb_qp_offset = vl_rbsp_se(rbsp); - pps->pps_cr_qp_offset = vl_rbsp_se(rbsp); - pps->pps_slice_chroma_qp_offsets_present_flag = vl_rbsp_u(rbsp, 1); - - pps->weighted_pred_flag = vl_rbsp_u(rbsp, 1); - pps->weighted_bipred_flag = vl_rbsp_u(rbsp, 1); - - pps->transquant_bypass_enabled_flag = vl_rbsp_u(rbsp, 1); - pps->tiles_enabled_flag = vl_rbsp_u(rbsp, 1); - pps->entropy_coding_sync_enabled_flag = vl_rbsp_u(rbsp, 1); - - if (pps->tiles_enabled_flag) { - pps->num_tile_columns_minus1 = vl_rbsp_ue(rbsp); - pps->num_tile_rows_minus1 = vl_rbsp_ue(rbsp); - - pps->uniform_spacing_flag = vl_rbsp_u(rbsp, 1); - if (!pps->uniform_spacing_flag) { - for (i = 0; i < pps->num_tile_columns_minus1; ++i) - pps->column_width_minus1[i] = vl_rbsp_ue(rbsp); - - for (i = 0; i < pps->num_tile_rows_minus1; ++i) - pps->row_height_minus1[i] = vl_rbsp_ue(rbsp); - } - - if (!pps->num_tile_columns_minus1 || !pps->num_tile_rows_minus1) - pps->loop_filter_across_tiles_enabled_flag = vl_rbsp_u(rbsp, 1); - } - - pps->pps_loop_filter_across_slices_enabled_flag = vl_rbsp_u(rbsp, 1); - - pps->deblocking_filter_control_present_flag = vl_rbsp_u(rbsp, 1); - if (pps->deblocking_filter_control_present_flag) { - pps->deblocking_filter_override_enabled_flag = vl_rbsp_u(rbsp, 1); - pps->pps_deblocking_filter_disabled_flag = vl_rbsp_u(rbsp, 1); - if (!pps->pps_deblocking_filter_disabled_flag) { - pps->pps_beta_offset_div2 = vl_rbsp_se(rbsp); - pps->pps_tc_offset_div2 = vl_rbsp_se(rbsp); - } - } - - /* pps_scaling_list_data_present_flag */ - if (vl_rbsp_u(rbsp, 1)) - scaling_list_data(priv, rbsp, sps); - - pps->lists_modification_present_flag = vl_rbsp_u(rbsp, 1); - pps->log2_parallel_merge_level_minus2 = vl_rbsp_ue(rbsp); - pps->slice_segment_header_extension_present_flag = vl_rbsp_u(rbsp, 1); -} - -static void vid_dec_h265_BeginFrame(vid_dec_PrivateType *priv) -{ - if (priv->frame_started) - return; - - if (!priv->codec) { - struct pipe_video_codec templat = {}; - omx_base_video_PortType *port = (omx_base_video_PortType *) - priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; - - templat.profile = priv->profile; - templat.entrypoint = PIPE_VIDEO_ENTRYPOINT_BITSTREAM; - templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; - templat.expect_chunked_decode = true; - templat.width = priv->codec_data.h265.pic_width_in_luma_samples; - templat.height = priv->codec_data.h265.pic_height_in_luma_samples; - templat.level = priv->codec_data.h265.level_idc; - priv->codec = priv->pipe->create_video_codec(priv->pipe, &templat); - - /* disable transcode tunnel if video size is different from coded size */ - if (priv->codec_data.h265.pic_width_in_luma_samples != - port->sPortParam.format.video.nFrameWidth || - priv->codec_data.h265.pic_height_in_luma_samples != - port->sPortParam.format.video.nFrameHeight) - priv->disable_tunnel = true; - } - - vid_dec_NeedTarget(priv); - - if (priv->first_buf_in_frame) - priv->timestamp = priv->timestamps[0]; - priv->first_buf_in_frame = false; - - priv->codec->begin_frame(priv->codec, priv->target, &priv->picture.base); - priv->frame_started = true; -} - -static struct pipe_video_buffer *vid_dec_h265_Flush(vid_dec_PrivateType *priv, - OMX_TICKS *timestamp) -{ - struct dpb_list *entry, *result = NULL; - struct pipe_video_buffer *buf; - - /* search for the lowest poc and break on zeros */ - LIST_FOR_EACH_ENTRY(entry, &priv->codec_data.h265.dpb_list, list) { - - if (result && entry->poc == 0) - break; - - if (!result || entry->poc < result->poc) - result = entry; - } - - if (!result) - return NULL; - - buf = result->buffer; - if (timestamp) - *timestamp = result->timestamp; - - --priv->codec_data.h265.dpb_num; - list_del(&result->list); - FREE(result); - - return buf; -} - -static void vid_dec_h265_EndFrame(vid_dec_PrivateType *priv) -{ - struct dpb_list *entry = NULL; - struct pipe_video_buffer *tmp; - struct ref_pic_set *rps; - int i; - OMX_TICKS timestamp; - - if (!priv->frame_started) - return; - - priv->picture.h265.NumPocStCurrBefore = 0; - priv->picture.h265.NumPocStCurrAfter = 0; - memset(priv->picture.h265.RefPicSetStCurrBefore, 0, 8); - memset(priv->picture.h265.RefPicSetStCurrAfter, 0, 8); - for (i = 0; i < MAX_NUM_REF_PICS; ++i) { - priv->picture.h265.ref[i] = NULL; - priv->picture.h265.PicOrderCntVal[i] = 0; - } - - rps = priv->codec_data.h265.rps; - - if (rps) { - unsigned bf = 0, af = 0; - - priv->picture.h265.NumDeltaPocsOfRefRpsIdx = rps->num_delta_poc; - for (i = 0; i < rps->num_pics; ++i) { - priv->picture.h265.PicOrderCntVal[i] = - rps->delta_poc[i] + get_poc(priv); - - LIST_FOR_EACH_ENTRY(entry, &priv->codec_data.h265.dpb_list, list) { - if (entry->poc == priv->picture.h265.PicOrderCntVal[i]) { - priv->picture.h265.ref[i] = entry->buffer; - break; - } - } - - if (rps->used[i]) { - if (i < rps->num_neg_pics) { - priv->picture.h265.NumPocStCurrBefore++; - priv->picture.h265.RefPicSetStCurrBefore[bf++] = i; - } else { - priv->picture.h265.NumPocStCurrAfter++; - priv->picture.h265.RefPicSetStCurrAfter[af++] = i; - } - } - } - } - - priv->codec->end_frame(priv->codec, priv->target, &priv->picture.base); - priv->frame_started = false; - - /* add the decoded picture to the dpb list */ - entry = CALLOC_STRUCT(dpb_list); - if (!entry) - return; - - priv->first_buf_in_frame = true; - entry->buffer = priv->target; - entry->timestamp = priv->timestamp; - entry->poc = get_poc(priv); - - list_addtail(&entry->list, &priv->codec_data.h265.dpb_list); - ++priv->codec_data.h265.dpb_num; - priv->target = NULL; - - if (priv->codec_data.h265.dpb_num <= DPB_MAX_SIZE) - return; - - tmp = priv->in_buffers[0]->pInputPortPrivate; - priv->in_buffers[0]->pInputPortPrivate = vid_dec_h265_Flush(priv, ×tamp); - priv->in_buffers[0]->nTimeStamp = timestamp; - priv->target = tmp; - priv->frame_finished = priv->in_buffers[0]->pInputPortPrivate != NULL; - if (priv->frame_finished && - (priv->in_buffers[0]->nFlags & OMX_BUFFERFLAG_EOS)) - FREE(priv->codec_data.h265.ref_pic_set_list); -} - -static void slice_header(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp, - unsigned nal_unit_type) -{ - struct pipe_h265_pps *pps; - struct pipe_h265_sps *sps; - bool first_slice_segment_in_pic_flag; - bool dependent_slice_segment_flag = false; - struct ref_pic_set *rps; - unsigned poc_lsb, poc_msb, slice_prev_poc; - unsigned max_poc_lsb, prev_poc_lsb, prev_poc_msb; - unsigned num_st_rps; - int i; - - if (priv->picture.h265.IDRPicFlag != is_idr_picture(nal_unit_type)) - vid_dec_h265_EndFrame(priv); - - priv->picture.h265.IDRPicFlag = is_idr_picture(nal_unit_type); - - first_slice_segment_in_pic_flag = vl_rbsp_u(rbsp, 1); - - if (is_rap_picture(nal_unit_type)) - /* no_output_of_prior_pics_flag */ - vl_rbsp_u(rbsp, 1); - - pps = pic_parameter_set_id(priv, rbsp); - if (!pps) - return; - - sps = pps->sps; - if (!sps) - return; - - if (pps != priv->picture.h265.pps) - vid_dec_h265_EndFrame(priv); - - priv->picture.h265.pps = pps; - - if (priv->picture.h265.RAPPicFlag != is_rap_picture(nal_unit_type)) - vid_dec_h265_EndFrame(priv); - priv->picture.h265.RAPPicFlag = is_rap_picture(nal_unit_type); - - num_st_rps = sps->num_short_term_ref_pic_sets; - - if (priv->picture.h265.CurrRpsIdx != num_st_rps) - vid_dec_h265_EndFrame(priv); - priv->picture.h265.CurrRpsIdx = num_st_rps; - - if (!first_slice_segment_in_pic_flag) { - int size, num; - int bits_slice_segment_address = 0; - - if (pps->dependent_slice_segments_enabled_flag) - dependent_slice_segment_flag = vl_rbsp_u(rbsp, 1); - - size = 1 << (sps->log2_min_luma_coding_block_size_minus3 + 3 + - sps->log2_diff_max_min_luma_coding_block_size); - - num = ((sps->pic_width_in_luma_samples + size - 1) / size) * - ((sps->pic_height_in_luma_samples + size - 1) / size); - - while (num > (1 << bits_slice_segment_address)) - bits_slice_segment_address++; - - /* slice_segment_address */ - vl_rbsp_u(rbsp, bits_slice_segment_address); - } - - if (dependent_slice_segment_flag) - return; - - for (i = 0; i < pps->num_extra_slice_header_bits; ++i) - /* slice_reserved_flag */ - vl_rbsp_u(rbsp, 1); - - /* slice_type */ - vl_rbsp_ue(rbsp); - - if (pps->output_flag_present_flag) - /* pic output flag */ - vl_rbsp_u(rbsp, 1); - - if (sps->separate_colour_plane_flag) - /* colour_plane_id */ - vl_rbsp_u(rbsp, 2); - - if (is_idr_picture(nal_unit_type)) { - set_poc(priv, nal_unit_type, 0); - return; - } - - /* slice_pic_order_cnt_lsb */ - poc_lsb = - vl_rbsp_u(rbsp, sps->log2_max_pic_order_cnt_lsb_minus4 + 4); - - slice_prev_poc = (int)priv->codec_data.h265.slice_prev_poc; - max_poc_lsb = 1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4); - - prev_poc_lsb = slice_prev_poc & (max_poc_lsb - 1); - prev_poc_msb = slice_prev_poc - prev_poc_lsb; - - if ((poc_lsb < prev_poc_lsb) && - ((prev_poc_lsb - poc_lsb ) >= (max_poc_lsb / 2))) - poc_msb = prev_poc_msb + max_poc_lsb; - - else if ((poc_lsb > prev_poc_lsb ) && - ((poc_lsb - prev_poc_lsb) > (max_poc_lsb / 2))) - poc_msb = prev_poc_msb - max_poc_lsb; - - else - poc_msb = prev_poc_msb; - - if (is_bla_picture(nal_unit_type)) - poc_msb = 0; - - if (get_poc(priv) != poc_msb + poc_lsb) - vid_dec_h265_EndFrame(priv); - - set_poc(priv, nal_unit_type, (poc_msb + poc_lsb)); - - /* short_term_ref_pic_set_sps_flag */ - if (!vl_rbsp_u(rbsp, 1)) { - rps = (struct ref_pic_set *) - priv->codec_data.h265.ref_pic_set_list + num_st_rps; - st_ref_pic_set(priv, rbsp, rps, sps, num_st_rps); - - } else if (num_st_rps > 1) { - int num_bits = 0; - unsigned idx; - - while ((1 << num_bits) < num_st_rps) - num_bits++; - - if (num_bits > 0) - /* short_term_ref_pic_set_idx */ - idx = vl_rbsp_u(rbsp, num_bits); - else - idx = 0; - - rps = (struct ref_pic_set *) - priv->codec_data.h265.ref_pic_set_list + idx; - } else - rps = (struct ref_pic_set *) - priv->codec_data.h265.ref_pic_set_list; - - if (is_bla_picture(nal_unit_type)) { - rps->num_neg_pics = 0; - rps->num_pos_pics = 0; - rps->num_pics = 0; - } - - priv->codec_data.h265.rps = rps; - - return; -} - -static void vid_dec_h265_Decode(vid_dec_PrivateType *priv, - struct vl_vlc *vlc, - unsigned min_bits_left) -{ - unsigned nal_unit_type; - unsigned nuh_layer_id; - unsigned nuh_temporal_id_plus1; - - if (!vl_vlc_search_byte(vlc, vl_vlc_bits_left(vlc) - min_bits_left, 0x00)) - return; - - if (vl_vlc_peekbits(vlc, 24) != 0x000001) { - vl_vlc_eatbits(vlc, 8); - return; - } - - if (priv->slice) { - unsigned bytes = priv->bytes_left - (vl_vlc_bits_left(vlc) / 8); - - priv->codec->decode_bitstream(priv->codec, priv->target, - &priv->picture.base, 1, - &priv->slice, &bytes); - priv->slice = NULL; - } - - vl_vlc_eatbits(vlc, 24); - - /* forbidden_zero_bit */ - vl_vlc_eatbits(vlc, 1); - - if (vl_vlc_valid_bits(vlc) < 15) - vl_vlc_fillbits(vlc); - - nal_unit_type = vl_vlc_get_uimsbf(vlc, 6); - - /* nuh_layer_id */ - nuh_layer_id = vl_vlc_get_uimsbf(vlc, 6); - - /* nuh_temporal_id_plus1 */ - nuh_temporal_id_plus1 = vl_vlc_get_uimsbf(vlc, 3); - priv->codec_data.h265.temporal_id = nuh_temporal_id_plus1 - 1; - - if (!is_slice_picture(nal_unit_type)) - vid_dec_h265_EndFrame(priv); - - if (nal_unit_type == NAL_UNIT_TYPE_SPS) { - struct vl_rbsp rbsp; - - vl_rbsp_init(&rbsp, vlc, ~0); - seq_parameter_set(priv, &rbsp); - - } else if (nal_unit_type == NAL_UNIT_TYPE_PPS) { - struct vl_rbsp rbsp; - - vl_rbsp_init(&rbsp, vlc, ~0); - picture_parameter_set(priv, &rbsp); - - } else if (is_slice_picture(nal_unit_type)) { - unsigned bits = vl_vlc_valid_bits(vlc); - unsigned bytes = bits / 8 + 5; - struct vl_rbsp rbsp; - uint8_t buf[9]; - const void *ptr = buf; - unsigned i; - - buf[0] = 0x0; - buf[1] = 0x0; - buf[2] = 0x1; - buf[3] = nal_unit_type << 1 | nuh_layer_id >> 5; - buf[4] = nuh_layer_id << 3 | nuh_temporal_id_plus1; - for (i = 5; i < bytes; ++i) - buf[i] = vl_vlc_peekbits(vlc, bits) >> ((bytes - i - 1) * 8); - - priv->bytes_left = (vl_vlc_bits_left(vlc) - bits) / 8; - priv->slice = vlc->data; - - vl_rbsp_init(&rbsp, vlc, 128); - slice_header(priv, &rbsp, nal_unit_type); - - vid_dec_h265_BeginFrame(priv); - - priv->codec->decode_bitstream(priv->codec, priv->target, - &priv->picture.base, 1, - &ptr, &bytes); - } - - /* resync to byte boundary */ - vl_vlc_eatbits(vlc, vl_vlc_valid_bits(vlc) % 8); -} - -void vid_dec_h265_Init(vid_dec_PrivateType *priv) -{ - priv->picture.base.profile = PIPE_VIDEO_PROFILE_HEVC_MAIN; - - list_inithead(&priv->codec_data.h265.dpb_list); - priv->codec_data.h265.ref_pic_set_list = (struct ref_pic_set *) - CALLOC(MAX_NUM_REF_PICS, sizeof(struct ref_pic_set)); - - priv->Decode = vid_dec_h265_Decode; - priv->EndFrame = vid_dec_h265_EndFrame; - priv->Flush = vid_dec_h265_Flush; - priv->first_buf_in_frame = true; -} diff --git a/src/gallium/state_trackers/omx/bellagio/vid_dec_mpeg12.c b/src/gallium/state_trackers/omx/bellagio/vid_dec_mpeg12.c deleted file mode 100644 index f64c2b83fa5..00000000000 --- a/src/gallium/state_trackers/omx/bellagio/vid_dec_mpeg12.c +++ /dev/null @@ -1,383 +0,0 @@ -/************************************************************************** - * - * Copyright 2013 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/* - * Authors: - * Christian König - * - */ - -#include "pipe/p_video_codec.h" -#include "vl/vl_vlc.h" -#include "vl/vl_zscan.h" - -#include "vid_dec.h" - -static uint8_t default_intra_matrix[64] = { - 8, 16, 19, 22, 26, 27, 29, 34, - 16, 16, 22, 24, 27, 29, 34, 37, - 19, 22, 26, 27, 29, 34, 34, 38, - 22, 22, 26, 27, 29, 34, 37, 40, - 22, 26, 27, 29, 32, 35, 40, 48, - 26, 27, 29, 32, 35, 40, 48, 58, - 26, 27, 29, 34, 38, 46, 56, 69, - 27, 29, 35, 38, 46, 56, 69, 83 -}; - -static uint8_t default_non_intra_matrix[64] = { - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16 -}; - -static void vid_dec_mpeg12_Decode(vid_dec_PrivateType *priv, struct vl_vlc *vlc, unsigned min_bits_left); -static void vid_dec_mpeg12_EndFrame(vid_dec_PrivateType *priv); -static struct pipe_video_buffer *vid_dec_mpeg12_Flush(vid_dec_PrivateType *priv, OMX_TICKS *timestamp); - -void vid_dec_mpeg12_Init(vid_dec_PrivateType *priv) -{ - struct pipe_video_codec templat = {}; - omx_base_video_PortType *port; - - port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; - templat.profile = priv->profile; - templat.entrypoint = PIPE_VIDEO_ENTRYPOINT_BITSTREAM; - templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; - templat.max_references = 2; - templat.expect_chunked_decode = true; - templat.width = port->sPortParam.format.video.nFrameWidth; - templat.height = port->sPortParam.format.video.nFrameHeight; - - priv->codec = priv->pipe->create_video_codec(priv->pipe, &templat); - - priv->picture.base.profile = PIPE_VIDEO_PROFILE_MPEG2_MAIN; - priv->picture.mpeg12.intra_matrix = default_intra_matrix; - priv->picture.mpeg12.non_intra_matrix = default_non_intra_matrix; - - priv->Decode = vid_dec_mpeg12_Decode; - priv->EndFrame = vid_dec_mpeg12_EndFrame; - priv->Flush = vid_dec_mpeg12_Flush; -} - -static void BeginFrame(vid_dec_PrivateType *priv) -{ - if (priv->picture.mpeg12.picture_coding_type != PIPE_MPEG12_PICTURE_CODING_TYPE_B) { - priv->picture.mpeg12.ref[0] = priv->picture.mpeg12.ref[1]; - priv->picture.mpeg12.ref[1] = NULL; - } - - if (priv->target == priv->picture.mpeg12.ref[0]) { - struct pipe_video_buffer *tmp = priv->target; - priv->target = priv->shadow; - priv->shadow = tmp; - } - - vid_dec_NeedTarget(priv); - - priv->codec->begin_frame(priv->codec, priv->target, &priv->picture.base); - priv->frame_started = true; -} - -static void vid_dec_mpeg12_EndFrame(vid_dec_PrivateType *priv) -{ - struct pipe_video_buffer *done; - - priv->codec->end_frame(priv->codec, priv->target, &priv->picture.base); - priv->frame_started = false; - - if (priv->picture.mpeg12.picture_coding_type != PIPE_MPEG12_PICTURE_CODING_TYPE_B) { - - priv->picture.mpeg12.ref[1] = priv->target; - done = priv->picture.mpeg12.ref[0]; - if (!done) { - priv->target = NULL; - return; - } - - } else - done = priv->target; - - priv->frame_finished = true; - priv->target = priv->in_buffers[0]->pInputPortPrivate; - priv->in_buffers[0]->pInputPortPrivate = done; -} - -static struct pipe_video_buffer *vid_dec_mpeg12_Flush(vid_dec_PrivateType *priv, OMX_TICKS *timestamp) -{ - struct pipe_video_buffer *result = priv->picture.mpeg12.ref[1]; - priv->picture.mpeg12.ref[1] = NULL; - if (timestamp) - *timestamp = OMX_VID_DEC_TIMESTAMP_INVALID; - return result; -} - -static void vid_dec_mpeg12_Decode(vid_dec_PrivateType *priv, struct vl_vlc *vlc, unsigned min_bits_left) -{ - uint8_t code; - unsigned i; - - if (!vl_vlc_search_byte(vlc, vl_vlc_bits_left(vlc) - min_bits_left, 0x00)) - return; - - if (vl_vlc_peekbits(vlc, 24) != 0x000001) { - vl_vlc_eatbits(vlc, 8); - return; - } - - if (priv->slice) { - unsigned bytes = priv->bytes_left - (vl_vlc_bits_left(vlc) / 8); - priv->codec->decode_bitstream(priv->codec, priv->target, &priv->picture.base, - 1, &priv->slice, &bytes); - priv->slice = NULL; - } - - vl_vlc_eatbits(vlc, 24); - code = vl_vlc_get_uimsbf(vlc, 8); - - if (priv->frame_started && (code == 0x00 || code > 0xAF)) - vid_dec_mpeg12_EndFrame(priv); - - if (code == 0xB3) { - /* sequence header code */ - vl_vlc_fillbits(vlc); - - /* horizontal_size_value */ - vl_vlc_get_uimsbf(vlc, 12); - - /* vertical_size_value */ - vl_vlc_get_uimsbf(vlc, 12); - - /* aspect_ratio_information */ - vl_vlc_get_uimsbf(vlc, 4); - - /* frame_rate_code */ - vl_vlc_get_uimsbf(vlc, 4); - - vl_vlc_fillbits(vlc); - - /* bit_rate_value */ - vl_vlc_get_uimsbf(vlc, 18); - - /* marker_bit */ - vl_vlc_get_uimsbf(vlc, 1); - - /* vbv_buffer_size_value */ - vl_vlc_get_uimsbf(vlc, 10); - - /* constrained_parameters_flag */ - vl_vlc_get_uimsbf(vlc, 1); - - vl_vlc_fillbits(vlc); - - /* load_intra_quantiser_matrix */ - if (vl_vlc_get_uimsbf(vlc, 1)) { - /* intra_quantiser_matrix */ - priv->picture.mpeg12.intra_matrix = priv->codec_data.mpeg12.intra_matrix; - for (i = 0; i < 64; ++i) { - priv->codec_data.mpeg12.intra_matrix[vl_zscan_normal[i]] = vl_vlc_get_uimsbf(vlc, 8); - vl_vlc_fillbits(vlc); - } - } else - priv->picture.mpeg12.intra_matrix = default_intra_matrix; - - /* load_non_intra_quantiser_matrix */ - if (vl_vlc_get_uimsbf(vlc, 1)) { - /* non_intra_quantiser_matrix */ - priv->picture.mpeg12.non_intra_matrix = priv->codec_data.mpeg12.non_intra_matrix; - for (i = 0; i < 64; ++i) { - priv->codec_data.mpeg12.non_intra_matrix[i] = vl_vlc_get_uimsbf(vlc, 8); - vl_vlc_fillbits(vlc); - } - } else - priv->picture.mpeg12.non_intra_matrix = default_non_intra_matrix; - - } else if (code == 0x00) { - /* picture start code */ - vl_vlc_fillbits(vlc); - - /* temporal_reference */ - vl_vlc_get_uimsbf(vlc, 10); - - priv->picture.mpeg12.picture_coding_type = vl_vlc_get_uimsbf(vlc, 3); - - /* vbv_delay */ - vl_vlc_get_uimsbf(vlc, 16); - - vl_vlc_fillbits(vlc); - if (priv->picture.mpeg12.picture_coding_type == 2 || - priv->picture.mpeg12.picture_coding_type == 3) { - priv->picture.mpeg12.full_pel_forward_vector = vl_vlc_get_uimsbf(vlc, 1); - /* forward_f_code */ - priv->picture.mpeg12.f_code[0][0] = vl_vlc_get_uimsbf(vlc, 3) - 1; - priv->picture.mpeg12.f_code[0][1] = priv->picture.mpeg12.f_code[0][0]; - } else { - priv->picture.mpeg12.full_pel_forward_vector = 0; - priv->picture.mpeg12.f_code[0][1] = priv->picture.mpeg12.f_code[0][0] = 14; - } - - if (priv->picture.mpeg12.picture_coding_type == 3) { - priv->picture.mpeg12.full_pel_backward_vector = vl_vlc_get_uimsbf(vlc, 1); - /* backward_f_code */ - priv->picture.mpeg12.f_code[1][0] = vl_vlc_get_uimsbf(vlc, 3) - 1; - priv->picture.mpeg12.f_code[1][1] = priv->picture.mpeg12.f_code[1][0]; - } else { - priv->picture.mpeg12.full_pel_backward_vector = 0; - priv->picture.mpeg12.f_code[0][1] = priv->picture.mpeg12.f_code[0][0] = 14; - } - - /* extra_bit_picture */ - while (vl_vlc_get_uimsbf(vlc, 1)) { - /* extra_information_picture */ - vl_vlc_get_uimsbf(vlc, 8); - vl_vlc_fillbits(vlc); - } - - } else if (code == 0xB5) { - /* extension start code */ - vl_vlc_fillbits(vlc); - - /* extension_start_code_identifier */ - switch (vl_vlc_get_uimsbf(vlc, 4)) { - case 0x3: /* quant matrix extension */ - - /* load_intra_quantiser_matrix */ - if (vl_vlc_get_uimsbf(vlc, 1)) { - /* intra_quantiser_matrix */ - priv->picture.mpeg12.intra_matrix = priv->codec_data.mpeg12.intra_matrix; - for (i = 0; i < 64; ++i) { - priv->codec_data.mpeg12.intra_matrix[vl_zscan_normal[i]] = vl_vlc_get_uimsbf(vlc, 8); - vl_vlc_fillbits(vlc); - } - } else - priv->picture.mpeg12.intra_matrix = default_intra_matrix; - - /* load_non_intra_quantiser_matrix */ - if (vl_vlc_get_uimsbf(vlc, 1)) { - /* non_intra_quantiser_matrix */ - priv->picture.mpeg12.non_intra_matrix = priv->codec_data.mpeg12.non_intra_matrix; - for (i = 0; i < 64; ++i) { - priv->codec_data.mpeg12.non_intra_matrix[i] = vl_vlc_get_uimsbf(vlc, 8); - vl_vlc_fillbits(vlc); - } - } else - priv->picture.mpeg12.intra_matrix = default_non_intra_matrix; - - break; - - case 0x8: /* picture coding extension */ - - priv->picture.mpeg12.f_code[0][0] = vl_vlc_get_uimsbf(vlc, 4) - 1; - priv->picture.mpeg12.f_code[0][1] = vl_vlc_get_uimsbf(vlc, 4) - 1; - priv->picture.mpeg12.f_code[1][0] = vl_vlc_get_uimsbf(vlc, 4) - 1; - priv->picture.mpeg12.f_code[1][1] = vl_vlc_get_uimsbf(vlc, 4) - 1; - priv->picture.mpeg12.intra_dc_precision = vl_vlc_get_uimsbf(vlc, 2); - priv->picture.mpeg12.picture_structure = vl_vlc_get_uimsbf(vlc, 2); - priv->picture.mpeg12.top_field_first = vl_vlc_get_uimsbf(vlc, 1); - priv->picture.mpeg12.frame_pred_frame_dct = vl_vlc_get_uimsbf(vlc, 1); - priv->picture.mpeg12.concealment_motion_vectors = vl_vlc_get_uimsbf(vlc, 1); - priv->picture.mpeg12.q_scale_type = vl_vlc_get_uimsbf(vlc, 1); - priv->picture.mpeg12.intra_vlc_format = vl_vlc_get_uimsbf(vlc, 1); - priv->picture.mpeg12.alternate_scan = vl_vlc_get_uimsbf(vlc, 1); - - /* repeat_first_field */ - vl_vlc_get_uimsbf(vlc, 1); - - /* chroma_420_type */ - vl_vlc_get_uimsbf(vlc, 1); - - vl_vlc_fillbits(vlc); - - /* progressive_frame */ - vl_vlc_get_uimsbf(vlc, 1); - - /* composite_display_flag */ - if (vl_vlc_get_uimsbf(vlc, 1)) { - - /* v_axis */ - vl_vlc_get_uimsbf(vlc, 1); - - /* field_sequence */ - vl_vlc_get_uimsbf(vlc, 3); - - /* sub_carrier */ - vl_vlc_get_uimsbf(vlc, 1); - - /* burst_amplitude */ - vl_vlc_get_uimsbf(vlc, 7); - - /* sub_carrier_phase */ - vl_vlc_get_uimsbf(vlc, 8); - } - break; - } - - } else if (code <= 0xAF) { - /* slice start */ - unsigned bytes = (vl_vlc_valid_bits(vlc) / 8) + 4; - uint8_t buf[12]; - const void *ptr = buf; - unsigned i; - - if (!priv->frame_started) - BeginFrame(priv); - - buf[0] = 0x00; - buf[1] = 0x00; - buf[2] = 0x01; - buf[3] = code; - for (i = 4; i < bytes; ++i) - buf[i] = vl_vlc_get_uimsbf(vlc, 8); - - priv->codec->decode_bitstream(priv->codec, priv->target, &priv->picture.base, - 1, &ptr, &bytes); - - priv->bytes_left = vl_vlc_bits_left(vlc) / 8; - priv->slice = vlc->data; - - } else if (code == 0xB2) { - /* user data start */ - - } else if (code == 0xB4) { - /* sequence error */ - } else if (code == 0xB7) { - /* sequence end */ - } else if (code == 0xB8) { - /* group start */ - } else if (code >= 0xB9) { - /* system start */ - } else { - /* reserved */ - } - - /* resync to byte boundary */ - vl_vlc_eatbits(vlc, vl_vlc_valid_bits(vlc) % 8); -} diff --git a/src/gallium/state_trackers/omx/bellagio/vid_enc.c b/src/gallium/state_trackers/omx/bellagio/vid_enc.c deleted file mode 100644 index 7f4a673d3cd..00000000000 --- a/src/gallium/state_trackers/omx/bellagio/vid_enc.c +++ /dev/null @@ -1,940 +0,0 @@ -/************************************************************************** - * - * Copyright 2013 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/* - * Authors: - * Christian König - * - */ - - -#include - -#include - -/* bellagio defines a DEBUG macro that we don't want */ -#ifndef DEBUG -#include -#undef DEBUG -#else -#include -#endif - -#include - -#include "pipe/p_screen.h" -#include "pipe/p_video_codec.h" -#include "util/u_memory.h" - -#include "entrypoint.h" -#include "vid_enc.h" -#include "vid_omx_common.h" -#include "vid_enc_common.h" - -static OMX_ERRORTYPE vid_enc_Constructor(OMX_COMPONENTTYPE *comp, OMX_STRING name); -static OMX_ERRORTYPE vid_enc_Destructor(OMX_COMPONENTTYPE *comp); -static OMX_ERRORTYPE vid_enc_SetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param); -static OMX_ERRORTYPE vid_enc_GetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param); -static OMX_ERRORTYPE vid_enc_SetConfig(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR config); -static OMX_ERRORTYPE vid_enc_GetConfig(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR config); -static OMX_ERRORTYPE vid_enc_MessageHandler(OMX_COMPONENTTYPE *comp, internalRequestMessageType *msg); -static OMX_ERRORTYPE vid_enc_AllocateInBuffer(omx_base_PortType *port, OMX_INOUT OMX_BUFFERHEADERTYPE **buf, - OMX_IN OMX_U32 idx, OMX_IN OMX_PTR private, OMX_IN OMX_U32 size); -static OMX_ERRORTYPE vid_enc_UseInBuffer(omx_base_PortType *port, OMX_BUFFERHEADERTYPE **buf, OMX_U32 idx, - OMX_PTR private, OMX_U32 size, OMX_U8 *mem); -static OMX_ERRORTYPE vid_enc_FreeInBuffer(omx_base_PortType *port, OMX_U32 idx, OMX_BUFFERHEADERTYPE *buf); -static OMX_ERRORTYPE vid_enc_EncodeFrame(omx_base_PortType *port, OMX_BUFFERHEADERTYPE *buf); -static OMX_ERRORTYPE vid_enc_AllocateOutBuffer(omx_base_PortType *comp, OMX_INOUT OMX_BUFFERHEADERTYPE **buf, - OMX_IN OMX_U32 idx, OMX_IN OMX_PTR private, OMX_IN OMX_U32 size); -static OMX_ERRORTYPE vid_enc_FreeOutBuffer(omx_base_PortType *port, OMX_U32 idx, OMX_BUFFERHEADERTYPE *buf); -static void vid_enc_BufferEncoded(OMX_COMPONENTTYPE *comp, OMX_BUFFERHEADERTYPE* input, OMX_BUFFERHEADERTYPE* output); - -OMX_ERRORTYPE vid_enc_LoaderComponent(stLoaderComponentType *comp) -{ - comp->componentVersion.s.nVersionMajor = 0; - comp->componentVersion.s.nVersionMinor = 0; - comp->componentVersion.s.nRevision = 0; - comp->componentVersion.s.nStep = 1; - comp->name_specific_length = 1; - comp->constructor = vid_enc_Constructor; - - comp->name = CALLOC(1, OMX_MAX_STRINGNAME_SIZE); - if (!comp->name) - return OMX_ErrorInsufficientResources; - - comp->name_specific = CALLOC(1, sizeof(char *)); - if (!comp->name_specific) - goto error_arrays; - - comp->role_specific = CALLOC(1, sizeof(char *)); - if (!comp->role_specific) - goto error_arrays; - - comp->name_specific[0] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE); - if (comp->name_specific[0] == NULL) - goto error_specific; - - comp->role_specific[0] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE); - if (comp->role_specific[0] == NULL) - goto error_specific; - - strcpy(comp->name, OMX_VID_ENC_BASE_NAME); - strcpy(comp->name_specific[0], OMX_VID_ENC_AVC_NAME); - strcpy(comp->role_specific[0], OMX_VID_ENC_AVC_ROLE); - - return OMX_ErrorNone; - -error_specific: - FREE(comp->role_specific[0]); - FREE(comp->name_specific[0]); - -error_arrays: - FREE(comp->role_specific); - FREE(comp->name_specific); - - FREE(comp->name); - - return OMX_ErrorInsufficientResources; -} - -static OMX_ERRORTYPE vid_enc_Constructor(OMX_COMPONENTTYPE *comp, OMX_STRING name) -{ - vid_enc_PrivateType *priv; - omx_base_video_PortType *port; - struct pipe_screen *screen; - OMX_ERRORTYPE r; - int i; - - assert(!comp->pComponentPrivate); - - priv = comp->pComponentPrivate = CALLOC(1, sizeof(vid_enc_PrivateType)); - if (!priv) - return OMX_ErrorInsufficientResources; - - r = omx_base_filter_Constructor(comp, name); - if (r) - return r; - - priv->BufferMgmtCallback = vid_enc_BufferEncoded; - priv->messageHandler = vid_enc_MessageHandler; - priv->destructor = vid_enc_Destructor; - - comp->SetParameter = vid_enc_SetParameter; - comp->GetParameter = vid_enc_GetParameter; - comp->GetConfig = vid_enc_GetConfig; - comp->SetConfig = vid_enc_SetConfig; - - priv->screen = omx_get_screen(); - if (!priv->screen) - return OMX_ErrorInsufficientResources; - - screen = priv->screen->pscreen; - if (!screen->get_video_param(screen, PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH, - PIPE_VIDEO_ENTRYPOINT_ENCODE, PIPE_VIDEO_CAP_SUPPORTED)) - return OMX_ErrorBadParameter; - - priv->s_pipe = pipe_create_multimedia_context(screen); - if (!priv->s_pipe) - return OMX_ErrorInsufficientResources; - - enc_InitCompute_common(priv); - - if (!vl_compositor_init(&priv->compositor, priv->s_pipe)) { - priv->s_pipe->destroy(priv->s_pipe); - priv->s_pipe = NULL; - return OMX_ErrorInsufficientResources; - } - - if (!vl_compositor_init_state(&priv->cstate, priv->s_pipe)) { - vl_compositor_cleanup(&priv->compositor); - priv->s_pipe->destroy(priv->s_pipe); - priv->s_pipe = NULL; - return OMX_ErrorInsufficientResources; - } - - priv->t_pipe = pipe_create_multimedia_context(screen); - if (!priv->t_pipe) - return OMX_ErrorInsufficientResources; - - priv->sPortTypesParam[OMX_PortDomainVideo].nStartPortNumber = 0; - priv->sPortTypesParam[OMX_PortDomainVideo].nPorts = 2; - priv->ports = CALLOC(2, sizeof(omx_base_PortType *)); - if (!priv->ports) - return OMX_ErrorInsufficientResources; - - for (i = 0; i < 2; ++i) { - priv->ports[i] = CALLOC(1, sizeof(omx_base_video_PortType)); - if (!priv->ports[i]) - return OMX_ErrorInsufficientResources; - - base_video_port_Constructor(comp, &priv->ports[i], i, i == 0); - } - - port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; - port->sPortParam.format.video.nFrameWidth = 176; - port->sPortParam.format.video.nFrameHeight = 144; - port->sPortParam.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; - port->sVideoParam.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; - port->sPortParam.nBufferCountActual = 8; - port->sPortParam.nBufferCountMin = 4; - - port->Port_SendBufferFunction = vid_enc_EncodeFrame; - port->Port_AllocateBuffer = vid_enc_AllocateInBuffer; - port->Port_UseBuffer = vid_enc_UseInBuffer; - port->Port_FreeBuffer = vid_enc_FreeInBuffer; - - port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]; - strcpy(port->sPortParam.format.video.cMIMEType,"video/H264"); - port->sPortParam.format.video.nFrameWidth = 176; - port->sPortParam.format.video.nFrameHeight = 144; - port->sPortParam.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC; - port->sVideoParam.eCompressionFormat = OMX_VIDEO_CodingAVC; - - port->Port_AllocateBuffer = vid_enc_AllocateOutBuffer; - port->Port_FreeBuffer = vid_enc_FreeOutBuffer; - - priv->bitrate.eControlRate = OMX_Video_ControlRateDisable; - priv->bitrate.nTargetBitrate = 0; - - priv->quant.nQpI = OMX_VID_ENC_QUANT_I_FRAMES_DEFAULT; - priv->quant.nQpP = OMX_VID_ENC_QUANT_P_FRAMES_DEFAULT; - priv->quant.nQpB = OMX_VID_ENC_QUANT_B_FRAMES_DEFAULT; - - priv->profile_level.eProfile = OMX_VIDEO_AVCProfileBaseline; - priv->profile_level.eLevel = OMX_VIDEO_AVCLevel51; - - priv->force_pic_type.IntraRefreshVOP = OMX_FALSE; - priv->frame_num = 0; - priv->pic_order_cnt = 0; - priv->restricted_b_frames = debug_get_bool_option("OMX_USE_RESTRICTED_B_FRAMES", FALSE); - - priv->scale.xWidth = OMX_VID_ENC_SCALING_WIDTH_DEFAULT; - priv->scale.xHeight = OMX_VID_ENC_SCALING_WIDTH_DEFAULT; - - list_inithead(&priv->free_tasks); - list_inithead(&priv->used_tasks); - list_inithead(&priv->b_frames); - list_inithead(&priv->stacked_tasks); - - return OMX_ErrorNone; -} - -static OMX_ERRORTYPE vid_enc_Destructor(OMX_COMPONENTTYPE *comp) -{ - vid_enc_PrivateType* priv = comp->pComponentPrivate; - int i; - - enc_ReleaseTasks(&priv->free_tasks); - enc_ReleaseTasks(&priv->used_tasks); - enc_ReleaseTasks(&priv->b_frames); - enc_ReleaseTasks(&priv->stacked_tasks); - - if (priv->ports) { - for (i = 0; i < priv->sPortTypesParam[OMX_PortDomainVideo].nPorts; ++i) { - if(priv->ports[i]) - priv->ports[i]->PortDestructor(priv->ports[i]); - } - FREE(priv->ports); - priv->ports=NULL; - } - - for (i = 0; i < OMX_VID_ENC_NUM_SCALING_BUFFERS; ++i) - if (priv->scale_buffer[i]) - priv->scale_buffer[i]->destroy(priv->scale_buffer[i]); - - if (priv->s_pipe) { - vl_compositor_cleanup_state(&priv->cstate); - vl_compositor_cleanup(&priv->compositor); - enc_ReleaseCompute_common(priv); - priv->s_pipe->destroy(priv->s_pipe); - } - - if (priv->t_pipe) - priv->t_pipe->destroy(priv->t_pipe); - - if (priv->screen) - omx_put_screen(); - - return omx_workaround_Destructor(comp); -} - -static OMX_ERRORTYPE enc_AllocateBackTexture(omx_base_PortType *port, - struct pipe_resource **resource, - struct pipe_transfer **transfer, - OMX_U8 **map) -{ - OMX_COMPONENTTYPE* comp = port->standCompContainer; - vid_enc_PrivateType *priv = comp->pComponentPrivate; - struct pipe_resource buf_templ; - struct pipe_box box = {}; - OMX_U8 *ptr; - - memset(&buf_templ, 0, sizeof buf_templ); - buf_templ.target = PIPE_TEXTURE_2D; - buf_templ.format = PIPE_FORMAT_I8_UNORM; - buf_templ.bind = PIPE_BIND_LINEAR; - buf_templ.usage = PIPE_USAGE_STAGING; - buf_templ.flags = 0; - buf_templ.width0 = port->sPortParam.format.video.nFrameWidth; - buf_templ.height0 = port->sPortParam.format.video.nFrameHeight * 3 / 2; - buf_templ.depth0 = 1; - buf_templ.array_size = 1; - - *resource = priv->s_pipe->screen->resource_create(priv->s_pipe->screen, &buf_templ); - if (!*resource) - return OMX_ErrorInsufficientResources; - - box.width = (*resource)->width0; - box.height = (*resource)->height0; - box.depth = (*resource)->depth0; - ptr = priv->s_pipe->transfer_map(priv->s_pipe, *resource, 0, PIPE_TRANSFER_WRITE, &box, transfer); - if (map) - *map = ptr; - - return OMX_ErrorNone; -} - -static OMX_ERRORTYPE vid_enc_SetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param) -{ - OMX_COMPONENTTYPE *comp = handle; - vid_enc_PrivateType *priv = comp->pComponentPrivate; - OMX_ERRORTYPE r; - - if (!param) - return OMX_ErrorBadParameter; - - switch(idx) { - case OMX_IndexParamPortDefinition: { - OMX_PARAM_PORTDEFINITIONTYPE *def = param; - - r = omx_base_component_SetParameter(handle, idx, param); - if (r) - return r; - - if (def->nPortIndex == OMX_BASE_FILTER_INPUTPORT_INDEX) { - omx_base_video_PortType *port; - unsigned framesize; - struct pipe_resource *resource; - struct pipe_transfer *transfer; - - port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; - enc_AllocateBackTexture(priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX], - &resource, &transfer, NULL); - port->sPortParam.format.video.nStride = transfer->stride; - pipe_transfer_unmap(priv->s_pipe, transfer); - pipe_resource_reference(&resource, NULL); - - framesize = port->sPortParam.format.video.nStride * - port->sPortParam.format.video.nFrameHeight; - port->sPortParam.format.video.nSliceHeight = port->sPortParam.format.video.nFrameHeight; - port->sPortParam.nBufferSize = framesize * 3 / 2; - - port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]; - port->sPortParam.nBufferSize = framesize * 512 / (16*16); - - priv->frame_rate = def->format.video.xFramerate; - - priv->callbacks->EventHandler(comp, priv->callbackData, OMX_EventPortSettingsChanged, - OMX_BASE_FILTER_OUTPUTPORT_INDEX, 0, NULL); - } - break; - } - case OMX_IndexParamStandardComponentRole: { - OMX_PARAM_COMPONENTROLETYPE *role = param; - - r = checkHeader(param, sizeof(OMX_PARAM_COMPONENTROLETYPE)); - if (r) - return r; - - if (strcmp((char *)role->cRole, OMX_VID_ENC_AVC_ROLE)) { - return OMX_ErrorBadParameter; - } - - break; - } - case OMX_IndexParamVideoBitrate: { - OMX_VIDEO_PARAM_BITRATETYPE *bitrate = param; - - r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_BITRATETYPE)); - if (r) - return r; - - priv->bitrate = *bitrate; - - break; - } - case OMX_IndexParamVideoQuantization: { - OMX_VIDEO_PARAM_QUANTIZATIONTYPE *quant = param; - - r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_QUANTIZATIONTYPE)); - if (r) - return r; - - priv->quant = *quant; - - break; - } - case OMX_IndexParamVideoProfileLevelCurrent: { - OMX_VIDEO_PARAM_PROFILELEVELTYPE *profile_level = param; - - r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); - if (r) - return r; - - priv->profile_level = *profile_level; - - break; - } - default: - return omx_base_component_SetParameter(handle, idx, param); - } - return OMX_ErrorNone; -} - -static OMX_ERRORTYPE vid_enc_GetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param) -{ - OMX_COMPONENTTYPE *comp = handle; - vid_enc_PrivateType *priv = comp->pComponentPrivate; - OMX_ERRORTYPE r; - - if (!param) - return OMX_ErrorBadParameter; - - switch(idx) { - case OMX_IndexParamStandardComponentRole: { - OMX_PARAM_COMPONENTROLETYPE *role = param; - - r = checkHeader(param, sizeof(OMX_PARAM_COMPONENTROLETYPE)); - if (r) - return r; - - strcpy((char *)role->cRole, OMX_VID_ENC_AVC_ROLE); - break; - } - case OMX_IndexParamVideoInit: - r = checkHeader(param, sizeof(OMX_PORT_PARAM_TYPE)); - if (r) - return r; - - memcpy(param, &priv->sPortTypesParam[OMX_PortDomainVideo], sizeof(OMX_PORT_PARAM_TYPE)); - break; - - case OMX_IndexParamVideoPortFormat: { - OMX_VIDEO_PARAM_PORTFORMATTYPE *format = param; - omx_base_video_PortType *port; - - r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); - if (r) - return r; - - if (format->nPortIndex > 1) - return OMX_ErrorBadPortIndex; - if (format->nIndex >= 1) - return OMX_ErrorNoMore; - - port = (omx_base_video_PortType *)priv->ports[format->nPortIndex]; - memcpy(format, &port->sVideoParam, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); - break; - } - case OMX_IndexParamVideoBitrate: { - OMX_VIDEO_PARAM_BITRATETYPE *bitrate = param; - - r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_BITRATETYPE)); - if (r) - return r; - - bitrate->eControlRate = priv->bitrate.eControlRate; - bitrate->nTargetBitrate = priv->bitrate.nTargetBitrate; - - break; - } - case OMX_IndexParamVideoQuantization: { - OMX_VIDEO_PARAM_QUANTIZATIONTYPE *quant = param; - - r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_QUANTIZATIONTYPE)); - if (r) - return r; - - quant->nQpI = priv->quant.nQpI; - quant->nQpP = priv->quant.nQpP; - quant->nQpB = priv->quant.nQpB; - - break; - } - case OMX_IndexParamVideoProfileLevelCurrent: { - OMX_VIDEO_PARAM_PROFILELEVELTYPE *profile_level = param; - - r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); - if (r) - return r; - - profile_level->eProfile = priv->profile_level.eProfile; - profile_level->eLevel = priv->profile_level.eLevel; - - break; - } - default: - return omx_base_component_GetParameter(handle, idx, param); - } - return OMX_ErrorNone; -} - -static OMX_ERRORTYPE vid_enc_SetConfig(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR config) -{ - OMX_COMPONENTTYPE *comp = handle; - vid_enc_PrivateType *priv = comp->pComponentPrivate; - OMX_ERRORTYPE r; - int i; - - if (!config) - return OMX_ErrorBadParameter; - - switch(idx) { - case OMX_IndexConfigVideoIntraVOPRefresh: { - OMX_CONFIG_INTRAREFRESHVOPTYPE *type = config; - - r = checkHeader(config, sizeof(OMX_CONFIG_INTRAREFRESHVOPTYPE)); - if (r) - return r; - - priv->force_pic_type = *type; - - break; - } - case OMX_IndexConfigCommonScale: { - OMX_CONFIG_SCALEFACTORTYPE *scale = config; - - r = checkHeader(config, sizeof(OMX_CONFIG_SCALEFACTORTYPE)); - if (r) - return r; - - if (scale->xWidth < 176 || scale->xHeight < 144) - return OMX_ErrorBadParameter; - - for (i = 0; i < OMX_VID_ENC_NUM_SCALING_BUFFERS; ++i) { - if (priv->scale_buffer[i]) { - priv->scale_buffer[i]->destroy(priv->scale_buffer[i]); - priv->scale_buffer[i] = NULL; - } - } - - priv->scale = *scale; - if (priv->scale.xWidth != 0xffffffff && priv->scale.xHeight != 0xffffffff) { - struct pipe_video_buffer templat = {}; - - templat.buffer_format = PIPE_FORMAT_NV12; - templat.width = priv->scale.xWidth; - templat.height = priv->scale.xHeight; - templat.interlaced = false; - for (i = 0; i < OMX_VID_ENC_NUM_SCALING_BUFFERS; ++i) { - priv->scale_buffer[i] = priv->s_pipe->create_video_buffer(priv->s_pipe, &templat); - if (!priv->scale_buffer[i]) - return OMX_ErrorInsufficientResources; - } - } - - break; - } - default: - return omx_base_component_SetConfig(handle, idx, config); - } - - return OMX_ErrorNone; -} - -static OMX_ERRORTYPE vid_enc_GetConfig(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR config) -{ - OMX_COMPONENTTYPE *comp = handle; - vid_enc_PrivateType *priv = comp->pComponentPrivate; - OMX_ERRORTYPE r; - - if (!config) - return OMX_ErrorBadParameter; - - switch(idx) { - case OMX_IndexConfigCommonScale: { - OMX_CONFIG_SCALEFACTORTYPE *scale = config; - - r = checkHeader(config, sizeof(OMX_CONFIG_SCALEFACTORTYPE)); - if (r) - return r; - - scale->xWidth = priv->scale.xWidth; - scale->xHeight = priv->scale.xHeight; - - break; - } - default: - return omx_base_component_GetConfig(handle, idx, config); - } - - return OMX_ErrorNone; -} - -static OMX_ERRORTYPE vid_enc_MessageHandler(OMX_COMPONENTTYPE* comp, internalRequestMessageType *msg) -{ - vid_enc_PrivateType* priv = comp->pComponentPrivate; - - if (msg->messageType == OMX_CommandStateSet) { - if ((msg->messageParam == OMX_StateIdle ) && (priv->state == OMX_StateLoaded)) { - - struct pipe_video_codec templat = {}; - omx_base_video_PortType *port; - - port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; - - templat.profile = enc_TranslateOMXProfileToPipe(priv->profile_level.eProfile); - templat.level = enc_TranslateOMXLevelToPipe(priv->profile_level.eLevel); - templat.entrypoint = PIPE_VIDEO_ENTRYPOINT_ENCODE; - templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; - templat.width = priv->scale_buffer[priv->current_scale_buffer] ? - priv->scale.xWidth : port->sPortParam.format.video.nFrameWidth; - templat.height = priv->scale_buffer[priv->current_scale_buffer] ? - priv->scale.xHeight : port->sPortParam.format.video.nFrameHeight; - - if (templat.profile == PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE) { - struct pipe_screen *screen = priv->screen->pscreen; - templat.max_references = 1; - priv->stacked_frames_num = - screen->get_video_param(screen, - PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH, - PIPE_VIDEO_ENTRYPOINT_ENCODE, - PIPE_VIDEO_CAP_STACKED_FRAMES); - } else { - templat.max_references = OMX_VID_ENC_P_PERIOD_DEFAULT; - priv->stacked_frames_num = 1; - } - priv->codec = priv->s_pipe->create_video_codec(priv->s_pipe, &templat); - - } else if ((msg->messageParam == OMX_StateLoaded) && (priv->state == OMX_StateIdle)) { - if (priv->codec) { - priv->codec->destroy(priv->codec); - priv->codec = NULL; - } - } - } - - return omx_base_component_MessageHandler(comp, msg); -} - -static OMX_ERRORTYPE vid_enc_AllocateInBuffer(omx_base_PortType *port, OMX_INOUT OMX_BUFFERHEADERTYPE **buf, - OMX_IN OMX_U32 idx, OMX_IN OMX_PTR private, OMX_IN OMX_U32 size) -{ - struct input_buf_private *inp; - OMX_ERRORTYPE r; - - r = base_port_AllocateBuffer(port, buf, idx, private, size); - if (r) - return r; - - inp = (*buf)->pInputPortPrivate = CALLOC_STRUCT(input_buf_private); - if (!inp) { - base_port_FreeBuffer(port, idx, *buf); - return OMX_ErrorInsufficientResources; - } - - list_inithead(&inp->tasks); - - FREE((*buf)->pBuffer); - r = enc_AllocateBackTexture(port, &inp->resource, &inp->transfer, &(*buf)->pBuffer); - if (r) { - FREE(inp); - base_port_FreeBuffer(port, idx, *buf); - return r; - } - - return OMX_ErrorNone; -} - -static OMX_ERRORTYPE vid_enc_UseInBuffer(omx_base_PortType *port, OMX_BUFFERHEADERTYPE **buf, OMX_U32 idx, - OMX_PTR private, OMX_U32 size, OMX_U8 *mem) -{ - struct input_buf_private *inp; - OMX_ERRORTYPE r; - - r = base_port_UseBuffer(port, buf, idx, private, size, mem); - if (r) - return r; - - inp = (*buf)->pInputPortPrivate = CALLOC_STRUCT(input_buf_private); - if (!inp) { - base_port_FreeBuffer(port, idx, *buf); - return OMX_ErrorInsufficientResources; - } - - list_inithead(&inp->tasks); - - return OMX_ErrorNone; -} - -static OMX_ERRORTYPE vid_enc_FreeInBuffer(omx_base_PortType *port, OMX_U32 idx, OMX_BUFFERHEADERTYPE *buf) -{ - OMX_COMPONENTTYPE* comp = port->standCompContainer; - vid_enc_PrivateType *priv = comp->pComponentPrivate; - struct input_buf_private *inp = buf->pInputPortPrivate; - - if (inp) { - enc_ReleaseTasks(&inp->tasks); - if (inp->transfer) - pipe_transfer_unmap(priv->s_pipe, inp->transfer); - pipe_resource_reference(&inp->resource, NULL); - FREE(inp); - } - buf->pBuffer = NULL; - - return base_port_FreeBuffer(port, idx, buf); -} - -static OMX_ERRORTYPE vid_enc_AllocateOutBuffer(omx_base_PortType *port, OMX_INOUT OMX_BUFFERHEADERTYPE **buf, - OMX_IN OMX_U32 idx, OMX_IN OMX_PTR private, OMX_IN OMX_U32 size) -{ - OMX_ERRORTYPE r; - - r = base_port_AllocateBuffer(port, buf, idx, private, size); - if (r) - return r; - - FREE((*buf)->pBuffer); - (*buf)->pBuffer = NULL; - (*buf)->pOutputPortPrivate = CALLOC(1, sizeof(struct output_buf_private)); - if (!(*buf)->pOutputPortPrivate) { - base_port_FreeBuffer(port, idx, *buf); - return OMX_ErrorInsufficientResources; - } - - return OMX_ErrorNone; -} - -static OMX_ERRORTYPE vid_enc_FreeOutBuffer(omx_base_PortType *port, OMX_U32 idx, OMX_BUFFERHEADERTYPE *buf) -{ - OMX_COMPONENTTYPE* comp = port->standCompContainer; - vid_enc_PrivateType *priv = comp->pComponentPrivate; - - if (buf->pOutputPortPrivate) { - struct output_buf_private *outp = buf->pOutputPortPrivate; - if (outp->transfer) - pipe_transfer_unmap(priv->t_pipe, outp->transfer); - pipe_resource_reference(&outp->bitstream, NULL); - FREE(outp); - buf->pOutputPortPrivate = NULL; - } - buf->pBuffer = NULL; - - return base_port_FreeBuffer(port, idx, buf); -} - -static struct encode_task *enc_NeedTask(omx_base_PortType *port) -{ - OMX_VIDEO_PORTDEFINITIONTYPE *def = &port->sPortParam.format.video; - OMX_COMPONENTTYPE* comp = port->standCompContainer; - vid_enc_PrivateType *priv = comp->pComponentPrivate; - - return enc_NeedTask_common(priv, def); -} - -static OMX_ERRORTYPE enc_LoadImage(omx_base_PortType *port, OMX_BUFFERHEADERTYPE *buf, - struct pipe_video_buffer *vbuf) -{ - OMX_COMPONENTTYPE* comp = port->standCompContainer; - vid_enc_PrivateType *priv = comp->pComponentPrivate; - OMX_VIDEO_PORTDEFINITIONTYPE *def = &port->sPortParam.format.video; - return enc_LoadImage_common(priv, def, buf, vbuf); -} - -static void enc_ScaleInput(omx_base_PortType *port, struct pipe_video_buffer **vbuf, unsigned *size) -{ - OMX_COMPONENTTYPE* comp = port->standCompContainer; - vid_enc_PrivateType *priv = comp->pComponentPrivate; - OMX_VIDEO_PORTDEFINITIONTYPE *def = &port->sPortParam.format.video; - enc_ScaleInput_common(priv, def, vbuf, size); -} - -static void enc_ControlPicture(omx_base_PortType *port, struct pipe_h264_enc_picture_desc *picture) -{ - OMX_COMPONENTTYPE* comp = port->standCompContainer; - vid_enc_PrivateType *priv = comp->pComponentPrivate; - enc_ControlPicture_common(priv, picture); -} - -static void enc_HandleTask(omx_base_PortType *port, struct encode_task *task, - enum pipe_h264_enc_picture_type picture_type) -{ - OMX_COMPONENTTYPE* comp = port->standCompContainer; - vid_enc_PrivateType *priv = comp->pComponentPrivate; - unsigned size = priv->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]->sPortParam.nBufferSize; - struct pipe_video_buffer *vbuf = task->buf; - struct pipe_h264_enc_picture_desc picture = {}; - - /* -------------- scale input image --------- */ - enc_ScaleInput(port, &vbuf, &size); - priv->s_pipe->flush(priv->s_pipe, NULL, 0); - - /* -------------- allocate output buffer --------- */ - task->bitstream = pipe_buffer_create(priv->s_pipe->screen, - PIPE_BIND_VERTEX_BUFFER, - PIPE_USAGE_STAGING, /* map for read */ - size); - - picture.picture_type = picture_type; - picture.pic_order_cnt = task->pic_order_cnt; - picture.base.profile = enc_TranslateOMXProfileToPipe(priv->profile_level.eProfile); - picture.base.entry_point = PIPE_VIDEO_ENTRYPOINT_ENCODE; - if (priv->restricted_b_frames && picture_type == PIPE_H264_ENC_PICTURE_TYPE_B) - picture.not_referenced = true; - enc_ControlPicture(port, &picture); - - /* -------------- encode frame --------- */ - priv->codec->begin_frame(priv->codec, vbuf, &picture.base); - priv->codec->encode_bitstream(priv->codec, vbuf, task->bitstream, &task->feedback); - priv->codec->end_frame(priv->codec, vbuf, &picture.base); -} - -static void enc_ClearBframes(omx_base_PortType *port, struct input_buf_private *inp) -{ - OMX_COMPONENTTYPE* comp = port->standCompContainer; - vid_enc_PrivateType *priv = comp->pComponentPrivate; - struct encode_task *task; - - if (list_is_empty(&priv->b_frames)) - return; - - task = LIST_ENTRY(struct encode_task, priv->b_frames.prev, list); - list_del(&task->list); - - /* promote last from to P frame */ - priv->ref_idx_l0 = priv->ref_idx_l1; - enc_HandleTask(port, task, PIPE_H264_ENC_PICTURE_TYPE_P); - list_addtail(&task->list, &inp->tasks); - priv->ref_idx_l1 = priv->frame_num++; - - /* handle B frames */ - LIST_FOR_EACH_ENTRY(task, &priv->b_frames, list) { - enc_HandleTask(port, task, PIPE_H264_ENC_PICTURE_TYPE_B); - if (!priv->restricted_b_frames) - priv->ref_idx_l0 = priv->frame_num; - priv->frame_num++; - } - - enc_MoveTasks(&priv->b_frames, &inp->tasks); -} - -static OMX_ERRORTYPE vid_enc_EncodeFrame(omx_base_PortType *port, OMX_BUFFERHEADERTYPE *buf) -{ - OMX_COMPONENTTYPE* comp = port->standCompContainer; - vid_enc_PrivateType *priv = comp->pComponentPrivate; - struct input_buf_private *inp = buf->pInputPortPrivate; - enum pipe_h264_enc_picture_type picture_type; - struct encode_task *task; - unsigned stacked_num = 0; - OMX_ERRORTYPE err; - - enc_MoveTasks(&inp->tasks, &priv->free_tasks); - task = enc_NeedTask(port); - if (!task) - return OMX_ErrorInsufficientResources; - - if (buf->nFilledLen == 0) { - if (buf->nFlags & OMX_BUFFERFLAG_EOS) { - buf->nFilledLen = buf->nAllocLen; - enc_ClearBframes(port, inp); - enc_MoveTasks(&priv->stacked_tasks, &inp->tasks); - priv->codec->flush(priv->codec); - } - return base_port_SendBufferFunction(port, buf); - } - - if (buf->pOutputPortPrivate) { - struct pipe_video_buffer *vbuf = buf->pOutputPortPrivate; - buf->pOutputPortPrivate = task->buf; - task->buf = vbuf; - } else { - /* ------- load input image into video buffer ---- */ - err = enc_LoadImage(port, buf, task->buf); - if (err != OMX_ErrorNone) { - FREE(task); - return err; - } - } - - /* -------------- determine picture type --------- */ - if (!(priv->pic_order_cnt % OMX_VID_ENC_IDR_PERIOD_DEFAULT) || - priv->force_pic_type.IntraRefreshVOP) { - enc_ClearBframes(port, inp); - picture_type = PIPE_H264_ENC_PICTURE_TYPE_IDR; - priv->force_pic_type.IntraRefreshVOP = OMX_FALSE; - priv->frame_num = 0; - } else if (priv->codec->profile == PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE || - !(priv->pic_order_cnt % OMX_VID_ENC_P_PERIOD_DEFAULT) || - (buf->nFlags & OMX_BUFFERFLAG_EOS)) { - picture_type = PIPE_H264_ENC_PICTURE_TYPE_P; - } else { - picture_type = PIPE_H264_ENC_PICTURE_TYPE_B; - } - - task->pic_order_cnt = priv->pic_order_cnt++; - - if (picture_type == PIPE_H264_ENC_PICTURE_TYPE_B) { - /* put frame at the tail of the queue */ - list_addtail(&task->list, &priv->b_frames); - } else { - /* handle I or P frame */ - priv->ref_idx_l0 = priv->ref_idx_l1; - enc_HandleTask(port, task, picture_type); - list_addtail(&task->list, &priv->stacked_tasks); - LIST_FOR_EACH_ENTRY(task, &priv->stacked_tasks, list) { - ++stacked_num; - } - if (stacked_num == priv->stacked_frames_num) { - struct encode_task *t; - t = LIST_ENTRY(struct encode_task, priv->stacked_tasks.next, list); - list_del(&t->list); - list_addtail(&t->list, &inp->tasks); - } - priv->ref_idx_l1 = priv->frame_num++; - - /* handle B frames */ - LIST_FOR_EACH_ENTRY(task, &priv->b_frames, list) { - enc_HandleTask(port, task, PIPE_H264_ENC_PICTURE_TYPE_B); - if (!priv->restricted_b_frames) - priv->ref_idx_l0 = priv->frame_num; - priv->frame_num++; - } - - enc_MoveTasks(&priv->b_frames, &inp->tasks); - } - - if (list_is_empty(&inp->tasks)) - return port->ReturnBufferFunction(port, buf); - else - return base_port_SendBufferFunction(port, buf); -} - -static void vid_enc_BufferEncoded(OMX_COMPONENTTYPE *comp, OMX_BUFFERHEADERTYPE* input, OMX_BUFFERHEADERTYPE* output) -{ - vid_enc_PrivateType *priv = comp->pComponentPrivate; - vid_enc_BufferEncoded_common(priv, input, output); -} diff --git a/src/gallium/state_trackers/omx/bellagio/vid_enc.h b/src/gallium/state_trackers/omx/bellagio/vid_enc.h deleted file mode 100644 index 4d2b867261b..00000000000 --- a/src/gallium/state_trackers/omx/bellagio/vid_enc.h +++ /dev/null @@ -1,48 +0,0 @@ -/************************************************************************** - * - * Copyright 2013 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/* - * Authors: - * Christian König - * - */ - -#ifndef OMX_VID_ENC_H -#define OMX_VID_ENC_H - -#include -#include - -#include - -#define OMX_VID_ENC_BASE_NAME "OMX.mesa.video_encoder" -#define OMX_VID_ENC_AVC_NAME "OMX.mesa.video_encoder.avc" -#define OMX_VID_ENC_AVC_ROLE "video_encoder.avc" - -OMX_ERRORTYPE vid_enc_LoaderComponent(stLoaderComponentType *comp); - -#endif diff --git a/src/gallium/state_trackers/omx/meson.build b/src/gallium/state_trackers/omx/meson.build deleted file mode 100644 index 35866c1cba0..00000000000 --- a/src/gallium/state_trackers/omx/meson.build +++ /dev/null @@ -1,71 +0,0 @@ -# Copyright © 2017, 2019 Intel Corporation - -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: - -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. - -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -inc_st_omx = [inc_include, inc_src, inc_mapi, inc_mesa, inc_gallium, inc_gallium_aux] -dep_st_omx = [ - dep_omx, dep_x11_xcb, dep_xcb, dep_xcb_dri2, dep_xcb_dri3, dep_libdrm, -] - -files_omx = files( - 'vid_dec_common.c', - 'vid_dec_h264_common.c', - 'vid_enc_common.c', - 'vid_omx_common.c' -) - -if with_gallium_omx == 'bellagio' - files_omx += files( - 'bellagio/entrypoint.c', - 'bellagio/vid_dec.c', - 'bellagio/vid_dec_mpeg12.c', - 'bellagio/vid_dec_h264.c', - 'bellagio/vid_dec_h265.c', - 'bellagio/vid_enc.c' - ) -elif with_gallium_omx == 'tizonia' - files_omx += files( - 'tizonia/entrypoint.c', - 'tizonia/h264d.c', - 'tizonia/h264dprc.c', - 'tizonia/h264dinport.c', - 'tizonia/h264e.c', - 'tizonia/h264eprc.c', - 'tizonia/h264einport.c', - 'tizonia/h264eoutport.c' - ) - inc_st_omx = [ - inc_st_omx, - inc_dri_common, - inc_loader, - inc_gbm, - inc_st_dri, - inc_egl, - inc_egl_dri2, - ] - dep_st_omx = [dep_st_omx, dep_omx_other] -endif - -libomx_st = static_library( - 'omx_st', - files_omx, - c_args : [c_vis_args, '-fcommon'], - include_directories : inc_st_omx, - dependencies : dep_st_omx, -) diff --git a/src/gallium/state_trackers/omx/tizonia/Makefile.sources b/src/gallium/state_trackers/omx/tizonia/Makefile.sources deleted file mode 100644 index 7e039d3c5ad..00000000000 --- a/src/gallium/state_trackers/omx/tizonia/Makefile.sources +++ /dev/null @@ -1,22 +0,0 @@ -C_SOURCES := \ - entrypoint.c \ - entrypoint.h \ - h264d.c \ - h264d.h \ - h264dprc.c \ - h264dprc.h \ - h264dinport.c \ - h264dinport.h \ - h264dinport_decls.h \ - h264e.c \ - h264e.h \ - h264eprc.c \ - h264eprc.h \ - h264einport.h \ - h264einport.c \ - h264einport_decls.h \ - h264einport.h \ - h264eoutport.c \ - h264eoutport_decls.h \ - h264eoutport.h \ - names.h diff --git a/src/gallium/state_trackers/omx/tizonia/entrypoint.c b/src/gallium/state_trackers/omx/tizonia/entrypoint.c deleted file mode 100644 index a6c2c45b39e..00000000000 --- a/src/gallium/state_trackers/omx/tizonia/entrypoint.c +++ /dev/null @@ -1,158 +0,0 @@ -/************************************************************************** - * - * Copyright 2013 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include - -#include "vid_dec_h264_common.h" -#include "entrypoint.h" -#include "h264d.h" -#include "h264dprc.h" -#include "h264dinport.h" -#include "h264e.h" -#include "h264eprc.h" -#include "h264einport.h" -#include "h264eoutport.h" -#include "names.h" - -#include "util/u_debug.h" - -DEBUG_GET_ONCE_BOOL_OPTION(mesa_enable_omx_eglimage, - "MESA_ENABLE_OMX_EGLIMAGE", - false) - -static OMX_BOOL egl_image_validation_hook(const OMX_HANDLETYPE ap_hdl, - OMX_U32 pid, OMX_PTR ap_eglimage, - void *ap_args) -{ - const void * p_krn = NULL; - const tiz_port_t * p_port = NULL; - - assert(ap_hdl); - assert(ap_eglimage); - assert(!ap_args); - - if (!debug_get_option_mesa_enable_omx_eglimage()) { - return OMX_FALSE; - } - - p_krn = tiz_get_krn(ap_hdl); - p_port = tiz_krn_get_port(p_krn, pid); - - const OMX_VIDEO_PORTDEFINITIONTYPE * p_video_portdef - = &(p_port->portdef_.format.video); - - if (!p_video_portdef->pNativeWindow) { - return OMX_FALSE; - } - - return OMX_TRUE; -} - -OMX_ERRORTYPE OMX_ComponentInit (OMX_HANDLETYPE ap_hdl) -{ - tiz_role_factory_t h264d_role; - tiz_role_factory_t h264e_role; - const tiz_role_factory_t * rf_list[] = {&h264d_role, &h264e_role}; - tiz_type_factory_t h264dprc_type; - tiz_type_factory_t h264d_inport_type; - tiz_type_factory_t h264eprc_type; - tiz_type_factory_t h264e_inport_type; - tiz_type_factory_t h264e_outport_type; - const tiz_type_factory_t * tf_list[] = {&h264dprc_type, - &h264d_inport_type, - &h264eprc_type, - &h264e_inport_type, - &h264e_outport_type}; - const tiz_eglimage_hook_t egl_validation_hook = { - OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX, - egl_image_validation_hook, - NULL - }; - - /* Settings for roles */ - strcpy ((OMX_STRING) h264d_role.role, OMX_VID_DEC_AVC_ROLE); - h264d_role.pf_cport = instantiate_h264d_config_port; - h264d_role.pf_port[0] = instantiate_h264d_input_port; - h264d_role.pf_port[1] = instantiate_h264d_output_port; - h264d_role.nports = 2; - h264d_role.pf_proc = instantiate_h264d_processor; - - strcpy ((OMX_STRING) h264e_role.role, OMX_VID_ENC_AVC_ROLE); - h264e_role.pf_cport = instantiate_h264e_config_port; - h264e_role.pf_port[0] = instantiate_h264e_input_port; - h264e_role.pf_port[1] = instantiate_h264e_output_port; - h264e_role.nports = 2; - h264e_role.pf_proc = instantiate_h264e_processor; - - /* Settings for classes */ - strcpy ((OMX_STRING) h264dprc_type.class_name, "h264dprc_class"); - h264dprc_type.pf_class_init = h264d_prc_class_init; - strcpy ((OMX_STRING) h264dprc_type.object_name, "h264dprc"); - h264dprc_type.pf_object_init = h264d_prc_init; - - strcpy ((OMX_STRING) h264d_inport_type.class_name, "h264dinport_class"); - h264d_inport_type.pf_class_init = h264d_inport_class_init; - strcpy ((OMX_STRING) h264d_inport_type.object_name, "h264dinport"); - h264d_inport_type.pf_object_init = h264d_inport_init; - - strcpy ((OMX_STRING) h264eprc_type.class_name, "h264eprc_class"); - h264eprc_type.pf_class_init = h264e_prc_class_init; - strcpy ((OMX_STRING) h264eprc_type.object_name, "h264eprc"); - h264eprc_type.pf_object_init = h264e_prc_init; - - strcpy ((OMX_STRING) h264e_inport_type.class_name, "h264einport_class"); - h264e_inport_type.pf_class_init = h264e_inport_class_init; - strcpy ((OMX_STRING) h264e_inport_type.object_name, "h264einport"); - h264e_inport_type.pf_object_init = h264e_inport_init; - - strcpy ((OMX_STRING) h264e_outport_type.class_name, "h264eoutport_class"); - h264e_outport_type.pf_class_init = h264e_outport_class_init; - strcpy ((OMX_STRING) h264e_outport_type.object_name, "h264eoutport"); - h264e_outport_type.pf_object_init = h264e_outport_init; - - /* Initialize the component infrastructure */ - tiz_comp_init (ap_hdl, OMX_VID_COMP_NAME); - - /* Classes need to be registered first */ - tiz_comp_register_types (ap_hdl, tf_list, 5); - - /* Register the component roles */ - tiz_comp_register_roles (ap_hdl, rf_list, 2); - - /* Register egl image validation hook for the decoder */ - tiz_check_omx (tiz_comp_register_role_eglimage_hook - (ap_hdl, (const OMX_U8 *) OMX_VID_DEC_AVC_ROLE, - &egl_validation_hook)); - - return OMX_ErrorNone; -} diff --git a/src/gallium/state_trackers/omx/tizonia/entrypoint.h b/src/gallium/state_trackers/omx/tizonia/entrypoint.h deleted file mode 100644 index 740a89dbffc..00000000000 --- a/src/gallium/state_trackers/omx/tizonia/entrypoint.h +++ /dev/null @@ -1,35 +0,0 @@ -/************************************************************************** - * - * Copyright 2013 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#ifndef OMX_TIZ_ENTRYPOINT_H -#define OMX_TIZ_ENTRYPOINT_H - -#include "vl/vl_winsys.h" - -PUBLIC OMX_ERRORTYPE OMX_ComponentInit(OMX_HANDLETYPE ap_hdl); - -#endif diff --git a/src/gallium/state_trackers/omx/tizonia/h264d.c b/src/gallium/state_trackers/omx/tizonia/h264d.c deleted file mode 100644 index 92019a7a4bd..00000000000 --- a/src/gallium/state_trackers/omx/tizonia/h264d.c +++ /dev/null @@ -1,176 +0,0 @@ -/************************************************************************** - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include - -#include "vid_dec_h264_common.h" - -#include "h264dprc.h" -#include "h264d.h" -#include "names.h" - -static OMX_VERSIONTYPE h264_decoder_version = {{0, 0, 0, 1}}; - -OMX_PTR instantiate_h264d_input_port(OMX_HANDLETYPE ap_hdl) -{ - OMX_VIDEO_PORTDEFINITIONTYPE portdef; - OMX_VIDEO_PARAM_AVCTYPE avctype; - OMX_VIDEO_CODINGTYPE encodings[] = { - OMX_VIDEO_CodingAVC, - OMX_VIDEO_CodingMax - }; - OMX_COLOR_FORMATTYPE formats[] = { - OMX_COLOR_FormatUnused, - OMX_COLOR_FormatMax - }; - tiz_port_options_t avc_port_opts = { - OMX_PortDomainVideo, - OMX_DirInput, - OMX_VID_DEC_AVC_INPUT_PORT_MIN_BUF_COUNT, - OMX_VID_DEC_AVC_PORT_MIN_INPUT_BUF_SIZE, - OMX_VID_DEC_AVC_PORT_NONCONTIGUOUS, - OMX_VID_DEC_AVC_PORT_ALIGNMENT, - OMX_VID_DEC_AVC_PORT_SUPPLIERPREF, - {OMX_VID_DEC_AVC_INPUT_PORT_INDEX, NULL, NULL, NULL}, - 1 /* slave port */ - }; - OMX_VIDEO_AVCLEVELTYPE levels[] = { - OMX_VIDEO_AVCLevel1, - OMX_VIDEO_AVCLevel1b, - OMX_VIDEO_AVCLevel11, - OMX_VIDEO_AVCLevel12, - OMX_VIDEO_AVCLevel13, - OMX_VIDEO_AVCLevel2, - OMX_VIDEO_AVCLevel21, - OMX_VIDEO_AVCLevel22, - OMX_VIDEO_AVCLevel3, - OMX_VIDEO_AVCLevel31, - OMX_VIDEO_AVCLevel32, - OMX_VIDEO_AVCLevel4, - OMX_VIDEO_AVCLevel41, - OMX_VIDEO_AVCLevel42, - OMX_VIDEO_AVCLevel5, - OMX_VIDEO_AVCLevel51, - OMX_VIDEO_AVCLevelMax - }; - - portdef.pNativeRender = NULL; - portdef.nFrameWidth = OMX_VID_DEC_AVC_DEFAULT_FRAME_WIDTH; - portdef.nFrameHeight = OMX_VID_DEC_AVC_DEFAULT_FRAME_HEIGHT; - portdef.nStride = 0; - portdef.nSliceHeight = 0; - portdef.nBitrate = 64000; - portdef.xFramerate = OMX_VID_DEC_AVC_DEFAULT_FRAME_RATE; - portdef.bFlagErrorConcealment = OMX_FALSE; - portdef.eCompressionFormat = OMX_VIDEO_CodingAVC; - portdef.eColorFormat = OMX_COLOR_FormatUnused; - portdef.pNativeWindow = NULL; - - avctype.nSize = sizeof (OMX_VIDEO_PARAM_AVCTYPE); - avctype.nVersion.nVersion = OMX_VERSION; - avctype.nPortIndex = OMX_VID_DEC_AVC_INPUT_PORT_INDEX; - avctype.eProfile = OMX_VIDEO_AVCProfileHigh; - /* Encoder related, decide if need to initialise these */ - avctype.nSliceHeaderSpacing = 0; - avctype.nPFrames = 0; - avctype.nBFrames = 0; - avctype.bUseHadamard = OMX_FALSE; - avctype.nRefFrames = 1; - avctype.nRefIdx10ActiveMinus1 = 1; - avctype.nRefIdx11ActiveMinus1 = 0; - avctype.bEnableUEP = OMX_FALSE; - avctype.bEnableFMO = OMX_FALSE; - avctype.bEnableASO = OMX_FALSE; - avctype.bEnableRS = OMX_FALSE; - avctype.eLevel = OMX_VIDEO_AVCLevel51; - avctype.nAllowedPictureTypes = 2; - avctype.bFrameMBsOnly = OMX_FALSE; - avctype.bMBAFF = OMX_FALSE; - avctype.bEntropyCodingCABAC = OMX_FALSE; - avctype.bWeightedPPrediction = OMX_FALSE; - avctype.nWeightedBipredicitonMode = 0; - avctype.bconstIpred = OMX_FALSE; - avctype.bDirect8x8Inference = OMX_FALSE; - avctype.bDirectSpatialTemporal = OMX_FALSE; - avctype.nCabacInitIdc = 0; - avctype.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable; - - return factory_new (tiz_get_type(ap_hdl, "h264dinport"), - &avc_port_opts, &portdef, - &encodings, &formats, &avctype, &levels, - NULL /* OMX_VIDEO_PARAM_BITRATETYPE */, - NULL /* OMX_VIDEO_PARAM_QUANTIZATIONTYPE */); -} - -OMX_PTR instantiate_h264d_output_port(OMX_HANDLETYPE ap_hdl) -{ - OMX_VIDEO_PORTDEFINITIONTYPE portdef; - OMX_VIDEO_CODINGTYPE encodings[] = { - OMX_VIDEO_CodingUnused, - OMX_VIDEO_CodingMax - }; - OMX_COLOR_FORMATTYPE formats[] = { - OMX_COLOR_FormatYUV420SemiPlanar, - OMX_COLOR_FormatMax - }; - tiz_port_options_t rawvideo_port_opts = { - OMX_PortDomainVideo, - OMX_DirOutput, - OMX_VID_DEC_AVC_OUTPUT_PORT_MIN_BUF_COUNT, - OMX_VID_DEC_AVC_PORT_MIN_OUTPUT_BUF_SIZE, - OMX_VID_DEC_AVC_PORT_NONCONTIGUOUS, - OMX_VID_DEC_AVC_PORT_ALIGNMENT, - OMX_VID_DEC_AVC_PORT_SUPPLIERPREF, - {OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX, NULL, NULL, NULL}, - 0 /* Master port */ - }; - - portdef.pNativeRender = NULL; - portdef.nFrameWidth = OMX_VID_DEC_AVC_DEFAULT_FRAME_WIDTH; - portdef.nFrameHeight = OMX_VID_DEC_AVC_DEFAULT_FRAME_HEIGHT; - portdef.nStride = 0; - portdef.nSliceHeight = 0; - portdef.nBitrate = 64000; - portdef.xFramerate = OMX_VID_DEC_AVC_DEFAULT_FRAME_RATE; - portdef.bFlagErrorConcealment = OMX_FALSE; - portdef.eCompressionFormat = OMX_VIDEO_CodingUnused; - portdef.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; - portdef.pNativeWindow = NULL; - - return factory_new(tiz_get_type(ap_hdl, "tizvideoport"), - &rawvideo_port_opts, &portdef, - &encodings, &formats); -} - -OMX_PTR instantiate_h264d_config_port(OMX_HANDLETYPE ap_hdl) -{ - return factory_new(tiz_get_type(ap_hdl, "tizconfigport"), - NULL, /* this port does not take options */ - OMX_VID_COMP_NAME, h264_decoder_version); -} - -OMX_PTR instantiate_h264d_processor(OMX_HANDLETYPE ap_hdl) -{ - return factory_new(tiz_get_type(ap_hdl, "h264dprc")); -} diff --git a/src/gallium/state_trackers/omx/tizonia/h264d.h b/src/gallium/state_trackers/omx/tizonia/h264d.h deleted file mode 100644 index 1733425d45c..00000000000 --- a/src/gallium/state_trackers/omx/tizonia/h264d.h +++ /dev/null @@ -1,40 +0,0 @@ -/************************************************************************** - * - * Copyright 2013 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#ifndef H264D_H -#define H264D_H - -#include -#include -#include - -OMX_PTR instantiate_h264d_config_port(OMX_HANDLETYPE ap_hdl); -OMX_PTR instantiate_h264d_input_port(OMX_HANDLETYPE ap_hdl); -OMX_PTR instantiate_h264d_output_port(OMX_HANDLETYPE ap_hdl); -OMX_PTR instantiate_h264d_processor(OMX_HANDLETYPE ap_hdl); - -#endif /* H264D_H */ diff --git a/src/gallium/state_trackers/omx/tizonia/h264dinport.c b/src/gallium/state_trackers/omx/tizonia/h264dinport.c deleted file mode 100644 index 858ae761560..00000000000 --- a/src/gallium/state_trackers/omx/tizonia/h264dinport.c +++ /dev/null @@ -1,147 +0,0 @@ -/************************************************************************** - * - * Copyright 2013 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include -#include -#include - -#include -#include - -#include "vl/vl_winsys.h" - -#include "h264d.h" -#include "h264dinport.h" -#include "h264dinport_decls.h" -#include "vid_dec_common.h" - -/* - * h264dinport class - */ - -static void * h264d_inport_ctor(void * ap_obj, va_list * app) -{ - return super_ctor(typeOf(ap_obj, "h264dinport"), ap_obj, app); -} - -static void * h264d_inport_dtor(void * ap_obj) -{ - return super_dtor(typeOf(ap_obj, "h264dinport"), ap_obj); -} - -/* - * from tiz_api - */ - -static OMX_ERRORTYPE h264d_inport_SetParameter(const void * ap_obj, OMX_HANDLETYPE ap_hdl, - OMX_INDEXTYPE a_index, OMX_PTR ap_struct) -{ - OMX_ERRORTYPE err = OMX_ErrorNone; - - assert(ap_obj); - assert(ap_hdl); - assert(ap_struct); - - if (a_index == OMX_IndexParamPortDefinition) { - vid_dec_PrivateType * p_prc = tiz_get_prc(ap_hdl); - OMX_VIDEO_PORTDEFINITIONTYPE * p_def = &(p_prc->out_port_def_.format.video); - OMX_PARAM_PORTDEFINITIONTYPE * i_def = (OMX_PARAM_PORTDEFINITIONTYPE *) ap_struct; - - /* Make changes only if there is a resolution change */ - if ((p_def->nFrameWidth == i_def->format.video.nFrameWidth) && - (p_def->nFrameHeight == i_def->format.video.nFrameHeight) && - (p_def->eCompressionFormat == i_def->format.video.eCompressionFormat)) - return err; - - /* Set some default values if not set */ - if (i_def->format.video.nStride == 0) - i_def->format.video.nStride = i_def->format.video.nFrameWidth; - if (i_def->format.video.nSliceHeight == 0) - i_def->format.video.nSliceHeight = i_def->format.video.nFrameHeight; - - err = super_SetParameter(typeOf (ap_obj, "h264dinport"), ap_obj, - ap_hdl, a_index, ap_struct); - if (err == OMX_ErrorNone) { - tiz_port_t * p_obj = (tiz_port_t *) ap_obj; - - /* Set desired buffer size that will be used when allocating input buffers */ - p_obj->portdef_.nBufferSize = i_def->format.video.nFrameWidth * i_def->format.video.nFrameHeight * 512 / (16*16); - - /* Get a locally copy of port def. Useful for the early return above */ - tiz_check_omx(tiz_api_GetParameter(tiz_get_krn(handleOf(p_prc)), handleOf(p_prc), - OMX_IndexParamPortDefinition, &(p_prc->out_port_def_))); - } - } - - return err; -} - -/* - * h264dinport_class - */ - -static void * h264d_inport_class_ctor(void * ap_obj, va_list * app) -{ - /* NOTE: Class methods might be added in the future. None for now. */ - return super_ctor (typeOf (ap_obj, "h264dinport_class"), ap_obj, app); -} - -/* - * initialization - */ - -void * h264d_inport_class_init(void * ap_tos, void * ap_hdl) -{ - void * tizavcport = tiz_get_type(ap_hdl, "tizavcport"); - void * h264dinport_class - = factory_new(classOf(tizavcport), "h264dinport_class", - classOf(tizavcport), sizeof(h264d_inport_class_t), - ap_tos, ap_hdl, ctor, h264d_inport_class_ctor, 0); - return h264dinport_class; -} - -void * h264d_inport_init(void * ap_tos, void * ap_hdl) -{ - void * tizavcport = tiz_get_type (ap_hdl, "tizavcport"); - void * h264dinport_class = tiz_get_type (ap_hdl, "h264dinport_class"); - void * h264dinport = factory_new - /* TIZ_CLASS_COMMENT: class type, class name, parent, size */ - (h264dinport_class, "h264dinport", tizavcport, - sizeof (h264d_inport_t), - /* TIZ_CLASS_COMMENT: class constructor */ - ap_tos, ap_hdl, - /* TIZ_CLASS_COMMENT: class constructor */ - ctor, h264d_inport_ctor, - /* TIZ_CLASS_COMMENT: class destructor */ - dtor, h264d_inport_dtor, - /* TIZ_CLASS_COMMENT: */ - tiz_api_SetParameter, h264d_inport_SetParameter, - /* TIZ_CLASS_COMMENT: stop value*/ - 0); - - return h264dinport; -} diff --git a/src/gallium/state_trackers/omx/tizonia/h264dinport.h b/src/gallium/state_trackers/omx/tizonia/h264dinport.h deleted file mode 100644 index f158e4e1038..00000000000 --- a/src/gallium/state_trackers/omx/tizonia/h264dinport.h +++ /dev/null @@ -1,31 +0,0 @@ -/************************************************************************** - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#ifndef H264DINPORT_H -#define H264DINPORT_H - -void * h264d_inport_class_init(void * ap_tos, void * ap_hdl); -void * h264d_inport_init(void * ap_tos, void * ap_hdl); - -#endif /* H264DINPORT_H */ diff --git a/src/gallium/state_trackers/omx/tizonia/h264dinport_decls.h b/src/gallium/state_trackers/omx/tizonia/h264dinport_decls.h deleted file mode 100644 index 0194f6e3d09..00000000000 --- a/src/gallium/state_trackers/omx/tizonia/h264dinport_decls.h +++ /dev/null @@ -1,48 +0,0 @@ -/************************************************************************** - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#ifndef H264DINPORT_DECLS_H -#define H264DINPORT_DECLS_H - -#include -#include - -#include - -typedef struct h264d_inport h264d_inport_t; -struct h264d_inport -{ - /* Object */ - const tiz_avcport_t _; -}; - -typedef struct h264d_inport_class h264d_inport_class_t; -struct h264d_inport_class -{ - /* Class */ - const tiz_avcport_class_t _; - /* NOTE: Class methods might be added in the future */ -}; - -#endif /* H264DINPORT_DECLS_H */ diff --git a/src/gallium/state_trackers/omx/tizonia/h264dprc.c b/src/gallium/state_trackers/omx/tizonia/h264dprc.c deleted file mode 100644 index c5df994b8c3..00000000000 --- a/src/gallium/state_trackers/omx/tizonia/h264dprc.c +++ /dev/null @@ -1,615 +0,0 @@ -/************************************************************************** - * - * Copyright 2013 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include -#include -#include - -#include "entrypoint.h" -#include "h264d.h" -#include "h264dprc.h" -#include "vid_omx_common.h" -#include "vid_dec_common.h" -#include "vid_dec_h264_common.h" - -#include "vl/vl_video_buffer.h" -#include "vl/vl_compositor.h" -#include "util/u_hash_table.h" -#include "util/u_surface.h" - -#include "dri_screen.h" -#include "egl_dri2.h" - -unsigned dec_frame_delta; - -static enum pipe_error hash_table_clear_item_callback(void *key, void *value, void *data) -{ - struct pipe_video_buffer *video_buffer = (struct pipe_video_buffer *)value; - video_buffer->destroy(video_buffer); - return PIPE_OK; -} - -static void release_input_headers(vid_dec_PrivateType* priv) { - int i; - for (i = 0; i < priv->num_in_buffers; i++) { - assert(!priv->in_port_disabled_); - if (priv->in_buffers[i]->pInputPortPrivate) { - vid_dec_FreeInputPortPrivate(priv->in_buffers[i]); - } - (void) tiz_krn_release_buffer (tiz_get_krn (handleOf (priv)), - OMX_VID_DEC_AVC_INPUT_PORT_INDEX, - priv->in_buffers[i]); - priv->in_buffers[i] = NULL; - } - priv->p_inhdr_ = NULL; - priv->num_in_buffers = 0; -} - -static void release_output_header(vid_dec_PrivateType* priv) { - if (priv->p_outhdr_) { - assert(!priv->out_port_disabled_); - (void) tiz_krn_release_buffer (tiz_get_krn (handleOf (priv)), - OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX, - priv->p_outhdr_); - priv->p_outhdr_ = NULL; - } -} - -static OMX_ERRORTYPE h264d_release_all_headers(vid_dec_PrivateType* priv) -{ - assert(priv); - release_input_headers(priv); - release_output_header(priv); - - return OMX_ErrorNone; -} - -static void h264d_buffer_emptied(vid_dec_PrivateType* priv, OMX_BUFFERHEADERTYPE * p_hdr) -{ - assert(priv); - assert(priv->in_buffers[0] == p_hdr); - - if (!priv->out_port_disabled_) { - assert (p_hdr->nFilledLen == 0); - p_hdr->nOffset = 0; - - if ((p_hdr->nFlags & OMX_BUFFERFLAG_EOS) != 0) { - priv->eos_ = true; - } - - (void) tiz_krn_release_buffer (tiz_get_krn (handleOf (priv)), 0, p_hdr); - priv->p_inhdr_ = NULL; - priv->in_buffers[0] = NULL; - } -} - -static void h264d_buffer_filled(vid_dec_PrivateType* priv, OMX_BUFFERHEADERTYPE * p_hdr) -{ - assert(priv); - assert(p_hdr); - assert(priv->p_outhdr_ == p_hdr); - - if (!priv->in_port_disabled_) { - p_hdr->nOffset = 0; - - if (priv->eos_) { - /* EOS has been received and all the input data has been consumed - * already, so its time to propagate the EOS flag */ - priv->p_outhdr_->nFlags |= OMX_BUFFERFLAG_EOS; - priv->eos_ = false; - } - - (void) tiz_krn_release_buffer(tiz_get_krn (handleOf (priv)), - OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX, - p_hdr); - priv->p_outhdr_ = NULL; - } -} - -static bool h264d_shift_buffers_left(vid_dec_PrivateType* priv) { - if (--priv->num_in_buffers) { - priv->in_buffers[0] = priv->in_buffers[1]; - priv->sizes[0] = priv->sizes[1] - dec_frame_delta; - priv->inputs[0] = priv->inputs[1] + dec_frame_delta; - priv->timestamps[0] = priv->timestamps[1]; - - return true; - } - return false; -} - -static OMX_BUFFERHEADERTYPE * get_input_buffer(vid_dec_PrivateType* priv) { - assert(priv); - - if (priv->in_port_disabled_) { - return NULL; - } - - if (priv->num_in_buffers > 1) { - /* The input buffer wasn't cleared last time. */ - h264d_buffer_emptied(priv, priv->in_buffers[0]); - if (priv->in_buffers[0]) { - /* Failed to release buffer */ - return NULL; - } - h264d_shift_buffers_left(priv); - } - - /* Decode_frame expects new buffers each time */ - assert(priv->p_inhdr_ || priv->first_buf_in_frame); - tiz_krn_claim_buffer(tiz_get_krn (handleOf (priv)), - OMX_VID_DEC_AVC_INPUT_PORT_INDEX, 0, - &priv->p_inhdr_); - return priv->p_inhdr_; -} - -static struct pipe_resource * st_omx_pipe_texture_from_eglimage(EGLDisplay egldisplay, - EGLImage eglimage) -{ - _EGLDisplay *disp = egldisplay; - struct dri2_egl_display *dri2_egl_dpy = disp->DriverData; - __DRIscreen *_dri_screen = dri2_egl_dpy->dri_screen; - struct dri_screen *st_dri_screen = dri_screen(_dri_screen); - __DRIimage *_dri_image = st_dri_screen->lookup_egl_image(st_dri_screen, eglimage); - - return _dri_image->texture; -} - -static void get_eglimage(vid_dec_PrivateType* priv) { - OMX_PTR p_eglimage = NULL; - OMX_NATIVE_WINDOWTYPE * p_egldisplay = NULL; - const tiz_port_t * p_port = NULL; - struct pipe_video_buffer templat = {}; - struct pipe_video_buffer *video_buffer = NULL; - struct pipe_resource * p_res = NULL; - struct pipe_resource *resources[VL_NUM_COMPONENTS]; - - if (OMX_ErrorNone == - tiz_krn_claim_eglimage(tiz_get_krn (handleOf (priv)), - OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX, - priv->p_outhdr_, &p_eglimage)) { - priv->use_eglimage = true; - p_port = tiz_krn_get_port(tiz_get_krn (handleOf (priv)), - OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX); - p_egldisplay = p_port->portdef_.format.video.pNativeWindow; - - if (!util_hash_table_get(priv->video_buffer_map, priv->p_outhdr_)) { - p_res = st_omx_pipe_texture_from_eglimage(p_egldisplay, p_eglimage); - - assert(p_res); - - memset(&templat, 0, sizeof(templat)); - templat.buffer_format = p_res->format; - templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_NONE; - templat.width = p_res->width0; - templat.height = p_res->height0; - templat.interlaced = 0; - - memset(resources, 0, sizeof(resources)); - pipe_resource_reference(&resources[0], p_res); - - video_buffer = vl_video_buffer_create_ex2(priv->pipe, &templat, resources); - - assert(video_buffer); - assert(video_buffer->buffer_format == p_res->format); - - _mesa_hash_table_insert(priv->video_buffer_map, priv->p_outhdr_, video_buffer); - } - } else { - (void) tiz_krn_release_buffer(tiz_get_krn (handleOf (priv)), - OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX, - priv->p_outhdr_); - priv->p_outhdr_ = NULL; - } -} - -static OMX_BUFFERHEADERTYPE * get_output_buffer(vid_dec_PrivateType* priv) { - assert (priv); - - if (priv->out_port_disabled_) { - return NULL; - } - - if (!priv->p_outhdr_) { - if (OMX_ErrorNone - == tiz_krn_claim_buffer(tiz_get_krn (handleOf (priv)), - OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX, 0, - &priv->p_outhdr_)) { - if (priv->p_outhdr_) { - /* Check pBuffer nullity to know if an eglimage has been registered. */ - if (!priv->p_outhdr_->pBuffer) { - get_eglimage(priv); - } - } - } - } - return priv->p_outhdr_; -} - -static void reset_stream_parameters(vid_dec_PrivateType* apriv) -{ - assert(apriv); - TIZ_INIT_OMX_PORT_STRUCT(apriv->out_port_def_, - OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX); - - tiz_api_GetParameter (tiz_get_krn (handleOf (apriv)), handleOf (apriv), - OMX_IndexParamPortDefinition, &(apriv->out_port_def_)); - - apriv->p_inhdr_ = 0; - apriv->num_in_buffers = 0; - apriv->first_buf_in_frame = true; - apriv->eos_ = false; - apriv->frame_finished = false; - apriv->frame_started = false; - apriv->picture.h264.field_order_cnt[0] = apriv->picture.h264.field_order_cnt[1] = INT_MAX; - apriv->slice = NULL; -} - -/* Replacement for bellagio's omx_base_filter_BufferMgmtFunction */ -static void h264d_manage_buffers(vid_dec_PrivateType* priv) { - bool next_is_eos = priv->num_in_buffers == 2 ? !!(priv->in_buffers[1]->nFlags & OMX_BUFFERFLAG_EOS) : false; - vid_dec_FrameDecoded_common(priv, priv->in_buffers[0], priv->p_outhdr_); - - priv->p_outhdr_->nTimeStamp = priv->in_buffers[0]->nTimeStamp; - - /* Realase output buffer if filled or eos - Keep if two input buffers are being decoded */ - if ((!next_is_eos) && ((priv->p_outhdr_->nFilledLen > 0) || priv->use_eglimage || priv->eos_)) { - h264d_buffer_filled(priv, priv->p_outhdr_); - } - - /* Release input buffer if possible */ - if (priv->in_buffers[0]->nFilledLen == 0) { - h264d_buffer_emptied(priv, priv->in_buffers[0]); - } -} - -static OMX_ERRORTYPE decode_frame(vid_dec_PrivateType*priv, - OMX_BUFFERHEADERTYPE *in_buf) -{ - unsigned i = priv->num_in_buffers++; - priv->in_buffers[i] = in_buf; - priv->sizes[i] = in_buf->nFilledLen; - priv->inputs[i] = in_buf->pBuffer; - priv->timestamps[i] = in_buf->nTimeStamp; - - while (priv->num_in_buffers > (!!(in_buf->nFlags & OMX_BUFFERFLAG_EOS) ? 0 : 1)) { - priv->eos_ = !!(priv->in_buffers[0]->nFlags & OMX_BUFFERFLAG_EOS); - unsigned min_bits_left = priv->eos_ ? 32 : MAX2(in_buf->nFilledLen * 8, 32); - struct vl_vlc vlc; - - vl_vlc_init(&vlc, priv->num_in_buffers, priv->inputs, priv->sizes); - - if (priv->slice) - priv->bytes_left = vl_vlc_bits_left(&vlc) / 8; - - while (vl_vlc_bits_left (&vlc) > min_bits_left) { - vid_dec_h264_Decode(priv, &vlc, min_bits_left); - vl_vlc_fillbits(&vlc); - } - - if (priv->slice) { - unsigned bytes = priv->bytes_left - vl_vlc_bits_left(&vlc) / 8; - - priv->codec->decode_bitstream(priv->codec, priv->target, &priv->picture.base, - 1, &priv->slice, &bytes); - - if (priv->num_in_buffers) - priv->slice = priv->inputs[1]; - else - priv->slice = NULL; - } - - if (priv->eos_ && priv->frame_started) - vid_dec_h264_EndFrame(priv); - - if (priv->frame_finished) { - priv->frame_finished = false; - h264d_manage_buffers(priv); - } else if (priv->eos_) { - vid_dec_FreeInputPortPrivate(priv->in_buffers[0]); - h264d_manage_buffers(priv); - } else { - priv->in_buffers[0]->nFilledLen = 0; - h264d_buffer_emptied(priv, priv->in_buffers[0]); - } - - if (priv->out_port_disabled_) { - /* In case out port is disabled, h264d_buffer_emptied will fail to release input port. - * We need to wait before shifting the buffers in that case and check in - * get_input_buffer when out port is enabled to release and shift the buffers. - * Infinite looping occurs if buffer is not released */ - if (priv->num_in_buffers == 2) { - /* Set the delta value for use in get_input_buffer before exiting */ - dec_frame_delta = MIN2((min_bits_left - vl_vlc_bits_left(&vlc)) / 8, priv->sizes[1]); - } - break; - } - - h264d_shift_buffers_left(priv); - } - - return OMX_ErrorNone; -} - -/* - * h264dprc - */ - -static void * h264d_prc_ctor(void *ap_obj, va_list * app) -{ - vid_dec_PrivateType*priv = super_ctor(typeOf (ap_obj, "h264dprc"), ap_obj, app); - assert(priv); - priv->p_inhdr_ = 0; - priv->p_outhdr_ = 0; - priv->first_buf_in_frame = true; - priv->eos_ = false; - priv->in_port_disabled_ = false; - priv->out_port_disabled_ = false; - priv->picture.base.profile = PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH; - priv->profile = PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH; - reset_stream_parameters(priv); - - return priv; -} - -static void * h264d_prc_dtor(void *ap_obj) -{ - return super_dtor(typeOf(ap_obj, "h264dprc"), ap_obj); -} - -static OMX_ERRORTYPE h264d_prc_allocate_resources(void *ap_obj, OMX_U32 a_pid) -{ - vid_dec_PrivateType*priv = ap_obj; - struct pipe_screen *screen; - vl_csc_matrix csc; - - assert (priv); - - priv->screen = omx_get_screen(); - if (!priv->screen) - return OMX_ErrorInsufficientResources; - - screen = priv->screen->pscreen; - priv->pipe = pipe_create_multimedia_context(screen); - if (!priv->pipe) - return OMX_ErrorInsufficientResources; - - if (!vl_compositor_init(&priv->compositor, priv->pipe)) { - priv->pipe->destroy(priv->pipe); - priv->pipe = NULL; - return OMX_ErrorInsufficientResources; - } - - if (!vl_compositor_init_state(&priv->cstate, priv->pipe)) { - vl_compositor_cleanup(&priv->compositor); - priv->pipe->destroy(priv->pipe); - priv->pipe = NULL; - return OMX_ErrorInsufficientResources; - } - - vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601, NULL, true, &csc); - if (!vl_compositor_set_csc_matrix(&priv->cstate, (const vl_csc_matrix *)&csc, 1.0f, 0.0f)) { - vl_compositor_cleanup(&priv->compositor); - priv->pipe->destroy(priv->pipe); - priv->pipe = NULL; - return OMX_ErrorInsufficientResources; - } - - list_inithead(&priv->codec_data.h264.dpb_list); - - priv->video_buffer_map = util_hash_table_create_ptr_keys(); - - return OMX_ErrorNone; -} - -static OMX_ERRORTYPE h264d_prc_deallocate_resources(void *ap_obj) -{ - vid_dec_PrivateType*priv = ap_obj; - assert(priv); - - /* Clear hash table */ - util_hash_table_foreach(priv->video_buffer_map, - &hash_table_clear_item_callback, - NULL); - _mesa_hash_table_destroy(priv->video_buffer_map, NULL); - - if (priv->pipe) { - vl_compositor_cleanup_state(&priv->cstate); - vl_compositor_cleanup(&priv->compositor); - priv->pipe->destroy(priv->pipe); - } - - if (priv->screen) - omx_put_screen(); - - return OMX_ErrorNone; -} - -static OMX_ERRORTYPE h264d_prc_prepare_to_transfer(void *ap_obj, OMX_U32 a_pid) -{ - vid_dec_PrivateType*priv = ap_obj; - assert(priv); - - TIZ_INIT_OMX_PORT_STRUCT(priv->out_port_def_, - OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX); - tiz_check_omx( - tiz_api_GetParameter(tiz_get_krn(handleOf(priv)), handleOf(priv), - OMX_IndexParamPortDefinition, &(priv->out_port_def_))); - - priv->first_buf_in_frame = true; - priv->eos_ = false; - return OMX_ErrorNone; -} - -static OMX_ERRORTYPE h264d_prc_transfer_and_process(void *ap_obj, OMX_U32 a_pid) -{ - return OMX_ErrorNone; -} - -static OMX_ERRORTYPE h264d_prc_stop_and_return(void *ap_obj) -{ - vid_dec_PrivateType*priv = (vid_dec_PrivateType*) ap_obj; - return h264d_release_all_headers (priv); -} - -static OMX_ERRORTYPE h264d_prc_buffers_ready(const void *ap_obj) -{ - vid_dec_PrivateType*priv = (vid_dec_PrivateType*) ap_obj; - OMX_BUFFERHEADERTYPE *in_buf = NULL; - OMX_BUFFERHEADERTYPE *out_buf = NULL; - - assert(priv); - - /* Set parameters if start of stream */ - if (!priv->eos_ && priv->first_buf_in_frame && (in_buf = get_input_buffer(priv))) { - decode_frame(priv, in_buf); - } - - /* Don't get input buffer if output buffer not found */ - while (!priv->eos_ && (out_buf = get_output_buffer(priv)) && (in_buf = get_input_buffer(priv))) { - if (!priv->out_port_disabled_) { - decode_frame(priv, in_buf); - } - } - - return OMX_ErrorNone; -} - -static OMX_ERRORTYPE h264d_prc_port_flush(const void *ap_obj, OMX_U32 a_pid) -{ - vid_dec_PrivateType*priv = (vid_dec_PrivateType*) ap_obj; - if (OMX_ALL == a_pid || OMX_VID_DEC_AVC_INPUT_PORT_INDEX == a_pid) { - release_input_headers(priv); - reset_stream_parameters(priv); - } - if (OMX_ALL == a_pid || OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX == a_pid) { - release_output_header(priv); - } - return OMX_ErrorNone; -} - -static OMX_ERRORTYPE h264d_prc_port_disable(const void *ap_obj, OMX_U32 a_pid) -{ - vid_dec_PrivateType*priv = (vid_dec_PrivateType*) ap_obj; - assert(priv); - if (OMX_ALL == a_pid || OMX_VID_DEC_AVC_INPUT_PORT_INDEX == a_pid) { - /* Release all buffers */ - h264d_release_all_headers(priv); - reset_stream_parameters(priv); - priv->in_port_disabled_ = true; - } - if (OMX_ALL == a_pid || OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX == a_pid) { - release_output_header(priv); - priv->out_port_disabled_ = true; - } - return OMX_ErrorNone; -} - -static OMX_ERRORTYPE h264d_prc_port_enable(const void *ap_obj, OMX_U32 a_pid) -{ - vid_dec_PrivateType* priv = (vid_dec_PrivateType*) ap_obj; - assert(priv); - if (OMX_ALL == a_pid || OMX_VID_DEC_AVC_INPUT_PORT_INDEX == a_pid) { - if (priv->in_port_disabled_) { - reset_stream_parameters(priv); - priv->in_port_disabled_ = false; - } - } - if (OMX_ALL == a_pid || OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX == a_pid) { - priv->out_port_disabled_ = false; - } - return OMX_ErrorNone; -} - -/* - * h264d_prc_class - */ - -static void * h264d_prc_class_ctor(void *ap_obj, va_list * app) -{ - /* NOTE: Class methods might be added in the future. None for now. */ - return super_ctor(typeOf(ap_obj, "h264dprc_class"), ap_obj, app); -} - -/* - * initialization - */ - -void * h264d_prc_class_init(void * ap_tos, void * ap_hdl) -{ - void * tizprc = tiz_get_type(ap_hdl, "tizprc"); - void * h264dprc_class = factory_new - /* TIZ_CLASS_COMMENT: class type, class name, parent, size */ - (classOf(tizprc), "h264dprc_class", classOf(tizprc), - sizeof(h264d_prc_class_t), - /* TIZ_CLASS_COMMENT: */ - ap_tos, ap_hdl, - /* TIZ_CLASS_COMMENT: class constructor */ - ctor, h264d_prc_class_ctor, - /* TIZ_CLASS_COMMENT: stop value*/ - 0); - return h264dprc_class; -} - -void * h264d_prc_init(void * ap_tos, void * ap_hdl) -{ - void * tizprc = tiz_get_type(ap_hdl, "tizprc"); - void * h264dprc_class = tiz_get_type(ap_hdl, "h264dprc_class"); - TIZ_LOG_CLASS (h264dprc_class); - void * h264dprc = factory_new - /* TIZ_CLASS_COMMENT: class type, class name, parent, size */ - (h264dprc_class, "h264dprc", tizprc, sizeof(vid_dec_PrivateType), - /* TIZ_CLASS_COMMENT: */ - ap_tos, ap_hdl, - /* TIZ_CLASS_COMMENT: class constructor */ - ctor, h264d_prc_ctor, - /* TIZ_CLASS_COMMENT: class destructor */ - dtor, h264d_prc_dtor, - /* TIZ_CLASS_COMMENT: */ - tiz_srv_allocate_resources, h264d_prc_allocate_resources, - /* TIZ_CLASS_COMMENT: */ - tiz_srv_deallocate_resources, h264d_prc_deallocate_resources, - /* TIZ_CLASS_COMMENT: */ - tiz_srv_prepare_to_transfer, h264d_prc_prepare_to_transfer, - /* TIZ_CLASS_COMMENT: */ - tiz_srv_transfer_and_process, h264d_prc_transfer_and_process, - /* TIZ_CLASS_COMMENT: */ - tiz_srv_stop_and_return, h264d_prc_stop_and_return, - /* TIZ_CLASS_COMMENT: */ - tiz_prc_buffers_ready, h264d_prc_buffers_ready, - /* TIZ_CLASS_COMMENT: */ - tiz_prc_port_flush, h264d_prc_port_flush, - /* TIZ_CLASS_COMMENT: */ - tiz_prc_port_disable, h264d_prc_port_disable, - /* TIZ_CLASS_COMMENT: */ - tiz_prc_port_enable, h264d_prc_port_enable, - /* TIZ_CLASS_COMMENT: stop value*/ - 0); - - return h264dprc; -} diff --git a/src/gallium/state_trackers/omx/tizonia/h264dprc.h b/src/gallium/state_trackers/omx/tizonia/h264dprc.h deleted file mode 100644 index 08af5491a3e..00000000000 --- a/src/gallium/state_trackers/omx/tizonia/h264dprc.h +++ /dev/null @@ -1,31 +0,0 @@ -/************************************************************************** - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#ifndef H264DPRC_H -#define H264DPRC_H - -void * h264d_prc_class_init(void * ap_tos, void * ap_hdl); -void * h264d_prc_init(void * ap_tos, void * ap_hdl); - -#endif /* H264DPRC_H */ diff --git a/src/gallium/state_trackers/omx/tizonia/h264e.c b/src/gallium/state_trackers/omx/tizonia/h264e.c deleted file mode 100644 index 8ff4b14c53c..00000000000 --- a/src/gallium/state_trackers/omx/tizonia/h264e.c +++ /dev/null @@ -1,184 +0,0 @@ -/************************************************************************** - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include - -#include "h264eprc.h" -#include "h264e.h" -#include "names.h" -#include "vid_enc_common.h" - -static OMX_VERSIONTYPE h264e_encoder_version = {{0, 0, 0, 1}}; - -OMX_PTR instantiate_h264e_input_port(OMX_HANDLETYPE ap_hdl) -{ - OMX_VIDEO_PORTDEFINITIONTYPE portdef; - OMX_VIDEO_CODINGTYPE encodings[] = { - OMX_VIDEO_CodingUnused, - OMX_VIDEO_CodingMax - }; - OMX_COLOR_FORMATTYPE formats[] = { - OMX_COLOR_FormatYUV420SemiPlanar, - OMX_COLOR_FormatMax - }; - tiz_port_options_t rawvideo_port_opts = { - OMX_PortDomainVideo, - OMX_DirInput, - OMX_VID_ENC_AVC_INPUT_PORT_MIN_BUF_COUNT, - OMX_VID_ENC_AVC_PORT_MIN_INPUT_BUF_SIZE, - OMX_VID_ENC_AVC_PORT_NONCONTIGUOUS, - OMX_VID_ENC_AVC_PORT_ALIGNMENT, - OMX_VID_ENC_AVC_PORT_SUPPLIERPREF, - {OMX_VID_ENC_AVC_INPUT_PORT_INDEX, NULL, NULL, NULL}, - 1 /* Slave port */ - }; - - portdef.pNativeRender = NULL; - portdef.nFrameWidth = OMX_VID_ENC_AVC_DEFAULT_FRAME_WIDTH; - portdef.nFrameHeight = OMX_VID_ENC_AVC_DEFAULT_FRAME_HEIGHT; - portdef.nStride = 0; - portdef.nSliceHeight = 0; - portdef.nBitrate = 64000; - portdef.xFramerate = 15; - portdef.bFlagErrorConcealment = OMX_FALSE; - portdef.eCompressionFormat = OMX_VIDEO_CodingUnused; - portdef.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; - portdef.pNativeWindow = NULL; - - return factory_new(tiz_get_type(ap_hdl, "h264einport"), - &rawvideo_port_opts, &portdef, - &encodings, &formats); -} - -OMX_PTR instantiate_h264e_output_port(OMX_HANDLETYPE ap_hdl) -{ - OMX_VIDEO_PORTDEFINITIONTYPE portdef; - OMX_VIDEO_PARAM_AVCTYPE avctype; - OMX_VIDEO_PARAM_BITRATETYPE bitrate; - OMX_VIDEO_PARAM_QUANTIZATIONTYPE quant; - - OMX_VIDEO_CODINGTYPE encodings[] = { - OMX_VIDEO_CodingAVC, - OMX_VIDEO_CodingMax - }; - OMX_COLOR_FORMATTYPE formats[] = { - OMX_COLOR_FormatUnused, - OMX_COLOR_FormatMax - }; - tiz_port_options_t avc_port_opts = { - OMX_PortDomainVideo, - OMX_DirOutput, - OMX_VID_ENC_AVC_OUTPUT_PORT_MIN_BUF_COUNT, - OMX_VID_ENC_AVC_PORT_MIN_OUTPUT_BUF_SIZE, - OMX_VID_ENC_AVC_PORT_NONCONTIGUOUS, - OMX_VID_ENC_AVC_PORT_ALIGNMENT, - OMX_VID_ENC_AVC_PORT_SUPPLIERPREF, - {OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX, NULL, NULL, NULL}, - 0 /* Master port */ - }; - OMX_VIDEO_AVCLEVELTYPE levels[] = { - OMX_VIDEO_AVCLevel51, - OMX_VIDEO_AVCLevel1, - OMX_VIDEO_AVCLevel1b, - OMX_VIDEO_AVCLevel11, - OMX_VIDEO_AVCLevel12, - OMX_VIDEO_AVCLevel13, - OMX_VIDEO_AVCLevel2, - OMX_VIDEO_AVCLevel21, - OMX_VIDEO_AVCLevel22, - OMX_VIDEO_AVCLevel3, - OMX_VIDEO_AVCLevel31, - OMX_VIDEO_AVCLevel32, - OMX_VIDEO_AVCLevel4, - OMX_VIDEO_AVCLevel41, - OMX_VIDEO_AVCLevel42, - OMX_VIDEO_AVCLevel5, - OMX_VIDEO_AVCLevelMax - }; - - /* Values set from as given in specification */ - portdef.pNativeRender = NULL; - portdef.nFrameWidth = OMX_VID_ENC_AVC_DEFAULT_FRAME_WIDTH; - portdef.nFrameHeight = OMX_VID_ENC_AVC_DEFAULT_FRAME_HEIGHT; - portdef.nStride = 0; - portdef.nSliceHeight = 0; - portdef.nBitrate = 64000; - portdef.xFramerate = 15; - portdef.bFlagErrorConcealment = OMX_FALSE; - portdef.eCompressionFormat = OMX_VIDEO_CodingAVC; - portdef.eColorFormat = OMX_COLOR_FormatUnused; - portdef.pNativeWindow = NULL; - - bitrate.eControlRate = OMX_Video_ControlRateDisable; - bitrate.nTargetBitrate = 0; - - quant.nQpI = OMX_VID_ENC_QUANT_I_FRAMES_DEFAULT; - quant.nQpP = OMX_VID_ENC_QUANT_P_FRAMES_DEFAULT; - quant.nQpB = OMX_VID_ENC_QUANT_B_FRAMES_DEFAULT; - - avctype.nSize = sizeof (OMX_VIDEO_PARAM_AVCTYPE); - avctype.nVersion.nVersion = OMX_VERSION; - avctype.nPortIndex = OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX; - avctype.eProfile = OMX_VIDEO_AVCProfileBaseline; - avctype.nSliceHeaderSpacing = 0; - avctype.nPFrames = 0; - avctype.nBFrames = 0; - avctype.bUseHadamard = OMX_TRUE; - avctype.nRefFrames = 1; - avctype.nRefIdx10ActiveMinus1 = 1; - avctype.nRefIdx11ActiveMinus1 = 0; - avctype.bEnableUEP = OMX_FALSE; - avctype.bEnableFMO = OMX_FALSE; - avctype.bEnableASO = OMX_FALSE; - avctype.bEnableRS = OMX_FALSE; - avctype.eLevel = OMX_VIDEO_AVCLevel51; - avctype.nAllowedPictureTypes = 2; - avctype.bFrameMBsOnly = OMX_FALSE; - avctype.bMBAFF = OMX_FALSE; - avctype.bEntropyCodingCABAC = OMX_FALSE; - avctype.bWeightedPPrediction = OMX_FALSE; - avctype.nWeightedBipredicitonMode = 0; - avctype.bconstIpred = OMX_FALSE; - avctype.bDirect8x8Inference = OMX_FALSE; - avctype.bDirectSpatialTemporal = OMX_FALSE; - avctype.nCabacInitIdc = 0; - avctype.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable; - - return factory_new(tiz_get_type(ap_hdl, "h264eoutport"), - &avc_port_opts, &portdef, - &encodings, &formats, &avctype, &levels, - &bitrate, &quant); -} - -OMX_PTR instantiate_h264e_config_port(OMX_HANDLETYPE ap_hdl) -{ - return factory_new(tiz_get_type(ap_hdl, "tizconfigport"), - NULL, /* this port does not take options */ - OMX_VID_COMP_NAME, h264e_encoder_version); -} - -OMX_PTR instantiate_h264e_processor(OMX_HANDLETYPE ap_hdl) -{ - return factory_new(tiz_get_type(ap_hdl, "h264eprc")); -} diff --git a/src/gallium/state_trackers/omx/tizonia/h264e.h b/src/gallium/state_trackers/omx/tizonia/h264e.h deleted file mode 100644 index de8316c726d..00000000000 --- a/src/gallium/state_trackers/omx/tizonia/h264e.h +++ /dev/null @@ -1,55 +0,0 @@ -/************************************************************************** - * - * Copyright 2013 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#ifndef H264E_H -#define H264E_H - -#include -#include -#include - -#define OMX_VID_ENC_AVC_ROLE "video_encoder.avc" - -/* With libtizonia, port indexes must start at index 0 */ -#define OMX_VID_ENC_AVC_INPUT_PORT_INDEX 0 -#define OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX 1 -#define OMX_VID_ENC_AVC_DEFAULT_FRAME_WIDTH 176 -#define OMX_VID_ENC_AVC_DEFAULT_FRAME_HEIGHT 144 -#define OMX_VID_ENC_AVC_INPUT_PORT_MIN_BUF_COUNT 8 -#define OMX_VID_ENC_AVC_OUTPUT_PORT_MIN_BUF_COUNT 2 -#define OMX_VID_ENC_AVC_PORT_MIN_INPUT_BUF_SIZE 4 * 1024 -#define OMX_VID_ENC_AVC_PORT_MIN_OUTPUT_BUF_SIZE 345600 -#define OMX_VID_ENC_AVC_PORT_NONCONTIGUOUS OMX_FALSE -#define OMX_VID_ENC_AVC_PORT_ALIGNMENT 0 -#define OMX_VID_ENC_AVC_PORT_SUPPLIERPREF OMX_BufferSupplyInput - -OMX_PTR instantiate_h264e_config_port(OMX_HANDLETYPE ap_hdl); -OMX_PTR instantiate_h264e_input_port(OMX_HANDLETYPE ap_hdl); -OMX_PTR instantiate_h264e_output_port(OMX_HANDLETYPE ap_hdl); -OMX_PTR instantiate_h264e_processor(OMX_HANDLETYPE ap_hdl); - -#endif /* H264E_H */ diff --git a/src/gallium/state_trackers/omx/tizonia/h264einport.c b/src/gallium/state_trackers/omx/tizonia/h264einport.c deleted file mode 100644 index 609a1782b6b..00000000000 --- a/src/gallium/state_trackers/omx/tizonia/h264einport.c +++ /dev/null @@ -1,216 +0,0 @@ -/************************************************************************** - * - * Copyright 2013 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include -#include -#include - -#include -#include - -#include "vl/vl_winsys.h" - -#include "h264e.h" -#include "h264einport.h" -#include "h264einport_decls.h" -#include "vid_enc_common.h" - -static OMX_ERRORTYPE enc_AllocateBackTexture(OMX_HANDLETYPE ap_hdl, - OMX_U32 idx, - struct pipe_resource **resource, - struct pipe_transfer **transfer, - OMX_U8 **map) -{ - vid_enc_PrivateType * priv = tiz_get_prc(ap_hdl); - tiz_port_t * port = tiz_krn_get_port(tiz_get_krn(ap_hdl), idx); - struct pipe_resource buf_templ; - struct pipe_box box = {}; - OMX_U8 *ptr; - - memset(&buf_templ, 0, sizeof buf_templ); - buf_templ.target = PIPE_TEXTURE_2D; - buf_templ.format = PIPE_FORMAT_I8_UNORM; - buf_templ.bind = PIPE_BIND_LINEAR; - buf_templ.usage = PIPE_USAGE_STAGING; - buf_templ.flags = 0; - buf_templ.width0 = port->portdef_.format.video.nFrameWidth; - buf_templ.height0 = port->portdef_.format.video.nFrameHeight * 3 / 2; - buf_templ.depth0 = 1; - buf_templ.array_size = 1; - - *resource = priv->s_pipe->screen->resource_create(priv->s_pipe->screen, &buf_templ); - if (!*resource) - return OMX_ErrorInsufficientResources; - - box.width = (*resource)->width0; - box.height = (*resource)->height0; - box.depth = (*resource)->depth0; - ptr = priv->s_pipe->transfer_map(priv->s_pipe, *resource, 0, PIPE_TRANSFER_WRITE, &box, transfer); - if (map) - *map = ptr; - - return OMX_ErrorNone; -} - -/* - * h264einport class - */ - -static void * h264e_inport_ctor(void * ap_obj, va_list * app) -{ - return super_ctor(typeOf(ap_obj, "h264einport"), ap_obj, app); -} - -static void * h264e_inport_dtor(void * ap_obj) -{ - return super_dtor(typeOf(ap_obj, "h264einport"), ap_obj); -} - -/* - * from tiz_api - */ - -static OMX_ERRORTYPE h264e_inport_AllocateBuffer(const void * ap_obj, OMX_HANDLETYPE ap_hdl, - OMX_BUFFERHEADERTYPE ** buf, OMX_U32 idx, - OMX_PTR private, OMX_U32 size) -{ - struct input_buf_private *inp; - OMX_ERRORTYPE r; - - r = super_UseBuffer(typeOf(ap_obj, "h264einport"), ap_obj, ap_hdl, - buf, idx, private, size, NULL); - if (r) - return r; - - inp = (*buf)->pInputPortPrivate = CALLOC_STRUCT(input_buf_private); - if (!inp) { - super_FreeBuffer(typeOf(ap_obj, "h264einport"), ap_obj, ap_hdl, idx, *buf); - return OMX_ErrorInsufficientResources; - } - - list_inithead(&inp->tasks); - - r = enc_AllocateBackTexture(ap_hdl, idx, &inp->resource, &inp->transfer, &(*buf)->pBuffer); - - if (r) { - FREE(inp); - super_FreeBuffer(typeOf(ap_obj, "h264einport"), ap_obj, ap_hdl, idx, *buf); - return r; - } - - return OMX_ErrorNone; -} - -static OMX_ERRORTYPE h264e_inport_UseBuffer(const void * ap_obj, OMX_HANDLETYPE ap_hdl, - OMX_BUFFERHEADERTYPE **buf, OMX_U32 idx, - OMX_PTR private, OMX_U32 size, OMX_U8 *mem) -{ - struct input_buf_private *inp; - OMX_ERRORTYPE r; - - r = super_UseBuffer(typeOf(ap_obj, "h264einport"), ap_obj, ap_hdl, - buf, idx, private, size, mem); - if (r) - return r; - - inp = (*buf)->pInputPortPrivate = CALLOC_STRUCT(input_buf_private); - if (!inp) { - super_FreeBuffer(typeOf(ap_obj, "h264einport"), ap_obj, ap_hdl, idx, *buf); - return OMX_ErrorInsufficientResources; - } - - list_inithead(&inp->tasks); - - return OMX_ErrorNone; -} - -static OMX_ERRORTYPE h264e_inport_FreeBuffer(const void * ap_obj, OMX_HANDLETYPE ap_hdl, - OMX_U32 idx, OMX_BUFFERHEADERTYPE *buf) -{ - vid_enc_PrivateType *priv = tiz_get_prc(ap_hdl); - struct input_buf_private *inp = buf->pInputPortPrivate; - - if (inp) { - enc_ReleaseTasks(&inp->tasks); - if (inp->transfer) - pipe_transfer_unmap(priv->s_pipe, inp->transfer); - pipe_resource_reference(&inp->resource, NULL); - FREE(inp); - } - - return super_FreeBuffer(typeOf(ap_obj, "h264einport"), ap_obj, ap_hdl, idx, buf); -} - -/* - * h264einport_class - */ - -static void * h264e_inport_class_ctor(void * ap_obj, va_list * app) -{ - /* NOTE: Class methods might be added in the future. None for now. */ - return super_ctor (typeOf (ap_obj, "h264einport_class"), ap_obj, app); -} - -/* - * initialization - */ - -void * h264e_inport_class_init(void * ap_tos, void * ap_hdl) -{ - void * tizvideoport = tiz_get_type(ap_hdl, "tizvideoport"); - void * h264einport_class - = factory_new(classOf(tizvideoport), "h264einport_class", - classOf(tizvideoport), sizeof(h264e_inport_class_t), - ap_tos, ap_hdl, ctor, h264e_inport_class_ctor, 0); - return h264einport_class; -} - -void * h264e_inport_init(void * ap_tos, void * ap_hdl) -{ - void * tizvideoport = tiz_get_type (ap_hdl, "tizvideoport"); - void * h264einport_class = tiz_get_type (ap_hdl, "h264einport_class"); - void * h264einport = factory_new - /* TIZ_CLASS_COMMENT: class type, class name, parent, size */ - (h264einport_class, "h264einport", tizvideoport, - sizeof (h264e_inport_t), - /* TIZ_CLASS_COMMENT: class constructor */ - ap_tos, ap_hdl, - /* TIZ_CLASS_COMMENT: class constructor */ - ctor, h264e_inport_ctor, - /* TIZ_CLASS_COMMENT: class destructor */ - dtor, h264e_inport_dtor, - /* TIZ_CLASS_COMMENT: */ - tiz_api_AllocateBuffer, h264e_inport_AllocateBuffer, - /* TIZ_CLASS_COMMENT: */ - tiz_api_UseBuffer, h264e_inport_UseBuffer, - /* TIZ_CLASS_COMMENT: */ - tiz_api_FreeBuffer, h264e_inport_FreeBuffer, - /* TIZ_CLASS_COMMENT: stop value*/ - 0); - - return h264einport; -} diff --git a/src/gallium/state_trackers/omx/tizonia/h264einport.h b/src/gallium/state_trackers/omx/tizonia/h264einport.h deleted file mode 100644 index 3dd89061970..00000000000 --- a/src/gallium/state_trackers/omx/tizonia/h264einport.h +++ /dev/null @@ -1,31 +0,0 @@ -/************************************************************************** - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#ifndef H264EINPORT_H -#define H264EINPORT_H - -void * h264e_inport_class_init(void * ap_tos, void * ap_hdl); -void * h264e_inport_init(void * ap_tos, void * ap_hdl); - -#endif /* H264EINPORT_H */ diff --git a/src/gallium/state_trackers/omx/tizonia/h264einport_decls.h b/src/gallium/state_trackers/omx/tizonia/h264einport_decls.h deleted file mode 100644 index 9efaf742b84..00000000000 --- a/src/gallium/state_trackers/omx/tizonia/h264einport_decls.h +++ /dev/null @@ -1,48 +0,0 @@ -/************************************************************************** - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#ifndef H264EINPORT_DECLS_H -#define H264EINPORT_DECLS_H - -#include -#include - -#include - -typedef struct h264e_inport h264e_inport_t; -struct h264e_inport -{ - /* Object */ - const tiz_videoport_t _; -}; - -typedef struct h264e_inport_class h264e_inport_class_t; -struct h264e_inport_class -{ - /* Class */ - const tiz_videoport_class_t _; - /* NOTE: Class methods might be added in the future */ -}; - -#endif /* H264EINPORT_DECLS_H */ diff --git a/src/gallium/state_trackers/omx/tizonia/h264eoutport.c b/src/gallium/state_trackers/omx/tizonia/h264eoutport.c deleted file mode 100644 index 775e04278a4..00000000000 --- a/src/gallium/state_trackers/omx/tizonia/h264eoutport.c +++ /dev/null @@ -1,143 +0,0 @@ -/************************************************************************** - * - * Copyright 2013 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include -#include -#include - -#include - -#include "vl/vl_winsys.h" - -#include "h264eoutport.h" -#include "h264eoutport_decls.h" -#include "vid_enc_common.h" - -/* - * h264eoutport class - */ - -static void * h264e_outport_ctor(void * ap_obj, va_list * app) -{ - return super_ctor(typeOf(ap_obj, "h264eoutport"), ap_obj, app); -} - -static void * h264e_outport_dtor(void * ap_obj) -{ - return super_dtor(typeOf(ap_obj, "h264eoutport"), ap_obj); -} - -/* - * from tiz_api - */ - -static OMX_ERRORTYPE h264e_outport_AllocateBuffer(const void * ap_obj, OMX_HANDLETYPE ap_hdl, - OMX_BUFFERHEADERTYPE ** buf, OMX_U32 idx, - OMX_PTR private, OMX_U32 size) -{ - OMX_ERRORTYPE r; - - r = super_UseBuffer(typeOf(ap_obj, "h264eoutport"), ap_obj, ap_hdl, - buf, idx, private, size, NULL); - if (r) - return r; - - (*buf)->pBuffer = NULL; - (*buf)->pOutputPortPrivate = CALLOC(1, sizeof(struct output_buf_private)); - if (!(*buf)->pOutputPortPrivate) { - super_FreeBuffer(typeOf(ap_obj, "h264eoutport"), ap_obj, ap_hdl, idx, *buf); - return OMX_ErrorInsufficientResources; - } - - return OMX_ErrorNone; -} - -static OMX_ERRORTYPE h264e_outport_FreeBuffer(const void * ap_obj, OMX_HANDLETYPE ap_hdl, - OMX_U32 idx, OMX_BUFFERHEADERTYPE *buf) -{ - vid_enc_PrivateType *priv = tiz_get_prc(ap_hdl); - struct output_buf_private *outp = buf->pOutputPortPrivate; - - if (outp) { - if (outp->transfer) - pipe_transfer_unmap(priv->t_pipe, outp->transfer); - pipe_resource_reference(&outp->bitstream, NULL); - FREE(outp); - buf->pOutputPortPrivate = NULL; - } - buf->pBuffer = NULL; - - return super_FreeBuffer(typeOf(ap_obj, "h264eoutport"), ap_obj, ap_hdl, idx, buf); -} - -/* - * h264e_outport_class - */ - -static void * h264e_outport_class_ctor(void * ap_obj, va_list * app) -{ - /* NOTE: Class methods might be added in the future. None for now. */ - return super_ctor(typeOf(ap_obj, "h264eoutport_class"), ap_obj, app); -} - -/* - * initialization - */ - -void * h264e_outport_class_init(void * ap_tos, void * ap_hdl) -{ - void * tizavcport = tiz_get_type(ap_hdl, "tizavcport"); - void * h264eoutport_class - = factory_new (classOf(tizavcport), "h264eoutport_class", - classOf(tizavcport), sizeof(h264e_outport_class_t), - ap_tos, ap_hdl, ctor, h264e_outport_class_ctor, 0); - return h264eoutport_class; -} - -void * h264e_outport_init(void * ap_tos, void * ap_hdl) -{ - void * tizavcport = tiz_get_type(ap_hdl, "tizavcport"); - void * h264eoutport_class = tiz_get_type(ap_hdl, "h264eoutport_class"); - void * h264eoutport = factory_new - /* TIZ_CLASS_COMMENT: class type, class name, parent, size */ - (h264eoutport_class, "h264eoutport", tizavcport, - sizeof(h264e_outport_t), - /* TIZ_CLASS_COMMENT: class constructor */ - ap_tos, ap_hdl, - /* TIZ_CLASS_COMMENT: class constructor */ - ctor, h264e_outport_ctor, - /* TIZ_CLASS_COMMENT: class destructor */ - dtor, h264e_outport_dtor, - /* TIZ_CLASS_COMMENT: */ - tiz_api_AllocateBuffer, h264e_outport_AllocateBuffer, - /* TIZ_CLASS_COMMENT: */ - tiz_api_FreeBuffer, h264e_outport_FreeBuffer, - /* TIZ_CLASS_COMMENT: stop value*/ - 0); - - return h264eoutport; -} diff --git a/src/gallium/state_trackers/omx/tizonia/h264eoutport.h b/src/gallium/state_trackers/omx/tizonia/h264eoutport.h deleted file mode 100644 index afbf9fed3f7..00000000000 --- a/src/gallium/state_trackers/omx/tizonia/h264eoutport.h +++ /dev/null @@ -1,31 +0,0 @@ -/************************************************************************** - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#ifndef H264EOUTPORT_H -#define H264EOUTPORT_H - -void * h264e_outport_class_init(void * ap_tos, void * ap_hdl); -void * h264e_outport_init(void * ap_tos, void * ap_hdl); - -#endif /* H264EOUTPORT_H */ diff --git a/src/gallium/state_trackers/omx/tizonia/h264eoutport_decls.h b/src/gallium/state_trackers/omx/tizonia/h264eoutport_decls.h deleted file mode 100644 index 28c9e06a0f7..00000000000 --- a/src/gallium/state_trackers/omx/tizonia/h264eoutport_decls.h +++ /dev/null @@ -1,48 +0,0 @@ -/************************************************************************** - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#ifndef H264EOUTPORT_DECLS_H -#define H264EOUTPORT_DECLS_H - -#include -#include - -#include - -typedef struct h264e_outport h264e_outport_t; -struct h264e_outport -{ - /* Object */ - const tiz_avcport_t _; -}; - -typedef struct h264e_outport_class h264e_outport_class_t; -struct h264e_outport_class -{ - /* Class */ - const tiz_avcport_class_t _; - /* NOTE: Class methods might be added in the future */ -}; - -#endif /* H264EOUTPORT_DECLS_H */ diff --git a/src/gallium/state_trackers/omx/tizonia/h264eprc.c b/src/gallium/state_trackers/omx/tizonia/h264eprc.c deleted file mode 100644 index b52e489f21c..00000000000 --- a/src/gallium/state_trackers/omx/tizonia/h264eprc.c +++ /dev/null @@ -1,698 +0,0 @@ -/************************************************************************** - * - * Copyright 2013 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include -#include -#include - -#include "pipe/p_screen.h" -#include "pipe/p_video_codec.h" -#include "util/u_memory.h" - -#include "entrypoint.h" -#include "h264e.h" -#include "h264eprc.h" -#include "vid_omx_common.h" -#include "vid_enc_common.h" - -static OMX_ERRORTYPE init_port_structs(vid_enc_PrivateType * priv) { - const void * p_krn = NULL; - - assert(priv); - - /* Initialisation */ - TIZ_INIT_OMX_PORT_STRUCT(priv->in_port_def_, - OMX_VID_ENC_AVC_INPUT_PORT_INDEX); - TIZ_INIT_OMX_PORT_STRUCT(priv->out_port_def_, - OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX); - TIZ_INIT_OMX_PORT_STRUCT(priv->bitrate, - OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX); - TIZ_INIT_OMX_PORT_STRUCT(priv->quant, - OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX); - TIZ_INIT_OMX_PORT_STRUCT(priv->profile_level, - OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX); - - /* Get values */ - p_krn = tiz_get_krn(handleOf(priv)); - - tiz_check_omx( - tiz_api_GetParameter(p_krn, handleOf(priv), - OMX_IndexParamPortDefinition, &(priv->in_port_def_))); - tiz_check_omx( - tiz_api_GetParameter(p_krn, handleOf(priv), - OMX_IndexParamPortDefinition, &(priv->out_port_def_))); - tiz_check_omx( - tiz_api_GetParameter(p_krn, handleOf(priv), - OMX_IndexParamVideoBitrate, &(priv->bitrate))); - tiz_check_omx( - tiz_api_GetParameter(p_krn, handleOf(priv), - OMX_IndexParamVideoQuantization, &(priv->quant))); - tiz_check_omx( - tiz_api_GetParameter(p_krn, handleOf(priv), - OMX_IndexParamVideoProfileLevelCurrent, &(priv->profile_level))); - - return OMX_ErrorNone; -} - -static OMX_BUFFERHEADERTYPE * get_input_buffer(vid_enc_PrivateType * priv) { - assert(priv); - - if (priv->in_port_disabled_) { - return NULL; - } - - assert(!priv->p_inhdr_); /* encode_frame expects new buffers every time */ - - tiz_krn_claim_buffer(tiz_get_krn(handleOf(priv)), - OMX_VID_ENC_AVC_INPUT_PORT_INDEX, 0, - &priv->p_inhdr_); - return priv->p_inhdr_; -} - -static OMX_BUFFERHEADERTYPE * get_output_buffer(vid_enc_PrivateType * priv) { - assert(priv); - - if (priv->out_port_disabled_) { - return NULL; - } - - if (!priv->p_outhdr_) { - tiz_krn_claim_buffer(tiz_get_krn(handleOf(priv)), - OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX, 0, - &priv->p_outhdr_); - } - return priv->p_outhdr_; -} - -static OMX_ERRORTYPE h264e_buffer_emptied(vid_enc_PrivateType * priv, OMX_BUFFERHEADERTYPE * p_hdr) -{ - OMX_ERRORTYPE r = OMX_ErrorNone; - - assert(priv); - assert(priv->p_inhdr_ == p_hdr); - - if (!priv->out_port_disabled_) { - p_hdr->nOffset = 0; - - if ((p_hdr->nFlags & OMX_BUFFERFLAG_EOS) != 0) { - priv->eos_ = true; - } - - r = tiz_krn_release_buffer(tiz_get_krn(handleOf(priv)), 0, p_hdr); - priv->p_inhdr_ = NULL; - } - - return r; -} - -static OMX_ERRORTYPE h264e_buffer_filled(vid_enc_PrivateType * priv, OMX_BUFFERHEADERTYPE * p_hdr) -{ - OMX_ERRORTYPE r = OMX_ErrorNone; - - assert(priv); - assert(priv->p_outhdr_ == p_hdr); - assert(p_hdr); - - if (!priv->in_port_disabled_) { - p_hdr->nOffset = 0; - - if (priv->eos_) { - /* EOS has been received and all the input data has been consumed - * already, so its time to propagate the EOS flag */ - priv->p_outhdr_->nFlags |= OMX_BUFFERFLAG_EOS; - } - - r = tiz_krn_release_buffer(tiz_get_krn(handleOf(priv)), - OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX, - p_hdr); - priv->p_outhdr_ = NULL; - } - - return r; -} - - -static void release_input_header(vid_enc_PrivateType * priv) { - assert(!priv->in_port_disabled_); - if (priv->p_inhdr_) { - (void) tiz_krn_release_buffer(tiz_get_krn(handleOf(priv)), - OMX_VID_ENC_AVC_INPUT_PORT_INDEX, - priv->p_inhdr_); - } - priv->p_inhdr_ = NULL; -} - -static void release_output_header(vid_enc_PrivateType * priv) { - if (priv->p_outhdr_) { - assert(!priv->out_port_disabled_); - (void) tiz_krn_release_buffer(tiz_get_krn(handleOf(priv)), - OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX, - priv->p_outhdr_); - priv->p_outhdr_ = NULL; - } -} - -static OMX_ERRORTYPE h264e_release_all_headers(vid_enc_PrivateType * priv) -{ - assert(priv); - - release_input_header(priv); - release_output_header(priv); - - return OMX_ErrorNone; -} - -static void reset_stream_parameters(vid_enc_PrivateType * priv) -{ - assert(priv); - init_port_structs(priv); - priv->p_inhdr_ = 0; - priv->p_outhdr_ = 0; - priv->eos_ = false; -} - -/* Replacement for bellagio's omx_base_filter_BufferMgmtFunction */ -static OMX_ERRORTYPE h264e_manage_buffers(vid_enc_PrivateType* priv) { - OMX_BUFFERHEADERTYPE * in_buf = priv->p_inhdr_; - OMX_BUFFERHEADERTYPE * out_buf = priv->p_outhdr_; - OMX_ERRORTYPE r = OMX_ErrorNone; - - if (in_buf->nFilledLen > 0) { - vid_enc_BufferEncoded_common(priv, in_buf, out_buf); - } else { - in_buf->nFilledLen = 0; - } - - out_buf->nTimeStamp = in_buf->nTimeStamp; - - /* Release input buffer if possible */ - if (in_buf->nFilledLen == 0) { - r = h264e_buffer_emptied(priv, in_buf); - } - - /* Realase output buffer if filled or eos */ - if ((out_buf->nFilledLen != 0) || priv->eos_) { - r = h264e_buffer_filled(priv, out_buf); - } - - return r; -} - -static struct encode_task *enc_NeedTask(vid_enc_PrivateType * priv) -{ - OMX_VIDEO_PORTDEFINITIONTYPE *def = &priv->in_port_def_.format.video; - - return enc_NeedTask_common(priv, def); -} - -static void enc_ScaleInput(vid_enc_PrivateType * priv, struct pipe_video_buffer **vbuf, unsigned *size) -{ - OMX_VIDEO_PORTDEFINITIONTYPE *def = &priv->in_port_def_.format.video; - enc_ScaleInput_common(priv, def, vbuf, size); -} - -static void enc_HandleTask(vid_enc_PrivateType * priv, struct encode_task *task, - enum pipe_h264_enc_picture_type picture_type) -{ - unsigned size = priv->out_port_def_.nBufferSize; - struct pipe_video_buffer *vbuf = task->buf; - struct pipe_h264_enc_picture_desc picture = {}; - - /* -------------- scale input image --------- */ - enc_ScaleInput(priv, &vbuf, &size); - priv->s_pipe->flush(priv->s_pipe, NULL, 0); - - /* -------------- allocate output buffer --------- */ - task->bitstream = pipe_buffer_create(priv->s_pipe->screen, - PIPE_BIND_VERTEX_BUFFER, - PIPE_USAGE_STAGING, /* map for read */ - size); - - picture.picture_type = picture_type; - picture.pic_order_cnt = task->pic_order_cnt; - if (priv->restricted_b_frames && picture_type == PIPE_H264_ENC_PICTURE_TYPE_B) - picture.not_referenced = true; - enc_ControlPicture_common(priv, &picture); - - /* -------------- encode frame --------- */ - priv->codec->begin_frame(priv->codec, vbuf, &picture.base); - priv->codec->encode_bitstream(priv->codec, vbuf, task->bitstream, &task->feedback); - priv->codec->end_frame(priv->codec, vbuf, &picture.base); -} - -static void enc_ClearBframes(vid_enc_PrivateType * priv, struct input_buf_private *inp) -{ - struct encode_task *task; - - if (list_is_empty(&priv->b_frames)) - return; - - task = LIST_ENTRY(struct encode_task, priv->b_frames.prev, list); - list_del(&task->list); - - /* promote last from to P frame */ - priv->ref_idx_l0 = priv->ref_idx_l1; - enc_HandleTask(priv, task, PIPE_H264_ENC_PICTURE_TYPE_P); - list_addtail(&task->list, &inp->tasks); - priv->ref_idx_l1 = priv->frame_num++; - - /* handle B frames */ - LIST_FOR_EACH_ENTRY(task, &priv->b_frames, list) { - enc_HandleTask(priv, task, PIPE_H264_ENC_PICTURE_TYPE_B); - if (!priv->restricted_b_frames) - priv->ref_idx_l0 = priv->frame_num; - priv->frame_num++; - } - - enc_MoveTasks(&priv->b_frames, &inp->tasks); -} - -static OMX_ERRORTYPE enc_LoadImage(vid_enc_PrivateType * priv, OMX_BUFFERHEADERTYPE *buf, - struct pipe_video_buffer *vbuf) -{ - OMX_VIDEO_PORTDEFINITIONTYPE *def = &priv->in_port_def_.format.video; - return enc_LoadImage_common(priv, def, buf, vbuf); -} - -static OMX_ERRORTYPE encode_frame(vid_enc_PrivateType * priv, OMX_BUFFERHEADERTYPE * in_buf) -{ - struct input_buf_private *inp = in_buf->pInputPortPrivate; - enum pipe_h264_enc_picture_type picture_type; - struct encode_task *task; - unsigned stacked_num = 0; - OMX_ERRORTYPE err; - - enc_MoveTasks(&inp->tasks, &priv->free_tasks); - task = enc_NeedTask(priv); - if (!task) - return OMX_ErrorInsufficientResources; - - /* EOS */ - if (in_buf->nFilledLen == 0) { - if (in_buf->nFlags & OMX_BUFFERFLAG_EOS) { - in_buf->nFilledLen = in_buf->nAllocLen; - enc_ClearBframes(priv, inp); - enc_MoveTasks(&priv->stacked_tasks, &inp->tasks); - priv->codec->flush(priv->codec); - } - return h264e_manage_buffers(priv); - } - - if (in_buf->pOutputPortPrivate) { - struct pipe_video_buffer *vbuf = in_buf->pOutputPortPrivate; - in_buf->pOutputPortPrivate = task->buf; - task->buf = vbuf; - } else { - /* ------- load input image into video buffer ---- */ - err = enc_LoadImage(priv, in_buf, task->buf); - if (err != OMX_ErrorNone) { - FREE(task); - return err; - } - } - - /* -------------- determine picture type --------- */ - if (!(priv->pic_order_cnt % OMX_VID_ENC_IDR_PERIOD_DEFAULT) || - priv->force_pic_type.IntraRefreshVOP) { - enc_ClearBframes(priv, inp); - picture_type = PIPE_H264_ENC_PICTURE_TYPE_IDR; - priv->force_pic_type.IntraRefreshVOP = OMX_FALSE; - priv->frame_num = 0; - } else if (priv->codec->profile == PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE || - !(priv->pic_order_cnt % OMX_VID_ENC_P_PERIOD_DEFAULT) || - (in_buf->nFlags & OMX_BUFFERFLAG_EOS)) { - picture_type = PIPE_H264_ENC_PICTURE_TYPE_P; - } else { - picture_type = PIPE_H264_ENC_PICTURE_TYPE_B; - } - - task->pic_order_cnt = priv->pic_order_cnt++; - - if (picture_type == PIPE_H264_ENC_PICTURE_TYPE_B) { - /* put frame at the tail of the queue */ - list_addtail(&task->list, &priv->b_frames); - } else { - /* handle I or P frame */ - priv->ref_idx_l0 = priv->ref_idx_l1; - enc_HandleTask(priv, task, picture_type); - list_addtail(&task->list, &priv->stacked_tasks); - LIST_FOR_EACH_ENTRY(task, &priv->stacked_tasks, list) { - ++stacked_num; - } - if (stacked_num == priv->stacked_frames_num) { - struct encode_task *t; - t = LIST_ENTRY(struct encode_task, priv->stacked_tasks.next, list); - list_del(&t->list); - list_addtail(&t->list, &inp->tasks); - } - priv->ref_idx_l1 = priv->frame_num++; - - /* handle B frames */ - LIST_FOR_EACH_ENTRY(task, &priv->b_frames, list) { - enc_HandleTask(priv, task, PIPE_H264_ENC_PICTURE_TYPE_B); - if (!priv->restricted_b_frames) - priv->ref_idx_l0 = priv->frame_num; - priv->frame_num++; - } - - enc_MoveTasks(&priv->b_frames, &inp->tasks); - } - - if (list_is_empty(&inp->tasks)) { - return h264e_buffer_emptied(priv, in_buf); - } else { - return h264e_manage_buffers(priv); - } -} - -static OMX_ERRORTYPE h264e_prc_create_encoder(void *ap_obj) -{ - vid_enc_PrivateType *priv = ap_obj; - struct pipe_screen *screen; - - priv->screen = omx_get_screen(); - if (!priv->screen) - return OMX_ErrorInsufficientResources; - - screen = priv->screen->pscreen; - if (!screen->get_video_param(screen, PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH, - PIPE_VIDEO_ENTRYPOINT_ENCODE, PIPE_VIDEO_CAP_SUPPORTED)) - return OMX_ErrorBadParameter; - - priv->s_pipe = pipe_create_multimedia_context(screen); - if (!priv->s_pipe) - return OMX_ErrorInsufficientResources; - - enc_InitCompute_common(priv); - - if (!vl_compositor_init(&priv->compositor, priv->s_pipe)) { - priv->s_pipe->destroy(priv->s_pipe); - priv->s_pipe = NULL; - return OMX_ErrorInsufficientResources; - } - - if (!vl_compositor_init_state(&priv->cstate, priv->s_pipe)) { - vl_compositor_cleanup(&priv->compositor); - priv->s_pipe->destroy(priv->s_pipe); - priv->s_pipe = NULL; - return OMX_ErrorInsufficientResources; - } - - priv->t_pipe = pipe_create_multimedia_context(screen); - if (!priv->t_pipe) - return OMX_ErrorInsufficientResources; - - list_inithead(&priv->free_tasks); - list_inithead(&priv->used_tasks); - list_inithead(&priv->b_frames); - list_inithead(&priv->stacked_tasks); - - return OMX_ErrorNone; -} - -static void h264e_prc_destroy_encoder(void *ap_obj) -{ - vid_enc_PrivateType *priv = ap_obj; - int i; - - assert (priv); - - enc_ReleaseTasks(&priv->free_tasks); - enc_ReleaseTasks(&priv->used_tasks); - enc_ReleaseTasks(&priv->b_frames); - enc_ReleaseTasks(&priv->stacked_tasks); - - for (i = 0; i < OMX_VID_ENC_NUM_SCALING_BUFFERS; ++i) - if (priv->scale_buffer[i]) - priv->scale_buffer[i]->destroy(priv->scale_buffer[i]); - - if (priv->s_pipe) { - vl_compositor_cleanup_state(&priv->cstate); - vl_compositor_cleanup(&priv->compositor); - enc_ReleaseCompute_common(priv); - priv->s_pipe->destroy(priv->s_pipe); - } - - if (priv->t_pipe) - priv->t_pipe->destroy(priv->t_pipe); - - if (priv->screen) - omx_put_screen(); -} - -/* - * h264eprc - */ - -static void * h264e_prc_ctor(void *ap_obj, va_list * app) -{ - vid_enc_PrivateType *priv = super_ctor(typeOf(ap_obj, "h264eprc"), ap_obj, app); - assert (priv); - - if (h264e_prc_create_encoder(ap_obj) != OMX_ErrorNone) - return priv; - - priv->p_inhdr_ = 0; - priv->p_outhdr_ = 0; - priv->profile_level.eProfile = OMX_VIDEO_AVCProfileBaseline; - priv->profile_level.eLevel = OMX_VIDEO_AVCLevel51; - priv->force_pic_type.IntraRefreshVOP = OMX_FALSE; - priv->frame_num = 0; - priv->pic_order_cnt = 0; - priv->restricted_b_frames = debug_get_bool_option("OMX_USE_RESTRICTED_B_FRAMES", FALSE); - priv->scale.xWidth = OMX_VID_ENC_SCALING_WIDTH_DEFAULT; - priv->scale.xHeight = OMX_VID_ENC_SCALING_WIDTH_DEFAULT; - priv->in_port_disabled_ = false; - priv->out_port_disabled_ = false; - reset_stream_parameters(priv); - - return priv; -} - -static void * h264e_prc_dtor(void *ap_obj) -{ - h264e_prc_destroy_encoder(ap_obj); - return super_dtor(typeOf(ap_obj, "h264eprc"), ap_obj); -} - -static OMX_ERRORTYPE h264e_prc_allocate_resources(void *ap_obj, OMX_U32 a_pid) -{ - vid_enc_PrivateType *priv = ap_obj; - - assert(priv); - if (!priv->screen) - return OMX_ErrorInsufficientResources; - - return OMX_ErrorNone; -} - -static OMX_ERRORTYPE h264e_prc_deallocate_resources(void *ap_obj) -{ - return OMX_ErrorNone; -} - -static OMX_ERRORTYPE h264e_prc_prepare_to_transfer(void *ap_obj, OMX_U32 a_pid) -{ - vid_enc_PrivateType *priv = ap_obj; - - assert(priv); - - init_port_structs(priv); - - priv->eos_ = false; - - struct pipe_video_codec templat = {}; - - templat.profile = enc_TranslateOMXProfileToPipe(priv->profile_level.eProfile); - templat.level = enc_TranslateOMXLevelToPipe(priv->profile_level.eLevel); - templat.entrypoint = PIPE_VIDEO_ENTRYPOINT_ENCODE; - templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; - templat.width = priv->scale_buffer[priv->current_scale_buffer] ? - priv->scale.xWidth : priv->in_port_def_.format.video.nFrameWidth; - templat.height = priv->scale_buffer[priv->current_scale_buffer] ? - priv->scale.xHeight : priv->in_port_def_.format.video.nFrameHeight; - - if (templat.profile == PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE) { - struct pipe_screen *screen = priv->screen->pscreen; - templat.max_references = 1; - priv->stacked_frames_num = - screen->get_video_param(screen, - PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH, - PIPE_VIDEO_ENTRYPOINT_ENCODE, - PIPE_VIDEO_CAP_STACKED_FRAMES); - } else { - templat.max_references = OMX_VID_ENC_P_PERIOD_DEFAULT; - priv->stacked_frames_num = 1; - } - priv->codec = priv->s_pipe->create_video_codec(priv->s_pipe, &templat); - - return OMX_ErrorNone; -} - -static OMX_ERRORTYPE h264e_prc_transfer_and_process(void *ap_obj, OMX_U32 a_pid) -{ - return OMX_ErrorNone; -} - -static OMX_ERRORTYPE h264e_prc_stop_and_return(void *ap_obj) -{ - vid_enc_PrivateType *priv = (vid_enc_PrivateType *) ap_obj; - return h264e_release_all_headers(priv); -} - -static OMX_ERRORTYPE h264e_prc_buffers_ready(const void *ap_obj) -{ - vid_enc_PrivateType *priv = (vid_enc_PrivateType *) ap_obj; - OMX_BUFFERHEADERTYPE *in_buf = NULL; - OMX_BUFFERHEADERTYPE *out_buf = NULL; - OMX_ERRORTYPE r = OMX_ErrorNone; - - assert(priv); - - /* Don't get input buffer if output buffer not found */ - while (!priv->eos_ && (out_buf = get_output_buffer(priv)) && (in_buf = get_input_buffer(priv))) { - if (!priv->out_port_disabled_) { - r = encode_frame(priv, in_buf); - } - } - - return r; -} - -static OMX_ERRORTYPE h264e_prc_port_flush(const void *ap_obj, OMX_U32 a_pid) -{ - vid_enc_PrivateType *priv = (vid_enc_PrivateType *) ap_obj; - if (OMX_ALL == a_pid || OMX_VID_ENC_AVC_INPUT_PORT_INDEX == a_pid) { - release_input_header(priv); - reset_stream_parameters(priv); - } - if (OMX_ALL == a_pid || OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX == a_pid) { - release_output_header(priv); - } - return OMX_ErrorNone; -} - -static OMX_ERRORTYPE h264e_prc_port_disable(const void *ap_obj, OMX_U32 a_pid) -{ - vid_enc_PrivateType *priv = (vid_enc_PrivateType *) ap_obj; - assert(priv); - if (OMX_ALL == a_pid || OMX_VID_ENC_AVC_INPUT_PORT_INDEX == a_pid) { - /* Release all buffers */ - h264e_release_all_headers(priv); - reset_stream_parameters(priv); - priv->in_port_disabled_ = true; - } - if (OMX_ALL == a_pid || OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX == a_pid) { - release_output_header(priv); - priv->out_port_disabled_ = true; - } - return OMX_ErrorNone; -} - -static OMX_ERRORTYPE h264e_prc_port_enable(const void *ap_obj, OMX_U32 a_pid) -{ - vid_enc_PrivateType * priv = (vid_enc_PrivateType *) ap_obj; - assert(priv); - if (OMX_ALL == a_pid || OMX_VID_ENC_AVC_INPUT_PORT_INDEX == a_pid) { - if (priv->in_port_disabled_) { - reset_stream_parameters(priv); - priv->in_port_disabled_ = false; - } - } - if (OMX_ALL == a_pid || OMX_VID_ENC_AVC_OUTPUT_PORT_INDEX == a_pid) { - priv->out_port_disabled_ = false; - } - return OMX_ErrorNone; -} - -/* - * h264e_prc_class - */ - -static void * h264e_prc_class_ctor(void *ap_obj, va_list * app) -{ - /* NOTE: Class methods might be added in the future. None for now. */ - return super_ctor(typeOf(ap_obj, "h264eprc_class"), ap_obj, app); -} - -/* - * initialization - */ - -void * h264e_prc_class_init(void * ap_tos, void * ap_hdl) -{ - void * tizprc = tiz_get_type(ap_hdl, "tizprc"); - void * h264eprc_class = factory_new - /* TIZ_CLASS_COMMENT: class type, class name, parent, size */ - (classOf(tizprc), "h264eprc_class", classOf(tizprc), - sizeof(h264e_prc_class_t), - /* TIZ_CLASS_COMMENT: */ - ap_tos, ap_hdl, - /* TIZ_CLASS_COMMENT: class constructor */ - ctor, h264e_prc_class_ctor, - /* TIZ_CLASS_COMMENT: stop value*/ - 0); - return h264eprc_class; -} - -void * h264e_prc_init(void * ap_tos, void * ap_hdl) -{ - void * tizprc = tiz_get_type(ap_hdl, "tizprc"); - void * h264eprc_class = tiz_get_type(ap_hdl, "h264eprc_class"); - TIZ_LOG_CLASS (h264eprc_class); - void * h264eprc = factory_new - /* TIZ_CLASS_COMMENT: class type, class name, parent, size */ - (h264eprc_class, "h264eprc", tizprc, sizeof(vid_enc_PrivateType), - /* TIZ_CLASS_COMMENT: */ - ap_tos, ap_hdl, - /* TIZ_CLASS_COMMENT: class constructor */ - ctor, h264e_prc_ctor, - /* TIZ_CLASS_COMMENT: class destructor */ - dtor, h264e_prc_dtor, - /* TIZ_CLASS_COMMENT: */ - tiz_srv_allocate_resources, h264e_prc_allocate_resources, - /* TIZ_CLASS_COMMENT: */ - tiz_srv_deallocate_resources, h264e_prc_deallocate_resources, - /* TIZ_CLASS_COMMENT: */ - tiz_srv_prepare_to_transfer, h264e_prc_prepare_to_transfer, - /* TIZ_CLASS_COMMENT: */ - tiz_srv_transfer_and_process, h264e_prc_transfer_and_process, - /* TIZ_CLASS_COMMENT: */ - tiz_srv_stop_and_return, h264e_prc_stop_and_return, - /* TIZ_CLASS_COMMENT: */ - tiz_prc_buffers_ready, h264e_prc_buffers_ready, - /* TIZ_CLASS_COMMENT: */ - tiz_prc_port_flush, h264e_prc_port_flush, - /* TIZ_CLASS_COMMENT: */ - tiz_prc_port_disable, h264e_prc_port_disable, - /* TIZ_CLASS_COMMENT: */ - tiz_prc_port_enable, h264e_prc_port_enable, - /* TIZ_CLASS_COMMENT: stop value*/ - 0); - - return h264eprc; -} diff --git a/src/gallium/state_trackers/omx/tizonia/h264eprc.h b/src/gallium/state_trackers/omx/tizonia/h264eprc.h deleted file mode 100644 index c5bc151a825..00000000000 --- a/src/gallium/state_trackers/omx/tizonia/h264eprc.h +++ /dev/null @@ -1,31 +0,0 @@ -/************************************************************************** - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#ifndef H264EPRC_H -#define H264EPRC_H - -void * h264e_prc_class_init(void * ap_tos, void * ap_hdl); -void * h264e_prc_init(void * ap_tos, void * ap_hdl); - -#endif /* H264EPRC_H */ diff --git a/src/gallium/state_trackers/omx/tizonia/names.h b/src/gallium/state_trackers/omx/tizonia/names.h deleted file mode 100644 index edde7df396a..00000000000 --- a/src/gallium/state_trackers/omx/tizonia/names.h +++ /dev/null @@ -1,30 +0,0 @@ -/************************************************************************** - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#ifndef OMX_TIZ_NAMES_H -#define OMX_TIZ_NAMES_H - -#define OMX_VID_COMP_NAME "OMX.mesa.video.all" - -#endif diff --git a/src/gallium/state_trackers/omx/vid_dec_common.c b/src/gallium/state_trackers/omx/vid_dec_common.c deleted file mode 100644 index 5ca544f8386..00000000000 --- a/src/gallium/state_trackers/omx/vid_dec_common.c +++ /dev/null @@ -1,156 +0,0 @@ -/************************************************************************** - * - * Copyright 2013 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#if ENABLE_ST_OMX_TIZONIA -#include -#endif - -#include "util/u_memory.h" -#include "vl/vl_winsys.h" -#include "vl/vl_video_buffer.h" -#include "util/u_surface.h" - -#include "vid_dec_common.h" -#include "vid_dec_h264_common.h" - -void vid_dec_NeedTarget(vid_dec_PrivateType *priv) -{ - struct pipe_video_buffer templat = {}; - struct vl_screen *omx_screen; - struct pipe_screen *pscreen; - - omx_screen = priv->screen; - assert(omx_screen); - - pscreen = omx_screen->pscreen; - assert(pscreen); - - if (!priv->target) { - memset(&templat, 0, sizeof(templat)); - - templat.width = priv->codec->width; - templat.height = priv->codec->height; - templat.buffer_format = pscreen->get_video_param( - pscreen, - PIPE_VIDEO_PROFILE_UNKNOWN, - PIPE_VIDEO_ENTRYPOINT_BITSTREAM, - PIPE_VIDEO_CAP_PREFERED_FORMAT - ); - templat.interlaced = pscreen->get_video_param( - pscreen, - PIPE_VIDEO_PROFILE_UNKNOWN, - PIPE_VIDEO_ENTRYPOINT_BITSTREAM, - PIPE_VIDEO_CAP_PREFERS_INTERLACED - ); - - priv->target = priv->pipe->create_video_buffer(priv->pipe, &templat); - } -} - -void vid_dec_FillOutput(vid_dec_PrivateType *priv, struct pipe_video_buffer *buf, - OMX_BUFFERHEADERTYPE* output) -{ -#if ENABLE_ST_OMX_TIZONIA - tiz_port_t *out_port = tiz_krn_get_port(tiz_get_krn(handleOf(priv)), - OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX); - OMX_VIDEO_PORTDEFINITIONTYPE *def = &out_port->portdef_.format.video; -#else - omx_base_PortType *port = priv->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]; - OMX_VIDEO_PORTDEFINITIONTYPE *def = &port->sPortParam.format.video; -#endif - - struct pipe_sampler_view **views; - unsigned i, j; - unsigned width, height; - - views = buf->get_sampler_view_planes(buf); - -#if ENABLE_ST_OMX_TIZONIA - if (!output->pBuffer) { - struct pipe_video_buffer *dst_buf = NULL; - struct pipe_surface **dst_surface = NULL; - struct u_rect src_rect; - struct u_rect dst_rect; - struct vl_compositor *compositor = &priv->compositor; - struct vl_compositor_state *s = &priv->cstate; - enum vl_compositor_deinterlace deinterlace = VL_COMPOSITOR_WEAVE; - - dst_buf = util_hash_table_get(priv->video_buffer_map, output); - assert(dst_buf); - - dst_surface = dst_buf->get_surfaces(dst_buf); - assert(views); - - src_rect.x0 = 0; - src_rect.y0 = 0; - src_rect.x1 = def->nFrameWidth; - src_rect.y1 = def->nFrameHeight; - - dst_rect.x0 = 0; - dst_rect.y0 = 0; - dst_rect.x1 = def->nFrameWidth; - dst_rect.y1 = def->nFrameHeight; - - vl_compositor_clear_layers(s); - vl_compositor_set_buffer_layer(s, compositor, 0, buf, - &src_rect, NULL, deinterlace); - vl_compositor_set_layer_dst_area(s, 0, &dst_rect); - vl_compositor_render(s, compositor, dst_surface[0], NULL, false); - - priv->pipe->flush(priv->pipe, NULL, 0); - - return; - } -#endif - - for (i = 0; i < 2 /* NV12 */; i++) { - if (!views[i]) continue; - width = def->nFrameWidth; - height = def->nFrameHeight; - vl_video_buffer_adjust_size(&width, &height, i, - pipe_format_to_chroma_format(buf->buffer_format), - buf->interlaced); - for (j = 0; j < views[i]->texture->array_size; ++j) { - struct pipe_box box = {0, 0, j, width, height, 1}; - struct pipe_transfer *transfer; - uint8_t *map, *dst; - map = priv->pipe->transfer_map(priv->pipe, views[i]->texture, 0, - PIPE_TRANSFER_READ, &box, &transfer); - if (!map) - return; - - dst = ((uint8_t*)output->pBuffer + output->nOffset) + j * def->nStride + - i * def->nFrameWidth * def->nFrameHeight; - util_copy_rect(dst, - views[i]->texture->format, - def->nStride * views[i]->texture->array_size, 0, 0, - box.width, box.height, map, transfer->stride, 0, 0); - - pipe_transfer_unmap(priv->pipe, transfer); - } - } -} diff --git a/src/gallium/state_trackers/omx/vid_dec_common.h b/src/gallium/state_trackers/omx/vid_dec_common.h deleted file mode 100644 index 26091e3e6f9..00000000000 --- a/src/gallium/state_trackers/omx/vid_dec_common.h +++ /dev/null @@ -1,197 +0,0 @@ -/************************************************************************** - * - * Copyright 2013 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#ifndef VID_DEC_COMMON_H -#define VID_DEC_COMMON_H - -#include "util/list.h" - -#include "vl/vl_compositor.h" -#include "vl/vl_rbsp.h" -#include "vl/vl_zscan.h" - -#include -#include - -#if ENABLE_ST_OMX_BELLAGIO - -#include -#include -#include - -DERIVEDCLASS(vid_dec_PrivateType, omx_base_filter_PrivateType) -#define vid_dec_PrivateType_FIELDS omx_base_filter_PrivateType_FIELDS \ - enum pipe_video_profile profile; \ - struct vl_screen *screen; \ - struct pipe_context *pipe; \ - struct pipe_video_codec *codec; \ - void (*Decode)(vid_dec_PrivateType *priv, struct vl_vlc *vlc, unsigned min_bits_left); \ - void (*EndFrame)(vid_dec_PrivateType *priv); \ - struct pipe_video_buffer *(*Flush)(vid_dec_PrivateType *priv, OMX_TICKS *timestamp); \ - struct pipe_video_buffer *target, *shadow; \ - union { \ - struct { \ - uint8_t intra_matrix[64]; \ - uint8_t non_intra_matrix[64]; \ - } mpeg12; \ - struct { \ - unsigned nal_ref_idc; \ - bool IdrPicFlag; \ - unsigned idr_pic_id; \ - unsigned pic_order_cnt_lsb; \ - unsigned pic_order_cnt_msb; \ - unsigned delta_pic_order_cnt_bottom; \ - unsigned delta_pic_order_cnt[2]; \ - unsigned prevFrameNumOffset; \ - struct pipe_h264_sps sps[32]; \ - struct pipe_h264_pps pps[256]; \ - struct list_head dpb_list; \ - unsigned dpb_num; \ - } h264; \ - struct { \ - unsigned temporal_id; \ - unsigned level_idc; \ - unsigned pic_width_in_luma_samples; \ - unsigned pic_height_in_luma_samples; \ - bool IdrPicFlag; \ - int slice_prev_poc; \ - void *ref_pic_set_list; \ - void *rps; \ - struct pipe_h265_sps sps[16]; \ - struct pipe_h265_pps pps[64]; \ - struct list_head dpb_list; \ - unsigned dpb_num; \ - } h265; \ - } codec_data; \ - union { \ - struct pipe_picture_desc base; \ - struct pipe_mpeg12_picture_desc mpeg12; \ - struct pipe_h264_picture_desc h264; \ - struct pipe_h265_picture_desc h265; \ - } picture; \ - unsigned num_in_buffers; \ - OMX_BUFFERHEADERTYPE *in_buffers[2]; \ - const void *inputs[2]; \ - unsigned sizes[2]; \ - OMX_TICKS timestamps[2]; \ - OMX_TICKS timestamp; \ - bool first_buf_in_frame; \ - bool frame_finished; \ - bool frame_started; \ - unsigned bytes_left; \ - const void *slice; \ - bool disable_tunnel; \ - struct vl_compositor compositor; \ - struct vl_compositor_state cstate; -ENDCLASS(vid_dec_PrivateType) - -#else - -#include -#include - -#include "util/list.h" -#include "util/u_hash_table.h" - -#include "pipe/p_video_state.h" - -typedef struct h264d_prc_class h264d_prc_class_t; -struct h264d_prc_class -{ - /* Class */ - const tiz_prc_class_t _; - /* NOTE: Class methods might be added in the future */ -}; - -typedef struct h264d_stream_info h264d_stream_info_t; -struct h264d_stream_info -{ - unsigned int width; - unsigned int height; -}; - -typedef struct h264d_prc vid_dec_PrivateType; -struct h264d_prc -{ - /* Object */ - const tiz_prc_t _; - OMX_BUFFERHEADERTYPE *in_buffers[2]; - OMX_BUFFERHEADERTYPE *p_inhdr_; - OMX_BUFFERHEADERTYPE *p_outhdr_; - OMX_PARAM_PORTDEFINITIONTYPE out_port_def_; - const void *inputs[2]; - unsigned sizes[2]; - OMX_TICKS timestamps[2]; - OMX_TICKS timestamp; - bool eos_; - bool in_port_disabled_; - bool out_port_disabled_; - struct vl_screen *screen; - struct pipe_context *pipe; - struct pipe_video_codec *codec; - struct pipe_video_buffer *target; - enum pipe_video_profile profile; - struct hash_table *video_buffer_map; - union { - struct { - unsigned nal_ref_idc; - bool IdrPicFlag; - unsigned idr_pic_id; - unsigned pic_order_cnt_lsb; - unsigned pic_order_cnt_msb; - unsigned delta_pic_order_cnt_bottom; - unsigned delta_pic_order_cnt[2]; - unsigned prevFrameNumOffset; - struct pipe_h264_sps sps[32]; - struct pipe_h264_pps pps[256]; - struct list_head dpb_list; - unsigned dpb_num; - } h264; - } codec_data; - union { - struct pipe_picture_desc base; - struct pipe_h264_picture_desc h264; - } picture; - h264d_stream_info_t stream_info; - unsigned num_in_buffers; - bool first_buf_in_frame; - bool frame_finished; - bool frame_started; - unsigned bytes_left; - const void *slice; - bool disable_tunnel; - struct vl_compositor compositor; - struct vl_compositor_state cstate; - bool use_eglimage; -}; - -#endif - -void vid_dec_NeedTarget(vid_dec_PrivateType* priv); -void vid_dec_FillOutput(vid_dec_PrivateType* priv, struct pipe_video_buffer* buf, - OMX_BUFFERHEADERTYPE* output); -#endif diff --git a/src/gallium/state_trackers/omx/vid_dec_h264_common.c b/src/gallium/state_trackers/omx/vid_dec_h264_common.c deleted file mode 100644 index 4074099cdd3..00000000000 --- a/src/gallium/state_trackers/omx/vid_dec_h264_common.c +++ /dev/null @@ -1,1137 +0,0 @@ -/************************************************************************** - * - * Copyright 2013 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#if ENABLE_ST_OMX_TIZONIA -#include -#endif - -#include "util/u_memory.h" - -#include "vid_dec_h264_common.h" - -static void vid_dec_h264_BeginFrame(vid_dec_PrivateType *priv) -{ - //TODO: sane buffer handling - - if (priv->frame_started) - return; - - if (!priv->codec) { - struct pipe_video_codec templat = {}; - templat.profile = priv->profile; - templat.entrypoint = PIPE_VIDEO_ENTRYPOINT_BITSTREAM; - templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; - templat.max_references = priv->picture.h264.num_ref_frames; - templat.expect_chunked_decode = true; -#if ENABLE_ST_OMX_BELLAGIO - omx_base_video_PortType *port; - port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; - templat.width = port->sPortParam.format.video.nFrameWidth; - templat.height = port->sPortParam.format.video.nFrameHeight; -#else - templat.width = priv->out_port_def_.format.video.nFrameWidth; - templat.height = priv->out_port_def_.format.video.nFrameHeight; -#endif - templat.level = priv->picture.h264.pps->sps->level_idc; - - priv->codec = priv->pipe->create_video_codec(priv->pipe, &templat); - } - - vid_dec_NeedTarget(priv); - - if (priv->first_buf_in_frame) - priv->timestamp = priv->timestamps[0]; - priv->first_buf_in_frame = false; - - priv->picture.h264.num_ref_frames = priv->picture.h264.pps->sps->max_num_ref_frames; - - priv->picture.h264.slice_count = 0; - priv->codec->begin_frame(priv->codec, priv->target, &priv->picture.base); - priv->frame_started = true; -} - -struct pipe_video_buffer *vid_dec_h264_Flush(vid_dec_PrivateType *priv, - OMX_TICKS *timestamp) -{ - struct dpb_list *entry, *result = NULL; - struct pipe_video_buffer *buf; - - /* search for the lowest poc and break on zeros */ - LIST_FOR_EACH_ENTRY(entry, &priv->codec_data.h264.dpb_list, list) { - - if (result && entry->poc == 0) - break; - - if (!result || entry->poc < result->poc) - result = entry; - } - - if (!result) - return NULL; - - buf = result->buffer; - if (timestamp) - *timestamp = result->timestamp; - - --priv->codec_data.h264.dpb_num; - list_del(&result->list); - FREE(result); - - return buf; -} - -void vid_dec_h264_EndFrame(vid_dec_PrivateType *priv) -{ - struct dpb_list *entry; - struct pipe_video_buffer *tmp; - bool top_field_first; - OMX_TICKS timestamp = 0; - - if (!priv->frame_started) - return; - - priv->codec->end_frame(priv->codec, priv->target, &priv->picture.base); - priv->frame_started = false; - - // TODO: implement frame number handling - priv->picture.h264.frame_num_list[0] = priv->picture.h264.frame_num; - priv->picture.h264.field_order_cnt_list[0][0] = priv->picture.h264.frame_num; - priv->picture.h264.field_order_cnt_list[0][1] = priv->picture.h264.frame_num; - - top_field_first = priv->picture.h264.field_order_cnt[0] < priv->picture.h264.field_order_cnt[1]; - - if (priv->picture.h264.field_pic_flag && priv->picture.h264.bottom_field_flag != top_field_first) - return; - - /* add the decoded picture to the dpb list */ - entry = CALLOC_STRUCT(dpb_list); - if (!entry) - return; - - priv->first_buf_in_frame = true; - entry->buffer = priv->target; - entry->timestamp = priv->timestamp; - entry->poc = MIN2(priv->picture.h264.field_order_cnt[0], priv->picture.h264.field_order_cnt[1]); - list_addtail(&entry->list, &priv->codec_data.h264.dpb_list); - ++priv->codec_data.h264.dpb_num; - priv->target = NULL; - priv->picture.h264.field_order_cnt[0] = priv->picture.h264.field_order_cnt[1] = INT_MAX; - - if (priv->codec_data.h264.dpb_num <= DPB_MAX_SIZE) - return; - - tmp = priv->in_buffers[0]->pInputPortPrivate; - priv->in_buffers[0]->pInputPortPrivate = vid_dec_h264_Flush(priv, ×tamp); - priv->in_buffers[0]->nTimeStamp = timestamp; - priv->target = tmp; - priv->frame_finished = priv->in_buffers[0]->pInputPortPrivate != NULL; -} - -static void vui_parameters(struct vl_rbsp *rbsp) -{ - // TODO -} - -static void scaling_list(struct vl_rbsp *rbsp, uint8_t *scalingList, unsigned sizeOfScalingList, - const uint8_t *defaultList, const uint8_t *fallbackList) -{ - unsigned lastScale = 8, nextScale = 8; - const int *list; - unsigned i; - - /* (pic|seq)_scaling_list_present_flag[i] */ - if (!vl_rbsp_u(rbsp, 1)) { - if (fallbackList) - memcpy(scalingList, fallbackList, sizeOfScalingList); - return; - } - - list = (sizeOfScalingList == 16) ? vl_zscan_normal_16 : vl_zscan_normal; - for (i = 0; i < sizeOfScalingList; ++i ) { - - if (nextScale != 0) { - signed delta_scale = vl_rbsp_se(rbsp); - nextScale = (lastScale + delta_scale + 256) % 256; - if (i == 0 && nextScale == 0) { - memcpy(scalingList, defaultList, sizeOfScalingList); - return; - } - } - scalingList[list[i]] = nextScale == 0 ? lastScale : nextScale; - lastScale = scalingList[list[i]]; - } -} - -static struct pipe_h264_sps *seq_parameter_set_id(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp) -{ - unsigned id = vl_rbsp_ue(rbsp); - if (id >= ARRAY_SIZE(priv->codec_data.h264.sps)) - return NULL; /* invalid seq_parameter_set_id */ - - return &priv->codec_data.h264.sps[id]; -} - -static void seq_parameter_set(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp) -{ - struct pipe_h264_sps *sps; - unsigned profile_idc, level_idc; - unsigned i; - - /* Sequence parameter set */ - profile_idc = vl_rbsp_u(rbsp, 8); - - /* constraint_set0_flag */ - vl_rbsp_u(rbsp, 1); - - /* constraint_set1_flag */ - vl_rbsp_u(rbsp, 1); - - /* constraint_set2_flag */ - vl_rbsp_u(rbsp, 1); - - /* constraint_set3_flag */ - vl_rbsp_u(rbsp, 1); - - /* constraint_set4_flag */ - vl_rbsp_u(rbsp, 1); - - /* constraint_set5_flag */ - vl_rbsp_u(rbsp, 1); - - /* reserved_zero_2bits */ - vl_rbsp_u(rbsp, 2); - - /* level_idc */ - level_idc = vl_rbsp_u(rbsp, 8); - - sps = seq_parameter_set_id(priv, rbsp); - if (!sps) - return; - - memset(sps, 0, sizeof(*sps)); - memset(sps->ScalingList4x4, 16, sizeof(sps->ScalingList4x4)); - memset(sps->ScalingList8x8, 16, sizeof(sps->ScalingList8x8)); - - sps->level_idc = level_idc; - - if (profile_idc == 100 || profile_idc == 110 || profile_idc == 122 || profile_idc == 244 || - profile_idc == 44 || profile_idc == 83 || profile_idc == 86 || profile_idc == 118 || - profile_idc == 128 || profile_idc == 138) { - - sps->chroma_format_idc = vl_rbsp_ue(rbsp); - - if (sps->chroma_format_idc == 3) - sps->separate_colour_plane_flag = vl_rbsp_u(rbsp, 1); - - sps->bit_depth_luma_minus8 = vl_rbsp_ue(rbsp); - - sps->bit_depth_chroma_minus8 = vl_rbsp_ue(rbsp); - - /* qpprime_y_zero_transform_bypass_flag */ - vl_rbsp_u(rbsp, 1); - - sps->seq_scaling_matrix_present_flag = vl_rbsp_u(rbsp, 1); - if (sps->seq_scaling_matrix_present_flag) { - - scaling_list(rbsp, sps->ScalingList4x4[0], 16, Default_4x4_Intra, Default_4x4_Intra); - scaling_list(rbsp, sps->ScalingList4x4[1], 16, Default_4x4_Intra, sps->ScalingList4x4[0]); - scaling_list(rbsp, sps->ScalingList4x4[2], 16, Default_4x4_Intra, sps->ScalingList4x4[1]); - scaling_list(rbsp, sps->ScalingList4x4[3], 16, Default_4x4_Inter, Default_4x4_Inter); - scaling_list(rbsp, sps->ScalingList4x4[4], 16, Default_4x4_Inter, sps->ScalingList4x4[3]); - scaling_list(rbsp, sps->ScalingList4x4[5], 16, Default_4x4_Inter, sps->ScalingList4x4[4]); - - scaling_list(rbsp, sps->ScalingList8x8[0], 64, Default_8x8_Intra, Default_8x8_Intra); - scaling_list(rbsp, sps->ScalingList8x8[1], 64, Default_8x8_Inter, Default_8x8_Inter); - if (sps->chroma_format_idc == 3) { - scaling_list(rbsp, sps->ScalingList8x8[2], 64, Default_8x8_Intra, sps->ScalingList8x8[0]); - scaling_list(rbsp, sps->ScalingList8x8[3], 64, Default_8x8_Inter, sps->ScalingList8x8[1]); - scaling_list(rbsp, sps->ScalingList8x8[4], 64, Default_8x8_Intra, sps->ScalingList8x8[2]); - scaling_list(rbsp, sps->ScalingList8x8[5], 64, Default_8x8_Inter, sps->ScalingList8x8[3]); - } - } - } else if (profile_idc == 183) - sps->chroma_format_idc = 0; - else - sps->chroma_format_idc = 1; - - sps->log2_max_frame_num_minus4 = vl_rbsp_ue(rbsp); - - sps->pic_order_cnt_type = vl_rbsp_ue(rbsp); - - if (sps->pic_order_cnt_type == 0) - sps->log2_max_pic_order_cnt_lsb_minus4 = vl_rbsp_ue(rbsp); - else if (sps->pic_order_cnt_type == 1) { - sps->delta_pic_order_always_zero_flag = vl_rbsp_u(rbsp, 1); - - sps->offset_for_non_ref_pic = vl_rbsp_se(rbsp); - - sps->offset_for_top_to_bottom_field = vl_rbsp_se(rbsp); - - sps->num_ref_frames_in_pic_order_cnt_cycle = vl_rbsp_ue(rbsp); - - for (i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; ++i) - sps->offset_for_ref_frame[i] = vl_rbsp_se(rbsp); - } - - sps->max_num_ref_frames = vl_rbsp_ue(rbsp); - - /* gaps_in_frame_num_value_allowed_flag */ - vl_rbsp_u(rbsp, 1); - - /* pic_width_in_mbs_minus1 */ - ASSERTED int pic_width_in_samplesl = (vl_rbsp_ue(rbsp) + 1) * 16; - assert(pic_width_in_samplesl); - - /* pic_height_in_map_units_minus1 */ - ASSERTED int pic_height_in_map_units = vl_rbsp_ue(rbsp) + 1; - assert(pic_height_in_map_units); - - sps->frame_mbs_only_flag = vl_rbsp_u(rbsp, 1); - if (!sps->frame_mbs_only_flag) - sps->mb_adaptive_frame_field_flag = vl_rbsp_u(rbsp, 1); - - sps->direct_8x8_inference_flag = vl_rbsp_u(rbsp, 1); - -#if ENABLE_ST_OMX_TIZONIA - priv->stream_info.width = pic_width_in_samplesl; - - int frame_height_in_mbs = (2 - sps->frame_mbs_only_flag) * pic_height_in_map_units; - int pic_height_in_mbs = frame_height_in_mbs / ( 1 + priv->picture.h264.field_pic_flag ); - int pic_height_in_samplesl = pic_height_in_mbs * 16; - priv->stream_info.height = pic_height_in_samplesl; - - - /* frame_cropping_flag */ - if (vl_rbsp_u(rbsp, 1)) { - unsigned frame_crop_left_offset = vl_rbsp_ue(rbsp); - unsigned frame_crop_right_offset = vl_rbsp_ue(rbsp); - unsigned frame_crop_top_offset = vl_rbsp_ue(rbsp); - unsigned frame_crop_bottom_offset = vl_rbsp_ue(rbsp); - - priv->stream_info.width -= (frame_crop_left_offset + frame_crop_right_offset) * 2; - priv->stream_info.height -= (frame_crop_top_offset + frame_crop_bottom_offset) * 2; - } -#else - /* frame_cropping_flag */ - if (vl_rbsp_u(rbsp, 1)) { - /* frame_crop_left_offset */ - vl_rbsp_ue(rbsp); - - /* frame_crop_right_offset */ - vl_rbsp_ue(rbsp); - - /* frame_crop_top_offset */ - vl_rbsp_ue(rbsp); - - /* frame_crop_bottom_offset */ - vl_rbsp_ue(rbsp); - } -#endif - - /* vui_parameters_present_flag */ - if (vl_rbsp_u(rbsp, 1)) - vui_parameters(rbsp); -} - -static struct pipe_h264_pps *pic_parameter_set_id(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp) -{ - unsigned id = vl_rbsp_ue(rbsp); - if (id >= ARRAY_SIZE(priv->codec_data.h264.pps)) - return NULL; /* invalid pic_parameter_set_id */ - - return &priv->codec_data.h264.pps[id]; -} - -static void picture_parameter_set(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp) -{ - struct pipe_h264_sps *sps; - struct pipe_h264_pps *pps; - unsigned i; - - pps = pic_parameter_set_id(priv, rbsp); - if (!pps) - return; - - memset(pps, 0, sizeof(*pps)); - - sps = pps->sps = seq_parameter_set_id(priv, rbsp); - if (!sps) - return; - - memcpy(pps->ScalingList4x4, sps->ScalingList4x4, sizeof(pps->ScalingList4x4)); - memcpy(pps->ScalingList8x8, sps->ScalingList8x8, sizeof(pps->ScalingList8x8)); - - pps->entropy_coding_mode_flag = vl_rbsp_u(rbsp, 1); - - pps->bottom_field_pic_order_in_frame_present_flag = vl_rbsp_u(rbsp, 1); - - pps->num_slice_groups_minus1 = vl_rbsp_ue(rbsp); - if (pps->num_slice_groups_minus1 > 0) { - pps->slice_group_map_type = vl_rbsp_ue(rbsp); - - if (pps->slice_group_map_type == 0) { - - for (i = 0; i <= pps->num_slice_groups_minus1; ++i) - /* run_length_minus1[i] */ - vl_rbsp_ue(rbsp); - - } else if (pps->slice_group_map_type == 2) { - - for (i = 0; i <= pps->num_slice_groups_minus1; ++i) { - /* top_left[i] */ - vl_rbsp_ue(rbsp); - - /* bottom_right[i] */ - vl_rbsp_ue(rbsp); - } - - } else if (pps->slice_group_map_type >= 3 && pps->slice_group_map_type <= 5) { - - /* slice_group_change_direction_flag */ - vl_rbsp_u(rbsp, 1); - - pps->slice_group_change_rate_minus1 = vl_rbsp_ue(rbsp); - - } else if (pps->slice_group_map_type == 6) { - - unsigned pic_size_in_map_units_minus1; - - pic_size_in_map_units_minus1 = vl_rbsp_ue(rbsp); - - for (i = 0; i <= pic_size_in_map_units_minus1; ++i) - /* slice_group_id[i] */ - vl_rbsp_u(rbsp, log2(pps->num_slice_groups_minus1 + 1)); - } - } - - pps->num_ref_idx_l0_default_active_minus1 = vl_rbsp_ue(rbsp); - - pps->num_ref_idx_l1_default_active_minus1 = vl_rbsp_ue(rbsp); - - pps->weighted_pred_flag = vl_rbsp_u(rbsp, 1); - - pps->weighted_bipred_idc = vl_rbsp_u(rbsp, 2); - - pps->pic_init_qp_minus26 = vl_rbsp_se(rbsp); - - /* pic_init_qs_minus26 */ - vl_rbsp_se(rbsp); - - pps->chroma_qp_index_offset = vl_rbsp_se(rbsp); - - pps->deblocking_filter_control_present_flag = vl_rbsp_u(rbsp, 1); - - pps->constrained_intra_pred_flag = vl_rbsp_u(rbsp, 1); - - pps->redundant_pic_cnt_present_flag = vl_rbsp_u(rbsp, 1); - - if (vl_rbsp_more_data(rbsp)) { - pps->transform_8x8_mode_flag = vl_rbsp_u(rbsp, 1); - - /* pic_scaling_matrix_present_flag */ - if (vl_rbsp_u(rbsp, 1)) { - - scaling_list(rbsp, pps->ScalingList4x4[0], 16, Default_4x4_Intra, - sps->seq_scaling_matrix_present_flag ? NULL : Default_4x4_Intra); - scaling_list(rbsp, pps->ScalingList4x4[1], 16, Default_4x4_Intra, pps->ScalingList4x4[0]); - scaling_list(rbsp, pps->ScalingList4x4[2], 16, Default_4x4_Intra, pps->ScalingList4x4[1]); - scaling_list(rbsp, pps->ScalingList4x4[3], 16, Default_4x4_Inter, - sps->seq_scaling_matrix_present_flag ? NULL : Default_4x4_Inter); - scaling_list(rbsp, pps->ScalingList4x4[4], 16, Default_4x4_Inter, pps->ScalingList4x4[3]); - scaling_list(rbsp, pps->ScalingList4x4[5], 16, Default_4x4_Inter, pps->ScalingList4x4[4]); - - if (pps->transform_8x8_mode_flag) { - scaling_list(rbsp, pps->ScalingList8x8[0], 64, Default_8x8_Intra, - sps->seq_scaling_matrix_present_flag ? NULL : Default_8x8_Intra); - scaling_list(rbsp, pps->ScalingList8x8[1], 64, Default_8x8_Inter, - sps->seq_scaling_matrix_present_flag ? NULL : Default_8x8_Inter); - if (sps->chroma_format_idc == 3) { - scaling_list(rbsp, pps->ScalingList8x8[2], 64, Default_8x8_Intra, pps->ScalingList8x8[0]); - scaling_list(rbsp, pps->ScalingList8x8[3], 64, Default_8x8_Inter, pps->ScalingList8x8[1]); - scaling_list(rbsp, pps->ScalingList8x8[4], 64, Default_8x8_Intra, pps->ScalingList8x8[2]); - scaling_list(rbsp, pps->ScalingList8x8[5], 64, Default_8x8_Inter, pps->ScalingList8x8[3]); - } - } - } - - pps->second_chroma_qp_index_offset = vl_rbsp_se(rbsp); - } -} - -static void ref_pic_list_mvc_modification(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp) -{ - // TODO - assert(0); -} - -static void ref_pic_list_modification(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp, - enum pipe_h264_slice_type slice_type) -{ - unsigned modification_of_pic_nums_idc; - - if (slice_type != 2 && slice_type != 4) { - /* ref_pic_list_modification_flag_l0 */ - if (vl_rbsp_u(rbsp, 1)) { - do { - modification_of_pic_nums_idc = vl_rbsp_ue(rbsp); - if (modification_of_pic_nums_idc == 0 || - modification_of_pic_nums_idc == 1) - /* abs_diff_pic_num_minus1 */ - vl_rbsp_ue(rbsp); - else if (modification_of_pic_nums_idc == 2) - /* long_term_pic_num */ - vl_rbsp_ue(rbsp); - } while (modification_of_pic_nums_idc != 3); - } - } - - if (slice_type == 1) { - /* ref_pic_list_modification_flag_l1 */ - if (vl_rbsp_u(rbsp, 1)) { - do { - modification_of_pic_nums_idc = vl_rbsp_ue(rbsp); - if (modification_of_pic_nums_idc == 0 || - modification_of_pic_nums_idc == 1) - /* abs_diff_pic_num_minus1 */ - vl_rbsp_ue(rbsp); - else if (modification_of_pic_nums_idc == 2) - /* long_term_pic_num */ - vl_rbsp_ue(rbsp); - } while (modification_of_pic_nums_idc != 3); - } - } -} - -static void pred_weight_table(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp, - struct pipe_h264_sps *sps, enum pipe_h264_slice_type slice_type) -{ - unsigned ChromaArrayType = sps->separate_colour_plane_flag ? 0 : sps->chroma_format_idc; - unsigned i, j; - - /* luma_log2_weight_denom */ - vl_rbsp_ue(rbsp); - - if (ChromaArrayType != 0) - /* chroma_log2_weight_denom */ - vl_rbsp_ue(rbsp); - - for (i = 0; i <= priv->picture.h264.num_ref_idx_l0_active_minus1; ++i) { - /* luma_weight_l0_flag */ - if (vl_rbsp_u(rbsp, 1)) { - /* luma_weight_l0[i] */ - vl_rbsp_se(rbsp); - /* luma_offset_l0[i] */ - vl_rbsp_se(rbsp); - } - if (ChromaArrayType != 0) { - /* chroma_weight_l0_flag */ - if (vl_rbsp_u(rbsp, 1)) { - for (j = 0; j < 2; ++j) { - /* chroma_weight_l0[i][j] */ - vl_rbsp_se(rbsp); - /* chroma_offset_l0[i][j] */ - vl_rbsp_se(rbsp); - } - } - } - } - - if (slice_type == 1) { - for (i = 0; i <= priv->picture.h264.num_ref_idx_l1_active_minus1; ++i) { - /* luma_weight_l1_flag */ - if (vl_rbsp_u(rbsp, 1)) { - /* luma_weight_l1[i] */ - vl_rbsp_se(rbsp); - /* luma_offset_l1[i] */ - vl_rbsp_se(rbsp); - } - if (ChromaArrayType != 0) { - /* chroma_weight_l1_flag */ - if (vl_rbsp_u(rbsp, 1)) { - for (j = 0; j < 2; ++j) { - /* chroma_weight_l1[i][j] */ - vl_rbsp_se(rbsp); - /* chroma_offset_l1[i][j] */ - vl_rbsp_se(rbsp); - } - } - } - } - } -} - -static void dec_ref_pic_marking(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp, - bool IdrPicFlag) -{ - unsigned memory_management_control_operation; - - if (IdrPicFlag) { - /* no_output_of_prior_pics_flag */ - vl_rbsp_u(rbsp, 1); - /* long_term_reference_flag */ - vl_rbsp_u(rbsp, 1); - } else { - /* adaptive_ref_pic_marking_mode_flag */ - if (vl_rbsp_u(rbsp, 1)) { - do { - memory_management_control_operation = vl_rbsp_ue(rbsp); - - if (memory_management_control_operation == 1 || - memory_management_control_operation == 3) - /* difference_of_pic_nums_minus1 */ - vl_rbsp_ue(rbsp); - - if (memory_management_control_operation == 2) - /* long_term_pic_num */ - vl_rbsp_ue(rbsp); - - if (memory_management_control_operation == 3 || - memory_management_control_operation == 6) - /* long_term_frame_idx */ - vl_rbsp_ue(rbsp); - - if (memory_management_control_operation == 4) - /* max_long_term_frame_idx_plus1 */ - vl_rbsp_ue(rbsp); - } while (memory_management_control_operation != 0); - } - } -} - -static void slice_header(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp, - unsigned nal_ref_idc, unsigned nal_unit_type) -{ - enum pipe_h264_slice_type slice_type; - struct pipe_h264_pps *pps; - struct pipe_h264_sps *sps; - unsigned frame_num, prevFrameNum; - bool IdrPicFlag = nal_unit_type == 5; - - if (IdrPicFlag != priv->codec_data.h264.IdrPicFlag) - vid_dec_h264_EndFrame(priv); - - priv->codec_data.h264.IdrPicFlag = IdrPicFlag; - - /* first_mb_in_slice */ - vl_rbsp_ue(rbsp); - - slice_type = vl_rbsp_ue(rbsp) % 5; - - /* get picture parameter set */ - pps = pic_parameter_set_id(priv, rbsp); - if (!pps) - return; - - /* get sequence parameter set */ - sps = pps->sps; - if (!sps) - return; - - if (pps != priv->picture.h264.pps) - vid_dec_h264_EndFrame(priv); - - priv->picture.h264.pps = pps; - - if (sps->separate_colour_plane_flag == 1 ) - /* colour_plane_id */ - vl_rbsp_u(rbsp, 2); - - /* frame number handling */ - frame_num = vl_rbsp_u(rbsp, sps->log2_max_frame_num_minus4 + 4); - - if (frame_num != priv->picture.h264.frame_num) - vid_dec_h264_EndFrame(priv); - - prevFrameNum = priv->picture.h264.frame_num; - priv->picture.h264.frame_num = frame_num; - - priv->picture.h264.field_pic_flag = 0; - priv->picture.h264.bottom_field_flag = 0; - - if (!sps->frame_mbs_only_flag) { - unsigned field_pic_flag = vl_rbsp_u(rbsp, 1); - - if (!field_pic_flag && field_pic_flag != priv->picture.h264.field_pic_flag) - vid_dec_h264_EndFrame(priv); - - priv->picture.h264.field_pic_flag = field_pic_flag; - - if (priv->picture.h264.field_pic_flag) { - unsigned bottom_field_flag = vl_rbsp_u(rbsp, 1); - - if (bottom_field_flag != priv->picture.h264.bottom_field_flag) - vid_dec_h264_EndFrame(priv); - - priv->picture.h264.bottom_field_flag = bottom_field_flag; - } - } - - if (IdrPicFlag) { - /* set idr_pic_id */ - unsigned idr_pic_id = vl_rbsp_ue(rbsp); - - if (idr_pic_id != priv->codec_data.h264.idr_pic_id) - vid_dec_h264_EndFrame(priv); - - priv->codec_data.h264.idr_pic_id = idr_pic_id; - } - - if (sps->pic_order_cnt_type == 0) { - /* pic_order_cnt_lsb */ - unsigned log2_max_pic_order_cnt_lsb = sps->log2_max_pic_order_cnt_lsb_minus4 + 4; - unsigned max_pic_order_cnt_lsb = 1 << log2_max_pic_order_cnt_lsb; - int pic_order_cnt_lsb = vl_rbsp_u(rbsp, log2_max_pic_order_cnt_lsb); - int pic_order_cnt_msb; - - if (pic_order_cnt_lsb != priv->codec_data.h264.pic_order_cnt_lsb) - vid_dec_h264_EndFrame(priv); - - if (IdrPicFlag) { - priv->codec_data.h264.pic_order_cnt_msb = 0; - priv->codec_data.h264.pic_order_cnt_lsb = 0; - } - - if ((pic_order_cnt_lsb < priv->codec_data.h264.pic_order_cnt_lsb) && - (priv->codec_data.h264.pic_order_cnt_lsb - pic_order_cnt_lsb) >= (max_pic_order_cnt_lsb / 2)) - pic_order_cnt_msb = priv->codec_data.h264.pic_order_cnt_msb + max_pic_order_cnt_lsb; - - else if ((pic_order_cnt_lsb > priv->codec_data.h264.pic_order_cnt_lsb) && - (pic_order_cnt_lsb - priv->codec_data.h264.pic_order_cnt_lsb) > (max_pic_order_cnt_lsb / 2)) - pic_order_cnt_msb = priv->codec_data.h264.pic_order_cnt_msb - max_pic_order_cnt_lsb; - - else - pic_order_cnt_msb = priv->codec_data.h264.pic_order_cnt_msb; - - priv->codec_data.h264.pic_order_cnt_msb = pic_order_cnt_msb; - priv->codec_data.h264.pic_order_cnt_lsb = pic_order_cnt_lsb; - - if (pps->bottom_field_pic_order_in_frame_present_flag && !priv->picture.h264.field_pic_flag) { - /* delta_pic_oreder_cnt_bottom */ - unsigned delta_pic_order_cnt_bottom = vl_rbsp_se(rbsp); - - if (delta_pic_order_cnt_bottom != priv->codec_data.h264.delta_pic_order_cnt_bottom) - vid_dec_h264_EndFrame(priv); - - priv->codec_data.h264.delta_pic_order_cnt_bottom = delta_pic_order_cnt_bottom; - } - - if (!priv->picture.h264.field_pic_flag) { - priv->picture.h264.field_order_cnt[0] = pic_order_cnt_msb + pic_order_cnt_lsb; - priv->picture.h264.field_order_cnt[1] = priv->picture.h264.field_order_cnt [0] + - priv->codec_data.h264.delta_pic_order_cnt_bottom; - } else if (!priv->picture.h264.bottom_field_flag) - priv->picture.h264.field_order_cnt[0] = pic_order_cnt_msb + pic_order_cnt_lsb; - else - priv->picture.h264.field_order_cnt[1] = pic_order_cnt_msb + pic_order_cnt_lsb; - - } else if (sps->pic_order_cnt_type == 1) { - /* delta_pic_order_cnt[0] */ - unsigned MaxFrameNum = 1 << (sps->log2_max_frame_num_minus4 + 4); - unsigned FrameNumOffset, absFrameNum, expectedPicOrderCnt; - - if (!sps->delta_pic_order_always_zero_flag) { - unsigned delta_pic_order_cnt[2]; - - delta_pic_order_cnt[0] = vl_rbsp_se(rbsp); - - if (delta_pic_order_cnt[0] != priv->codec_data.h264.delta_pic_order_cnt[0]) - vid_dec_h264_EndFrame(priv); - - priv->codec_data.h264.delta_pic_order_cnt[0] = delta_pic_order_cnt[0]; - - if (pps->bottom_field_pic_order_in_frame_present_flag && !priv->picture.h264.field_pic_flag) { - /* delta_pic_order_cnt[1] */ - delta_pic_order_cnt[1] = vl_rbsp_se(rbsp); - - if (delta_pic_order_cnt[1] != priv->codec_data.h264.delta_pic_order_cnt[1]) - vid_dec_h264_EndFrame(priv); - - priv->codec_data.h264.delta_pic_order_cnt[1] = delta_pic_order_cnt[1]; - } - } - - if (IdrPicFlag) - FrameNumOffset = 0; - else if (prevFrameNum > frame_num) - FrameNumOffset = priv->codec_data.h264.prevFrameNumOffset + MaxFrameNum; - else - FrameNumOffset = priv->codec_data.h264.prevFrameNumOffset; - - priv->codec_data.h264.prevFrameNumOffset = FrameNumOffset; - - if (sps->num_ref_frames_in_pic_order_cnt_cycle != 0) - absFrameNum = FrameNumOffset + frame_num; - else - absFrameNum = 0; - - if (nal_ref_idc == 0 && absFrameNum > 0) - absFrameNum = absFrameNum - 1; - - if (absFrameNum > 0) { - unsigned picOrderCntCycleCnt = (absFrameNum - 1) / sps->num_ref_frames_in_pic_order_cnt_cycle; - unsigned frameNumInPicOrderCntCycle = (absFrameNum - 1) % sps->num_ref_frames_in_pic_order_cnt_cycle; - signed ExpectedDeltaPerPicOrderCntCycle = 0; - unsigned i; - - for (i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; ++i) - ExpectedDeltaPerPicOrderCntCycle += sps->offset_for_ref_frame[i]; - - expectedPicOrderCnt = picOrderCntCycleCnt * ExpectedDeltaPerPicOrderCntCycle; - for (i = 0; i <= frameNumInPicOrderCntCycle; ++i) - expectedPicOrderCnt += sps->offset_for_ref_frame[i]; - - } else - expectedPicOrderCnt = 0; - - if (nal_ref_idc == 0) - expectedPicOrderCnt += sps->offset_for_non_ref_pic; - - if (!priv->picture.h264.field_pic_flag) { - priv->picture.h264.field_order_cnt[0] = expectedPicOrderCnt + priv->codec_data.h264.delta_pic_order_cnt[0]; - priv->picture.h264.field_order_cnt[1] = priv->picture.h264.field_order_cnt[0] + - sps->offset_for_top_to_bottom_field + priv->codec_data.h264.delta_pic_order_cnt[1]; - - } else if (!priv->picture.h264.bottom_field_flag) - priv->picture.h264.field_order_cnt[0] = expectedPicOrderCnt + priv->codec_data.h264.delta_pic_order_cnt[0]; - else - priv->picture.h264.field_order_cnt[1] = expectedPicOrderCnt + sps->offset_for_top_to_bottom_field + - priv->codec_data.h264.delta_pic_order_cnt[0]; - - } else if (sps->pic_order_cnt_type == 2) { - unsigned MaxFrameNum = 1 << (sps->log2_max_frame_num_minus4 + 4); - unsigned FrameNumOffset, tempPicOrderCnt; - - if (IdrPicFlag) - FrameNumOffset = 0; - else if (prevFrameNum > frame_num) - FrameNumOffset = priv->codec_data.h264.prevFrameNumOffset + MaxFrameNum; - else - FrameNumOffset = priv->codec_data.h264.prevFrameNumOffset; - - priv->codec_data.h264.prevFrameNumOffset = FrameNumOffset; - - if (IdrPicFlag) - tempPicOrderCnt = 0; - else if (nal_ref_idc == 0) - tempPicOrderCnt = 2 * (FrameNumOffset + frame_num) - 1; - else - tempPicOrderCnt = 2 * (FrameNumOffset + frame_num); - - if (!priv->picture.h264.field_pic_flag) { - priv->picture.h264.field_order_cnt[0] = tempPicOrderCnt; - priv->picture.h264.field_order_cnt[1] = tempPicOrderCnt; - - } else if (!priv->picture.h264.bottom_field_flag) - priv->picture.h264.field_order_cnt[0] = tempPicOrderCnt; - else - priv->picture.h264.field_order_cnt[1] = tempPicOrderCnt; - } - - if (pps->redundant_pic_cnt_present_flag) - /* redundant_pic_cnt */ - vl_rbsp_ue(rbsp); - - if (slice_type == PIPE_H264_SLICE_TYPE_B) - /* direct_spatial_mv_pred_flag */ - vl_rbsp_u(rbsp, 1); - - priv->picture.h264.num_ref_idx_l0_active_minus1 = pps->num_ref_idx_l0_default_active_minus1; - priv->picture.h264.num_ref_idx_l1_active_minus1 = pps->num_ref_idx_l1_default_active_minus1; - - if (slice_type == PIPE_H264_SLICE_TYPE_P || - slice_type == PIPE_H264_SLICE_TYPE_SP || - slice_type == PIPE_H264_SLICE_TYPE_B) { - - /* num_ref_idx_active_override_flag */ - if (vl_rbsp_u(rbsp, 1)) { - priv->picture.h264.num_ref_idx_l0_active_minus1 = vl_rbsp_ue(rbsp); - - if (slice_type == PIPE_H264_SLICE_TYPE_B) - priv->picture.h264.num_ref_idx_l1_active_minus1 = vl_rbsp_ue(rbsp); - } - } - - if (nal_unit_type == 20 || nal_unit_type == 21) - ref_pic_list_mvc_modification(priv, rbsp); - else - ref_pic_list_modification(priv, rbsp, slice_type); - - if ((pps->weighted_pred_flag && (slice_type == PIPE_H264_SLICE_TYPE_P || slice_type == PIPE_H264_SLICE_TYPE_SP)) || - (pps->weighted_bipred_idc == 1 && slice_type == PIPE_H264_SLICE_TYPE_B)) - pred_weight_table(priv, rbsp, sps, slice_type); - - if (nal_ref_idc != 0) - dec_ref_pic_marking(priv, rbsp, IdrPicFlag); - - if (pps->entropy_coding_mode_flag && slice_type != PIPE_H264_SLICE_TYPE_I && slice_type != PIPE_H264_SLICE_TYPE_SI) - /* cabac_init_idc */ - vl_rbsp_ue(rbsp); - - /* slice_qp_delta */ - vl_rbsp_se(rbsp); - - if (slice_type == PIPE_H264_SLICE_TYPE_SP || slice_type == PIPE_H264_SLICE_TYPE_SI) { - if (slice_type == PIPE_H264_SLICE_TYPE_SP) - /* sp_for_switch_flag */ - vl_rbsp_u(rbsp, 1); - - /*slice_qs_delta */ - vl_rbsp_se(rbsp); - } - - if (pps->deblocking_filter_control_present_flag) { - unsigned disable_deblocking_filter_idc = vl_rbsp_ue(rbsp); - - if (disable_deblocking_filter_idc != 1) { - /* slice_alpha_c0_offset_div2 */ - vl_rbsp_se(rbsp); - - /* slice_beta_offset_div2 */ - vl_rbsp_se(rbsp); - } - } - - if (pps->num_slice_groups_minus1 > 0 && pps->slice_group_map_type >= 3 && pps->slice_group_map_type <= 5) - /* slice_group_change_cycle */ - vl_rbsp_u(rbsp, 2); -} - -#if ENABLE_ST_OMX_TIZONIA -static OMX_ERRORTYPE update_port_parameters(vid_dec_PrivateType* priv) { - OMX_VIDEO_PORTDEFINITIONTYPE * p_def = NULL; /* Output port info */ - h264d_stream_info_t * i_def = NULL; /* Info read from stream */ - OMX_ERRORTYPE err = OMX_ErrorNone; - - assert(priv); - - p_def = &(priv->out_port_def_.format.video); - i_def = &(priv->stream_info); - - /* Handle dynamic resolution change */ - if ((p_def->nFrameWidth == i_def->width) && p_def->nFrameHeight == i_def->height) - return err; - - p_def->nFrameWidth = i_def->width; - p_def->nFrameHeight = i_def->height; - p_def->nStride = i_def->width; - p_def->nSliceHeight = i_def->height; - - err = tiz_krn_SetParameter_internal(tiz_get_krn(handleOf(priv)), handleOf(priv), - OMX_IndexParamPortDefinition, &(priv->out_port_def_)); - if (err == OMX_ErrorNone) { - tiz_port_t * p_obj = tiz_krn_get_port(tiz_get_krn(handleOf(priv)), OMX_VID_DEC_AVC_INPUT_PORT_INDEX); - - /* Set desired buffer size that will be used when allocating input buffers */ - p_obj->portdef_.nBufferSize = p_def->nFrameWidth * p_def->nFrameHeight * 512 / (16*16); - - /* Get a locally copy of port def. Useful for the early return above */ - tiz_check_omx(tiz_api_GetParameter(tiz_get_krn(handleOf(priv)), handleOf(priv), - OMX_IndexParamPortDefinition, &(priv->out_port_def_))); - - tiz_srv_issue_event((OMX_PTR) priv, OMX_EventPortSettingsChanged, - OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX, - OMX_IndexParamPortDefinition, - NULL); - } - - return err; -} -#endif - -void vid_dec_h264_Decode(vid_dec_PrivateType *priv, struct vl_vlc *vlc, unsigned min_bits_left) -{ - unsigned nal_ref_idc, nal_unit_type; - - if (!vl_vlc_search_byte(vlc, vl_vlc_bits_left(vlc) - min_bits_left, 0x00)) - return; - - if (vl_vlc_peekbits(vlc, 24) != 0x000001) { - vl_vlc_eatbits(vlc, 8); - return; - } - - if (priv->slice) { - unsigned bytes = priv->bytes_left - (vl_vlc_bits_left(vlc) / 8); - ++priv->picture.h264.slice_count; - priv->codec->decode_bitstream(priv->codec, priv->target, &priv->picture.base, - 1, &priv->slice, &bytes); - priv->slice = NULL; - } - - vl_vlc_eatbits(vlc, 24); - - /* forbidden_zero_bit */ - vl_vlc_eatbits(vlc, 1); - - nal_ref_idc = vl_vlc_get_uimsbf(vlc, 2); - - if (nal_ref_idc != priv->codec_data.h264.nal_ref_idc && - (nal_ref_idc * priv->codec_data.h264.nal_ref_idc) == 0) - vid_dec_h264_EndFrame(priv); - - priv->codec_data.h264.nal_ref_idc = nal_ref_idc; - - nal_unit_type = vl_vlc_get_uimsbf(vlc, 5); - - if (nal_unit_type != 1 && nal_unit_type != 5) - vid_dec_h264_EndFrame(priv); - - if (nal_unit_type == 7) { - struct vl_rbsp rbsp; - vl_rbsp_init(&rbsp, vlc, ~0); - seq_parameter_set(priv, &rbsp); -#if ENABLE_ST_OMX_TIZONIA - update_port_parameters(priv); -#endif - - } else if (nal_unit_type == 8) { - struct vl_rbsp rbsp; - vl_rbsp_init(&rbsp, vlc, ~0); - picture_parameter_set(priv, &rbsp); - - } else if (nal_unit_type == 1 || nal_unit_type == 5) { - /* Coded slice of a non-IDR or IDR picture */ - unsigned bits = vl_vlc_valid_bits(vlc); - unsigned bytes = bits / 8 + 4; - struct vl_rbsp rbsp; - uint8_t buf[8]; - const void *ptr = buf; - unsigned i; - - buf[0] = 0x0; - buf[1] = 0x0; - buf[2] = 0x1; - buf[3] = (nal_ref_idc << 5) | nal_unit_type; - for (i = 4; i < bytes; ++i) - buf[i] = vl_vlc_peekbits(vlc, bits) >> ((bytes - i - 1) * 8); - - priv->bytes_left = (vl_vlc_bits_left(vlc) - bits) / 8; - priv->slice = vlc->data; - - vl_rbsp_init(&rbsp, vlc, 128); - slice_header(priv, &rbsp, nal_ref_idc, nal_unit_type); - - vid_dec_h264_BeginFrame(priv); - - ++priv->picture.h264.slice_count; - priv->codec->decode_bitstream(priv->codec, priv->target, &priv->picture.base, - 1, &ptr, &bytes); - } - - /* resync to byte boundary */ - vl_vlc_eatbits(vlc, vl_vlc_valid_bits(vlc) % 8); -} - -void vid_dec_FreeInputPortPrivate(OMX_BUFFERHEADERTYPE *buf) -{ - struct pipe_video_buffer *vbuf = buf->pInputPortPrivate; - if (!vbuf) - return; - - vbuf->destroy(vbuf); - buf->pInputPortPrivate = NULL; -} - -void vid_dec_FrameDecoded_common(vid_dec_PrivateType* priv, OMX_BUFFERHEADERTYPE* input, - OMX_BUFFERHEADERTYPE* output) -{ -#if ENABLE_ST_OMX_BELLAGIO - bool eos = !!(input->nFlags & OMX_BUFFERFLAG_EOS); -#else - bool eos = priv->eos_; -#endif - OMX_TICKS timestamp; - - if (!input->pInputPortPrivate) { -#if ENABLE_ST_OMX_BELLAGIO - input->pInputPortPrivate = priv->Flush(priv, ×tamp); -#else - input->pInputPortPrivate = vid_dec_h264_Flush(priv, ×tamp); -#endif - if (timestamp != OMX_VID_DEC_AVC_TIMESTAMP_INVALID) - input->nTimeStamp = timestamp; - } - - if (input->pInputPortPrivate) { - if (output->pInputPortPrivate && !priv->disable_tunnel) { - struct pipe_video_buffer *tmp, *vbuf, *new_vbuf; - - tmp = output->pOutputPortPrivate; - vbuf = input->pInputPortPrivate; - if (vbuf->interlaced) { - /* re-allocate the progressive buffer */ - struct pipe_video_buffer templat = {}; - struct u_rect src_rect, dst_rect; - -#if ENABLE_ST_OMX_BELLAGIO - omx_base_video_PortType *port; - port = (omx_base_video_PortType *) - priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; -#else - tiz_port_t *port; - port = tiz_krn_get_port(tiz_get_krn(handleOf (priv)), OMX_VID_DEC_AVC_INPUT_PORT_INDEX); -#endif - memset(&templat, 0, sizeof(templat)); -#if ENABLE_ST_OMX_BELLAGIO - templat.width = port->sPortParam.format.video.nFrameWidth; - templat.height = port->sPortParam.format.video.nFrameHeight; -#else - templat.width = port->portdef_.format.video.nFrameWidth; - templat.height = port->portdef_.format.video.nFrameHeight; -#endif - templat.buffer_format = PIPE_FORMAT_NV12; - templat.interlaced = false; - new_vbuf = priv->pipe->create_video_buffer(priv->pipe, &templat); - - /* convert the interlaced to the progressive */ - src_rect.x0 = dst_rect.x0 = 0; - src_rect.x1 = dst_rect.x1 = templat.width; - src_rect.y0 = dst_rect.y0 = 0; - src_rect.y1 = dst_rect.y1 = templat.height; - - vl_compositor_yuv_deint_full(&priv->cstate, &priv->compositor, - input->pInputPortPrivate, new_vbuf, - &src_rect, &dst_rect, VL_COMPOSITOR_WEAVE); - - /* set the progrssive buffer for next round */ - vbuf->destroy(vbuf); - input->pInputPortPrivate = new_vbuf; - } - output->pOutputPortPrivate = input->pInputPortPrivate; - input->pInputPortPrivate = tmp; - } else { - vid_dec_FillOutput(priv, input->pInputPortPrivate, output); - } - output->nFilledLen = output->nAllocLen; - output->nTimeStamp = input->nTimeStamp; - } - - if (eos && input->pInputPortPrivate) - vid_dec_FreeInputPortPrivate(input); - else - input->nFilledLen = 0; -} diff --git a/src/gallium/state_trackers/omx/vid_dec_h264_common.h b/src/gallium/state_trackers/omx/vid_dec_h264_common.h deleted file mode 100644 index abde53beef9..00000000000 --- a/src/gallium/state_trackers/omx/vid_dec_h264_common.h +++ /dev/null @@ -1,99 +0,0 @@ -/************************************************************************** - * - * Copyright 2013 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#ifndef VID_DEC_H264_COMMON_H -#define VID_DEC_H264_COMMON_H - -#include "vid_dec_common.h" - -#define OMX_VID_DEC_AVC_DEFAULT_FRAME_WIDTH 176 -#define OMX_VID_DEC_AVC_DEFAULT_FRAME_HEIGHT 144 -#define OMX_VID_DEC_AVC_DEFAULT_FRAME_RATE 15<<16 -#define OMX_VID_DEC_AVC_ROLE "video_decoder.avc" -/* With libtizonia, port indexes must start at index 0 */ -#define OMX_VID_DEC_AVC_INPUT_PORT_INDEX 0 -#define OMX_VID_DEC_AVC_OUTPUT_PORT_INDEX 1 -#define OMX_VID_DEC_AVC_INPUT_PORT_MIN_BUF_COUNT 8 -#define OMX_VID_DEC_AVC_OUTPUT_PORT_MIN_BUF_COUNT 4 -/* 38016 = (width * height) + ((width * height)/2) */ -#define OMX_VID_DEC_AVC_PORT_MIN_INPUT_BUF_SIZE 38016 -#define OMX_VID_DEC_AVC_PORT_MIN_OUTPUT_BUF_SIZE 345600 -#define OMX_VID_DEC_AVC_PORT_NONCONTIGUOUS OMX_FALSE -#define OMX_VID_DEC_AVC_PORT_ALIGNMENT 0 -#define OMX_VID_DEC_AVC_PORT_SUPPLIERPREF OMX_BufferSupplyInput -#define OMX_VID_DEC_AVC_TIMESTAMP_INVALID ((OMX_TICKS) -1) - -#define DPB_MAX_SIZE 5 - -struct dpb_list { - struct list_head list; - struct pipe_video_buffer *buffer; - OMX_TICKS timestamp; - int poc; -}; - -static const uint8_t Default_4x4_Intra[16] = { - 6, 13, 20, 28, 13, 20, 28, 32, - 20, 28, 32, 37, 28, 32, 37, 42 -}; - -static const uint8_t Default_4x4_Inter[16] = { - 10, 14, 20, 24, 14, 20, 24, 27, - 20, 24, 27, 30, 24, 27, 30, 34 -}; - -static const uint8_t Default_8x8_Intra[64] = { - 6, 10, 13, 16, 18, 23, 25, 27, - 10, 11, 16, 18, 23, 25, 27, 29, - 13, 16, 18, 23, 25, 27, 29, 31, - 16, 18, 23, 25, 27, 29, 31, 33, - 18, 23, 25, 27, 29, 31, 33, 36, - 23, 25, 27, 29, 31, 33, 36, 38, - 25, 27, 29, 31, 33, 36, 38, 40, - 27, 29, 31, 33, 36, 38, 40, 42 -}; - -static const uint8_t Default_8x8_Inter[64] = { - 9, 13, 15, 17, 19, 21, 22, 24, - 13, 13, 17, 19, 21, 22, 24, 25, - 15, 17, 19, 21, 22, 24, 25, 27, - 17, 19, 21, 22, 24, 25, 27, 28, - 19, 21, 22, 24, 25, 27, 28, 30, - 21, 22, 24, 25, 27, 28, 30, 32, - 22, 24, 25, 27, 28, 30, 32, 33, - 24, 25, 27, 28, 30, 32, 33, 35 -}; - -struct pipe_video_buffer *vid_dec_h264_Flush(vid_dec_PrivateType *priv, - OMX_TICKS *timestamp); -void vid_dec_h264_EndFrame(vid_dec_PrivateType *priv); -void vid_dec_h264_Decode(vid_dec_PrivateType *priv, struct vl_vlc *vlc, unsigned min_bits_left); -void vid_dec_FreeInputPortPrivate(OMX_BUFFERHEADERTYPE *buf); -void vid_dec_FrameDecoded_common(vid_dec_PrivateType*priv, OMX_BUFFERHEADERTYPE* input, - OMX_BUFFERHEADERTYPE* output); - -#endif diff --git a/src/gallium/state_trackers/omx/vid_enc_common.c b/src/gallium/state_trackers/omx/vid_enc_common.c deleted file mode 100644 index 1cc0c130e5d..00000000000 --- a/src/gallium/state_trackers/omx/vid_enc_common.c +++ /dev/null @@ -1,554 +0,0 @@ -/************************************************************************** - * - * Copyright 2013 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include "vid_enc_common.h" - -#include "vl/vl_video_buffer.h" -#include "tgsi/tgsi_text.h" - -void enc_ReleaseTasks(struct list_head *head) -{ - struct encode_task *i, *next; - - if (!head || !head->next) - return; - - LIST_FOR_EACH_ENTRY_SAFE(i, next, head, list) { - pipe_resource_reference(&i->bitstream, NULL); - i->buf->destroy(i->buf); - FREE(i); - } -} - -void enc_MoveTasks(struct list_head *from, struct list_head *to) -{ - to->prev->next = from->next; - from->next->prev = to->prev; - from->prev->next = to; - to->prev = from->prev; - list_inithead(from); -} - -static void enc_GetPictureParamPreset(struct pipe_h264_enc_picture_desc *picture) -{ - picture->motion_est.enc_disable_sub_mode = 0x000000fe; - picture->motion_est.enc_ime2_search_range_x = 0x00000001; - picture->motion_est.enc_ime2_search_range_y = 0x00000001; - picture->pic_ctrl.enc_constraint_set_flags = 0x00000040; -} - -enum pipe_video_profile enc_TranslateOMXProfileToPipe(unsigned omx_profile) -{ - switch (omx_profile) { - case OMX_VIDEO_AVCProfileBaseline: - return PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE; - case OMX_VIDEO_AVCProfileMain: - return PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN; - case OMX_VIDEO_AVCProfileExtended: - return PIPE_VIDEO_PROFILE_MPEG4_AVC_EXTENDED; - case OMX_VIDEO_AVCProfileHigh: - return PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH; - case OMX_VIDEO_AVCProfileHigh10: - return PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH10; - case OMX_VIDEO_AVCProfileHigh422: - return PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH422; - case OMX_VIDEO_AVCProfileHigh444: - return PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH444; - default: - return PIPE_VIDEO_PROFILE_UNKNOWN; - } -} - -unsigned enc_TranslateOMXLevelToPipe(unsigned omx_level) -{ - switch (omx_level) { - case OMX_VIDEO_AVCLevel1: - case OMX_VIDEO_AVCLevel1b: - return 10; - case OMX_VIDEO_AVCLevel11: - return 11; - case OMX_VIDEO_AVCLevel12: - return 12; - case OMX_VIDEO_AVCLevel13: - return 13; - case OMX_VIDEO_AVCLevel2: - return 20; - case OMX_VIDEO_AVCLevel21: - return 21; - case OMX_VIDEO_AVCLevel22: - return 22; - case OMX_VIDEO_AVCLevel3: - return 30; - case OMX_VIDEO_AVCLevel31: - return 31; - case OMX_VIDEO_AVCLevel32: - return 32; - case OMX_VIDEO_AVCLevel4: - return 40; - case OMX_VIDEO_AVCLevel41: - return 41; - default: - case OMX_VIDEO_AVCLevel42: - return 42; - case OMX_VIDEO_AVCLevel5: - return 50; - case OMX_VIDEO_AVCLevel51: - return 51; - } -} - -void vid_enc_BufferEncoded_common(vid_enc_PrivateType * priv, OMX_BUFFERHEADERTYPE* input, OMX_BUFFERHEADERTYPE* output) -{ - struct output_buf_private *outp = output->pOutputPortPrivate; - struct input_buf_private *inp = input->pInputPortPrivate; - struct encode_task *task; - struct pipe_box box = {}; - unsigned size; - -#if ENABLE_ST_OMX_BELLAGIO - if (!inp || list_is_empty(&inp->tasks)) { - input->nFilledLen = 0; /* mark buffer as empty */ - enc_MoveTasks(&priv->used_tasks, &inp->tasks); - return; - } -#endif - - task = LIST_ENTRY(struct encode_task, inp->tasks.next, list); - list_del(&task->list); - list_addtail(&task->list, &priv->used_tasks); - - if (!task->bitstream) - return; - - /* ------------- map result buffer ----------------- */ - - if (outp->transfer) - pipe_transfer_unmap(priv->t_pipe, outp->transfer); - - pipe_resource_reference(&outp->bitstream, task->bitstream); - pipe_resource_reference(&task->bitstream, NULL); - - box.width = outp->bitstream->width0; - box.height = outp->bitstream->height0; - box.depth = outp->bitstream->depth0; - - output->pBuffer = priv->t_pipe->transfer_map(priv->t_pipe, outp->bitstream, 0, - PIPE_TRANSFER_READ_WRITE, - &box, &outp->transfer); - - /* ------------- get size of result ----------------- */ - - priv->codec->get_feedback(priv->codec, task->feedback, &size); - - output->nOffset = 0; - output->nFilledLen = size; /* mark buffer as full */ - - /* all output buffers contain exactly one frame */ - output->nFlags = OMX_BUFFERFLAG_ENDOFFRAME; - -#if ENABLE_ST_OMX_TIZONIA - input->nFilledLen = 0; /* mark buffer as empty */ - enc_MoveTasks(&priv->used_tasks, &inp->tasks); -#endif -} - - -struct encode_task *enc_NeedTask_common(vid_enc_PrivateType * priv, OMX_VIDEO_PORTDEFINITIONTYPE *def) -{ - struct pipe_video_buffer templat = {}; - struct encode_task *task; - - if (!list_is_empty(&priv->free_tasks)) { - task = LIST_ENTRY(struct encode_task, priv->free_tasks.next, list); - list_del(&task->list); - return task; - } - - /* allocate a new one */ - task = CALLOC_STRUCT(encode_task); - if (!task) - return NULL; - - templat.buffer_format = PIPE_FORMAT_NV12; - templat.width = def->nFrameWidth; - templat.height = def->nFrameHeight; - templat.interlaced = false; - - task->buf = priv->s_pipe->create_video_buffer(priv->s_pipe, &templat); - if (!task->buf) { - FREE(task); - return NULL; - } - - return task; -} - -void enc_ScaleInput_common(vid_enc_PrivateType * priv, OMX_VIDEO_PORTDEFINITIONTYPE *def, - struct pipe_video_buffer **vbuf, unsigned *size) -{ - struct pipe_video_buffer *src_buf = *vbuf; - struct vl_compositor *compositor = &priv->compositor; - struct vl_compositor_state *s = &priv->cstate; - struct pipe_sampler_view **views; - struct pipe_surface **dst_surface; - unsigned i; - - if (!priv->scale_buffer[priv->current_scale_buffer]) - return; - - views = src_buf->get_sampler_view_planes(src_buf); - dst_surface = priv->scale_buffer[priv->current_scale_buffer]->get_surfaces - (priv->scale_buffer[priv->current_scale_buffer]); - vl_compositor_clear_layers(s); - - for (i = 0; i < VL_MAX_SURFACES; ++i) { - struct u_rect src_rect; - if (!views[i] || !dst_surface[i]) - continue; - src_rect.x0 = 0; - src_rect.y0 = 0; - src_rect.x1 = def->nFrameWidth; - src_rect.y1 = def->nFrameHeight; - if (i > 0) { - src_rect.x1 /= 2; - src_rect.y1 /= 2; - } - vl_compositor_set_rgba_layer(s, compositor, 0, views[i], &src_rect, NULL, NULL); - vl_compositor_render(s, compositor, dst_surface[i], NULL, false); - } - *size = priv->scale.xWidth * priv->scale.xHeight * 2; - *vbuf = priv->scale_buffer[priv->current_scale_buffer++]; - priv->current_scale_buffer %= OMX_VID_ENC_NUM_SCALING_BUFFERS; -} - -void enc_ControlPicture_common(vid_enc_PrivateType * priv, struct pipe_h264_enc_picture_desc *picture) -{ - struct pipe_h264_enc_rate_control *rate_ctrl = &picture->rate_ctrl; - - /* Get bitrate from port */ - switch (priv->bitrate.eControlRate) { - case OMX_Video_ControlRateVariable: - rate_ctrl->rate_ctrl_method = PIPE_H264_ENC_RATE_CONTROL_METHOD_VARIABLE; - break; - case OMX_Video_ControlRateConstant: - rate_ctrl->rate_ctrl_method = PIPE_H264_ENC_RATE_CONTROL_METHOD_CONSTANT; - break; - case OMX_Video_ControlRateVariableSkipFrames: - rate_ctrl->rate_ctrl_method = PIPE_H264_ENC_RATE_CONTROL_METHOD_VARIABLE_SKIP; - break; - case OMX_Video_ControlRateConstantSkipFrames: - rate_ctrl->rate_ctrl_method = PIPE_H264_ENC_RATE_CONTROL_METHOD_CONSTANT_SKIP; - break; - default: - rate_ctrl->rate_ctrl_method = PIPE_H264_ENC_RATE_CONTROL_METHOD_DISABLE; - break; - } - - rate_ctrl->frame_rate_den = OMX_VID_ENC_CONTROL_FRAME_RATE_DEN_DEFAULT; - rate_ctrl->frame_rate_num = ((priv->frame_rate) >> 16) * rate_ctrl->frame_rate_den; - - if (rate_ctrl->rate_ctrl_method != PIPE_H264_ENC_RATE_CONTROL_METHOD_DISABLE) { - if (priv->bitrate.nTargetBitrate < OMX_VID_ENC_BITRATE_MIN) - rate_ctrl->target_bitrate = OMX_VID_ENC_BITRATE_MIN; - else if (priv->bitrate.nTargetBitrate < OMX_VID_ENC_BITRATE_MAX) - rate_ctrl->target_bitrate = priv->bitrate.nTargetBitrate; - else - rate_ctrl->target_bitrate = OMX_VID_ENC_BITRATE_MAX; - rate_ctrl->peak_bitrate = rate_ctrl->target_bitrate; - if (rate_ctrl->target_bitrate < OMX_VID_ENC_BITRATE_MEDIAN) - rate_ctrl->vbv_buffer_size = MIN2((rate_ctrl->target_bitrate * 2.75), OMX_VID_ENC_BITRATE_MEDIAN); - else - rate_ctrl->vbv_buffer_size = rate_ctrl->target_bitrate; - - if (rate_ctrl->frame_rate_num) { - unsigned long long t = rate_ctrl->target_bitrate; - t *= rate_ctrl->frame_rate_den; - rate_ctrl->target_bits_picture = t / rate_ctrl->frame_rate_num; - } else { - rate_ctrl->target_bits_picture = rate_ctrl->target_bitrate; - } - rate_ctrl->peak_bits_picture_integer = rate_ctrl->target_bits_picture; - rate_ctrl->peak_bits_picture_fraction = 0; - } - - picture->quant_i_frames = priv->quant.nQpI; - picture->quant_p_frames = priv->quant.nQpP; - picture->quant_b_frames = priv->quant.nQpB; - - picture->frame_num = priv->frame_num; - picture->ref_idx_l0 = priv->ref_idx_l0; - picture->ref_idx_l1 = priv->ref_idx_l1; - picture->enable_vui = (picture->rate_ctrl.frame_rate_num != 0); - enc_GetPictureParamPreset(picture); -} - -static void *create_compute_state(struct pipe_context *pipe, - const char *source) -{ - struct tgsi_token tokens[1024]; - struct pipe_compute_state state = {0}; - - if (!tgsi_text_translate(source, tokens, ARRAY_SIZE(tokens))) { - assert(false); - return NULL; - } - - state.ir_type = PIPE_SHADER_IR_TGSI; - state.prog = tokens; - - return pipe->create_compute_state(pipe, &state); -} - -void enc_InitCompute_common(vid_enc_PrivateType *priv) -{ - struct pipe_context *pipe = priv->s_pipe; - struct pipe_screen *screen = pipe->screen; - - /* We need the partial last block support. */ - if (!screen->get_param(screen, PIPE_CAP_COMPUTE_GRID_INFO_LAST_BLOCK)) - return; - - static const char *copy_y = - "COMP\n" - "PROPERTY CS_FIXED_BLOCK_WIDTH 64\n" - "PROPERTY CS_FIXED_BLOCK_HEIGHT 1\n" - "PROPERTY CS_FIXED_BLOCK_DEPTH 1\n" - "DCL SV[0], THREAD_ID\n" - "DCL SV[1], BLOCK_ID\n" - "DCL IMAGE[0], 2D, PIPE_FORMAT_R8_UINT\n" - "DCL IMAGE[1], 2D, PIPE_FORMAT_R8_UINT, WR\n" - "DCL TEMP[0..1]\n" - "IMM[0] UINT32 {64, 0, 0, 0}\n" - - "UMAD TEMP[0].x, SV[1], IMM[0], SV[0]\n" - "MOV TEMP[0].y, SV[1]\n" - "LOAD TEMP[1].x, IMAGE[0], TEMP[0], 2D, PIPE_FORMAT_R8_UINT\n" - "STORE IMAGE[1].x, TEMP[0], TEMP[1], 2D, PIPE_FORMAT_R8_UINT\n" - "END\n"; - - static const char *copy_uv = - "COMP\n" - "PROPERTY CS_FIXED_BLOCK_WIDTH 64\n" - "PROPERTY CS_FIXED_BLOCK_HEIGHT 1\n" - "PROPERTY CS_FIXED_BLOCK_DEPTH 1\n" - "DCL SV[0], THREAD_ID\n" - "DCL SV[1], BLOCK_ID\n" - "DCL IMAGE[0], 2D, PIPE_FORMAT_R8_UINT\n" - "DCL IMAGE[2], 2D, PIPE_FORMAT_R8G8_UINT, WR\n" - "DCL CONST[0][0]\n" /* .x = offset of the UV portion in the y direction */ - "DCL TEMP[0..4]\n" - "IMM[0] UINT32 {64, 0, 2, 1}\n" - /* Destination R8G8 coordinates */ - "UMAD TEMP[0].x, SV[1], IMM[0], SV[0]\n" - "MOV TEMP[0].y, SV[1]\n" - /* Source R8 coordinates of U */ - "UMUL TEMP[1].x, TEMP[0], IMM[0].zzzz\n" - "UADD TEMP[1].y, TEMP[0], CONST[0].xxxx\n" - /* Source R8 coordinates of V */ - "UADD TEMP[2].x, TEMP[1], IMM[0].wwww\n" - "MOV TEMP[2].y, TEMP[1]\n" - - "LOAD TEMP[3].x, IMAGE[0], TEMP[1], 2D, PIPE_FORMAT_R8_UINT\n" - "LOAD TEMP[4].x, IMAGE[0], TEMP[2], 2D, PIPE_FORMAT_R8_UINT\n" - "MOV TEMP[3].y, TEMP[4].xxxx\n" - "STORE IMAGE[2], TEMP[0], TEMP[3], 2D, PIPE_FORMAT_R8G8_UINT\n" - "END\n"; - - priv->copy_y_shader = create_compute_state(pipe, copy_y); - priv->copy_uv_shader = create_compute_state(pipe, copy_uv); -} - -void enc_ReleaseCompute_common(vid_enc_PrivateType *priv) -{ - struct pipe_context *pipe = priv->s_pipe; - - if (priv->copy_y_shader) - pipe->delete_compute_state(pipe, priv->copy_y_shader); - if (priv->copy_uv_shader) - pipe->delete_compute_state(pipe, priv->copy_uv_shader); -} - -OMX_ERRORTYPE enc_LoadImage_common(vid_enc_PrivateType * priv, OMX_VIDEO_PORTDEFINITIONTYPE *def, - OMX_BUFFERHEADERTYPE *buf, - struct pipe_video_buffer *vbuf) -{ - struct pipe_context *pipe = priv->s_pipe; - struct pipe_box box = {}; - struct input_buf_private *inp = buf->pInputPortPrivate; - - if (!inp->resource) { - struct pipe_sampler_view **views; - void *ptr; - - views = vbuf->get_sampler_view_planes(vbuf); - if (!views) - return OMX_ErrorInsufficientResources; - - ptr = buf->pBuffer; - box.width = def->nFrameWidth; - box.height = def->nFrameHeight; - box.depth = 1; - pipe->texture_subdata(pipe, views[0]->texture, 0, - PIPE_TRANSFER_WRITE, &box, - ptr, def->nStride, 0); - ptr = ((uint8_t*)buf->pBuffer) + (def->nStride * box.height); - box.width = def->nFrameWidth / 2; - box.height = def->nFrameHeight / 2; - box.depth = 1; - pipe->texture_subdata(pipe, views[1]->texture, 0, - PIPE_TRANSFER_WRITE, &box, - ptr, def->nStride, 0); - } else { - struct vl_video_buffer *dst_buf = (struct vl_video_buffer *)vbuf; - - pipe_transfer_unmap(pipe, inp->transfer); - - /* inp->resource uses PIPE_FORMAT_I8 and the layout looks like this: - * - * def->nFrameWidth = 4, def->nFrameHeight = 4: - * |----| - * |YYYY| - * |YYYY| - * |YYYY| - * |YYYY| - * |UVUV| - * |UVUV| - * |----| - * - * The copy has 2 steps: - * - Copy Y to dst_buf->resources[0] as R8. - * - Copy UV to dst_buf->resources[1] as R8G8. - */ - if (priv->copy_y_shader && priv->copy_uv_shader) { - /* Compute path */ - /* Set shader images for both copies. */ - struct pipe_image_view image[3] = {0}; - image[0].resource = inp->resource; - image[0].shader_access = image[0].access = PIPE_IMAGE_ACCESS_READ; - image[0].format = PIPE_FORMAT_R8_UINT; - - image[1].resource = dst_buf->resources[0]; - image[1].shader_access = image[1].access = PIPE_IMAGE_ACCESS_WRITE; - image[1].format = PIPE_FORMAT_R8_UINT; - - image[2].resource = dst_buf->resources[1]; - image[2].shader_access = image[1].access = PIPE_IMAGE_ACCESS_WRITE; - image[2].format = PIPE_FORMAT_R8G8_UINT; - - pipe->set_shader_images(pipe, PIPE_SHADER_COMPUTE, 0, 3, image); - - /* Set the constant buffer. */ - uint32_t constants[4] = {def->nFrameHeight}; - struct pipe_constant_buffer cb = {}; - - cb.buffer_size = sizeof(constants); - cb.user_buffer = constants; - pipe->set_constant_buffer(pipe, PIPE_SHADER_COMPUTE, 0, &cb); - - /* Use the optimal block size for the linear image layout. */ - struct pipe_grid_info info = {}; - info.block[0] = 64; - info.block[1] = 1; - info.block[2] = 1; - info.grid[2] = 1; - - /* Copy Y */ - pipe->bind_compute_state(pipe, priv->copy_y_shader); - - info.grid[0] = DIV_ROUND_UP(def->nFrameWidth, 64); - info.grid[1] = def->nFrameHeight; - info.last_block[0] = def->nFrameWidth % 64; - pipe->launch_grid(pipe, &info); - - /* Copy UV */ - pipe->bind_compute_state(pipe, priv->copy_uv_shader); - - info.grid[0] = DIV_ROUND_UP(def->nFrameWidth / 2, 64); - info.grid[1] = def->nFrameHeight / 2; - info.last_block[0] = (def->nFrameWidth / 2) % 64; - pipe->launch_grid(pipe, &info); - - /* Make the result visible to all clients. */ - pipe->memory_barrier(pipe, PIPE_BARRIER_ALL); - - /* Unbind. */ - pipe->set_shader_images(pipe, PIPE_SHADER_COMPUTE, 0, 3, NULL); - pipe->set_constant_buffer(pipe, PIPE_SHADER_COMPUTE, 0, NULL); - pipe->bind_compute_state(pipe, NULL); - } else { - /* Graphics path */ - struct pipe_blit_info blit; - - box.width = def->nFrameWidth; - box.height = def->nFrameHeight; - box.depth = 1; - - /* Copy Y */ - pipe->resource_copy_region(pipe, - dst_buf->resources[0], - 0, 0, 0, 0, inp->resource, 0, &box); - - /* Copy U */ - memset(&blit, 0, sizeof(blit)); - blit.src.resource = inp->resource; - blit.src.format = inp->resource->format; - - blit.src.box.x = -1; - blit.src.box.y = def->nFrameHeight; - blit.src.box.width = def->nFrameWidth; - blit.src.box.height = def->nFrameHeight / 2 ; - blit.src.box.depth = 1; - - blit.dst.resource = dst_buf->resources[1]; - blit.dst.format = blit.dst.resource->format; - - blit.dst.box.width = def->nFrameWidth / 2; - blit.dst.box.height = def->nFrameHeight / 2; - blit.dst.box.depth = 1; - blit.filter = PIPE_TEX_FILTER_NEAREST; - - blit.mask = PIPE_MASK_R; - pipe->blit(pipe, &blit); - - /* Copy V */ - blit.src.box.x = 0; - blit.mask = PIPE_MASK_G; - pipe->blit(pipe, &blit); - } - - pipe->flush(pipe, NULL, 0); - - box.width = inp->resource->width0; - box.height = inp->resource->height0; - box.depth = inp->resource->depth0; - buf->pBuffer = pipe->transfer_map(pipe, inp->resource, 0, - PIPE_TRANSFER_WRITE, &box, - &inp->transfer); - } - - return OMX_ErrorNone; -} diff --git a/src/gallium/state_trackers/omx/vid_enc_common.h b/src/gallium/state_trackers/omx/vid_enc_common.h deleted file mode 100644 index 8c8830dfcc6..00000000000 --- a/src/gallium/state_trackers/omx/vid_enc_common.h +++ /dev/null @@ -1,179 +0,0 @@ -/************************************************************************** - * - * Copyright 2013 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#ifndef VID_ENC_COMMON_H -#define VID_ENC_COMMON_H - -#include "util/list.h" -#include "util/u_memory.h" - -#include "vl/vl_defines.h" -#include "vl/vl_compositor.h" -#include "vl/vl_winsys.h" - -#include - -#define OMX_VID_ENC_BITRATE_MIN 64000 -#define OMX_VID_ENC_BITRATE_MEDIAN 2000000 -#define OMX_VID_ENC_BITRATE_MAX 240000000 -#define OMX_VID_ENC_CONTROL_FRAME_RATE_DEN_DEFAULT 1001 -#define OMX_VID_ENC_QUANT_I_FRAMES_DEFAULT 0x1c -#define OMX_VID_ENC_QUANT_P_FRAMES_DEFAULT 0x1c -#define OMX_VID_ENC_QUANT_B_FRAMES_DEFAULT 0x1c -#define OMX_VID_ENC_SCALING_WIDTH_DEFAULT 0xffffffff -#define OMX_VID_ENC_SCALING_HEIGHT_DEFAULT 0xffffffff -#define OMX_VID_ENC_IDR_PERIOD_DEFAULT 1000 -#define OMX_VID_ENC_P_PERIOD_DEFAULT 3 - -#define OMX_VID_ENC_NUM_SCALING_BUFFERS 4 - -struct encode_task { - struct list_head list; - - struct pipe_video_buffer *buf; - unsigned pic_order_cnt; - struct pipe_resource *bitstream; - void *feedback; -}; - -struct input_buf_private { - struct list_head tasks; - - struct pipe_resource *resource; - struct pipe_transfer *transfer; -}; - -struct output_buf_private { - struct pipe_resource *bitstream; - struct pipe_transfer *transfer; -}; - -#if ENABLE_ST_OMX_BELLAGIO - -#include - -DERIVEDCLASS(vid_enc_PrivateType, omx_base_filter_PrivateType) -#define vid_enc_PrivateType_FIELDS omx_base_filter_PrivateType_FIELDS \ - struct vl_screen *screen; \ - struct pipe_context *s_pipe; \ - struct pipe_context *t_pipe; \ - struct pipe_video_codec *codec; \ - struct list_head free_tasks; \ - struct list_head used_tasks; \ - struct list_head b_frames; \ - struct list_head stacked_tasks; \ - OMX_U32 frame_rate; \ - OMX_U32 frame_num; \ - OMX_U32 pic_order_cnt; \ - OMX_U32 ref_idx_l0, ref_idx_l1; \ - OMX_BOOL restricted_b_frames; \ - OMX_VIDEO_PARAM_BITRATETYPE bitrate; \ - OMX_VIDEO_PARAM_QUANTIZATIONTYPE quant; \ - OMX_VIDEO_PARAM_PROFILELEVELTYPE profile_level; \ - OMX_CONFIG_INTRAREFRESHVOPTYPE force_pic_type; \ - struct vl_compositor compositor; \ - struct vl_compositor_state cstate; \ - struct pipe_video_buffer *scale_buffer[OMX_VID_ENC_NUM_SCALING_BUFFERS]; \ - OMX_CONFIG_SCALEFACTORTYPE scale; \ - OMX_U32 current_scale_buffer; \ - OMX_U32 stacked_frames_num; \ - void *copy_y_shader; \ - void *copy_uv_shader; -ENDCLASS(vid_enc_PrivateType) - -#else - -#include -#include - -typedef struct h264e_prc_class h264e_prc_class_t; -struct h264e_prc_class -{ - /* Class */ - const tiz_prc_class_t _; - /* NOTE: Class methods might be added in the future */ -}; - -typedef struct h264e_prc vid_enc_PrivateType; -struct h264e_prc -{ - /* Object */ - const tiz_prc_t _; - OMX_BUFFERHEADERTYPE *p_inhdr_; - OMX_BUFFERHEADERTYPE *p_outhdr_; - OMX_PARAM_PORTDEFINITIONTYPE in_port_def_; - OMX_PARAM_PORTDEFINITIONTYPE out_port_def_; - struct vl_screen *screen; - struct pipe_context *s_pipe; - struct pipe_context *t_pipe; - struct pipe_video_codec *codec; - struct list_head free_tasks; - struct list_head used_tasks; - struct list_head b_frames; - struct list_head stacked_tasks; - OMX_U32 frame_rate; - OMX_U32 frame_num; - OMX_U32 pic_order_cnt; - OMX_U32 ref_idx_l0, ref_idx_l1; - OMX_BOOL restricted_b_frames; - OMX_VIDEO_PARAM_BITRATETYPE bitrate; - OMX_VIDEO_PARAM_QUANTIZATIONTYPE quant; - OMX_VIDEO_PARAM_PROFILELEVELTYPE profile_level; - OMX_CONFIG_INTRAREFRESHVOPTYPE force_pic_type; - struct vl_compositor compositor; - struct vl_compositor_state cstate; - struct pipe_video_buffer *scale_buffer[OMX_VID_ENC_NUM_SCALING_BUFFERS]; - OMX_CONFIG_SCALEFACTORTYPE scale; - OMX_U32 current_scale_buffer; - OMX_U32 stacked_frames_num; - bool eos_; - bool in_port_disabled_; - bool out_port_disabled_; - void *copy_y_shader; - void *copy_uv_shader; -}; -#endif - -void enc_ReleaseTasks(struct list_head *head); -void enc_MoveTasks(struct list_head *from, struct list_head *to); -enum pipe_video_profile enc_TranslateOMXProfileToPipe(unsigned omx_profile); -unsigned enc_TranslateOMXLevelToPipe(unsigned omx_level); -void vid_enc_BufferEncoded_common(vid_enc_PrivateType * priv, OMX_BUFFERHEADERTYPE* input, - OMX_BUFFERHEADERTYPE* output); -struct encode_task *enc_NeedTask_common(vid_enc_PrivateType * priv, - OMX_VIDEO_PORTDEFINITIONTYPE *def); -void enc_ScaleInput_common(vid_enc_PrivateType * priv, - OMX_VIDEO_PORTDEFINITIONTYPE *def, - struct pipe_video_buffer **vbuf, unsigned *size); -void enc_ControlPicture_common(vid_enc_PrivateType * priv, - struct pipe_h264_enc_picture_desc *picture); -void enc_InitCompute_common(vid_enc_PrivateType *priv); -void enc_ReleaseCompute_common(vid_enc_PrivateType *priv); -OMX_ERRORTYPE enc_LoadImage_common(vid_enc_PrivateType * priv, OMX_VIDEO_PORTDEFINITIONTYPE *def, - OMX_BUFFERHEADERTYPE *buf, - struct pipe_video_buffer *vbuf); -#endif diff --git a/src/gallium/state_trackers/omx/vid_omx_common.c b/src/gallium/state_trackers/omx/vid_omx_common.c deleted file mode 100644 index 63afa898ba1..00000000000 --- a/src/gallium/state_trackers/omx/vid_omx_common.c +++ /dev/null @@ -1,111 +0,0 @@ -/************************************************************************** - * - * Copyright 2013 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include -#include -#include - -#if defined(HAVE_X11_PLATFORM) -#include -#else -#define XOpenDisplay(x) NULL -#define XCloseDisplay(x) -#define Display void -#endif - -#include "os/os_thread.h" -#include "util/u_memory.h" -#include "loader/loader.h" - -#include "vid_omx_common.h" - -static mtx_t omx_lock = _MTX_INITIALIZER_NP; -static Display *omx_display = NULL; -static struct vl_screen *omx_screen = NULL; -static unsigned omx_usecount = 0; -static const char *omx_render_node = NULL; -static int drm_fd; - -struct vl_screen *omx_get_screen(void) -{ - static bool first_time = true; - mtx_lock(&omx_lock); - - if (!omx_screen) { - if (first_time) { - omx_render_node = debug_get_option("OMX_RENDER_NODE", NULL); - first_time = false; - } - if (omx_render_node) { - drm_fd = loader_open_device(omx_render_node); - if (drm_fd < 0) - goto error; - - omx_screen = vl_drm_screen_create(drm_fd); - if (!omx_screen) { - close(drm_fd); - goto error; - } - } else { - omx_display = XOpenDisplay(NULL); - if (!omx_display) - goto error; - - omx_screen = vl_dri3_screen_create(omx_display, 0); - if (!omx_screen) - omx_screen = vl_dri2_screen_create(omx_display, 0); - if (!omx_screen) { - XCloseDisplay(omx_display); - goto error; - } - } - } - - ++omx_usecount; - - mtx_unlock(&omx_lock); - return omx_screen; - -error: - mtx_unlock(&omx_lock); - return NULL; -} - -void omx_put_screen(void) -{ - mtx_lock(&omx_lock); - if ((--omx_usecount) == 0) { - omx_screen->destroy(omx_screen); - omx_screen = NULL; - - if (omx_render_node) - close(drm_fd); - else - XCloseDisplay(omx_display); - } - mtx_unlock(&omx_lock); -} diff --git a/src/gallium/state_trackers/omx/vid_omx_common.h b/src/gallium/state_trackers/omx/vid_omx_common.h deleted file mode 100644 index e27013d1746..00000000000 --- a/src/gallium/state_trackers/omx/vid_omx_common.h +++ /dev/null @@ -1,36 +0,0 @@ -/************************************************************************** - * - * Copyright 2013 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#ifndef VID_OMX_COMMON_H -#define VID_OMX_COMMON_H - -#include "vl/vl_winsys.h" - -struct vl_screen *omx_get_screen(void); -void omx_put_screen(void); - -#endif diff --git a/src/gallium/state_trackers/osmesa/meson.build b/src/gallium/state_trackers/osmesa/meson.build deleted file mode 100644 index e5848fd9934..00000000000 --- a/src/gallium/state_trackers/osmesa/meson.build +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright © 2017-2018 Intel Corporation - -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: - -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. - -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -osmesa_st_c_args = [] -if with_platform_windows - osmesa_st_c_args += ['-DBUILD_GL32', '-DWIN32_LEAN_AND_MEAN'] - if not with_shared_glapi - osmesa_st_c_args += ['-D_GLAPI_NO_EXPORTS'] - endif -endif - -libosmesa_st = static_library( - 'osmesa_st', - 'osmesa.c', - c_args : osmesa_st_c_args, - include_directories : [ - inc_include, inc_src, inc_gallium, inc_gallium_aux, inc_mapi, inc_mesa, - ], -) diff --git a/src/gallium/state_trackers/osmesa/osmesa.c b/src/gallium/state_trackers/osmesa/osmesa.c deleted file mode 100644 index b1890a33c46..00000000000 --- a/src/gallium/state_trackers/osmesa/osmesa.c +++ /dev/null @@ -1,1047 +0,0 @@ -/* - * Copyright (c) 2013 Brian Paul All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - - -/* - * Off-Screen rendering into client memory. - * State tracker for gallium (for softpipe and llvmpipe) - * - * Notes: - * - * If Gallium is built with LLVM support we use the llvmpipe driver. - * Otherwise we use softpipe. The GALLIUM_DRIVER environment variable - * may be set to "softpipe" or "llvmpipe" to override. - * - * With softpipe we could render directly into the user's buffer by using a - * display target resource. However, softpipe doesn't support "upside-down" - * rendering which would be needed for the OSMESA_Y_UP=TRUE case. - * - * With llvmpipe we could only render directly into the user's buffer when its - * width and height is a multiple of the tile size (64 pixels). - * - * Because of these constraints we always render into ordinary resources then - * copy the results to the user's buffer in the flush_front() function which - * is called when the app calls glFlush/Finish. - * - * In general, the OSMesa interface is pretty ugly and not a good match - * for Gallium. But we're interested in doing the best we can to preserve - * application portability. With a little work we could come up with a - * much nicer, new off-screen Gallium interface... - */ - - -#include -#include -#include "GL/osmesa.h" - -#include "glapi/glapi.h" /* for OSMesaGetProcAddress below */ - -#include "pipe/p_context.h" -#include "pipe/p_screen.h" -#include "pipe/p_state.h" - -#include "util/u_atomic.h" -#include "util/u_box.h" -#include "util/u_debug.h" -#include "util/format/u_format.h" -#include "util/u_inlines.h" -#include "util/u_memory.h" - -#include "postprocess/filters.h" -#include "postprocess/postprocess.h" - -#include "state_tracker/st_api.h" -#include "state_tracker/st_gl_api.h" - - - -extern struct pipe_screen * -osmesa_create_screen(void); - - - -struct osmesa_buffer -{ - struct st_framebuffer_iface *stfb; - struct st_visual visual; - unsigned width, height; - - struct pipe_resource *textures[ST_ATTACHMENT_COUNT]; - - void *map; - - struct osmesa_buffer *next; /**< next in linked list */ -}; - - -struct osmesa_context -{ - struct st_context_iface *stctx; - - boolean ever_used; /*< Has this context ever been current? */ - - struct osmesa_buffer *current_buffer; - - enum pipe_format depth_stencil_format, accum_format; - - GLenum format; /*< User-specified context format */ - GLenum type; /*< Buffer's data type */ - GLint user_row_length; /*< user-specified number of pixels per row */ - GLboolean y_up; /*< TRUE -> Y increases upward */ - /*< FALSE -> Y increases downward */ - - /** Which postprocessing filters are enabled. */ - unsigned pp_enabled[PP_FILTERS]; - struct pp_queue_t *pp; -}; - - -/** - * Linked list of all osmesa_buffers. - * We can re-use an osmesa_buffer from one OSMesaMakeCurrent() call to - * the next unless the color/depth/stencil/accum formats change. - * We have to do this to be compatible with the original OSMesa implementation - * because some apps call OSMesaMakeCurrent() several times during rendering - * a frame. - */ -static struct osmesa_buffer *BufferList = NULL; - - -/** - * Called from the ST manager. - */ -static int -osmesa_st_get_param(struct st_manager *smapi, enum st_manager_param param) -{ - /* no-op */ - return 0; -} - - -/** - * Create/return singleton st_api object. - */ -static struct st_api * -get_st_api(void) -{ - static struct st_api *stapi = NULL; - if (!stapi) { - stapi = st_gl_api_create(); - } - return stapi; -} - -static struct st_manager *stmgr = NULL; - -static void -create_st_manager(void) -{ - stmgr = CALLOC_STRUCT(st_manager); - if (stmgr) { - stmgr->screen = osmesa_create_screen(); - stmgr->get_param = osmesa_st_get_param; - stmgr->get_egl_image = NULL; - } -} - -/** - * Create/return a singleton st_manager object. - */ -static struct st_manager * -get_st_manager(void) -{ - static once_flag create_once_flag = ONCE_FLAG_INIT; - - call_once(&create_once_flag, create_st_manager); - - return stmgr; -} - - -/** - * Given an OSMESA_x format and a GL_y type, return the best - * matching PIPE_FORMAT_z. - * Note that we can't exactly match all user format/type combinations - * with gallium formats. If we find this to be a problem, we can - * implement more elaborate format/type conversion in the flush_front() - * function. - */ -static enum pipe_format -osmesa_choose_format(GLenum format, GLenum type) -{ - switch (format) { - case OSMESA_RGBA: - if (type == GL_UNSIGNED_BYTE) { -#if UTIL_ARCH_LITTLE_ENDIAN - return PIPE_FORMAT_R8G8B8A8_UNORM; -#else - return PIPE_FORMAT_A8B8G8R8_UNORM; -#endif - } - else if (type == GL_UNSIGNED_SHORT) { - return PIPE_FORMAT_R16G16B16A16_UNORM; - } - else if (type == GL_FLOAT) { - return PIPE_FORMAT_R32G32B32A32_FLOAT; - } - else { - return PIPE_FORMAT_NONE; - } - break; - case OSMESA_BGRA: - if (type == GL_UNSIGNED_BYTE) { -#if UTIL_ARCH_LITTLE_ENDIAN - return PIPE_FORMAT_B8G8R8A8_UNORM; -#else - return PIPE_FORMAT_A8R8G8B8_UNORM; -#endif - } - else if (type == GL_UNSIGNED_SHORT) { - return PIPE_FORMAT_R16G16B16A16_UNORM; - } - else if (type == GL_FLOAT) { - return PIPE_FORMAT_R32G32B32A32_FLOAT; - } - else { - return PIPE_FORMAT_NONE; - } - break; - case OSMESA_ARGB: - if (type == GL_UNSIGNED_BYTE) { -#if UTIL_ARCH_LITTLE_ENDIAN - return PIPE_FORMAT_A8R8G8B8_UNORM; -#else - return PIPE_FORMAT_B8G8R8A8_UNORM; -#endif - } - else if (type == GL_UNSIGNED_SHORT) { - return PIPE_FORMAT_R16G16B16A16_UNORM; - } - else if (type == GL_FLOAT) { - return PIPE_FORMAT_R32G32B32A32_FLOAT; - } - else { - return PIPE_FORMAT_NONE; - } - break; - case OSMESA_RGB: - if (type == GL_UNSIGNED_BYTE) { - return PIPE_FORMAT_R8G8B8_UNORM; - } - else if (type == GL_UNSIGNED_SHORT) { - return PIPE_FORMAT_R16G16B16_UNORM; - } - else if (type == GL_FLOAT) { - return PIPE_FORMAT_R32G32B32_FLOAT; - } - else { - return PIPE_FORMAT_NONE; - } - break; - case OSMESA_BGR: - /* No gallium format for this one */ - return PIPE_FORMAT_NONE; - case OSMESA_RGB_565: - if (type != GL_UNSIGNED_SHORT_5_6_5) - return PIPE_FORMAT_NONE; - return PIPE_FORMAT_B5G6R5_UNORM; - default: - ; /* fall-through */ - } - return PIPE_FORMAT_NONE; -} - - -/** - * Initialize an st_visual object. - */ -static void -osmesa_init_st_visual(struct st_visual *vis, - enum pipe_format color_format, - enum pipe_format ds_format, - enum pipe_format accum_format) -{ - vis->buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK; - - if (ds_format != PIPE_FORMAT_NONE) - vis->buffer_mask |= ST_ATTACHMENT_DEPTH_STENCIL_MASK; - if (accum_format != PIPE_FORMAT_NONE) - vis->buffer_mask |= ST_ATTACHMENT_ACCUM; - - vis->color_format = color_format; - vis->depth_stencil_format = ds_format; - vis->accum_format = accum_format; - vis->samples = 1; - vis->render_buffer = ST_ATTACHMENT_FRONT_LEFT; -} - - -/** - * Return the osmesa_buffer that corresponds to an st_framebuffer_iface. - */ -static inline struct osmesa_buffer * -stfbi_to_osbuffer(struct st_framebuffer_iface *stfbi) -{ - return (struct osmesa_buffer *) stfbi->st_manager_private; -} - - -/** - * Called via glFlush/glFinish. This is where we copy the contents - * of the driver's color buffer into the user-specified buffer. - */ -static bool -osmesa_st_framebuffer_flush_front(struct st_context_iface *stctx, - struct st_framebuffer_iface *stfbi, - enum st_attachment_type statt) -{ - OSMesaContext osmesa = OSMesaGetCurrentContext(); - struct osmesa_buffer *osbuffer = stfbi_to_osbuffer(stfbi); - struct pipe_context *pipe = stctx->pipe; - struct pipe_resource *res = osbuffer->textures[statt]; - struct pipe_transfer *transfer = NULL; - struct pipe_box box; - void *map; - ubyte *src, *dst; - unsigned y, bytes, bpp; - int dst_stride; - - if (osmesa->pp) { - struct pipe_resource *zsbuf = NULL; - unsigned i; - - /* Find the z/stencil buffer if there is one */ - for (i = 0; i < ARRAY_SIZE(osbuffer->textures); i++) { - struct pipe_resource *res = osbuffer->textures[i]; - if (res) { - const struct util_format_description *desc = - util_format_description(res->format); - - if (util_format_has_depth(desc)) { - zsbuf = res; - break; - } - } - } - - /* run the postprocess stage(s) */ - pp_run(osmesa->pp, res, res, zsbuf); - } - - u_box_2d(0, 0, res->width0, res->height0, &box); - - map = pipe->transfer_map(pipe, res, 0, PIPE_TRANSFER_READ, &box, - &transfer); - - /* - * Copy the color buffer from the resource to the user's buffer. - */ - bpp = util_format_get_blocksize(osbuffer->visual.color_format); - src = map; - dst = osbuffer->map; - if (osmesa->user_row_length) - dst_stride = bpp * osmesa->user_row_length; - else - dst_stride = bpp * osbuffer->width; - bytes = bpp * res->width0; - - if (osmesa->y_up) { - /* need to flip image upside down */ - dst = dst + (res->height0 - 1) * dst_stride; - dst_stride = -dst_stride; - } - - for (y = 0; y < res->height0; y++) { - memcpy(dst, src, bytes); - dst += dst_stride; - src += transfer->stride; - } - - pipe->transfer_unmap(pipe, transfer); - - return true; -} - - -/** - * Called by the st manager to validate the framebuffer (allocate - * its resources). - */ -static bool -osmesa_st_framebuffer_validate(struct st_context_iface *stctx, - struct st_framebuffer_iface *stfbi, - const enum st_attachment_type *statts, - unsigned count, - struct pipe_resource **out) -{ - struct pipe_screen *screen = get_st_manager()->screen; - enum st_attachment_type i; - struct osmesa_buffer *osbuffer = stfbi_to_osbuffer(stfbi); - struct pipe_resource templat; - - memset(&templat, 0, sizeof(templat)); - templat.target = PIPE_TEXTURE_RECT; - templat.format = 0; /* setup below */ - templat.last_level = 0; - templat.width0 = osbuffer->width; - templat.height0 = osbuffer->height; - templat.depth0 = 1; - templat.array_size = 1; - templat.usage = PIPE_USAGE_DEFAULT; - templat.bind = 0; /* setup below */ - templat.flags = 0; - - for (i = 0; i < count; i++) { - enum pipe_format format = PIPE_FORMAT_NONE; - unsigned bind = 0; - - /* - * At this time, we really only need to handle the front-left color - * attachment, since that's all we specified for the visual in - * osmesa_init_st_visual(). - */ - if (statts[i] == ST_ATTACHMENT_FRONT_LEFT) { - format = osbuffer->visual.color_format; - bind = PIPE_BIND_RENDER_TARGET; - } - else if (statts[i] == ST_ATTACHMENT_DEPTH_STENCIL) { - format = osbuffer->visual.depth_stencil_format; - bind = PIPE_BIND_DEPTH_STENCIL; - } - else if (statts[i] == ST_ATTACHMENT_ACCUM) { - format = osbuffer->visual.accum_format; - bind = PIPE_BIND_RENDER_TARGET; - } - else { - debug_warning("Unexpected attachment type in " - "osmesa_st_framebuffer_validate()"); - } - - templat.format = format; - templat.bind = bind; - pipe_resource_reference(&out[i], NULL); - out[i] = osbuffer->textures[statts[i]] = - screen->resource_create(screen, &templat); - } - - return true; -} - -static uint32_t osmesa_fb_ID = 0; - -static struct st_framebuffer_iface * -osmesa_create_st_framebuffer(void) -{ - struct st_framebuffer_iface *stfbi = CALLOC_STRUCT(st_framebuffer_iface); - if (stfbi) { - stfbi->flush_front = osmesa_st_framebuffer_flush_front; - stfbi->validate = osmesa_st_framebuffer_validate; - p_atomic_set(&stfbi->stamp, 1); - stfbi->ID = p_atomic_inc_return(&osmesa_fb_ID); - stfbi->state_manager = get_st_manager(); - } - return stfbi; -} - - -/** - * Create new buffer and add to linked list. - */ -static struct osmesa_buffer * -osmesa_create_buffer(enum pipe_format color_format, - enum pipe_format ds_format, - enum pipe_format accum_format) -{ - struct osmesa_buffer *osbuffer = CALLOC_STRUCT(osmesa_buffer); - if (osbuffer) { - osbuffer->stfb = osmesa_create_st_framebuffer(); - - osbuffer->stfb->st_manager_private = osbuffer; - osbuffer->stfb->visual = &osbuffer->visual; - - osmesa_init_st_visual(&osbuffer->visual, color_format, - ds_format, accum_format); - - /* insert into linked list */ - osbuffer->next = BufferList; - BufferList = osbuffer; - } - - return osbuffer; -} - - -/** - * Search linked list for a buffer with matching pixel formats and size. - */ -static struct osmesa_buffer * -osmesa_find_buffer(enum pipe_format color_format, - enum pipe_format ds_format, - enum pipe_format accum_format, - GLsizei width, GLsizei height) -{ - struct osmesa_buffer *b; - - /* Check if we already have a suitable buffer for the given formats */ - for (b = BufferList; b; b = b->next) { - if (b->visual.color_format == color_format && - b->visual.depth_stencil_format == ds_format && - b->visual.accum_format == accum_format && - b->width == width && - b->height == height) { - return b; - } - } - return NULL; -} - - -static void -osmesa_destroy_buffer(struct osmesa_buffer *osbuffer) -{ - struct st_api *stapi = get_st_api(); - - /* - * Notify the state manager that the associated framebuffer interface - * is no longer valid. - */ - stapi->destroy_drawable(stapi, osbuffer->stfb); - - FREE(osbuffer->stfb); - FREE(osbuffer); -} - - - -/**********************************************************************/ -/***** Public Functions *****/ -/**********************************************************************/ - - -/** - * Create an Off-Screen Mesa rendering context. The only attribute needed is - * an RGBA vs Color-Index mode flag. - * - * Input: format - Must be GL_RGBA - * sharelist - specifies another OSMesaContext with which to share - * display lists. NULL indicates no sharing. - * Return: an OSMesaContext or 0 if error - */ -GLAPI OSMesaContext GLAPIENTRY -OSMesaCreateContext(GLenum format, OSMesaContext sharelist) -{ - return OSMesaCreateContextExt(format, 24, 8, 0, sharelist); -} - - -/** - * New in Mesa 3.5 - * - * Create context and specify size of ancillary buffers. - */ -GLAPI OSMesaContext GLAPIENTRY -OSMesaCreateContextExt(GLenum format, GLint depthBits, GLint stencilBits, - GLint accumBits, OSMesaContext sharelist) -{ - int attribs[100], n = 0; - - attribs[n++] = OSMESA_FORMAT; - attribs[n++] = format; - attribs[n++] = OSMESA_DEPTH_BITS; - attribs[n++] = depthBits; - attribs[n++] = OSMESA_STENCIL_BITS; - attribs[n++] = stencilBits; - attribs[n++] = OSMESA_ACCUM_BITS; - attribs[n++] = accumBits; - attribs[n++] = 0; - - return OSMesaCreateContextAttribs(attribs, sharelist); -} - - -/** - * New in Mesa 11.2 - * - * Create context with attribute list. - */ -GLAPI OSMesaContext GLAPIENTRY -OSMesaCreateContextAttribs(const int *attribList, OSMesaContext sharelist) -{ - OSMesaContext osmesa; - struct st_context_iface *st_shared; - enum st_context_error st_error = 0; - struct st_context_attribs attribs; - struct st_api *stapi = get_st_api(); - GLenum format = GL_RGBA; - int depthBits = 0, stencilBits = 0, accumBits = 0; - int profile = OSMESA_COMPAT_PROFILE, version_major = 1, version_minor = 0; - int i; - - if (sharelist) { - st_shared = sharelist->stctx; - } - else { - st_shared = NULL; - } - - for (i = 0; attribList[i]; i += 2) { - switch (attribList[i]) { - case OSMESA_FORMAT: - format = attribList[i+1]; - switch (format) { - case OSMESA_COLOR_INDEX: - case OSMESA_RGBA: - case OSMESA_BGRA: - case OSMESA_ARGB: - case OSMESA_RGB: - case OSMESA_BGR: - case OSMESA_RGB_565: - /* legal */ - break; - default: - return NULL; - } - break; - case OSMESA_DEPTH_BITS: - depthBits = attribList[i+1]; - if (depthBits < 0) - return NULL; - break; - case OSMESA_STENCIL_BITS: - stencilBits = attribList[i+1]; - if (stencilBits < 0) - return NULL; - break; - case OSMESA_ACCUM_BITS: - accumBits = attribList[i+1]; - if (accumBits < 0) - return NULL; - break; - case OSMESA_PROFILE: - profile = attribList[i+1]; - if (profile != OSMESA_CORE_PROFILE && - profile != OSMESA_COMPAT_PROFILE) - return NULL; - break; - case OSMESA_CONTEXT_MAJOR_VERSION: - version_major = attribList[i+1]; - if (version_major < 1) - return NULL; - break; - case OSMESA_CONTEXT_MINOR_VERSION: - version_minor = attribList[i+1]; - if (version_minor < 0) - return NULL; - break; - case 0: - /* end of list */ - break; - default: - fprintf(stderr, "Bad attribute in OSMesaCreateContextAttribs()\n"); - return NULL; - } - } - - osmesa = (OSMesaContext) CALLOC_STRUCT(osmesa_context); - if (!osmesa) - return NULL; - - /* Choose depth/stencil/accum buffer formats */ - if (accumBits > 0) { - osmesa->accum_format = PIPE_FORMAT_R16G16B16A16_SNORM; - } - if (depthBits > 0 && stencilBits > 0) { - osmesa->depth_stencil_format = PIPE_FORMAT_Z24_UNORM_S8_UINT; - } - else if (stencilBits > 0) { - osmesa->depth_stencil_format = PIPE_FORMAT_S8_UINT; - } - else if (depthBits >= 24) { - osmesa->depth_stencil_format = PIPE_FORMAT_Z24X8_UNORM; - } - else if (depthBits >= 16) { - osmesa->depth_stencil_format = PIPE_FORMAT_Z16_UNORM; - } - - /* - * Create the rendering context - */ - memset(&attribs, 0, sizeof(attribs)); - attribs.profile = (profile == OSMESA_CORE_PROFILE) - ? ST_PROFILE_OPENGL_CORE : ST_PROFILE_DEFAULT; - attribs.major = version_major; - attribs.minor = version_minor; - attribs.flags = 0; /* ST_CONTEXT_FLAG_x */ - attribs.options.force_glsl_extensions_warn = FALSE; - attribs.options.disable_blend_func_extended = FALSE; - attribs.options.disable_glsl_line_continuations = FALSE; - attribs.options.force_glsl_version = 0; - - osmesa_init_st_visual(&attribs.visual, - PIPE_FORMAT_NONE, - osmesa->depth_stencil_format, - osmesa->accum_format); - - osmesa->stctx = stapi->create_context(stapi, get_st_manager(), - &attribs, &st_error, st_shared); - if (!osmesa->stctx) { - FREE(osmesa); - return NULL; - } - - osmesa->stctx->st_manager_private = osmesa; - - osmesa->format = format; - osmesa->user_row_length = 0; - osmesa->y_up = GL_TRUE; - - return osmesa; -} - - - -/** - * Destroy an Off-Screen Mesa rendering context. - * - * \param osmesa the context to destroy - */ -GLAPI void GLAPIENTRY -OSMesaDestroyContext(OSMesaContext osmesa) -{ - if (osmesa) { - pp_free(osmesa->pp); - osmesa->stctx->destroy(osmesa->stctx); - FREE(osmesa); - } -} - - -/** - * Bind an OSMesaContext to an image buffer. The image buffer is just a - * block of memory which the client provides. Its size must be at least - * as large as width*height*pixelSize. Its address should be a multiple - * of 4 if using RGBA mode. - * - * By default, image data is stored in the order of glDrawPixels: row-major - * order with the lower-left image pixel stored in the first array position - * (ie. bottom-to-top). - * - * If the context's viewport hasn't been initialized yet, it will now be - * initialized to (0,0,width,height). - * - * Input: osmesa - the rendering context - * buffer - the image buffer memory - * type - data type for pixel components - * GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT - * or GL_FLOAT. - * width, height - size of image buffer in pixels, at least 1 - * Return: GL_TRUE if success, GL_FALSE if error because of invalid osmesa, - * invalid type, invalid size, etc. - */ -GLAPI GLboolean GLAPIENTRY -OSMesaMakeCurrent(OSMesaContext osmesa, void *buffer, GLenum type, - GLsizei width, GLsizei height) -{ - struct st_api *stapi = get_st_api(); - struct osmesa_buffer *osbuffer; - enum pipe_format color_format; - - if (!osmesa && !buffer) { - stapi->make_current(stapi, NULL, NULL, NULL); - return GL_TRUE; - } - - if (!osmesa || !buffer || width < 1 || height < 1) { - return GL_FALSE; - } - - color_format = osmesa_choose_format(osmesa->format, type); - if (color_format == PIPE_FORMAT_NONE) { - fprintf(stderr, "OSMesaMakeCurrent(unsupported format/type)\n"); - return GL_FALSE; - } - - /* See if we already have a buffer that uses these pixel formats */ - osbuffer = osmesa_find_buffer(color_format, - osmesa->depth_stencil_format, - osmesa->accum_format, width, height); - if (!osbuffer) { - /* Existing buffer found, create new buffer */ - osbuffer = osmesa_create_buffer(color_format, - osmesa->depth_stencil_format, - osmesa->accum_format); - } - - osbuffer->width = width; - osbuffer->height = height; - osbuffer->map = buffer; - - /* XXX unused for now */ - (void) osmesa_destroy_buffer; - - osmesa->current_buffer = osbuffer; - osmesa->type = type; - - stapi->make_current(stapi, osmesa->stctx, osbuffer->stfb, osbuffer->stfb); - - if (!osmesa->ever_used) { - /* one-time init, just postprocessing for now */ - boolean any_pp_enabled = FALSE; - unsigned i; - - for (i = 0; i < ARRAY_SIZE(osmesa->pp_enabled); i++) { - if (osmesa->pp_enabled[i]) { - any_pp_enabled = TRUE; - break; - } - } - - if (any_pp_enabled) { - osmesa->pp = pp_init(osmesa->stctx->pipe, - osmesa->pp_enabled, - osmesa->stctx->cso_context); - - pp_init_fbos(osmesa->pp, width, height); - } - - osmesa->ever_used = TRUE; - } - - return GL_TRUE; -} - - - -GLAPI OSMesaContext GLAPIENTRY -OSMesaGetCurrentContext(void) -{ - struct st_api *stapi = get_st_api(); - struct st_context_iface *st = stapi->get_current(stapi); - return st ? (OSMesaContext) st->st_manager_private : NULL; -} - - - -GLAPI void GLAPIENTRY -OSMesaPixelStore(GLint pname, GLint value) -{ - OSMesaContext osmesa = OSMesaGetCurrentContext(); - - switch (pname) { - case OSMESA_ROW_LENGTH: - osmesa->user_row_length = value; - break; - case OSMESA_Y_UP: - osmesa->y_up = value ? GL_TRUE : GL_FALSE; - break; - default: - fprintf(stderr, "Invalid pname in OSMesaPixelStore()\n"); - return; - } -} - - -GLAPI void GLAPIENTRY -OSMesaGetIntegerv(GLint pname, GLint *value) -{ - OSMesaContext osmesa = OSMesaGetCurrentContext(); - struct osmesa_buffer *osbuffer = osmesa ? osmesa->current_buffer : NULL; - - switch (pname) { - case OSMESA_WIDTH: - *value = osbuffer ? osbuffer->width : 0; - return; - case OSMESA_HEIGHT: - *value = osbuffer ? osbuffer->height : 0; - return; - case OSMESA_FORMAT: - *value = osmesa->format; - return; - case OSMESA_TYPE: - /* current color buffer's data type */ - *value = osmesa->type; - return; - case OSMESA_ROW_LENGTH: - *value = osmesa->user_row_length; - return; - case OSMESA_Y_UP: - *value = osmesa->y_up; - return; - case OSMESA_MAX_WIDTH: - /* fall-through */ - case OSMESA_MAX_HEIGHT: - { - struct pipe_screen *screen = get_st_manager()->screen; - *value = screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_2D_SIZE); - } - return; - default: - fprintf(stderr, "Invalid pname in OSMesaGetIntegerv()\n"); - return; - } -} - - -/** - * Return information about the depth buffer associated with an OSMesa context. - * Input: c - the OSMesa context - * Output: width, height - size of buffer in pixels - * bytesPerValue - bytes per depth value (2 or 4) - * buffer - pointer to depth buffer values - * Return: GL_TRUE or GL_FALSE to indicate success or failure. - */ -GLAPI GLboolean GLAPIENTRY -OSMesaGetDepthBuffer(OSMesaContext c, GLint *width, GLint *height, - GLint *bytesPerValue, void **buffer) -{ - struct osmesa_buffer *osbuffer = c->current_buffer; - struct pipe_context *pipe = c->stctx->pipe; - struct pipe_resource *res = osbuffer->textures[ST_ATTACHMENT_DEPTH_STENCIL]; - struct pipe_transfer *transfer = NULL; - struct pipe_box box; - - /* - * Note: we can't really implement this function with gallium as - * we did for swrast. We can't just map the resource and leave it - * mapped (and there's no OSMesaUnmapDepthBuffer() function) so - * we unmap the buffer here and return a 'stale' pointer. This should - * actually be OK in most cases where the caller of this function - * immediately uses the pointer. - */ - - u_box_2d(0, 0, res->width0, res->height0, &box); - - *buffer = pipe->transfer_map(pipe, res, 0, PIPE_TRANSFER_READ, &box, - &transfer); - if (!*buffer) { - return GL_FALSE; - } - - *width = res->width0; - *height = res->height0; - *bytesPerValue = util_format_get_blocksize(res->format); - - pipe->transfer_unmap(pipe, transfer); - - return GL_TRUE; -} - - -/** - * Return the color buffer associated with an OSMesa context. - * Input: c - the OSMesa context - * Output: width, height - size of buffer in pixels - * format - the pixel format (OSMESA_FORMAT) - * buffer - pointer to color buffer values - * Return: GL_TRUE or GL_FALSE to indicate success or failure. - */ -GLAPI GLboolean GLAPIENTRY -OSMesaGetColorBuffer(OSMesaContext osmesa, GLint *width, - GLint *height, GLint *format, void **buffer) -{ - struct osmesa_buffer *osbuffer = osmesa->current_buffer; - - if (osbuffer) { - *width = osbuffer->width; - *height = osbuffer->height; - *format = osmesa->format; - *buffer = osbuffer->map; - return GL_TRUE; - } - else { - *width = 0; - *height = 0; - *format = 0; - *buffer = 0; - return GL_FALSE; - } -} - - -struct name_function -{ - const char *Name; - OSMESAproc Function; -}; - -static struct name_function functions[] = { - { "OSMesaCreateContext", (OSMESAproc) OSMesaCreateContext }, - { "OSMesaCreateContextExt", (OSMESAproc) OSMesaCreateContextExt }, - { "OSMesaCreateContextAttribs", (OSMESAproc) OSMesaCreateContextAttribs }, - { "OSMesaDestroyContext", (OSMESAproc) OSMesaDestroyContext }, - { "OSMesaMakeCurrent", (OSMESAproc) OSMesaMakeCurrent }, - { "OSMesaGetCurrentContext", (OSMESAproc) OSMesaGetCurrentContext }, - { "OSMesaPixelStore", (OSMESAproc) OSMesaPixelStore }, - { "OSMesaGetIntegerv", (OSMESAproc) OSMesaGetIntegerv }, - { "OSMesaGetDepthBuffer", (OSMESAproc) OSMesaGetDepthBuffer }, - { "OSMesaGetColorBuffer", (OSMESAproc) OSMesaGetColorBuffer }, - { "OSMesaGetProcAddress", (OSMESAproc) OSMesaGetProcAddress }, - { "OSMesaColorClamp", (OSMESAproc) OSMesaColorClamp }, - { "OSMesaPostprocess", (OSMESAproc) OSMesaPostprocess }, - { NULL, NULL } -}; - - -GLAPI OSMESAproc GLAPIENTRY -OSMesaGetProcAddress(const char *funcName) -{ - int i; - for (i = 0; functions[i].Name; i++) { - if (strcmp(functions[i].Name, funcName) == 0) - return functions[i].Function; - } - return _glapi_get_proc_address(funcName); -} - - -GLAPI void GLAPIENTRY -OSMesaColorClamp(GLboolean enable) -{ - extern void GLAPIENTRY _mesa_ClampColor(GLenum target, GLenum clamp); - - _mesa_ClampColor(GL_CLAMP_FRAGMENT_COLOR_ARB, - enable ? GL_TRUE : GL_FIXED_ONLY_ARB); -} - - -GLAPI void GLAPIENTRY -OSMesaPostprocess(OSMesaContext osmesa, const char *filter, - unsigned enable_value) -{ - if (!osmesa->ever_used) { - /* We can only enable/disable postprocess filters before a context - * is made current for the first time. - */ - unsigned i; - - for (i = 0; i < PP_FILTERS; i++) { - if (strcmp(pp_filters[i].name, filter) == 0) { - osmesa->pp_enabled[i] = enable_value; - return; - } - } - debug_warning("OSMesaPostprocess(unknown filter)\n"); - } - else { - debug_warning("Calling OSMesaPostprocess() after OSMesaMakeCurrent()\n"); - } -} diff --git a/src/gallium/state_trackers/va/Makefile.sources b/src/gallium/state_trackers/va/Makefile.sources deleted file mode 100644 index bd43100a870..00000000000 --- a/src/gallium/state_trackers/va/Makefile.sources +++ /dev/null @@ -1,20 +0,0 @@ -C_SOURCES := \ - buffer.c \ - config.c \ - context.c \ - display.c \ - image.c \ - picture.c \ - picture_mpeg12.c \ - picture_mpeg4.c \ - picture_h264.c \ - picture_h264_enc.c \ - picture_hevc.c \ - picture_hevc_enc.c \ - picture_vc1.c \ - picture_mjpeg.c \ - picture_vp9.c \ - postproc.c \ - subpicture.c \ - surface.c \ - va_private.h diff --git a/src/gallium/state_trackers/va/buffer.c b/src/gallium/state_trackers/va/buffer.c deleted file mode 100644 index 0691b7023b2..00000000000 --- a/src/gallium/state_trackers/va/buffer.c +++ /dev/null @@ -1,373 +0,0 @@ -/************************************************************************** - * - * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian. - * Copyright 2014 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include "pipe/p_screen.h" -#include "state_tracker/drm_driver.h" -#include "util/u_memory.h" -#include "util/u_handle_table.h" -#include "util/u_transfer.h" -#include "vl/vl_winsys.h" - -#include "va_private.h" - -VAStatus -vlVaCreateBuffer(VADriverContextP ctx, VAContextID context, VABufferType type, - unsigned int size, unsigned int num_elements, void *data, - VABufferID *buf_id) -{ - vlVaDriver *drv; - vlVaBuffer *buf; - - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - buf = CALLOC(1, sizeof(vlVaBuffer)); - if (!buf) - return VA_STATUS_ERROR_ALLOCATION_FAILED; - - buf->type = type; - buf->size = size; - buf->num_elements = num_elements; - buf->data = MALLOC(size * num_elements); - - if (!buf->data) { - FREE(buf); - return VA_STATUS_ERROR_ALLOCATION_FAILED; - } - - if (data) - memcpy(buf->data, data, size * num_elements); - - drv = VL_VA_DRIVER(ctx); - mtx_lock(&drv->mutex); - *buf_id = handle_table_add(drv->htab, buf); - mtx_unlock(&drv->mutex); - - return VA_STATUS_SUCCESS; -} - -VAStatus -vlVaBufferSetNumElements(VADriverContextP ctx, VABufferID buf_id, - unsigned int num_elements) -{ - vlVaDriver *drv; - vlVaBuffer *buf; - - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - drv = VL_VA_DRIVER(ctx); - mtx_lock(&drv->mutex); - buf = handle_table_get(drv->htab, buf_id); - mtx_unlock(&drv->mutex); - if (!buf) - return VA_STATUS_ERROR_INVALID_BUFFER; - - if (buf->derived_surface.resource) - return VA_STATUS_ERROR_INVALID_BUFFER; - - buf->data = REALLOC(buf->data, buf->size * buf->num_elements, - buf->size * num_elements); - buf->num_elements = num_elements; - - if (!buf->data) - return VA_STATUS_ERROR_ALLOCATION_FAILED; - - return VA_STATUS_SUCCESS; -} - -VAStatus -vlVaMapBuffer(VADriverContextP ctx, VABufferID buf_id, void **pbuff) -{ - vlVaDriver *drv; - vlVaBuffer *buf; - - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - drv = VL_VA_DRIVER(ctx); - if (!drv) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - if (!pbuff) - return VA_STATUS_ERROR_INVALID_PARAMETER; - - mtx_lock(&drv->mutex); - buf = handle_table_get(drv->htab, buf_id); - if (!buf || buf->export_refcount > 0) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_INVALID_BUFFER; - } - - if (buf->derived_surface.resource) { - struct pipe_resource *resource; - struct pipe_box box = {}; - - resource = buf->derived_surface.resource; - box.width = resource->width0; - box.height = resource->height0; - box.depth = resource->depth0; - *pbuff = drv->pipe->transfer_map(drv->pipe, resource, 0, PIPE_TRANSFER_WRITE, - &box, &buf->derived_surface.transfer); - mtx_unlock(&drv->mutex); - - if (!buf->derived_surface.transfer || !*pbuff) - return VA_STATUS_ERROR_INVALID_BUFFER; - - if (buf->type == VAEncCodedBufferType) { - ((VACodedBufferSegment*)buf->data)->buf = *pbuff; - ((VACodedBufferSegment*)buf->data)->size = buf->coded_size; - ((VACodedBufferSegment*)buf->data)->next = NULL; - *pbuff = buf->data; - } - } else { - mtx_unlock(&drv->mutex); - *pbuff = buf->data; - } - - return VA_STATUS_SUCCESS; -} - -VAStatus -vlVaUnmapBuffer(VADriverContextP ctx, VABufferID buf_id) -{ - vlVaDriver *drv; - vlVaBuffer *buf; - - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - drv = VL_VA_DRIVER(ctx); - if (!drv) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - mtx_lock(&drv->mutex); - buf = handle_table_get(drv->htab, buf_id); - if (!buf || buf->export_refcount > 0) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_INVALID_BUFFER; - } - - if (buf->derived_surface.resource) { - if (!buf->derived_surface.transfer) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_INVALID_BUFFER; - } - - pipe_buffer_unmap(drv->pipe, buf->derived_surface.transfer); - buf->derived_surface.transfer = NULL; - } - mtx_unlock(&drv->mutex); - - return VA_STATUS_SUCCESS; -} - -VAStatus -vlVaDestroyBuffer(VADriverContextP ctx, VABufferID buf_id) -{ - vlVaDriver *drv; - vlVaBuffer *buf; - - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - drv = VL_VA_DRIVER(ctx); - mtx_lock(&drv->mutex); - buf = handle_table_get(drv->htab, buf_id); - if (!buf) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_INVALID_BUFFER; - } - - if (buf->derived_surface.resource) - pipe_resource_reference(&buf->derived_surface.resource, NULL); - - FREE(buf->data); - FREE(buf); - handle_table_remove(VL_VA_DRIVER(ctx)->htab, buf_id); - mtx_unlock(&drv->mutex); - - return VA_STATUS_SUCCESS; -} - -VAStatus -vlVaBufferInfo(VADriverContextP ctx, VABufferID buf_id, VABufferType *type, - unsigned int *size, unsigned int *num_elements) -{ - vlVaDriver *drv; - vlVaBuffer *buf; - - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - drv = VL_VA_DRIVER(ctx); - mtx_lock(&drv->mutex); - buf = handle_table_get(drv->htab, buf_id); - mtx_unlock(&drv->mutex); - if (!buf) - return VA_STATUS_ERROR_INVALID_BUFFER; - - *type = buf->type; - *size = buf->size; - *num_elements = buf->num_elements; - - return VA_STATUS_SUCCESS; -} - -VAStatus -vlVaAcquireBufferHandle(VADriverContextP ctx, VABufferID buf_id, - VABufferInfo *out_buf_info) -{ - vlVaDriver *drv; - uint32_t i; - uint32_t mem_type; - vlVaBuffer *buf ; - struct pipe_screen *screen; - - /* List of supported memory types, in preferred order. */ - static const uint32_t mem_types[] = { - VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME, - 0 - }; - - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - drv = VL_VA_DRIVER(ctx); - screen = VL_VA_PSCREEN(ctx); - mtx_lock(&drv->mutex); - buf = handle_table_get(VL_VA_DRIVER(ctx)->htab, buf_id); - mtx_unlock(&drv->mutex); - - if (!buf) - return VA_STATUS_ERROR_INVALID_BUFFER; - - /* Only VA surface|image like buffers are supported for now .*/ - if (buf->type != VAImageBufferType) - return VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE; - - if (!out_buf_info) - return VA_STATUS_ERROR_INVALID_PARAMETER; - - if (!out_buf_info->mem_type) - mem_type = mem_types[0]; - else { - mem_type = 0; - for (i = 0; mem_types[i] != 0; i++) { - if (out_buf_info->mem_type & mem_types[i]) { - mem_type = out_buf_info->mem_type; - break; - } - } - if (!mem_type) - return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE; - } - - if (!buf->derived_surface.resource) - return VA_STATUS_ERROR_INVALID_BUFFER; - - if (buf->export_refcount > 0) { - if (buf->export_state.mem_type != mem_type) - return VA_STATUS_ERROR_INVALID_PARAMETER; - } else { - VABufferInfo * const buf_info = &buf->export_state; - - switch (mem_type) { - case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME: { - struct winsys_handle whandle; - - mtx_lock(&drv->mutex); - drv->pipe->flush(drv->pipe, NULL, 0); - - memset(&whandle, 0, sizeof(whandle)); - whandle.type = WINSYS_HANDLE_TYPE_FD; - - if (!screen->resource_get_handle(screen, drv->pipe, - buf->derived_surface.resource, - &whandle, PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE)) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_INVALID_BUFFER; - } - - mtx_unlock(&drv->mutex); - - buf_info->handle = (intptr_t)whandle.handle; - break; - } - default: - return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE; - } - - buf_info->type = buf->type; - buf_info->mem_type = mem_type; - buf_info->mem_size = buf->num_elements * buf->size; - } - - buf->export_refcount++; - - *out_buf_info = buf->export_state; - - return VA_STATUS_SUCCESS; -} - -VAStatus -vlVaReleaseBufferHandle(VADriverContextP ctx, VABufferID buf_id) -{ - vlVaDriver *drv; - vlVaBuffer *buf; - - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - drv = VL_VA_DRIVER(ctx); - mtx_lock(&drv->mutex); - buf = handle_table_get(drv->htab, buf_id); - mtx_unlock(&drv->mutex); - - if (!buf) - return VA_STATUS_ERROR_INVALID_BUFFER; - - if (buf->export_refcount == 0) - return VA_STATUS_ERROR_INVALID_BUFFER; - - if (--buf->export_refcount == 0) { - VABufferInfo * const buf_info = &buf->export_state; - - switch (buf_info->mem_type) { - case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME: - close((intptr_t)buf_info->handle); - break; - default: - return VA_STATUS_ERROR_INVALID_BUFFER; - } - - buf_info->mem_type = 0; - } - - return VA_STATUS_SUCCESS; -} diff --git a/src/gallium/state_trackers/va/config.c b/src/gallium/state_trackers/va/config.c deleted file mode 100644 index 294cbcc6418..00000000000 --- a/src/gallium/state_trackers/va/config.c +++ /dev/null @@ -1,382 +0,0 @@ -/************************************************************************** - * - * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian. - * Copyright 2014 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include "pipe/p_screen.h" - -#include "util/u_video.h" -#include "util/u_memory.h" - -#include "vl/vl_winsys.h" - -#include "va_private.h" - -#include "util/u_handle_table.h" - -DEBUG_GET_ONCE_BOOL_OPTION(mpeg4, "VAAPI_MPEG4_ENABLED", false) - -VAStatus -vlVaQueryConfigProfiles(VADriverContextP ctx, VAProfile *profile_list, int *num_profiles) -{ - struct pipe_screen *pscreen; - enum pipe_video_profile p; - VAProfile vap; - - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - *num_profiles = 0; - - pscreen = VL_VA_PSCREEN(ctx); - for (p = PIPE_VIDEO_PROFILE_MPEG2_SIMPLE; p <= PIPE_VIDEO_PROFILE_VP9_PROFILE2; ++p) { - if (u_reduce_video_profile(p) == PIPE_VIDEO_FORMAT_MPEG4 && !debug_get_option_mpeg4()) - continue; - - if (pscreen->get_video_param(pscreen, p, PIPE_VIDEO_ENTRYPOINT_BITSTREAM, PIPE_VIDEO_CAP_SUPPORTED)) { - vap = PipeToProfile(p); - if (vap != VAProfileNone) - profile_list[(*num_profiles)++] = vap; - } - } - - /* Support postprocessing through vl_compositor */ - profile_list[(*num_profiles)++] = VAProfileNone; - - return VA_STATUS_SUCCESS; -} - -VAStatus -vlVaQueryConfigEntrypoints(VADriverContextP ctx, VAProfile profile, - VAEntrypoint *entrypoint_list, int *num_entrypoints) -{ - struct pipe_screen *pscreen; - enum pipe_video_profile p; - - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - *num_entrypoints = 0; - - if (profile == VAProfileNone) { - entrypoint_list[(*num_entrypoints)++] = VAEntrypointVideoProc; - return VA_STATUS_SUCCESS; - } - - p = ProfileToPipe(profile); - if (p == PIPE_VIDEO_PROFILE_UNKNOWN) - return VA_STATUS_ERROR_UNSUPPORTED_PROFILE; - - pscreen = VL_VA_PSCREEN(ctx); - if (pscreen->get_video_param(pscreen, p, PIPE_VIDEO_ENTRYPOINT_BITSTREAM, - PIPE_VIDEO_CAP_SUPPORTED)) - entrypoint_list[(*num_entrypoints)++] = VAEntrypointVLD; - - if (pscreen->get_video_param(pscreen, p, PIPE_VIDEO_ENTRYPOINT_ENCODE, - PIPE_VIDEO_CAP_SUPPORTED)) - entrypoint_list[(*num_entrypoints)++] = VAEntrypointEncSlice; - - if (num_entrypoints == 0) - return VA_STATUS_ERROR_UNSUPPORTED_PROFILE; - - assert(*num_entrypoints <= ctx->max_entrypoints); - - return VA_STATUS_SUCCESS; -} - -VAStatus -vlVaGetConfigAttributes(VADriverContextP ctx, VAProfile profile, VAEntrypoint entrypoint, - VAConfigAttrib *attrib_list, int num_attribs) -{ - struct pipe_screen *pscreen; - int i; - - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - pscreen = VL_VA_PSCREEN(ctx); - - for (i = 0; i < num_attribs; ++i) { - unsigned int value; - if ((entrypoint == VAEntrypointVLD) && - (pscreen->get_video_param(pscreen, ProfileToPipe(profile), - PIPE_VIDEO_ENTRYPOINT_BITSTREAM, PIPE_VIDEO_CAP_SUPPORTED))) { - switch (attrib_list[i].type) { - case VAConfigAttribRTFormat: - value = VA_RT_FORMAT_YUV420 | VA_RT_FORMAT_YUV422; - if (pscreen->is_video_format_supported(pscreen, PIPE_FORMAT_P010, - ProfileToPipe(profile), - PIPE_VIDEO_ENTRYPOINT_BITSTREAM) || - pscreen->is_video_format_supported(pscreen, PIPE_FORMAT_P016, - ProfileToPipe(profile), - PIPE_VIDEO_ENTRYPOINT_BITSTREAM)) - value |= VA_RT_FORMAT_YUV420_10BPP; - break; - default: - value = VA_ATTRIB_NOT_SUPPORTED; - break; - } - } else if ((entrypoint == VAEntrypointEncSlice) && - (pscreen->get_video_param(pscreen, ProfileToPipe(profile), - PIPE_VIDEO_ENTRYPOINT_ENCODE, PIPE_VIDEO_CAP_SUPPORTED))) { - switch (attrib_list[i].type) { - case VAConfigAttribRTFormat: - value = VA_RT_FORMAT_YUV420; - if (pscreen->is_video_format_supported(pscreen, PIPE_FORMAT_P010, - ProfileToPipe(profile), - PIPE_VIDEO_ENTRYPOINT_BITSTREAM) || - pscreen->is_video_format_supported(pscreen, PIPE_FORMAT_P016, - ProfileToPipe(profile), - PIPE_VIDEO_ENTRYPOINT_BITSTREAM)) - value |= VA_RT_FORMAT_YUV420_10BPP; - break; - case VAConfigAttribRateControl: - value = VA_RC_CQP | VA_RC_CBR | VA_RC_VBR; - break; - case VAConfigAttribEncPackedHeaders: - value = 0; - break; - case VAConfigAttribEncMaxRefFrames: - value = 1; - break; - default: - value = VA_ATTRIB_NOT_SUPPORTED; - break; - } - } else if (entrypoint == VAEntrypointVideoProc) { - switch (attrib_list[i].type) { - case VAConfigAttribRTFormat: - value = (VA_RT_FORMAT_YUV420 | - VA_RT_FORMAT_YUV420_10BPP | - VA_RT_FORMAT_RGB32); - break; - default: - value = VA_ATTRIB_NOT_SUPPORTED; - break; - } - } else { - value = VA_ATTRIB_NOT_SUPPORTED; - } - attrib_list[i].value = value; - } - - return VA_STATUS_SUCCESS; -} - -VAStatus -vlVaCreateConfig(VADriverContextP ctx, VAProfile profile, VAEntrypoint entrypoint, - VAConfigAttrib *attrib_list, int num_attribs, VAConfigID *config_id) -{ - vlVaDriver *drv; - vlVaConfig *config; - struct pipe_screen *pscreen; - enum pipe_video_profile p; - unsigned int supported_rt_formats; - - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - drv = VL_VA_DRIVER(ctx); - - if (!drv) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - config = CALLOC(1, sizeof(vlVaConfig)); - if (!config) - return VA_STATUS_ERROR_ALLOCATION_FAILED; - - if (profile == VAProfileNone && entrypoint == VAEntrypointVideoProc) { - config->entrypoint = PIPE_VIDEO_ENTRYPOINT_UNKNOWN; - config->profile = PIPE_VIDEO_PROFILE_UNKNOWN; - supported_rt_formats = VA_RT_FORMAT_YUV420 | - VA_RT_FORMAT_YUV420_10BPP | - VA_RT_FORMAT_RGB32; - for (int i = 0; i < num_attribs; i++) { - if (attrib_list[i].type == VAConfigAttribRTFormat) { - if (attrib_list[i].value & supported_rt_formats) { - config->rt_format = attrib_list[i].value; - } else { - FREE(config); - return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT; - } - } - } - - /* Default value if not specified in the input attributes. */ - if (!config->rt_format) - config->rt_format = supported_rt_formats; - - mtx_lock(&drv->mutex); - *config_id = handle_table_add(drv->htab, config); - mtx_unlock(&drv->mutex); - return VA_STATUS_SUCCESS; - } - - p = ProfileToPipe(profile); - if (p == PIPE_VIDEO_PROFILE_UNKNOWN) { - FREE(config); - return VA_STATUS_ERROR_UNSUPPORTED_PROFILE; - } - - pscreen = VL_VA_PSCREEN(ctx); - - switch (entrypoint) { - case VAEntrypointVLD: - if (!pscreen->get_video_param(pscreen, p, PIPE_VIDEO_ENTRYPOINT_BITSTREAM, - PIPE_VIDEO_CAP_SUPPORTED)) { - FREE(config); - return VA_STATUS_ERROR_UNSUPPORTED_PROFILE; - } - - config->entrypoint = PIPE_VIDEO_ENTRYPOINT_BITSTREAM; - break; - - case VAEntrypointEncSlice: - if (!pscreen->get_video_param(pscreen, p, PIPE_VIDEO_ENTRYPOINT_ENCODE, - PIPE_VIDEO_CAP_SUPPORTED)) { - FREE(config); - return VA_STATUS_ERROR_UNSUPPORTED_PROFILE; - } - - config->entrypoint = PIPE_VIDEO_ENTRYPOINT_ENCODE; - break; - - default: - FREE(config); - return VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT; - } - - config->profile = p; - supported_rt_formats = VA_RT_FORMAT_YUV420 | VA_RT_FORMAT_YUV422; - if (pscreen->is_video_format_supported(pscreen, PIPE_FORMAT_P010, p, - config->entrypoint) || - pscreen->is_video_format_supported(pscreen, PIPE_FORMAT_P016, p, - config->entrypoint)) - supported_rt_formats |= VA_RT_FORMAT_YUV420_10BPP; - - for (int i = 0; i rc = PIPE_H264_ENC_RATE_CONTROL_METHOD_CONSTANT; - else if (attrib_list[i].value == VA_RC_VBR) - config->rc = PIPE_H264_ENC_RATE_CONTROL_METHOD_VARIABLE; - else - config->rc = PIPE_H264_ENC_RATE_CONTROL_METHOD_DISABLE; - } - if (attrib_list[i].type == VAConfigAttribRTFormat) { - if (attrib_list[i].value & supported_rt_formats) { - config->rt_format = attrib_list[i].value; - } else { - FREE(config); - return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT; - } - } - } - - /* Default value if not specified in the input attributes. */ - if (!config->rt_format) - config->rt_format = supported_rt_formats; - - mtx_lock(&drv->mutex); - *config_id = handle_table_add(drv->htab, config); - mtx_unlock(&drv->mutex); - - return VA_STATUS_SUCCESS; -} - -VAStatus -vlVaDestroyConfig(VADriverContextP ctx, VAConfigID config_id) -{ - vlVaDriver *drv; - vlVaConfig *config; - - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - drv = VL_VA_DRIVER(ctx); - - if (!drv) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - mtx_lock(&drv->mutex); - config = handle_table_get(drv->htab, config_id); - - if (!config) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_INVALID_CONFIG; - } - - FREE(config); - handle_table_remove(drv->htab, config_id); - mtx_unlock(&drv->mutex); - - return VA_STATUS_SUCCESS; -} - -VAStatus -vlVaQueryConfigAttributes(VADriverContextP ctx, VAConfigID config_id, VAProfile *profile, - VAEntrypoint *entrypoint, VAConfigAttrib *attrib_list, int *num_attribs) -{ - vlVaDriver *drv; - vlVaConfig *config; - - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - drv = VL_VA_DRIVER(ctx); - - if (!drv) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - mtx_lock(&drv->mutex); - config = handle_table_get(drv->htab, config_id); - mtx_unlock(&drv->mutex); - - if (!config) - return VA_STATUS_ERROR_INVALID_CONFIG; - - *profile = PipeToProfile(config->profile); - - switch (config->entrypoint) { - case PIPE_VIDEO_ENTRYPOINT_BITSTREAM: - *entrypoint = VAEntrypointVLD; - break; - case PIPE_VIDEO_ENTRYPOINT_ENCODE: - *entrypoint = VAEntrypointEncSlice; - break; - case PIPE_VIDEO_ENTRYPOINT_UNKNOWN: - *entrypoint = VAEntrypointVideoProc; - break; - default: - return VA_STATUS_ERROR_INVALID_CONFIG; - } - - *num_attribs = 1; - attrib_list[0].type = VAConfigAttribRTFormat; - attrib_list[0].value = config->rt_format; - - return VA_STATUS_SUCCESS; -} diff --git a/src/gallium/state_trackers/va/context.c b/src/gallium/state_trackers/va/context.c deleted file mode 100644 index 0c596f3f811..00000000000 --- a/src/gallium/state_trackers/va/context.c +++ /dev/null @@ -1,397 +0,0 @@ -/************************************************************************** - * - * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian. - * Copyright 2014 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include "pipe/p_screen.h" -#include "pipe/p_video_codec.h" -#include "util/u_memory.h" -#include "util/u_handle_table.h" -#include "util/u_video.h" -#include "vl/vl_deint_filter.h" -#include "vl/vl_winsys.h" - -#include "va_private.h" - -#include - -static struct VADriverVTable vtable = -{ - &vlVaTerminate, - &vlVaQueryConfigProfiles, - &vlVaQueryConfigEntrypoints, - &vlVaGetConfigAttributes, - &vlVaCreateConfig, - &vlVaDestroyConfig, - &vlVaQueryConfigAttributes, - &vlVaCreateSurfaces, - &vlVaDestroySurfaces, - &vlVaCreateContext, - &vlVaDestroyContext, - &vlVaCreateBuffer, - &vlVaBufferSetNumElements, - &vlVaMapBuffer, - &vlVaUnmapBuffer, - &vlVaDestroyBuffer, - &vlVaBeginPicture, - &vlVaRenderPicture, - &vlVaEndPicture, - &vlVaSyncSurface, - &vlVaQuerySurfaceStatus, - &vlVaQuerySurfaceError, - &vlVaPutSurface, - &vlVaQueryImageFormats, - &vlVaCreateImage, - &vlVaDeriveImage, - &vlVaDestroyImage, - &vlVaSetImagePalette, - &vlVaGetImage, - &vlVaPutImage, - &vlVaQuerySubpictureFormats, - &vlVaCreateSubpicture, - &vlVaDestroySubpicture, - &vlVaSubpictureImage, - &vlVaSetSubpictureChromakey, - &vlVaSetSubpictureGlobalAlpha, - &vlVaAssociateSubpicture, - &vlVaDeassociateSubpicture, - &vlVaQueryDisplayAttributes, - &vlVaGetDisplayAttributes, - &vlVaSetDisplayAttributes, - &vlVaBufferInfo, - &vlVaLockSurface, - &vlVaUnlockSurface, - NULL, /* DEPRECATED VaGetSurfaceAttributes */ - &vlVaCreateSurfaces2, - &vlVaQuerySurfaceAttributes, - &vlVaAcquireBufferHandle, - &vlVaReleaseBufferHandle, -#if VA_CHECK_VERSION(1, 1, 0) - NULL, /* vaCreateMFContext */ - NULL, /* vaMFAddContext */ - NULL, /* vaMFReleaseContext */ - NULL, /* vaMFSubmit */ - NULL, /* vaCreateBuffer2 */ - NULL, /* vaQueryProcessingRate */ - &vlVaExportSurfaceHandle, -#endif -}; - -static struct VADriverVTableVPP vtable_vpp = -{ - 1, - &vlVaQueryVideoProcFilters, - &vlVaQueryVideoProcFilterCaps, - &vlVaQueryVideoProcPipelineCaps -}; - -PUBLIC VAStatus -VA_DRIVER_INIT_FUNC(VADriverContextP ctx) -{ - vlVaDriver *drv; - - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - drv = CALLOC(1, sizeof(vlVaDriver)); - if (!drv) - return VA_STATUS_ERROR_ALLOCATION_FAILED; - - switch (ctx->display_type) { - case VA_DISPLAY_ANDROID: - FREE(drv); - return VA_STATUS_ERROR_UNIMPLEMENTED; - case VA_DISPLAY_GLX: - case VA_DISPLAY_X11: - drv->vscreen = vl_dri3_screen_create(ctx->native_dpy, ctx->x11_screen); - if (!drv->vscreen) - drv->vscreen = vl_dri2_screen_create(ctx->native_dpy, ctx->x11_screen); - break; - case VA_DISPLAY_WAYLAND: - case VA_DISPLAY_DRM: - case VA_DISPLAY_DRM_RENDERNODES: { - const struct drm_state *drm_info = (struct drm_state *) ctx->drm_state; - - if (!drm_info || drm_info->fd < 0) { - FREE(drv); - return VA_STATUS_ERROR_INVALID_PARAMETER; - } - - drv->vscreen = vl_drm_screen_create(drm_info->fd); - break; - } - default: - FREE(drv); - return VA_STATUS_ERROR_INVALID_DISPLAY; - } - - if (!drv->vscreen) - goto error_screen; - - drv->pipe = pipe_create_multimedia_context(drv->vscreen->pscreen); - if (!drv->pipe) - goto error_pipe; - - drv->htab = handle_table_create(); - if (!drv->htab) - goto error_htab; - - if (!vl_compositor_init(&drv->compositor, drv->pipe)) - goto error_compositor; - if (!vl_compositor_init_state(&drv->cstate, drv->pipe)) - goto error_compositor_state; - - vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601, NULL, true, &drv->csc); - if (!vl_compositor_set_csc_matrix(&drv->cstate, (const vl_csc_matrix *)&drv->csc, 1.0f, 0.0f)) - goto error_csc_matrix; - (void) mtx_init(&drv->mutex, mtx_plain); - - ctx->pDriverData = (void *)drv; - ctx->version_major = 0; - ctx->version_minor = 1; - *ctx->vtable = vtable; - *ctx->vtable_vpp = vtable_vpp; - ctx->max_profiles = PIPE_VIDEO_PROFILE_MAX - PIPE_VIDEO_PROFILE_UNKNOWN - 1; - ctx->max_entrypoints = 2; - ctx->max_attributes = 1; - ctx->max_image_formats = VL_VA_MAX_IMAGE_FORMATS; - ctx->max_subpic_formats = 1; - ctx->max_display_attributes = 1; - - snprintf(drv->vendor_string, sizeof(drv->vendor_string), - "Mesa Gallium driver " PACKAGE_VERSION " for %s", - drv->vscreen->pscreen->get_name(drv->vscreen->pscreen)); - ctx->str_vendor = drv->vendor_string; - - return VA_STATUS_SUCCESS; - -error_csc_matrix: - vl_compositor_cleanup_state(&drv->cstate); - -error_compositor_state: - vl_compositor_cleanup(&drv->compositor); - -error_compositor: - handle_table_destroy(drv->htab); - -error_htab: - drv->pipe->destroy(drv->pipe); - -error_pipe: - drv->vscreen->destroy(drv->vscreen); - -error_screen: - FREE(drv); - return VA_STATUS_ERROR_ALLOCATION_FAILED; -} - -VAStatus -vlVaCreateContext(VADriverContextP ctx, VAConfigID config_id, int picture_width, - int picture_height, int flag, VASurfaceID *render_targets, - int num_render_targets, VAContextID *context_id) -{ - vlVaDriver *drv; - vlVaContext *context; - vlVaConfig *config; - int is_vpp; - - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - drv = VL_VA_DRIVER(ctx); - mtx_lock(&drv->mutex); - config = handle_table_get(drv->htab, config_id); - mtx_unlock(&drv->mutex); - - is_vpp = config->profile == PIPE_VIDEO_PROFILE_UNKNOWN && !picture_width && - !picture_height && !flag && !render_targets && !num_render_targets; - - if (!(picture_width && picture_height) && !is_vpp) - return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT; - - context = CALLOC(1, sizeof(vlVaContext)); - if (!context) - return VA_STATUS_ERROR_ALLOCATION_FAILED; - - if (is_vpp) { - context->decoder = NULL; - } else { - context->templat.profile = config->profile; - context->templat.entrypoint = config->entrypoint; - context->templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; - context->templat.width = picture_width; - context->templat.height = picture_height; - context->templat.expect_chunked_decode = true; - - switch (u_reduce_video_profile(context->templat.profile)) { - case PIPE_VIDEO_FORMAT_MPEG12: - case PIPE_VIDEO_FORMAT_VC1: - case PIPE_VIDEO_FORMAT_MPEG4: - context->templat.max_references = 2; - break; - - case PIPE_VIDEO_FORMAT_MPEG4_AVC: - context->templat.max_references = 0; - if (config->entrypoint != PIPE_VIDEO_ENTRYPOINT_ENCODE) { - context->desc.h264.pps = CALLOC_STRUCT(pipe_h264_pps); - if (!context->desc.h264.pps) { - FREE(context); - return VA_STATUS_ERROR_ALLOCATION_FAILED; - } - context->desc.h264.pps->sps = CALLOC_STRUCT(pipe_h264_sps); - if (!context->desc.h264.pps->sps) { - FREE(context->desc.h264.pps); - FREE(context); - return VA_STATUS_ERROR_ALLOCATION_FAILED; - } - } - break; - - case PIPE_VIDEO_FORMAT_HEVC: - context->templat.max_references = num_render_targets; - if (config->entrypoint != PIPE_VIDEO_ENTRYPOINT_ENCODE) { - context->desc.h265.pps = CALLOC_STRUCT(pipe_h265_pps); - if (!context->desc.h265.pps) { - FREE(context); - return VA_STATUS_ERROR_ALLOCATION_FAILED; - } - context->desc.h265.pps->sps = CALLOC_STRUCT(pipe_h265_sps); - if (!context->desc.h265.pps->sps) { - FREE(context->desc.h265.pps); - FREE(context); - return VA_STATUS_ERROR_ALLOCATION_FAILED; - } - } - break; - - case PIPE_VIDEO_FORMAT_VP9: - context->templat.max_references = num_render_targets; - break; - - default: - break; - } - } - - context->desc.base.profile = config->profile; - context->desc.base.entry_point = config->entrypoint; - if (config->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) { - switch (u_reduce_video_profile(context->templat.profile)) { - case PIPE_VIDEO_FORMAT_MPEG4_AVC: - context->desc.h264enc.rate_ctrl.rate_ctrl_method = config->rc; - context->desc.h264enc.frame_idx = util_hash_table_create_ptr_keys(); - break; - case PIPE_VIDEO_FORMAT_HEVC: - context->desc.h265enc.rc.rate_ctrl_method = config->rc; - context->desc.h265enc.frame_idx = util_hash_table_create_ptr_keys(); - break; - default: - break; - } - } - - mtx_lock(&drv->mutex); - *context_id = handle_table_add(drv->htab, context); - mtx_unlock(&drv->mutex); - - return VA_STATUS_SUCCESS; -} - -VAStatus -vlVaDestroyContext(VADriverContextP ctx, VAContextID context_id) -{ - vlVaDriver *drv; - vlVaContext *context; - - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - drv = VL_VA_DRIVER(ctx); - mtx_lock(&drv->mutex); - context = handle_table_get(drv->htab, context_id); - if (!context) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_INVALID_CONTEXT; - } - - if (context->decoder) { - if (context->desc.base.entry_point == PIPE_VIDEO_ENTRYPOINT_ENCODE) { - if (u_reduce_video_profile(context->decoder->profile) == - PIPE_VIDEO_FORMAT_MPEG4_AVC) { - if (context->desc.h264enc.frame_idx) - _mesa_hash_table_destroy(context->desc.h264enc.frame_idx, NULL); - } - if (u_reduce_video_profile(context->decoder->profile) == - PIPE_VIDEO_FORMAT_HEVC) { - if (context->desc.h265enc.frame_idx) - _mesa_hash_table_destroy(context->desc.h265enc.frame_idx, NULL); - } - } else { - if (u_reduce_video_profile(context->decoder->profile) == - PIPE_VIDEO_FORMAT_MPEG4_AVC) { - FREE(context->desc.h264.pps->sps); - FREE(context->desc.h264.pps); - } - if (u_reduce_video_profile(context->decoder->profile) == - PIPE_VIDEO_FORMAT_HEVC) { - FREE(context->desc.h265.pps->sps); - FREE(context->desc.h265.pps); - } - } - context->decoder->destroy(context->decoder); - } - if (context->blit_cs) - drv->pipe->delete_compute_state(drv->pipe, context->blit_cs); - if (context->deint) { - vl_deint_filter_cleanup(context->deint); - FREE(context->deint); - } - FREE(context); - handle_table_remove(drv->htab, context_id); - mtx_unlock(&drv->mutex); - - return VA_STATUS_SUCCESS; -} - -VAStatus -vlVaTerminate(VADriverContextP ctx) -{ - vlVaDriver *drv; - - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - drv = ctx->pDriverData; - vl_compositor_cleanup_state(&drv->cstate); - vl_compositor_cleanup(&drv->compositor); - drv->pipe->destroy(drv->pipe); - drv->vscreen->destroy(drv->vscreen); - handle_table_destroy(drv->htab); - mtx_destroy(&drv->mutex); - FREE(drv); - - return VA_STATUS_SUCCESS; -} diff --git a/src/gallium/state_trackers/va/display.c b/src/gallium/state_trackers/va/display.c deleted file mode 100644 index 3d0fe09ca61..00000000000 --- a/src/gallium/state_trackers/va/display.c +++ /dev/null @@ -1,61 +0,0 @@ -/************************************************************************** - * - * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian. - * Copyright 2014 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include "va_private.h" - -VAStatus -vlVaQueryDisplayAttributes(VADriverContextP ctx, VADisplayAttribute *attr_list, int *num_attributes) -{ - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - if (!(attr_list && num_attributes)) - return VA_STATUS_ERROR_UNKNOWN; - - *num_attributes = 0; - - return VA_STATUS_SUCCESS; -} - -VAStatus -vlVaGetDisplayAttributes(VADriverContextP ctx, VADisplayAttribute *attr_list, int num_attributes) -{ - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - return VA_STATUS_ERROR_UNIMPLEMENTED; -} - -VAStatus -vlVaSetDisplayAttributes(VADriverContextP ctx, VADisplayAttribute *attr_list, int num_attributes) -{ - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - return VA_STATUS_ERROR_UNIMPLEMENTED; -} diff --git a/src/gallium/state_trackers/va/image.c b/src/gallium/state_trackers/va/image.c deleted file mode 100644 index 3a6a7e83d14..00000000000 --- a/src/gallium/state_trackers/va/image.c +++ /dev/null @@ -1,628 +0,0 @@ -/************************************************************************** - * - * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian. - * Copyright 2014 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include "pipe/p_screen.h" - -#include "util/u_memory.h" -#include "util/u_handle_table.h" -#include "util/u_surface.h" -#include "util/u_video.h" - -#include "vl/vl_winsys.h" -#include "vl/vl_video_buffer.h" - -#include "va_private.h" - -static const VAImageFormat formats[] = -{ - {VA_FOURCC('N','V','1','2')}, - {VA_FOURCC('P','0','1','0')}, - {VA_FOURCC('P','0','1','6')}, - {VA_FOURCC('I','4','2','0')}, - {VA_FOURCC('Y','V','1','2')}, - {VA_FOURCC('Y','U','Y','V')}, - {VA_FOURCC('Y','U','Y','2')}, - {VA_FOURCC('U','Y','V','Y')}, - {.fourcc = VA_FOURCC('B','G','R','A'), .byte_order = VA_LSB_FIRST, 32, 32, - 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000}, - {.fourcc = VA_FOURCC('R','G','B','A'), .byte_order = VA_LSB_FIRST, 32, 32, - 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000}, - {.fourcc = VA_FOURCC('B','G','R','X'), .byte_order = VA_LSB_FIRST, 32, 24, - 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000}, - {.fourcc = VA_FOURCC('R','G','B','X'), .byte_order = VA_LSB_FIRST, 32, 24, - 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000} -}; - -static void -vlVaVideoSurfaceSize(vlVaSurface *p_surf, int component, - unsigned *width, unsigned *height) -{ - *width = p_surf->templat.width; - *height = p_surf->templat.height; - - vl_video_buffer_adjust_size(width, height, component, - pipe_format_to_chroma_format(p_surf->templat.buffer_format), - p_surf->templat.interlaced); -} - -VAStatus -vlVaQueryImageFormats(VADriverContextP ctx, VAImageFormat *format_list, int *num_formats) -{ - struct pipe_screen *pscreen; - enum pipe_format format; - int i; - - STATIC_ASSERT(ARRAY_SIZE(formats) == VL_VA_MAX_IMAGE_FORMATS); - - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - if (!(format_list && num_formats)) - return VA_STATUS_ERROR_INVALID_PARAMETER; - - *num_formats = 0; - pscreen = VL_VA_PSCREEN(ctx); - for (i = 0; i < ARRAY_SIZE(formats); ++i) { - format = VaFourccToPipeFormat(formats[i].fourcc); - if (pscreen->is_video_format_supported(pscreen, format, - PIPE_VIDEO_PROFILE_UNKNOWN, - PIPE_VIDEO_ENTRYPOINT_BITSTREAM)) - format_list[(*num_formats)++] = formats[i]; - } - - return VA_STATUS_SUCCESS; -} - -VAStatus -vlVaCreateImage(VADriverContextP ctx, VAImageFormat *format, int width, int height, VAImage *image) -{ - VAStatus status; - vlVaDriver *drv; - VAImage *img; - int w, h; - - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - if (!(format && image && width && height)) - return VA_STATUS_ERROR_INVALID_PARAMETER; - - drv = VL_VA_DRIVER(ctx); - - img = CALLOC(1, sizeof(VAImage)); - if (!img) - return VA_STATUS_ERROR_ALLOCATION_FAILED; - mtx_lock(&drv->mutex); - img->image_id = handle_table_add(drv->htab, img); - mtx_unlock(&drv->mutex); - - img->format = *format; - img->width = width; - img->height = height; - w = align(width, 2); - h = align(height, 2); - - switch (format->fourcc) { - case VA_FOURCC('N','V','1','2'): - img->num_planes = 2; - img->pitches[0] = w; - img->offsets[0] = 0; - img->pitches[1] = w; - img->offsets[1] = w * h; - img->data_size = w * h * 3 / 2; - break; - - case VA_FOURCC('P','0','1','0'): - case VA_FOURCC('P','0','1','6'): - img->num_planes = 2; - img->pitches[0] = w * 2; - img->offsets[0] = 0; - img->pitches[1] = w * 2; - img->offsets[1] = w * h * 2; - img->data_size = w * h * 3; - break; - - case VA_FOURCC('I','4','2','0'): - case VA_FOURCC('Y','V','1','2'): - img->num_planes = 3; - img->pitches[0] = w; - img->offsets[0] = 0; - img->pitches[1] = w / 2; - img->offsets[1] = w * h; - img->pitches[2] = w / 2; - img->offsets[2] = w * h * 5 / 4; - img->data_size = w * h * 3 / 2; - break; - - case VA_FOURCC('U','Y','V','Y'): - case VA_FOURCC('Y','U','Y','V'): - case VA_FOURCC('Y','U','Y','2'): - img->num_planes = 1; - img->pitches[0] = w * 2; - img->offsets[0] = 0; - img->data_size = w * h * 2; - break; - - case VA_FOURCC('B','G','R','A'): - case VA_FOURCC('R','G','B','A'): - case VA_FOURCC('B','G','R','X'): - case VA_FOURCC('R','G','B','X'): - img->num_planes = 1; - img->pitches[0] = w * 4; - img->offsets[0] = 0; - img->data_size = w * h * 4; - break; - - default: - return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT; - } - - status = vlVaCreateBuffer(ctx, 0, VAImageBufferType, - align(img->data_size, 16), - 1, NULL, &img->buf); - if (status != VA_STATUS_SUCCESS) - return status; - *image = *img; - - return status; -} - -VAStatus -vlVaDeriveImage(VADriverContextP ctx, VASurfaceID surface, VAImage *image) -{ - vlVaDriver *drv; - vlVaSurface *surf; - vlVaBuffer *img_buf; - VAImage *img; - struct pipe_screen *screen; - struct pipe_surface **surfaces; - int w; - int h; - int i; - unsigned stride = 0; - unsigned offset = 0; - - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - drv = VL_VA_DRIVER(ctx); - - if (!drv) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - screen = VL_VA_PSCREEN(ctx); - - if (!screen) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - surf = handle_table_get(drv->htab, surface); - - if (!surf || !surf->buffer) - return VA_STATUS_ERROR_INVALID_SURFACE; - - if (surf->buffer->interlaced) - return VA_STATUS_ERROR_OPERATION_FAILED; - - surfaces = surf->buffer->get_surfaces(surf->buffer); - if (!surfaces || !surfaces[0]->texture) - return VA_STATUS_ERROR_ALLOCATION_FAILED; - - img = CALLOC(1, sizeof(VAImage)); - if (!img) - return VA_STATUS_ERROR_ALLOCATION_FAILED; - - img->format.fourcc = PipeFormatToVaFourcc(surf->buffer->buffer_format); - img->buf = VA_INVALID_ID; - /* Use the visible dimensions. */ - img->width = surf->templat.width; - img->height = surf->templat.height; - img->num_palette_entries = 0; - img->entry_bytes = 0; - /* Image data size is computed using internal dimensions. */ - w = align(surf->buffer->width, 2); - h = align(surf->buffer->height, 2); - - for (i = 0; i < ARRAY_SIZE(formats); ++i) { - if (img->format.fourcc == formats[i].fourcc) { - img->format = formats[i]; - break; - } - } - - mtx_lock(&drv->mutex); - if (screen->resource_get_info) { - screen->resource_get_info(screen, surfaces[0]->texture, &stride, - &offset); - if (!stride) - offset = 0; - } - - switch (img->format.fourcc) { - case VA_FOURCC('U','Y','V','Y'): - case VA_FOURCC('Y','U','Y','V'): - img->pitches[0] = stride > 0 ? stride : w * 2; - assert(img->pitches[0] >= (w * 2)); - break; - - case VA_FOURCC('B','G','R','A'): - case VA_FOURCC('R','G','B','A'): - case VA_FOURCC('B','G','R','X'): - case VA_FOURCC('R','G','B','X'): - img->pitches[0] = stride > 0 ? stride : w * 4; - assert(img->pitches[0] >= (w * 4)); - break; - - default: - /* VaDeriveImage only supports contiguous planes. But there is now a - more generic api vlVaExportSurfaceHandle. */ - FREE(img); - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_OPERATION_FAILED; - } - - img->num_planes = 1; - img->offsets[0] = offset; - img->data_size = img->pitches[0] * h; - - img_buf = CALLOC(1, sizeof(vlVaBuffer)); - if (!img_buf) { - FREE(img); - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_ALLOCATION_FAILED; - } - - img->image_id = handle_table_add(drv->htab, img); - - img_buf->type = VAImageBufferType; - img_buf->size = img->data_size; - img_buf->num_elements = 1; - - pipe_resource_reference(&img_buf->derived_surface.resource, surfaces[0]->texture); - - img->buf = handle_table_add(VL_VA_DRIVER(ctx)->htab, img_buf); - mtx_unlock(&drv->mutex); - - *image = *img; - - return VA_STATUS_SUCCESS; -} - -VAStatus -vlVaDestroyImage(VADriverContextP ctx, VAImageID image) -{ - vlVaDriver *drv; - VAImage *vaimage; - VAStatus status; - - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - drv = VL_VA_DRIVER(ctx); - mtx_lock(&drv->mutex); - vaimage = handle_table_get(drv->htab, image); - if (!vaimage) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_INVALID_IMAGE; - } - - handle_table_remove(VL_VA_DRIVER(ctx)->htab, image); - mtx_unlock(&drv->mutex); - status = vlVaDestroyBuffer(ctx, vaimage->buf); - FREE(vaimage); - return status; -} - -VAStatus -vlVaSetImagePalette(VADriverContextP ctx, VAImageID image, unsigned char *palette) -{ - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - return VA_STATUS_ERROR_UNIMPLEMENTED; -} - -VAStatus -vlVaGetImage(VADriverContextP ctx, VASurfaceID surface, int x, int y, - unsigned int width, unsigned int height, VAImageID image) -{ - vlVaDriver *drv; - vlVaSurface *surf; - vlVaBuffer *img_buf; - VAImage *vaimage; - struct pipe_sampler_view **views; - enum pipe_format format; - bool convert = false; - void *data[3]; - unsigned pitches[3], i, j; - - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - drv = VL_VA_DRIVER(ctx); - - mtx_lock(&drv->mutex); - surf = handle_table_get(drv->htab, surface); - if (!surf || !surf->buffer) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_INVALID_SURFACE; - } - - vaimage = handle_table_get(drv->htab, image); - if (!vaimage) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_INVALID_IMAGE; - } - - if (x < 0 || y < 0) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_INVALID_PARAMETER; - } - - if (x + width > surf->templat.width || - y + height > surf->templat.height) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_INVALID_PARAMETER; - } - - if (width > vaimage->width || - height > vaimage->height) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_INVALID_PARAMETER; - } - - img_buf = handle_table_get(drv->htab, vaimage->buf); - if (!img_buf) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_INVALID_BUFFER; - } - - format = VaFourccToPipeFormat(vaimage->format.fourcc); - if (format == PIPE_FORMAT_NONE) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_OPERATION_FAILED; - } - - - if (format != surf->buffer->buffer_format) { - /* support NV12 to YV12 and IYUV conversion now only */ - if ((format == PIPE_FORMAT_YV12 && - surf->buffer->buffer_format == PIPE_FORMAT_NV12) || - (format == PIPE_FORMAT_IYUV && - surf->buffer->buffer_format == PIPE_FORMAT_NV12)) - convert = true; - else if (format == PIPE_FORMAT_NV12 && - (surf->buffer->buffer_format == PIPE_FORMAT_P010 || - surf->buffer->buffer_format == PIPE_FORMAT_P016)) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_OPERATION_FAILED; - } - else { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_OPERATION_FAILED; - } - } - - views = surf->buffer->get_sampler_view_planes(surf->buffer); - if (!views) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_OPERATION_FAILED; - } - - for (i = 0; i < vaimage->num_planes; i++) { - data[i] = img_buf->data + vaimage->offsets[i]; - pitches[i] = vaimage->pitches[i]; - } - if (vaimage->format.fourcc == VA_FOURCC('I','4','2','0')) { - void *tmp_d; - unsigned tmp_p; - tmp_d = data[1]; - data[1] = data[2]; - data[2] = tmp_d; - tmp_p = pitches[1]; - pitches[1] = pitches[2]; - pitches[2] = tmp_p; - } - - for (i = 0; i < vaimage->num_planes; i++) { - unsigned box_w = align(width, 2); - unsigned box_h = align(height, 2); - unsigned box_x = x & ~1; - unsigned box_y = y & ~1; - if (!views[i]) continue; - vl_video_buffer_adjust_size(&box_w, &box_h, i, - pipe_format_to_chroma_format(surf->templat.buffer_format), - surf->templat.interlaced); - vl_video_buffer_adjust_size(&box_x, &box_y, i, - pipe_format_to_chroma_format(surf->templat.buffer_format), - surf->templat.interlaced); - for (j = 0; j < views[i]->texture->array_size; ++j) { - struct pipe_box box = {box_x, box_y, j, box_w, box_h, 1}; - struct pipe_transfer *transfer; - uint8_t *map; - map = drv->pipe->transfer_map(drv->pipe, views[i]->texture, 0, - PIPE_TRANSFER_READ, &box, &transfer); - if (!map) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_OPERATION_FAILED; - } - - if (i == 1 && convert) { - u_copy_nv12_to_yv12(data, pitches, i, j, - transfer->stride, views[i]->texture->array_size, - map, box.width, box.height); - } else { - util_copy_rect(data[i] + pitches[i] * j, - views[i]->texture->format, - pitches[i] * views[i]->texture->array_size, 0, 0, - box.width, box.height, map, transfer->stride, 0, 0); - } - pipe_transfer_unmap(drv->pipe, transfer); - } - } - mtx_unlock(&drv->mutex); - - return VA_STATUS_SUCCESS; -} - -VAStatus -vlVaPutImage(VADriverContextP ctx, VASurfaceID surface, VAImageID image, - int src_x, int src_y, unsigned int src_width, unsigned int src_height, - int dest_x, int dest_y, unsigned int dest_width, unsigned int dest_height) -{ - vlVaDriver *drv; - vlVaSurface *surf; - vlVaBuffer *img_buf; - VAImage *vaimage; - struct pipe_sampler_view **views; - enum pipe_format format; - void *data[3]; - unsigned pitches[3], i, j; - - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - drv = VL_VA_DRIVER(ctx); - mtx_lock(&drv->mutex); - - surf = handle_table_get(drv->htab, surface); - if (!surf || !surf->buffer) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_INVALID_SURFACE; - } - - vaimage = handle_table_get(drv->htab, image); - if (!vaimage) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_INVALID_IMAGE; - } - - img_buf = handle_table_get(drv->htab, vaimage->buf); - if (!img_buf) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_INVALID_BUFFER; - } - - if (img_buf->derived_surface.resource) { - /* Attempting to transfer derived image to surface */ - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_UNIMPLEMENTED; - } - - format = VaFourccToPipeFormat(vaimage->format.fourcc); - - if (format == PIPE_FORMAT_NONE) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_OPERATION_FAILED; - } - - if ((format != surf->buffer->buffer_format) && - ((format != PIPE_FORMAT_YV12) || (surf->buffer->buffer_format != PIPE_FORMAT_NV12)) && - ((format != PIPE_FORMAT_IYUV) || (surf->buffer->buffer_format != PIPE_FORMAT_NV12))) { - struct pipe_video_buffer *tmp_buf; - - surf->templat.buffer_format = format; - if (format == PIPE_FORMAT_YUYV || format == PIPE_FORMAT_UYVY || - format == PIPE_FORMAT_B8G8R8A8_UNORM || format == PIPE_FORMAT_B8G8R8X8_UNORM || - format == PIPE_FORMAT_R8G8B8A8_UNORM || format == PIPE_FORMAT_R8G8B8X8_UNORM) - surf->templat.interlaced = false; - tmp_buf = drv->pipe->create_video_buffer(drv->pipe, &surf->templat); - - if (!tmp_buf) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_ALLOCATION_FAILED; - } - - surf->buffer->destroy(surf->buffer); - surf->buffer = tmp_buf; - } - - views = surf->buffer->get_sampler_view_planes(surf->buffer); - if (!views) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_OPERATION_FAILED; - } - - for (i = 0; i < vaimage->num_planes; i++) { - data[i] = img_buf->data + vaimage->offsets[i]; - pitches[i] = vaimage->pitches[i]; - } - if (vaimage->format.fourcc == VA_FOURCC('I','4','2','0')) { - void *tmp_d; - unsigned tmp_p; - tmp_d = data[1]; - data[1] = data[2]; - data[2] = tmp_d; - tmp_p = pitches[1]; - pitches[1] = pitches[2]; - pitches[2] = tmp_p; - } - - for (i = 0; i < vaimage->num_planes; ++i) { - unsigned width, height; - struct pipe_resource *tex; - - if (!views[i]) continue; - tex = views[i]->texture; - - vlVaVideoSurfaceSize(surf, i, &width, &height); - for (j = 0; j < tex->array_size; ++j) { - struct pipe_box dst_box = {0, 0, j, width, height, 1}; - - if (((format == PIPE_FORMAT_YV12) || (format == PIPE_FORMAT_IYUV)) - && (surf->buffer->buffer_format == PIPE_FORMAT_NV12) - && i == 1) { - struct pipe_transfer *transfer = NULL; - uint8_t *map = NULL; - - map = drv->pipe->transfer_map(drv->pipe, - tex, - 0, - PIPE_TRANSFER_WRITE | - PIPE_TRANSFER_DISCARD_RANGE, - &dst_box, &transfer); - if (map == NULL) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_OPERATION_FAILED; - } - - u_copy_nv12_from_yv12((const void * const*) data, pitches, i, j, - transfer->stride, tex->array_size, - map, dst_box.width, dst_box.height); - pipe_transfer_unmap(drv->pipe, transfer); - } else { - drv->pipe->texture_subdata(drv->pipe, tex, 0, - PIPE_TRANSFER_WRITE, &dst_box, - data[i] + pitches[i] * j, - pitches[i] * views[i]->texture->array_size, 0); - } - } - } - mtx_unlock(&drv->mutex); - - return VA_STATUS_SUCCESS; -} diff --git a/src/gallium/state_trackers/va/meson.build b/src/gallium/state_trackers/va/meson.build deleted file mode 100644 index 1929d907b9d..00000000000 --- a/src/gallium/state_trackers/va/meson.build +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright © 2017-2019 Intel Corporation - -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: - -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. - -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -libva_version = dep_va.version().split('.') - -libva_st = static_library( - 'va_st', - files( - 'buffer.c', 'config.c', 'context.c', 'display.c', 'image.c', 'picture.c', - 'picture_mpeg12.c', 'picture_mpeg4.c', 'picture_h264.c', 'picture_hevc.c', - 'picture_vc1.c', 'picture_mjpeg.c', 'picture_vp9.c','postproc.c', - 'subpicture.c', 'surface.c', 'picture_h264_enc.c', 'picture_hevc_enc.c', - ), - c_args : [ - c_vis_args, - '-DVA_DRIVER_INIT_FUNC=__vaDriverInit_@0@_@1@'.format( - libva_version[0], libva_version[1] - ), - ], - include_directories : [inc_include, inc_src, inc_mapi, inc_mesa, inc_gallium, inc_gallium_aux], - dependencies : [ - dep_va_headers, dep_x11_xcb, dep_xcb, dep_xcb_dri2, dep_xcb_dri3, - dep_libdrm, - ], -) diff --git a/src/gallium/state_trackers/va/picture.c b/src/gallium/state_trackers/va/picture.c deleted file mode 100644 index d292594590c..00000000000 --- a/src/gallium/state_trackers/va/picture.c +++ /dev/null @@ -1,689 +0,0 @@ -/************************************************************************** - * - * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian. - * Copyright 2014 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include "pipe/p_video_codec.h" - -#include "util/u_handle_table.h" -#include "util/u_video.h" - -#include "vl/vl_vlc.h" -#include "vl/vl_winsys.h" - -#include "va_private.h" - -VAStatus -vlVaBeginPicture(VADriverContextP ctx, VAContextID context_id, VASurfaceID render_target) -{ - vlVaDriver *drv; - vlVaContext *context; - vlVaSurface *surf; - - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - drv = VL_VA_DRIVER(ctx); - if (!drv) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - mtx_lock(&drv->mutex); - context = handle_table_get(drv->htab, context_id); - if (!context) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_INVALID_CONTEXT; - } - - if (u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_MPEG12) { - context->desc.mpeg12.intra_matrix = NULL; - context->desc.mpeg12.non_intra_matrix = NULL; - } - - surf = handle_table_get(drv->htab, render_target); - mtx_unlock(&drv->mutex); - if (!surf || !surf->buffer) - return VA_STATUS_ERROR_INVALID_SURFACE; - - context->target_id = render_target; - surf->ctx = context_id; - context->target = surf->buffer; - context->mjpeg.sampling_factor = 0; - - if (!context->decoder) { - - /* VPP */ - if (context->templat.profile == PIPE_VIDEO_PROFILE_UNKNOWN && - context->target->buffer_format != PIPE_FORMAT_B8G8R8A8_UNORM && - context->target->buffer_format != PIPE_FORMAT_R8G8B8A8_UNORM && - context->target->buffer_format != PIPE_FORMAT_B8G8R8X8_UNORM && - context->target->buffer_format != PIPE_FORMAT_R8G8B8X8_UNORM && - context->target->buffer_format != PIPE_FORMAT_NV12 && - context->target->buffer_format != PIPE_FORMAT_P010 && - context->target->buffer_format != PIPE_FORMAT_P016) - return VA_STATUS_ERROR_UNIMPLEMENTED; - - return VA_STATUS_SUCCESS; - } - - if (context->decoder->entrypoint != PIPE_VIDEO_ENTRYPOINT_ENCODE) - context->needs_begin_frame = true; - - return VA_STATUS_SUCCESS; -} - -void -vlVaGetReferenceFrame(vlVaDriver *drv, VASurfaceID surface_id, - struct pipe_video_buffer **ref_frame) -{ - vlVaSurface *surf = handle_table_get(drv->htab, surface_id); - if (surf) - *ref_frame = surf->buffer; - else - *ref_frame = NULL; -} - -static VAStatus -handlePictureParameterBuffer(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) -{ - VAStatus vaStatus = VA_STATUS_SUCCESS; - - switch (u_reduce_video_profile(context->templat.profile)) { - case PIPE_VIDEO_FORMAT_MPEG12: - vlVaHandlePictureParameterBufferMPEG12(drv, context, buf); - break; - - case PIPE_VIDEO_FORMAT_MPEG4_AVC: - vlVaHandlePictureParameterBufferH264(drv, context, buf); - break; - - case PIPE_VIDEO_FORMAT_VC1: - vlVaHandlePictureParameterBufferVC1(drv, context, buf); - break; - - case PIPE_VIDEO_FORMAT_MPEG4: - vlVaHandlePictureParameterBufferMPEG4(drv, context, buf); - break; - - case PIPE_VIDEO_FORMAT_HEVC: - vlVaHandlePictureParameterBufferHEVC(drv, context, buf); - break; - - case PIPE_VIDEO_FORMAT_JPEG: - vlVaHandlePictureParameterBufferMJPEG(drv, context, buf); - break; - - case PIPE_VIDEO_FORMAT_VP9: - vlVaHandlePictureParameterBufferVP9(drv, context, buf); - break; - - default: - break; - } - - /* Create the decoder once max_references is known. */ - if (!context->decoder) { - enum pipe_video_format format = - u_reduce_video_profile(context->templat.profile); - - if (!context->target) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - if (context->templat.max_references == 0 && - format != PIPE_VIDEO_FORMAT_JPEG) - return VA_STATUS_ERROR_INVALID_BUFFER; - - if (format == PIPE_VIDEO_FORMAT_MPEG4_AVC) - context->templat.level = u_get_h264_level(context->templat.width, - context->templat.height, &context->templat.max_references); - - context->decoder = drv->pipe->create_video_codec(drv->pipe, - &context->templat); - - if (!context->decoder) - return VA_STATUS_ERROR_ALLOCATION_FAILED; - - context->needs_begin_frame = true; - } - - return vaStatus; -} - -static void -handleIQMatrixBuffer(vlVaContext *context, vlVaBuffer *buf) -{ - switch (u_reduce_video_profile(context->templat.profile)) { - case PIPE_VIDEO_FORMAT_MPEG12: - vlVaHandleIQMatrixBufferMPEG12(context, buf); - break; - - case PIPE_VIDEO_FORMAT_MPEG4_AVC: - vlVaHandleIQMatrixBufferH264(context, buf); - break; - - case PIPE_VIDEO_FORMAT_MPEG4: - vlVaHandleIQMatrixBufferMPEG4(context, buf); - break; - - case PIPE_VIDEO_FORMAT_HEVC: - vlVaHandleIQMatrixBufferHEVC(context, buf); - break; - - case PIPE_VIDEO_FORMAT_JPEG: - vlVaHandleIQMatrixBufferMJPEG(context, buf); - break; - - default: - break; - } -} - -static void -handleSliceParameterBuffer(vlVaContext *context, vlVaBuffer *buf) -{ - switch (u_reduce_video_profile(context->templat.profile)) { - case PIPE_VIDEO_FORMAT_MPEG12: - vlVaHandleSliceParameterBufferMPEG12(context, buf); - break; - - case PIPE_VIDEO_FORMAT_VC1: - vlVaHandleSliceParameterBufferVC1(context, buf); - break; - - case PIPE_VIDEO_FORMAT_MPEG4_AVC: - vlVaHandleSliceParameterBufferH264(context, buf); - break; - - case PIPE_VIDEO_FORMAT_MPEG4: - vlVaHandleSliceParameterBufferMPEG4(context, buf); - break; - - case PIPE_VIDEO_FORMAT_HEVC: - vlVaHandleSliceParameterBufferHEVC(context, buf); - break; - - case PIPE_VIDEO_FORMAT_JPEG: - vlVaHandleSliceParameterBufferMJPEG(context, buf); - break; - - case PIPE_VIDEO_FORMAT_VP9: - vlVaHandleSliceParameterBufferVP9(context, buf); - break; - - default: - break; - } -} - -static unsigned int -bufHasStartcode(vlVaBuffer *buf, unsigned int code, unsigned int bits) -{ - struct vl_vlc vlc = {0}; - int i; - - /* search the first 64 bytes for a startcode */ - vl_vlc_init(&vlc, 1, (const void * const*)&buf->data, &buf->size); - for (i = 0; i < 64 && vl_vlc_bits_left(&vlc) >= bits; ++i) { - if (vl_vlc_peekbits(&vlc, bits) == code) - return 1; - vl_vlc_eatbits(&vlc, 8); - vl_vlc_fillbits(&vlc); - } - - return 0; -} - -static void -handleVASliceDataBufferType(vlVaContext *context, vlVaBuffer *buf) -{ - enum pipe_video_format format; - unsigned num_buffers = 0; - void * const *buffers[3]; - unsigned sizes[3]; - static const uint8_t start_code_h264[] = { 0x00, 0x00, 0x01 }; - static const uint8_t start_code_h265[] = { 0x00, 0x00, 0x01 }; - static const uint8_t start_code_vc1[] = { 0x00, 0x00, 0x01, 0x0d }; - static const uint8_t eoi_jpeg[] = { 0xff, 0xd9 }; - - format = u_reduce_video_profile(context->templat.profile); - switch (format) { - case PIPE_VIDEO_FORMAT_MPEG4_AVC: - if (bufHasStartcode(buf, 0x000001, 24)) - break; - - buffers[num_buffers] = (void *const)&start_code_h264; - sizes[num_buffers++] = sizeof(start_code_h264); - break; - case PIPE_VIDEO_FORMAT_HEVC: - if (bufHasStartcode(buf, 0x000001, 24)) - break; - - buffers[num_buffers] = (void *const)&start_code_h265; - sizes[num_buffers++] = sizeof(start_code_h265); - break; - case PIPE_VIDEO_FORMAT_VC1: - if (bufHasStartcode(buf, 0x0000010d, 32) || - bufHasStartcode(buf, 0x0000010c, 32) || - bufHasStartcode(buf, 0x0000010b, 32)) - break; - - if (context->decoder->profile == PIPE_VIDEO_PROFILE_VC1_ADVANCED) { - buffers[num_buffers] = (void *const)&start_code_vc1; - sizes[num_buffers++] = sizeof(start_code_vc1); - } - break; - case PIPE_VIDEO_FORMAT_MPEG4: - if (bufHasStartcode(buf, 0x000001, 24)) - break; - - vlVaDecoderFixMPEG4Startcode(context); - buffers[num_buffers] = (void *)context->mpeg4.start_code; - sizes[num_buffers++] = context->mpeg4.start_code_size; - break; - case PIPE_VIDEO_FORMAT_JPEG: - vlVaGetJpegSliceHeader(context); - buffers[num_buffers] = (void *)context->mjpeg.slice_header; - sizes[num_buffers++] = context->mjpeg.slice_header_size; - break; - case PIPE_VIDEO_FORMAT_VP9: - vlVaDecoderVP9BitstreamHeader(context, buf); - break; - default: - break; - } - - buffers[num_buffers] = buf->data; - sizes[num_buffers] = buf->size; - ++num_buffers; - - if (format == PIPE_VIDEO_FORMAT_JPEG) { - buffers[num_buffers] = (void *const)&eoi_jpeg; - sizes[num_buffers++] = sizeof(eoi_jpeg); - } - - if (context->needs_begin_frame) { - context->decoder->begin_frame(context->decoder, context->target, - &context->desc.base); - context->needs_begin_frame = false; - } - context->decoder->decode_bitstream(context->decoder, context->target, &context->desc.base, - num_buffers, (const void * const*)buffers, sizes); -} - -static VAStatus -handleVAEncMiscParameterTypeRateControl(vlVaContext *context, VAEncMiscParameterBuffer *misc) -{ - VAStatus status = VA_STATUS_SUCCESS; - - switch (u_reduce_video_profile(context->templat.profile)) { - case PIPE_VIDEO_FORMAT_MPEG4_AVC: - status = vlVaHandleVAEncMiscParameterTypeRateControlH264(context, misc); - break; - - case PIPE_VIDEO_FORMAT_HEVC: - status = vlVaHandleVAEncMiscParameterTypeRateControlHEVC(context, misc); - break; - - default: - break; - } - - return status; -} - -static VAStatus -handleVAEncMiscParameterTypeFrameRate(vlVaContext *context, VAEncMiscParameterBuffer *misc) -{ - VAStatus status = VA_STATUS_SUCCESS; - - switch (u_reduce_video_profile(context->templat.profile)) { - case PIPE_VIDEO_FORMAT_MPEG4_AVC: - status = vlVaHandleVAEncMiscParameterTypeFrameRateH264(context, misc); - break; - - case PIPE_VIDEO_FORMAT_HEVC: - status = vlVaHandleVAEncMiscParameterTypeFrameRateHEVC(context, misc); - break; - - default: - break; - } - - return status; -} - -static VAStatus -handleVAEncSequenceParameterBufferType(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) -{ - VAStatus status = VA_STATUS_SUCCESS; - - switch (u_reduce_video_profile(context->templat.profile)) { - case PIPE_VIDEO_FORMAT_MPEG4_AVC: - status = vlVaHandleVAEncSequenceParameterBufferTypeH264(drv, context, buf); - break; - - case PIPE_VIDEO_FORMAT_HEVC: - status = vlVaHandleVAEncSequenceParameterBufferTypeHEVC(drv, context, buf); - break; - - default: - break; - } - - return status; -} - -static VAStatus -handleVAEncMiscParameterBufferType(vlVaContext *context, vlVaBuffer *buf) -{ - VAStatus vaStatus = VA_STATUS_SUCCESS; - VAEncMiscParameterBuffer *misc; - misc = buf->data; - - switch (misc->type) { - case VAEncMiscParameterTypeRateControl: - vaStatus = handleVAEncMiscParameterTypeRateControl(context, misc); - break; - - case VAEncMiscParameterTypeFrameRate: - vaStatus = handleVAEncMiscParameterTypeFrameRate(context, misc); - break; - - default: - break; - } - - return vaStatus; -} - -static VAStatus -handleVAEncPictureParameterBufferType(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) -{ - VAStatus status = VA_STATUS_SUCCESS; - - switch (u_reduce_video_profile(context->templat.profile)) { - case PIPE_VIDEO_FORMAT_MPEG4_AVC: - status = vlVaHandleVAEncPictureParameterBufferTypeH264(drv, context, buf); - break; - - case PIPE_VIDEO_FORMAT_HEVC: - status = vlVaHandleVAEncPictureParameterBufferTypeHEVC(drv, context, buf); - break; - - default: - break; - } - - return status; -} - -static VAStatus -handleVAEncSliceParameterBufferType(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) -{ - VAStatus status = VA_STATUS_SUCCESS; - - switch (u_reduce_video_profile(context->templat.profile)) { - case PIPE_VIDEO_FORMAT_MPEG4_AVC: - status = vlVaHandleVAEncSliceParameterBufferTypeH264(drv, context, buf); - break; - - case PIPE_VIDEO_FORMAT_HEVC: - status = vlVaHandleVAEncSliceParameterBufferTypeHEVC(drv, context, buf); - break; - - default: - break; - } - - return status; -} - -VAStatus -vlVaRenderPicture(VADriverContextP ctx, VAContextID context_id, VABufferID *buffers, int num_buffers) -{ - vlVaDriver *drv; - vlVaContext *context; - VAStatus vaStatus = VA_STATUS_SUCCESS; - - unsigned i; - - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - drv = VL_VA_DRIVER(ctx); - if (!drv) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - mtx_lock(&drv->mutex); - context = handle_table_get(drv->htab, context_id); - if (!context) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_INVALID_CONTEXT; - } - - for (i = 0; i < num_buffers; ++i) { - vlVaBuffer *buf = handle_table_get(drv->htab, buffers[i]); - if (!buf) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_INVALID_BUFFER; - } - - switch (buf->type) { - case VAPictureParameterBufferType: - vaStatus = handlePictureParameterBuffer(drv, context, buf); - break; - - case VAIQMatrixBufferType: - handleIQMatrixBuffer(context, buf); - break; - - case VASliceParameterBufferType: - handleSliceParameterBuffer(context, buf); - break; - - case VASliceDataBufferType: - handleVASliceDataBufferType(context, buf); - break; - case VAProcPipelineParameterBufferType: - vaStatus = vlVaHandleVAProcPipelineParameterBufferType(drv, context, buf); - break; - - case VAEncSequenceParameterBufferType: - vaStatus = handleVAEncSequenceParameterBufferType(drv, context, buf); - break; - - case VAEncMiscParameterBufferType: - vaStatus = handleVAEncMiscParameterBufferType(context, buf); - break; - - case VAEncPictureParameterBufferType: - vaStatus = handleVAEncPictureParameterBufferType(drv, context, buf); - break; - - case VAEncSliceParameterBufferType: - vaStatus = handleVAEncSliceParameterBufferType(drv, context, buf); - break; - - case VAHuffmanTableBufferType: - vlVaHandleHuffmanTableBufferType(context, buf); - break; - - default: - break; - } - } - mtx_unlock(&drv->mutex); - - return vaStatus; -} - -VAStatus -vlVaEndPicture(VADriverContextP ctx, VAContextID context_id) -{ - vlVaDriver *drv; - vlVaContext *context; - vlVaBuffer *coded_buf; - vlVaSurface *surf; - void *feedback; - struct pipe_screen *screen; - bool supported; - bool realloc = false; - enum pipe_format format; - - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - drv = VL_VA_DRIVER(ctx); - if (!drv) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - mtx_lock(&drv->mutex); - context = handle_table_get(drv->htab, context_id); - mtx_unlock(&drv->mutex); - if (!context) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - if (!context->decoder) { - if (context->templat.profile != PIPE_VIDEO_PROFILE_UNKNOWN) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - /* VPP */ - return VA_STATUS_SUCCESS; - } - - mtx_lock(&drv->mutex); - surf = handle_table_get(drv->htab, context->target_id); - context->mpeg4.frame_num++; - - screen = context->decoder->context->screen; - supported = screen->get_video_param(screen, context->decoder->profile, - context->decoder->entrypoint, - surf->buffer->interlaced ? - PIPE_VIDEO_CAP_SUPPORTS_INTERLACED : - PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE); - - if (!supported) { - surf->templat.interlaced = screen->get_video_param(screen, - context->decoder->profile, - context->decoder->entrypoint, - PIPE_VIDEO_CAP_PREFERS_INTERLACED); - realloc = true; - } - - format = screen->get_video_param(screen, context->decoder->profile, - PIPE_VIDEO_ENTRYPOINT_BITSTREAM, - PIPE_VIDEO_CAP_PREFERED_FORMAT); - - if (surf->buffer->buffer_format != format && - surf->buffer->buffer_format == PIPE_FORMAT_NV12) { - /* check originally as NV12 only */ - surf->templat.buffer_format = format; - realloc = true; - } - - if (u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_JPEG && - surf->buffer->buffer_format == PIPE_FORMAT_NV12) { - if (context->mjpeg.sampling_factor == 0x211111 || - context->mjpeg.sampling_factor == 0x221212) { - surf->templat.buffer_format = PIPE_FORMAT_YUYV; - realloc = true; - } else if (context->mjpeg.sampling_factor != 0x221111) { - /* Not NV12 either */ - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_INVALID_SURFACE; - } - } - - if (realloc) { - struct pipe_video_buffer *old_buf = surf->buffer; - - if (vlVaHandleSurfaceAllocate(drv, surf, &surf->templat) != VA_STATUS_SUCCESS) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_ALLOCATION_FAILED; - } - - if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) { - if (old_buf->interlaced) { - struct u_rect src_rect, dst_rect; - - dst_rect.x0 = src_rect.x0 = 0; - dst_rect.y0 = src_rect.y0 = 0; - dst_rect.x1 = src_rect.x1 = surf->templat.width; - dst_rect.y1 = src_rect.y1 = surf->templat.height; - vl_compositor_yuv_deint_full(&drv->cstate, &drv->compositor, - old_buf, surf->buffer, - &src_rect, &dst_rect, VL_COMPOSITOR_WEAVE); - } else { - /* Can't convert from progressive to interlaced yet */ - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_INVALID_SURFACE; - } - } - - old_buf->destroy(old_buf); - context->target = surf->buffer; - } - - if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) { - coded_buf = context->coded_buf; - if (u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_MPEG4_AVC) { - getEncParamPresetH264(context); - context->desc.h264enc.frame_num_cnt++; - } else if (u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_HEVC) - getEncParamPresetH265(context); - context->decoder->begin_frame(context->decoder, context->target, &context->desc.base); - context->decoder->encode_bitstream(context->decoder, context->target, - coded_buf->derived_surface.resource, &feedback); - surf->feedback = feedback; - surf->coded_buf = coded_buf; - } - - context->decoder->end_frame(context->decoder, context->target, &context->desc.base); - if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE && - u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_MPEG4_AVC) { - int idr_period = context->desc.h264enc.gop_size / context->gop_coeff; - int p_remain_in_idr = idr_period - context->desc.h264enc.frame_num; - surf->frame_num_cnt = context->desc.h264enc.frame_num_cnt; - surf->force_flushed = false; - if (context->first_single_submitted) { - context->decoder->flush(context->decoder); - context->first_single_submitted = false; - surf->force_flushed = true; - } - if (p_remain_in_idr == 1) { - if ((context->desc.h264enc.frame_num_cnt % 2) != 0) { - context->decoder->flush(context->decoder); - context->first_single_submitted = true; - } - else - context->first_single_submitted = false; - surf->force_flushed = true; - } - } else if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE && - u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_HEVC) - context->desc.h265enc.frame_num++; - mtx_unlock(&drv->mutex); - return VA_STATUS_SUCCESS; -} diff --git a/src/gallium/state_trackers/va/picture_h264.c b/src/gallium/state_trackers/va/picture_h264.c deleted file mode 100644 index 883a94a2b52..00000000000 --- a/src/gallium/state_trackers/va/picture_h264.c +++ /dev/null @@ -1,171 +0,0 @@ - /************************************************************************** - * - * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian. - * Copyright 2014 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include "util/u_video.h" -#include "va_private.h" - -static void resetReferencePictureDesc(struct pipe_h264_picture_desc *h264, - unsigned int i) -{ - h264->ref[i] = NULL; - h264->frame_num_list[i] = 0; - h264->is_long_term[i] = 0; - h264->top_is_reference[i] = 0; - h264->bottom_is_reference[i] = 0; - h264->field_order_cnt_list[i][0] = 0; - h264->field_order_cnt_list[i][1] = 0; -} - -void vlVaHandlePictureParameterBufferH264(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) -{ - VAPictureParameterBufferH264 *h264 = buf->data; - unsigned int top_or_bottom_field; - unsigned i; - - assert(buf->size >= sizeof(VAPictureParameterBufferH264) && buf->num_elements == 1); - context->desc.h264.slice_count = 0; - /*CurrPic*/ - context->desc.h264.field_order_cnt[0] = h264->CurrPic.TopFieldOrderCnt; - context->desc.h264.field_order_cnt[1] = h264->CurrPic.BottomFieldOrderCnt; - /*ReferenceFrames[16]*/ - /*picture_width_in_mbs_minus1*/ - /*picture_height_in_mbs_minus1*/ - /*bit_depth_luma_minus8*/ - /*bit_depth_chroma_minus8*/ - context->desc.h264.num_ref_frames = h264->num_ref_frames; - /*chroma_format_idc*/ - /*residual_colour_transform_flag*/ - /*gaps_in_frame_num_value_allowed_flag*/ - context->desc.h264.pps->sps->frame_mbs_only_flag = - h264->seq_fields.bits.frame_mbs_only_flag; - context->desc.h264.pps->sps->mb_adaptive_frame_field_flag = - h264->seq_fields.bits.mb_adaptive_frame_field_flag; - context->desc.h264.pps->sps->direct_8x8_inference_flag = - h264->seq_fields.bits.direct_8x8_inference_flag; - /*MinLumaBiPredSize8x8*/ - context->desc.h264.pps->sps->log2_max_frame_num_minus4 = - h264->seq_fields.bits.log2_max_frame_num_minus4; - context->desc.h264.pps->sps->pic_order_cnt_type = - h264->seq_fields.bits.pic_order_cnt_type; - context->desc.h264.pps->sps->log2_max_pic_order_cnt_lsb_minus4 = - h264->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4; - context->desc.h264.pps->sps->delta_pic_order_always_zero_flag = - h264->seq_fields.bits.delta_pic_order_always_zero_flag; - /*num_slice_groups_minus1*/ - /*slice_group_map_type*/ - /*slice_group_change_rate_minus1*/ - context->desc.h264.pps->pic_init_qp_minus26 = - h264->pic_init_qp_minus26; - /*pic_init_qs_minus26*/ - context->desc.h264.pps->chroma_qp_index_offset = - h264->chroma_qp_index_offset; - context->desc.h264.pps->second_chroma_qp_index_offset = - h264->second_chroma_qp_index_offset; - context->desc.h264.pps->entropy_coding_mode_flag = - h264->pic_fields.bits.entropy_coding_mode_flag; - context->desc.h264.pps->weighted_pred_flag = - h264->pic_fields.bits.weighted_pred_flag; - context->desc.h264.pps->weighted_bipred_idc = - h264->pic_fields.bits.weighted_bipred_idc; - context->desc.h264.pps->transform_8x8_mode_flag = - h264->pic_fields.bits.transform_8x8_mode_flag; - context->desc.h264.field_pic_flag = - h264->pic_fields.bits.field_pic_flag; - context->desc.h264.pps->constrained_intra_pred_flag = - h264->pic_fields.bits.constrained_intra_pred_flag; - context->desc.h264.pps->bottom_field_pic_order_in_frame_present_flag = - h264->pic_fields.bits.pic_order_present_flag; - context->desc.h264.pps->deblocking_filter_control_present_flag = - h264->pic_fields.bits.deblocking_filter_control_present_flag; - context->desc.h264.pps->redundant_pic_cnt_present_flag = - h264->pic_fields.bits.redundant_pic_cnt_present_flag; - /*reference_pic_flag*/ - context->desc.h264.frame_num = h264->frame_num; - context->desc.h264.is_reference = h264->pic_fields.bits.reference_pic_flag; - context->desc.h264.bottom_field_flag = - h264->pic_fields.bits.field_pic_flag && - (h264->CurrPic.flags & VA_PICTURE_H264_BOTTOM_FIELD) != 0; - - if (!context->decoder && context->desc.h264.num_ref_frames > 0) - context->templat.max_references = MIN2(context->desc.h264.num_ref_frames, 16); - - for (i = 0; i < context->templat.max_references; ++i) { - if ((h264->ReferenceFrames[i].flags & VA_PICTURE_H264_INVALID) || - (h264->ReferenceFrames[i].picture_id == VA_INVALID_SURFACE)) { - resetReferencePictureDesc(&context->desc.h264, i); - break; - } - - vlVaGetReferenceFrame(drv, h264->ReferenceFrames[i].picture_id, &context->desc.h264.ref[i]); - context->desc.h264.frame_num_list[i] = h264->ReferenceFrames[i].frame_idx; - - top_or_bottom_field = h264->ReferenceFrames[i].flags & - (VA_PICTURE_H264_TOP_FIELD | VA_PICTURE_H264_BOTTOM_FIELD); - context->desc.h264.is_long_term[i] = (h264->ReferenceFrames[i].flags & - (VA_PICTURE_H264_SHORT_TERM_REFERENCE | - VA_PICTURE_H264_LONG_TERM_REFERENCE)) != - VA_PICTURE_H264_SHORT_TERM_REFERENCE; - context->desc.h264.top_is_reference[i] = - !context->desc.h264.is_long_term[i] || - !!(h264->ReferenceFrames[i].flags & VA_PICTURE_H264_TOP_FIELD); - context->desc.h264.bottom_is_reference[i] = - !context->desc.h264.is_long_term[i] || - !!(h264->ReferenceFrames[i].flags & VA_PICTURE_H264_BOTTOM_FIELD); - context->desc.h264.field_order_cnt_list[i][0] = - top_or_bottom_field != VA_PICTURE_H264_BOTTOM_FIELD ? - h264->ReferenceFrames[i].TopFieldOrderCnt: INT_MAX; - context->desc.h264.field_order_cnt_list[i][1] = - top_or_bottom_field != VA_PICTURE_H264_TOP_FIELD ? - h264->ReferenceFrames[i].BottomFieldOrderCnt: INT_MAX; - } - - /* Make sure remaining elements are clean */ - for (; i < 16; ++i) - resetReferencePictureDesc(&context->desc.h264, i); -} - -void vlVaHandleIQMatrixBufferH264(vlVaContext *context, vlVaBuffer *buf) -{ - VAIQMatrixBufferH264 *h264 = buf->data; - - assert(buf->size >= sizeof(VAIQMatrixBufferH264) && buf->num_elements == 1); - memcpy(&context->desc.h264.pps->ScalingList4x4, h264->ScalingList4x4, 6 * 16); - memcpy(&context->desc.h264.pps->ScalingList8x8, h264->ScalingList8x8, 2 * 64); -} - -void vlVaHandleSliceParameterBufferH264(vlVaContext *context, vlVaBuffer *buf) -{ - VASliceParameterBufferH264 *h264 = buf->data; - - assert(buf->size >= sizeof(VASliceParameterBufferH264) && buf->num_elements == 1); - context->desc.h264.slice_count += buf->num_elements; - context->desc.h264.num_ref_idx_l0_active_minus1 = - h264->num_ref_idx_l0_active_minus1; - context->desc.h264.num_ref_idx_l1_active_minus1 = - h264->num_ref_idx_l1_active_minus1; -} diff --git a/src/gallium/state_trackers/va/picture_h264_enc.c b/src/gallium/state_trackers/va/picture_h264_enc.c deleted file mode 100644 index 8ee27d2cb29..00000000000 --- a/src/gallium/state_trackers/va/picture_h264_enc.c +++ /dev/null @@ -1,210 +0,0 @@ -/************************************************************************** - * - * Copyright 2018 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include "util/u_handle_table.h" -#include "util/u_video.h" -#include "va_private.h" - -VAStatus -vlVaHandleVAEncPictureParameterBufferTypeH264(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) -{ - VAEncPictureParameterBufferH264 *h264; - vlVaBuffer *coded_buf; - - h264 = buf->data; - context->desc.h264enc.frame_num = h264->frame_num; - context->desc.h264enc.not_referenced = false; - context->desc.h264enc.pic_order_cnt = h264->CurrPic.TopFieldOrderCnt; - if (context->desc.h264enc.gop_cnt == 0) - context->desc.h264enc.i_remain = context->gop_coeff; - else if (context->desc.h264enc.frame_num == 1) - context->desc.h264enc.i_remain--; - - context->desc.h264enc.p_remain = context->desc.h264enc.gop_size - context->desc.h264enc.gop_cnt - context->desc.h264enc.i_remain; - - coded_buf = handle_table_get(drv->htab, h264->coded_buf); - if (!coded_buf->derived_surface.resource) - coded_buf->derived_surface.resource = pipe_buffer_create(drv->pipe->screen, PIPE_BIND_VERTEX_BUFFER, - PIPE_USAGE_STREAM, coded_buf->size); - context->coded_buf = coded_buf; - - _mesa_hash_table_insert(context->desc.h264enc.frame_idx, - UINT_TO_PTR(h264->CurrPic.picture_id), - UINT_TO_PTR(h264->frame_num)); - - if (h264->pic_fields.bits.idr_pic_flag == 1) - context->desc.h264enc.picture_type = PIPE_H264_ENC_PICTURE_TYPE_IDR; - else - context->desc.h264enc.picture_type = PIPE_H264_ENC_PICTURE_TYPE_P; - - context->desc.h264enc.quant_i_frames = h264->pic_init_qp; - context->desc.h264enc.quant_b_frames = h264->pic_init_qp; - context->desc.h264enc.quant_p_frames = h264->pic_init_qp; - context->desc.h264enc.gop_cnt++; - if (context->desc.h264enc.gop_cnt == context->desc.h264enc.gop_size) - context->desc.h264enc.gop_cnt = 0; - - return VA_STATUS_SUCCESS; -} - -VAStatus -vlVaHandleVAEncSliceParameterBufferTypeH264(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) -{ - VAEncSliceParameterBufferH264 *h264; - - h264 = buf->data; - context->desc.h264enc.ref_idx_l0 = VA_INVALID_ID; - context->desc.h264enc.ref_idx_l1 = VA_INVALID_ID; - - for (int i = 0; i < 32; i++) { - if (h264->RefPicList0[i].picture_id != VA_INVALID_ID) { - if (context->desc.h264enc.ref_idx_l0 == VA_INVALID_ID) - context->desc.h264enc.ref_idx_l0 = PTR_TO_UINT(util_hash_table_get(context->desc.h264enc.frame_idx, - UINT_TO_PTR(h264->RefPicList0[i].picture_id))); - } - if (h264->RefPicList1[i].picture_id != VA_INVALID_ID && h264->slice_type == 1) { - if (context->desc.h264enc.ref_idx_l1 == VA_INVALID_ID) - context->desc.h264enc.ref_idx_l1 = PTR_TO_UINT(util_hash_table_get(context->desc.h264enc.frame_idx, - UINT_TO_PTR(h264->RefPicList1[i].picture_id))); - } - } - - if (h264->slice_type == 1) - context->desc.h264enc.picture_type = PIPE_H264_ENC_PICTURE_TYPE_B; - else if (h264->slice_type == 0) - context->desc.h264enc.picture_type = PIPE_H264_ENC_PICTURE_TYPE_P; - else if (h264->slice_type == 2) { - if (context->desc.h264enc.picture_type == PIPE_H264_ENC_PICTURE_TYPE_IDR) - context->desc.h264enc.idr_pic_id++; - else - context->desc.h264enc.picture_type = PIPE_H264_ENC_PICTURE_TYPE_I; - } else - context->desc.h264enc.picture_type = PIPE_H264_ENC_PICTURE_TYPE_SKIP; - - return VA_STATUS_SUCCESS; -} - -VAStatus -vlVaHandleVAEncSequenceParameterBufferTypeH264(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) -{ - VAEncSequenceParameterBufferH264 *h264 = (VAEncSequenceParameterBufferH264 *)buf->data; - if (!context->decoder) { - context->templat.max_references = h264->max_num_ref_frames; - context->templat.level = h264->level_idc; - context->decoder = drv->pipe->create_video_codec(drv->pipe, &context->templat); - if (!context->decoder) - return VA_STATUS_ERROR_ALLOCATION_FAILED; - } - - context->gop_coeff = ((1024 + h264->intra_idr_period - 1) / h264->intra_idr_period + 1) / 2 * 2; - if (context->gop_coeff > VL_VA_ENC_GOP_COEFF) - context->gop_coeff = VL_VA_ENC_GOP_COEFF; - context->desc.h264enc.gop_size = h264->intra_idr_period * context->gop_coeff; - context->desc.h264enc.rate_ctrl.frame_rate_num = h264->time_scale / 2; - context->desc.h264enc.rate_ctrl.frame_rate_den = h264->num_units_in_tick; - context->desc.h264enc.pic_order_cnt_type = h264->seq_fields.bits.pic_order_cnt_type; - - if (h264->frame_cropping_flag) { - context->desc.h264enc.pic_ctrl.enc_frame_cropping_flag = h264->frame_cropping_flag; - context->desc.h264enc.pic_ctrl.enc_frame_crop_left_offset = h264->frame_crop_left_offset; - context->desc.h264enc.pic_ctrl.enc_frame_crop_right_offset = h264->frame_crop_right_offset; - context->desc.h264enc.pic_ctrl.enc_frame_crop_top_offset = h264->frame_crop_top_offset; - context->desc.h264enc.pic_ctrl.enc_frame_crop_bottom_offset = h264->frame_crop_bottom_offset; - } - return VA_STATUS_SUCCESS; -} - -VAStatus -vlVaHandleVAEncMiscParameterTypeRateControlH264(vlVaContext *context, VAEncMiscParameterBuffer *misc) -{ - VAEncMiscParameterRateControl *rc = (VAEncMiscParameterRateControl *)misc->data; - if (context->desc.h264enc.rate_ctrl.rate_ctrl_method == - PIPE_H264_ENC_RATE_CONTROL_METHOD_CONSTANT) - context->desc.h264enc.rate_ctrl.target_bitrate = rc->bits_per_second; - else - context->desc.h264enc.rate_ctrl.target_bitrate = rc->bits_per_second * (rc->target_percentage / 100.0); - context->desc.h264enc.rate_ctrl.peak_bitrate = rc->bits_per_second; - if (context->desc.h264enc.rate_ctrl.target_bitrate < 2000000) - context->desc.h264enc.rate_ctrl.vbv_buffer_size = MIN2((context->desc.h264enc.rate_ctrl.target_bitrate * 2.75), 2000000); - else - context->desc.h264enc.rate_ctrl.vbv_buffer_size = context->desc.h264enc.rate_ctrl.target_bitrate; - - return VA_STATUS_SUCCESS; -} - -VAStatus -vlVaHandleVAEncMiscParameterTypeFrameRateH264(vlVaContext *context, VAEncMiscParameterBuffer *misc) -{ - VAEncMiscParameterFrameRate *fr = (VAEncMiscParameterFrameRate *)misc->data; - if (fr->framerate & 0xffff0000) { - context->desc.h264enc.rate_ctrl.frame_rate_num = fr->framerate & 0xffff; - context->desc.h264enc.rate_ctrl.frame_rate_den = fr->framerate >> 16 & 0xffff; - } else { - context->desc.h264enc.rate_ctrl.frame_rate_num = fr->framerate; - context->desc.h264enc.rate_ctrl.frame_rate_den = 1; - } - return VA_STATUS_SUCCESS; -} - -void getEncParamPresetH264(vlVaContext *context) -{ - //motion estimation preset - context->desc.h264enc.motion_est.motion_est_quarter_pixel = 0x00000001; - context->desc.h264enc.motion_est.lsmvert = 0x00000002; - context->desc.h264enc.motion_est.enc_disable_sub_mode = 0x00000078; - context->desc.h264enc.motion_est.enc_en_ime_overw_dis_subm = 0x00000001; - context->desc.h264enc.motion_est.enc_ime_overw_dis_subm_no = 0x00000001; - context->desc.h264enc.motion_est.enc_ime2_search_range_x = 0x00000004; - context->desc.h264enc.motion_est.enc_ime2_search_range_y = 0x00000004; - - //pic control preset - context->desc.h264enc.pic_ctrl.enc_cabac_enable = 0x00000001; - context->desc.h264enc.pic_ctrl.enc_constraint_set_flags = 0x00000040; - - //rate control - context->desc.h264enc.rate_ctrl.vbv_buffer_size = 20000000; - context->desc.h264enc.rate_ctrl.vbv_buf_lv = 48; - context->desc.h264enc.rate_ctrl.fill_data_enable = 1; - context->desc.h264enc.rate_ctrl.enforce_hrd = 1; - context->desc.h264enc.enable_vui = false; - if (context->desc.h264enc.rate_ctrl.frame_rate_num == 0 || - context->desc.h264enc.rate_ctrl.frame_rate_den == 0) { - context->desc.h264enc.rate_ctrl.frame_rate_num = 30; - context->desc.h264enc.rate_ctrl.frame_rate_den = 1; - } - context->desc.h264enc.rate_ctrl.target_bits_picture = - context->desc.h264enc.rate_ctrl.target_bitrate * - ((float)context->desc.h264enc.rate_ctrl.frame_rate_den / - context->desc.h264enc.rate_ctrl.frame_rate_num); - context->desc.h264enc.rate_ctrl.peak_bits_picture_integer = - context->desc.h264enc.rate_ctrl.peak_bitrate * - ((float)context->desc.h264enc.rate_ctrl.frame_rate_den / - context->desc.h264enc.rate_ctrl.frame_rate_num); - - context->desc.h264enc.rate_ctrl.peak_bits_picture_fraction = 0; - context->desc.h264enc.ref_pic_mode = 0x00000201; -} diff --git a/src/gallium/state_trackers/va/picture_hevc.c b/src/gallium/state_trackers/va/picture_hevc.c deleted file mode 100644 index e879259ae1f..00000000000 --- a/src/gallium/state_trackers/va/picture_hevc.c +++ /dev/null @@ -1,221 +0,0 @@ -/************************************************************************** - * - * Copyright 2014 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include "vl/vl_zscan.h" -#include "va_private.h" - -void vlVaHandlePictureParameterBufferHEVC(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) -{ - VAPictureParameterBufferHEVC *hevc = buf->data; - unsigned i; - - assert(buf->size >= sizeof(VAPictureParameterBufferHEVC) && buf->num_elements == 1); - context->desc.h265.pps->sps->chroma_format_idc = hevc->pic_fields.bits.chroma_format_idc; - context->desc.h265.pps->sps->separate_colour_plane_flag = - hevc->pic_fields.bits.separate_colour_plane_flag; - context->desc.h265.pps->sps->pic_width_in_luma_samples = hevc->pic_width_in_luma_samples; - context->desc.h265.pps->sps->pic_height_in_luma_samples = hevc->pic_height_in_luma_samples; - context->desc.h265.pps->sps->bit_depth_luma_minus8 = hevc->bit_depth_luma_minus8; - context->desc.h265.pps->sps->bit_depth_chroma_minus8 = hevc->bit_depth_chroma_minus8; - context->desc.h265.pps->sps->log2_max_pic_order_cnt_lsb_minus4 = - hevc->log2_max_pic_order_cnt_lsb_minus4; - context->desc.h265.pps->sps->sps_max_dec_pic_buffering_minus1 = - hevc->sps_max_dec_pic_buffering_minus1; - context->desc.h265.pps->sps->log2_min_luma_coding_block_size_minus3 = - hevc->log2_min_luma_coding_block_size_minus3; - context->desc.h265.pps->sps->log2_diff_max_min_luma_coding_block_size = - hevc->log2_diff_max_min_luma_coding_block_size; - context->desc.h265.pps->sps->log2_min_transform_block_size_minus2 = - hevc->log2_min_transform_block_size_minus2; - context->desc.h265.pps->sps->log2_diff_max_min_transform_block_size = - hevc->log2_diff_max_min_transform_block_size; - context->desc.h265.pps->sps->max_transform_hierarchy_depth_inter = - hevc->max_transform_hierarchy_depth_inter; - context->desc.h265.pps->sps->max_transform_hierarchy_depth_intra = - hevc->max_transform_hierarchy_depth_intra; - context->desc.h265.pps->sps->scaling_list_enabled_flag = - hevc->pic_fields.bits.scaling_list_enabled_flag; - context->desc.h265.pps->sps->amp_enabled_flag = hevc->pic_fields.bits.amp_enabled_flag; - context->desc.h265.pps->sps->sample_adaptive_offset_enabled_flag = - hevc->slice_parsing_fields.bits.sample_adaptive_offset_enabled_flag; - context->desc.h265.pps->sps->pcm_enabled_flag = hevc->pic_fields.bits.pcm_enabled_flag; - if (hevc->pic_fields.bits.pcm_enabled_flag == 1) { - context->desc.h265.pps->sps->pcm_sample_bit_depth_luma_minus1 = - hevc->pcm_sample_bit_depth_luma_minus1; - context->desc.h265.pps->sps->pcm_sample_bit_depth_chroma_minus1 = - hevc->pcm_sample_bit_depth_chroma_minus1; - context->desc.h265.pps->sps->log2_min_pcm_luma_coding_block_size_minus3 = - hevc->log2_min_pcm_luma_coding_block_size_minus3; - context->desc.h265.pps->sps->log2_diff_max_min_pcm_luma_coding_block_size = - hevc->log2_diff_max_min_pcm_luma_coding_block_size; - context->desc.h265.pps->sps->pcm_loop_filter_disabled_flag = - hevc->pic_fields.bits.pcm_loop_filter_disabled_flag; - } - context->desc.h265.pps->sps->num_short_term_ref_pic_sets = hevc->num_short_term_ref_pic_sets; - context->desc.h265.pps->sps->long_term_ref_pics_present_flag = - hevc->slice_parsing_fields.bits.long_term_ref_pics_present_flag; - context->desc.h265.pps->sps->num_long_term_ref_pics_sps = hevc->num_long_term_ref_pic_sps; - context->desc.h265.pps->sps->sps_temporal_mvp_enabled_flag = - hevc->slice_parsing_fields.bits.sps_temporal_mvp_enabled_flag; - context->desc.h265.pps->sps->strong_intra_smoothing_enabled_flag = - hevc->pic_fields.bits.strong_intra_smoothing_enabled_flag; - - context->desc.h265.pps->dependent_slice_segments_enabled_flag = - hevc->slice_parsing_fields.bits.dependent_slice_segments_enabled_flag; - context->desc.h265.pps->output_flag_present_flag = - hevc->slice_parsing_fields.bits.output_flag_present_flag; - context->desc.h265.pps->num_extra_slice_header_bits = hevc->num_extra_slice_header_bits; - context->desc.h265.pps->sign_data_hiding_enabled_flag = - hevc->pic_fields.bits.sign_data_hiding_enabled_flag; - context->desc.h265.pps->cabac_init_present_flag = - hevc->slice_parsing_fields.bits.cabac_init_present_flag; - context->desc.h265.pps->num_ref_idx_l0_default_active_minus1 = - hevc->num_ref_idx_l0_default_active_minus1; - context->desc.h265.pps->num_ref_idx_l1_default_active_minus1 = - hevc->num_ref_idx_l1_default_active_minus1; - context->desc.h265.pps->init_qp_minus26 = hevc->init_qp_minus26; - context->desc.h265.pps->constrained_intra_pred_flag = - hevc->pic_fields.bits.constrained_intra_pred_flag; - context->desc.h265.pps->transform_skip_enabled_flag = - hevc->pic_fields.bits.transform_skip_enabled_flag; - context->desc.h265.pps->cu_qp_delta_enabled_flag = - hevc->pic_fields.bits.cu_qp_delta_enabled_flag; - context->desc.h265.pps->diff_cu_qp_delta_depth = hevc->diff_cu_qp_delta_depth; - context->desc.h265.pps->pps_cb_qp_offset = hevc->pps_cb_qp_offset; - context->desc.h265.pps->pps_cr_qp_offset = hevc->pps_cr_qp_offset; - context->desc.h265.pps->pps_slice_chroma_qp_offsets_present_flag = - hevc->slice_parsing_fields.bits.pps_slice_chroma_qp_offsets_present_flag; - context->desc.h265.pps->weighted_pred_flag = hevc->pic_fields.bits.weighted_pred_flag; - context->desc.h265.pps->weighted_bipred_flag = hevc->pic_fields.bits.weighted_bipred_flag; - context->desc.h265.pps->transquant_bypass_enabled_flag = - hevc->pic_fields.bits.transquant_bypass_enabled_flag; - context->desc.h265.pps->tiles_enabled_flag = hevc->pic_fields.bits.tiles_enabled_flag; - context->desc.h265.pps->entropy_coding_sync_enabled_flag = - hevc->pic_fields.bits.entropy_coding_sync_enabled_flag; - if (hevc->pic_fields.bits.tiles_enabled_flag == 1) { - context->desc.h265.pps->num_tile_columns_minus1 = hevc->num_tile_columns_minus1; - context->desc.h265.pps->num_tile_rows_minus1 = hevc->num_tile_rows_minus1; - for (i = 0 ; i < 19 ; i++) - context->desc.h265.pps->column_width_minus1[i] = hevc->column_width_minus1[i]; - for (i = 0 ; i < 21 ; i++) - context->desc.h265.pps->row_height_minus1[i] = hevc->row_height_minus1[i]; - context->desc.h265.pps->loop_filter_across_tiles_enabled_flag = - hevc->pic_fields.bits.loop_filter_across_tiles_enabled_flag; - } - context->desc.h265.pps->pps_loop_filter_across_slices_enabled_flag = - hevc->pic_fields.bits.pps_loop_filter_across_slices_enabled_flag; - context->desc.h265.pps->deblocking_filter_override_enabled_flag = - hevc->slice_parsing_fields.bits.deblocking_filter_override_enabled_flag; - context->desc.h265.pps->pps_deblocking_filter_disabled_flag = - hevc->slice_parsing_fields.bits.pps_disable_deblocking_filter_flag; - context->desc.h265.pps->pps_beta_offset_div2 = hevc->pps_beta_offset_div2; - context->desc.h265.pps->pps_tc_offset_div2 = hevc->pps_tc_offset_div2; - context->desc.h265.pps->lists_modification_present_flag = - hevc->slice_parsing_fields.bits.lists_modification_present_flag; - context->desc.h265.pps->log2_parallel_merge_level_minus2 = - hevc->log2_parallel_merge_level_minus2; - context->desc.h265.pps->slice_segment_header_extension_present_flag = - hevc->slice_parsing_fields.bits.slice_segment_header_extension_present_flag; - - context->desc.h265.IDRPicFlag = hevc->slice_parsing_fields.bits.IdrPicFlag; - context->desc.h265.RAPPicFlag = hevc->slice_parsing_fields.bits.RapPicFlag; - - context->desc.h265.CurrPicOrderCntVal = hevc->CurrPic.pic_order_cnt; - - for (i = 0 ; i < 8 ; i++) { - context->desc.h265.RefPicSetStCurrBefore[i] = 0xFF; - context->desc.h265.RefPicSetStCurrAfter[i] = 0xFF; - context->desc.h265.RefPicSetLtCurr[i] = 0xFF; - } - context->desc.h265.NumPocStCurrBefore = 0; - context->desc.h265.NumPocStCurrAfter = 0; - context->desc.h265.NumPocLtCurr = 0; - unsigned int iBefore = 0; - unsigned int iAfter = 0; - unsigned int iCurr = 0; - for (i = 0 ; i < 15 ; i++) { - context->desc.h265.PicOrderCntVal[i] = hevc->ReferenceFrames[i].pic_order_cnt; - - vlVaGetReferenceFrame(drv, hevc->ReferenceFrames[i].picture_id, &context->desc.h265.ref[i]); - - if ((hevc->ReferenceFrames[i].flags & VA_PICTURE_HEVC_RPS_ST_CURR_BEFORE) && (iBefore < 8)) { - context->desc.h265.RefPicSetStCurrBefore[iBefore++] = i; - context->desc.h265.NumPocStCurrBefore++; - } - if ((hevc->ReferenceFrames[i].flags & VA_PICTURE_HEVC_RPS_ST_CURR_AFTER) && (iAfter < 8)) { - context->desc.h265.RefPicSetStCurrAfter[iAfter++] = i; - context->desc.h265.NumPocStCurrAfter++; - } - if ((hevc->ReferenceFrames[i].flags & VA_PICTURE_HEVC_RPS_LT_CURR) && (iCurr < 8)) { - context->desc.h265.RefPicSetLtCurr[iCurr++] = i; - context->desc.h265.NumPocLtCurr++; - } - } -} - -void vlVaHandleIQMatrixBufferHEVC(vlVaContext *context, vlVaBuffer *buf) -{ - VAIQMatrixBufferHEVC *h265 = buf->data; - int i, j; - - assert(buf->size >= sizeof(VAIQMatrixBufferHEVC) && buf->num_elements == 1); - - for (i = 0; i < 6; i++) { - for (j = 0; j < 16; j++) - context->desc.h265.pps->sps->ScalingList4x4[i][j] = - h265->ScalingList4x4[i][vl_zscan_h265_up_right_diagonal_16[j]]; - - for (j = 0; j < 64; j++) { - context->desc.h265.pps->sps->ScalingList8x8[i][j] = - h265->ScalingList8x8[i][vl_zscan_h265_up_right_diagonal[j]]; - context->desc.h265.pps->sps->ScalingList16x16[i][j] = - h265->ScalingList16x16[i][vl_zscan_h265_up_right_diagonal[j]]; - - if (i < 2) - context->desc.h265.pps->sps->ScalingList32x32[i][j] = - h265->ScalingList32x32[i][vl_zscan_h265_up_right_diagonal[j]]; - } - - context->desc.h265.pps->sps->ScalingListDCCoeff16x16[i] = - h265->ScalingListDC16x16[i]; - if (i < 2) - context->desc.h265.pps->sps->ScalingListDCCoeff32x32[i] = - h265->ScalingListDC32x32[i]; - } -} - -void vlVaHandleSliceParameterBufferHEVC(vlVaContext *context, vlVaBuffer *buf) -{ - VASliceParameterBufferHEVC *h265 = buf->data; - - assert(buf->size >= sizeof(VASliceParameterBufferHEVC) && buf->num_elements == 1); - for (int i = 0 ; i < 2 ; i++) { - for (int j = 0 ; j < 15 ; j++) - context->desc.h265.RefPicList[i][j] = h265->RefPicList[i][j]; - } - context->desc.h265.UseRefPicList = true; -} diff --git a/src/gallium/state_trackers/va/picture_hevc_enc.c b/src/gallium/state_trackers/va/picture_hevc_enc.c deleted file mode 100644 index 510597753ce..00000000000 --- a/src/gallium/state_trackers/va/picture_hevc_enc.c +++ /dev/null @@ -1,213 +0,0 @@ -/************************************************************************** - * - * Copyright 2018 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include "util/u_handle_table.h" -#include "util/u_video.h" -#include "va_private.h" - -VAStatus -vlVaHandleVAEncPictureParameterBufferTypeHEVC(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) -{ - VAEncPictureParameterBufferHEVC *h265; - vlVaBuffer *coded_buf; - int i; - - h265 = buf->data; - context->desc.h265enc.decoded_curr_pic = h265->decoded_curr_pic.picture_id; - - for (i = 0; i < 15; i++) - context->desc.h265enc.reference_frames[i] = h265->reference_frames[i].picture_id; - - context->desc.h265enc.pic_order_cnt = h265->decoded_curr_pic.pic_order_cnt; - coded_buf = handle_table_get(drv->htab, h265->coded_buf); - - if (!coded_buf->derived_surface.resource) - coded_buf->derived_surface.resource = pipe_buffer_create(drv->pipe->screen, PIPE_BIND_VERTEX_BUFFER, - PIPE_USAGE_STREAM, coded_buf->size); - - context->coded_buf = coded_buf; - context->desc.h265enc.pic.log2_parallel_merge_level_minus2 = h265->log2_parallel_merge_level_minus2; - context->desc.h265enc.pic.nal_unit_type = h265->nal_unit_type; - context->desc.h265enc.rc.quant_i_frames = h265->pic_init_qp; - - switch(h265->pic_fields.bits.coding_type) { - case 1: - if (h265->pic_fields.bits.idr_pic_flag) - context->desc.h265enc.picture_type = PIPE_H265_ENC_PICTURE_TYPE_IDR; - else - context->desc.h265enc.picture_type = PIPE_H265_ENC_PICTURE_TYPE_I; - break; - case 2: - context->desc.h265enc.picture_type = PIPE_H265_ENC_PICTURE_TYPE_P; - break; - case 3: - case 4: - case 5: - return VA_STATUS_ERROR_UNIMPLEMENTED; //no b frame support - break; - } - - context->desc.h265enc.pic.constrained_intra_pred_flag = h265->pic_fields.bits.constrained_intra_pred_flag; - - _mesa_hash_table_insert(context->desc.h265enc.frame_idx, - UINT_TO_PTR(h265->decoded_curr_pic.picture_id), - UINT_TO_PTR(context->desc.h265enc.frame_num)); - - return VA_STATUS_SUCCESS; -} - -VAStatus -vlVaHandleVAEncSliceParameterBufferTypeHEVC(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) -{ - VAEncSliceParameterBufferHEVC *h265; - - h265 = buf->data; - context->desc.h265enc.ref_idx_l0 = VA_INVALID_ID; - context->desc.h265enc.ref_idx_l1 = VA_INVALID_ID; - - for (int i = 0; i < 15; i++) { - if (h265->ref_pic_list0[i].picture_id != VA_INVALID_ID) { - if (context->desc.h265enc.ref_idx_l0 == VA_INVALID_ID) - context->desc.h265enc.ref_idx_l0 = PTR_TO_UINT(util_hash_table_get(context->desc.h265enc.frame_idx, - UINT_TO_PTR(h265->ref_pic_list0[i].picture_id))); - } - if (h265->ref_pic_list1[i].picture_id != VA_INVALID_ID && h265->slice_type == 1) { - if (context->desc.h265enc.ref_idx_l1 == VA_INVALID_ID) - context->desc.h265enc.ref_idx_l1 = PTR_TO_UINT(util_hash_table_get(context->desc.h265enc.frame_idx, - UINT_TO_PTR(h265->ref_pic_list1[i].picture_id))); - } - } - - context->desc.h265enc.slice.max_num_merge_cand = h265->max_num_merge_cand; - context->desc.h265enc.slice.slice_cb_qp_offset = h265->slice_cb_qp_offset; - context->desc.h265enc.slice.slice_cr_qp_offset = h265->slice_cr_qp_offset; - context->desc.h265enc.slice.slice_beta_offset_div2 = h265->slice_beta_offset_div2; - context->desc.h265enc.slice.slice_tc_offset_div2 = h265->slice_tc_offset_div2; - context->desc.h265enc.slice.cabac_init_flag = h265->slice_fields.bits.cabac_init_flag; - context->desc.h265enc.slice.slice_deblocking_filter_disabled_flag = h265->slice_fields.bits.slice_deblocking_filter_disabled_flag; - context->desc.h265enc.slice.slice_loop_filter_across_slices_enabled_flag = h265->slice_fields.bits.slice_loop_filter_across_slices_enabled_flag; - - return VA_STATUS_SUCCESS; -} - -VAStatus -vlVaHandleVAEncSequenceParameterBufferTypeHEVC(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) -{ - VAEncSequenceParameterBufferHEVC *h265 = (VAEncSequenceParameterBufferHEVC *)buf->data; - - if (!context->decoder) { - context->templat.level = h265->general_level_idc; - context->decoder = drv->pipe->create_video_codec(drv->pipe, &context->templat); - - if (!context->decoder) - return VA_STATUS_ERROR_ALLOCATION_FAILED; - } - - context->desc.h265enc.seq.general_profile_idc = h265->general_profile_idc; - context->desc.h265enc.seq.general_level_idc = h265->general_level_idc; - context->desc.h265enc.seq.general_tier_flag = h265->general_tier_flag; - context->desc.h265enc.seq.intra_period = h265->intra_period; - context->desc.h265enc.seq.pic_width_in_luma_samples = h265->pic_width_in_luma_samples; - context->desc.h265enc.seq.pic_height_in_luma_samples = h265->pic_height_in_luma_samples; - context->desc.h265enc.seq.chroma_format_idc = h265->seq_fields.bits.chroma_format_idc; - context->desc.h265enc.seq.bit_depth_luma_minus8 = h265->seq_fields.bits.bit_depth_luma_minus8; - context->desc.h265enc.seq.bit_depth_chroma_minus8 = h265->seq_fields.bits.bit_depth_chroma_minus8; - context->desc.h265enc.seq.strong_intra_smoothing_enabled_flag = h265->seq_fields.bits.strong_intra_smoothing_enabled_flag; - context->desc.h265enc.seq.amp_enabled_flag = h265->seq_fields.bits.amp_enabled_flag; - context->desc.h265enc.seq.sample_adaptive_offset_enabled_flag = h265->seq_fields.bits.sample_adaptive_offset_enabled_flag; - context->desc.h265enc.seq.pcm_enabled_flag = h265->seq_fields.bits.pcm_enabled_flag; - context->desc.h265enc.seq.sps_temporal_mvp_enabled_flag = h265->seq_fields.bits.sps_temporal_mvp_enabled_flag; - context->desc.h265enc.seq.log2_min_luma_coding_block_size_minus3 = h265->log2_min_luma_coding_block_size_minus3; - context->desc.h265enc.seq.log2_diff_max_min_luma_coding_block_size = h265->log2_diff_max_min_luma_coding_block_size; - context->desc.h265enc.seq.log2_min_transform_block_size_minus2 = h265->log2_min_transform_block_size_minus2; - context->desc.h265enc.seq.log2_diff_max_min_transform_block_size = h265->log2_diff_max_min_transform_block_size; - context->desc.h265enc.seq.max_transform_hierarchy_depth_inter = h265->max_transform_hierarchy_depth_inter; - context->desc.h265enc.seq.max_transform_hierarchy_depth_intra = h265->max_transform_hierarchy_depth_intra; - context->desc.h265enc.rc.frame_rate_num = h265->vui_time_scale; - context->desc.h265enc.rc.frame_rate_den = h265->vui_num_units_in_tick; - - return VA_STATUS_SUCCESS; -} - -VAStatus -vlVaHandleVAEncMiscParameterTypeRateControlHEVC(vlVaContext *context, VAEncMiscParameterBuffer *misc) -{ - VAEncMiscParameterRateControl *rc = (VAEncMiscParameterRateControl *)misc->data; - - if (context->desc.h265enc.rc.rate_ctrl_method == - PIPE_H265_ENC_RATE_CONTROL_METHOD_CONSTANT) - context->desc.h265enc.rc.target_bitrate = rc->bits_per_second; - else - context->desc.h265enc.rc.target_bitrate = rc->bits_per_second * (rc->target_percentage / 100.0); - context->desc.h265enc.rc.peak_bitrate = rc->bits_per_second; - if (context->desc.h265enc.rc.target_bitrate < 2000000) - context->desc.h265enc.rc.vbv_buffer_size = MIN2((context->desc.h265enc.rc.target_bitrate * 2.75), 2000000); - else - context->desc.h265enc.rc.vbv_buffer_size = context->desc.h265enc.rc.target_bitrate; - - return VA_STATUS_SUCCESS; -} - -VAStatus -vlVaHandleVAEncMiscParameterTypeFrameRateHEVC(vlVaContext *context, VAEncMiscParameterBuffer *misc) -{ - VAEncMiscParameterFrameRate *fr = (VAEncMiscParameterFrameRate *)misc->data; - - if (fr->framerate & 0xffff0000) { - context->desc.h265enc.rc.frame_rate_num = fr->framerate & 0xffff; - context->desc.h265enc.rc.frame_rate_den = fr->framerate >> 16 & 0xffff; - } else { - context->desc.h265enc.rc.frame_rate_num = fr->framerate; - context->desc.h265enc.rc.frame_rate_den = 1; - } - - return VA_STATUS_SUCCESS; -} - -void getEncParamPresetH265(vlVaContext *context) -{ - //rate control - context->desc.h265enc.rc.vbv_buffer_size = 20000000; - context->desc.h265enc.rc.vbv_buf_lv = 48; - context->desc.h265enc.rc.fill_data_enable = 1; - context->desc.h265enc.rc.enforce_hrd = 1; - if (context->desc.h265enc.rc.frame_rate_num == 0 || - context->desc.h265enc.rc.frame_rate_den == 0) { - context->desc.h265enc.rc.frame_rate_num = 30; - context->desc.h265enc.rc.frame_rate_den = 1; - } - context->desc.h265enc.rc.target_bits_picture = - context->desc.h265enc.rc.target_bitrate * - ((float)context->desc.h265enc.rc.frame_rate_den / - context->desc.h265enc.rc.frame_rate_num); - context->desc.h265enc.rc.peak_bits_picture_integer = - context->desc.h265enc.rc.peak_bitrate * - ((float)context->desc.h265enc.rc.frame_rate_den / - context->desc.h265enc.rc.frame_rate_num); - - context->desc.h265enc.rc.peak_bits_picture_fraction = 0; -} diff --git a/src/gallium/state_trackers/va/picture_mjpeg.c b/src/gallium/state_trackers/va/picture_mjpeg.c deleted file mode 100644 index defb0b546de..00000000000 --- a/src/gallium/state_trackers/va/picture_mjpeg.c +++ /dev/null @@ -1,258 +0,0 @@ -/************************************************************************** - * - * Copyright 2017 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include "va_private.h" - -void vlVaHandlePictureParameterBufferMJPEG(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) -{ - VAPictureParameterBufferJPEGBaseline *mjpeg = buf->data; - unsigned sf; - int i; - - assert(buf->size >= sizeof(VAPictureParameterBufferJPEGBaseline) && buf->num_elements == 1); - - context->desc.mjpeg.picture_parameter.picture_width = mjpeg->picture_width; - context->desc.mjpeg.picture_parameter.picture_height = mjpeg->picture_height; - - for (i = 0; i < mjpeg->num_components; ++i) { - context->desc.mjpeg.picture_parameter.components[i].component_id = - mjpeg->components[i].component_id; - context->desc.mjpeg.picture_parameter.components[i].h_sampling_factor = - mjpeg->components[i].h_sampling_factor; - context->desc.mjpeg.picture_parameter.components[i].v_sampling_factor = - mjpeg->components[i].v_sampling_factor; - context->desc.mjpeg.picture_parameter.components[i].quantiser_table_selector = - mjpeg->components[i].quantiser_table_selector; - - sf = mjpeg->components[i].h_sampling_factor << 4 | mjpeg->components[i].v_sampling_factor; - context->mjpeg.sampling_factor <<= 8; - context->mjpeg.sampling_factor |= sf; - } - - context->desc.mjpeg.picture_parameter.num_components = mjpeg->num_components; -} - -void vlVaHandleIQMatrixBufferMJPEG(vlVaContext *context, vlVaBuffer *buf) -{ - VAIQMatrixBufferJPEGBaseline *mjpeg = buf->data; - - assert(buf->size >= sizeof(VAIQMatrixBufferJPEGBaseline) && buf->num_elements == 1); - - memcpy(&context->desc.mjpeg.quantization_table.load_quantiser_table, mjpeg->load_quantiser_table, 4); - memcpy(&context->desc.mjpeg.quantization_table.quantiser_table, mjpeg->quantiser_table, 4 * 64); -} - -void vlVaHandleHuffmanTableBufferType(vlVaContext *context, vlVaBuffer *buf) -{ - VAHuffmanTableBufferJPEGBaseline *mjpeg = buf->data; - int i; - - assert(buf->size >= sizeof(VASliceParameterBufferJPEGBaseline) && buf->num_elements == 1); - - for (i = 0; i < 2; ++i) { - context->desc.mjpeg.huffman_table.load_huffman_table[i] = mjpeg->load_huffman_table[i]; - - memcpy(&context->desc.mjpeg.huffman_table.table[i].num_dc_codes, - mjpeg->huffman_table[i].num_dc_codes, 16); - memcpy(&context->desc.mjpeg.huffman_table.table[i].dc_values, - mjpeg->huffman_table[i].dc_values, 12); - memcpy(&context->desc.mjpeg.huffman_table.table[i].num_ac_codes, - mjpeg->huffman_table[i].num_ac_codes, 16); - memcpy(&context->desc.mjpeg.huffman_table.table[i].ac_values, - mjpeg->huffman_table[i].ac_values, 162); - memcpy(&context->desc.mjpeg.huffman_table.table[i].pad, mjpeg->huffman_table[i].pad, 2); - } -} - -void vlVaHandleSliceParameterBufferMJPEG(vlVaContext *context, vlVaBuffer *buf) -{ - VASliceParameterBufferJPEGBaseline *mjpeg = buf->data; - int i; - - assert(buf->size >= sizeof(VASliceParameterBufferJPEGBaseline) && buf->num_elements == 1); - - context->desc.mjpeg.slice_parameter.slice_data_size = mjpeg->slice_data_size; - context->desc.mjpeg.slice_parameter.slice_data_offset = mjpeg->slice_data_offset; - context->desc.mjpeg.slice_parameter.slice_data_flag = mjpeg->slice_data_flag; - context->desc.mjpeg.slice_parameter.slice_horizontal_position = mjpeg->slice_horizontal_position; - context->desc.mjpeg.slice_parameter.slice_vertical_position = mjpeg->slice_vertical_position; - - for (i = 0; i < mjpeg->num_components; ++i) { - context->desc.mjpeg.slice_parameter.components[i].component_selector = - mjpeg->components[i].component_selector; - context->desc.mjpeg.slice_parameter.components[i].dc_table_selector = - mjpeg->components[i].dc_table_selector; - context->desc.mjpeg.slice_parameter.components[i].ac_table_selector = - mjpeg->components[i].ac_table_selector; - } - - context->desc.mjpeg.slice_parameter.num_components = mjpeg->num_components; - context->desc.mjpeg.slice_parameter.restart_interval = mjpeg->restart_interval; - context->desc.mjpeg.slice_parameter.num_mcus = mjpeg->num_mcus; -} - -void vlVaGetJpegSliceHeader(vlVaContext *context) -{ - int size = 0, saved_size, len_pos, i; - uint16_t *bs; - uint8_t *p = context->mjpeg.slice_header; - - /* SOI */ - p[size++] = 0xff; - p[size++] = 0xd8; - - /* DQT */ - p[size++] = 0xff; - p[size++] = 0xdb; - - len_pos = size++; - size++; - - for (i = 0; i < 4; ++i) { - if (context->desc.mjpeg.quantization_table.load_quantiser_table[i] == 0) - continue; - - p[size++] = i; - memcpy((p + size), &context->desc.mjpeg.quantization_table.quantiser_table[i], 64); - size += 64; - } - - bs = (uint16_t*)&p[len_pos]; - *bs = util_bswap16(size - 4); - - saved_size = size; - - /* DHT */ - p[size++] = 0xff; - p[size++] = 0xc4; - - len_pos = size++; - size++; - - for (i = 0; i < 2; ++i) { - int num = 0, j; - - if (context->desc.mjpeg.huffman_table.load_huffman_table[i] == 0) - continue; - - p[size++] = 0x00 | i; - memcpy((p + size), &context->desc.mjpeg.huffman_table.table[i].num_dc_codes, 16); - size += 16; - for (j = 0; j < 16; ++j) - num += context->desc.mjpeg.huffman_table.table[i].num_dc_codes[j]; - assert(num <= 12); - memcpy((p + size), &context->desc.mjpeg.huffman_table.table[i].dc_values, num); - size += num; - } - - for (i = 0; i < 2; ++i) { - int num = 0, j; - - if (context->desc.mjpeg.huffman_table.load_huffman_table[i] == 0) - continue; - - p[size++] = 0x10 | i; - memcpy((p + size), &context->desc.mjpeg.huffman_table.table[i].num_ac_codes, 16); - size += 16; - for (j = 0; j < 16; ++j) - num += context->desc.mjpeg.huffman_table.table[i].num_ac_codes[j]; - assert(num <= 162); - memcpy((p + size), &context->desc.mjpeg.huffman_table.table[i].ac_values, num); - size += num; - } - - bs = (uint16_t*)&p[len_pos]; - *bs = util_bswap16(size - saved_size - 2); - - saved_size = size; - - /* DRI */ - if (context->desc.mjpeg.slice_parameter.restart_interval) { - p[size++] = 0xff; - p[size++] = 0xdd; - p[size++] = 0x00; - p[size++] = 0x04; - bs = (uint16_t*)&p[size++]; - *bs = util_bswap16(context->desc.mjpeg.slice_parameter.restart_interval); - saved_size = ++size; - } - - /* SOF */ - p[size++] = 0xff; - p[size++] = 0xc0; - - len_pos = size++; - size++; - - p[size++] = 0x08; - - bs = (uint16_t*)&p[size++]; - *bs = util_bswap16(context->desc.mjpeg.picture_parameter.picture_height); - size++; - - bs = (uint16_t*)&p[size++]; - *bs = util_bswap16(context->desc.mjpeg.picture_parameter.picture_width); - size++; - - p[size++] = context->desc.mjpeg.picture_parameter.num_components; - - for (i = 0; i < context->desc.mjpeg.picture_parameter.num_components; ++i) { - p[size++] = context->desc.mjpeg.picture_parameter.components[i].component_id; - p[size++] = context->desc.mjpeg.picture_parameter.components[i].h_sampling_factor << 4 | - context->desc.mjpeg.picture_parameter.components[i].v_sampling_factor; - p[size++] = context->desc.mjpeg.picture_parameter.components[i].quantiser_table_selector; - } - - bs = (uint16_t*)&p[len_pos]; - *bs = util_bswap16(size - saved_size - 2); - - saved_size = size; - - /* SOS */ - p[size++] = 0xff; - p[size++] = 0xda; - - len_pos = size++; - size++; - - p[size++] = context->desc.mjpeg.slice_parameter.num_components; - - for (i = 0; i < context->desc.mjpeg.slice_parameter.num_components; ++i) { - p[size++] = context->desc.mjpeg.slice_parameter.components[i].component_selector; - p[size++] = context->desc.mjpeg.slice_parameter.components[i].dc_table_selector << 4 | - context->desc.mjpeg.slice_parameter.components[i].ac_table_selector; - } - - p[size++] = 0x00; - p[size++] = 0x3f; - p[size++] = 0x00; - - bs = (uint16_t*)&p[len_pos]; - *bs = util_bswap16(size - saved_size - 2); - - context->mjpeg.slice_header_size = size; -} diff --git a/src/gallium/state_trackers/va/picture_mpeg12.c b/src/gallium/state_trackers/va/picture_mpeg12.c deleted file mode 100644 index daf95f7403c..00000000000 --- a/src/gallium/state_trackers/va/picture_mpeg12.c +++ /dev/null @@ -1,112 +0,0 @@ -/************************************************************************** - * - * Copyright 2014 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include "va_private.h" - -const int reverse_inverse_zscan[] = -{ - /* Reverse inverse z scan pattern */ - 0, 2, 3, 9, 10, 20, 21, 35, - 1, 4, 8, 11, 19, 22, 34, 36, - 5, 7, 12, 18, 23, 33, 37, 48, - 6, 13, 17, 24, 32, 38, 47, 49, - 14, 16, 25, 31, 39, 46, 50, 57, - 15, 26, 30, 40, 45, 51, 56, 58, - 27, 29, 41, 44, 52, 55, 59, 62, - 28, 42, 43, 53, 54, 60, 61, 63, -}; - -void vlVaHandlePictureParameterBufferMPEG12(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) -{ - VAPictureParameterBufferMPEG2 *mpeg2 = buf->data; - - assert(buf->size >= sizeof(VAPictureParameterBufferMPEG2) && buf->num_elements == 1); - context->desc.mpeg12.num_slices = 0; - /*horizontal_size;*/ - /*vertical_size;*/ - vlVaGetReferenceFrame(drv, mpeg2->forward_reference_picture, &context->desc.mpeg12.ref[0]); - vlVaGetReferenceFrame(drv, mpeg2->backward_reference_picture, &context->desc.mpeg12.ref[1]); - context->desc.mpeg12.picture_coding_type = mpeg2->picture_coding_type; - context->desc.mpeg12.f_code[0][0] = ((mpeg2->f_code >> 12) & 0xf) - 1; - context->desc.mpeg12.f_code[0][1] = ((mpeg2->f_code >> 8) & 0xf) - 1; - context->desc.mpeg12.f_code[1][0] = ((mpeg2->f_code >> 4) & 0xf) - 1; - context->desc.mpeg12.f_code[1][1] = (mpeg2->f_code & 0xf) - 1; - context->desc.mpeg12.intra_dc_precision = - mpeg2->picture_coding_extension.bits.intra_dc_precision; - context->desc.mpeg12.picture_structure = - mpeg2->picture_coding_extension.bits.picture_structure; - context->desc.mpeg12.top_field_first = - mpeg2->picture_coding_extension.bits.top_field_first; - context->desc.mpeg12.frame_pred_frame_dct = - mpeg2->picture_coding_extension.bits.frame_pred_frame_dct; - context->desc.mpeg12.concealment_motion_vectors = - mpeg2->picture_coding_extension.bits.concealment_motion_vectors; - context->desc.mpeg12.q_scale_type = - mpeg2->picture_coding_extension.bits.q_scale_type; - context->desc.mpeg12.intra_vlc_format = - mpeg2->picture_coding_extension.bits.intra_vlc_format; - context->desc.mpeg12.alternate_scan = - mpeg2->picture_coding_extension.bits.alternate_scan; - /*repeat_first_field*/ - /*progressive_frame*/ - /*is_first_field*/ -} - -void vlVaHandleIQMatrixBufferMPEG12(vlVaContext *context, vlVaBuffer *buf) -{ - VAIQMatrixBufferMPEG2 *mpeg2 = buf->data; - static uint8_t temp_intra_matrix[64]; - static uint8_t temp_nonintra_matrix[64]; - - assert(buf->size >= sizeof(VAIQMatrixBufferMPEG2) && buf->num_elements == 1); - if (mpeg2->load_intra_quantiser_matrix) { - /* The quantiser matrix that VAAPI provides has been applied - with inverse z-scan. However, what we expect in MPEG2 - picture description is the original order. Therefore, - we need to reverse it back to its original order. - */ - for (int i = 0; i < 64; i++) - temp_intra_matrix[i] = - mpeg2->intra_quantiser_matrix[reverse_inverse_zscan[i]]; - context->desc.mpeg12.intra_matrix = temp_intra_matrix; - } else - context->desc.mpeg12.intra_matrix = NULL; - - if (mpeg2->load_non_intra_quantiser_matrix) { - for (int i = 0; i < 64; i++) - temp_nonintra_matrix[i] = - mpeg2->non_intra_quantiser_matrix[reverse_inverse_zscan[i]]; - context->desc.mpeg12.non_intra_matrix = temp_nonintra_matrix; - } else - context->desc.mpeg12.non_intra_matrix = NULL; -} - -void vlVaHandleSliceParameterBufferMPEG12(vlVaContext *context, vlVaBuffer *buf) -{ - assert(buf->size >= sizeof(VASliceParameterBufferMPEG2)); - context->desc.mpeg12.num_slices += buf->num_elements; -} diff --git a/src/gallium/state_trackers/va/picture_mpeg4.c b/src/gallium/state_trackers/va/picture_mpeg4.c deleted file mode 100644 index 82659ef7b20..00000000000 --- a/src/gallium/state_trackers/va/picture_mpeg4.c +++ /dev/null @@ -1,209 +0,0 @@ -/************************************************************************** - * - * Copyright 2014 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include "va_private.h" - -void vlVaHandlePictureParameterBufferMPEG4(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) -{ - static const uint8_t default_intra_quant_matrix[64] = { 0 }; - static const uint8_t default_non_intra_quant_matrix[64] = { 0 }; - - VAPictureParameterBufferMPEG4 *mpeg4 = buf->data; - unsigned i; - - assert(buf->size >= sizeof(VAPictureParameterBufferMPEG4) && buf->num_elements == 1); - - context->mpeg4.pps = *mpeg4; - - /* vop_width */ - /* vop_height */ - /* forward_reference_picture */ - /* backward_reference_picture */ - context->desc.mpeg4.short_video_header = - mpeg4->vol_fields.bits.short_video_header; - /* chroma_format */ - context->desc.mpeg4.interlaced = mpeg4->vol_fields.bits.interlaced; - /* obmc_disable */ - /* sprite_enable */ - /* sprite_warping_accuracy */ - context->desc.mpeg4.quant_type = mpeg4->vol_fields.bits.quant_type; - context->desc.mpeg4.quarter_sample = mpeg4->vol_fields.bits.quarter_sample; - /* data_partitioned */ - /* reversible_vlc */ - context->desc.mpeg4.resync_marker_disable = - mpeg4->vol_fields.bits.resync_marker_disable; - /* no_of_sprite_warping_points */ - /* sprite_trajectory_du */ - /* sprite_trajectory_dv */ - /* quant_precision */ - context->desc.mpeg4.vop_coding_type = mpeg4->vop_fields.bits.vop_coding_type; - /* backward_reference_vop_coding_type */ - /* vop_rounding_type */ - /* intra_dc_vlc_thr */ - context->desc.mpeg4.top_field_first = - mpeg4->vop_fields.bits.top_field_first; - context->desc.mpeg4.alternate_vertical_scan_flag = - mpeg4->vop_fields.bits.alternate_vertical_scan_flag; - context->desc.mpeg4.vop_fcode_forward = mpeg4->vop_fcode_forward; - context->desc.mpeg4.vop_fcode_backward = mpeg4->vop_fcode_backward; - context->desc.mpeg4.vop_time_increment_resolution = - mpeg4->vop_time_increment_resolution; - /* num_gobs_in_vop */ - /* num_macroblocks_in_gob */ - context->desc.mpeg4.trb[0] = mpeg4->TRB; - context->desc.mpeg4.trb[1] = mpeg4->TRB; - context->desc.mpeg4.trd[0] = mpeg4->TRD; - context->desc.mpeg4.trd[1] = mpeg4->TRD; - - /* default [non-]intra quant matrix because mpv does not set these - matrices */ - if (!context->desc.mpeg4.intra_matrix) - context->desc.mpeg4.intra_matrix = default_intra_quant_matrix; - if (!context->desc.mpeg4.non_intra_matrix) - context->desc.mpeg4.non_intra_matrix = default_non_intra_quant_matrix; - - vlVaGetReferenceFrame(drv, mpeg4->forward_reference_picture, &context->desc.mpeg4.ref[0]); - vlVaGetReferenceFrame(drv, mpeg4->backward_reference_picture, &context->desc.mpeg4.ref[1]); - - context->mpeg4.vti_bits = 0; - for (i = context->desc.mpeg4.vop_time_increment_resolution; i > 0; i /= 2) - ++context->mpeg4.vti_bits; -} - -void vlVaHandleIQMatrixBufferMPEG4(vlVaContext *context, vlVaBuffer *buf) -{ - VAIQMatrixBufferMPEG4 *mpeg4 = buf->data; - - assert(buf->size >= sizeof(VAIQMatrixBufferMPEG4) && buf->num_elements == 1); - if (mpeg4->load_intra_quant_mat) - context->desc.mpeg4.intra_matrix = mpeg4->intra_quant_mat; - else - context->desc.mpeg4.intra_matrix = NULL; - - if (mpeg4->load_non_intra_quant_mat) - context->desc.mpeg4.non_intra_matrix = mpeg4->non_intra_quant_mat; - else - context->desc.mpeg4.non_intra_matrix = NULL; -} - -void vlVaHandleSliceParameterBufferMPEG4(vlVaContext *context, vlVaBuffer *buf) -{ - VASliceParameterBufferMPEG4 *mpeg4 = buf->data; - - assert(buf->size >= sizeof(VASliceParameterBufferMPEG4) && buf->num_elements == 1); - context->mpeg4.quant_scale = mpeg4->quant_scale; -} - -struct bit_stream -{ - uint8_t *data; - unsigned int length; /* bits */ - unsigned int pos; /* bits */ -}; - -static inline void -write_bit(struct bit_stream *writer, unsigned int bit) -{ - assert(writer->length > (writer)->pos); - writer->data[writer->pos>>3] |= ((bit & 1)<<(7 - (writer->pos & 7))); - writer->pos++; -} - -static inline void -write_bits(struct bit_stream *writer, unsigned int bits, unsigned int len) -{ - int i; - assert(len <= sizeof(bits)*8); - for (i = len - 1; i >= 0; i--) - write_bit(writer, bits>>i); -} - -void vlVaDecoderFixMPEG4Startcode(vlVaContext *context) -{ - uint8_t vop[] = { 0x00, 0x00, 0x01, 0xb6, 0x00, 0x00, 0x00, 0x00, 0x00 }; - struct bit_stream bs_vop = {vop, sizeof(vop)*8, 32}; - unsigned int vop_time_inc; - int mod_time; - unsigned int vop_size; - unsigned int vop_coding_type = context->desc.mpeg4.vop_coding_type; - - context->mpeg4.start_code_size = 0; - memset(context->mpeg4.start_code, 0, sizeof(context->mpeg4.start_code)); - if (vop_coding_type+1 == PIPE_MPEG12_PICTURE_CODING_TYPE_I) { - unsigned int vop_time = context->mpeg4.frame_num/ - context->desc.mpeg4.vop_time_increment_resolution; - unsigned int vop_hour = vop_time / 3600; - unsigned int vop_minute = (vop_time / 60) % 60; - unsigned int vop_second = vop_time % 60; - uint8_t group_of_vop[] = { 0x00, 0x00, 0x01, 0xb3, 0x00, 0x00, 0x00 }; - struct bit_stream bs_gvop = {group_of_vop, sizeof(group_of_vop)*8, 32}; - - write_bits(&bs_gvop, vop_hour, 5); - write_bits(&bs_gvop, vop_minute, 6); - write_bit(&bs_gvop, 1); /* marker_bit */ - write_bits(&bs_gvop, vop_second, 6); - write_bit(&bs_gvop, 0); /* closed_gov */ /* TODO replace magic */ - write_bit(&bs_gvop, 0); /* broken_link */ - write_bit(&bs_gvop, 0); /* padding */ - write_bits(&bs_gvop, 7, 3); /* padding */ - - memcpy(context->mpeg4.start_code, group_of_vop, sizeof(group_of_vop)); - context->mpeg4.start_code_size += sizeof(group_of_vop); - } - - write_bits(&bs_vop, vop_coding_type, 2); - mod_time = context->mpeg4.frame_num % - context->desc.mpeg4.vop_time_increment_resolution == 0 && - vop_coding_type+1 != PIPE_MPEG12_PICTURE_CODING_TYPE_I; - while (mod_time--) - write_bit(&bs_vop, 1); /* modulo_time_base */ - write_bit(&bs_vop, 0); /* modulo_time_base */ - - write_bit(&bs_vop, 1); /* marker_bit */ - vop_time_inc = context->mpeg4.frame_num % - context->desc.mpeg4.vop_time_increment_resolution; - write_bits(&bs_vop, vop_time_inc, context->mpeg4.vti_bits); - write_bit(&bs_vop, 1); /* marker_bit */ - write_bit(&bs_vop, 1); /* vop_coded */ - if (vop_coding_type+1 == PIPE_MPEG12_PICTURE_CODING_TYPE_P) - write_bit(&bs_vop, context->mpeg4.pps.vop_fields.bits.vop_rounding_type); - write_bits(&bs_vop, context->mpeg4.pps.vop_fields.bits.intra_dc_vlc_thr, 3); - if (context->mpeg4.pps.vol_fields.bits.interlaced) { - write_bit(&bs_vop, context->mpeg4.pps.vop_fields.bits.top_field_first); - write_bit(&bs_vop, context->mpeg4.pps.vop_fields.bits.alternate_vertical_scan_flag); - } - - write_bits(&bs_vop, context->mpeg4.quant_scale, context->mpeg4.pps.quant_precision); - if (vop_coding_type+1 != PIPE_MPEG12_PICTURE_CODING_TYPE_I) - write_bits(&bs_vop, context->desc.mpeg4.vop_fcode_forward, 3); - if (vop_coding_type+1 == PIPE_MPEG12_PICTURE_CODING_TYPE_B) - write_bits(&bs_vop, context->desc.mpeg4.vop_fcode_backward, 3); - - vop_size = bs_vop.pos/8; - memcpy(context->mpeg4.start_code + context->mpeg4.start_code_size, vop, vop_size); - context->mpeg4.start_code_size += vop_size; -} diff --git a/src/gallium/state_trackers/va/picture_vc1.c b/src/gallium/state_trackers/va/picture_vc1.c deleted file mode 100644 index 6ad1571ca96..00000000000 --- a/src/gallium/state_trackers/va/picture_vc1.c +++ /dev/null @@ -1,74 +0,0 @@ -/************************************************************************** - * - * Copyright 2014 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include "va_private.h" - -void vlVaHandlePictureParameterBufferVC1(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) -{ - VAPictureParameterBufferVC1 * vc1 = buf->data; - - assert(buf->size >= sizeof(VAPictureParameterBufferVC1) && buf->num_elements == 1); - context->desc.vc1.slice_count = 0; - vlVaGetReferenceFrame(drv, vc1->forward_reference_picture, &context->desc.vc1.ref[0]); - vlVaGetReferenceFrame(drv, vc1->backward_reference_picture, &context->desc.vc1.ref[1]); - context->desc.vc1.picture_type = vc1->picture_fields.bits.picture_type; - context->desc.vc1.frame_coding_mode = vc1->picture_fields.bits.frame_coding_mode; - context->desc.vc1.postprocflag = vc1->post_processing != 0; - context->desc.vc1.pulldown = vc1->sequence_fields.bits.pulldown; - context->desc.vc1.interlace = vc1->sequence_fields.bits.interlace; - context->desc.vc1.tfcntrflag = vc1->sequence_fields.bits.tfcntrflag; - context->desc.vc1.finterpflag = vc1->sequence_fields.bits.finterpflag; - context->desc.vc1.psf = vc1->sequence_fields.bits.psf; - context->desc.vc1.dquant = vc1->pic_quantizer_fields.bits.dquant; - context->desc.vc1.panscan_flag = vc1->entrypoint_fields.bits.panscan_flag; - context->desc.vc1.refdist_flag = - vc1->reference_fields.bits.reference_distance_flag; - context->desc.vc1.quantizer = vc1->pic_quantizer_fields.bits.quantizer; - context->desc.vc1.extended_mv = vc1->mv_fields.bits.extended_mv_flag; - context->desc.vc1.extended_dmv = vc1->mv_fields.bits.extended_dmv_flag; - context->desc.vc1.overlap = vc1->sequence_fields.bits.overlap; - context->desc.vc1.vstransform = - vc1->transform_fields.bits.variable_sized_transform_flag; - context->desc.vc1.loopfilter = vc1->entrypoint_fields.bits.loopfilter; - context->desc.vc1.fastuvmc = vc1->fast_uvmc_flag; - context->desc.vc1.range_mapy_flag = vc1->range_mapping_fields.bits.luma_flag; - context->desc.vc1.range_mapy = vc1->range_mapping_fields.bits.luma; - context->desc.vc1.range_mapuv_flag = vc1->range_mapping_fields.bits.chroma_flag; - context->desc.vc1.range_mapuv = vc1->range_mapping_fields.bits.chroma; - context->desc.vc1.multires = vc1->sequence_fields.bits.multires; - context->desc.vc1.syncmarker = vc1->sequence_fields.bits.syncmarker; - context->desc.vc1.rangered = vc1->sequence_fields.bits.rangered; - context->desc.vc1.maxbframes = vc1->sequence_fields.bits.max_b_frames; - context->desc.vc1.deblockEnable = vc1->post_processing != 0; - context->desc.vc1.pquant = vc1->pic_quantizer_fields.bits.pic_quantizer_scale; -} - -void vlVaHandleSliceParameterBufferVC1(vlVaContext *context, vlVaBuffer *buf) -{ - assert(buf->size >= sizeof(VASliceParameterBufferVC1) && buf->num_elements == 1); - context->desc.vc1.slice_count += buf->num_elements; -} diff --git a/src/gallium/state_trackers/va/picture_vp9.c b/src/gallium/state_trackers/va/picture_vp9.c deleted file mode 100644 index b5aca9a513c..00000000000 --- a/src/gallium/state_trackers/va/picture_vp9.c +++ /dev/null @@ -1,353 +0,0 @@ -/************************************************************************** - * - * Copyright 2018 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include "vl/vl_vlc.h" -#include "va_private.h" - -#define NUM_VP9_REFS 8 - -void vlVaHandlePictureParameterBufferVP9(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) -{ - VADecPictureParameterBufferVP9 *vp9 = buf->data; - int i; - - assert(buf->size >= sizeof(VADecPictureParameterBufferVP9) && buf->num_elements == 1); - - context->desc.vp9.picture_parameter.frame_width = vp9->frame_width; - context->desc.vp9.picture_parameter.frame_height = vp9->frame_height; - - context->desc.vp9.picture_parameter.pic_fields.subsampling_x = vp9->pic_fields.bits.subsampling_x; - context->desc.vp9.picture_parameter.pic_fields.subsampling_y = vp9->pic_fields.bits.subsampling_y; - context->desc.vp9.picture_parameter.pic_fields.frame_type = vp9->pic_fields.bits.frame_type; - context->desc.vp9.picture_parameter.pic_fields.show_frame = vp9->pic_fields.bits.show_frame; - context->desc.vp9.picture_parameter.pic_fields.error_resilient_mode = vp9->pic_fields.bits.error_resilient_mode; - context->desc.vp9.picture_parameter.pic_fields.intra_only = vp9->pic_fields.bits.intra_only; - context->desc.vp9.picture_parameter.pic_fields.allow_high_precision_mv = vp9->pic_fields.bits.allow_high_precision_mv; - context->desc.vp9.picture_parameter.pic_fields.mcomp_filter_type = vp9->pic_fields.bits.mcomp_filter_type; - context->desc.vp9.picture_parameter.pic_fields.frame_parallel_decoding_mode = vp9->pic_fields.bits.frame_parallel_decoding_mode; - context->desc.vp9.picture_parameter.pic_fields.reset_frame_context = vp9->pic_fields.bits.reset_frame_context; - context->desc.vp9.picture_parameter.pic_fields.refresh_frame_context = vp9->pic_fields.bits.refresh_frame_context; - context->desc.vp9.picture_parameter.pic_fields.frame_context_idx = vp9->pic_fields.bits.frame_context_idx; - context->desc.vp9.picture_parameter.pic_fields.segmentation_enabled = vp9->pic_fields.bits.segmentation_enabled; - context->desc.vp9.picture_parameter.pic_fields.segmentation_temporal_update = vp9->pic_fields.bits.segmentation_temporal_update; - context->desc.vp9.picture_parameter.pic_fields.segmentation_update_map = vp9->pic_fields.bits.segmentation_update_map; - context->desc.vp9.picture_parameter.pic_fields.last_ref_frame = vp9->pic_fields.bits.last_ref_frame; - context->desc.vp9.picture_parameter.pic_fields.last_ref_frame_sign_bias = vp9->pic_fields.bits.last_ref_frame_sign_bias; - context->desc.vp9.picture_parameter.pic_fields.golden_ref_frame = vp9->pic_fields.bits.golden_ref_frame; - context->desc.vp9.picture_parameter.pic_fields.golden_ref_frame_sign_bias = vp9->pic_fields.bits.golden_ref_frame_sign_bias; - context->desc.vp9.picture_parameter.pic_fields.alt_ref_frame = vp9->pic_fields.bits.alt_ref_frame; - context->desc.vp9.picture_parameter.pic_fields.alt_ref_frame_sign_bias = vp9->pic_fields.bits.alt_ref_frame_sign_bias; - context->desc.vp9.picture_parameter.pic_fields.lossless_flag = vp9->pic_fields.bits.lossless_flag; - - context->desc.vp9.picture_parameter.filter_level = vp9->filter_level; - context->desc.vp9.picture_parameter.sharpness_level = vp9->sharpness_level; - - context->desc.vp9.picture_parameter.log2_tile_rows = vp9->log2_tile_rows; - context->desc.vp9.picture_parameter.log2_tile_columns = vp9->log2_tile_columns; - - context->desc.vp9.picture_parameter.frame_header_length_in_bytes = vp9->frame_header_length_in_bytes; - context->desc.vp9.picture_parameter.first_partition_size = vp9->first_partition_size; - - for (i = 0; i < 7; ++i) - context->desc.vp9.picture_parameter.mb_segment_tree_probs[i] = vp9->mb_segment_tree_probs[i]; - for (i = 0; i < 3; ++i) - context->desc.vp9.picture_parameter.segment_pred_probs[i] = vp9->segment_pred_probs[i]; - - context->desc.vp9.picture_parameter.profile = vp9->profile; - - context->desc.vp9.picture_parameter.bit_depth = vp9->bit_depth; - - for (i = 0 ; i < NUM_VP9_REFS ; i++) - vlVaGetReferenceFrame(drv, vp9->reference_frames[i], &context->desc.vp9.ref[i]); - - if (!context->decoder && !context->templat.max_references) - context->templat.max_references = NUM_VP9_REFS; -} - -void vlVaHandleSliceParameterBufferVP9(vlVaContext *context, vlVaBuffer *buf) -{ - VASliceParameterBufferVP9 *vp9 = buf->data; - int i; - - assert(buf->size >= sizeof(VASliceParameterBufferVP9) && buf->num_elements == 1); - - context->desc.vp9.slice_parameter.slice_data_size = vp9->slice_data_size; - context->desc.vp9.slice_parameter.slice_data_offset = vp9->slice_data_offset; - context->desc.vp9.slice_parameter.slice_data_flag = vp9->slice_data_flag; - - for (i = 0; i < 8; ++i) { - context->desc.vp9.slice_parameter.seg_param[i].segment_flags.segment_reference_enabled = - vp9->seg_param[i].segment_flags.fields.segment_reference_enabled; - context->desc.vp9.slice_parameter.seg_param[i].segment_flags.segment_reference = - vp9->seg_param[i].segment_flags.fields.segment_reference; - context->desc.vp9.slice_parameter.seg_param[i].segment_flags.segment_reference_skipped = - vp9->seg_param[i].segment_flags.fields.segment_reference_skipped; - - memcpy(context->desc.vp9.slice_parameter.seg_param[i].filter_level, vp9->seg_param[i].filter_level, 4 * 2); - - context->desc.vp9.slice_parameter.seg_param[i].luma_ac_quant_scale = vp9->seg_param[i].luma_ac_quant_scale; - context->desc.vp9.slice_parameter.seg_param[i].luma_dc_quant_scale = vp9->seg_param[i].luma_dc_quant_scale; - context->desc.vp9.slice_parameter.seg_param[i].chroma_ac_quant_scale = vp9->seg_param[i].chroma_ac_quant_scale; - context->desc.vp9.slice_parameter.seg_param[i].chroma_dc_quant_scale = vp9->seg_param[i].chroma_dc_quant_scale; - } -} - -static unsigned vp9_u(struct vl_vlc *vlc, unsigned n) -{ - unsigned valid = vl_vlc_valid_bits(vlc); - - if (n == 0) - return 0; - - if (valid < 32) - vl_vlc_fillbits(vlc); - - return vl_vlc_get_uimsbf(vlc, n); -} - -static signed vp9_s(struct vl_vlc *vlc, unsigned n) -{ - unsigned v; - bool s; - - v = vp9_u(vlc, n); - s = vp9_u(vlc, 1); - - return s ? -v : v; -} - -static void bitdepth_colorspace_sampling(struct vl_vlc *vlc, unsigned profile) -{ - unsigned cs; - - if (profile == 2) - /* bit_depth */ - vp9_u(vlc, 1); - - cs = vp9_u(vlc, 3); - if (cs != 7) - /* yuv_range_flag */ - vp9_u(vlc, 1); -} - -static void frame_size(struct vl_vlc *vlc) -{ - /* width_minus_one */ - vp9_u(vlc, 16); - /* height_minus_one */ - vp9_u(vlc, 16); - - /* has_scaling */ - if (vp9_u(vlc, 1)) { - /* render_width_minus_one */ - vp9_u(vlc, 16); - /* render_height_minus_one */ - vp9_u(vlc, 16); - } -} - -void vlVaDecoderVP9BitstreamHeader(vlVaContext *context, vlVaBuffer *buf) -{ - struct vl_vlc vlc; - unsigned profile; - bool frame_type, show_frame, error_resilient_mode; - bool mode_ref_delta_enabled, mode_ref_delta_update = false; - int i; - - vl_vlc_init(&vlc, 1, (const void * const*)&buf->data, - (const unsigned *)&context->desc.vp9.picture_parameter.frame_header_length_in_bytes); - - /* frame_marker */ - if (vp9_u(&vlc, 2) != 0x2) - return; - - profile = vp9_u(&vlc, 1) | vp9_u(&vlc, 1) << 1; - - if (profile == 3) - profile += vp9_u(&vlc, 1); - - if (profile != 0 && profile != 2) - return; - - /* show_existing_frame */ - if (vp9_u(&vlc, 1)) - return; - - frame_type = vp9_u(&vlc, 1); - show_frame = vp9_u(&vlc, 1); - error_resilient_mode = vp9_u(&vlc, 1); - - if (frame_type == 0) { - /* sync_code */ - if (vp9_u(&vlc, 24) != 0x498342) - return; - - bitdepth_colorspace_sampling(&vlc, profile); - frame_size(&vlc); - } else { - bool intra_only, size_in_refs = false; - - intra_only = show_frame ? 0 : vp9_u(&vlc, 1); - if (!error_resilient_mode) - /* reset_frame_context */ - vp9_u(&vlc, 2); - - if (intra_only) { - /* sync_code */ - if (vp9_u(&vlc, 24) != 0x498342) - return; - - bitdepth_colorspace_sampling(&vlc, profile); - /* refresh_frame_flags */ - vp9_u(&vlc, 8); - frame_size(&vlc); - } else { - /* refresh_frame_flags */ - vp9_u(&vlc, 8); - - for (i = 0; i < 3; ++i) { - /* frame refs */ - vp9_u(&vlc, 3); - vp9_u(&vlc, 1); - } - - for (i = 0; i < 3; ++i) { - size_in_refs = vp9_u(&vlc, 1); - if (size_in_refs) - break; - } - - if (!size_in_refs) { - /* width/height_minus_one */ - vp9_u(&vlc, 16); - vp9_u(&vlc, 16); - } - - if (vp9_u(&vlc, 1)) { - /* render_width/height_minus_one */ - vp9_u(&vlc, 16); - vp9_u(&vlc, 16); - } - - /* high_precision_mv */ - vp9_u(&vlc, 1); - /* filter_switchable */ - if (!vp9_u(&vlc, 1)) - /* filter_index */ - vp9_u(&vlc, 2); - } - } - if (!error_resilient_mode) { - /* refresh_frame_context */ - vp9_u(&vlc, 1); - /* frame_parallel_decoding_mode */ - vp9_u(&vlc, 1); - } - /* frame_context_index */ - vp9_u(&vlc, 2); - - /* loop filter */ - - /* filter_level */ - vp9_u(&vlc, 6); - /* sharpness_level */ - vp9_u(&vlc, 3); - - mode_ref_delta_enabled = vp9_u(&vlc, 1); - if (mode_ref_delta_enabled) { - mode_ref_delta_update = vp9_u(&vlc, 1); - if (mode_ref_delta_update) { - for (i = 0; i < 4; ++i) { - /* update_ref_delta */ - if (vp9_u(&vlc, 1)) - /* ref_deltas */ - vp9_s(&vlc, 6); - } - for (i = 0; i < 2; ++i) { - /* update_mode_delta */ - if (vp9_u(&vlc, 1)) - /* mode_deltas */ - vp9_s(&vlc, 6); - } - } - } - context->desc.vp9.picture_parameter.mode_ref_delta_enabled = mode_ref_delta_enabled; - context->desc.vp9.picture_parameter.mode_ref_delta_update = mode_ref_delta_update; - - /* quantization */ - - context->desc.vp9.picture_parameter.base_qindex = vp9_u(&vlc, 8); - context->desc.vp9.picture_parameter.y_dc_delta_q = vp9_u(&vlc, 1) ? vp9_s(&vlc, 4) : 0; - context->desc.vp9.picture_parameter.uv_ac_delta_q = vp9_u(&vlc, 1) ? vp9_s(&vlc, 4) : 0; - context->desc.vp9.picture_parameter.uv_dc_delta_q = vp9_u(&vlc, 1) ? vp9_s(&vlc, 4) : 0; - - /* segmentation */ - - /* enabled */ - if (!vp9_u(&vlc, 1)) - return; - - /* update_map */ - if (vp9_u(&vlc, 1)) { - for (i = 0; i < 7; ++i) { - /* tree_probs_set */ - if (vp9_u(&vlc, 1)) { - /* tree_probs */ - vp9_u(&vlc, 8); - } - } - - /* temporal_update */ - if (vp9_u(&vlc, 1)) { - for (i = 0; i < 3; ++i) { - /* pred_probs_set */ - if (vp9_u(&vlc, 1)) - /* pred_probs */ - vp9_u(&vlc, 8); - } - } - } - - /* update_data */ - if (vp9_u(&vlc, 1)) { - /* abs_delta */ - vp9_u(&vlc, 1); - for (i = 0; i < 8; ++i) { - /* Use alternate quantizer */ - if ((context->desc.vp9.slice_parameter.seg_param[i].alt_quant_enabled = vp9_u(&vlc, 1))) - context->desc.vp9.slice_parameter.seg_param[i].alt_quant = vp9_s(&vlc, 8); - /* Use alternate loop filter value */ - if ((context->desc.vp9.slice_parameter.seg_param[i].alt_lf_enabled = vp9_u(&vlc, 1))) - context->desc.vp9.slice_parameter.seg_param[i].alt_lf = vp9_s(&vlc, 6); - /* Optional Segment reference frame */ - if (vp9_u(&vlc, 1)) - vp9_u(&vlc, 2); - /* Optional Segment skip mode */ - vp9_u(&vlc, 1); - } - } -} diff --git a/src/gallium/state_trackers/va/postproc.c b/src/gallium/state_trackers/va/postproc.c deleted file mode 100644 index 18458832844..00000000000 --- a/src/gallium/state_trackers/va/postproc.c +++ /dev/null @@ -1,362 +0,0 @@ -/************************************************************************** - * - * Copyright 2015 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include "util/u_handle_table.h" -#include "util/u_memory.h" -#include "util/u_compute.h" - -#include "vl/vl_defines.h" -#include "vl/vl_video_buffer.h" -#include "vl/vl_deint_filter.h" - -#include "va_private.h" - -static const VARectangle * -vlVaRegionDefault(const VARectangle *region, vlVaSurface *surf, - VARectangle *def) -{ - if (region) - return region; - - def->x = 0; - def->y = 0; - def->width = surf->templat.width; - def->height = surf->templat.height; - - return def; -} - -static VAStatus -vlVaPostProcCompositor(vlVaDriver *drv, vlVaContext *context, - const VARectangle *src_region, - const VARectangle *dst_region, - struct pipe_video_buffer *src, - struct pipe_video_buffer *dst, - enum vl_compositor_deinterlace deinterlace) -{ - struct pipe_surface **surfaces; - struct u_rect src_rect; - struct u_rect dst_rect; - - surfaces = dst->get_surfaces(dst); - if (!surfaces || !surfaces[0]) - return VA_STATUS_ERROR_INVALID_SURFACE; - - src_rect.x0 = src_region->x; - src_rect.y0 = src_region->y; - src_rect.x1 = src_region->x + src_region->width; - src_rect.y1 = src_region->y + src_region->height; - - dst_rect.x0 = dst_region->x; - dst_rect.y0 = dst_region->y; - dst_rect.x1 = dst_region->x + dst_region->width; - dst_rect.y1 = dst_region->y + dst_region->height; - - vl_compositor_clear_layers(&drv->cstate); - vl_compositor_set_buffer_layer(&drv->cstate, &drv->compositor, 0, src, - &src_rect, NULL, deinterlace); - vl_compositor_set_layer_dst_area(&drv->cstate, 0, &dst_rect); - vl_compositor_render(&drv->cstate, &drv->compositor, surfaces[0], NULL, false); - - drv->pipe->flush(drv->pipe, NULL, 0); - return VA_STATUS_SUCCESS; -} - -static void vlVaGetBox(struct pipe_video_buffer *buf, unsigned idx, - struct pipe_box *box, const VARectangle *region) -{ - unsigned plane = buf->interlaced ? idx / 2: idx; - unsigned x, y, width, height; - - x = abs(region->x); - y = abs(region->y); - width = region->width; - height = region->height; - - vl_video_buffer_adjust_size(&x, &y, plane, - pipe_format_to_chroma_format(buf->buffer_format), - buf->interlaced); - vl_video_buffer_adjust_size(&width, &height, plane, - pipe_format_to_chroma_format(buf->buffer_format), - buf->interlaced); - - box->x = region->x < 0 ? -x : x; - box->y = region->y < 0 ? -y : y; - box->width = width; - box->height = height; -} - -static VAStatus vlVaPostProcBlit(vlVaDriver *drv, vlVaContext *context, - const VARectangle *src_region, - const VARectangle *dst_region, - struct pipe_video_buffer *src, - struct pipe_video_buffer *dst, - enum vl_compositor_deinterlace deinterlace) -{ - struct pipe_surface **src_surfaces; - struct pipe_surface **dst_surfaces; - struct u_rect src_rect; - struct u_rect dst_rect; - bool scale = false; - bool grab = false; - unsigned i; - - if ((src->buffer_format == PIPE_FORMAT_B8G8R8A8_UNORM || - src->buffer_format == PIPE_FORMAT_B8G8R8X8_UNORM) && - !src->interlaced) - grab = true; - - if ((src->width != dst->width || src->height != dst->height) && - (src->interlaced && dst->interlaced)) - scale = true; - - src_surfaces = src->get_surfaces(src); - if (!src_surfaces || !src_surfaces[0]) - return VA_STATUS_ERROR_INVALID_SURFACE; - - if (scale || (src->interlaced != dst->interlaced && dst->interlaced)) { - vlVaSurface *surf; - - surf = handle_table_get(drv->htab, context->target_id); - surf->templat.interlaced = false; - dst->destroy(dst); - - if (vlVaHandleSurfaceAllocate(drv, surf, &surf->templat) != VA_STATUS_SUCCESS) - return VA_STATUS_ERROR_ALLOCATION_FAILED; - - dst = context->target = surf->buffer; - } - - dst_surfaces = dst->get_surfaces(dst); - if (!dst_surfaces || !dst_surfaces[0]) - return VA_STATUS_ERROR_INVALID_SURFACE; - - src_rect.x0 = src_region->x; - src_rect.y0 = src_region->y; - src_rect.x1 = src_region->x + src_region->width; - src_rect.y1 = src_region->y + src_region->height; - - dst_rect.x0 = dst_region->x; - dst_rect.y0 = dst_region->y; - dst_rect.x1 = dst_region->x + dst_region->width; - dst_rect.y1 = dst_region->y + dst_region->height; - - if (grab) { - vl_compositor_convert_rgb_to_yuv(&drv->cstate, &drv->compositor, 0, - ((struct vl_video_buffer *)src)->resources[0], - dst, &src_rect, &dst_rect); - - return VA_STATUS_SUCCESS; - } - - if (src->interlaced != dst->interlaced) { - vl_compositor_yuv_deint_full(&drv->cstate, &drv->compositor, - src, dst, &src_rect, &dst_rect, - deinterlace); - - return VA_STATUS_SUCCESS; - } - - for (i = 0; i < VL_MAX_SURFACES; ++i) { - struct pipe_surface *from = src_surfaces[i]; - struct pipe_blit_info blit; - - if (src->interlaced) { - /* Not 100% accurate, but close enough */ - switch (deinterlace) { - case VL_COMPOSITOR_BOB_TOP: - from = src_surfaces[i & ~1]; - break; - case VL_COMPOSITOR_BOB_BOTTOM: - from = src_surfaces[(i & ~1) + 1]; - break; - default: - break; - } - } - - if (!from || !dst_surfaces[i]) - continue; - - memset(&blit, 0, sizeof(blit)); - blit.src.resource = from->texture; - blit.src.format = from->format; - blit.src.level = 0; - blit.src.box.z = from->u.tex.first_layer; - blit.src.box.depth = 1; - vlVaGetBox(src, i, &blit.src.box, src_region); - - blit.dst.resource = dst_surfaces[i]->texture; - blit.dst.format = dst_surfaces[i]->format; - blit.dst.level = 0; - blit.dst.box.z = dst_surfaces[i]->u.tex.first_layer; - blit.dst.box.depth = 1; - vlVaGetBox(dst, i, &blit.dst.box, dst_region); - - blit.mask = PIPE_MASK_RGBA; - blit.filter = PIPE_TEX_MIPFILTER_LINEAR; - - if (drv->pipe->screen->get_param(drv->pipe->screen, - PIPE_CAP_PREFER_COMPUTE_FOR_MULTIMEDIA)) - util_compute_blit(drv->pipe, &blit, &context->blit_cs); - else - drv->pipe->blit(drv->pipe, &blit); - } - - // TODO: figure out why this is necessary for DMA-buf sharing - drv->pipe->flush(drv->pipe, NULL, 0); - - return VA_STATUS_SUCCESS; -} - -static struct pipe_video_buffer * -vlVaApplyDeint(vlVaDriver *drv, vlVaContext *context, - VAProcPipelineParameterBuffer *param, - struct pipe_video_buffer *current, - unsigned field) -{ - vlVaSurface *prevprev, *prev, *next; - - if (param->num_forward_references < 2 || - param->num_backward_references < 1) - return current; - - prevprev = handle_table_get(drv->htab, param->forward_references[1]); - prev = handle_table_get(drv->htab, param->forward_references[0]); - next = handle_table_get(drv->htab, param->backward_references[0]); - - if (!prevprev || !prev || !next) - return current; - - if (context->deint && (context->deint->video_width != current->width || - context->deint->video_height != current->height)) { - vl_deint_filter_cleanup(context->deint); - FREE(context->deint); - context->deint = NULL; - } - - if (!context->deint) { - context->deint = MALLOC(sizeof(struct vl_deint_filter)); - if (!vl_deint_filter_init(context->deint, drv->pipe, current->width, - current->height, false, false)) { - FREE(context->deint); - context->deint = NULL; - return current; - } - } - - if (!vl_deint_filter_check_buffers(context->deint, prevprev->buffer, - prev->buffer, current, next->buffer)) - return current; - - vl_deint_filter_render(context->deint, prevprev->buffer, prev->buffer, - current, next->buffer, field); - return context->deint->video_buffer; -} - -VAStatus -vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) -{ - enum vl_compositor_deinterlace deinterlace = VL_COMPOSITOR_WEAVE; - VARectangle def_src_region, def_dst_region; - const VARectangle *src_region, *dst_region; - VAProcPipelineParameterBuffer *param; - struct pipe_video_buffer *src; - vlVaSurface *src_surface, *dst_surface; - unsigned i; - - if (!drv || !context) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - if (!buf || !buf->data) - return VA_STATUS_ERROR_INVALID_BUFFER; - - if (!context->target) - return VA_STATUS_ERROR_INVALID_SURFACE; - - param = buf->data; - - src_surface = handle_table_get(drv->htab, param->surface); - dst_surface = handle_table_get(drv->htab, context->target_id); - - if (!src_surface || !src_surface->buffer) - return VA_STATUS_ERROR_INVALID_SURFACE; - - src = src_surface->buffer; - - for (i = 0; i < param->num_filters; i++) { - vlVaBuffer *buf = handle_table_get(drv->htab, param->filters[i]); - VAProcFilterParameterBufferBase *filter; - - if (!buf || buf->type != VAProcFilterParameterBufferType) - return VA_STATUS_ERROR_INVALID_BUFFER; - - filter = buf->data; - switch (filter->type) { - case VAProcFilterDeinterlacing: { - VAProcFilterParameterBufferDeinterlacing *deint = buf->data; - switch (deint->algorithm) { - case VAProcDeinterlacingBob: - if (deint->flags & VA_DEINTERLACING_BOTTOM_FIELD) - deinterlace = VL_COMPOSITOR_BOB_BOTTOM; - else - deinterlace = VL_COMPOSITOR_BOB_TOP; - break; - - case VAProcDeinterlacingWeave: - deinterlace = VL_COMPOSITOR_WEAVE; - break; - - case VAProcDeinterlacingMotionAdaptive: - src = vlVaApplyDeint(drv, context, param, src, - !!(deint->flags & VA_DEINTERLACING_BOTTOM_FIELD)); - break; - - default: - return VA_STATUS_ERROR_UNIMPLEMENTED; - } - - break; - } - - default: - return VA_STATUS_ERROR_UNIMPLEMENTED; - } - } - - src_region = vlVaRegionDefault(param->surface_region, src_surface, &def_src_region); - dst_region = vlVaRegionDefault(param->output_region, dst_surface, &def_dst_region); - - if (context->target->buffer_format != PIPE_FORMAT_NV12 && - context->target->buffer_format != PIPE_FORMAT_P010 && - context->target->buffer_format != PIPE_FORMAT_P016) - return vlVaPostProcCompositor(drv, context, src_region, dst_region, - src, context->target, deinterlace); - else - return vlVaPostProcBlit(drv, context, src_region, dst_region, - src, context->target, deinterlace); -} diff --git a/src/gallium/state_trackers/va/subpicture.c b/src/gallium/state_trackers/va/subpicture.c deleted file mode 100644 index b213e9abb7d..00000000000 --- a/src/gallium/state_trackers/va/subpicture.c +++ /dev/null @@ -1,290 +0,0 @@ -/************************************************************************** - * - * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian. - * Copyright 2014 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include "util/u_memory.h" -#include "util/u_handle_table.h" -#include "util/u_sampler.h" - -#include "va_private.h" - -static VAImageFormat subpic_formats[] = { - { - .fourcc = VA_FOURCC_BGRA, - .byte_order = VA_LSB_FIRST, - .bits_per_pixel = 32, - .depth = 32, - .red_mask = 0x00ff0000ul, - .green_mask = 0x0000ff00ul, - .blue_mask = 0x000000fful, - .alpha_mask = 0xff000000ul, - }, -}; - -VAStatus -vlVaQuerySubpictureFormats(VADriverContextP ctx, VAImageFormat *format_list, - unsigned int *flags, unsigned int *num_formats) -{ - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - if (!(format_list && flags && num_formats)) - return VA_STATUS_ERROR_UNKNOWN; - - *num_formats = sizeof(subpic_formats)/sizeof(VAImageFormat); - memcpy(format_list, subpic_formats, sizeof(subpic_formats)); - - return VA_STATUS_SUCCESS; -} - -VAStatus -vlVaCreateSubpicture(VADriverContextP ctx, VAImageID image, - VASubpictureID *subpicture) -{ - vlVaDriver *drv; - vlVaSubpicture *sub; - VAImage *img; - - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - drv = VL_VA_DRIVER(ctx); - mtx_lock(&drv->mutex); - img = handle_table_get(drv->htab, image); - if (!img) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_INVALID_IMAGE; - } - - sub = CALLOC(1, sizeof(*sub)); - if (!sub) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_ALLOCATION_FAILED; - } - - sub->image = img; - *subpicture = handle_table_add(VL_VA_DRIVER(ctx)->htab, sub); - mtx_unlock(&drv->mutex); - - return VA_STATUS_SUCCESS; -} - -VAStatus -vlVaDestroySubpicture(VADriverContextP ctx, VASubpictureID subpicture) -{ - vlVaDriver *drv; - vlVaSubpicture *sub; - - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - drv = VL_VA_DRIVER(ctx); - mtx_lock(&drv->mutex); - - sub = handle_table_get(drv->htab, subpicture); - if (!sub) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_INVALID_SUBPICTURE; - } - - FREE(sub); - handle_table_remove(drv->htab, subpicture); - mtx_unlock(&drv->mutex); - - return VA_STATUS_SUCCESS; -} - -VAStatus -vlVaSubpictureImage(VADriverContextP ctx, VASubpictureID subpicture, VAImageID image) -{ - vlVaDriver *drv; - vlVaSubpicture *sub; - VAImage *img; - - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - drv = VL_VA_DRIVER(ctx); - mtx_lock(&drv->mutex); - - img = handle_table_get(drv->htab, image); - if (!img) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_INVALID_IMAGE; - } - - sub = handle_table_get(drv->htab, subpicture); - mtx_unlock(&drv->mutex); - if (!sub) - return VA_STATUS_ERROR_INVALID_SUBPICTURE; - - sub->image = img; - - return VA_STATUS_SUCCESS; -} - -VAStatus -vlVaSetSubpictureChromakey(VADriverContextP ctx, VASubpictureID subpicture, - unsigned int chromakey_min, unsigned int chromakey_max, unsigned int chromakey_mask) -{ - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - return VA_STATUS_ERROR_UNIMPLEMENTED; -} - -VAStatus -vlVaSetSubpictureGlobalAlpha(VADriverContextP ctx, VASubpictureID subpicture, float global_alpha) -{ - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - return VA_STATUS_ERROR_UNIMPLEMENTED; -} - -VAStatus -vlVaAssociateSubpicture(VADriverContextP ctx, VASubpictureID subpicture, - VASurfaceID *target_surfaces, int num_surfaces, - short src_x, short src_y, unsigned short src_width, - unsigned short src_height, short dest_x, short dest_y, - unsigned short dest_width, unsigned short dest_height, - unsigned int flags) -{ - vlVaSubpicture *sub; - struct pipe_resource tex_temp, *tex; - struct pipe_sampler_view sampler_templ; - vlVaDriver *drv; - vlVaSurface *surf; - int i; - struct u_rect src_rect = {src_x, src_x + src_width, src_y, src_y + src_height}; - struct u_rect dst_rect = {dest_x, dest_x + dest_width, dest_y, dest_y + dest_height}; - - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - drv = VL_VA_DRIVER(ctx); - mtx_lock(&drv->mutex); - - sub = handle_table_get(drv->htab, subpicture); - if (!sub) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_INVALID_SUBPICTURE; - } - - for (i = 0; i < num_surfaces; i++) { - surf = handle_table_get(drv->htab, target_surfaces[i]); - if (!surf) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_INVALID_SURFACE; - } - } - - sub->src_rect = src_rect; - sub->dst_rect = dst_rect; - - memset(&tex_temp, 0, sizeof(tex_temp)); - tex_temp.target = PIPE_TEXTURE_2D; - tex_temp.format = PIPE_FORMAT_B8G8R8A8_UNORM; - tex_temp.last_level = 0; - tex_temp.width0 = src_width; - tex_temp.height0 = src_height; - tex_temp.depth0 = 1; - tex_temp.array_size = 1; - tex_temp.usage = PIPE_USAGE_DYNAMIC; - tex_temp.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; - tex_temp.flags = 0; - if (!drv->pipe->screen->is_format_supported( - drv->pipe->screen, tex_temp.format, tex_temp.target, - tex_temp.nr_samples, tex_temp.nr_storage_samples, tex_temp.bind)) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_ALLOCATION_FAILED; - } - - tex = drv->pipe->screen->resource_create(drv->pipe->screen, &tex_temp); - - memset(&sampler_templ, 0, sizeof(sampler_templ)); - u_sampler_view_default_template(&sampler_templ, tex, tex->format); - sub->sampler = drv->pipe->create_sampler_view(drv->pipe, tex, &sampler_templ); - pipe_resource_reference(&tex, NULL); - if (!sub->sampler) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_ALLOCATION_FAILED; - } - - for (i = 0; i < num_surfaces; i++) { - surf = handle_table_get(drv->htab, target_surfaces[i]); - util_dynarray_append(&surf->subpics, vlVaSubpicture *, sub); - } - mtx_unlock(&drv->mutex); - - return VA_STATUS_SUCCESS; -} - -VAStatus -vlVaDeassociateSubpicture(VADriverContextP ctx, VASubpictureID subpicture, - VASurfaceID *target_surfaces, int num_surfaces) -{ - int i; - int j; - vlVaSurface *surf; - vlVaSubpicture *sub, **array; - vlVaDriver *drv; - - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - drv = VL_VA_DRIVER(ctx); - mtx_lock(&drv->mutex); - - sub = handle_table_get(drv->htab, subpicture); - if (!sub) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_INVALID_SUBPICTURE; - } - - for (i = 0; i < num_surfaces; i++) { - surf = handle_table_get(drv->htab, target_surfaces[i]); - if (!surf) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_INVALID_SURFACE; - } - - array = surf->subpics.data; - if (!array) - continue; - - for (j = 0; j < surf->subpics.size/sizeof(vlVaSubpicture *); j++) { - if (array[j] == sub) - array[j] = NULL; - } - - while (surf->subpics.size && util_dynarray_top(&surf->subpics, vlVaSubpicture *) == NULL) - (void)util_dynarray_pop(&surf->subpics, vlVaSubpicture *); - } - pipe_sampler_view_reference(&sub->sampler,NULL); - mtx_unlock(&drv->mutex); - - return VA_STATUS_SUCCESS; -} diff --git a/src/gallium/state_trackers/va/surface.c b/src/gallium/state_trackers/va/surface.c deleted file mode 100644 index bfad93f8f3d..00000000000 --- a/src/gallium/state_trackers/va/surface.c +++ /dev/null @@ -1,1110 +0,0 @@ -/************************************************************************** - * - * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian. - * Copyright 2014 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include "pipe/p_screen.h" -#include "pipe/p_video_codec.h" - -#include "state_tracker/drm_driver.h" - -#include "util/u_memory.h" -#include "util/u_handle_table.h" -#include "util/u_rect.h" -#include "util/u_sampler.h" -#include "util/u_surface.h" -#include "util/u_video.h" - -#include "vl/vl_compositor.h" -#include "vl/vl_video_buffer.h" -#include "vl/vl_winsys.h" - -#include "va_private.h" - -#include -#include "drm-uapi/drm_fourcc.h" - -static const enum pipe_format vpp_surface_formats[] = { - PIPE_FORMAT_B8G8R8A8_UNORM, PIPE_FORMAT_R8G8B8A8_UNORM, - PIPE_FORMAT_B8G8R8X8_UNORM, PIPE_FORMAT_R8G8B8X8_UNORM -}; - -VAStatus -vlVaCreateSurfaces(VADriverContextP ctx, int width, int height, int format, - int num_surfaces, VASurfaceID *surfaces) -{ - return vlVaCreateSurfaces2(ctx, format, width, height, surfaces, num_surfaces, - NULL, 0); -} - -VAStatus -vlVaDestroySurfaces(VADriverContextP ctx, VASurfaceID *surface_list, int num_surfaces) -{ - vlVaDriver *drv; - int i; - - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - drv = VL_VA_DRIVER(ctx); - mtx_lock(&drv->mutex); - for (i = 0; i < num_surfaces; ++i) { - vlVaSurface *surf = handle_table_get(drv->htab, surface_list[i]); - if (!surf) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_INVALID_SURFACE; - } - if (surf->buffer) - surf->buffer->destroy(surf->buffer); - util_dynarray_fini(&surf->subpics); - FREE(surf); - handle_table_remove(drv->htab, surface_list[i]); - } - mtx_unlock(&drv->mutex); - - return VA_STATUS_SUCCESS; -} - -VAStatus -vlVaSyncSurface(VADriverContextP ctx, VASurfaceID render_target) -{ - vlVaDriver *drv; - vlVaContext *context; - vlVaSurface *surf; - - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - drv = VL_VA_DRIVER(ctx); - if (!drv) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - mtx_lock(&drv->mutex); - surf = handle_table_get(drv->htab, render_target); - - if (!surf || !surf->buffer) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_INVALID_SURFACE; - } - - if (!surf->feedback) { - // No outstanding operation: nothing to do. - mtx_unlock(&drv->mutex); - return VA_STATUS_SUCCESS; - } - - context = handle_table_get(drv->htab, surf->ctx); - if (!context) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_INVALID_CONTEXT; - } - - if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) { - if (u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_MPEG4_AVC) { - int frame_diff; - if (context->desc.h264enc.frame_num_cnt >= surf->frame_num_cnt) - frame_diff = context->desc.h264enc.frame_num_cnt - surf->frame_num_cnt; - else - frame_diff = 0xFFFFFFFF - surf->frame_num_cnt + 1 + context->desc.h264enc.frame_num_cnt; - if ((frame_diff == 0) && - (surf->force_flushed == false) && - (context->desc.h264enc.frame_num_cnt % 2 != 0)) { - context->decoder->flush(context->decoder); - context->first_single_submitted = true; - } - } - context->decoder->get_feedback(context->decoder, surf->feedback, &(surf->coded_buf->coded_size)); - surf->feedback = NULL; - } - mtx_unlock(&drv->mutex); - return VA_STATUS_SUCCESS; -} - -VAStatus -vlVaQuerySurfaceStatus(VADriverContextP ctx, VASurfaceID render_target, VASurfaceStatus *status) -{ - vlVaDriver *drv; - vlVaSurface *surf; - vlVaContext *context; - - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - drv = VL_VA_DRIVER(ctx); - if (!drv) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - mtx_lock(&drv->mutex); - - surf = handle_table_get(drv->htab, render_target); - if (!surf || !surf->buffer) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_INVALID_SURFACE; - } - - context = handle_table_get(drv->htab, surf->ctx); - if (!context) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_INVALID_CONTEXT; - } - - if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) { - if(surf->feedback == NULL) - *status=VASurfaceReady; - else - *status=VASurfaceRendering; - } - - mtx_unlock(&drv->mutex); - - return VA_STATUS_SUCCESS; -} - -VAStatus -vlVaQuerySurfaceError(VADriverContextP ctx, VASurfaceID render_target, VAStatus error_status, void **error_info) -{ - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - return VA_STATUS_ERROR_UNIMPLEMENTED; -} - -static void -upload_sampler(struct pipe_context *pipe, struct pipe_sampler_view *dst, - const struct pipe_box *dst_box, const void *src, unsigned src_stride, - unsigned src_x, unsigned src_y) -{ - struct pipe_transfer *transfer; - void *map; - - map = pipe->transfer_map(pipe, dst->texture, 0, PIPE_TRANSFER_WRITE, - dst_box, &transfer); - if (!map) - return; - - util_copy_rect(map, dst->texture->format, transfer->stride, 0, 0, - dst_box->width, dst_box->height, - src, src_stride, src_x, src_y); - - pipe->transfer_unmap(pipe, transfer); -} - -static VAStatus -vlVaPutSubpictures(vlVaSurface *surf, vlVaDriver *drv, - struct pipe_surface *surf_draw, struct u_rect *dirty_area, - struct u_rect *src_rect, struct u_rect *dst_rect) -{ - vlVaSubpicture *sub; - int i; - - if (!(surf->subpics.data || surf->subpics.size)) - return VA_STATUS_SUCCESS; - - for (i = 0; i < surf->subpics.size/sizeof(vlVaSubpicture *); i++) { - struct pipe_blend_state blend; - void *blend_state; - vlVaBuffer *buf; - struct pipe_box box; - struct u_rect *s, *d, sr, dr, c; - int sw, sh, dw, dh; - - sub = ((vlVaSubpicture **)surf->subpics.data)[i]; - if (!sub) - continue; - - buf = handle_table_get(drv->htab, sub->image->buf); - if (!buf) - return VA_STATUS_ERROR_INVALID_IMAGE; - - box.x = 0; - box.y = 0; - box.z = 0; - box.width = sub->dst_rect.x1 - sub->dst_rect.x0; - box.height = sub->dst_rect.y1 - sub->dst_rect.y0; - box.depth = 1; - - s = &sub->src_rect; - d = &sub->dst_rect; - sw = s->x1 - s->x0; - sh = s->y1 - s->y0; - dw = d->x1 - d->x0; - dh = d->y1 - d->y0; - c.x0 = MAX2(d->x0, s->x0); - c.y0 = MAX2(d->y0, s->y0); - c.x1 = MIN2(d->x0 + dw, src_rect->x1); - c.y1 = MIN2(d->y0 + dh, src_rect->y1); - sr.x0 = s->x0 + (c.x0 - d->x0)*(sw/(float)dw); - sr.y0 = s->y0 + (c.y0 - d->y0)*(sh/(float)dh); - sr.x1 = s->x0 + (c.x1 - d->x0)*(sw/(float)dw); - sr.y1 = s->y0 + (c.y1 - d->y0)*(sh/(float)dh); - - s = src_rect; - d = dst_rect; - sw = s->x1 - s->x0; - sh = s->y1 - s->y0; - dw = d->x1 - d->x0; - dh = d->y1 - d->y0; - dr.x0 = d->x0 + c.x0*(dw/(float)sw); - dr.y0 = d->y0 + c.y0*(dh/(float)sh); - dr.x1 = d->x0 + c.x1*(dw/(float)sw); - dr.y1 = d->y0 + c.y1*(dh/(float)sh); - - memset(&blend, 0, sizeof(blend)); - blend.independent_blend_enable = 0; - blend.rt[0].blend_enable = 1; - blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA; - blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA; - blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ZERO; - blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; - blend.rt[0].rgb_func = PIPE_BLEND_ADD; - blend.rt[0].alpha_func = PIPE_BLEND_ADD; - blend.rt[0].colormask = PIPE_MASK_RGBA; - blend.logicop_enable = 0; - blend.logicop_func = PIPE_LOGICOP_CLEAR; - blend.dither = 0; - blend_state = drv->pipe->create_blend_state(drv->pipe, &blend); - - vl_compositor_clear_layers(&drv->cstate); - vl_compositor_set_layer_blend(&drv->cstate, 0, blend_state, false); - upload_sampler(drv->pipe, sub->sampler, &box, buf->data, - sub->image->pitches[0], 0, 0); - vl_compositor_set_rgba_layer(&drv->cstate, &drv->compositor, 0, sub->sampler, - &sr, NULL, NULL); - vl_compositor_set_layer_dst_area(&drv->cstate, 0, &dr); - vl_compositor_render(&drv->cstate, &drv->compositor, surf_draw, dirty_area, false); - drv->pipe->delete_blend_state(drv->pipe, blend_state); - } - - return VA_STATUS_SUCCESS; -} - -VAStatus -vlVaPutSurface(VADriverContextP ctx, VASurfaceID surface_id, void* draw, short srcx, short srcy, - unsigned short srcw, unsigned short srch, short destx, short desty, - unsigned short destw, unsigned short desth, VARectangle *cliprects, - unsigned int number_cliprects, unsigned int flags) -{ - vlVaDriver *drv; - vlVaSurface *surf; - struct pipe_screen *screen; - struct pipe_resource *tex; - struct pipe_surface surf_templ, *surf_draw; - struct vl_screen *vscreen; - struct u_rect src_rect, *dirty_area; - struct u_rect dst_rect = {destx, destx + destw, desty, desty + desth}; - enum pipe_format format; - VAStatus status; - - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - drv = VL_VA_DRIVER(ctx); - mtx_lock(&drv->mutex); - surf = handle_table_get(drv->htab, surface_id); - if (!surf) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_INVALID_SURFACE; - } - - screen = drv->pipe->screen; - vscreen = drv->vscreen; - - tex = vscreen->texture_from_drawable(vscreen, draw); - if (!tex) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_INVALID_DISPLAY; - } - - dirty_area = vscreen->get_dirty_area(vscreen); - - memset(&surf_templ, 0, sizeof(surf_templ)); - surf_templ.format = tex->format; - surf_draw = drv->pipe->create_surface(drv->pipe, tex, &surf_templ); - if (!surf_draw) { - pipe_resource_reference(&tex, NULL); - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_INVALID_DISPLAY; - } - - src_rect.x0 = srcx; - src_rect.y0 = srcy; - src_rect.x1 = srcw + srcx; - src_rect.y1 = srch + srcy; - - format = surf->buffer->buffer_format; - - vl_compositor_clear_layers(&drv->cstate); - - if (format == PIPE_FORMAT_B8G8R8A8_UNORM || format == PIPE_FORMAT_B8G8R8X8_UNORM || - format == PIPE_FORMAT_R8G8B8A8_UNORM || format == PIPE_FORMAT_R8G8B8X8_UNORM) { - struct pipe_sampler_view **views; - - views = surf->buffer->get_sampler_view_planes(surf->buffer); - vl_compositor_set_rgba_layer(&drv->cstate, &drv->compositor, 0, views[0], &src_rect, NULL, NULL); - } else - vl_compositor_set_buffer_layer(&drv->cstate, &drv->compositor, 0, surf->buffer, &src_rect, NULL, VL_COMPOSITOR_WEAVE); - - vl_compositor_set_layer_dst_area(&drv->cstate, 0, &dst_rect); - vl_compositor_render(&drv->cstate, &drv->compositor, surf_draw, dirty_area, true); - - status = vlVaPutSubpictures(surf, drv, surf_draw, dirty_area, &src_rect, &dst_rect); - if (status) { - mtx_unlock(&drv->mutex); - return status; - } - - /* flush before calling flush_frontbuffer so that rendering is flushed - * to back buffer so the texture can be copied in flush_frontbuffer - */ - drv->pipe->flush(drv->pipe, NULL, 0); - - screen->flush_frontbuffer(screen, tex, 0, 0, - vscreen->get_private(vscreen), NULL); - - - pipe_resource_reference(&tex, NULL); - pipe_surface_reference(&surf_draw, NULL); - mtx_unlock(&drv->mutex); - - return VA_STATUS_SUCCESS; -} - -VAStatus -vlVaLockSurface(VADriverContextP ctx, VASurfaceID surface, unsigned int *fourcc, - unsigned int *luma_stride, unsigned int *chroma_u_stride, unsigned int *chroma_v_stride, - unsigned int *luma_offset, unsigned int *chroma_u_offset, unsigned int *chroma_v_offset, - unsigned int *buffer_name, void **buffer) -{ - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - return VA_STATUS_ERROR_UNIMPLEMENTED; -} - -VAStatus -vlVaUnlockSurface(VADriverContextP ctx, VASurfaceID surface) -{ - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - return VA_STATUS_ERROR_UNIMPLEMENTED; -} - -VAStatus -vlVaQuerySurfaceAttributes(VADriverContextP ctx, VAConfigID config_id, - VASurfaceAttrib *attrib_list, unsigned int *num_attribs) -{ - vlVaDriver *drv; - vlVaConfig *config; - VASurfaceAttrib *attribs; - struct pipe_screen *pscreen; - int i, j; - - STATIC_ASSERT(ARRAY_SIZE(vpp_surface_formats) <= VL_VA_MAX_IMAGE_FORMATS); - - if (config_id == VA_INVALID_ID) - return VA_STATUS_ERROR_INVALID_CONFIG; - - if (!attrib_list && !num_attribs) - return VA_STATUS_ERROR_INVALID_PARAMETER; - - if (!attrib_list) { - *num_attribs = VL_VA_MAX_IMAGE_FORMATS + VASurfaceAttribCount; - return VA_STATUS_SUCCESS; - } - - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - drv = VL_VA_DRIVER(ctx); - - if (!drv) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - mtx_lock(&drv->mutex); - config = handle_table_get(drv->htab, config_id); - mtx_unlock(&drv->mutex); - - if (!config) - return VA_STATUS_ERROR_INVALID_CONFIG; - - pscreen = VL_VA_PSCREEN(ctx); - - if (!pscreen) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - attribs = CALLOC(VL_VA_MAX_IMAGE_FORMATS + VASurfaceAttribCount, - sizeof(VASurfaceAttrib)); - - if (!attribs) - return VA_STATUS_ERROR_ALLOCATION_FAILED; - - i = 0; - - /* vlVaCreateConfig returns PIPE_VIDEO_PROFILE_UNKNOWN - * only for VAEntrypointVideoProc. */ - if (config->profile == PIPE_VIDEO_PROFILE_UNKNOWN) { - if (config->rt_format & VA_RT_FORMAT_RGB32) { - for (j = 0; j < ARRAY_SIZE(vpp_surface_formats); ++j) { - attribs[i].type = VASurfaceAttribPixelFormat; - attribs[i].value.type = VAGenericValueTypeInteger; - attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE; - attribs[i].value.value.i = PipeFormatToVaFourcc(vpp_surface_formats[j]); - i++; - } - } - } - if (config->rt_format & VA_RT_FORMAT_YUV420) { - attribs[i].type = VASurfaceAttribPixelFormat; - attribs[i].value.type = VAGenericValueTypeInteger; - attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE; - attribs[i].value.value.i = VA_FOURCC_NV12; - i++; - } - if (config->rt_format & VA_RT_FORMAT_YUV420_10BPP) { - attribs[i].type = VASurfaceAttribPixelFormat; - attribs[i].value.type = VAGenericValueTypeInteger; - attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE; - attribs[i].value.value.i = VA_FOURCC_P010; - i++; - attribs[i].type = VASurfaceAttribPixelFormat; - attribs[i].value.type = VAGenericValueTypeInteger; - attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE; - attribs[i].value.value.i = VA_FOURCC_P016; - i++; - } - - attribs[i].type = VASurfaceAttribMemoryType; - attribs[i].value.type = VAGenericValueTypeInteger; - attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE; - attribs[i].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_VA | - VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME; - i++; - - attribs[i].type = VASurfaceAttribExternalBufferDescriptor; - attribs[i].value.type = VAGenericValueTypePointer; - attribs[i].flags = VA_SURFACE_ATTRIB_SETTABLE; - attribs[i].value.value.p = NULL; /* ignore */ - i++; - - if (config->entrypoint != PIPE_VIDEO_ENTRYPOINT_UNKNOWN) { - attribs[i].type = VASurfaceAttribMaxWidth; - attribs[i].value.type = VAGenericValueTypeInteger; - attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE; - attribs[i].value.value.i = - pscreen->get_video_param(pscreen, - config->profile, config->entrypoint, - PIPE_VIDEO_CAP_MAX_WIDTH); - i++; - - attribs[i].type = VASurfaceAttribMaxHeight; - attribs[i].value.type = VAGenericValueTypeInteger; - attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE; - attribs[i].value.value.i = - pscreen->get_video_param(pscreen, - config->profile, config->entrypoint, - PIPE_VIDEO_CAP_MAX_HEIGHT); - i++; - } else { - attribs[i].type = VASurfaceAttribMaxWidth; - attribs[i].value.type = VAGenericValueTypeInteger; - attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE; - attribs[i].value.value.i = vl_video_buffer_max_size(pscreen); - i++; - - attribs[i].type = VASurfaceAttribMaxHeight; - attribs[i].value.type = VAGenericValueTypeInteger; - attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE; - attribs[i].value.value.i = vl_video_buffer_max_size(pscreen); - i++; - } - - if (i > *num_attribs) { - *num_attribs = i; - FREE(attribs); - return VA_STATUS_ERROR_MAX_NUM_EXCEEDED; - } - - *num_attribs = i; - memcpy(attrib_list, attribs, i * sizeof(VASurfaceAttrib)); - FREE(attribs); - - return VA_STATUS_SUCCESS; -} - -static VAStatus -surface_from_external_memory(VADriverContextP ctx, vlVaSurface *surface, - VASurfaceAttribExternalBuffers *memory_attribute, - unsigned index, struct pipe_video_buffer *templat) -{ - vlVaDriver *drv; - struct pipe_screen *pscreen; - struct pipe_resource res_templ; - struct winsys_handle whandle; - struct pipe_resource *resources[VL_NUM_COMPONENTS]; - enum pipe_format resource_formats[VL_NUM_COMPONENTS]; - VAStatus result; - int i; - - pscreen = VL_VA_PSCREEN(ctx); - drv = VL_VA_DRIVER(ctx); - - if (!memory_attribute || !memory_attribute->buffers || - index > memory_attribute->num_buffers) - return VA_STATUS_ERROR_INVALID_PARAMETER; - - if (surface->templat.width != memory_attribute->width || - surface->templat.height != memory_attribute->height || - memory_attribute->num_planes < 1) - return VA_STATUS_ERROR_INVALID_PARAMETER; - - if (memory_attribute->num_planes > VL_NUM_COMPONENTS) - return VA_STATUS_ERROR_INVALID_PARAMETER; - - vl_get_video_buffer_formats(pscreen, templat->buffer_format, resource_formats); - - memset(&res_templ, 0, sizeof(res_templ)); - res_templ.target = PIPE_TEXTURE_2D; - res_templ.last_level = 0; - res_templ.depth0 = 1; - res_templ.array_size = 1; - res_templ.width0 = memory_attribute->width; - res_templ.height0 = memory_attribute->height; - res_templ.bind = PIPE_BIND_SAMPLER_VIEW; - res_templ.usage = PIPE_USAGE_DEFAULT; - - memset(&whandle, 0, sizeof(struct winsys_handle)); - whandle.type = WINSYS_HANDLE_TYPE_FD; - whandle.handle = memory_attribute->buffers[index]; - - // Create a resource for each plane. - memset(resources, 0, sizeof resources); - for (i = 0; i < memory_attribute->num_planes; i++) { - res_templ.format = resource_formats[i]; - if (res_templ.format == PIPE_FORMAT_NONE) { - result = VA_STATUS_ERROR_INVALID_PARAMETER; - goto fail; - } - - whandle.stride = memory_attribute->pitches[i]; - whandle.offset = memory_attribute->offsets[i]; - resources[i] = pscreen->resource_from_handle(pscreen, &res_templ, &whandle, - PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE); - if (!resources[i]) { - result = VA_STATUS_ERROR_ALLOCATION_FAILED; - goto fail; - } - } - - surface->buffer = vl_video_buffer_create_ex2(drv->pipe, templat, resources); - if (!surface->buffer) { - result = VA_STATUS_ERROR_ALLOCATION_FAILED; - goto fail; - } - return VA_STATUS_SUCCESS; - -fail: - for (i = 0; i < VL_NUM_COMPONENTS; i++) - pipe_resource_reference(&resources[i], NULL); - return result; -} - -VAStatus -vlVaHandleSurfaceAllocate(vlVaDriver *drv, vlVaSurface *surface, - struct pipe_video_buffer *templat) -{ - struct pipe_surface **surfaces; - unsigned i; - - surface->buffer = drv->pipe->create_video_buffer(drv->pipe, templat); - if (!surface->buffer) - return VA_STATUS_ERROR_ALLOCATION_FAILED; - - surfaces = surface->buffer->get_surfaces(surface->buffer); - for (i = 0; i < VL_MAX_SURFACES; ++i) { - union pipe_color_union c = {}; - - if (!surfaces[i]) - continue; - - if (i > !!surface->buffer->interlaced) - c.f[0] = c.f[1] = c.f[2] = c.f[3] = 0.5f; - - drv->pipe->clear_render_target(drv->pipe, surfaces[i], &c, 0, 0, - surfaces[i]->width, surfaces[i]->height, - false); - } - drv->pipe->flush(drv->pipe, NULL, 0); - - return VA_STATUS_SUCCESS; -} - -VAStatus -vlVaCreateSurfaces2(VADriverContextP ctx, unsigned int format, - unsigned int width, unsigned int height, - VASurfaceID *surfaces, unsigned int num_surfaces, - VASurfaceAttrib *attrib_list, unsigned int num_attribs) -{ - vlVaDriver *drv; - VASurfaceAttribExternalBuffers *memory_attribute; - struct pipe_video_buffer templat; - struct pipe_screen *pscreen; - int i; - int memory_type; - int expected_fourcc; - VAStatus vaStatus; - vlVaSurface *surf; - - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - if (!(width && height)) - return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT; - - drv = VL_VA_DRIVER(ctx); - - if (!drv) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - pscreen = VL_VA_PSCREEN(ctx); - - if (!pscreen) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - /* Default. */ - memory_attribute = NULL; - memory_type = VA_SURFACE_ATTRIB_MEM_TYPE_VA; - expected_fourcc = 0; - - for (i = 0; i < num_attribs && attrib_list; i++) { - if ((attrib_list[i].type == VASurfaceAttribPixelFormat) && - (attrib_list[i].flags & VA_SURFACE_ATTRIB_SETTABLE)) { - if (attrib_list[i].value.type != VAGenericValueTypeInteger) - return VA_STATUS_ERROR_INVALID_PARAMETER; - expected_fourcc = attrib_list[i].value.value.i; - } - - if ((attrib_list[i].type == VASurfaceAttribMemoryType) && - (attrib_list[i].flags & VA_SURFACE_ATTRIB_SETTABLE)) { - - if (attrib_list[i].value.type != VAGenericValueTypeInteger) - return VA_STATUS_ERROR_INVALID_PARAMETER; - - switch (attrib_list[i].value.value.i) { - case VA_SURFACE_ATTRIB_MEM_TYPE_VA: - case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME: - memory_type = attrib_list[i].value.value.i; - break; - default: - return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE; - } - } - - if ((attrib_list[i].type == VASurfaceAttribExternalBufferDescriptor) && - (attrib_list[i].flags == VA_SURFACE_ATTRIB_SETTABLE)) { - if (attrib_list[i].value.type != VAGenericValueTypePointer) - return VA_STATUS_ERROR_INVALID_PARAMETER; - memory_attribute = (VASurfaceAttribExternalBuffers *)attrib_list[i].value.value.p; - } - } - - if (VA_RT_FORMAT_YUV420 != format && - VA_RT_FORMAT_YUV422 != format && - VA_RT_FORMAT_YUV444 != format && - VA_RT_FORMAT_YUV420_10BPP != format && - VA_RT_FORMAT_RGB32 != format) { - return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT; - } - - switch (memory_type) { - case VA_SURFACE_ATTRIB_MEM_TYPE_VA: - break; - case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME: - if (!memory_attribute) - return VA_STATUS_ERROR_INVALID_PARAMETER; - - expected_fourcc = memory_attribute->pixel_format; - break; - default: - assert(0); - } - - memset(&templat, 0, sizeof(templat)); - - templat.buffer_format = pscreen->get_video_param( - pscreen, - PIPE_VIDEO_PROFILE_UNKNOWN, - PIPE_VIDEO_ENTRYPOINT_BITSTREAM, - PIPE_VIDEO_CAP_PREFERED_FORMAT - ); - templat.interlaced = pscreen->get_video_param( - pscreen, - PIPE_VIDEO_PROFILE_UNKNOWN, - PIPE_VIDEO_ENTRYPOINT_BITSTREAM, - PIPE_VIDEO_CAP_PREFERS_INTERLACED - ); - - if (expected_fourcc) { - enum pipe_format expected_format = VaFourccToPipeFormat(expected_fourcc); - - if (expected_format != templat.buffer_format || memory_attribute) - templat.interlaced = 0; - - templat.buffer_format = expected_format; - } - - templat.width = width; - templat.height = height; - - memset(surfaces, VA_INVALID_ID, num_surfaces * sizeof(VASurfaceID)); - - mtx_lock(&drv->mutex); - for (i = 0; i < num_surfaces; i++) { - surf = CALLOC(1, sizeof(vlVaSurface)); - if (!surf) { - vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; - goto no_res; - } - - surf->templat = templat; - - switch (memory_type) { - case VA_SURFACE_ATTRIB_MEM_TYPE_VA: - /* The application will clear the TILING flag when the surface is - * intended to be exported as dmabuf. Adding shared flag because not - * null memory_attribute means VASurfaceAttribExternalBuffers is used. - */ - if (memory_attribute && - !(memory_attribute->flags & VA_SURFACE_EXTBUF_DESC_ENABLE_TILING)) - templat.bind = PIPE_BIND_LINEAR | PIPE_BIND_SHARED; - - vaStatus = vlVaHandleSurfaceAllocate(drv, surf, &templat); - if (vaStatus != VA_STATUS_SUCCESS) - goto free_surf; - break; - - case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME: - vaStatus = surface_from_external_memory(ctx, surf, memory_attribute, i, &templat); - if (vaStatus != VA_STATUS_SUCCESS) - goto free_surf; - break; - - default: - assert(0); - } - - util_dynarray_init(&surf->subpics, NULL); - surfaces[i] = handle_table_add(drv->htab, surf); - if (!surfaces[i]) { - vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; - goto destroy_surf; - } - } - mtx_unlock(&drv->mutex); - - return VA_STATUS_SUCCESS; - -destroy_surf: - surf->buffer->destroy(surf->buffer); - -free_surf: - FREE(surf); - -no_res: - mtx_unlock(&drv->mutex); - if (i) - vlVaDestroySurfaces(ctx, surfaces, i); - - return vaStatus; -} - -VAStatus -vlVaQueryVideoProcFilters(VADriverContextP ctx, VAContextID context, - VAProcFilterType *filters, unsigned int *num_filters) -{ - unsigned int num = 0; - - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - if (!num_filters || !filters) - return VA_STATUS_ERROR_INVALID_PARAMETER; - - filters[num++] = VAProcFilterDeinterlacing; - - *num_filters = num; - - return VA_STATUS_SUCCESS; -} - -VAStatus -vlVaQueryVideoProcFilterCaps(VADriverContextP ctx, VAContextID context, - VAProcFilterType type, void *filter_caps, - unsigned int *num_filter_caps) -{ - unsigned int i; - - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - if (!filter_caps || !num_filter_caps) - return VA_STATUS_ERROR_INVALID_PARAMETER; - - i = 0; - - switch (type) { - case VAProcFilterNone: - break; - case VAProcFilterDeinterlacing: { - VAProcFilterCapDeinterlacing *deint = filter_caps; - - if (*num_filter_caps < 3) { - *num_filter_caps = 3; - return VA_STATUS_ERROR_MAX_NUM_EXCEEDED; - } - - deint[i++].type = VAProcDeinterlacingBob; - deint[i++].type = VAProcDeinterlacingWeave; - deint[i++].type = VAProcDeinterlacingMotionAdaptive; - break; - } - - case VAProcFilterNoiseReduction: - case VAProcFilterSharpening: - case VAProcFilterColorBalance: - case VAProcFilterSkinToneEnhancement: - return VA_STATUS_ERROR_UNIMPLEMENTED; - default: - assert(0); - } - - *num_filter_caps = i; - - return VA_STATUS_SUCCESS; -} - -static VAProcColorStandardType vpp_input_color_standards[] = { - VAProcColorStandardBT601 -}; - -static VAProcColorStandardType vpp_output_color_standards[] = { - VAProcColorStandardBT601 -}; - -VAStatus -vlVaQueryVideoProcPipelineCaps(VADriverContextP ctx, VAContextID context, - VABufferID *filters, unsigned int num_filters, - VAProcPipelineCaps *pipeline_cap) -{ - unsigned int i = 0; - - if (!ctx) - return VA_STATUS_ERROR_INVALID_CONTEXT; - - if (!pipeline_cap) - return VA_STATUS_ERROR_INVALID_PARAMETER; - - if (num_filters && !filters) - return VA_STATUS_ERROR_INVALID_PARAMETER; - - pipeline_cap->pipeline_flags = 0; - pipeline_cap->filter_flags = 0; - pipeline_cap->num_forward_references = 0; - pipeline_cap->num_backward_references = 0; - pipeline_cap->num_input_color_standards = ARRAY_SIZE(vpp_input_color_standards); - pipeline_cap->input_color_standards = vpp_input_color_standards; - pipeline_cap->num_output_color_standards = ARRAY_SIZE(vpp_output_color_standards); - pipeline_cap->output_color_standards = vpp_output_color_standards; - - for (i = 0; i < num_filters; i++) { - vlVaBuffer *buf = handle_table_get(VL_VA_DRIVER(ctx)->htab, filters[i]); - VAProcFilterParameterBufferBase *filter; - - if (!buf || buf->type != VAProcFilterParameterBufferType) - return VA_STATUS_ERROR_INVALID_BUFFER; - - filter = buf->data; - switch (filter->type) { - case VAProcFilterDeinterlacing: { - VAProcFilterParameterBufferDeinterlacing *deint = buf->data; - if (deint->algorithm == VAProcDeinterlacingMotionAdaptive) { - pipeline_cap->num_forward_references = 2; - pipeline_cap->num_backward_references = 1; - } - break; - } - default: - return VA_STATUS_ERROR_UNIMPLEMENTED; - } - } - - return VA_STATUS_SUCCESS; -} - -#if VA_CHECK_VERSION(1, 1, 0) -VAStatus -vlVaExportSurfaceHandle(VADriverContextP ctx, - VASurfaceID surface_id, - uint32_t mem_type, - uint32_t flags, - void *descriptor) -{ - vlVaDriver *drv; - vlVaSurface *surf; - struct pipe_surface **surfaces; - struct pipe_screen *screen; - VAStatus ret; - unsigned int usage; - int i, p; - - VADRMPRIMESurfaceDescriptor *desc = descriptor; - - if (mem_type != VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2) - return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE; - if (flags & VA_EXPORT_SURFACE_COMPOSED_LAYERS) - return VA_STATUS_ERROR_INVALID_SURFACE; - - drv = VL_VA_DRIVER(ctx); - screen = VL_VA_PSCREEN(ctx); - mtx_lock(&drv->mutex); - - surf = handle_table_get(drv->htab, surface_id); - if (!surf || !surf->buffer) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_INVALID_SURFACE; - } - - if (surf->buffer->interlaced) { - struct pipe_video_buffer *interlaced = surf->buffer; - struct u_rect src_rect, dst_rect; - - surf->templat.interlaced = false; - - ret = vlVaHandleSurfaceAllocate(drv, surf, &surf->templat); - if (ret != VA_STATUS_SUCCESS) { - mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_ALLOCATION_FAILED; - } - - src_rect.x0 = dst_rect.x0 = 0; - src_rect.y0 = dst_rect.y0 = 0; - src_rect.x1 = dst_rect.x1 = surf->templat.width; - src_rect.y1 = dst_rect.y1 = surf->templat.height; - - vl_compositor_yuv_deint_full(&drv->cstate, &drv->compositor, - interlaced, surf->buffer, - &src_rect, &dst_rect, - VL_COMPOSITOR_WEAVE); - - interlaced->destroy(interlaced); - } - - surfaces = surf->buffer->get_surfaces(surf->buffer); - - usage = 0; - if (flags & VA_EXPORT_SURFACE_WRITE_ONLY) - usage |= PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE; - - desc->fourcc = PipeFormatToVaFourcc(surf->buffer->buffer_format); - desc->width = surf->buffer->width; - desc->height = surf->buffer->height; - - for (p = 0; p < VL_MAX_SURFACES; p++) { - struct winsys_handle whandle; - struct pipe_resource *resource; - uint32_t drm_format; - - if (!surfaces[p]) - break; - - resource = surfaces[p]->texture; - - switch (resource->format) { - case PIPE_FORMAT_R8_UNORM: - drm_format = DRM_FORMAT_R8; - break; - case PIPE_FORMAT_R8G8_UNORM: - drm_format = DRM_FORMAT_GR88; - break; - case PIPE_FORMAT_R16_UNORM: - drm_format = DRM_FORMAT_R16; - break; - case PIPE_FORMAT_R16G16_UNORM: - drm_format = DRM_FORMAT_GR1616; - break; - case PIPE_FORMAT_B8G8R8A8_UNORM: - drm_format = DRM_FORMAT_ARGB8888; - break; - case PIPE_FORMAT_R8G8B8A8_UNORM: - drm_format = DRM_FORMAT_ABGR8888; - break; - case PIPE_FORMAT_B8G8R8X8_UNORM: - drm_format = DRM_FORMAT_XRGB8888; - break; - case PIPE_FORMAT_R8G8B8X8_UNORM: - drm_format = DRM_FORMAT_XBGR8888; - break; - default: - ret = VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE; - goto fail; - } - - memset(&whandle, 0, sizeof(whandle)); - whandle.type = WINSYS_HANDLE_TYPE_FD; - - if (!screen->resource_get_handle(screen, drv->pipe, resource, - &whandle, usage)) { - ret = VA_STATUS_ERROR_INVALID_SURFACE; - goto fail; - } - - desc->objects[p].fd = (int)whandle.handle; - desc->objects[p].size = 0; - desc->objects[p].drm_format_modifier = whandle.modifier; - - desc->layers[p].drm_format = drm_format; - desc->layers[p].num_planes = 1; - desc->layers[p].object_index[0] = p; - desc->layers[p].offset[0] = whandle.offset; - desc->layers[p].pitch[0] = whandle.stride; - } - - desc->num_objects = p; - desc->num_layers = p; - - mtx_unlock(&drv->mutex); - - return VA_STATUS_SUCCESS; - -fail: - for (i = 0; i < p; i++) - close(desc->objects[i].fd); - - mtx_unlock(&drv->mutex); - - return ret; -} -#endif diff --git a/src/gallium/state_trackers/va/va_private.h b/src/gallium/state_trackers/va/va_private.h deleted file mode 100644 index e3a9790103b..00000000000 --- a/src/gallium/state_trackers/va/va_private.h +++ /dev/null @@ -1,462 +0,0 @@ -/************************************************************************** - * - * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian. - * Copyright 2014 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#ifndef VA_PRIVATE_H -#define VA_PRIVATE_H - -#include - -#include -#include -#include -#include - -#include "pipe/p_video_enums.h" -#include "pipe/p_video_codec.h" -#include "pipe/p_video_state.h" - -#include "vl/vl_compositor.h" -#include "vl/vl_csc.h" - -#include "util/u_dynarray.h" -#include "os/os_thread.h" - -#define VL_VA_DRIVER(ctx) ((vlVaDriver *)ctx->pDriverData) -#define VL_VA_PSCREEN(ctx) (VL_VA_DRIVER(ctx)->vscreen->pscreen) - -#define VL_VA_MAX_IMAGE_FORMATS 12 -#define VL_VA_ENC_GOP_COEFF 16 - -#define UINT_TO_PTR(x) ((void*)(uintptr_t)(x)) -#define PTR_TO_UINT(x) ((unsigned)((intptr_t)(x))) - -#define SOI 2 -#define DQT (4 + 4 * 65) -#define DHT (4 + 2 * 29 + 2 * 179) -#define DRI 6 -#define SOF (10 + 255 * 3) -#define SOS (8 + 4 * 2) -#define MAX_MJPEG_SLICE_HEADER_SIZE (SOI + DQT + DHT + DRI + SOF + SOS) - -static inline enum pipe_video_chroma_format -ChromaToPipe(int format) -{ - switch (format) { - case VA_RT_FORMAT_YUV420: - case VA_RT_FORMAT_YUV420_10BPP: - return PIPE_VIDEO_CHROMA_FORMAT_420; - case VA_RT_FORMAT_YUV422: - return PIPE_VIDEO_CHROMA_FORMAT_422; - case VA_RT_FORMAT_YUV444: - return PIPE_VIDEO_CHROMA_FORMAT_444; - default: - return PIPE_VIDEO_CHROMA_FORMAT_NONE; - } -} - -static inline enum pipe_format -VaFourccToPipeFormat(unsigned format) -{ - switch(format) { - case VA_FOURCC('N','V','1','2'): - return PIPE_FORMAT_NV12; - case VA_FOURCC('P','0','1','0'): - return PIPE_FORMAT_P010; - case VA_FOURCC('P','0','1','6'): - return PIPE_FORMAT_P016; - case VA_FOURCC('I','4','2','0'): - return PIPE_FORMAT_IYUV; - case VA_FOURCC('Y','V','1','2'): - return PIPE_FORMAT_YV12; - case VA_FOURCC('Y','U','Y','V'): - case VA_FOURCC('Y','U','Y','2'): - return PIPE_FORMAT_YUYV; - case VA_FOURCC('U','Y','V','Y'): - return PIPE_FORMAT_UYVY; - case VA_FOURCC('B','G','R','A'): - return PIPE_FORMAT_B8G8R8A8_UNORM; - case VA_FOURCC('R','G','B','A'): - return PIPE_FORMAT_R8G8B8A8_UNORM; - case VA_FOURCC('B','G','R','X'): - return PIPE_FORMAT_B8G8R8X8_UNORM; - case VA_FOURCC('R','G','B','X'): - return PIPE_FORMAT_R8G8B8X8_UNORM; - default: - assert(0); - return PIPE_FORMAT_NONE; - } -} - -static inline unsigned -PipeFormatToVaFourcc(enum pipe_format p_format) -{ - switch (p_format) { - case PIPE_FORMAT_NV12: - return VA_FOURCC('N','V','1','2'); - case PIPE_FORMAT_P010: - return VA_FOURCC('P','0','1','0'); - case PIPE_FORMAT_P016: - return VA_FOURCC('P','0','1','6'); - case PIPE_FORMAT_IYUV: - return VA_FOURCC('I','4','2','0'); - case PIPE_FORMAT_YV12: - return VA_FOURCC('Y','V','1','2'); - case PIPE_FORMAT_UYVY: - return VA_FOURCC('U','Y','V','Y'); - case PIPE_FORMAT_YUYV: - return VA_FOURCC('Y','U','Y','V'); - case PIPE_FORMAT_B8G8R8A8_UNORM: - return VA_FOURCC('B','G','R','A'); - case PIPE_FORMAT_R8G8B8A8_UNORM: - return VA_FOURCC('R','G','B','A'); - case PIPE_FORMAT_B8G8R8X8_UNORM: - return VA_FOURCC('B','G','R','X'); - case PIPE_FORMAT_R8G8B8X8_UNORM: - return VA_FOURCC('R','G','B','X'); - default: - assert(0); - return -1; - } -} - -static inline VAProfile -PipeToProfile(enum pipe_video_profile profile) -{ - switch (profile) { - case PIPE_VIDEO_PROFILE_MPEG2_SIMPLE: - return VAProfileMPEG2Simple; - case PIPE_VIDEO_PROFILE_MPEG2_MAIN: - return VAProfileMPEG2Main; - case PIPE_VIDEO_PROFILE_MPEG4_SIMPLE: - return VAProfileMPEG4Simple; - case PIPE_VIDEO_PROFILE_MPEG4_ADVANCED_SIMPLE: - return VAProfileMPEG4AdvancedSimple; - case PIPE_VIDEO_PROFILE_VC1_SIMPLE: - return VAProfileVC1Simple; - case PIPE_VIDEO_PROFILE_VC1_MAIN: - return VAProfileVC1Main; - case PIPE_VIDEO_PROFILE_VC1_ADVANCED: - return VAProfileVC1Advanced; - case PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE: - return VAProfileH264ConstrainedBaseline; - case PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN: - return VAProfileH264Main; - case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH: - return VAProfileH264High; - case PIPE_VIDEO_PROFILE_HEVC_MAIN: - return VAProfileHEVCMain; - case PIPE_VIDEO_PROFILE_HEVC_MAIN_10: - return VAProfileHEVCMain10; - case PIPE_VIDEO_PROFILE_JPEG_BASELINE: - return VAProfileJPEGBaseline; - case PIPE_VIDEO_PROFILE_VP9_PROFILE0: - return VAProfileVP9Profile0; - case PIPE_VIDEO_PROFILE_VP9_PROFILE2: - return VAProfileVP9Profile2; - case PIPE_VIDEO_PROFILE_MPEG4_AVC_EXTENDED: - case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH10: - case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH422: - case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH444: - case PIPE_VIDEO_PROFILE_MPEG4_AVC_CONSTRAINED_BASELINE: - case PIPE_VIDEO_PROFILE_HEVC_MAIN_12: - case PIPE_VIDEO_PROFILE_HEVC_MAIN_STILL: - case PIPE_VIDEO_PROFILE_HEVC_MAIN_444: - case PIPE_VIDEO_PROFILE_UNKNOWN: - return VAProfileNone; - default: - assert(0); - return -1; - } -} - -static inline enum pipe_video_profile -ProfileToPipe(VAProfile profile) -{ - switch (profile) { - case VAProfileMPEG2Simple: - return PIPE_VIDEO_PROFILE_MPEG2_SIMPLE; - case VAProfileMPEG2Main: - return PIPE_VIDEO_PROFILE_MPEG2_MAIN; - case VAProfileMPEG4Simple: - return PIPE_VIDEO_PROFILE_MPEG4_SIMPLE; - case VAProfileMPEG4AdvancedSimple: - return PIPE_VIDEO_PROFILE_MPEG4_ADVANCED_SIMPLE; - case VAProfileVC1Simple: - return PIPE_VIDEO_PROFILE_VC1_SIMPLE; - case VAProfileVC1Main: - return PIPE_VIDEO_PROFILE_VC1_MAIN; - case VAProfileVC1Advanced: - return PIPE_VIDEO_PROFILE_VC1_ADVANCED; - case VAProfileH264ConstrainedBaseline: - return PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE; - case VAProfileH264Main: - return PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN; - case VAProfileH264High: - return PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH; - case VAProfileHEVCMain: - return PIPE_VIDEO_PROFILE_HEVC_MAIN; - case VAProfileHEVCMain10: - return PIPE_VIDEO_PROFILE_HEVC_MAIN_10; - case VAProfileJPEGBaseline: - return PIPE_VIDEO_PROFILE_JPEG_BASELINE; - case VAProfileVP9Profile0: - return PIPE_VIDEO_PROFILE_VP9_PROFILE0; - case VAProfileVP9Profile2: - return PIPE_VIDEO_PROFILE_VP9_PROFILE2; - case VAProfileNone: - return PIPE_VIDEO_PROFILE_UNKNOWN; - default: - return PIPE_VIDEO_PROFILE_UNKNOWN; - } -} - -typedef struct { - struct vl_screen *vscreen; - struct pipe_context *pipe; - struct handle_table *htab; - struct vl_compositor compositor; - struct vl_compositor_state cstate; - vl_csc_matrix csc; - mtx_t mutex; - char vendor_string[256]; -} vlVaDriver; - -typedef struct { - VAImage *image; - - struct u_rect src_rect; - struct u_rect dst_rect; - - struct pipe_sampler_view *sampler; -} vlVaSubpicture; - -typedef struct { - VABufferType type; - unsigned int size; - unsigned int num_elements; - void *data; - struct { - struct pipe_resource *resource; - struct pipe_transfer *transfer; - } derived_surface; - unsigned int export_refcount; - VABufferInfo export_state; - unsigned int coded_size; -} vlVaBuffer; - -typedef struct { - struct pipe_video_codec templat, *decoder; - struct pipe_video_buffer *target; - union { - struct pipe_picture_desc base; - struct pipe_mpeg12_picture_desc mpeg12; - struct pipe_mpeg4_picture_desc mpeg4; - struct pipe_vc1_picture_desc vc1; - struct pipe_h264_picture_desc h264; - struct pipe_h265_picture_desc h265; - struct pipe_mjpeg_picture_desc mjpeg; - struct pipe_vp9_picture_desc vp9; - struct pipe_h264_enc_picture_desc h264enc; - struct pipe_h265_enc_picture_desc h265enc; - } desc; - - struct { - unsigned long long int frame_num; - unsigned int start_code_size; - unsigned int vti_bits; - unsigned int quant_scale; - VAPictureParameterBufferMPEG4 pps; - uint8_t start_code[32]; - } mpeg4; - - struct { - unsigned sampling_factor; - uint8_t slice_header[MAX_MJPEG_SLICE_HEADER_SIZE]; - unsigned int slice_header_size; - } mjpeg; - - struct vl_deint_filter *deint; - vlVaBuffer *coded_buf; - int target_id; - bool first_single_submitted; - int gop_coeff; - bool needs_begin_frame; - void *blit_cs; -} vlVaContext; - -typedef struct { - enum pipe_video_profile profile; - enum pipe_video_entrypoint entrypoint; - enum pipe_h264_enc_rate_control_method rc; - unsigned int rt_format; -} vlVaConfig; - -typedef struct { - struct pipe_video_buffer templat, *buffer; - struct util_dynarray subpics; /* vlVaSubpicture */ - VAContextID ctx; - vlVaBuffer *coded_buf; - void *feedback; - unsigned int frame_num_cnt; - bool force_flushed; -} vlVaSurface; - -// Public functions: -VAStatus VA_DRIVER_INIT_FUNC(VADriverContextP ctx); - -// vtable functions: -VAStatus vlVaTerminate(VADriverContextP ctx); -VAStatus vlVaQueryConfigProfiles(VADriverContextP ctx, VAProfile *profile_list,int *num_profiles); -VAStatus vlVaQueryConfigEntrypoints(VADriverContextP ctx, VAProfile profile, - VAEntrypoint *entrypoint_list, int *num_entrypoints); -VAStatus vlVaGetConfigAttributes(VADriverContextP ctx, VAProfile profile, VAEntrypoint entrypoint, - VAConfigAttrib *attrib_list, int num_attribs); -VAStatus vlVaCreateConfig(VADriverContextP ctx, VAProfile profile, VAEntrypoint entrypoint, - VAConfigAttrib *attrib_list, int num_attribs, VAConfigID *config_id); -VAStatus vlVaDestroyConfig(VADriverContextP ctx, VAConfigID config_id); -VAStatus vlVaQueryConfigAttributes(VADriverContextP ctx, VAConfigID config_id, VAProfile *profile, - VAEntrypoint *entrypoint, VAConfigAttrib *attrib_list, int *num_attribs); -VAStatus vlVaCreateSurfaces(VADriverContextP ctx, int width, int height, int format, - int num_surfaces, VASurfaceID *surfaces); -VAStatus vlVaDestroySurfaces(VADriverContextP ctx, VASurfaceID *surface_list, int num_surfaces); -VAStatus vlVaCreateContext(VADriverContextP ctx, VAConfigID config_id, int picture_width, int picture_height, - int flag, VASurfaceID *render_targets, int num_render_targets, VAContextID *context); -VAStatus vlVaDestroyContext(VADriverContextP ctx, VAContextID context); -VAStatus vlVaCreateBuffer(VADriverContextP ctx, VAContextID context, VABufferType type, unsigned int size, - unsigned int num_elements, void *data, VABufferID *buf_id); -VAStatus vlVaBufferSetNumElements(VADriverContextP ctx, VABufferID buf_id, unsigned int num_elements); -VAStatus vlVaMapBuffer(VADriverContextP ctx, VABufferID buf_id, void **pbuf); -VAStatus vlVaUnmapBuffer(VADriverContextP ctx, VABufferID buf_id); -VAStatus vlVaDestroyBuffer(VADriverContextP ctx, VABufferID buffer_id); -VAStatus vlVaBeginPicture(VADriverContextP ctx, VAContextID context, VASurfaceID render_target); -VAStatus vlVaRenderPicture(VADriverContextP ctx, VAContextID context, VABufferID *buffers, int num_buffers); -VAStatus vlVaEndPicture(VADriverContextP ctx, VAContextID context); -VAStatus vlVaSyncSurface(VADriverContextP ctx, VASurfaceID render_target); -VAStatus vlVaQuerySurfaceStatus(VADriverContextP ctx, VASurfaceID render_target, VASurfaceStatus *status); -VAStatus vlVaQuerySurfaceError(VADriverContextP ctx, VASurfaceID render_target, - VAStatus error_status, void **error_info); -VAStatus vlVaPutSurface(VADriverContextP ctx, VASurfaceID surface, void* draw, short srcx, short srcy, - unsigned short srcw, unsigned short srch, short destx, short desty, unsigned short destw, - unsigned short desth, VARectangle *cliprects, unsigned int number_cliprects, - unsigned int flags); -VAStatus vlVaQueryImageFormats(VADriverContextP ctx, VAImageFormat *format_list, int *num_formats); -VAStatus vlVaQuerySubpictureFormats(VADriverContextP ctx, VAImageFormat *format_list, - unsigned int *flags, unsigned int *num_formats); -VAStatus vlVaCreateImage(VADriverContextP ctx, VAImageFormat *format, int width, int height, VAImage *image); -VAStatus vlVaDeriveImage(VADriverContextP ctx, VASurfaceID surface, VAImage *image); -VAStatus vlVaDestroyImage(VADriverContextP ctx, VAImageID image); -VAStatus vlVaSetImagePalette(VADriverContextP ctx, VAImageID image, unsigned char *palette); -VAStatus vlVaGetImage(VADriverContextP ctx, VASurfaceID surface, int x, int y, - unsigned int width, unsigned int height, VAImageID image); -VAStatus vlVaPutImage(VADriverContextP ctx, VASurfaceID surface, VAImageID image, int src_x, int src_y, - unsigned int src_width, unsigned int src_height, int dest_x, int dest_y, - unsigned int dest_width, unsigned int dest_height); -VAStatus vlVaQuerySubpictureFormats(VADriverContextP ctx, VAImageFormat *format_list, - unsigned int *flags, unsigned int *num_formats); -VAStatus vlVaCreateSubpicture(VADriverContextP ctx, VAImageID image, VASubpictureID *subpicture); -VAStatus vlVaDestroySubpicture(VADriverContextP ctx, VASubpictureID subpicture); -VAStatus vlVaSubpictureImage(VADriverContextP ctx, VASubpictureID subpicture, VAImageID image); -VAStatus vlVaSetSubpictureChromakey(VADriverContextP ctx, VASubpictureID subpicture, - unsigned int chromakey_min, unsigned int chromakey_max, - unsigned int chromakey_mask); -VAStatus vlVaSetSubpictureGlobalAlpha(VADriverContextP ctx, VASubpictureID subpicture, float global_alpha); -VAStatus vlVaAssociateSubpicture(VADriverContextP ctx, VASubpictureID subpicture, VASurfaceID *target_surfaces, - int num_surfaces, short src_x, short src_y, - unsigned short src_width, unsigned short src_height, - short dest_x, short dest_y, unsigned short dest_width, unsigned short dest_height, - unsigned int flags); -VAStatus vlVaDeassociateSubpicture(VADriverContextP ctx, VASubpictureID subpicture, - VASurfaceID *target_surfaces, int num_surfaces); -VAStatus vlVaQueryDisplayAttributes(VADriverContextP ctx, VADisplayAttribute *attr_list, int *num_attributes); -VAStatus vlVaGetDisplayAttributes(VADriverContextP ctx, VADisplayAttribute *attr_list, int num_attributes); -VAStatus vlVaSetDisplayAttributes(VADriverContextP ctx, VADisplayAttribute *attr_list, int num_attributes); -VAStatus vlVaBufferInfo(VADriverContextP ctx, VABufferID buf_id, VABufferType *type, - unsigned int *size, unsigned int *num_elements); -VAStatus vlVaLockSurface(VADriverContextP ctx, VASurfaceID surface, unsigned int *fourcc, - unsigned int *luma_stride, unsigned int *chroma_u_stride, unsigned int *chroma_v_stride, - unsigned int *luma_offset, unsigned int *chroma_u_offset, unsigned int *chroma_v_offset, - unsigned int *buffer_name, void **buffer); -VAStatus vlVaUnlockSurface(VADriverContextP ctx, VASurfaceID surface); -VAStatus vlVaCreateSurfaces2(VADriverContextP ctx, unsigned int format, unsigned int width, unsigned int height, - VASurfaceID *surfaces, unsigned int num_surfaces, VASurfaceAttrib *attrib_list, - unsigned int num_attribs); -VAStatus vlVaQuerySurfaceAttributes(VADriverContextP ctx, VAConfigID config, VASurfaceAttrib *attrib_list, - unsigned int *num_attribs); - -VAStatus vlVaAcquireBufferHandle(VADriverContextP ctx, VABufferID buf_id, VABufferInfo *out_buf_info); -VAStatus vlVaReleaseBufferHandle(VADriverContextP ctx, VABufferID buf_id); -VAStatus vlVaExportSurfaceHandle(VADriverContextP ctx, VASurfaceID surface_id, uint32_t mem_type, uint32_t flags, void *descriptor); - -VAStatus vlVaQueryVideoProcFilters(VADriverContextP ctx, VAContextID context, VAProcFilterType *filters, - unsigned int *num_filters); -VAStatus vlVaQueryVideoProcFilterCaps(VADriverContextP ctx, VAContextID context, VAProcFilterType type, - void *filter_caps, unsigned int *num_filter_caps); -VAStatus vlVaQueryVideoProcPipelineCaps(VADriverContextP ctx, VAContextID context, VABufferID *filters, - unsigned int num_filters, VAProcPipelineCaps *pipeline_cap); - -// internal functions -VAStatus vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf); -VAStatus vlVaHandleSurfaceAllocate(vlVaDriver *drv, vlVaSurface *surface, struct pipe_video_buffer *templat); -void vlVaGetReferenceFrame(vlVaDriver *drv, VASurfaceID surface_id, struct pipe_video_buffer **ref_frame); -void vlVaHandlePictureParameterBufferMPEG12(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf); -void vlVaHandleIQMatrixBufferMPEG12(vlVaContext *context, vlVaBuffer *buf); -void vlVaHandleSliceParameterBufferMPEG12(vlVaContext *context, vlVaBuffer *buf); -void vlVaHandlePictureParameterBufferH264(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf); -void vlVaHandleIQMatrixBufferH264(vlVaContext *context, vlVaBuffer *buf); -void vlVaHandleSliceParameterBufferH264(vlVaContext *context, vlVaBuffer *buf); -void vlVaHandlePictureParameterBufferVC1(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf); -void vlVaHandleSliceParameterBufferVC1(vlVaContext *context, vlVaBuffer *buf); -void vlVaHandlePictureParameterBufferMPEG4(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf); -void vlVaHandleIQMatrixBufferMPEG4(vlVaContext *context, vlVaBuffer *buf); -void vlVaHandleSliceParameterBufferMPEG4(vlVaContext *context, vlVaBuffer *buf); -void vlVaDecoderFixMPEG4Startcode(vlVaContext *context); -void vlVaGetJpegSliceHeader(vlVaContext *context); -void vlVaHandlePictureParameterBufferHEVC(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf); -void vlVaHandleIQMatrixBufferHEVC(vlVaContext *context, vlVaBuffer *buf); -void vlVaHandleSliceParameterBufferHEVC(vlVaContext *context, vlVaBuffer *buf); -void vlVaHandlePictureParameterBufferMJPEG(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf); -void vlVaHandleIQMatrixBufferMJPEG(vlVaContext *context, vlVaBuffer *buf); -void vlVaHandleHuffmanTableBufferType(vlVaContext *context, vlVaBuffer *buf); -void vlVaHandleSliceParameterBufferMJPEG(vlVaContext *context, vlVaBuffer *buf); -void vlVaHandlePictureParameterBufferVP9(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf); -void vlVaHandleSliceParameterBufferVP9(vlVaContext *context, vlVaBuffer *buf); -void vlVaDecoderVP9BitstreamHeader(vlVaContext *context, vlVaBuffer *buf); -void getEncParamPresetH264(vlVaContext *context); -void getEncParamPresetH265(vlVaContext *context); -VAStatus vlVaHandleVAEncPictureParameterBufferTypeH264(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf); -VAStatus vlVaHandleVAEncSliceParameterBufferTypeH264(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf); -VAStatus vlVaHandleVAEncSequenceParameterBufferTypeH264(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf); -VAStatus vlVaHandleVAEncMiscParameterTypeRateControlH264(vlVaContext *context, VAEncMiscParameterBuffer *buf); -VAStatus vlVaHandleVAEncMiscParameterTypeFrameRateH264(vlVaContext *context, VAEncMiscParameterBuffer *buf); -VAStatus vlVaHandleVAEncPictureParameterBufferTypeHEVC(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf); -VAStatus vlVaHandleVAEncSliceParameterBufferTypeHEVC(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf); -VAStatus vlVaHandleVAEncSequenceParameterBufferTypeHEVC(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf); -VAStatus vlVaHandleVAEncMiscParameterTypeRateControlHEVC(vlVaContext *context, VAEncMiscParameterBuffer *buf); -VAStatus vlVaHandleVAEncMiscParameterTypeFrameRateHEVC(vlVaContext *context, VAEncMiscParameterBuffer *buf); - -#endif //VA_PRIVATE_H diff --git a/src/gallium/state_trackers/vdpau/Makefile.sources b/src/gallium/state_trackers/vdpau/Makefile.sources deleted file mode 100644 index dfe0bcd043f..00000000000 --- a/src/gallium/state_trackers/vdpau/Makefile.sources +++ /dev/null @@ -1,13 +0,0 @@ -C_SOURCES := \ - bitmap.c \ - decode.c \ - device.c \ - ftab.c \ - htab.c \ - mixer.c \ - output.c \ - preemption.c \ - presentation.c \ - query.c \ - surface.c \ - vdpau_private.h diff --git a/src/gallium/state_trackers/vdpau/bitmap.c b/src/gallium/state_trackers/vdpau/bitmap.c deleted file mode 100644 index 643be75e618..00000000000 --- a/src/gallium/state_trackers/vdpau/bitmap.c +++ /dev/null @@ -1,209 +0,0 @@ -/************************************************************************** - * - * Copyright 2010 Thomas Balling Sørensen. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include - -#include "util/u_memory.h" -#include "util/u_sampler.h" - -#include "vdpau_private.h" - -/** - * Create a VdpBitmapSurface. - */ -VdpStatus -vlVdpBitmapSurfaceCreate(VdpDevice device, - VdpRGBAFormat rgba_format, - uint32_t width, uint32_t height, - VdpBool frequently_accessed, - VdpBitmapSurface *surface) -{ - struct pipe_context *pipe; - struct pipe_resource res_tmpl, *res; - struct pipe_sampler_view sv_templ; - VdpStatus ret; - - vlVdpBitmapSurface *vlsurface = NULL; - - if (!(width && height)) - return VDP_STATUS_INVALID_SIZE; - - vlVdpDevice *dev = vlGetDataHTAB(device); - if (!dev) - return VDP_STATUS_INVALID_HANDLE; - - pipe = dev->context; - if (!pipe) - return VDP_STATUS_INVALID_HANDLE; - - if (!surface) - return VDP_STATUS_INVALID_POINTER; - - vlsurface = CALLOC(1, sizeof(vlVdpBitmapSurface)); - if (!vlsurface) - return VDP_STATUS_RESOURCES; - - DeviceReference(&vlsurface->device, dev); - - memset(&res_tmpl, 0, sizeof(res_tmpl)); - res_tmpl.target = PIPE_TEXTURE_2D; - res_tmpl.format = VdpFormatRGBAToPipe(rgba_format); - res_tmpl.width0 = width; - res_tmpl.height0 = height; - res_tmpl.depth0 = 1; - res_tmpl.array_size = 1; - res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; - res_tmpl.usage = frequently_accessed ? PIPE_USAGE_DYNAMIC : PIPE_USAGE_DEFAULT; - - mtx_lock(&dev->mutex); - - if (!CheckSurfaceParams(pipe->screen, &res_tmpl)) { - ret = VDP_STATUS_RESOURCES; - goto err_unlock; - } - - res = pipe->screen->resource_create(pipe->screen, &res_tmpl); - if (!res) { - ret = VDP_STATUS_RESOURCES; - goto err_unlock; - } - - vlVdpDefaultSamplerViewTemplate(&sv_templ, res); - vlsurface->sampler_view = pipe->create_sampler_view(pipe, res, &sv_templ); - - pipe_resource_reference(&res, NULL); - - if (!vlsurface->sampler_view) { - ret = VDP_STATUS_RESOURCES; - goto err_unlock; - } - - mtx_unlock(&dev->mutex); - - *surface = vlAddDataHTAB(vlsurface); - if (*surface == 0) { - mtx_lock(&dev->mutex); - ret = VDP_STATUS_ERROR; - goto err_sampler; - } - - return VDP_STATUS_OK; - -err_sampler: - pipe_sampler_view_reference(&vlsurface->sampler_view, NULL); -err_unlock: - mtx_unlock(&dev->mutex); - DeviceReference(&vlsurface->device, NULL); - FREE(vlsurface); - return ret; -} - -/** - * Destroy a VdpBitmapSurface. - */ -VdpStatus -vlVdpBitmapSurfaceDestroy(VdpBitmapSurface surface) -{ - vlVdpBitmapSurface *vlsurface; - - vlsurface = vlGetDataHTAB(surface); - if (!vlsurface) - return VDP_STATUS_INVALID_HANDLE; - - mtx_lock(&vlsurface->device->mutex); - pipe_sampler_view_reference(&vlsurface->sampler_view, NULL); - mtx_unlock(&vlsurface->device->mutex); - - vlRemoveDataHTAB(surface); - DeviceReference(&vlsurface->device, NULL); - FREE(vlsurface); - - return VDP_STATUS_OK; -} - -/** - * Retrieve the parameters used to create a VdpBitmapSurface. - */ -VdpStatus -vlVdpBitmapSurfaceGetParameters(VdpBitmapSurface surface, - VdpRGBAFormat *rgba_format, - uint32_t *width, uint32_t *height, - VdpBool *frequently_accessed) -{ - vlVdpBitmapSurface *vlsurface; - struct pipe_resource *res; - - vlsurface = vlGetDataHTAB(surface); - if (!vlsurface) - return VDP_STATUS_INVALID_HANDLE; - - if (!(rgba_format && width && height && frequently_accessed)) - return VDP_STATUS_INVALID_POINTER; - - res = vlsurface->sampler_view->texture; - *rgba_format = PipeToFormatRGBA(res->format); - *width = res->width0; - *height = res->height0; - *frequently_accessed = res->usage == PIPE_USAGE_DYNAMIC; - - return VDP_STATUS_OK; -} - -/** - * Copy image data from application memory in the surface's native format to - * a VdpBitmapSurface. - */ -VdpStatus -vlVdpBitmapSurfacePutBitsNative(VdpBitmapSurface surface, - void const *const *source_data, - uint32_t const *source_pitches, - VdpRect const *destination_rect) -{ - vlVdpBitmapSurface *vlsurface; - struct pipe_box dst_box; - struct pipe_context *pipe; - - vlsurface = vlGetDataHTAB(surface); - if (!vlsurface) - return VDP_STATUS_INVALID_HANDLE; - - if (!(source_data && source_pitches)) - return VDP_STATUS_INVALID_POINTER; - - pipe = vlsurface->device->context; - - mtx_lock(&vlsurface->device->mutex); - - dst_box = RectToPipeBox(destination_rect, vlsurface->sampler_view->texture); - pipe->texture_subdata(pipe, vlsurface->sampler_view->texture, 0, - PIPE_TRANSFER_WRITE, &dst_box, *source_data, - *source_pitches, 0); - - mtx_unlock(&vlsurface->device->mutex); - - return VDP_STATUS_OK; -} diff --git a/src/gallium/state_trackers/vdpau/decode.c b/src/gallium/state_trackers/vdpau/decode.c deleted file mode 100644 index 8d3c58714a8..00000000000 --- a/src/gallium/state_trackers/vdpau/decode.c +++ /dev/null @@ -1,684 +0,0 @@ -/************************************************************************** - * - * Copyright 2010 Thomas Balling Sørensen. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include "util/u_memory.h" -#include "util/u_math.h" -#include "util/u_debug.h" -#include "util/u_video.h" - -#include "vl/vl_vlc.h" - -#include "vdpau_private.h" - -/** - * Create a VdpDecoder. - */ -VdpStatus -vlVdpDecoderCreate(VdpDevice device, - VdpDecoderProfile profile, - uint32_t width, uint32_t height, - uint32_t max_references, - VdpDecoder *decoder) -{ - struct pipe_video_codec templat = {}; - struct pipe_context *pipe; - struct pipe_screen *screen; - vlVdpDevice *dev; - vlVdpDecoder *vldecoder; - VdpStatus ret; - bool supported; - uint32_t maxwidth, maxheight; - - if (!decoder) - return VDP_STATUS_INVALID_POINTER; - *decoder = 0; - - if (!(width && height)) - return VDP_STATUS_INVALID_VALUE; - - templat.profile = ProfileToPipe(profile); - if (templat.profile == PIPE_VIDEO_PROFILE_UNKNOWN) - return VDP_STATUS_INVALID_DECODER_PROFILE; - - dev = vlGetDataHTAB(device); - if (!dev) - return VDP_STATUS_INVALID_HANDLE; - - pipe = dev->context; - screen = dev->vscreen->pscreen; - - mtx_lock(&dev->mutex); - - supported = screen->get_video_param - ( - screen, - templat.profile, - PIPE_VIDEO_ENTRYPOINT_BITSTREAM, - PIPE_VIDEO_CAP_SUPPORTED - ); - if (!supported) { - mtx_unlock(&dev->mutex); - return VDP_STATUS_INVALID_DECODER_PROFILE; - } - - maxwidth = screen->get_video_param - ( - screen, - templat.profile, - PIPE_VIDEO_ENTRYPOINT_BITSTREAM, - PIPE_VIDEO_CAP_MAX_WIDTH - ); - maxheight = screen->get_video_param - ( - screen, - templat.profile, - PIPE_VIDEO_ENTRYPOINT_BITSTREAM, - PIPE_VIDEO_CAP_MAX_HEIGHT - ); - if (width > maxwidth || height > maxheight) { - mtx_unlock(&dev->mutex); - return VDP_STATUS_INVALID_SIZE; - } - - vldecoder = CALLOC(1,sizeof(vlVdpDecoder)); - if (!vldecoder) { - mtx_unlock(&dev->mutex); - return VDP_STATUS_RESOURCES; - } - - DeviceReference(&vldecoder->device, dev); - - templat.entrypoint = PIPE_VIDEO_ENTRYPOINT_BITSTREAM; - templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; - templat.width = width; - templat.height = height; - templat.max_references = max_references; - - if (u_reduce_video_profile(templat.profile) == - PIPE_VIDEO_FORMAT_MPEG4_AVC) - templat.level = u_get_h264_level(templat.width, templat.height, - &templat.max_references); - - vldecoder->decoder = pipe->create_video_codec(pipe, &templat); - - if (!vldecoder->decoder) { - ret = VDP_STATUS_ERROR; - goto error_decoder; - } - - *decoder = vlAddDataHTAB(vldecoder); - if (*decoder == 0) { - ret = VDP_STATUS_ERROR; - goto error_handle; - } - - (void) mtx_init(&vldecoder->mutex, mtx_plain); - mtx_unlock(&dev->mutex); - - return VDP_STATUS_OK; - -error_handle: - vldecoder->decoder->destroy(vldecoder->decoder); - -error_decoder: - mtx_unlock(&dev->mutex); - DeviceReference(&vldecoder->device, NULL); - FREE(vldecoder); - return ret; -} - -/** - * Destroy a VdpDecoder. - */ -VdpStatus -vlVdpDecoderDestroy(VdpDecoder decoder) -{ - vlVdpDecoder *vldecoder; - - vldecoder = (vlVdpDecoder *)vlGetDataHTAB(decoder); - if (!vldecoder) - return VDP_STATUS_INVALID_HANDLE; - - mtx_lock(&vldecoder->mutex); - vldecoder->decoder->destroy(vldecoder->decoder); - mtx_unlock(&vldecoder->mutex); - mtx_destroy(&vldecoder->mutex); - - vlRemoveDataHTAB(decoder); - DeviceReference(&vldecoder->device, NULL); - FREE(vldecoder); - - return VDP_STATUS_OK; -} - -/** - * Retrieve the parameters used to create a VdpDecoder. - */ -VdpStatus -vlVdpDecoderGetParameters(VdpDecoder decoder, - VdpDecoderProfile *profile, - uint32_t *width, - uint32_t *height) -{ - vlVdpDecoder *vldecoder; - - vldecoder = (vlVdpDecoder *)vlGetDataHTAB(decoder); - if (!vldecoder) - return VDP_STATUS_INVALID_HANDLE; - - *profile = PipeToProfile(vldecoder->decoder->profile); - *width = vldecoder->decoder->width; - *height = vldecoder->decoder->height; - - return VDP_STATUS_OK; -} - -static VdpStatus -vlVdpGetReferenceFrame(VdpVideoSurface handle, struct pipe_video_buffer **ref_frame) -{ - vlVdpSurface *surface; - - /* if surfaces equals VDP_STATUS_INVALID_HANDLE, they are not used */ - if (handle == VDP_INVALID_HANDLE) { - *ref_frame = NULL; - return VDP_STATUS_OK; - } - - surface = vlGetDataHTAB(handle); - if (!surface) - return VDP_STATUS_INVALID_HANDLE; - - *ref_frame = surface->video_buffer; - if (!*ref_frame) - return VDP_STATUS_INVALID_HANDLE; - - return VDP_STATUS_OK; -} - -/** - * Decode a mpeg 1/2 video. - */ -static VdpStatus -vlVdpDecoderRenderMpeg12(struct pipe_mpeg12_picture_desc *picture, - VdpPictureInfoMPEG1Or2 *picture_info) -{ - VdpStatus r; - - VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Decoding MPEG12\n"); - - r = vlVdpGetReferenceFrame(picture_info->forward_reference, &picture->ref[0]); - if (r != VDP_STATUS_OK) - return r; - - r = vlVdpGetReferenceFrame(picture_info->backward_reference, &picture->ref[1]); - if (r != VDP_STATUS_OK) - return r; - - picture->picture_coding_type = picture_info->picture_coding_type; - picture->picture_structure = picture_info->picture_structure; - picture->frame_pred_frame_dct = picture_info->frame_pred_frame_dct; - picture->q_scale_type = picture_info->q_scale_type; - picture->alternate_scan = picture_info->alternate_scan; - picture->intra_vlc_format = picture_info->intra_vlc_format; - picture->concealment_motion_vectors = picture_info->concealment_motion_vectors; - picture->intra_dc_precision = picture_info->intra_dc_precision; - picture->f_code[0][0] = picture_info->f_code[0][0] - 1; - picture->f_code[0][1] = picture_info->f_code[0][1] - 1; - picture->f_code[1][0] = picture_info->f_code[1][0] - 1; - picture->f_code[1][1] = picture_info->f_code[1][1] - 1; - picture->num_slices = picture_info->slice_count; - picture->top_field_first = picture_info->top_field_first; - picture->full_pel_forward_vector = picture_info->full_pel_forward_vector; - picture->full_pel_backward_vector = picture_info->full_pel_backward_vector; - picture->intra_matrix = picture_info->intra_quantizer_matrix; - picture->non_intra_matrix = picture_info->non_intra_quantizer_matrix; - - return VDP_STATUS_OK; -} - -/** - * Decode a mpeg 4 video. - */ -static VdpStatus -vlVdpDecoderRenderMpeg4(struct pipe_mpeg4_picture_desc *picture, - VdpPictureInfoMPEG4Part2 *picture_info) -{ - VdpStatus r; - unsigned i; - - VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Decoding MPEG4\n"); - - r = vlVdpGetReferenceFrame(picture_info->forward_reference, &picture->ref[0]); - if (r != VDP_STATUS_OK) - return r; - - r = vlVdpGetReferenceFrame(picture_info->backward_reference, &picture->ref[1]); - if (r != VDP_STATUS_OK) - return r; - - for (i = 0; i < 2; ++i) { - picture->trd[i] = picture_info->trd[i]; - picture->trb[i] = picture_info->trb[i]; - } - picture->vop_time_increment_resolution = picture_info->vop_time_increment_resolution; - picture->vop_coding_type = picture_info->vop_coding_type; - picture->vop_fcode_forward = picture_info->vop_fcode_forward; - picture->vop_fcode_backward = picture_info->vop_fcode_backward; - picture->resync_marker_disable = picture_info->resync_marker_disable; - picture->interlaced = picture_info->interlaced; - picture->quant_type = picture_info->quant_type; - picture->quarter_sample = picture_info->quarter_sample; - picture->short_video_header = picture_info->short_video_header; - picture->rounding_control = picture_info->rounding_control; - picture->alternate_vertical_scan_flag = picture_info->alternate_vertical_scan_flag; - picture->top_field_first = picture_info->top_field_first; - picture->intra_matrix = picture_info->intra_quantizer_matrix; - picture->non_intra_matrix = picture_info->non_intra_quantizer_matrix; - - return VDP_STATUS_OK; -} - -static VdpStatus -vlVdpDecoderRenderVC1(struct pipe_vc1_picture_desc *picture, - VdpPictureInfoVC1 *picture_info) -{ - VdpStatus r; - - VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Decoding VC-1\n"); - - r = vlVdpGetReferenceFrame(picture_info->forward_reference, &picture->ref[0]); - if (r != VDP_STATUS_OK) - return r; - - r = vlVdpGetReferenceFrame(picture_info->backward_reference, &picture->ref[1]); - if (r != VDP_STATUS_OK) - return r; - - picture->slice_count = picture_info->slice_count; - picture->picture_type = picture_info->picture_type; - picture->frame_coding_mode = picture_info->frame_coding_mode; - picture->postprocflag = picture_info->postprocflag; - picture->pulldown = picture_info->pulldown; - picture->interlace = picture_info->interlace; - picture->tfcntrflag = picture_info->tfcntrflag; - picture->finterpflag = picture_info->finterpflag; - picture->psf = picture_info->psf; - picture->dquant = picture_info->dquant; - picture->panscan_flag = picture_info->panscan_flag; - picture->refdist_flag = picture_info->refdist_flag; - picture->quantizer = picture_info->quantizer; - picture->extended_mv = picture_info->extended_mv; - picture->extended_dmv = picture_info->extended_dmv; - picture->overlap = picture_info->overlap; - picture->vstransform = picture_info->vstransform; - picture->loopfilter = picture_info->loopfilter; - picture->fastuvmc = picture_info->fastuvmc; - picture->range_mapy_flag = picture_info->range_mapy_flag; - picture->range_mapy = picture_info->range_mapy; - picture->range_mapuv_flag = picture_info->range_mapuv_flag; - picture->range_mapuv = picture_info->range_mapuv; - picture->multires = picture_info->multires; - picture->syncmarker = picture_info->syncmarker; - picture->rangered = picture_info->rangered; - picture->maxbframes = picture_info->maxbframes; - picture->deblockEnable = picture_info->deblockEnable; - picture->pquant = picture_info->pquant; - - return VDP_STATUS_OK; -} - -static VdpStatus -vlVdpDecoderRenderH264(struct pipe_h264_picture_desc *picture, - VdpPictureInfoH264 *picture_info) -{ - unsigned i; - - VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Decoding H264\n"); - - picture->pps->sps->mb_adaptive_frame_field_flag = picture_info->mb_adaptive_frame_field_flag; - picture->pps->sps->frame_mbs_only_flag = picture_info->frame_mbs_only_flag; - picture->pps->sps->log2_max_frame_num_minus4 = picture_info->log2_max_frame_num_minus4; - picture->pps->sps->pic_order_cnt_type = picture_info->pic_order_cnt_type; - picture->pps->sps->log2_max_pic_order_cnt_lsb_minus4 = picture_info->log2_max_pic_order_cnt_lsb_minus4; - picture->pps->sps->delta_pic_order_always_zero_flag = picture_info->delta_pic_order_always_zero_flag; - picture->pps->sps->direct_8x8_inference_flag = picture_info->direct_8x8_inference_flag; - - picture->pps->transform_8x8_mode_flag = picture_info->transform_8x8_mode_flag; - picture->pps->chroma_qp_index_offset = picture_info->chroma_qp_index_offset; - picture->pps->second_chroma_qp_index_offset = picture_info->second_chroma_qp_index_offset; - picture->pps->pic_init_qp_minus26 = picture_info->pic_init_qp_minus26; - picture->pps->entropy_coding_mode_flag = picture_info->entropy_coding_mode_flag; - picture->pps->deblocking_filter_control_present_flag = picture_info->deblocking_filter_control_present_flag; - picture->pps->redundant_pic_cnt_present_flag = picture_info->redundant_pic_cnt_present_flag; - picture->pps->constrained_intra_pred_flag = picture_info->constrained_intra_pred_flag; - picture->pps->weighted_pred_flag = picture_info->weighted_pred_flag; - picture->pps->weighted_bipred_idc = picture_info->weighted_bipred_idc; - picture->pps->bottom_field_pic_order_in_frame_present_flag = picture_info->pic_order_present_flag; - memcpy(picture->pps->ScalingList4x4, picture_info->scaling_lists_4x4, 6*16); - memcpy(picture->pps->ScalingList8x8, picture_info->scaling_lists_8x8, 2*64); - - picture->slice_count = picture_info->slice_count; - picture->field_order_cnt[0] = picture_info->field_order_cnt[0]; - picture->field_order_cnt[1] = picture_info->field_order_cnt[1]; - picture->is_reference = picture_info->is_reference; - picture->frame_num = picture_info->frame_num; - picture->field_pic_flag = picture_info->field_pic_flag; - picture->bottom_field_flag = picture_info->bottom_field_flag; - picture->num_ref_frames = picture_info->num_ref_frames; - - picture->num_ref_idx_l0_active_minus1 = picture_info->num_ref_idx_l0_active_minus1; - picture->num_ref_idx_l1_active_minus1 = picture_info->num_ref_idx_l1_active_minus1; - - for (i = 0; i < 16; ++i) { - VdpStatus ret = vlVdpGetReferenceFrame - ( - picture_info->referenceFrames[i].surface, - &picture->ref[i] - ); - if (ret != VDP_STATUS_OK) - return ret; - - picture->is_long_term[i] = picture_info->referenceFrames[i].is_long_term; - picture->top_is_reference[i] = picture_info->referenceFrames[i].top_is_reference; - picture->bottom_is_reference[i] = picture_info->referenceFrames[i].bottom_is_reference; - picture->field_order_cnt_list[i][0] = picture_info->referenceFrames[i].field_order_cnt[0]; - picture->field_order_cnt_list[i][1] = picture_info->referenceFrames[i].field_order_cnt[1]; - picture->frame_num_list[i] = picture_info->referenceFrames[i].frame_idx; - } - - return VDP_STATUS_OK; -} - -static VdpStatus -vlVdpDecoderRenderH265(struct pipe_h265_picture_desc *picture, - VdpPictureInfoHEVC *picture_info) -{ - unsigned i; - - picture->pps->sps->chroma_format_idc = picture_info->chroma_format_idc; - picture->pps->sps->separate_colour_plane_flag = picture_info->separate_colour_plane_flag; - picture->pps->sps->pic_width_in_luma_samples = picture_info->pic_width_in_luma_samples; - picture->pps->sps->pic_height_in_luma_samples = picture_info->pic_height_in_luma_samples; - picture->pps->sps->bit_depth_luma_minus8 = picture_info->bit_depth_luma_minus8; - picture->pps->sps->bit_depth_chroma_minus8 = picture_info->bit_depth_chroma_minus8; - picture->pps->sps->log2_max_pic_order_cnt_lsb_minus4 = picture_info->log2_max_pic_order_cnt_lsb_minus4; - picture->pps->sps->sps_max_dec_pic_buffering_minus1 = picture_info->sps_max_dec_pic_buffering_minus1; - picture->pps->sps->log2_min_luma_coding_block_size_minus3 = picture_info->log2_min_luma_coding_block_size_minus3; - picture->pps->sps->log2_diff_max_min_luma_coding_block_size = picture_info->log2_diff_max_min_luma_coding_block_size; - picture->pps->sps->log2_min_transform_block_size_minus2 = picture_info->log2_min_transform_block_size_minus2; - picture->pps->sps->log2_diff_max_min_transform_block_size = picture_info->log2_diff_max_min_transform_block_size; - picture->pps->sps->max_transform_hierarchy_depth_inter = picture_info->max_transform_hierarchy_depth_inter; - picture->pps->sps->max_transform_hierarchy_depth_intra = picture_info->max_transform_hierarchy_depth_intra; - picture->pps->sps->scaling_list_enabled_flag = picture_info->scaling_list_enabled_flag; - memcpy(picture->pps->sps->ScalingList4x4, picture_info->ScalingList4x4, 6*16); - memcpy(picture->pps->sps->ScalingList8x8, picture_info->ScalingList8x8, 6*64); - memcpy(picture->pps->sps->ScalingList16x16, picture_info->ScalingList16x16, 6*64); - memcpy(picture->pps->sps->ScalingList32x32, picture_info->ScalingList32x32, 2*64); - memcpy(picture->pps->sps->ScalingListDCCoeff16x16, picture_info->ScalingListDCCoeff16x16, 6); - memcpy(picture->pps->sps->ScalingListDCCoeff32x32, picture_info->ScalingListDCCoeff32x32, 2); - picture->pps->sps->amp_enabled_flag = picture_info->amp_enabled_flag; - picture->pps->sps->sample_adaptive_offset_enabled_flag = picture_info->sample_adaptive_offset_enabled_flag; - picture->pps->sps->pcm_enabled_flag = picture_info->pcm_enabled_flag; - picture->pps->sps->pcm_sample_bit_depth_luma_minus1 = picture_info->pcm_sample_bit_depth_luma_minus1; - picture->pps->sps->pcm_sample_bit_depth_chroma_minus1 = picture_info->pcm_sample_bit_depth_chroma_minus1; - picture->pps->sps->log2_min_pcm_luma_coding_block_size_minus3 = picture_info->log2_min_pcm_luma_coding_block_size_minus3; - picture->pps->sps->log2_diff_max_min_pcm_luma_coding_block_size = picture_info->log2_diff_max_min_pcm_luma_coding_block_size; - picture->pps->sps->pcm_loop_filter_disabled_flag = picture_info->pcm_loop_filter_disabled_flag; - picture->pps->sps->num_short_term_ref_pic_sets = picture_info->num_short_term_ref_pic_sets; - picture->pps->sps->long_term_ref_pics_present_flag = picture_info->long_term_ref_pics_present_flag; - picture->pps->sps->num_long_term_ref_pics_sps = picture_info->num_long_term_ref_pics_sps; - picture->pps->sps->sps_temporal_mvp_enabled_flag = picture_info->sps_temporal_mvp_enabled_flag; - picture->pps->sps->strong_intra_smoothing_enabled_flag = picture_info->strong_intra_smoothing_enabled_flag; - - picture->pps->dependent_slice_segments_enabled_flag = picture_info->dependent_slice_segments_enabled_flag; - picture->pps->output_flag_present_flag = picture_info->output_flag_present_flag; - picture->pps->num_extra_slice_header_bits = picture_info->num_extra_slice_header_bits; - picture->pps->sign_data_hiding_enabled_flag = picture_info->sign_data_hiding_enabled_flag; - picture->pps->cabac_init_present_flag = picture_info->cabac_init_present_flag; - picture->pps->num_ref_idx_l0_default_active_minus1 = picture_info->num_ref_idx_l0_default_active_minus1; - picture->pps->num_ref_idx_l1_default_active_minus1 = picture_info->num_ref_idx_l1_default_active_minus1; - picture->pps->init_qp_minus26 = picture_info->init_qp_minus26; - picture->pps->constrained_intra_pred_flag = picture_info->constrained_intra_pred_flag; - picture->pps->transform_skip_enabled_flag = picture_info->transform_skip_enabled_flag; - picture->pps->cu_qp_delta_enabled_flag = picture_info->cu_qp_delta_enabled_flag; - picture->pps->diff_cu_qp_delta_depth = picture_info->diff_cu_qp_delta_depth; - picture->pps->pps_cb_qp_offset = picture_info->pps_cb_qp_offset; - picture->pps->pps_cr_qp_offset = picture_info->pps_cr_qp_offset; - picture->pps->pps_slice_chroma_qp_offsets_present_flag = picture_info->pps_slice_chroma_qp_offsets_present_flag; - picture->pps->weighted_pred_flag = picture_info->weighted_pred_flag; - picture->pps->weighted_bipred_flag = picture_info->weighted_bipred_flag; - picture->pps->transquant_bypass_enabled_flag = picture_info->transquant_bypass_enabled_flag; - picture->pps->tiles_enabled_flag = picture_info->tiles_enabled_flag; - picture->pps->entropy_coding_sync_enabled_flag = picture_info->entropy_coding_sync_enabled_flag; - picture->pps->num_tile_columns_minus1 = picture_info->num_tile_columns_minus1; - picture->pps->num_tile_rows_minus1 = picture_info->num_tile_rows_minus1; - picture->pps->uniform_spacing_flag = picture_info->uniform_spacing_flag; - memcpy(picture->pps->column_width_minus1, picture_info->column_width_minus1, 20 * 2); - memcpy(picture->pps->row_height_minus1, picture_info->row_height_minus1, 22 * 2); - picture->pps->loop_filter_across_tiles_enabled_flag = picture_info->loop_filter_across_tiles_enabled_flag; - picture->pps->pps_loop_filter_across_slices_enabled_flag = picture_info->pps_loop_filter_across_slices_enabled_flag; - picture->pps->deblocking_filter_control_present_flag = picture_info->deblocking_filter_control_present_flag; - picture->pps->deblocking_filter_override_enabled_flag = picture_info->deblocking_filter_override_enabled_flag; - picture->pps->pps_deblocking_filter_disabled_flag = picture_info->pps_deblocking_filter_disabled_flag; - picture->pps->pps_beta_offset_div2 = picture_info->pps_beta_offset_div2; - picture->pps->pps_tc_offset_div2 = picture_info->pps_tc_offset_div2; - picture->pps->lists_modification_present_flag = picture_info->lists_modification_present_flag; - picture->pps->log2_parallel_merge_level_minus2 = picture_info->log2_parallel_merge_level_minus2; - picture->pps->slice_segment_header_extension_present_flag = picture_info->slice_segment_header_extension_present_flag; - - picture->IDRPicFlag = picture_info->IDRPicFlag; - picture->RAPPicFlag = picture_info->RAPPicFlag; - picture->CurrRpsIdx = picture_info->CurrRpsIdx; - picture->NumPocTotalCurr = picture_info->NumPocTotalCurr; - picture->NumDeltaPocsOfRefRpsIdx = picture_info->NumDeltaPocsOfRefRpsIdx; - picture->NumShortTermPictureSliceHeaderBits = picture_info->NumShortTermPictureSliceHeaderBits; - picture->NumLongTermPictureSliceHeaderBits = picture_info->NumLongTermPictureSliceHeaderBits; - picture->CurrPicOrderCntVal = picture_info->CurrPicOrderCntVal; - - for (i = 0; i < 16; ++i) { - VdpStatus ret = vlVdpGetReferenceFrame - ( - picture_info->RefPics[i], - &picture->ref[i] - ); - if (ret != VDP_STATUS_OK) - return ret; - - picture->PicOrderCntVal[i] = picture_info->PicOrderCntVal[i]; - picture->IsLongTerm[i] = picture_info->IsLongTerm[i]; - } - - picture->NumPocStCurrBefore = picture_info->NumPocStCurrBefore; - picture->NumPocStCurrAfter = picture_info->NumPocStCurrAfter; - picture->NumPocLtCurr = picture_info->NumPocLtCurr; - memcpy(picture->RefPicSetStCurrBefore, picture_info->RefPicSetStCurrBefore, 8); - memcpy(picture->RefPicSetStCurrAfter, picture_info->RefPicSetStCurrAfter, 8); - memcpy(picture->RefPicSetLtCurr, picture_info->RefPicSetLtCurr, 8); - picture->UseRefPicList = false; - - return VDP_STATUS_OK; -} - -static void -vlVdpDecoderFixVC1Startcode(uint32_t *num_buffers, const void *buffers[], unsigned sizes[]) -{ - static const uint8_t vc1_startcode[] = { 0x00, 0x00, 0x01, 0x0D }; - struct vl_vlc vlc = {}; - unsigned i; - - /* search the first 64 bytes for a startcode */ - vl_vlc_init(&vlc, *num_buffers, buffers, sizes); - while (vl_vlc_search_byte(&vlc, 64*8, 0x00) && vl_vlc_bits_left(&vlc) >= 32) { - uint32_t value = vl_vlc_peekbits(&vlc, 32); - if (value == 0x0000010D || - value == 0x0000010C || - value == 0x0000010B) - return; - vl_vlc_eatbits(&vlc, 8); - } - - /* none found, ok add one manually */ - VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Manually adding VC-1 startcode\n"); - for (i = *num_buffers; i > 0; --i) { - buffers[i] = buffers[i - 1]; - sizes[i] = sizes[i - 1]; - } - ++(*num_buffers); - buffers[0] = vc1_startcode; - sizes[0] = 4; -} - -/** - * Decode a compressed field/frame and render the result into a VdpVideoSurface. - */ -VdpStatus -vlVdpDecoderRender(VdpDecoder decoder, - VdpVideoSurface target, - VdpPictureInfo const *picture_info, - uint32_t bitstream_buffer_count, - VdpBitstreamBuffer const *bitstream_buffers) -{ - const void * buffers[bitstream_buffer_count + 1]; - unsigned sizes[bitstream_buffer_count + 1]; - vlVdpDecoder *vldecoder; - vlVdpSurface *vlsurf; - VdpStatus ret; - struct pipe_screen *screen; - struct pipe_video_codec *dec; - bool buffer_support[2]; - unsigned i; - struct pipe_h264_sps sps_h264 = {}; - struct pipe_h264_pps pps_h264 = { &sps_h264 }; - struct pipe_h265_sps sps_h265 = {}; - struct pipe_h265_pps pps_h265 = { &sps_h265 }; - union { - struct pipe_picture_desc base; - struct pipe_mpeg12_picture_desc mpeg12; - struct pipe_mpeg4_picture_desc mpeg4; - struct pipe_vc1_picture_desc vc1; - struct pipe_h264_picture_desc h264; - struct pipe_h265_picture_desc h265; - } desc; - - if (!(picture_info && bitstream_buffers)) - return VDP_STATUS_INVALID_POINTER; - - vldecoder = (vlVdpDecoder *)vlGetDataHTAB(decoder); - if (!vldecoder) - return VDP_STATUS_INVALID_HANDLE; - dec = vldecoder->decoder; - screen = dec->context->screen; - - vlsurf = (vlVdpSurface *)vlGetDataHTAB(target); - if (!vlsurf) - return VDP_STATUS_INVALID_HANDLE; - - if (vlsurf->device != vldecoder->device) - return VDP_STATUS_HANDLE_DEVICE_MISMATCH; - - if (vlsurf->video_buffer != NULL && - pipe_format_to_chroma_format(vlsurf->video_buffer->buffer_format) != dec->chroma_format) - // TODO: Recreate decoder with correct chroma - return VDP_STATUS_INVALID_CHROMA_TYPE; - - buffer_support[0] = screen->get_video_param(screen, dec->profile, PIPE_VIDEO_ENTRYPOINT_BITSTREAM, - PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE); - buffer_support[1] = screen->get_video_param(screen, dec->profile, PIPE_VIDEO_ENTRYPOINT_BITSTREAM, - PIPE_VIDEO_CAP_SUPPORTS_INTERLACED); - - if (vlsurf->video_buffer == NULL || - !screen->is_video_format_supported(screen, vlsurf->video_buffer->buffer_format, - dec->profile, PIPE_VIDEO_ENTRYPOINT_BITSTREAM) || - !buffer_support[vlsurf->video_buffer->interlaced]) { - - mtx_lock(&vlsurf->device->mutex); - - /* destroy the old one */ - if (vlsurf->video_buffer) - vlsurf->video_buffer->destroy(vlsurf->video_buffer); - - /* set the buffer format to the prefered one */ - vlsurf->templat.buffer_format = screen->get_video_param(screen, dec->profile, PIPE_VIDEO_ENTRYPOINT_BITSTREAM, - PIPE_VIDEO_CAP_PREFERED_FORMAT); - - /* also set interlacing to decoders preferences */ - vlsurf->templat.interlaced = screen->get_video_param(screen, dec->profile, PIPE_VIDEO_ENTRYPOINT_BITSTREAM, - PIPE_VIDEO_CAP_PREFERS_INTERLACED); - - /* and recreate the video buffer */ - vlsurf->video_buffer = dec->context->create_video_buffer(dec->context, &vlsurf->templat); - - /* still no luck? get me out of here... */ - if (!vlsurf->video_buffer) { - mtx_unlock(&vlsurf->device->mutex); - return VDP_STATUS_NO_IMPLEMENTATION; - } - vlVdpVideoSurfaceClear(vlsurf); - mtx_unlock(&vlsurf->device->mutex); - } - - for (i = 0; i < bitstream_buffer_count; ++i) { - buffers[i] = bitstream_buffers[i].bitstream; - sizes[i] = bitstream_buffers[i].bitstream_bytes; - } - - memset(&desc, 0, sizeof(desc)); - desc.base.profile = dec->profile; - switch (u_reduce_video_profile(dec->profile)) { - case PIPE_VIDEO_FORMAT_MPEG12: - ret = vlVdpDecoderRenderMpeg12(&desc.mpeg12, (VdpPictureInfoMPEG1Or2 *)picture_info); - break; - case PIPE_VIDEO_FORMAT_MPEG4: - ret = vlVdpDecoderRenderMpeg4(&desc.mpeg4, (VdpPictureInfoMPEG4Part2 *)picture_info); - break; - case PIPE_VIDEO_FORMAT_VC1: - if (dec->profile == PIPE_VIDEO_PROFILE_VC1_ADVANCED) - vlVdpDecoderFixVC1Startcode(&bitstream_buffer_count, buffers, sizes); - ret = vlVdpDecoderRenderVC1(&desc.vc1, (VdpPictureInfoVC1 *)picture_info); - break; - case PIPE_VIDEO_FORMAT_MPEG4_AVC: - desc.h264.pps = &pps_h264; - ret = vlVdpDecoderRenderH264(&desc.h264, (VdpPictureInfoH264 *)picture_info); - break; - case PIPE_VIDEO_FORMAT_HEVC: - desc.h265.pps = &pps_h265; - ret = vlVdpDecoderRenderH265(&desc.h265, (VdpPictureInfoHEVC *)picture_info); - break; - default: - return VDP_STATUS_INVALID_DECODER_PROFILE; - } - - if (ret != VDP_STATUS_OK) - return ret; - - mtx_lock(&vldecoder->mutex); - dec->begin_frame(dec, vlsurf->video_buffer, &desc.base); - dec->decode_bitstream(dec, vlsurf->video_buffer, &desc.base, bitstream_buffer_count, buffers, sizes); - dec->end_frame(dec, vlsurf->video_buffer, &desc.base); - mtx_unlock(&vldecoder->mutex); - return ret; -} diff --git a/src/gallium/state_trackers/vdpau/device.c b/src/gallium/state_trackers/vdpau/device.c deleted file mode 100644 index 5df30ea3c08..00000000000 --- a/src/gallium/state_trackers/vdpau/device.c +++ /dev/null @@ -1,327 +0,0 @@ -/************************************************************************** - * - * Copyright 2010 Younes Manton og Thomas Balling Sørensen. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include "pipe/p_compiler.h" - -#include "util/u_memory.h" -#include "util/u_debug.h" -#include "util/format/u_format.h" -#include "util/u_sampler.h" - -#include "vdpau_private.h" - -/** - * Create a VdpDevice object for use with X11. - */ -PUBLIC VdpStatus -vdp_imp_device_create_x11(Display *display, int screen, VdpDevice *device, - VdpGetProcAddress **get_proc_address) -{ - struct pipe_screen *pscreen; - struct pipe_resource *res, res_tmpl; - struct pipe_sampler_view sv_tmpl; - vlVdpDevice *dev = NULL; - VdpStatus ret; - - if (!(display && device && get_proc_address)) - return VDP_STATUS_INVALID_POINTER; - - if (!vlCreateHTAB()) { - ret = VDP_STATUS_RESOURCES; - goto no_htab; - } - - dev = CALLOC(1, sizeof(vlVdpDevice)); - if (!dev) { - ret = VDP_STATUS_RESOURCES; - goto no_dev; - } - - pipe_reference_init(&dev->reference, 1); - - dev->vscreen = vl_dri3_screen_create(display, screen); - if (!dev->vscreen) - dev->vscreen = vl_dri2_screen_create(display, screen); - if (!dev->vscreen) { - ret = VDP_STATUS_RESOURCES; - goto no_vscreen; - } - - pscreen = dev->vscreen->pscreen; - dev->context = pipe_create_multimedia_context(pscreen); - if (!dev->context) { - ret = VDP_STATUS_RESOURCES; - goto no_context; - } - - if (!pscreen->get_param(pscreen, PIPE_CAP_NPOT_TEXTURES)) { - ret = VDP_STATUS_NO_IMPLEMENTATION; - goto no_context; - } - - memset(&res_tmpl, 0, sizeof(res_tmpl)); - - res_tmpl.target = PIPE_TEXTURE_2D; - res_tmpl.format = PIPE_FORMAT_R8G8B8A8_UNORM; - res_tmpl.width0 = 1; - res_tmpl.height0 = 1; - res_tmpl.depth0 = 1; - res_tmpl.array_size = 1; - res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW; - res_tmpl.usage = PIPE_USAGE_DEFAULT; - - if (!CheckSurfaceParams(pscreen, &res_tmpl)) { - ret = VDP_STATUS_NO_IMPLEMENTATION; - goto no_resource; - } - - res = pscreen->resource_create(pscreen, &res_tmpl); - if (!res) { - ret = VDP_STATUS_RESOURCES; - goto no_resource; - } - - memset(&sv_tmpl, 0, sizeof(sv_tmpl)); - u_sampler_view_default_template(&sv_tmpl, res, res->format); - - sv_tmpl.swizzle_r = PIPE_SWIZZLE_1; - sv_tmpl.swizzle_g = PIPE_SWIZZLE_1; - sv_tmpl.swizzle_b = PIPE_SWIZZLE_1; - sv_tmpl.swizzle_a = PIPE_SWIZZLE_1; - - dev->dummy_sv = dev->context->create_sampler_view(dev->context, res, &sv_tmpl); - pipe_resource_reference(&res, NULL); - if (!dev->dummy_sv) { - ret = VDP_STATUS_RESOURCES; - goto no_resource; - } - - *device = vlAddDataHTAB(dev); - if (*device == 0) { - ret = VDP_STATUS_ERROR; - goto no_handle; - } - - if (!vl_compositor_init(&dev->compositor, dev->context)) { - ret = VDP_STATUS_ERROR; - goto no_compositor; - } - - (void) mtx_init(&dev->mutex, mtx_plain); - - *get_proc_address = &vlVdpGetProcAddress; - - return VDP_STATUS_OK; - -no_compositor: - vlRemoveDataHTAB(*device); -no_handle: - pipe_sampler_view_reference(&dev->dummy_sv, NULL); -no_resource: - dev->context->destroy(dev->context); -no_context: - dev->vscreen->destroy(dev->vscreen); -no_vscreen: - FREE(dev); -no_dev: - vlDestroyHTAB(); -no_htab: - return ret; -} - -/** - * Create a VdpPresentationQueueTarget for use with X11. - */ -VdpStatus -vlVdpPresentationQueueTargetCreateX11(VdpDevice device, Drawable drawable, - VdpPresentationQueueTarget *target) -{ - vlVdpPresentationQueueTarget *pqt; - VdpStatus ret; - - if (!drawable) - return VDP_STATUS_INVALID_HANDLE; - - vlVdpDevice *dev = vlGetDataHTAB(device); - if (!dev) - return VDP_STATUS_INVALID_HANDLE; - - pqt = CALLOC(1, sizeof(vlVdpPresentationQueue)); - if (!pqt) - return VDP_STATUS_RESOURCES; - - DeviceReference(&pqt->device, dev); - pqt->drawable = drawable; - - *target = vlAddDataHTAB(pqt); - if (*target == 0) { - ret = VDP_STATUS_ERROR; - goto no_handle; - } - - return VDP_STATUS_OK; - -no_handle: - FREE(pqt); - return ret; -} - -/** - * Destroy a VdpPresentationQueueTarget. - */ -VdpStatus -vlVdpPresentationQueueTargetDestroy(VdpPresentationQueueTarget presentation_queue_target) -{ - vlVdpPresentationQueueTarget *pqt; - - pqt = vlGetDataHTAB(presentation_queue_target); - if (!pqt) - return VDP_STATUS_INVALID_HANDLE; - - vlRemoveDataHTAB(presentation_queue_target); - DeviceReference(&pqt->device, NULL); - FREE(pqt); - - return VDP_STATUS_OK; -} - -/** - * Destroy a VdpDevice. - */ -VdpStatus -vlVdpDeviceDestroy(VdpDevice device) -{ - vlVdpDevice *dev = vlGetDataHTAB(device); - if (!dev) - return VDP_STATUS_INVALID_HANDLE; - - vlRemoveDataHTAB(device); - DeviceReference(&dev, NULL); - - return VDP_STATUS_OK; -} - -/** - * Free a VdpDevice. - */ -void -vlVdpDeviceFree(vlVdpDevice *dev) -{ - mtx_destroy(&dev->mutex); - vl_compositor_cleanup(&dev->compositor); - pipe_sampler_view_reference(&dev->dummy_sv, NULL); - dev->context->destroy(dev->context); - dev->vscreen->destroy(dev->vscreen); - FREE(dev); - vlDestroyHTAB(); -} - -/** - * Retrieve a VDPAU function pointer. - */ -VdpStatus -vlVdpGetProcAddress(VdpDevice device, VdpFuncId function_id, void **function_pointer) -{ - vlVdpDevice *dev = vlGetDataHTAB(device); - if (!dev) - return VDP_STATUS_INVALID_HANDLE; - - if (!function_pointer) - return VDP_STATUS_INVALID_POINTER; - - if (!vlGetFuncFTAB(function_id, function_pointer)) - return VDP_STATUS_INVALID_FUNC_ID; - - VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Got proc address %p for id %d\n", *function_pointer, function_id); - - return VDP_STATUS_OK; -} - -#define _ERROR_TYPE(TYPE,STRING) case TYPE: return STRING; - -/** - * Retrieve a string describing an error code. - */ -char const * -vlVdpGetErrorString (VdpStatus status) -{ - switch (status) { - _ERROR_TYPE(VDP_STATUS_OK,"The operation completed successfully; no error."); - _ERROR_TYPE(VDP_STATUS_NO_IMPLEMENTATION,"No backend implementation could be loaded."); - _ERROR_TYPE(VDP_STATUS_DISPLAY_PREEMPTED,"The display was preempted, or a fatal error occurred. The application must re-initialize VDPAU."); - _ERROR_TYPE(VDP_STATUS_INVALID_HANDLE,"An invalid handle value was provided. Either the handle does not exist at all, or refers to an object of an incorrect type."); - _ERROR_TYPE(VDP_STATUS_INVALID_POINTER,"An invalid pointer was provided. Typically, this means that a NULL pointer was provided for an 'output' parameter."); - _ERROR_TYPE(VDP_STATUS_INVALID_CHROMA_TYPE,"An invalid/unsupported VdpChromaType value was supplied."); - _ERROR_TYPE(VDP_STATUS_INVALID_Y_CB_CR_FORMAT,"An invalid/unsupported VdpYCbCrFormat value was supplied."); - _ERROR_TYPE(VDP_STATUS_INVALID_RGBA_FORMAT,"An invalid/unsupported VdpRGBAFormat value was supplied."); - _ERROR_TYPE(VDP_STATUS_INVALID_INDEXED_FORMAT,"An invalid/unsupported VdpIndexedFormat value was supplied."); - _ERROR_TYPE(VDP_STATUS_INVALID_COLOR_STANDARD,"An invalid/unsupported VdpColorStandard value was supplied."); - _ERROR_TYPE(VDP_STATUS_INVALID_COLOR_TABLE_FORMAT,"An invalid/unsupported VdpColorTableFormat value was supplied."); - _ERROR_TYPE(VDP_STATUS_INVALID_BLEND_FACTOR,"An invalid/unsupported VdpOutputSurfaceRenderBlendFactor value was supplied."); - _ERROR_TYPE(VDP_STATUS_INVALID_BLEND_EQUATION,"An invalid/unsupported VdpOutputSurfaceRenderBlendEquation value was supplied."); - _ERROR_TYPE(VDP_STATUS_INVALID_FLAG,"An invalid/unsupported flag value/combination was supplied."); - _ERROR_TYPE(VDP_STATUS_INVALID_DECODER_PROFILE,"An invalid/unsupported VdpDecoderProfile value was supplied."); - _ERROR_TYPE(VDP_STATUS_INVALID_VIDEO_MIXER_FEATURE,"An invalid/unsupported VdpVideoMixerFeature value was supplied."); - _ERROR_TYPE(VDP_STATUS_INVALID_VIDEO_MIXER_PARAMETER,"An invalid/unsupported VdpVideoMixerParameter value was supplied."); - _ERROR_TYPE(VDP_STATUS_INVALID_VIDEO_MIXER_ATTRIBUTE,"An invalid/unsupported VdpVideoMixerAttribute value was supplied."); - _ERROR_TYPE(VDP_STATUS_INVALID_VIDEO_MIXER_PICTURE_STRUCTURE,"An invalid/unsupported VdpVideoMixerPictureStructure value was supplied."); - _ERROR_TYPE(VDP_STATUS_INVALID_FUNC_ID,"An invalid/unsupported VdpFuncId value was supplied."); - _ERROR_TYPE(VDP_STATUS_INVALID_SIZE,"The size of a supplied object does not match the object it is being used with.\ - For example, a VdpVideoMixer is configured to process VdpVideoSurface objects of a specific size.\ - If presented with a VdpVideoSurface of a different size, this error will be raised."); - _ERROR_TYPE(VDP_STATUS_INVALID_VALUE,"An invalid/unsupported value was supplied.\ - This is a catch-all error code for values of type other than those with a specific error code."); - _ERROR_TYPE(VDP_STATUS_INVALID_STRUCT_VERSION,"An invalid/unsupported structure version was specified in a versioned structure. \ - This implies that the implementation is older than the header file the application was built against."); - _ERROR_TYPE(VDP_STATUS_RESOURCES,"The system does not have enough resources to complete the requested operation at this time."); - _ERROR_TYPE(VDP_STATUS_HANDLE_DEVICE_MISMATCH,"The set of handles supplied are not all related to the same VdpDevice.When performing operations \ - that operate on multiple surfaces, such as VdpOutputSurfaceRenderOutputSurface or VdpVideoMixerRender, \ - all supplied surfaces must have been created within the context of the same VdpDevice object. \ - This error is raised if they were not."); - _ERROR_TYPE(VDP_STATUS_ERROR,"A catch-all error, used when no other error code applies."); - default: return "Unknown Error"; - } -} - -void -vlVdpDefaultSamplerViewTemplate(struct pipe_sampler_view *templ, struct pipe_resource *res) -{ - const struct util_format_description *desc; - - memset(templ, 0, sizeof(*templ)); - u_sampler_view_default_template(templ, res, res->format); - - desc = util_format_description(res->format); - if (desc->swizzle[0] == PIPE_SWIZZLE_0) - templ->swizzle_r = PIPE_SWIZZLE_1; - if (desc->swizzle[1] == PIPE_SWIZZLE_0) - templ->swizzle_g = PIPE_SWIZZLE_1; - if (desc->swizzle[2] == PIPE_SWIZZLE_0) - templ->swizzle_b = PIPE_SWIZZLE_1; - if (desc->swizzle[3] == PIPE_SWIZZLE_0) - templ->swizzle_a = PIPE_SWIZZLE_1; -} diff --git a/src/gallium/state_trackers/vdpau/ftab.c b/src/gallium/state_trackers/vdpau/ftab.c deleted file mode 100644 index 31786229bc5..00000000000 --- a/src/gallium/state_trackers/vdpau/ftab.c +++ /dev/null @@ -1,139 +0,0 @@ -/************************************************************************** - * - * Copyright 2010 Younes Manton & Thomas Balling Sørensen. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include - -#include "util/u_memory.h" - -#include "vdpau_private.h" - -static void* ftab[67] = -{ - &vlVdpGetErrorString, /* VDP_FUNC_ID_GET_ERROR_STRING */ - &vlVdpGetProcAddress, /* VDP_FUNC_ID_GET_PROC_ADDRESS */ - &vlVdpGetApiVersion, /* VDP_FUNC_ID_GET_API_VERSION */ - NULL, /* DUMMY */ - &vlVdpGetInformationString, /* VDP_FUNC_ID_GET_INFORMATION_STRING */ - &vlVdpDeviceDestroy, /* VDP_FUNC_ID_DEVICE_DESTROY */ - &vlVdpGenerateCSCMatrix, /* VDP_FUNC_ID_GENERATE_CSC_MATRIX */ - &vlVdpVideoSurfaceQueryCapabilities, /* VDP_FUNC_ID_VIDEO_SURFACE_QUERY_CAPABILITIES */ - &vlVdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities, /* VDP_FUNC_ID_VIDEO_SURFACE_QUERY_GET_PUT_BITS_Y_CB_CR_CAPABILITIES */ - &vlVdpVideoSurfaceCreate, /* VDP_FUNC_ID_VIDEO_SURFACE_CREATE */ - &vlVdpVideoSurfaceDestroy, /* VDP_FUNC_ID_VIDEO_SURFACE_DESTROY */ - &vlVdpVideoSurfaceGetParameters, /* VDP_FUNC_ID_VIDEO_SURFACE_GET_PARAMETERS */ - &vlVdpVideoSurfaceGetBitsYCbCr, /* VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR */ - &vlVdpVideoSurfacePutBitsYCbCr, /* VDP_FUNC_ID_VIDEO_SURFACE_PUT_BITS_Y_CB_CR */ - &vlVdpOutputSurfaceQueryCapabilities, /* VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_CAPABILITIES */ - &vlVdpOutputSurfaceQueryGetPutBitsNativeCapabilities, /* VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_GET_PUT_BITS_NATIVE_CAPABILITIES */ - &vlVdpOutputSurfaceQueryPutBitsIndexedCapabilities, /* VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_PUT_BITS_INDEXED_CAPABILITIES */ - &vlVdpOutputSurfaceQueryPutBitsYCbCrCapabilities, /* VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_PUT_BITS_Y_CB_CR_CAPABILITIES */ - &vlVdpOutputSurfaceCreate, /* VDP_FUNC_ID_OUTPUT_SURFACE_CREATE */ - &vlVdpOutputSurfaceDestroy, /* VDP_FUNC_ID_OUTPUT_SURFACE_DESTROY */ - &vlVdpOutputSurfaceGetParameters, /* VDP_FUNC_ID_OUTPUT_SURFACE_GET_PARAMETERS */ - &vlVdpOutputSurfaceGetBitsNative, /* VDP_FUNC_ID_OUTPUT_SURFACE_GET_BITS_NATIVE */ - &vlVdpOutputSurfacePutBitsNative, /* VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_NATIVE */ - &vlVdpOutputSurfacePutBitsIndexed, /* VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_INDEXED */ - &vlVdpOutputSurfacePutBitsYCbCr, /* VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_Y_CB_CR */ - &vlVdpBitmapSurfaceQueryCapabilities, /* VDP_FUNC_ID_BITMAP_SURFACE_QUERY_CAPABILITIES */ - &vlVdpBitmapSurfaceCreate, /* VDP_FUNC_ID_BITMAP_SURFACE_CREATE */ - &vlVdpBitmapSurfaceDestroy, /* VDP_FUNC_ID_BITMAP_SURFACE_DESTROY */ - &vlVdpBitmapSurfaceGetParameters, /* VDP_FUNC_ID_BITMAP_SURFACE_GET_PARAMETERS */ - &vlVdpBitmapSurfacePutBitsNative, /* VDP_FUNC_ID_BITMAP_SURFACE_PUT_BITS_NATIVE */ - NULL, /* DUMMY */ - NULL, /* DUMMY */ - NULL, /* DUMMY */ - &vlVdpOutputSurfaceRenderOutputSurface, /* VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_OUTPUT_SURFACE */ - &vlVdpOutputSurfaceRenderBitmapSurface, /* VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_BITMAP_SURFACE */ - NULL, /* VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_VIDEO_SURFACE_LUMA */ - &vlVdpDecoderQueryCapabilities, /* VDP_FUNC_ID_DECODER_QUERY_CAPABILITIES */ - &vlVdpDecoderCreate, /* VDP_FUNC_ID_DECODER_CREATE */ - &vlVdpDecoderDestroy, /* VDP_FUNC_ID_DECODER_DESTROY */ - &vlVdpDecoderGetParameters, /* VDP_FUNC_ID_DECODER_GET_PARAMETERS */ - &vlVdpDecoderRender, /* VDP_FUNC_ID_DECODER_RENDER */ - &vlVdpVideoMixerQueryFeatureSupport, /* VDP_FUNC_ID_VIDEO_MIXER_QUERY_FEATURE_SUPPORT */ - &vlVdpVideoMixerQueryParameterSupport, /* VDP_FUNC_ID_VIDEO_MIXER_QUERY_PARAMETER_SUPPORT */ - &vlVdpVideoMixerQueryAttributeSupport, /* VDP_FUNC_ID_VIDEO_MIXER_QUERY_ATTRIBUTE_SUPPORT */ - &vlVdpVideoMixerQueryParameterValueRange, /* VDP_FUNC_ID_VIDEO_MIXER_QUERY_PARAMETER_VALUE_RANGE */ - &vlVdpVideoMixerQueryAttributeValueRange, /* VDP_FUNC_ID_VIDEO_MIXER_QUERY_ATTRIBUTE_VALUE_RANGE */ - &vlVdpVideoMixerCreate, /* VDP_FUNC_ID_VIDEO_MIXER_CREATE */ - &vlVdpVideoMixerSetFeatureEnables, /* VDP_FUNC_ID_VIDEO_MIXER_SET_FEATURE_ENABLES */ - &vlVdpVideoMixerSetAttributeValues, /* VDP_FUNC_ID_VIDEO_MIXER_SET_ATTRIBUTE_VALUES */ - &vlVdpVideoMixerGetFeatureSupport, /* VDP_FUNC_ID_VIDEO_MIXER_GET_FEATURE_SUPPORT */ - &vlVdpVideoMixerGetFeatureEnables, /* VDP_FUNC_ID_VIDEO_MIXER_GET_FEATURE_ENABLES */ - &vlVdpVideoMixerGetParameterValues, /* VDP_FUNC_ID_VIDEO_MIXER_GET_PARAMETER_VALUES */ - &vlVdpVideoMixerGetAttributeValues, /* VDP_FUNC_ID_VIDEO_MIXER_GET_ATTRIBUTE_VALUES */ - &vlVdpVideoMixerDestroy, /* VDP_FUNC_ID_VIDEO_MIXER_DESTROY */ - &vlVdpVideoMixerRender, /* VDP_FUNC_ID_VIDEO_MIXER_RENDER */ - &vlVdpPresentationQueueTargetDestroy, /* VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_DESTROY */ - &vlVdpPresentationQueueCreate, /* VDP_FUNC_ID_PRESENTATION_QUEUE_CREATE */ - &vlVdpPresentationQueueDestroy, /* VDP_FUNC_ID_PRESENTATION_QUEUE_DESTROY */ - &vlVdpPresentationQueueSetBackgroundColor, /* VDP_FUNC_ID_PRESENTATION_QUEUE_SET_BACKGROUND_COLOR */ - &vlVdpPresentationQueueGetBackgroundColor, /* VDP_FUNC_ID_PRESENTATION_QUEUE_GET_BACKGROUND_COLOR */ - NULL, /* DUMMY */ - NULL, /* DUMMY */ - &vlVdpPresentationQueueGetTime, /* VDP_FUNC_ID_PRESENTATION_QUEUE_GET_TIME */ - &vlVdpPresentationQueueDisplay, /* VDP_FUNC_ID_PRESENTATION_QUEUE_DISPLAY */ - &vlVdpPresentationQueueBlockUntilSurfaceIdle, /* VDP_FUNC_ID_PRESENTATION_QUEUE_BLOCK_UNTIL_SURFACE_IDLE */ - &vlVdpPresentationQueueQuerySurfaceStatus, /* VDP_FUNC_ID_PRESENTATION_QUEUE_QUERY_SURFACE_STATUS */ - &vlVdpPreemptionCallbackRegister /* VDP_FUNC_ID_PREEMPTION_CALLBACK_REGISTER */ -}; - -static void* ftab_winsys[1] = -{ - &vlVdpPresentationQueueTargetCreateX11 /* VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_CREATE_X11 */ -}; - -static void* ftab_driver[4] = -{ - &vlVdpVideoSurfaceGallium, /* VDP_FUNC_ID_SURFACE_GALLIUM */ - &vlVdpOutputSurfaceGallium, /* VDP_FUNC_ID_OUTPUT_SURFACE_GALLIUM */ - &vlVdpVideoSurfaceDMABuf, /* VDP_FUNC_ID_VIDEO_SURFACE_DMA_BUF */ - &vlVdpOutputSurfaceDMABuf /* VDP_FUNC_ID_OUTPUT_SURFACE_DMA_BUF */ -}; - -boolean vlGetFuncFTAB(VdpFuncId function_id, void **func) -{ - assert(func); - *func = NULL; - - if (function_id < VDP_FUNC_ID_BASE_WINSYS) { - if (function_id < ARRAY_SIZE(ftab)) - *func = ftab[function_id]; - - } else if (function_id < VDP_FUNC_ID_BASE_DRIVER) { - function_id -= VDP_FUNC_ID_BASE_WINSYS; - if (function_id < ARRAY_SIZE(ftab_winsys)) - *func = ftab_winsys[function_id]; - - } else { - function_id -= VDP_FUNC_ID_BASE_DRIVER; - if (function_id < ARRAY_SIZE(ftab_driver)) - *func = ftab_driver[function_id]; - } - - return *func != NULL; -} diff --git a/src/gallium/state_trackers/vdpau/htab.c b/src/gallium/state_trackers/vdpau/htab.c deleted file mode 100644 index f596b2d571f..00000000000 --- a/src/gallium/state_trackers/vdpau/htab.c +++ /dev/null @@ -1,89 +0,0 @@ -/************************************************************************** - * - * Copyright 2010 Younes Manton. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include "util/u_handle_table.h" -#include "os/os_thread.h" -#include "vdpau_private.h" - -static struct handle_table *htab = NULL; -static mtx_t htab_lock = _MTX_INITIALIZER_NP; - -boolean vlCreateHTAB(void) -{ - boolean ret; - - /* Make sure handle table handles match VDPAU handles. */ - assert(sizeof(unsigned) <= sizeof(vlHandle)); - mtx_lock(&htab_lock); - if (!htab) - htab = handle_table_create(); - ret = htab != NULL; - mtx_unlock(&htab_lock); - return ret; -} - -void vlDestroyHTAB(void) -{ - mtx_lock(&htab_lock); - if (htab && !handle_table_get_first_handle(htab)) { - handle_table_destroy(htab); - htab = NULL; - } - mtx_unlock(&htab_lock); -} - -vlHandle vlAddDataHTAB(void *data) -{ - vlHandle handle = 0; - - assert(data); - mtx_lock(&htab_lock); - if (htab) - handle = handle_table_add(htab, data); - mtx_unlock(&htab_lock); - return handle; -} - -void* vlGetDataHTAB(vlHandle handle) -{ - void *data = NULL; - - assert(handle); - mtx_lock(&htab_lock); - if (htab) - data = handle_table_get(htab, handle); - mtx_unlock(&htab_lock); - return data; -} - -void vlRemoveDataHTAB(vlHandle handle) -{ - mtx_lock(&htab_lock); - if (htab) - handle_table_remove(htab, handle); - mtx_unlock(&htab_lock); -} diff --git a/src/gallium/state_trackers/vdpau/meson.build b/src/gallium/state_trackers/vdpau/meson.build deleted file mode 100644 index 28c4e9cab76..00000000000 --- a/src/gallium/state_trackers/vdpau/meson.build +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright © 2017, 2019 Intel Corproration - -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: - -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. - -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -VDPAU_MAJOR = 1 -VDPAU_MINOR = 0 - -libvdpau_st = static_library( - 'vdpau_st', - files( - 'bitmap.c', 'decode.c', 'device.c', 'ftab.c', 'htab.c', 'mixer.c', - 'output.c', 'preemption.c', 'presentation.c', 'query.c', 'surface.c', - ), - c_args : [ - c_vis_args, - '-DVER_MAJOR=@0@'.format(VDPAU_MAJOR), - '-DVER_MINOR=@0@'.format(VDPAU_MINOR), - ], - include_directories : [ - inc_include, inc_src, inc_util, inc_gallium, inc_gallium_aux, - ], - dependencies : [dep_vdpau, dep_xcb, dep_x11_xcb, dep_xcb_dri2, dep_libdrm], -) diff --git a/src/gallium/state_trackers/vdpau/mixer.c b/src/gallium/state_trackers/vdpau/mixer.c deleted file mode 100644 index 2e2bd20ef39..00000000000 --- a/src/gallium/state_trackers/vdpau/mixer.c +++ /dev/null @@ -1,1028 +0,0 @@ -/************************************************************************** - * - * Copyright 2010 Thomas Balling Sørensen. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include - -#include "util/u_memory.h" -#include "util/u_debug.h" - -#include "vl/vl_csc.h" - -#include "vdpau_private.h" - -/** - * Create a VdpVideoMixer. - */ -VdpStatus -vlVdpVideoMixerCreate(VdpDevice device, - uint32_t feature_count, - VdpVideoMixerFeature const *features, - uint32_t parameter_count, - VdpVideoMixerParameter const *parameters, - void const *const *parameter_values, - VdpVideoMixer *mixer) -{ - vlVdpVideoMixer *vmixer = NULL; - VdpStatus ret; - struct pipe_screen *screen; - unsigned max_size, i; - - vlVdpDevice *dev = vlGetDataHTAB(device); - if (!dev) - return VDP_STATUS_INVALID_HANDLE; - screen = dev->vscreen->pscreen; - - vmixer = CALLOC(1, sizeof(vlVdpVideoMixer)); - if (!vmixer) - return VDP_STATUS_RESOURCES; - - DeviceReference(&vmixer->device, dev); - - mtx_lock(&dev->mutex); - - if (!vl_compositor_init_state(&vmixer->cstate, dev->context)) { - ret = VDP_STATUS_ERROR; - goto no_compositor_state; - } - - vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601, NULL, true, &vmixer->csc); - if (!debug_get_bool_option("G3DVL_NO_CSC", FALSE)) { - if (!vl_compositor_set_csc_matrix(&vmixer->cstate, (const vl_csc_matrix *)&vmixer->csc, 1.0f, 0.0f)) { - ret = VDP_STATUS_ERROR; - goto err_csc_matrix; - } - } - - *mixer = vlAddDataHTAB(vmixer); - if (*mixer == 0) { - ret = VDP_STATUS_ERROR; - goto no_handle; - } - - ret = VDP_STATUS_INVALID_VIDEO_MIXER_FEATURE; - for (i = 0; i < feature_count; ++i) { - switch (features[i]) { - /* they are valid, but we doesn't support them */ - case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL: - case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2: - case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3: - case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4: - case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L5: - case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L6: - case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L7: - case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L8: - case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L9: - case VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE: - break; - - case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL: - vmixer->deint.supported = true; - break; - - case VDP_VIDEO_MIXER_FEATURE_SHARPNESS: - vmixer->sharpness.supported = true; - break; - - case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION: - vmixer->noise_reduction.supported = true; - break; - - case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY: - vmixer->luma_key.supported = true; - break; - - case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1: - vmixer->bicubic.supported = true; - break; - default: goto no_params; - } - } - - vmixer->chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; - ret = VDP_STATUS_INVALID_VIDEO_MIXER_PARAMETER; - for (i = 0; i < parameter_count; ++i) { - switch (parameters[i]) { - case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH: - vmixer->video_width = *(uint32_t*)parameter_values[i]; - break; - case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT: - vmixer->video_height = *(uint32_t*)parameter_values[i]; - break; - case VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE: - vmixer->chroma_format = ChromaToPipe(*(VdpChromaType*)parameter_values[i]); - break; - case VDP_VIDEO_MIXER_PARAMETER_LAYERS: - vmixer->max_layers = *(uint32_t*)parameter_values[i]; - break; - default: goto no_params; - } - } - ret = VDP_STATUS_INVALID_VALUE; - if (vmixer->max_layers > 4) { - VDPAU_MSG(VDPAU_WARN, "[VDPAU] Max layers > 4 not supported\n", vmixer->max_layers); - goto no_params; - } - - max_size = screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_2D_SIZE); - if (vmixer->video_width < 48 || vmixer->video_width > max_size) { - VDPAU_MSG(VDPAU_WARN, "[VDPAU] 48 < %u < %u not valid for width\n", - vmixer->video_width, max_size); - goto no_params; - } - if (vmixer->video_height < 48 || vmixer->video_height > max_size) { - VDPAU_MSG(VDPAU_WARN, "[VDPAU] 48 < %u < %u not valid for height\n", - vmixer->video_height, max_size); - goto no_params; - } - vmixer->luma_key.luma_min = 1.0f; - vmixer->luma_key.luma_max = 0.0f; - mtx_unlock(&dev->mutex); - - return VDP_STATUS_OK; - -no_params: - vlRemoveDataHTAB(*mixer); - -no_handle: -err_csc_matrix: - vl_compositor_cleanup_state(&vmixer->cstate); -no_compositor_state: - mtx_unlock(&dev->mutex); - DeviceReference(&vmixer->device, NULL); - FREE(vmixer); - return ret; -} - -/** - * Destroy a VdpVideoMixer. - */ -VdpStatus -vlVdpVideoMixerDestroy(VdpVideoMixer mixer) -{ - vlVdpVideoMixer *vmixer; - - vmixer = vlGetDataHTAB(mixer); - if (!vmixer) - return VDP_STATUS_INVALID_HANDLE; - - mtx_lock(&vmixer->device->mutex); - - vlRemoveDataHTAB(mixer); - - vl_compositor_cleanup_state(&vmixer->cstate); - - if (vmixer->deint.filter) { - vl_deint_filter_cleanup(vmixer->deint.filter); - FREE(vmixer->deint.filter); - } - - if (vmixer->noise_reduction.filter) { - vl_median_filter_cleanup(vmixer->noise_reduction.filter); - FREE(vmixer->noise_reduction.filter); - } - - if (vmixer->sharpness.filter) { - vl_matrix_filter_cleanup(vmixer->sharpness.filter); - FREE(vmixer->sharpness.filter); - } - - if (vmixer->bicubic.filter) { - vl_bicubic_filter_cleanup(vmixer->bicubic.filter); - FREE(vmixer->bicubic.filter); - } - mtx_unlock(&vmixer->device->mutex); - DeviceReference(&vmixer->device, NULL); - - FREE(vmixer); - - return VDP_STATUS_OK; -} - -/** - * Perform a video post-processing and compositing operation. - */ -VdpStatus vlVdpVideoMixerRender(VdpVideoMixer mixer, - VdpOutputSurface background_surface, - VdpRect const *background_source_rect, - VdpVideoMixerPictureStructure current_picture_structure, - uint32_t video_surface_past_count, - VdpVideoSurface const *video_surface_past, - VdpVideoSurface video_surface_current, - uint32_t video_surface_future_count, - VdpVideoSurface const *video_surface_future, - VdpRect const *video_source_rect, - VdpOutputSurface destination_surface, - VdpRect const *destination_rect, - VdpRect const *destination_video_rect, - uint32_t layer_count, - VdpLayer const *layers) -{ - enum vl_compositor_deinterlace deinterlace; - struct u_rect rect, clip, *prect, dirty_area; - unsigned i, layer = 0; - struct pipe_video_buffer *video_buffer; - struct pipe_sampler_view *sampler_view, sv_templ; - struct pipe_surface *surface, surf_templ; - struct pipe_context *pipe = NULL; - struct pipe_resource res_tmpl, *res; - - vlVdpVideoMixer *vmixer; - vlVdpSurface *surf; - vlVdpOutputSurface *dst, *bg = NULL; - - struct vl_compositor *compositor; - - vmixer = vlGetDataHTAB(mixer); - if (!vmixer) - return VDP_STATUS_INVALID_HANDLE; - - compositor = &vmixer->device->compositor; - - surf = vlGetDataHTAB(video_surface_current); - if (!surf) - return VDP_STATUS_INVALID_HANDLE; - video_buffer = surf->video_buffer; - - if (surf->device != vmixer->device) - return VDP_STATUS_HANDLE_DEVICE_MISMATCH; - - if (vmixer->video_width > video_buffer->width || - vmixer->video_height > video_buffer->height || - vmixer->chroma_format != pipe_format_to_chroma_format(video_buffer->buffer_format)) - return VDP_STATUS_INVALID_SIZE; - - if (layer_count > vmixer->max_layers) - return VDP_STATUS_INVALID_VALUE; - - dst = vlGetDataHTAB(destination_surface); - if (!dst) - return VDP_STATUS_INVALID_HANDLE; - - if (background_surface != VDP_INVALID_HANDLE) { - bg = vlGetDataHTAB(background_surface); - if (!bg) - return VDP_STATUS_INVALID_HANDLE; - } - - mtx_lock(&vmixer->device->mutex); - - vl_compositor_clear_layers(&vmixer->cstate); - - if (bg) - vl_compositor_set_rgba_layer(&vmixer->cstate, compositor, layer++, bg->sampler_view, - RectToPipe(background_source_rect, &rect), NULL, NULL); - - switch (current_picture_structure) { - case VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD: - deinterlace = VL_COMPOSITOR_BOB_TOP; - break; - - case VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD: - deinterlace = VL_COMPOSITOR_BOB_BOTTOM; - break; - - case VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME: - deinterlace = VL_COMPOSITOR_WEAVE; - break; - - default: - mtx_unlock(&vmixer->device->mutex); - return VDP_STATUS_INVALID_VIDEO_MIXER_PICTURE_STRUCTURE; - } - - if (deinterlace != VL_COMPOSITOR_WEAVE && vmixer->deint.enabled && - video_surface_past_count > 1 && video_surface_future_count > 0) { - vlVdpSurface *prevprev = vlGetDataHTAB(video_surface_past[1]); - vlVdpSurface *prev = vlGetDataHTAB(video_surface_past[0]); - vlVdpSurface *next = vlGetDataHTAB(video_surface_future[0]); - if (prevprev && prev && next && - vl_deint_filter_check_buffers(vmixer->deint.filter, - prevprev->video_buffer, prev->video_buffer, surf->video_buffer, next->video_buffer)) { - vl_deint_filter_render(vmixer->deint.filter, prevprev->video_buffer, - prev->video_buffer, surf->video_buffer, - next->video_buffer, - deinterlace == VL_COMPOSITOR_BOB_BOTTOM); - deinterlace = VL_COMPOSITOR_WEAVE; - video_buffer = vmixer->deint.filter->video_buffer; - } - } - - prect = RectToPipe(video_source_rect, &rect); - if (!prect) { - rect.x0 = 0; - rect.y0 = 0; - rect.x1 = surf->templat.width; - rect.y1 = surf->templat.height; - prect = ▭ - } - vl_compositor_set_buffer_layer(&vmixer->cstate, compositor, layer, video_buffer, prect, NULL, deinterlace); - - if (vmixer->bicubic.filter || vmixer->sharpness.filter || vmixer->noise_reduction.filter) { - pipe = vmixer->device->context; - memset(&res_tmpl, 0, sizeof(res_tmpl)); - - res_tmpl.target = PIPE_TEXTURE_2D; - res_tmpl.format = dst->sampler_view->format; - res_tmpl.depth0 = 1; - res_tmpl.array_size = 1; - res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; - res_tmpl.usage = PIPE_USAGE_DEFAULT; - - if (!vmixer->bicubic.filter) { - res_tmpl.width0 = dst->surface->width; - res_tmpl.height0 = dst->surface->height; - } else { - res_tmpl.width0 = surf->templat.width; - res_tmpl.height0 = surf->templat.height; - } - - res = pipe->screen->resource_create(pipe->screen, &res_tmpl); - - vlVdpDefaultSamplerViewTemplate(&sv_templ, res); - sampler_view = pipe->create_sampler_view(pipe, res, &sv_templ); - - memset(&surf_templ, 0, sizeof(surf_templ)); - surf_templ.format = res->format; - surface = pipe->create_surface(pipe, res, &surf_templ); - - vl_compositor_reset_dirty_area(&dirty_area); - pipe_resource_reference(&res, NULL); - } else { - surface = dst->surface; - sampler_view = dst->sampler_view; - dirty_area = dst->dirty_area; - } - - if (!vmixer->bicubic.filter) { - vl_compositor_set_layer_dst_area(&vmixer->cstate, layer++, RectToPipe(destination_video_rect, &rect)); - vl_compositor_set_dst_clip(&vmixer->cstate, RectToPipe(destination_rect, &clip)); - } - - for (i = 0; i < layer_count; ++i) { - vlVdpOutputSurface *src = vlGetDataHTAB(layers->source_surface); - if (!src) { - mtx_unlock(&vmixer->device->mutex); - return VDP_STATUS_INVALID_HANDLE; - } - - assert(layers->struct_version == VDP_LAYER_VERSION); - - vl_compositor_set_rgba_layer(&vmixer->cstate, compositor, layer, src->sampler_view, - RectToPipe(layers->source_rect, &rect), NULL, NULL); - vl_compositor_set_layer_dst_area(&vmixer->cstate, layer++, RectToPipe(layers->destination_rect, &rect)); - - ++layers; - } - - vl_compositor_render(&vmixer->cstate, compositor, surface, &dirty_area, true); - - if (vmixer->noise_reduction.filter) { - if (!vmixer->sharpness.filter && !vmixer->bicubic.filter) { - vl_median_filter_render(vmixer->noise_reduction.filter, - sampler_view, dst->surface); - } else { - res = pipe->screen->resource_create(pipe->screen, &res_tmpl); - struct pipe_sampler_view *sampler_view_temp = pipe->create_sampler_view(pipe, res, &sv_templ); - struct pipe_surface *surface_temp = pipe->create_surface(pipe, res, &surf_templ); - pipe_resource_reference(&res, NULL); - - vl_median_filter_render(vmixer->noise_reduction.filter, - sampler_view, surface_temp); - - pipe_sampler_view_reference(&sampler_view, NULL); - pipe_surface_reference(&surface, NULL); - - sampler_view = sampler_view_temp; - surface = surface_temp; - } - } - - if (vmixer->sharpness.filter) { - if (!vmixer->bicubic.filter) { - vl_matrix_filter_render(vmixer->sharpness.filter, - sampler_view, dst->surface); - } else { - res = pipe->screen->resource_create(pipe->screen, &res_tmpl); - struct pipe_sampler_view *sampler_view_temp = pipe->create_sampler_view(pipe, res, &sv_templ); - struct pipe_surface *surface_temp = pipe->create_surface(pipe, res, &surf_templ); - pipe_resource_reference(&res, NULL); - - vl_matrix_filter_render(vmixer->sharpness.filter, - sampler_view, surface_temp); - - pipe_sampler_view_reference(&sampler_view, NULL); - pipe_surface_reference(&surface, NULL); - - sampler_view = sampler_view_temp; - surface = surface_temp; - } - } - - if (vmixer->bicubic.filter) - vl_bicubic_filter_render(vmixer->bicubic.filter, - sampler_view, dst->surface, - RectToPipe(destination_video_rect, &rect), - RectToPipe(destination_rect, &clip)); - - if(surface != dst->surface) { - pipe_sampler_view_reference(&sampler_view, NULL); - pipe_surface_reference(&surface, NULL); - } - mtx_unlock(&vmixer->device->mutex); - - return VDP_STATUS_OK; -} - -static void -vlVdpVideoMixerUpdateDeinterlaceFilter(vlVdpVideoMixer *vmixer) -{ - struct pipe_context *pipe = vmixer->device->context; - assert(vmixer); - - /* remove existing filter */ - if (vmixer->deint.filter) { - vl_deint_filter_cleanup(vmixer->deint.filter); - FREE(vmixer->deint.filter); - vmixer->deint.filter = NULL; - } - - /* create a new filter if requested */ - if (vmixer->deint.enabled && vmixer->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420) { - vmixer->deint.filter = MALLOC(sizeof(struct vl_deint_filter)); - vmixer->deint.enabled = vl_deint_filter_init(vmixer->deint.filter, pipe, - vmixer->video_width, vmixer->video_height, - vmixer->skip_chroma_deint, vmixer->deint.spatial); - if (!vmixer->deint.enabled) { - FREE(vmixer->deint.filter); - } - } -} - -/** - * Update the noise reduction setting - */ -static void -vlVdpVideoMixerUpdateNoiseReductionFilter(vlVdpVideoMixer *vmixer) -{ - assert(vmixer); - - /* if present remove the old filter first */ - if (vmixer->noise_reduction.filter) { - vl_median_filter_cleanup(vmixer->noise_reduction.filter); - FREE(vmixer->noise_reduction.filter); - vmixer->noise_reduction.filter = NULL; - } - - /* and create a new filter as needed */ - if (vmixer->noise_reduction. enabled && vmixer->noise_reduction.level > 0) { - vmixer->noise_reduction.filter = MALLOC(sizeof(struct vl_median_filter)); - vl_median_filter_init(vmixer->noise_reduction.filter, vmixer->device->context, - vmixer->video_width, vmixer->video_height, - vmixer->noise_reduction.level + 1, - VL_MEDIAN_FILTER_CROSS); - } -} - -static void -vlVdpVideoMixerUpdateSharpnessFilter(vlVdpVideoMixer *vmixer) -{ - assert(vmixer); - - /* if present remove the old filter first */ - if (vmixer->sharpness.filter) { - vl_matrix_filter_cleanup(vmixer->sharpness.filter); - FREE(vmixer->sharpness.filter); - vmixer->sharpness.filter = NULL; - } - - /* and create a new filter as needed */ - if (vmixer->sharpness.enabled && vmixer->sharpness.value != 0.0f) { - float matrix[9]; - unsigned i; - - if (vmixer->sharpness.value > 0.0f) { - matrix[0] = -1.0f; matrix[1] = -1.0f; matrix[2] = -1.0f; - matrix[3] = -1.0f; matrix[4] = 8.0f; matrix[5] = -1.0f; - matrix[6] = -1.0f; matrix[7] = -1.0f; matrix[8] = -1.0f; - - for (i = 0; i < 9; ++i) - matrix[i] *= vmixer->sharpness.value; - - matrix[4] += 1.0f; - - } else { - matrix[0] = 1.0f; matrix[1] = 2.0f; matrix[2] = 1.0f; - matrix[3] = 2.0f; matrix[4] = 4.0f; matrix[5] = 2.0f; - matrix[6] = 1.0f; matrix[7] = 2.0f; matrix[8] = 1.0f; - - for (i = 0; i < 9; ++i) - matrix[i] *= fabsf(vmixer->sharpness.value) / 16.0f; - - matrix[4] += 1.0f - fabsf(vmixer->sharpness.value); - } - - vmixer->sharpness.filter = MALLOC(sizeof(struct vl_matrix_filter)); - vl_matrix_filter_init(vmixer->sharpness.filter, vmixer->device->context, - vmixer->video_width, vmixer->video_height, - 3, 3, matrix); - } -} - -/** - * Update the bicubic filter - */ -static void -vlVdpVideoMixerUpdateBicubicFilter(vlVdpVideoMixer *vmixer) -{ - assert(vmixer); - - /* if present remove the old filter first */ - if (vmixer->bicubic.filter) { - vl_bicubic_filter_cleanup(vmixer->bicubic.filter); - FREE(vmixer->bicubic.filter); - vmixer->bicubic.filter = NULL; - } - /* and create a new filter as needed */ - if (vmixer->bicubic.enabled) { - vmixer->bicubic.filter = MALLOC(sizeof(struct vl_bicubic_filter)); - vl_bicubic_filter_init(vmixer->bicubic.filter, vmixer->device->context, - vmixer->video_width, vmixer->video_height); - } -} - -/** - * Retrieve whether features were requested at creation time. - */ -VdpStatus -vlVdpVideoMixerGetFeatureSupport(VdpVideoMixer mixer, - uint32_t feature_count, - VdpVideoMixerFeature const *features, - VdpBool *feature_supports) -{ - vlVdpVideoMixer *vmixer; - unsigned i; - - if (!(features && feature_supports)) - return VDP_STATUS_INVALID_POINTER; - - vmixer = vlGetDataHTAB(mixer); - if (!vmixer) - return VDP_STATUS_INVALID_HANDLE; - - for (i = 0; i < feature_count; ++i) { - switch (features[i]) { - /* they are valid, but we doesn't support them */ - case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL: - case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2: - case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3: - case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4: - case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L5: - case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L6: - case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L7: - case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L8: - case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L9: - case VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE: - feature_supports[i] = false; - break; - - case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL: - feature_supports[i] = vmixer->deint.supported; - break; - - case VDP_VIDEO_MIXER_FEATURE_SHARPNESS: - feature_supports[i] = vmixer->sharpness.supported; - break; - - case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION: - feature_supports[i] = vmixer->noise_reduction.supported; - break; - - case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY: - feature_supports[i] = vmixer->luma_key.supported; - break; - - case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1: - feature_supports[i] = vmixer->bicubic.supported; - break; - - default: - return VDP_STATUS_INVALID_VIDEO_MIXER_FEATURE; - } - } - - return VDP_STATUS_OK; -} - -/** - * Enable or disable features. - */ -VdpStatus -vlVdpVideoMixerSetFeatureEnables(VdpVideoMixer mixer, - uint32_t feature_count, - VdpVideoMixerFeature const *features, - VdpBool const *feature_enables) -{ - vlVdpVideoMixer *vmixer; - unsigned i; - - if (!(features && feature_enables)) - return VDP_STATUS_INVALID_POINTER; - - vmixer = vlGetDataHTAB(mixer); - if (!vmixer) - return VDP_STATUS_INVALID_HANDLE; - - mtx_lock(&vmixer->device->mutex); - for (i = 0; i < feature_count; ++i) { - switch (features[i]) { - /* they are valid, but we doesn't support them */ - case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL: - case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2: - case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3: - case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4: - case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L5: - case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L6: - case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L7: - case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L8: - case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L9: - case VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE: - break; - - case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL: - vmixer->deint.enabled = feature_enables[i]; - vlVdpVideoMixerUpdateDeinterlaceFilter(vmixer); - break; - - case VDP_VIDEO_MIXER_FEATURE_SHARPNESS: - vmixer->sharpness.enabled = feature_enables[i]; - vlVdpVideoMixerUpdateSharpnessFilter(vmixer); - break; - - case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION: - vmixer->noise_reduction.enabled = feature_enables[i]; - vlVdpVideoMixerUpdateNoiseReductionFilter(vmixer); - break; - - case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY: - vmixer->luma_key.enabled = feature_enables[i]; - if (!debug_get_bool_option("G3DVL_NO_CSC", FALSE)) - if (!vl_compositor_set_csc_matrix(&vmixer->cstate, (const vl_csc_matrix *)&vmixer->csc, - vmixer->luma_key.luma_min, vmixer->luma_key.luma_max)) { - mtx_unlock(&vmixer->device->mutex); - return VDP_STATUS_ERROR; - } - break; - - case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1: - vmixer->bicubic.enabled = feature_enables[i]; - vlVdpVideoMixerUpdateBicubicFilter(vmixer); - break; - - default: - mtx_unlock(&vmixer->device->mutex); - return VDP_STATUS_INVALID_VIDEO_MIXER_FEATURE; - } - } - mtx_unlock(&vmixer->device->mutex); - - return VDP_STATUS_OK; -} - -/** - * Retrieve whether features are enabled. - */ -VdpStatus -vlVdpVideoMixerGetFeatureEnables(VdpVideoMixer mixer, - uint32_t feature_count, - VdpVideoMixerFeature const *features, - VdpBool *feature_enables) -{ - vlVdpVideoMixer *vmixer; - unsigned i; - - if (!(features && feature_enables)) - return VDP_STATUS_INVALID_POINTER; - - vmixer = vlGetDataHTAB(mixer); - if (!vmixer) - return VDP_STATUS_INVALID_HANDLE; - - for (i = 0; i < feature_count; ++i) { - switch (features[i]) { - /* they are valid, but we doesn't support them */ - case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL: - case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL: - case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2: - case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3: - case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4: - case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L5: - case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L6: - case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L7: - case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L8: - case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L9: - case VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE: - break; - - case VDP_VIDEO_MIXER_FEATURE_SHARPNESS: - feature_enables[i] = vmixer->sharpness.enabled; - break; - - case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION: - feature_enables[i] = vmixer->noise_reduction.enabled; - break; - - case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY: - feature_enables[i] = vmixer->luma_key.enabled; - break; - - case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1: - feature_enables[i] = vmixer->bicubic.enabled; - break; - - default: - return VDP_STATUS_INVALID_VIDEO_MIXER_FEATURE; - } - } - - return VDP_STATUS_OK; -} - -/** - * Set attribute values. - */ -VdpStatus -vlVdpVideoMixerSetAttributeValues(VdpVideoMixer mixer, - uint32_t attribute_count, - VdpVideoMixerAttribute const *attributes, - void const *const *attribute_values) -{ - const VdpColor *background_color; - union pipe_color_union color; - const float *vdp_csc; - float val; - unsigned i; - VdpStatus ret; - - if (!(attributes && attribute_values)) - return VDP_STATUS_INVALID_POINTER; - - vlVdpVideoMixer *vmixer = vlGetDataHTAB(mixer); - if (!vmixer) - return VDP_STATUS_INVALID_HANDLE; - - mtx_lock(&vmixer->device->mutex); - for (i = 0; i < attribute_count; ++i) { - switch (attributes[i]) { - case VDP_VIDEO_MIXER_ATTRIBUTE_BACKGROUND_COLOR: - background_color = attribute_values[i]; - color.f[0] = background_color->red; - color.f[1] = background_color->green; - color.f[2] = background_color->blue; - color.f[3] = background_color->alpha; - vl_compositor_set_clear_color(&vmixer->cstate, &color); - break; - case VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX: - vdp_csc = attribute_values[i]; - vmixer->custom_csc = !!vdp_csc; - if (!vdp_csc) - vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601, NULL, 1, &vmixer->csc); - else - memcpy(vmixer->csc, vdp_csc, sizeof(vl_csc_matrix)); - if (!debug_get_bool_option("G3DVL_NO_CSC", FALSE)) - if (!vl_compositor_set_csc_matrix(&vmixer->cstate, (const vl_csc_matrix *)&vmixer->csc, - vmixer->luma_key.luma_min, vmixer->luma_key.luma_max)) { - ret = VDP_STATUS_ERROR; - goto fail; - } - break; - - case VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL: - - val = *(float*)attribute_values[i]; - if (val < 0.0f || val > 1.0f) { - ret = VDP_STATUS_INVALID_VALUE; - goto fail; - } - - vmixer->noise_reduction.level = val * 10; - vlVdpVideoMixerUpdateNoiseReductionFilter(vmixer); - break; - - case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MIN_LUMA: - val = *(float*)attribute_values[i]; - if (val < 0.0f || val > 1.0f) { - ret = VDP_STATUS_INVALID_VALUE; - goto fail; - } - vmixer->luma_key.luma_min = val; - if (!debug_get_bool_option("G3DVL_NO_CSC", FALSE)) - if (!vl_compositor_set_csc_matrix(&vmixer->cstate, (const vl_csc_matrix *)&vmixer->csc, - vmixer->luma_key.luma_min, vmixer->luma_key.luma_max)) { - ret = VDP_STATUS_ERROR; - goto fail; - } - break; - - case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MAX_LUMA: - val = *(float*)attribute_values[i]; - if (val < 0.0f || val > 1.0f) { - ret = VDP_STATUS_INVALID_VALUE; - goto fail; - } - vmixer->luma_key.luma_max = val; - if (!debug_get_bool_option("G3DVL_NO_CSC", FALSE)) - if (!vl_compositor_set_csc_matrix(&vmixer->cstate, (const vl_csc_matrix *)&vmixer->csc, - vmixer->luma_key.luma_min, vmixer->luma_key.luma_max)) { - ret = VDP_STATUS_ERROR; - goto fail; - } - break; - - case VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL: - - val = *(float*)attribute_values[i]; - if (val < -1.0f || val > 1.0f) { - ret = VDP_STATUS_INVALID_VALUE; - goto fail; - } - - vmixer->sharpness.value = val; - vlVdpVideoMixerUpdateSharpnessFilter(vmixer); - break; - - case VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE: - if (*(uint8_t*)attribute_values[i] > 1) { - ret = VDP_STATUS_INVALID_VALUE; - goto fail; - } - vmixer->skip_chroma_deint = *(uint8_t*)attribute_values[i]; - vlVdpVideoMixerUpdateDeinterlaceFilter(vmixer); - break; - default: - ret = VDP_STATUS_INVALID_VIDEO_MIXER_ATTRIBUTE; - goto fail; - } - } - mtx_unlock(&vmixer->device->mutex); - - return VDP_STATUS_OK; -fail: - mtx_unlock(&vmixer->device->mutex); - return ret; -} - -/** - * Retrieve parameter values given at creation time. - */ -VdpStatus -vlVdpVideoMixerGetParameterValues(VdpVideoMixer mixer, - uint32_t parameter_count, - VdpVideoMixerParameter const *parameters, - void *const *parameter_values) -{ - vlVdpVideoMixer *vmixer = vlGetDataHTAB(mixer); - unsigned i; - if (!vmixer) - return VDP_STATUS_INVALID_HANDLE; - - if (!parameter_count) - return VDP_STATUS_OK; - if (!(parameters && parameter_values)) - return VDP_STATUS_INVALID_POINTER; - for (i = 0; i < parameter_count; ++i) { - switch (parameters[i]) { - case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH: - *(uint32_t*)parameter_values[i] = vmixer->video_width; - break; - case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT: - *(uint32_t*)parameter_values[i] = vmixer->video_height; - break; - case VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE: - *(VdpChromaType*)parameter_values[i] = PipeToChroma(vmixer->chroma_format); - break; - case VDP_VIDEO_MIXER_PARAMETER_LAYERS: - *(uint32_t*)parameter_values[i] = vmixer->max_layers; - break; - default: - return VDP_STATUS_INVALID_VIDEO_MIXER_PARAMETER; - } - } - return VDP_STATUS_OK; -} - -/** - * Retrieve current attribute values. - */ -VdpStatus -vlVdpVideoMixerGetAttributeValues(VdpVideoMixer mixer, - uint32_t attribute_count, - VdpVideoMixerAttribute const *attributes, - void *const *attribute_values) -{ - unsigned i; - VdpCSCMatrix **vdp_csc; - - if (!(attributes && attribute_values)) - return VDP_STATUS_INVALID_POINTER; - - vlVdpVideoMixer *vmixer = vlGetDataHTAB(mixer); - if (!vmixer) - return VDP_STATUS_INVALID_HANDLE; - - mtx_lock(&vmixer->device->mutex); - for (i = 0; i < attribute_count; ++i) { - switch (attributes[i]) { - case VDP_VIDEO_MIXER_ATTRIBUTE_BACKGROUND_COLOR: - vl_compositor_get_clear_color(&vmixer->cstate, attribute_values[i]); - break; - case VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX: - vdp_csc = attribute_values[i]; - if (!vmixer->custom_csc) { - *vdp_csc = NULL; - break; - } - memcpy(*vdp_csc, vmixer->csc, sizeof(float)*12); - break; - - case VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL: - *(float*)attribute_values[i] = (float)vmixer->noise_reduction.level / 10.0f; - break; - - case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MIN_LUMA: - *(float*)attribute_values[i] = vmixer->luma_key.luma_min; - break; - case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MAX_LUMA: - *(float*)attribute_values[i] = vmixer->luma_key.luma_max; - break; - case VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL: - *(float*)attribute_values[i] = vmixer->sharpness.value; - break; - case VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE: - *(uint8_t*)attribute_values[i] = vmixer->skip_chroma_deint; - break; - default: - mtx_unlock(&vmixer->device->mutex); - return VDP_STATUS_INVALID_VIDEO_MIXER_ATTRIBUTE; - } - } - mtx_unlock(&vmixer->device->mutex); - return VDP_STATUS_OK; -} - -/** - * Generate a color space conversion matrix. - */ -VdpStatus -vlVdpGenerateCSCMatrix(VdpProcamp *procamp, - VdpColorStandard standard, - VdpCSCMatrix *csc_matrix) -{ - enum VL_CSC_COLOR_STANDARD vl_std; - struct vl_procamp camp; - - if (!csc_matrix) - return VDP_STATUS_INVALID_POINTER; - - switch (standard) { - case VDP_COLOR_STANDARD_ITUR_BT_601: vl_std = VL_CSC_COLOR_STANDARD_BT_601; break; - case VDP_COLOR_STANDARD_ITUR_BT_709: vl_std = VL_CSC_COLOR_STANDARD_BT_709; break; - case VDP_COLOR_STANDARD_SMPTE_240M: vl_std = VL_CSC_COLOR_STANDARD_SMPTE_240M; break; - default: return VDP_STATUS_INVALID_COLOR_STANDARD; - } - - if (procamp) { - if (procamp->struct_version > VDP_PROCAMP_VERSION) - return VDP_STATUS_INVALID_STRUCT_VERSION; - camp.brightness = procamp->brightness; - camp.contrast = procamp->contrast; - camp.saturation = procamp->saturation; - camp.hue = procamp->hue; - } - - vl_csc_get_matrix(vl_std, procamp ? &camp : NULL, true, csc_matrix); - return VDP_STATUS_OK; -} diff --git a/src/gallium/state_trackers/vdpau/output.c b/src/gallium/state_trackers/vdpau/output.c deleted file mode 100644 index ac8fc550bc7..00000000000 --- a/src/gallium/state_trackers/vdpau/output.c +++ /dev/null @@ -1,828 +0,0 @@ -/************************************************************************** - * - * Copyright 2010 Thomas Balling Sørensen. - * Copyright 2011 Christian König. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include - -#include "util/u_debug.h" -#include "util/u_memory.h" -#include "util/u_sampler.h" -#include "util/format/u_format.h" -#include "util/u_surface.h" - -#include "vl/vl_csc.h" - -#include "state_tracker/drm_driver.h" - -#include "vdpau_private.h" - -/** - * Create a VdpOutputSurface. - */ -VdpStatus -vlVdpOutputSurfaceCreate(VdpDevice device, - VdpRGBAFormat rgba_format, - uint32_t width, uint32_t height, - VdpOutputSurface *surface) -{ - struct pipe_context *pipe; - struct pipe_resource res_tmpl, *res; - struct pipe_sampler_view sv_templ; - struct pipe_surface surf_templ; - - vlVdpOutputSurface *vlsurface = NULL; - - if (!(width && height)) - return VDP_STATUS_INVALID_SIZE; - - vlVdpDevice *dev = vlGetDataHTAB(device); - if (!dev) - return VDP_STATUS_INVALID_HANDLE; - - pipe = dev->context; - if (!pipe) - return VDP_STATUS_INVALID_HANDLE; - - vlsurface = CALLOC(1, sizeof(vlVdpOutputSurface)); - if (!vlsurface) - return VDP_STATUS_RESOURCES; - - DeviceReference(&vlsurface->device, dev); - - memset(&res_tmpl, 0, sizeof(res_tmpl)); - - /* - * The output won't look correctly when this buffer is send to X, - * if the VDPAU RGB component order doesn't match the X11 one so - * we only allow the X11 format - */ - vlsurface->send_to_X = dev->vscreen->color_depth == 24 && - rgba_format == VDP_RGBA_FORMAT_B8G8R8A8; - - res_tmpl.target = PIPE_TEXTURE_2D; - res_tmpl.format = VdpFormatRGBAToPipe(rgba_format); - res_tmpl.width0 = width; - res_tmpl.height0 = height; - res_tmpl.depth0 = 1; - res_tmpl.array_size = 1; - res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET | - PIPE_BIND_SHARED | PIPE_BIND_SCANOUT; - res_tmpl.usage = PIPE_USAGE_DEFAULT; - - mtx_lock(&dev->mutex); - - if (!CheckSurfaceParams(pipe->screen, &res_tmpl)) - goto err_unlock; - - res = pipe->screen->resource_create(pipe->screen, &res_tmpl); - if (!res) - goto err_unlock; - - vlVdpDefaultSamplerViewTemplate(&sv_templ, res); - vlsurface->sampler_view = pipe->create_sampler_view(pipe, res, &sv_templ); - if (!vlsurface->sampler_view) - goto err_resource; - - memset(&surf_templ, 0, sizeof(surf_templ)); - surf_templ.format = res->format; - vlsurface->surface = pipe->create_surface(pipe, res, &surf_templ); - if (!vlsurface->surface) - goto err_resource; - - *surface = vlAddDataHTAB(vlsurface); - if (*surface == 0) - goto err_resource; - - pipe_resource_reference(&res, NULL); - - if (!vl_compositor_init_state(&vlsurface->cstate, pipe)) - goto err_resource; - - vl_compositor_reset_dirty_area(&vlsurface->dirty_area); - mtx_unlock(&dev->mutex); - - return VDP_STATUS_OK; - -err_resource: - pipe_sampler_view_reference(&vlsurface->sampler_view, NULL); - pipe_surface_reference(&vlsurface->surface, NULL); - pipe_resource_reference(&res, NULL); -err_unlock: - mtx_unlock(&dev->mutex); - DeviceReference(&vlsurface->device, NULL); - FREE(vlsurface); - return VDP_STATUS_ERROR; -} - -/** - * Destroy a VdpOutputSurface. - */ -VdpStatus -vlVdpOutputSurfaceDestroy(VdpOutputSurface surface) -{ - vlVdpOutputSurface *vlsurface; - struct pipe_context *pipe; - - vlsurface = vlGetDataHTAB(surface); - if (!vlsurface) - return VDP_STATUS_INVALID_HANDLE; - - pipe = vlsurface->device->context; - - mtx_lock(&vlsurface->device->mutex); - - pipe_surface_reference(&vlsurface->surface, NULL); - pipe_sampler_view_reference(&vlsurface->sampler_view, NULL); - pipe->screen->fence_reference(pipe->screen, &vlsurface->fence, NULL); - vl_compositor_cleanup_state(&vlsurface->cstate); - mtx_unlock(&vlsurface->device->mutex); - - vlRemoveDataHTAB(surface); - DeviceReference(&vlsurface->device, NULL); - FREE(vlsurface); - - return VDP_STATUS_OK; -} - -/** - * Retrieve the parameters used to create a VdpOutputSurface. - */ -VdpStatus -vlVdpOutputSurfaceGetParameters(VdpOutputSurface surface, - VdpRGBAFormat *rgba_format, - uint32_t *width, uint32_t *height) -{ - vlVdpOutputSurface *vlsurface; - - vlsurface = vlGetDataHTAB(surface); - if (!vlsurface) - return VDP_STATUS_INVALID_HANDLE; - - *rgba_format = PipeToFormatRGBA(vlsurface->sampler_view->texture->format); - *width = vlsurface->sampler_view->texture->width0; - *height = vlsurface->sampler_view->texture->height0; - - return VDP_STATUS_OK; -} - -/** - * Copy image data from a VdpOutputSurface to application memory in the - * surface's native format. - */ -VdpStatus -vlVdpOutputSurfaceGetBitsNative(VdpOutputSurface surface, - VdpRect const *source_rect, - void *const *destination_data, - uint32_t const *destination_pitches) -{ - vlVdpOutputSurface *vlsurface; - struct pipe_context *pipe; - struct pipe_resource *res; - struct pipe_box box; - struct pipe_transfer *transfer; - uint8_t *map; - - vlsurface = vlGetDataHTAB(surface); - if (!vlsurface) - return VDP_STATUS_INVALID_HANDLE; - - pipe = vlsurface->device->context; - if (!pipe) - return VDP_STATUS_INVALID_HANDLE; - - if (!destination_data || !destination_pitches) - return VDP_STATUS_INVALID_POINTER; - - mtx_lock(&vlsurface->device->mutex); - - res = vlsurface->sampler_view->texture; - box = RectToPipeBox(source_rect, res); - map = pipe->transfer_map(pipe, res, 0, PIPE_TRANSFER_READ, &box, &transfer); - if (!map) { - mtx_unlock(&vlsurface->device->mutex); - return VDP_STATUS_RESOURCES; - } - - util_copy_rect(*destination_data, res->format, *destination_pitches, 0, 0, - box.width, box.height, map, transfer->stride, 0, 0); - - pipe_transfer_unmap(pipe, transfer); - mtx_unlock(&vlsurface->device->mutex); - - return VDP_STATUS_OK; -} - -/** - * Copy image data from application memory in the surface's native format to - * a VdpOutputSurface. - */ -VdpStatus -vlVdpOutputSurfacePutBitsNative(VdpOutputSurface surface, - void const *const *source_data, - uint32_t const *source_pitches, - VdpRect const *destination_rect) -{ - vlVdpOutputSurface *vlsurface; - struct pipe_box dst_box; - struct pipe_context *pipe; - - vlsurface = vlGetDataHTAB(surface); - if (!vlsurface) - return VDP_STATUS_INVALID_HANDLE; - - pipe = vlsurface->device->context; - if (!pipe) - return VDP_STATUS_INVALID_HANDLE; - - if (!source_data || !source_pitches) - return VDP_STATUS_INVALID_POINTER; - - mtx_lock(&vlsurface->device->mutex); - - dst_box = RectToPipeBox(destination_rect, vlsurface->sampler_view->texture); - - /* Check for a no-op. (application bug?) */ - if (!dst_box.width || !dst_box.height) { - mtx_unlock(&vlsurface->device->mutex); - return VDP_STATUS_OK; - } - - pipe->texture_subdata(pipe, vlsurface->sampler_view->texture, 0, - PIPE_TRANSFER_WRITE, &dst_box, *source_data, - *source_pitches, 0); - mtx_unlock(&vlsurface->device->mutex); - - return VDP_STATUS_OK; -} - -/** - * Copy image data from application memory in a specific indexed format to - * a VdpOutputSurface. - */ -VdpStatus -vlVdpOutputSurfacePutBitsIndexed(VdpOutputSurface surface, - VdpIndexedFormat source_indexed_format, - void const *const *source_data, - uint32_t const *source_pitch, - VdpRect const *destination_rect, - VdpColorTableFormat color_table_format, - void const *color_table) -{ - vlVdpOutputSurface *vlsurface; - struct pipe_context *context; - struct vl_compositor *compositor; - struct vl_compositor_state *cstate; - - enum pipe_format index_format; - enum pipe_format colortbl_format; - - struct pipe_resource *res, res_tmpl; - struct pipe_sampler_view sv_tmpl; - struct pipe_sampler_view *sv_idx = NULL, *sv_tbl = NULL; - - struct pipe_box box; - struct u_rect dst_rect; - - vlsurface = vlGetDataHTAB(surface); - if (!vlsurface) - return VDP_STATUS_INVALID_HANDLE; - - context = vlsurface->device->context; - compositor = &vlsurface->device->compositor; - cstate = &vlsurface->cstate; - - index_format = FormatIndexedToPipe(source_indexed_format); - if (index_format == PIPE_FORMAT_NONE) - return VDP_STATUS_INVALID_INDEXED_FORMAT; - - if (!source_data || !source_pitch) - return VDP_STATUS_INVALID_POINTER; - - colortbl_format = FormatColorTableToPipe(color_table_format); - if (colortbl_format == PIPE_FORMAT_NONE) - return VDP_STATUS_INVALID_COLOR_TABLE_FORMAT; - - if (!color_table) - return VDP_STATUS_INVALID_POINTER; - - memset(&res_tmpl, 0, sizeof(res_tmpl)); - res_tmpl.target = PIPE_TEXTURE_2D; - res_tmpl.format = index_format; - - if (destination_rect) { - res_tmpl.width0 = abs(destination_rect->x0-destination_rect->x1); - res_tmpl.height0 = abs(destination_rect->y0-destination_rect->y1); - } else { - res_tmpl.width0 = vlsurface->surface->texture->width0; - res_tmpl.height0 = vlsurface->surface->texture->height0; - } - res_tmpl.depth0 = 1; - res_tmpl.array_size = 1; - res_tmpl.usage = PIPE_USAGE_STAGING; - res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW; - - mtx_lock(&vlsurface->device->mutex); - - if (!CheckSurfaceParams(context->screen, &res_tmpl)) - goto error_resource; - - res = context->screen->resource_create(context->screen, &res_tmpl); - if (!res) - goto error_resource; - - box.x = box.y = box.z = 0; - box.width = res->width0; - box.height = res->height0; - box.depth = res->depth0; - - context->texture_subdata(context, res, 0, PIPE_TRANSFER_WRITE, &box, - source_data[0], source_pitch[0], - source_pitch[0] * res->height0); - - memset(&sv_tmpl, 0, sizeof(sv_tmpl)); - u_sampler_view_default_template(&sv_tmpl, res, res->format); - - sv_idx = context->create_sampler_view(context, res, &sv_tmpl); - pipe_resource_reference(&res, NULL); - - if (!sv_idx) - goto error_resource; - - memset(&res_tmpl, 0, sizeof(res_tmpl)); - res_tmpl.target = PIPE_TEXTURE_1D; - res_tmpl.format = colortbl_format; - res_tmpl.width0 = 1 << util_format_get_component_bits( - index_format, UTIL_FORMAT_COLORSPACE_RGB, 0); - res_tmpl.height0 = 1; - res_tmpl.depth0 = 1; - res_tmpl.array_size = 1; - res_tmpl.usage = PIPE_USAGE_STAGING; - res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW; - - res = context->screen->resource_create(context->screen, &res_tmpl); - if (!res) - goto error_resource; - - box.x = box.y = box.z = 0; - box.width = res->width0; - box.height = res->height0; - box.depth = res->depth0; - - context->texture_subdata(context, res, 0, PIPE_TRANSFER_WRITE, &box, color_table, - util_format_get_stride(colortbl_format, res->width0), 0); - - memset(&sv_tmpl, 0, sizeof(sv_tmpl)); - u_sampler_view_default_template(&sv_tmpl, res, res->format); - - sv_tbl = context->create_sampler_view(context, res, &sv_tmpl); - pipe_resource_reference(&res, NULL); - - if (!sv_tbl) - goto error_resource; - - vl_compositor_clear_layers(cstate); - vl_compositor_set_palette_layer(cstate, compositor, 0, sv_idx, sv_tbl, NULL, NULL, false); - vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect)); - vl_compositor_render(cstate, compositor, vlsurface->surface, &vlsurface->dirty_area, false); - - pipe_sampler_view_reference(&sv_idx, NULL); - pipe_sampler_view_reference(&sv_tbl, NULL); - mtx_unlock(&vlsurface->device->mutex); - - return VDP_STATUS_OK; - -error_resource: - pipe_sampler_view_reference(&sv_idx, NULL); - pipe_sampler_view_reference(&sv_tbl, NULL); - mtx_unlock(&vlsurface->device->mutex); - return VDP_STATUS_RESOURCES; -} - -/** - * Copy image data from application memory in a specific YCbCr format to - * a VdpOutputSurface. - */ -VdpStatus -vlVdpOutputSurfacePutBitsYCbCr(VdpOutputSurface surface, - VdpYCbCrFormat source_ycbcr_format, - void const *const *source_data, - uint32_t const *source_pitches, - VdpRect const *destination_rect, - VdpCSCMatrix const *csc_matrix) -{ - vlVdpOutputSurface *vlsurface; - struct vl_compositor *compositor; - struct vl_compositor_state *cstate; - - struct pipe_context *pipe; - enum pipe_format format; - struct pipe_video_buffer vtmpl, *vbuffer; - struct u_rect dst_rect; - struct pipe_sampler_view **sampler_views; - - unsigned i; - - vlsurface = vlGetDataHTAB(surface); - if (!vlsurface) - return VDP_STATUS_INVALID_HANDLE; - - - pipe = vlsurface->device->context; - compositor = &vlsurface->device->compositor; - cstate = &vlsurface->cstate; - - format = FormatYCBCRToPipe(source_ycbcr_format); - if (format == PIPE_FORMAT_NONE) - return VDP_STATUS_INVALID_Y_CB_CR_FORMAT; - - if (!source_data || !source_pitches) - return VDP_STATUS_INVALID_POINTER; - - mtx_lock(&vlsurface->device->mutex); - memset(&vtmpl, 0, sizeof(vtmpl)); - vtmpl.buffer_format = format; - - if (destination_rect) { - vtmpl.width = abs(destination_rect->x0-destination_rect->x1); - vtmpl.height = abs(destination_rect->y0-destination_rect->y1); - } else { - vtmpl.width = vlsurface->surface->texture->width0; - vtmpl.height = vlsurface->surface->texture->height0; - } - - vbuffer = pipe->create_video_buffer(pipe, &vtmpl); - if (!vbuffer) { - mtx_unlock(&vlsurface->device->mutex); - return VDP_STATUS_RESOURCES; - } - - sampler_views = vbuffer->get_sampler_view_planes(vbuffer); - if (!sampler_views) { - vbuffer->destroy(vbuffer); - mtx_unlock(&vlsurface->device->mutex); - return VDP_STATUS_RESOURCES; - } - - for (i = 0; i < 3; ++i) { - struct pipe_sampler_view *sv = sampler_views[i]; - if (!sv) continue; - - struct pipe_box dst_box = { - 0, 0, 0, - sv->texture->width0, sv->texture->height0, 1 - }; - - pipe->texture_subdata(pipe, sv->texture, 0, PIPE_TRANSFER_WRITE, &dst_box, - source_data[i], source_pitches[i], 0); - } - - if (!csc_matrix) { - vl_csc_matrix csc; - vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601, NULL, 1, &csc); - if (!vl_compositor_set_csc_matrix(cstate, (const vl_csc_matrix*)&csc, 1.0f, 0.0f)) - goto err_csc_matrix; - } else { - if (!vl_compositor_set_csc_matrix(cstate, csc_matrix, 1.0f, 0.0f)) - goto err_csc_matrix; - } - - vl_compositor_clear_layers(cstate); - vl_compositor_set_buffer_layer(cstate, compositor, 0, vbuffer, NULL, NULL, VL_COMPOSITOR_WEAVE); - vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect)); - vl_compositor_render(cstate, compositor, vlsurface->surface, &vlsurface->dirty_area, false); - - vbuffer->destroy(vbuffer); - mtx_unlock(&vlsurface->device->mutex); - - return VDP_STATUS_OK; -err_csc_matrix: - vbuffer->destroy(vbuffer); - mtx_unlock(&vlsurface->device->mutex); - return VDP_STATUS_ERROR; -} - -static unsigned -BlendFactorToPipe(VdpOutputSurfaceRenderBlendFactor factor) -{ - switch (factor) { - case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ZERO: - return PIPE_BLENDFACTOR_ZERO; - case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE: - return PIPE_BLENDFACTOR_ONE; - case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_COLOR: - return PIPE_BLENDFACTOR_SRC_COLOR; - case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_COLOR: - return PIPE_BLENDFACTOR_INV_SRC_COLOR; - case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA: - return PIPE_BLENDFACTOR_SRC_ALPHA; - case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA: - return PIPE_BLENDFACTOR_INV_SRC_ALPHA; - case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_DST_ALPHA: - return PIPE_BLENDFACTOR_DST_ALPHA; - case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_DST_ALPHA: - return PIPE_BLENDFACTOR_INV_DST_ALPHA; - case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_DST_COLOR: - return PIPE_BLENDFACTOR_DST_COLOR; - case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_DST_COLOR: - return PIPE_BLENDFACTOR_INV_DST_COLOR; - case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA_SATURATE: - return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE; - case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_CONSTANT_COLOR: - return PIPE_BLENDFACTOR_CONST_COLOR; - case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR: - return PIPE_BLENDFACTOR_INV_CONST_COLOR; - case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_CONSTANT_ALPHA: - return PIPE_BLENDFACTOR_CONST_ALPHA; - case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA: - return PIPE_BLENDFACTOR_INV_CONST_ALPHA; - default: - assert(0); - return PIPE_BLENDFACTOR_ONE; - } -} - -static unsigned -BlendEquationToPipe(VdpOutputSurfaceRenderBlendEquation equation) -{ - switch (equation) { - case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_SUBTRACT: - return PIPE_BLEND_SUBTRACT; - case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_REVERSE_SUBTRACT: - return PIPE_BLEND_REVERSE_SUBTRACT; - case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD: - return PIPE_BLEND_ADD; - case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_MIN: - return PIPE_BLEND_MIN; - case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_MAX: - return PIPE_BLEND_MAX; - default: - assert(0); - return PIPE_BLEND_ADD; - } -} - -static void * -BlenderToPipe(struct pipe_context *context, - VdpOutputSurfaceRenderBlendState const *blend_state) -{ - struct pipe_blend_state blend; - - memset(&blend, 0, sizeof blend); - blend.independent_blend_enable = 0; - - if (blend_state) { - blend.rt[0].blend_enable = 1; - blend.rt[0].rgb_src_factor = BlendFactorToPipe(blend_state->blend_factor_source_color); - blend.rt[0].rgb_dst_factor = BlendFactorToPipe(blend_state->blend_factor_destination_color); - blend.rt[0].alpha_src_factor = BlendFactorToPipe(blend_state->blend_factor_source_alpha); - blend.rt[0].alpha_dst_factor = BlendFactorToPipe(blend_state->blend_factor_destination_alpha); - blend.rt[0].rgb_func = BlendEquationToPipe(blend_state->blend_equation_color); - blend.rt[0].alpha_func = BlendEquationToPipe(blend_state->blend_equation_alpha); - } else { - blend.rt[0].blend_enable = 0; - } - - blend.logicop_enable = 0; - blend.logicop_func = PIPE_LOGICOP_CLEAR; - blend.rt[0].colormask = PIPE_MASK_RGBA; - blend.dither = 0; - - return context->create_blend_state(context, &blend); -} - -static struct vertex4f * -ColorsToPipe(VdpColor const *colors, uint32_t flags, struct vertex4f result[4]) -{ - unsigned i; - struct vertex4f *dst = result; - - if (!colors) - return NULL; - - for (i = 0; i < 4; ++i) { - dst->x = colors->red; - dst->y = colors->green; - dst->z = colors->blue; - dst->w = colors->alpha; - - ++dst; - if (flags & VDP_OUTPUT_SURFACE_RENDER_COLOR_PER_VERTEX) - ++colors; - } - return result; -} - -/** - * Composite a sub-rectangle of a VdpOutputSurface into a sub-rectangle of - * another VdpOutputSurface; Output Surface object VdpOutputSurface. - */ -VdpStatus -vlVdpOutputSurfaceRenderOutputSurface(VdpOutputSurface destination_surface, - VdpRect const *destination_rect, - VdpOutputSurface source_surface, - VdpRect const *source_rect, - VdpColor const *colors, - VdpOutputSurfaceRenderBlendState const *blend_state, - uint32_t flags) -{ - vlVdpOutputSurface *dst_vlsurface; - - struct pipe_context *context; - struct pipe_sampler_view *src_sv; - struct vl_compositor *compositor; - struct vl_compositor_state *cstate; - - struct u_rect src_rect, dst_rect; - - struct vertex4f vlcolors[4]; - void *blend; - - dst_vlsurface = vlGetDataHTAB(destination_surface); - if (!dst_vlsurface) - return VDP_STATUS_INVALID_HANDLE; - - if (source_surface == VDP_INVALID_HANDLE) { - src_sv = dst_vlsurface->device->dummy_sv; - - } else { - vlVdpOutputSurface *src_vlsurface = vlGetDataHTAB(source_surface); - if (!src_vlsurface) - return VDP_STATUS_INVALID_HANDLE; - - if (dst_vlsurface->device != src_vlsurface->device) - return VDP_STATUS_HANDLE_DEVICE_MISMATCH; - - src_sv = src_vlsurface->sampler_view; - } - - mtx_lock(&dst_vlsurface->device->mutex); - - context = dst_vlsurface->device->context; - compositor = &dst_vlsurface->device->compositor; - cstate = &dst_vlsurface->cstate; - - blend = BlenderToPipe(context, blend_state); - - vl_compositor_clear_layers(cstate); - vl_compositor_set_layer_blend(cstate, 0, blend, false); - vl_compositor_set_rgba_layer(cstate, compositor, 0, src_sv, - RectToPipe(source_rect, &src_rect), NULL, - ColorsToPipe(colors, flags, vlcolors)); - STATIC_ASSERT(VL_COMPOSITOR_ROTATE_0 == VDP_OUTPUT_SURFACE_RENDER_ROTATE_0); - STATIC_ASSERT(VL_COMPOSITOR_ROTATE_90 == VDP_OUTPUT_SURFACE_RENDER_ROTATE_90); - STATIC_ASSERT(VL_COMPOSITOR_ROTATE_180 == VDP_OUTPUT_SURFACE_RENDER_ROTATE_180); - STATIC_ASSERT(VL_COMPOSITOR_ROTATE_270 == VDP_OUTPUT_SURFACE_RENDER_ROTATE_270); - vl_compositor_set_layer_rotation(cstate, 0, flags & 3); - vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect)); - vl_compositor_render(cstate, compositor, dst_vlsurface->surface, &dst_vlsurface->dirty_area, false); - - context->delete_blend_state(context, blend); - mtx_unlock(&dst_vlsurface->device->mutex); - - return VDP_STATUS_OK; -} - -/** - * Composite a sub-rectangle of a VdpBitmapSurface into a sub-rectangle of - * a VdpOutputSurface; Output Surface object VdpOutputSurface. - */ -VdpStatus -vlVdpOutputSurfaceRenderBitmapSurface(VdpOutputSurface destination_surface, - VdpRect const *destination_rect, - VdpBitmapSurface source_surface, - VdpRect const *source_rect, - VdpColor const *colors, - VdpOutputSurfaceRenderBlendState const *blend_state, - uint32_t flags) -{ - vlVdpOutputSurface *dst_vlsurface; - - struct pipe_context *context; - struct pipe_sampler_view *src_sv; - struct vl_compositor *compositor; - struct vl_compositor_state *cstate; - - struct u_rect src_rect, dst_rect; - - struct vertex4f vlcolors[4]; - void *blend; - - dst_vlsurface = vlGetDataHTAB(destination_surface); - if (!dst_vlsurface) - return VDP_STATUS_INVALID_HANDLE; - - if (source_surface == VDP_INVALID_HANDLE) { - src_sv = dst_vlsurface->device->dummy_sv; - - } else { - vlVdpBitmapSurface *src_vlsurface = vlGetDataHTAB(source_surface); - if (!src_vlsurface) - return VDP_STATUS_INVALID_HANDLE; - - if (dst_vlsurface->device != src_vlsurface->device) - return VDP_STATUS_HANDLE_DEVICE_MISMATCH; - - src_sv = src_vlsurface->sampler_view; - } - - context = dst_vlsurface->device->context; - compositor = &dst_vlsurface->device->compositor; - cstate = &dst_vlsurface->cstate; - - mtx_lock(&dst_vlsurface->device->mutex); - - blend = BlenderToPipe(context, blend_state); - - vl_compositor_clear_layers(cstate); - vl_compositor_set_layer_blend(cstate, 0, blend, false); - vl_compositor_set_rgba_layer(cstate, compositor, 0, src_sv, - RectToPipe(source_rect, &src_rect), NULL, - ColorsToPipe(colors, flags, vlcolors)); - vl_compositor_set_layer_rotation(cstate, 0, flags & 3); - vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect)); - vl_compositor_render(cstate, compositor, dst_vlsurface->surface, &dst_vlsurface->dirty_area, false); - - context->delete_blend_state(context, blend); - mtx_unlock(&dst_vlsurface->device->mutex); - - return VDP_STATUS_OK; -} - -struct pipe_resource *vlVdpOutputSurfaceGallium(VdpOutputSurface surface) -{ - vlVdpOutputSurface *vlsurface; - - vlsurface = vlGetDataHTAB(surface); - if (!vlsurface || !vlsurface->surface) - return NULL; - - mtx_lock(&vlsurface->device->mutex); - vlsurface->device->context->flush(vlsurface->device->context, NULL, 0); - mtx_unlock(&vlsurface->device->mutex); - - return vlsurface->surface->texture; -} - -VdpStatus vlVdpOutputSurfaceDMABuf(VdpOutputSurface surface, - struct VdpSurfaceDMABufDesc *result) -{ - vlVdpOutputSurface *vlsurface; - struct pipe_screen *pscreen; - struct winsys_handle whandle; - - memset(result, 0, sizeof(*result)); - result->handle = -1; - - vlsurface = vlGetDataHTAB(surface); - if (!vlsurface || !vlsurface->surface) - return VDP_STATUS_INVALID_HANDLE; - - mtx_lock(&vlsurface->device->mutex); - vlsurface->device->context->flush(vlsurface->device->context, NULL, 0); - - memset(&whandle, 0, sizeof(struct winsys_handle)); - whandle.type = WINSYS_HANDLE_TYPE_FD; - - pscreen = vlsurface->surface->texture->screen; - if (!pscreen->resource_get_handle(pscreen, vlsurface->device->context, - vlsurface->surface->texture, &whandle, - PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE)) { - mtx_unlock(&vlsurface->device->mutex); - return VDP_STATUS_NO_IMPLEMENTATION; - } - - mtx_unlock(&vlsurface->device->mutex); - - result->handle = whandle.handle; - result->width = vlsurface->surface->width; - result->height = vlsurface->surface->height; - result->offset = whandle.offset; - result->stride = whandle.stride; - result->format = PipeToFormatRGBA(vlsurface->surface->format); - - return VDP_STATUS_OK; -} diff --git a/src/gallium/state_trackers/vdpau/preemption.c b/src/gallium/state_trackers/vdpau/preemption.c deleted file mode 100644 index 6d376acd339..00000000000 --- a/src/gallium/state_trackers/vdpau/preemption.c +++ /dev/null @@ -1,48 +0,0 @@ -/************************************************************************** - * - * Copyright 2010 Thomas Balling Sørensen. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include -#include "vdpau_private.h" - -/** - * A callback to notify the client application that a device's display has - * been preempted. - */ -void vlVdpPreemptionCallback(VdpDevice device, void *context) -{ - /* TODO: Implement preemption */ -} - -/** - * Configure the display preemption callback. - */ -VdpStatus vlVdpPreemptionCallbackRegister(VdpDevice device, - VdpPreemptionCallback callback, - void *context) -{ - return VDP_STATUS_OK; -} diff --git a/src/gallium/state_trackers/vdpau/presentation.c b/src/gallium/state_trackers/vdpau/presentation.c deleted file mode 100644 index 54f15ff34b1..00000000000 --- a/src/gallium/state_trackers/vdpau/presentation.c +++ /dev/null @@ -1,384 +0,0 @@ -/************************************************************************** - * - * Copyright 2010 Thomas Balling Sørensen. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include -#include - -#include "util/u_debug.h" -#include "util/u_memory.h" - -#include "vdpau_private.h" - -/** - * Create a VdpPresentationQueue. - */ -VdpStatus -vlVdpPresentationQueueCreate(VdpDevice device, - VdpPresentationQueueTarget presentation_queue_target, - VdpPresentationQueue *presentation_queue) -{ - vlVdpPresentationQueue *pq = NULL; - VdpStatus ret; - - if (!presentation_queue) - return VDP_STATUS_INVALID_POINTER; - - vlVdpDevice *dev = vlGetDataHTAB(device); - if (!dev) - return VDP_STATUS_INVALID_HANDLE; - - vlVdpPresentationQueueTarget *pqt = vlGetDataHTAB(presentation_queue_target); - if (!pqt) - return VDP_STATUS_INVALID_HANDLE; - - if (dev != pqt->device) - return VDP_STATUS_HANDLE_DEVICE_MISMATCH; - - pq = CALLOC(1, sizeof(vlVdpPresentationQueue)); - if (!pq) - return VDP_STATUS_RESOURCES; - - DeviceReference(&pq->device, dev); - pq->drawable = pqt->drawable; - - mtx_lock(&dev->mutex); - if (!vl_compositor_init_state(&pq->cstate, dev->context)) { - mtx_unlock(&dev->mutex); - ret = VDP_STATUS_ERROR; - goto no_compositor; - } - mtx_unlock(&dev->mutex); - - *presentation_queue = vlAddDataHTAB(pq); - if (*presentation_queue == 0) { - ret = VDP_STATUS_ERROR; - goto no_handle; - } - - return VDP_STATUS_OK; - -no_handle: -no_compositor: - DeviceReference(&pq->device, NULL); - FREE(pq); - return ret; -} - -/** - * Destroy a VdpPresentationQueue. - */ -VdpStatus -vlVdpPresentationQueueDestroy(VdpPresentationQueue presentation_queue) -{ - vlVdpPresentationQueue *pq; - - pq = vlGetDataHTAB(presentation_queue); - if (!pq) - return VDP_STATUS_INVALID_HANDLE; - - mtx_lock(&pq->device->mutex); - vl_compositor_cleanup_state(&pq->cstate); - mtx_unlock(&pq->device->mutex); - - vlRemoveDataHTAB(presentation_queue); - DeviceReference(&pq->device, NULL); - FREE(pq); - - return VDP_STATUS_OK; -} - -/** - * Configure the background color setting. - */ -VdpStatus -vlVdpPresentationQueueSetBackgroundColor(VdpPresentationQueue presentation_queue, - VdpColor *const background_color) -{ - vlVdpPresentationQueue *pq; - union pipe_color_union color; - - if (!background_color) - return VDP_STATUS_INVALID_POINTER; - - pq = vlGetDataHTAB(presentation_queue); - if (!pq) - return VDP_STATUS_INVALID_HANDLE; - - color.f[0] = background_color->red; - color.f[1] = background_color->green; - color.f[2] = background_color->blue; - color.f[3] = background_color->alpha; - - mtx_lock(&pq->device->mutex); - vl_compositor_set_clear_color(&pq->cstate, &color); - mtx_unlock(&pq->device->mutex); - - return VDP_STATUS_OK; -} - -/** - * Retrieve the current background color setting. - */ -VdpStatus -vlVdpPresentationQueueGetBackgroundColor(VdpPresentationQueue presentation_queue, - VdpColor *const background_color) -{ - vlVdpPresentationQueue *pq; - union pipe_color_union color; - - if (!background_color) - return VDP_STATUS_INVALID_POINTER; - - pq = vlGetDataHTAB(presentation_queue); - if (!pq) - return VDP_STATUS_INVALID_HANDLE; - - mtx_lock(&pq->device->mutex); - vl_compositor_get_clear_color(&pq->cstate, &color); - mtx_unlock(&pq->device->mutex); - - background_color->red = color.f[0]; - background_color->green = color.f[1]; - background_color->blue = color.f[2]; - background_color->alpha = color.f[3]; - - return VDP_STATUS_OK; -} - -/** - * Retrieve the presentation queue's "current" time. - */ -VdpStatus -vlVdpPresentationQueueGetTime(VdpPresentationQueue presentation_queue, - VdpTime *current_time) -{ - vlVdpPresentationQueue *pq; - - if (!current_time) - return VDP_STATUS_INVALID_POINTER; - - pq = vlGetDataHTAB(presentation_queue); - if (!pq) - return VDP_STATUS_INVALID_HANDLE; - - mtx_lock(&pq->device->mutex); - *current_time = pq->device->vscreen->get_timestamp(pq->device->vscreen, - (void *)pq->drawable); - mtx_unlock(&pq->device->mutex); - - return VDP_STATUS_OK; -} - -/** - * Enter a surface into the presentation queue. - */ -VdpStatus -vlVdpPresentationQueueDisplay(VdpPresentationQueue presentation_queue, - VdpOutputSurface surface, - uint32_t clip_width, - uint32_t clip_height, - VdpTime earliest_presentation_time) -{ - static int dump_window = -1; - - vlVdpPresentationQueue *pq; - vlVdpOutputSurface *surf; - - struct pipe_context *pipe; - struct pipe_resource *tex; - struct pipe_surface surf_templ, *surf_draw = NULL; - struct u_rect src_rect, dst_clip, *dirty_area; - - struct vl_compositor *compositor; - struct vl_compositor_state *cstate; - struct vl_screen *vscreen; - - pq = vlGetDataHTAB(presentation_queue); - if (!pq) - return VDP_STATUS_INVALID_HANDLE; - - surf = vlGetDataHTAB(surface); - if (!surf) - return VDP_STATUS_INVALID_HANDLE; - - pipe = pq->device->context; - compositor = &pq->device->compositor; - cstate = &pq->cstate; - vscreen = pq->device->vscreen; - - mtx_lock(&pq->device->mutex); - if (vscreen->set_back_texture_from_output && surf->send_to_X) - vscreen->set_back_texture_from_output(vscreen, surf->surface->texture, clip_width, clip_height); - tex = vscreen->texture_from_drawable(vscreen, (void *)pq->drawable); - if (!tex) { - mtx_unlock(&pq->device->mutex); - return VDP_STATUS_INVALID_HANDLE; - } - - if (!vscreen->set_back_texture_from_output || !surf->send_to_X) { - dirty_area = vscreen->get_dirty_area(vscreen); - - memset(&surf_templ, 0, sizeof(surf_templ)); - surf_templ.format = tex->format; - surf_draw = pipe->create_surface(pipe, tex, &surf_templ); - - dst_clip.x0 = 0; - dst_clip.y0 = 0; - dst_clip.x1 = clip_width ? clip_width : surf_draw->width; - dst_clip.y1 = clip_height ? clip_height : surf_draw->height; - - src_rect.x0 = 0; - src_rect.y0 = 0; - src_rect.x1 = surf_draw->width; - src_rect.y1 = surf_draw->height; - - vl_compositor_clear_layers(cstate); - vl_compositor_set_rgba_layer(cstate, compositor, 0, surf->sampler_view, &src_rect, NULL, NULL); - vl_compositor_set_dst_clip(cstate, &dst_clip); - vl_compositor_render(cstate, compositor, surf_draw, dirty_area, true); - } - - vscreen->set_next_timestamp(vscreen, earliest_presentation_time); - - // flush before calling flush_frontbuffer so that rendering is flushed - // to back buffer so the texture can be copied in flush_frontbuffer - pipe->screen->fence_reference(pipe->screen, &surf->fence, NULL); - pipe->flush(pipe, &surf->fence, 0); - pipe->screen->flush_frontbuffer(pipe->screen, tex, 0, 0, - vscreen->get_private(vscreen), NULL); - - pq->last_surf = surf; - - if (dump_window == -1) { - dump_window = debug_get_num_option("VDPAU_DUMP", 0); - } - - if (dump_window) { - static unsigned int framenum = 0; - char cmd[256]; - - if (framenum) { - sprintf(cmd, "xwd -id %d -silent -out vdpau_frame_%08d.xwd", (int)pq->drawable, framenum); - if (system(cmd) != 0) - VDPAU_MSG(VDPAU_ERR, "[VDPAU] Dumping surface %d failed.\n", surface); - } - framenum++; - } - - if (!vscreen->set_back_texture_from_output || !surf->send_to_X) { - pipe_resource_reference(&tex, NULL); - pipe_surface_reference(&surf_draw, NULL); - } - mtx_unlock(&pq->device->mutex); - - return VDP_STATUS_OK; -} - -/** - * Wait for a surface to finish being displayed. - */ -VdpStatus -vlVdpPresentationQueueBlockUntilSurfaceIdle(VdpPresentationQueue presentation_queue, - VdpOutputSurface surface, - VdpTime *first_presentation_time) -{ - vlVdpPresentationQueue *pq; - vlVdpOutputSurface *surf; - struct pipe_screen *screen; - - if (!first_presentation_time) - return VDP_STATUS_INVALID_POINTER; - - pq = vlGetDataHTAB(presentation_queue); - if (!pq) - return VDP_STATUS_INVALID_HANDLE; - - surf = vlGetDataHTAB(surface); - if (!surf) - return VDP_STATUS_INVALID_HANDLE; - - mtx_lock(&pq->device->mutex); - if (surf->fence) { - screen = pq->device->vscreen->pscreen; - screen->fence_finish(screen, NULL, surf->fence, PIPE_TIMEOUT_INFINITE); - screen->fence_reference(screen, &surf->fence, NULL); - } - mtx_unlock(&pq->device->mutex); - - return vlVdpPresentationQueueGetTime(presentation_queue, first_presentation_time); -} - -/** - * Poll the current queue status of a surface. - */ -VdpStatus -vlVdpPresentationQueueQuerySurfaceStatus(VdpPresentationQueue presentation_queue, - VdpOutputSurface surface, - VdpPresentationQueueStatus *status, - VdpTime *first_presentation_time) -{ - vlVdpPresentationQueue *pq; - vlVdpOutputSurface *surf; - struct pipe_screen *screen; - - if (!(status && first_presentation_time)) - return VDP_STATUS_INVALID_POINTER; - - pq = vlGetDataHTAB(presentation_queue); - if (!pq) - return VDP_STATUS_INVALID_HANDLE; - - surf = vlGetDataHTAB(surface); - if (!surf) - return VDP_STATUS_INVALID_HANDLE; - - *first_presentation_time = 0; - - if (!surf->fence) { - if (pq->last_surf == surf) - *status = VDP_PRESENTATION_QUEUE_STATUS_VISIBLE; - else - *status = VDP_PRESENTATION_QUEUE_STATUS_IDLE; - } else { - mtx_lock(&pq->device->mutex); - screen = pq->device->vscreen->pscreen; - if (screen->fence_finish(screen, NULL, surf->fence, 0)) { - screen->fence_reference(screen, &surf->fence, NULL); - *status = VDP_PRESENTATION_QUEUE_STATUS_VISIBLE; - mtx_unlock(&pq->device->mutex); - - // We actually need to query the timestamp of the last VSYNC event from the hardware - vlVdpPresentationQueueGetTime(presentation_queue, first_presentation_time); - *first_presentation_time += 1; - } else { - *status = VDP_PRESENTATION_QUEUE_STATUS_QUEUED; - mtx_unlock(&pq->device->mutex); - } - } - - return VDP_STATUS_OK; -} diff --git a/src/gallium/state_trackers/vdpau/query.c b/src/gallium/state_trackers/vdpau/query.c deleted file mode 100644 index 701d9f220c4..00000000000 --- a/src/gallium/state_trackers/vdpau/query.c +++ /dev/null @@ -1,622 +0,0 @@ -/************************************************************************** - * - * Copyright 2010 Younes Manton. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include -#include - -#include "vdpau_private.h" -#include "pipe/p_screen.h" -#include "pipe/p_defines.h" -#include "util/u_debug.h" - -/** - * Retrieve the VDPAU version implemented by the backend. - */ -VdpStatus -vlVdpGetApiVersion(uint32_t *api_version) -{ - if (!api_version) - return VDP_STATUS_INVALID_POINTER; - - *api_version = 1; - return VDP_STATUS_OK; -} - -/** - * Retrieve an implementation-specific string description of the implementation. - * This typically includes detailed version information. - */ -VdpStatus -vlVdpGetInformationString(char const **information_string) -{ - if (!information_string) - return VDP_STATUS_INVALID_POINTER; - - *information_string = INFORMATION_STRING; - return VDP_STATUS_OK; -} - -/** - * Query the implementation's VdpVideoSurface capabilities. - */ -VdpStatus -vlVdpVideoSurfaceQueryCapabilities(VdpDevice device, VdpChromaType surface_chroma_type, - VdpBool *is_supported, uint32_t *max_width, uint32_t *max_height) -{ - vlVdpDevice *dev; - struct pipe_screen *pscreen; - uint32_t max_2d_texture_size; - - if (!(is_supported && max_width && max_height)) - return VDP_STATUS_INVALID_POINTER; - - dev = vlGetDataHTAB(device); - if (!dev) - return VDP_STATUS_INVALID_HANDLE; - - pscreen = dev->vscreen->pscreen; - if (!pscreen) - return VDP_STATUS_RESOURCES; - - mtx_lock(&dev->mutex); - - /* XXX: Current limits */ - *is_supported = true; - max_2d_texture_size = pscreen->get_param(pscreen, PIPE_CAP_MAX_TEXTURE_2D_SIZE); - mtx_unlock(&dev->mutex); - if (!max_2d_texture_size) - return VDP_STATUS_RESOURCES; - - *max_width = *max_height = max_2d_texture_size; - - return VDP_STATUS_OK; -} - -/** - * Query the implementation's VdpVideoSurface GetBits/PutBits capabilities. - */ -VdpStatus -vlVdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities(VdpDevice device, VdpChromaType surface_chroma_type, - VdpYCbCrFormat bits_ycbcr_format, - VdpBool *is_supported) -{ - vlVdpDevice *dev; - struct pipe_screen *pscreen; - - if (!is_supported) - return VDP_STATUS_INVALID_POINTER; - - dev = vlGetDataHTAB(device); - if (!dev) - return VDP_STATUS_INVALID_HANDLE; - - pscreen = dev->vscreen->pscreen; - if (!pscreen) - return VDP_STATUS_RESOURCES; - - mtx_lock(&dev->mutex); - - switch(bits_ycbcr_format) { - case VDP_YCBCR_FORMAT_NV12: - *is_supported = surface_chroma_type == VDP_CHROMA_TYPE_420; - break; - - case VDP_YCBCR_FORMAT_YV12: - *is_supported = surface_chroma_type == VDP_CHROMA_TYPE_420; - - /* We can convert YV12 to NV12 on the fly! */ - if (*is_supported && - pscreen->is_video_format_supported(pscreen, - PIPE_FORMAT_NV12, - PIPE_VIDEO_PROFILE_UNKNOWN, - PIPE_VIDEO_ENTRYPOINT_BITSTREAM)) { - mtx_unlock(&dev->mutex); - return VDP_STATUS_OK; - } - break; - - case VDP_YCBCR_FORMAT_UYVY: - case VDP_YCBCR_FORMAT_YUYV: - *is_supported = surface_chroma_type == VDP_CHROMA_TYPE_422; - break; - - case VDP_YCBCR_FORMAT_Y8U8V8A8: - case VDP_YCBCR_FORMAT_V8U8Y8A8: - *is_supported = surface_chroma_type == VDP_CHROMA_TYPE_444; - break; - - default: - *is_supported = false; - break; - } - - if (*is_supported && - !pscreen->is_video_format_supported(pscreen, - FormatYCBCRToPipe(bits_ycbcr_format), - PIPE_VIDEO_PROFILE_UNKNOWN, - PIPE_VIDEO_ENTRYPOINT_BITSTREAM)) { - *is_supported = false; - } - mtx_unlock(&dev->mutex); - - return VDP_STATUS_OK; -} - -/** - * Query the implementation's VdpDecoder capabilities. - */ -VdpStatus -vlVdpDecoderQueryCapabilities(VdpDevice device, VdpDecoderProfile profile, - VdpBool *is_supported, uint32_t *max_level, uint32_t *max_macroblocks, - uint32_t *max_width, uint32_t *max_height) -{ - vlVdpDevice *dev; - struct pipe_screen *pscreen; - enum pipe_video_profile p_profile; - - if (!(is_supported && max_level && max_macroblocks && max_width && max_height)) - return VDP_STATUS_INVALID_POINTER; - - dev = vlGetDataHTAB(device); - if (!dev) - return VDP_STATUS_INVALID_HANDLE; - - pscreen = dev->vscreen->pscreen; - if (!pscreen) - return VDP_STATUS_RESOURCES; - - p_profile = ProfileToPipe(profile); - if (p_profile == PIPE_VIDEO_PROFILE_UNKNOWN) { - *is_supported = false; - return VDP_STATUS_OK; - } - - mtx_lock(&dev->mutex); - *is_supported = pscreen->get_video_param(pscreen, p_profile, PIPE_VIDEO_ENTRYPOINT_BITSTREAM, - PIPE_VIDEO_CAP_SUPPORTED); - if (*is_supported) { - *max_width = pscreen->get_video_param(pscreen, p_profile, PIPE_VIDEO_ENTRYPOINT_BITSTREAM, - PIPE_VIDEO_CAP_MAX_WIDTH); - *max_height = pscreen->get_video_param(pscreen, p_profile, PIPE_VIDEO_ENTRYPOINT_BITSTREAM, - PIPE_VIDEO_CAP_MAX_HEIGHT); - *max_level = pscreen->get_video_param(pscreen, p_profile, PIPE_VIDEO_ENTRYPOINT_BITSTREAM, - PIPE_VIDEO_CAP_MAX_LEVEL); - *max_macroblocks = (*max_width/16)*(*max_height/16); - } else { - *max_width = 0; - *max_height = 0; - *max_level = 0; - *max_macroblocks = 0; - } - mtx_unlock(&dev->mutex); - - return VDP_STATUS_OK; -} - -/** - * Query the implementation's VdpOutputSurface capabilities. - */ -VdpStatus -vlVdpOutputSurfaceQueryCapabilities(VdpDevice device, VdpRGBAFormat surface_rgba_format, - VdpBool *is_supported, uint32_t *max_width, uint32_t *max_height) -{ - vlVdpDevice *dev; - struct pipe_screen *pscreen; - enum pipe_format format; - - dev = vlGetDataHTAB(device); - if (!dev) - return VDP_STATUS_INVALID_HANDLE; - - pscreen = dev->vscreen->pscreen; - if (!pscreen) - return VDP_STATUS_RESOURCES; - - format = VdpFormatRGBAToPipe(surface_rgba_format); - if (format == PIPE_FORMAT_NONE || format == PIPE_FORMAT_A8_UNORM) - return VDP_STATUS_INVALID_RGBA_FORMAT; - - if (!(is_supported && max_width && max_height)) - return VDP_STATUS_INVALID_POINTER; - - mtx_lock(&dev->mutex); - *is_supported = pscreen->is_format_supported - ( - pscreen, format, PIPE_TEXTURE_2D, 1, 1, - PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET - ); - if (*is_supported) { - uint32_t max_2d_texture_size = pscreen->get_param( - pscreen, PIPE_CAP_MAX_TEXTURE_2D_SIZE); - - if (!max_2d_texture_size) { - mtx_unlock(&dev->mutex); - return VDP_STATUS_ERROR; - } - - *max_width = *max_height = max_2d_texture_size; - } else { - *max_width = 0; - *max_height = 0; - } - mtx_unlock(&dev->mutex); - - return VDP_STATUS_OK; -} - -/** - * Query the implementation's capability to perform a PutBits operation using - * application data matching the surface's format. - */ -VdpStatus -vlVdpOutputSurfaceQueryGetPutBitsNativeCapabilities(VdpDevice device, VdpRGBAFormat surface_rgba_format, - VdpBool *is_supported) -{ - vlVdpDevice *dev; - struct pipe_screen *pscreen; - enum pipe_format format; - - dev = vlGetDataHTAB(device); - if (!dev) - return VDP_STATUS_INVALID_HANDLE; - - pscreen = dev->vscreen->pscreen; - if (!pscreen) - return VDP_STATUS_ERROR; - - format = VdpFormatRGBAToPipe(surface_rgba_format); - if (format == PIPE_FORMAT_NONE || format == PIPE_FORMAT_A8_UNORM) - return VDP_STATUS_INVALID_RGBA_FORMAT; - - if (!is_supported) - return VDP_STATUS_INVALID_POINTER; - - mtx_lock(&dev->mutex); - *is_supported = pscreen->is_format_supported - ( - pscreen, format, PIPE_TEXTURE_2D, 1, 1, - PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET - ); - mtx_unlock(&dev->mutex); - - return VDP_STATUS_OK; -} - -/** - * Query the implementation's capability to perform a PutBits operation using - * application data in a specific indexed format. - */ -VdpStatus -vlVdpOutputSurfaceQueryPutBitsIndexedCapabilities(VdpDevice device, - VdpRGBAFormat surface_rgba_format, - VdpIndexedFormat bits_indexed_format, - VdpColorTableFormat color_table_format, - VdpBool *is_supported) -{ - vlVdpDevice *dev; - struct pipe_screen *pscreen; - enum pipe_format rgba_format, index_format, colortbl_format; - - dev = vlGetDataHTAB(device); - if (!dev) - return VDP_STATUS_INVALID_HANDLE; - - pscreen = dev->vscreen->pscreen; - if (!pscreen) - return VDP_STATUS_ERROR; - - rgba_format = VdpFormatRGBAToPipe(surface_rgba_format); - if (rgba_format == PIPE_FORMAT_NONE || rgba_format == PIPE_FORMAT_A8_UNORM) - return VDP_STATUS_INVALID_RGBA_FORMAT; - - index_format = FormatIndexedToPipe(bits_indexed_format); - if (index_format == PIPE_FORMAT_NONE) - return VDP_STATUS_INVALID_INDEXED_FORMAT; - - colortbl_format = FormatColorTableToPipe(color_table_format); - if (colortbl_format == PIPE_FORMAT_NONE) - return VDP_STATUS_INVALID_COLOR_TABLE_FORMAT; - - if (!is_supported) - return VDP_STATUS_INVALID_POINTER; - - mtx_lock(&dev->mutex); - *is_supported = pscreen->is_format_supported - ( - pscreen, rgba_format, PIPE_TEXTURE_2D, 1, 1, - PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET - ); - - *is_supported &= pscreen->is_format_supported - ( - pscreen, index_format, PIPE_TEXTURE_2D, 1, 1, - PIPE_BIND_SAMPLER_VIEW - ); - - *is_supported &= pscreen->is_format_supported - ( - pscreen, colortbl_format, PIPE_TEXTURE_1D, 1, 1, - PIPE_BIND_SAMPLER_VIEW - ); - mtx_unlock(&dev->mutex); - - return VDP_STATUS_OK; -} - -/** - * Query the implementation's capability to perform a PutBits operation using - * application data in a specific YCbCr/YUB format. - */ -VdpStatus -vlVdpOutputSurfaceQueryPutBitsYCbCrCapabilities(VdpDevice device, VdpRGBAFormat surface_rgba_format, - VdpYCbCrFormat bits_ycbcr_format, - VdpBool *is_supported) -{ - vlVdpDevice *dev; - struct pipe_screen *pscreen; - enum pipe_format rgba_format, ycbcr_format; - - dev = vlGetDataHTAB(device); - if (!dev) - return VDP_STATUS_INVALID_HANDLE; - - pscreen = dev->vscreen->pscreen; - if (!pscreen) - return VDP_STATUS_ERROR; - - rgba_format = VdpFormatRGBAToPipe(surface_rgba_format); - if (rgba_format == PIPE_FORMAT_NONE || rgba_format == PIPE_FORMAT_A8_UNORM) - return VDP_STATUS_INVALID_RGBA_FORMAT; - - ycbcr_format = FormatYCBCRToPipe(bits_ycbcr_format); - if (ycbcr_format == PIPE_FORMAT_NONE) - return VDP_STATUS_INVALID_INDEXED_FORMAT; - - if (!is_supported) - return VDP_STATUS_INVALID_POINTER; - - mtx_lock(&dev->mutex); - *is_supported = pscreen->is_format_supported - ( - pscreen, rgba_format, PIPE_TEXTURE_2D, 1, 1, - PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET - ); - - *is_supported &= pscreen->is_video_format_supported - ( - pscreen, ycbcr_format, - PIPE_VIDEO_PROFILE_UNKNOWN, - PIPE_VIDEO_ENTRYPOINT_BITSTREAM - ); - mtx_unlock(&dev->mutex); - - return VDP_STATUS_OK; -} - -/** - * Query the implementation's VdpBitmapSurface capabilities. - */ -VdpStatus -vlVdpBitmapSurfaceQueryCapabilities(VdpDevice device, VdpRGBAFormat surface_rgba_format, - VdpBool *is_supported, uint32_t *max_width, uint32_t *max_height) -{ - vlVdpDevice *dev; - struct pipe_screen *pscreen; - enum pipe_format format; - - dev = vlGetDataHTAB(device); - if (!dev) - return VDP_STATUS_INVALID_HANDLE; - - pscreen = dev->vscreen->pscreen; - if (!pscreen) - return VDP_STATUS_RESOURCES; - - format = VdpFormatRGBAToPipe(surface_rgba_format); - if (format == PIPE_FORMAT_NONE) - return VDP_STATUS_INVALID_RGBA_FORMAT; - - if (!(is_supported && max_width && max_height)) - return VDP_STATUS_INVALID_POINTER; - - mtx_lock(&dev->mutex); - *is_supported = pscreen->is_format_supported - ( - pscreen, format, PIPE_TEXTURE_2D, 1, 1, - PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET - ); - if (*is_supported) { - uint32_t max_2d_texture_size = pscreen->get_param( - pscreen, PIPE_CAP_MAX_TEXTURE_2D_SIZE); - - if (!max_2d_texture_size) { - mtx_unlock(&dev->mutex); - return VDP_STATUS_ERROR; - } - - *max_width = *max_height = max_2d_texture_size; - } else { - *max_width = 0; - *max_height = 0; - } - mtx_unlock(&dev->mutex); - - return VDP_STATUS_OK; -} - -/** - * Query the implementation's support for a specific feature. - */ -VdpStatus -vlVdpVideoMixerQueryFeatureSupport(VdpDevice device, VdpVideoMixerFeature feature, - VdpBool *is_supported) -{ - if (!is_supported) - return VDP_STATUS_INVALID_POINTER; - - switch (feature) { - case VDP_VIDEO_MIXER_FEATURE_SHARPNESS: - case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION: - case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL: - case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY: - case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1: - *is_supported = VDP_TRUE; - break; - default: - *is_supported = VDP_FALSE; - break; - } - return VDP_STATUS_OK; -} - -/** - * Query the implementation's support for a specific parameter. - */ -VdpStatus -vlVdpVideoMixerQueryParameterSupport(VdpDevice device, VdpVideoMixerParameter parameter, - VdpBool *is_supported) -{ - if (!is_supported) - return VDP_STATUS_INVALID_POINTER; - - switch (parameter) { - case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH: - case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT: - case VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE: - case VDP_VIDEO_MIXER_PARAMETER_LAYERS: - *is_supported = VDP_TRUE; - break; - default: - *is_supported = VDP_FALSE; - break; - } - return VDP_STATUS_OK; -} - -/** - * Query the implementation's supported for a specific parameter. - */ -VdpStatus -vlVdpVideoMixerQueryParameterValueRange(VdpDevice device, VdpVideoMixerParameter parameter, - void *min_value, void *max_value) -{ - vlVdpDevice *dev = vlGetDataHTAB(device); - struct pipe_screen *screen; - - if (!dev) - return VDP_STATUS_INVALID_HANDLE; - if (!(min_value && max_value)) - return VDP_STATUS_INVALID_POINTER; - - mtx_lock(&dev->mutex); - screen = dev->vscreen->pscreen; - switch (parameter) { - case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH: - *(uint32_t*)min_value = 48; - *(uint32_t*)max_value = screen->get_video_param(screen, PIPE_VIDEO_PROFILE_UNKNOWN, - PIPE_VIDEO_ENTRYPOINT_BITSTREAM, - PIPE_VIDEO_CAP_MAX_WIDTH); - break; - case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT: - *(uint32_t*)min_value = 48; - *(uint32_t*)max_value = screen->get_video_param(screen, PIPE_VIDEO_PROFILE_UNKNOWN, - PIPE_VIDEO_ENTRYPOINT_BITSTREAM, - PIPE_VIDEO_CAP_MAX_HEIGHT); - break; - - case VDP_VIDEO_MIXER_PARAMETER_LAYERS: - *(uint32_t*)min_value = 0; - *(uint32_t*)max_value = 4; - break; - - case VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE: - default: - mtx_unlock(&dev->mutex); - return VDP_STATUS_INVALID_VIDEO_MIXER_PARAMETER; - } - mtx_unlock(&dev->mutex); - return VDP_STATUS_OK; -} - -/** - * Query the implementation's support for a specific attribute. - */ -VdpStatus -vlVdpVideoMixerQueryAttributeSupport(VdpDevice device, VdpVideoMixerAttribute attribute, - VdpBool *is_supported) -{ - if (!is_supported) - return VDP_STATUS_INVALID_POINTER; - - switch (attribute) { - case VDP_VIDEO_MIXER_ATTRIBUTE_BACKGROUND_COLOR: - case VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX: - case VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL: - case VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL: - case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MIN_LUMA: - case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MAX_LUMA: - case VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE: - *is_supported = VDP_TRUE; - break; - default: - *is_supported = VDP_FALSE; - } - return VDP_STATUS_OK; -} - -/** - * Query the implementation's supported for a specific attribute. - */ -VdpStatus -vlVdpVideoMixerQueryAttributeValueRange(VdpDevice device, VdpVideoMixerAttribute attribute, - void *min_value, void *max_value) -{ - if (!(min_value && max_value)) - return VDP_STATUS_INVALID_POINTER; - - switch (attribute) { - case VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL: - case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MIN_LUMA: - case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MAX_LUMA: - *(float*)min_value = 0.0f; - *(float*)max_value = 1.0f; - break; - case VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL: - *(float*)min_value = -1.0f; - *(float*)max_value = 1.0f; - break; - case VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE: - *(uint8_t*)min_value = 0; - *(uint8_t*)max_value = 1; - break; - case VDP_VIDEO_MIXER_ATTRIBUTE_BACKGROUND_COLOR: - case VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX: - default: - return VDP_STATUS_INVALID_VIDEO_MIXER_ATTRIBUTE; - } - return VDP_STATUS_OK; -} diff --git a/src/gallium/state_trackers/vdpau/surface.c b/src/gallium/state_trackers/vdpau/surface.c deleted file mode 100644 index 4158e6bcfe6..00000000000 --- a/src/gallium/state_trackers/vdpau/surface.c +++ /dev/null @@ -1,554 +0,0 @@ -/************************************************************************** - * - * Copyright 2010 Thomas Balling Sørensen. - * Copyright 2011 Christian König. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include - -#include "pipe/p_state.h" - -#include "util/u_memory.h" -#include "util/u_debug.h" -#include "util/u_rect.h" -#include "util/u_surface.h" -#include "util/u_video.h" -#include "vl/vl_defines.h" - -#include "state_tracker/drm_driver.h" - -#include "vdpau_private.h" - -enum getbits_conversion { - CONVERSION_NONE, - CONVERSION_NV12_TO_YV12, - CONVERSION_YV12_TO_NV12, - CONVERSION_SWAP_YUYV_UYVY, -}; - -/** - * Create a VdpVideoSurface. - */ -VdpStatus -vlVdpVideoSurfaceCreate(VdpDevice device, VdpChromaType chroma_type, - uint32_t width, uint32_t height, - VdpVideoSurface *surface) -{ - struct pipe_context *pipe; - vlVdpSurface *p_surf; - VdpStatus ret; - - if (!(width && height)) { - ret = VDP_STATUS_INVALID_SIZE; - goto inv_size; - } - - p_surf = CALLOC(1, sizeof(vlVdpSurface)); - if (!p_surf) { - ret = VDP_STATUS_RESOURCES; - goto no_res; - } - - vlVdpDevice *dev = vlGetDataHTAB(device); - if (!dev) { - ret = VDP_STATUS_INVALID_HANDLE; - goto inv_device; - } - - DeviceReference(&p_surf->device, dev); - pipe = dev->context; - - mtx_lock(&dev->mutex); - memset(&p_surf->templat, 0, sizeof(p_surf->templat)); - /* TODO: buffer_format should be selected to match chroma_type */ - p_surf->templat.buffer_format = pipe->screen->get_video_param - ( - pipe->screen, - PIPE_VIDEO_PROFILE_UNKNOWN, - PIPE_VIDEO_ENTRYPOINT_BITSTREAM, - PIPE_VIDEO_CAP_PREFERED_FORMAT - ); - p_surf->templat.width = width; - p_surf->templat.height = height; - p_surf->templat.interlaced = pipe->screen->get_video_param - ( - pipe->screen, - PIPE_VIDEO_PROFILE_UNKNOWN, - PIPE_VIDEO_ENTRYPOINT_BITSTREAM, - PIPE_VIDEO_CAP_PREFERS_INTERLACED - ); - if (p_surf->templat.buffer_format != PIPE_FORMAT_NONE) - p_surf->video_buffer = pipe->create_video_buffer(pipe, &p_surf->templat); - - /* do not mandate early allocation of a video buffer */ - vlVdpVideoSurfaceClear(p_surf); - mtx_unlock(&dev->mutex); - - *surface = vlAddDataHTAB(p_surf); - if (*surface == 0) { - ret = VDP_STATUS_ERROR; - goto no_handle; - } - - return VDP_STATUS_OK; - -no_handle: - p_surf->video_buffer->destroy(p_surf->video_buffer); - -inv_device: - DeviceReference(&p_surf->device, NULL); - FREE(p_surf); - -no_res: -inv_size: - return ret; -} - -/** - * Destroy a VdpVideoSurface. - */ -VdpStatus -vlVdpVideoSurfaceDestroy(VdpVideoSurface surface) -{ - vlVdpSurface *p_surf; - - p_surf = (vlVdpSurface *)vlGetDataHTAB((vlHandle)surface); - if (!p_surf) - return VDP_STATUS_INVALID_HANDLE; - - mtx_lock(&p_surf->device->mutex); - if (p_surf->video_buffer) - p_surf->video_buffer->destroy(p_surf->video_buffer); - mtx_unlock(&p_surf->device->mutex); - - vlRemoveDataHTAB(surface); - DeviceReference(&p_surf->device, NULL); - FREE(p_surf); - - return VDP_STATUS_OK; -} - -/** - * Retrieve the parameters used to create a VdpVideoSurface. - */ -VdpStatus -vlVdpVideoSurfaceGetParameters(VdpVideoSurface surface, - VdpChromaType *chroma_type, - uint32_t *width, uint32_t *height) -{ - if (!(width && height && chroma_type)) - return VDP_STATUS_INVALID_POINTER; - - vlVdpSurface *p_surf = vlGetDataHTAB(surface); - if (!p_surf) - return VDP_STATUS_INVALID_HANDLE; - - if (p_surf->video_buffer) { - *width = p_surf->video_buffer->width; - *height = p_surf->video_buffer->height; - *chroma_type = PipeToChroma(pipe_format_to_chroma_format(p_surf->video_buffer->buffer_format)); - } else { - *width = p_surf->templat.width; - *height = p_surf->templat.height; - *chroma_type = PipeToChroma(pipe_format_to_chroma_format(p_surf->templat.buffer_format)); - } - - return VDP_STATUS_OK; -} - -static void -vlVdpVideoSurfaceSize(vlVdpSurface *p_surf, int component, - unsigned *width, unsigned *height) -{ - *width = p_surf->templat.width; - *height = p_surf->templat.height; - - vl_video_buffer_adjust_size(width, height, component, - pipe_format_to_chroma_format(p_surf->templat.buffer_format), - p_surf->templat.interlaced); -} - -/** - * Copy image data from a VdpVideoSurface to application memory in a specified - * YCbCr format. - */ -VdpStatus -vlVdpVideoSurfaceGetBitsYCbCr(VdpVideoSurface surface, - VdpYCbCrFormat destination_ycbcr_format, - void *const *destination_data, - uint32_t const *destination_pitches) -{ - vlVdpSurface *vlsurface; - struct pipe_context *pipe; - enum pipe_format format, buffer_format; - struct pipe_sampler_view **sampler_views; - enum getbits_conversion conversion = CONVERSION_NONE; - unsigned i, j; - - vlsurface = vlGetDataHTAB(surface); - if (!vlsurface) - return VDP_STATUS_INVALID_HANDLE; - - pipe = vlsurface->device->context; - if (!pipe) - return VDP_STATUS_INVALID_HANDLE; - - if (!destination_data || !destination_pitches) - return VDP_STATUS_INVALID_POINTER; - - format = FormatYCBCRToPipe(destination_ycbcr_format); - if (format == PIPE_FORMAT_NONE) - return VDP_STATUS_INVALID_Y_CB_CR_FORMAT; - - if (vlsurface->video_buffer == NULL) - return VDP_STATUS_INVALID_VALUE; - - buffer_format = vlsurface->video_buffer->buffer_format; - if (format != buffer_format) { - if (format == PIPE_FORMAT_YV12 && buffer_format == PIPE_FORMAT_NV12) - conversion = CONVERSION_NV12_TO_YV12; - else if (format == PIPE_FORMAT_NV12 && buffer_format == PIPE_FORMAT_YV12) - conversion = CONVERSION_YV12_TO_NV12; - else if ((format == PIPE_FORMAT_YUYV && buffer_format == PIPE_FORMAT_UYVY) || - (format == PIPE_FORMAT_UYVY && buffer_format == PIPE_FORMAT_YUYV)) - conversion = CONVERSION_SWAP_YUYV_UYVY; - else - return VDP_STATUS_NO_IMPLEMENTATION; - } - - mtx_lock(&vlsurface->device->mutex); - sampler_views = vlsurface->video_buffer->get_sampler_view_planes(vlsurface->video_buffer); - if (!sampler_views) { - mtx_unlock(&vlsurface->device->mutex); - return VDP_STATUS_RESOURCES; - } - - for (i = 0; i < 3; ++i) { - unsigned width, height; - struct pipe_sampler_view *sv = sampler_views[i]; - if (!sv) continue; - - vlVdpVideoSurfaceSize(vlsurface, i, &width, &height); - - for (j = 0; j < sv->texture->array_size; ++j) { - struct pipe_box box = { - 0, 0, j, - width, height, 1 - }; - struct pipe_transfer *transfer; - uint8_t *map; - - map = pipe->transfer_map(pipe, sv->texture, 0, - PIPE_TRANSFER_READ, &box, &transfer); - if (!map) { - mtx_unlock(&vlsurface->device->mutex); - return VDP_STATUS_RESOURCES; - } - - if (conversion == CONVERSION_NV12_TO_YV12 && i == 1) { - u_copy_nv12_to_yv12(destination_data, destination_pitches, - i, j, transfer->stride, sv->texture->array_size, - map, box.width, box.height); - } else if (conversion == CONVERSION_YV12_TO_NV12 && i > 0) { - u_copy_yv12_to_nv12(destination_data, destination_pitches, - i, j, transfer->stride, sv->texture->array_size, - map, box.width, box.height); - } else if (conversion == CONVERSION_SWAP_YUYV_UYVY) { - u_copy_swap422_packed(destination_data, destination_pitches, - i, j, transfer->stride, sv->texture->array_size, - map, box.width, box.height); - } else { - util_copy_rect(destination_data[i] + destination_pitches[i] * j, sv->texture->format, - destination_pitches[i] * sv->texture->array_size, 0, 0, - box.width, box.height, map, transfer->stride, 0, 0); - } - - pipe_transfer_unmap(pipe, transfer); - } - } - mtx_unlock(&vlsurface->device->mutex); - - return VDP_STATUS_OK; -} - -/** - * Copy image data from application memory in a specific YCbCr format to - * a VdpVideoSurface. - */ -VdpStatus -vlVdpVideoSurfacePutBitsYCbCr(VdpVideoSurface surface, - VdpYCbCrFormat source_ycbcr_format, - void const *const *source_data, - uint32_t const *source_pitches) -{ - enum pipe_format pformat = FormatYCBCRToPipe(source_ycbcr_format); - enum getbits_conversion conversion = CONVERSION_NONE; - struct pipe_context *pipe; - struct pipe_sampler_view **sampler_views; - unsigned i, j; - unsigned usage = PIPE_TRANSFER_WRITE; - - vlVdpSurface *p_surf = vlGetDataHTAB(surface); - if (!p_surf) - return VDP_STATUS_INVALID_HANDLE; - - pipe = p_surf->device->context; - if (!pipe) - return VDP_STATUS_INVALID_HANDLE; - - if (!source_data || !source_pitches) - return VDP_STATUS_INVALID_POINTER; - - mtx_lock(&p_surf->device->mutex); - - if (p_surf->video_buffer == NULL || - ((pformat != p_surf->video_buffer->buffer_format))) { - enum pipe_format nformat = pformat; - struct pipe_screen *screen = pipe->screen; - - /* Determine the most suitable format for the new surface */ - if (!screen->is_video_format_supported(screen, nformat, - PIPE_VIDEO_PROFILE_UNKNOWN, - PIPE_VIDEO_ENTRYPOINT_BITSTREAM)) { - nformat = screen->get_video_param(screen, - PIPE_VIDEO_PROFILE_UNKNOWN, - PIPE_VIDEO_ENTRYPOINT_BITSTREAM, - PIPE_VIDEO_CAP_PREFERED_FORMAT); - if (nformat == PIPE_FORMAT_NONE) { - mtx_unlock(&p_surf->device->mutex); - return VDP_STATUS_NO_IMPLEMENTATION; - } - } - - if (p_surf->video_buffer == NULL || - nformat != p_surf->video_buffer->buffer_format) { - /* destroy the old one */ - if (p_surf->video_buffer) - p_surf->video_buffer->destroy(p_surf->video_buffer); - - /* adjust the template parameters */ - p_surf->templat.buffer_format = nformat; - if (nformat == PIPE_FORMAT_YUYV || nformat == PIPE_FORMAT_UYVY) - p_surf->templat.interlaced = false; - - /* and try to create the video buffer with the new format */ - p_surf->video_buffer = pipe->create_video_buffer(pipe, &p_surf->templat); - - /* stil no luck? ok forget it we don't support it */ - if (!p_surf->video_buffer) { - mtx_unlock(&p_surf->device->mutex); - return VDP_STATUS_NO_IMPLEMENTATION; - } - vlVdpVideoSurfaceClear(p_surf); - } - } - - if (pformat != p_surf->video_buffer->buffer_format) { - if (pformat == PIPE_FORMAT_YV12 && - p_surf->video_buffer->buffer_format == PIPE_FORMAT_NV12) - conversion = CONVERSION_YV12_TO_NV12; - else { - mtx_unlock(&p_surf->device->mutex); - return VDP_STATUS_NO_IMPLEMENTATION; - } - } - - sampler_views = p_surf->video_buffer->get_sampler_view_planes(p_surf->video_buffer); - if (!sampler_views) { - mtx_unlock(&p_surf->device->mutex); - return VDP_STATUS_RESOURCES; - } - - for (i = 0; i < 3; ++i) { - unsigned width, height; - struct pipe_sampler_view *sv = sampler_views[i]; - struct pipe_resource *tex; - if (!sv || !source_pitches[i]) continue; - - tex = sv->texture; - vlVdpVideoSurfaceSize(p_surf, i, &width, &height); - - for (j = 0; j < tex->array_size; ++j) { - struct pipe_box dst_box = { - 0, 0, j, - width, height, 1 - }; - - if (conversion == CONVERSION_YV12_TO_NV12 && i == 1) { - struct pipe_transfer *transfer; - uint8_t *map; - - map = pipe->transfer_map(pipe, tex, 0, usage, - &dst_box, &transfer); - if (!map) { - mtx_unlock(&p_surf->device->mutex); - return VDP_STATUS_RESOURCES; - } - - u_copy_nv12_from_yv12(source_data, source_pitches, - i, j, transfer->stride, tex->array_size, - map, dst_box.width, dst_box.height); - - pipe_transfer_unmap(pipe, transfer); - } else { - pipe->texture_subdata(pipe, tex, 0, - PIPE_TRANSFER_WRITE, &dst_box, - source_data[i] + source_pitches[i] * j, - source_pitches[i] * tex->array_size, - 0); - } - /* - * This surface has already been synced - * by the first map. - */ - usage |= PIPE_TRANSFER_UNSYNCHRONIZED; - } - } - mtx_unlock(&p_surf->device->mutex); - - return VDP_STATUS_OK; -} - -/** - * Helper function to initially clear the VideoSurface after (re-)creation - */ -void -vlVdpVideoSurfaceClear(vlVdpSurface *vlsurf) -{ - struct pipe_context *pipe = vlsurf->device->context; - struct pipe_surface **surfaces; - unsigned i; - - if (!vlsurf->video_buffer) - return; - - surfaces = vlsurf->video_buffer->get_surfaces(vlsurf->video_buffer); - for (i = 0; i < VL_MAX_SURFACES; ++i) { - union pipe_color_union c = {}; - - if (!surfaces[i]) - continue; - - if (i > !!vlsurf->templat.interlaced) - c.f[0] = c.f[1] = c.f[2] = c.f[3] = 0.5f; - - pipe->clear_render_target(pipe, surfaces[i], &c, 0, 0, - surfaces[i]->width, surfaces[i]->height, false); - } - pipe->flush(pipe, NULL, 0); -} - -/** - * Interop to mesa state tracker - */ -struct pipe_video_buffer *vlVdpVideoSurfaceGallium(VdpVideoSurface surface) -{ - vlVdpSurface *p_surf = vlGetDataHTAB(surface); - if (!p_surf) - return NULL; - - mtx_lock(&p_surf->device->mutex); - if (p_surf->video_buffer == NULL) { - struct pipe_context *pipe = p_surf->device->context; - - /* try to create a video buffer if we don't already have one */ - p_surf->video_buffer = pipe->create_video_buffer(pipe, &p_surf->templat); - } - mtx_unlock(&p_surf->device->mutex); - - return p_surf->video_buffer; -} - -VdpStatus vlVdpVideoSurfaceDMABuf(VdpVideoSurface surface, - VdpVideoSurfacePlane plane, - struct VdpSurfaceDMABufDesc *result) -{ - vlVdpSurface *p_surf = vlGetDataHTAB(surface); - - struct pipe_screen *pscreen; - struct winsys_handle whandle; - - struct pipe_surface *surf; - - if (!p_surf) - return VDP_STATUS_INVALID_HANDLE; - - if (plane > 3) - return VDP_STATUS_INVALID_VALUE; - - if (!result) - return VDP_STATUS_INVALID_POINTER; - - memset(result, 0, sizeof(*result)); - result->handle = -1; - - mtx_lock(&p_surf->device->mutex); - if (p_surf->video_buffer == NULL) { - struct pipe_context *pipe = p_surf->device->context; - - /* try to create a video buffer if we don't already have one */ - p_surf->video_buffer = pipe->create_video_buffer(pipe, &p_surf->templat); - } - - /* Check if surface match interop requirements */ - if (p_surf->video_buffer == NULL || !p_surf->video_buffer->interlaced || - p_surf->video_buffer->buffer_format != PIPE_FORMAT_NV12) { - mtx_unlock(&p_surf->device->mutex); - return VDP_STATUS_NO_IMPLEMENTATION; - } - - surf = p_surf->video_buffer->get_surfaces(p_surf->video_buffer)[plane]; - if (!surf) { - mtx_unlock(&p_surf->device->mutex); - return VDP_STATUS_RESOURCES; - } - - memset(&whandle, 0, sizeof(struct winsys_handle)); - whandle.type = WINSYS_HANDLE_TYPE_FD; - whandle.layer = surf->u.tex.first_layer; - - pscreen = surf->texture->screen; - if (!pscreen->resource_get_handle(pscreen, p_surf->device->context, - surf->texture, &whandle, - PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE)) { - mtx_unlock(&p_surf->device->mutex); - return VDP_STATUS_NO_IMPLEMENTATION; - } - - mtx_unlock(&p_surf->device->mutex); - - result->handle = whandle.handle; - result->width = surf->width; - result->height = surf->height; - result->offset = whandle.offset; - result->stride = whandle.stride; - - if (surf->format == PIPE_FORMAT_R8_UNORM) - result->format = VDP_RGBA_FORMAT_R8; - else - result->format = VDP_RGBA_FORMAT_R8G8; - - return VDP_STATUS_OK; -} diff --git a/src/gallium/state_trackers/vdpau/vdpau_private.h b/src/gallium/state_trackers/vdpau/vdpau_private.h deleted file mode 100644 index 80bb5aee0fe..00000000000 --- a/src/gallium/state_trackers/vdpau/vdpau_private.h +++ /dev/null @@ -1,586 +0,0 @@ -/************************************************************************** - * - * Copyright 2010 Younes Manton & Thomas Balling Sørensen. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#ifndef VDPAU_PRIVATE_H -#define VDPAU_PRIVATE_H - -#include - -#include -#include - -#include "pipe/p_compiler.h" -#include "pipe/p_video_codec.h" - -#include "state_tracker/vdpau_interop.h" -#include "state_tracker/vdpau_dmabuf.h" -#include "state_tracker/vdpau_funcs.h" - -#include "util/u_debug.h" -#include "util/u_rect.h" -#include "os/os_thread.h" - -#include "vl/vl_video_buffer.h" -#include "vl/vl_bicubic_filter.h" -#include "vl/vl_compositor.h" -#include "vl/vl_csc.h" -#include "vl/vl_deint_filter.h" -#include "vl/vl_matrix_filter.h" -#include "vl/vl_median_filter.h" -#include "vl/vl_winsys.h" - -/* Full VDPAU API documentation available at : - * ftp://download.nvidia.com/XFree86/vdpau/doxygen/html/index.html */ - -#define INFORMATION G3DVL VDPAU Driver Shared Library version VER_MAJOR.VER_MINOR -#define QUOTEME(x) #x -#define TOSTRING(x) QUOTEME(x) -#define INFORMATION_STRING TOSTRING(INFORMATION) - -static inline enum pipe_video_chroma_format -ChromaToPipe(VdpChromaType vdpau_type) -{ - switch (vdpau_type) { - case VDP_CHROMA_TYPE_420: - return PIPE_VIDEO_CHROMA_FORMAT_420; - case VDP_CHROMA_TYPE_422: - return PIPE_VIDEO_CHROMA_FORMAT_422; - case VDP_CHROMA_TYPE_444: - return PIPE_VIDEO_CHROMA_FORMAT_444; - default: - assert(0); - } - - return -1; -} - -static inline VdpChromaType -PipeToChroma(enum pipe_video_chroma_format pipe_type) -{ - switch (pipe_type) { - case PIPE_VIDEO_CHROMA_FORMAT_420: - return VDP_CHROMA_TYPE_420; - case PIPE_VIDEO_CHROMA_FORMAT_422: - return VDP_CHROMA_TYPE_422; - case PIPE_VIDEO_CHROMA_FORMAT_444: - return VDP_CHROMA_TYPE_444; - default: - assert(0); - } - - return -1; -} - -static inline enum pipe_video_chroma_format -FormatYCBCRToPipeChroma(VdpYCbCrFormat vdpau_format) -{ - switch (vdpau_format) { - case VDP_YCBCR_FORMAT_NV12: - return PIPE_VIDEO_CHROMA_FORMAT_420; - case VDP_YCBCR_FORMAT_YV12: - return PIPE_VIDEO_CHROMA_FORMAT_420; - case VDP_YCBCR_FORMAT_UYVY: - return PIPE_VIDEO_CHROMA_FORMAT_422; - case VDP_YCBCR_FORMAT_YUYV: - return PIPE_VIDEO_CHROMA_FORMAT_422; - case VDP_YCBCR_FORMAT_Y8U8V8A8: - return PIPE_VIDEO_CHROMA_FORMAT_444; - case VDP_YCBCR_FORMAT_V8U8Y8A8: - return PIPE_VIDEO_CHROMA_FORMAT_444; - default: - assert(0); - } - - return PIPE_FORMAT_NONE; -} - -static inline enum pipe_format -FormatYCBCRToPipe(VdpYCbCrFormat vdpau_format) -{ - switch (vdpau_format) { - case VDP_YCBCR_FORMAT_NV12: - return PIPE_FORMAT_NV12; - case VDP_YCBCR_FORMAT_YV12: - return PIPE_FORMAT_YV12; - case VDP_YCBCR_FORMAT_UYVY: - return PIPE_FORMAT_UYVY; - case VDP_YCBCR_FORMAT_YUYV: - return PIPE_FORMAT_YUYV; - case VDP_YCBCR_FORMAT_Y8U8V8A8: - return PIPE_FORMAT_R8G8B8A8_UNORM; - case VDP_YCBCR_FORMAT_V8U8Y8A8: - return PIPE_FORMAT_B8G8R8A8_UNORM; -#ifdef VDP_YCBCR_FORMAT_P010 - case VDP_YCBCR_FORMAT_P010: - return PIPE_FORMAT_P010; -#endif -#ifdef VDP_YCBCR_FORMAT_P016 - case VDP_YCBCR_FORMAT_P016: - return PIPE_FORMAT_P016; -#endif - default: - /* NOTE: Can't be "unreachable", as it's quite reachable. */ - assert(!"unexpected VdpYCbCrFormat"); - /* fallthrough */ -#ifdef VDP_YCBCR_FORMAT_Y_UV_444 - case VDP_YCBCR_FORMAT_Y_UV_444: -#endif -#ifdef VDP_YCBCR_FORMAT_Y_U_V_444 - case VDP_YCBCR_FORMAT_Y_U_V_444: -#endif -#ifdef VDP_YCBCR_FORMAT_Y_U_V_444_16 - case VDP_YCBCR_FORMAT_Y_U_V_444_16: -#endif - return PIPE_FORMAT_NONE; - } - -} - -static inline VdpYCbCrFormat -PipeToFormatYCBCR(enum pipe_format p_format) -{ - switch (p_format) { - case PIPE_FORMAT_NV12: - return VDP_YCBCR_FORMAT_NV12; - case PIPE_FORMAT_YV12: - return VDP_YCBCR_FORMAT_YV12; - case PIPE_FORMAT_UYVY: - return VDP_YCBCR_FORMAT_UYVY; - case PIPE_FORMAT_YUYV: - return VDP_YCBCR_FORMAT_YUYV; - case PIPE_FORMAT_R8G8B8A8_UNORM: - return VDP_YCBCR_FORMAT_Y8U8V8A8; - case PIPE_FORMAT_B8G8R8A8_UNORM: - return VDP_YCBCR_FORMAT_V8U8Y8A8; - default: - assert(0); - } - - return -1; -} - -static inline VdpRGBAFormat -PipeToFormatRGBA(enum pipe_format p_format) -{ - switch (p_format) { - case PIPE_FORMAT_A8_UNORM: - return VDP_RGBA_FORMAT_A8; - case PIPE_FORMAT_B10G10R10A2_UNORM: - return VDP_RGBA_FORMAT_B10G10R10A2; - case PIPE_FORMAT_B8G8R8A8_UNORM: - return VDP_RGBA_FORMAT_B8G8R8A8; - case PIPE_FORMAT_R10G10B10A2_UNORM: - return VDP_RGBA_FORMAT_R10G10B10A2; - case PIPE_FORMAT_R8G8B8A8_UNORM: - return VDP_RGBA_FORMAT_R8G8B8A8; - default: - assert(0); - } - - return -1; -} - -static inline enum pipe_format -FormatIndexedToPipe(VdpRGBAFormat vdpau_format) -{ - switch (vdpau_format) { - case VDP_INDEXED_FORMAT_A4I4: - return PIPE_FORMAT_R4A4_UNORM; - case VDP_INDEXED_FORMAT_I4A4: - return PIPE_FORMAT_A4R4_UNORM; - case VDP_INDEXED_FORMAT_A8I8: - return PIPE_FORMAT_A8R8_UNORM; - case VDP_INDEXED_FORMAT_I8A8: - return PIPE_FORMAT_R8A8_UNORM; - default: - assert(0); - } - - return PIPE_FORMAT_NONE; -} - -static inline enum pipe_format -FormatColorTableToPipe(VdpColorTableFormat vdpau_format) -{ - switch(vdpau_format) { - case VDP_COLOR_TABLE_FORMAT_B8G8R8X8: - return PIPE_FORMAT_B8G8R8X8_UNORM; - default: - assert(0); - } - - return PIPE_FORMAT_NONE; -} - -static inline enum pipe_video_profile -ProfileToPipe(VdpDecoderProfile vdpau_profile) -{ - switch (vdpau_profile) { - case VDP_DECODER_PROFILE_MPEG1: - return PIPE_VIDEO_PROFILE_MPEG1; - case VDP_DECODER_PROFILE_MPEG2_SIMPLE: - return PIPE_VIDEO_PROFILE_MPEG2_SIMPLE; - case VDP_DECODER_PROFILE_MPEG2_MAIN: - return PIPE_VIDEO_PROFILE_MPEG2_MAIN; - case VDP_DECODER_PROFILE_H264_BASELINE: - return PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE; - case VDP_DECODER_PROFILE_H264_CONSTRAINED_BASELINE: - return PIPE_VIDEO_PROFILE_MPEG4_AVC_CONSTRAINED_BASELINE; - case VDP_DECODER_PROFILE_H264_MAIN: - return PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN; - case VDP_DECODER_PROFILE_H264_HIGH: - return PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH; - case VDP_DECODER_PROFILE_MPEG4_PART2_SP: - return PIPE_VIDEO_PROFILE_MPEG4_SIMPLE; - case VDP_DECODER_PROFILE_MPEG4_PART2_ASP: - return PIPE_VIDEO_PROFILE_MPEG4_ADVANCED_SIMPLE; - case VDP_DECODER_PROFILE_VC1_SIMPLE: - return PIPE_VIDEO_PROFILE_VC1_SIMPLE; - case VDP_DECODER_PROFILE_VC1_MAIN: - return PIPE_VIDEO_PROFILE_VC1_MAIN; - case VDP_DECODER_PROFILE_VC1_ADVANCED: - return PIPE_VIDEO_PROFILE_VC1_ADVANCED; - case VDP_DECODER_PROFILE_HEVC_MAIN: - return PIPE_VIDEO_PROFILE_HEVC_MAIN; - case VDP_DECODER_PROFILE_HEVC_MAIN_10: - return PIPE_VIDEO_PROFILE_HEVC_MAIN_10; - case VDP_DECODER_PROFILE_HEVC_MAIN_STILL: - return PIPE_VIDEO_PROFILE_HEVC_MAIN_STILL; - case VDP_DECODER_PROFILE_HEVC_MAIN_12: - return PIPE_VIDEO_PROFILE_HEVC_MAIN_12; - case VDP_DECODER_PROFILE_HEVC_MAIN_444: - return PIPE_VIDEO_PROFILE_HEVC_MAIN_444; - default: - return PIPE_VIDEO_PROFILE_UNKNOWN; - } -} - -static inline VdpDecoderProfile -PipeToProfile(enum pipe_video_profile p_profile) -{ - switch (p_profile) { - case PIPE_VIDEO_PROFILE_MPEG1: - return VDP_DECODER_PROFILE_MPEG1; - case PIPE_VIDEO_PROFILE_MPEG2_SIMPLE: - return VDP_DECODER_PROFILE_MPEG2_SIMPLE; - case PIPE_VIDEO_PROFILE_MPEG2_MAIN: - return VDP_DECODER_PROFILE_MPEG2_MAIN; - case PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE: - return VDP_DECODER_PROFILE_H264_BASELINE; - case PIPE_VIDEO_PROFILE_MPEG4_AVC_CONSTRAINED_BASELINE: - return VDP_DECODER_PROFILE_H264_CONSTRAINED_BASELINE; - case PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN: - return VDP_DECODER_PROFILE_H264_MAIN; - case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH: - return VDP_DECODER_PROFILE_H264_HIGH; - case PIPE_VIDEO_PROFILE_MPEG4_SIMPLE: - return VDP_DECODER_PROFILE_MPEG4_PART2_SP; - case PIPE_VIDEO_PROFILE_MPEG4_ADVANCED_SIMPLE: - return VDP_DECODER_PROFILE_MPEG4_PART2_ASP; - case PIPE_VIDEO_PROFILE_VC1_SIMPLE: - return VDP_DECODER_PROFILE_VC1_SIMPLE; - case PIPE_VIDEO_PROFILE_VC1_MAIN: - return VDP_DECODER_PROFILE_VC1_MAIN; - case PIPE_VIDEO_PROFILE_VC1_ADVANCED: - return VDP_DECODER_PROFILE_VC1_ADVANCED; - case PIPE_VIDEO_PROFILE_HEVC_MAIN: - return VDP_DECODER_PROFILE_HEVC_MAIN; - case PIPE_VIDEO_PROFILE_HEVC_MAIN_10: - return VDP_DECODER_PROFILE_HEVC_MAIN_10; - case PIPE_VIDEO_PROFILE_HEVC_MAIN_STILL: - return VDP_DECODER_PROFILE_HEVC_MAIN_STILL; - case PIPE_VIDEO_PROFILE_HEVC_MAIN_12: - return VDP_DECODER_PROFILE_HEVC_MAIN_12; - case PIPE_VIDEO_PROFILE_HEVC_MAIN_444: - return VDP_DECODER_PROFILE_HEVC_MAIN_444; - default: - assert(0); - return -1; - } -} - -static inline struct u_rect * -RectToPipe(const VdpRect *src, struct u_rect *dst) -{ - if (src) { - dst->x0 = src->x0; - dst->y0 = src->y0; - dst->x1 = src->x1; - dst->y1 = src->y1; - return dst; - } - return NULL; -} - -static inline struct pipe_box -RectToPipeBox(const VdpRect *rect, struct pipe_resource *res) -{ - struct pipe_box box; - - box.x = 0; - box.y = 0; - box.z = 0; - box.width = res->width0; - box.height = res->height0; - box.depth = 1; - - if (rect) { - box.x = MIN2(rect->x0, rect->x1); - box.y = MIN2(rect->y0, rect->y1); - box.width = abs(rect->x1 - rect->x0); - box.height = abs(rect->y1 - rect->y0); - } - - return box; -} - -static inline bool -CheckSurfaceParams(struct pipe_screen *screen, - const struct pipe_resource *templ) -{ - return screen->is_format_supported(screen, templ->format, templ->target, - templ->nr_samples, - templ->nr_storage_samples, templ->bind); -} - -typedef struct -{ - struct pipe_reference reference; - struct vl_screen *vscreen; - struct pipe_context *context; - struct vl_compositor compositor; - struct pipe_sampler_view *dummy_sv; - mtx_t mutex; -} vlVdpDevice; - -typedef struct -{ - vlVdpDevice *device; - struct vl_compositor_state cstate; - - struct { - bool supported, enabled; - float luma_min, luma_max; - } luma_key; - - struct { - bool supported, enabled, spatial; - struct vl_deint_filter *filter; - } deint; - - struct { - bool supported, enabled; - struct vl_bicubic_filter *filter; - } bicubic; - - struct { - bool supported, enabled; - unsigned level; - struct vl_median_filter *filter; - } noise_reduction; - - struct { - bool supported, enabled; - float value; - struct vl_matrix_filter *filter; - } sharpness; - - unsigned video_width, video_height; - enum pipe_video_chroma_format chroma_format; - unsigned max_layers, skip_chroma_deint; - - bool custom_csc; - vl_csc_matrix csc; -} vlVdpVideoMixer; - -typedef struct -{ - vlVdpDevice *device; - struct pipe_video_buffer templat, *video_buffer; -} vlVdpSurface; - -typedef struct -{ - vlVdpDevice *device; - struct pipe_sampler_view *sampler_view; -} vlVdpBitmapSurface; - -typedef uint64_t vlVdpTime; - -typedef struct -{ - vlVdpDevice *device; - struct pipe_surface *surface; - struct pipe_sampler_view *sampler_view; - struct pipe_fence_handle *fence; - struct vl_compositor_state cstate; - struct u_rect dirty_area; - bool send_to_X; -} vlVdpOutputSurface; - -typedef struct -{ - vlVdpDevice *device; - Drawable drawable; -} vlVdpPresentationQueueTarget; - -typedef struct -{ - vlVdpDevice *device; - Drawable drawable; - struct vl_compositor_state cstate; - vlVdpOutputSurface *last_surf; -} vlVdpPresentationQueue; - -typedef struct -{ - vlVdpDevice *device; - mtx_t mutex; - struct pipe_video_codec *decoder; -} vlVdpDecoder; - -typedef uint32_t vlHandle; - -boolean vlCreateHTAB(void); -void vlDestroyHTAB(void); -vlHandle vlAddDataHTAB(void *data); -void* vlGetDataHTAB(vlHandle handle); -void vlRemoveDataHTAB(vlHandle handle); - -boolean vlGetFuncFTAB(VdpFuncId function_id, void **func); - -/* Public functions */ -VdpDeviceCreateX11 vdp_imp_device_create_x11; - -void vlVdpDefaultSamplerViewTemplate(struct pipe_sampler_view *templ, struct pipe_resource *res); - -/* Internal function pointers */ -VdpGetErrorString vlVdpGetErrorString; -VdpDeviceDestroy vlVdpDeviceDestroy; -void vlVdpDeviceFree(vlVdpDevice *dev); -VdpGetProcAddress vlVdpGetProcAddress; -VdpGetApiVersion vlVdpGetApiVersion; -VdpGetInformationString vlVdpGetInformationString; -VdpVideoSurfaceQueryCapabilities vlVdpVideoSurfaceQueryCapabilities; -VdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities vlVdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities; -VdpDecoderQueryCapabilities vlVdpDecoderQueryCapabilities; -VdpOutputSurfaceQueryCapabilities vlVdpOutputSurfaceQueryCapabilities; -VdpOutputSurfaceQueryGetPutBitsNativeCapabilities vlVdpOutputSurfaceQueryGetPutBitsNativeCapabilities; -VdpOutputSurfaceQueryPutBitsIndexedCapabilities vlVdpOutputSurfaceQueryPutBitsIndexedCapabilities; -VdpOutputSurfaceQueryPutBitsYCbCrCapabilities vlVdpOutputSurfaceQueryPutBitsYCbCrCapabilities; -VdpBitmapSurfaceQueryCapabilities vlVdpBitmapSurfaceQueryCapabilities; -VdpVideoMixerQueryFeatureSupport vlVdpVideoMixerQueryFeatureSupport; -VdpVideoMixerQueryParameterSupport vlVdpVideoMixerQueryParameterSupport; -VdpVideoMixerQueryParameterValueRange vlVdpVideoMixerQueryParameterValueRange; -VdpVideoMixerQueryAttributeSupport vlVdpVideoMixerQueryAttributeSupport; -VdpVideoMixerQueryAttributeValueRange vlVdpVideoMixerQueryAttributeValueRange; -VdpVideoSurfaceCreate vlVdpVideoSurfaceCreate; -VdpVideoSurfaceDestroy vlVdpVideoSurfaceDestroy; -VdpVideoSurfaceGetParameters vlVdpVideoSurfaceGetParameters; -VdpVideoSurfaceGetBitsYCbCr vlVdpVideoSurfaceGetBitsYCbCr; -VdpVideoSurfacePutBitsYCbCr vlVdpVideoSurfacePutBitsYCbCr; -void vlVdpVideoSurfaceClear(vlVdpSurface *vlsurf); -VdpDecoderCreate vlVdpDecoderCreate; -VdpDecoderDestroy vlVdpDecoderDestroy; -VdpDecoderGetParameters vlVdpDecoderGetParameters; -VdpDecoderRender vlVdpDecoderRender; -VdpOutputSurfaceCreate vlVdpOutputSurfaceCreate; -VdpOutputSurfaceDestroy vlVdpOutputSurfaceDestroy; -VdpOutputSurfaceGetParameters vlVdpOutputSurfaceGetParameters; -VdpOutputSurfaceGetBitsNative vlVdpOutputSurfaceGetBitsNative; -VdpOutputSurfacePutBitsNative vlVdpOutputSurfacePutBitsNative; -VdpOutputSurfacePutBitsIndexed vlVdpOutputSurfacePutBitsIndexed; -VdpOutputSurfacePutBitsYCbCr vlVdpOutputSurfacePutBitsYCbCr; -VdpOutputSurfaceRenderOutputSurface vlVdpOutputSurfaceRenderOutputSurface; -VdpOutputSurfaceRenderBitmapSurface vlVdpOutputSurfaceRenderBitmapSurface; -VdpBitmapSurfaceCreate vlVdpBitmapSurfaceCreate; -VdpBitmapSurfaceDestroy vlVdpBitmapSurfaceDestroy; -VdpBitmapSurfaceGetParameters vlVdpBitmapSurfaceGetParameters; -VdpBitmapSurfacePutBitsNative vlVdpBitmapSurfacePutBitsNative; -VdpPresentationQueueTargetDestroy vlVdpPresentationQueueTargetDestroy; -VdpPresentationQueueCreate vlVdpPresentationQueueCreate; -VdpPresentationQueueDestroy vlVdpPresentationQueueDestroy; -VdpPresentationQueueSetBackgroundColor vlVdpPresentationQueueSetBackgroundColor; -VdpPresentationQueueGetBackgroundColor vlVdpPresentationQueueGetBackgroundColor; -VdpPresentationQueueGetTime vlVdpPresentationQueueGetTime; -VdpPresentationQueueDisplay vlVdpPresentationQueueDisplay; -VdpPresentationQueueBlockUntilSurfaceIdle vlVdpPresentationQueueBlockUntilSurfaceIdle; -VdpPresentationQueueQuerySurfaceStatus vlVdpPresentationQueueQuerySurfaceStatus; -VdpPreemptionCallback vlVdpPreemptionCallback; -VdpPreemptionCallbackRegister vlVdpPreemptionCallbackRegister; -VdpVideoMixerSetFeatureEnables vlVdpVideoMixerSetFeatureEnables; -VdpVideoMixerCreate vlVdpVideoMixerCreate; -VdpVideoMixerRender vlVdpVideoMixerRender; -VdpVideoMixerSetAttributeValues vlVdpVideoMixerSetAttributeValues; -VdpVideoMixerGetFeatureSupport vlVdpVideoMixerGetFeatureSupport; -VdpVideoMixerGetFeatureEnables vlVdpVideoMixerGetFeatureEnables; -VdpVideoMixerGetParameterValues vlVdpVideoMixerGetParameterValues; -VdpVideoMixerGetAttributeValues vlVdpVideoMixerGetAttributeValues; -VdpVideoMixerDestroy vlVdpVideoMixerDestroy; -VdpGenerateCSCMatrix vlVdpGenerateCSCMatrix; -/* Winsys specific internal function pointers */ -VdpPresentationQueueTargetCreateX11 vlVdpPresentationQueueTargetCreateX11; - - -/* interop to mesa state tracker */ -VdpVideoSurfaceGallium vlVdpVideoSurfaceGallium; -VdpOutputSurfaceGallium vlVdpOutputSurfaceGallium; -VdpVideoSurfaceDMABuf vlVdpVideoSurfaceDMABuf; -VdpOutputSurfaceDMABuf vlVdpOutputSurfaceDMABuf; - -#define VDPAU_OUT 0 -#define VDPAU_ERR 1 -#define VDPAU_WARN 2 -#define VDPAU_TRACE 3 - -static inline void VDPAU_MSG(unsigned int level, const char *fmt, ...) -{ - static int debug_level = -1; - - if (debug_level == -1) { - debug_level = MAX2(debug_get_num_option("VDPAU_DEBUG", 0), 0); - } - - if (level <= debug_level) { - va_list ap; - va_start(ap, fmt); - _debug_vprintf(fmt, ap); - va_end(ap); - } -} - -static inline void -DeviceReference(vlVdpDevice **ptr, vlVdpDevice *dev) -{ - vlVdpDevice *old_dev = *ptr; - - if (pipe_reference(&(*ptr)->reference, &dev->reference)) - vlVdpDeviceFree(old_dev); - *ptr = dev; -} - -#endif /* VDPAU_PRIVATE_H */ diff --git a/src/gallium/state_trackers/wgl/Makefile.sources b/src/gallium/state_trackers/wgl/Makefile.sources deleted file mode 100644 index 2630b445d54..00000000000 --- a/src/gallium/state_trackers/wgl/Makefile.sources +++ /dev/null @@ -1,17 +0,0 @@ -C_SOURCES := \ - stw_context.c \ - stw_device.c \ - stw_ext_context.c \ - stw_ext_extensionsstring.c \ - stw_ext_pbuffer.c \ - stw_ext_pixelformat.c \ - stw_ext_rendertexture.c \ - stw_ext_swapinterval.c \ - stw_framebuffer.c \ - stw_getprocaddress.c \ - stw_nopfuncs.c \ - stw_nopfuncs.h \ - stw_pixelformat.c \ - stw_st.c \ - stw_tls.c \ - stw_wgl.c diff --git a/src/gallium/state_trackers/wgl/SConscript b/src/gallium/state_trackers/wgl/SConscript deleted file mode 100644 index bbf5ebd9764..00000000000 --- a/src/gallium/state_trackers/wgl/SConscript +++ /dev/null @@ -1,24 +0,0 @@ -import os - -Import('*') - -env = env.Clone() - -env.Append(CPPPATH = [ - '#src/mapi', - '#src/mesa', - '.', -]) - -env.AppendUnique(CPPDEFINES = [ - '_GDI32_', # prevent wgl* being declared __declspec(dllimport) - 'BUILD_GL32', # declare gl* as __declspec(dllexport) in Mesa headers - 'WIN32_LEAN_AND_MEAN', # http://msdn2.microsoft.com/en-us/library/6dwk3a1z.aspx - '_GLAPI_NO_EXPORTS', # prevent _glapi_* from being declared __declspec(dllimport) -]) - -wgl = env.ConvenienceLibrary( - target ='wgl', - source = env.ParseSourceList('Makefile.sources', 'C_SOURCES'), -) -Export('wgl') diff --git a/src/gallium/state_trackers/wgl/gldrv.h b/src/gallium/state_trackers/wgl/gldrv.h deleted file mode 100644 index 829422c96a8..00000000000 --- a/src/gallium/state_trackers/wgl/gldrv.h +++ /dev/null @@ -1,589 +0,0 @@ -/* - * Copyright © Microsoft Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef _GLDRV_ -#define _GLDRV_ - -#include - -// Number of entries expected for various versions of OpenGL -#define OPENGL_VERSION_100_ENTRIES 306 -#define OPENGL_VERSION_110_ENTRIES 336 - -typedef struct _GLDISPATCHTABLE { - void (APIENTRY *glNewList )( GLuint list, GLenum mode ); - void (APIENTRY *glEndList )( void ); - void (APIENTRY *glCallList )( GLuint list ); - void (APIENTRY *glCallLists )( GLsizei n, GLenum type, const GLvoid *lists ); - void (APIENTRY *glDeleteLists )( GLuint list, GLsizei range ); - GLuint (APIENTRY *glGenLists )( GLsizei range ); - void (APIENTRY *glListBase )( GLuint base ); - void (APIENTRY *glBegin )( GLenum mode ); - void (APIENTRY *glBitmap )( GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap ); - void (APIENTRY *glColor3b )( GLbyte red, GLbyte green, GLbyte blue ); - void (APIENTRY *glColor3bv )( const GLbyte *v ); - void (APIENTRY *glColor3d )( GLdouble red, GLdouble green, GLdouble blue ); - void (APIENTRY *glColor3dv )( const GLdouble *v ); - void (APIENTRY *glColor3f )( GLfloat red, GLfloat green, GLfloat blue ); - void (APIENTRY *glColor3fv )( const GLfloat *v ); - void (APIENTRY *glColor3i )( GLint red, GLint green, GLint blue ); - void (APIENTRY *glColor3iv )( const GLint *v ); - void (APIENTRY *glColor3s )( GLshort red, GLshort green, GLshort blue ); - void (APIENTRY *glColor3sv )( const GLshort *v ); - void (APIENTRY *glColor3ub )( GLubyte red, GLubyte green, GLubyte blue ); - void (APIENTRY *glColor3ubv )( const GLubyte *v ); - void (APIENTRY *glColor3ui )( GLuint red, GLuint green, GLuint blue ); - void (APIENTRY *glColor3uiv )( const GLuint *v ); - void (APIENTRY *glColor3us )( GLushort red, GLushort green, GLushort blue ); - void (APIENTRY *glColor3usv )( const GLushort *v ); - void (APIENTRY *glColor4b )( GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha ); - void (APIENTRY *glColor4bv )( const GLbyte *v ); - void (APIENTRY *glColor4d )( GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha ); - void (APIENTRY *glColor4dv )( const GLdouble *v ); - void (APIENTRY *glColor4f )( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha ); - void (APIENTRY *glColor4fv )( const GLfloat *v ); - void (APIENTRY *glColor4i )( GLint red, GLint green, GLint blue, GLint alpha ); - void (APIENTRY *glColor4iv )( const GLint *v ); - void (APIENTRY *glColor4s )( GLshort red, GLshort green, GLshort blue, GLshort alpha ); - void (APIENTRY *glColor4sv )( const GLshort *v ); - void (APIENTRY *glColor4ub )( GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha ); - void (APIENTRY *glColor4ubv )( const GLubyte *v ); - void (APIENTRY *glColor4ui )( GLuint red, GLuint green, GLuint blue, GLuint alpha ); - void (APIENTRY *glColor4uiv )( const GLuint *v ); - void (APIENTRY *glColor4us )( GLushort red, GLushort green, GLushort blue, GLushort alpha ); - void (APIENTRY *glColor4usv )( const GLushort *v ); - void (APIENTRY *glEdgeFlag )( GLboolean flag ); - void (APIENTRY *glEdgeFlagv )( const GLboolean *flag ); - void (APIENTRY *glEnd )( void ); - void (APIENTRY *glIndexd )( GLdouble c ); - void (APIENTRY *glIndexdv )( const GLdouble *c ); - void (APIENTRY *glIndexf )( GLfloat c ); - void (APIENTRY *glIndexfv )( const GLfloat *c ); - void (APIENTRY *glIndexi )( GLint c ); - void (APIENTRY *glIndexiv )( const GLint *c ); - void (APIENTRY *glIndexs )( GLshort c ); - void (APIENTRY *glIndexsv )( const GLshort *c ); - void (APIENTRY *glNormal3b )( GLbyte nx, GLbyte ny, GLbyte nz ); - void (APIENTRY *glNormal3bv )( const GLbyte *v ); - void (APIENTRY *glNormal3d )( GLdouble nx, GLdouble ny, GLdouble nz ); - void (APIENTRY *glNormal3dv )( const GLdouble *v ); - void (APIENTRY *glNormal3f )( GLfloat nx, GLfloat ny, GLfloat nz ); - void (APIENTRY *glNormal3fv )( const GLfloat *v ); - void (APIENTRY *glNormal3i )( GLint nx, GLint ny, GLint nz ); - void (APIENTRY *glNormal3iv )( const GLint *v ); - void (APIENTRY *glNormal3s )( GLshort nx, GLshort ny, GLshort nz ); - void (APIENTRY *glNormal3sv )( const GLshort *v ); - void (APIENTRY *glRasterPos2d )( GLdouble x, GLdouble y ); - void (APIENTRY *glRasterPos2dv )( const GLdouble *v ); - void (APIENTRY *glRasterPos2f )( GLfloat x, GLfloat y ); - void (APIENTRY *glRasterPos2fv )( const GLfloat *v ); - void (APIENTRY *glRasterPos2i )( GLint x, GLint y ); - void (APIENTRY *glRasterPos2iv )( const GLint *v ); - void (APIENTRY *glRasterPos2s )( GLshort x, GLshort y ); - void (APIENTRY *glRasterPos2sv )( const GLshort *v ); - void (APIENTRY *glRasterPos3d )( GLdouble x, GLdouble y, GLdouble z ); - void (APIENTRY *glRasterPos3dv )( const GLdouble *v ); - void (APIENTRY *glRasterPos3f )( GLfloat x, GLfloat y, GLfloat z ); - void (APIENTRY *glRasterPos3fv )( const GLfloat *v ); - void (APIENTRY *glRasterPos3i )( GLint x, GLint y, GLint z ); - void (APIENTRY *glRasterPos3iv )( const GLint *v ); - void (APIENTRY *glRasterPos3s )( GLshort x, GLshort y, GLshort z ); - void (APIENTRY *glRasterPos3sv )( const GLshort *v ); - void (APIENTRY *glRasterPos4d )( GLdouble x, GLdouble y, GLdouble z, GLdouble w ); - void (APIENTRY *glRasterPos4dv )( const GLdouble *v ); - void (APIENTRY *glRasterPos4f )( GLfloat x, GLfloat y, GLfloat z, GLfloat w ); - void (APIENTRY *glRasterPos4fv )( const GLfloat *v ); - void (APIENTRY *glRasterPos4i )( GLint x, GLint y, GLint z, GLint w ); - void (APIENTRY *glRasterPos4iv )( const GLint *v ); - void (APIENTRY *glRasterPos4s )( GLshort x, GLshort y, GLshort z, GLshort w ); - void (APIENTRY *glRasterPos4sv )( const GLshort *v ); - void (APIENTRY *glRectd )( GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2 ); - void (APIENTRY *glRectdv )( const GLdouble *v1, const GLdouble *v2 ); - void (APIENTRY *glRectf )( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 ); - void (APIENTRY *glRectfv )( const GLfloat *v1, const GLfloat *v2 ); - void (APIENTRY *glRecti )( GLint x1, GLint y1, GLint x2, GLint y2 ); - void (APIENTRY *glRectiv )( const GLint *v1, const GLint *v2 ); - void (APIENTRY *glRects )( GLshort x1, GLshort y1, GLshort x2, GLshort y2 ); - void (APIENTRY *glRectsv )( const GLshort *v1, const GLshort *v2 ); - void (APIENTRY *glTexCoord1d )( GLdouble s ); - void (APIENTRY *glTexCoord1dv )( const GLdouble *v ); - void (APIENTRY *glTexCoord1f )( GLfloat s ); - void (APIENTRY *glTexCoord1fv )( const GLfloat *v ); - void (APIENTRY *glTexCoord1i )( GLint s ); - void (APIENTRY *glTexCoord1iv )( const GLint *v ); - void (APIENTRY *glTexCoord1s )( GLshort s ); - void (APIENTRY *glTexCoord1sv )( const GLshort *v ); - void (APIENTRY *glTexCoord2d )( GLdouble s, GLdouble t ); - void (APIENTRY *glTexCoord2dv )( const GLdouble *v ); - void (APIENTRY *glTexCoord2f )( GLfloat s, GLfloat t ); - void (APIENTRY *glTexCoord2fv )( const GLfloat *v ); - void (APIENTRY *glTexCoord2i )( GLint s, GLint t ); - void (APIENTRY *glTexCoord2iv )( const GLint *v ); - void (APIENTRY *glTexCoord2s )( GLshort s, GLshort t ); - void (APIENTRY *glTexCoord2sv )( const GLshort *v ); - void (APIENTRY *glTexCoord3d )( GLdouble s, GLdouble t, GLdouble r ); - void (APIENTRY *glTexCoord3dv )( const GLdouble *v ); - void (APIENTRY *glTexCoord3f )( GLfloat s, GLfloat t, GLfloat r ); - void (APIENTRY *glTexCoord3fv )( const GLfloat *v ); - void (APIENTRY *glTexCoord3i )( GLint s, GLint t, GLint r ); - void (APIENTRY *glTexCoord3iv )( const GLint *v ); - void (APIENTRY *glTexCoord3s )( GLshort s, GLshort t, GLshort r ); - void (APIENTRY *glTexCoord3sv )( const GLshort *v ); - void (APIENTRY *glTexCoord4d )( GLdouble s, GLdouble t, GLdouble r, GLdouble q ); - void (APIENTRY *glTexCoord4dv )( const GLdouble *v ); - void (APIENTRY *glTexCoord4f )( GLfloat s, GLfloat t, GLfloat r, GLfloat q ); - void (APIENTRY *glTexCoord4fv )( const GLfloat *v ); - void (APIENTRY *glTexCoord4i )( GLint s, GLint t, GLint r, GLint q ); - void (APIENTRY *glTexCoord4iv )( const GLint *v ); - void (APIENTRY *glTexCoord4s )( GLshort s, GLshort t, GLshort r, GLshort q ); - void (APIENTRY *glTexCoord4sv )( const GLshort *v ); - void (APIENTRY *glVertex2d )( GLdouble x, GLdouble y ); - void (APIENTRY *glVertex2dv )( const GLdouble *v ); - void (APIENTRY *glVertex2f )( GLfloat x, GLfloat y ); - void (APIENTRY *glVertex2fv )( const GLfloat *v ); - void (APIENTRY *glVertex2i )( GLint x, GLint y ); - void (APIENTRY *glVertex2iv )( const GLint *v ); - void (APIENTRY *glVertex2s )( GLshort x, GLshort y ); - void (APIENTRY *glVertex2sv )( const GLshort *v ); - void (APIENTRY *glVertex3d )( GLdouble x, GLdouble y, GLdouble z ); - void (APIENTRY *glVertex3dv )( const GLdouble *v ); - void (APIENTRY *glVertex3f )( GLfloat x, GLfloat y, GLfloat z ); - void (APIENTRY *glVertex3fv )( const GLfloat *v ); - void (APIENTRY *glVertex3i )( GLint x, GLint y, GLint z ); - void (APIENTRY *glVertex3iv )( const GLint *v ); - void (APIENTRY *glVertex3s )( GLshort x, GLshort y, GLshort z ); - void (APIENTRY *glVertex3sv )( const GLshort *v ); - void (APIENTRY *glVertex4d )( GLdouble x, GLdouble y, GLdouble z, GLdouble w ); - void (APIENTRY *glVertex4dv )( const GLdouble *v ); - void (APIENTRY *glVertex4f )( GLfloat x, GLfloat y, GLfloat z, GLfloat w ); - void (APIENTRY *glVertex4fv )( const GLfloat *v ); - void (APIENTRY *glVertex4i )( GLint x, GLint y, GLint z, GLint w ); - void (APIENTRY *glVertex4iv )( const GLint *v ); - void (APIENTRY *glVertex4s )( GLshort x, GLshort y, GLshort z, GLshort w ); - void (APIENTRY *glVertex4sv )( const GLshort *v ); - void (APIENTRY *glClipPlane )( GLenum plane, const GLdouble *equation ); - void (APIENTRY *glColorMaterial )( GLenum face, GLenum mode ); - void (APIENTRY *glCullFace )( GLenum mode ); - void (APIENTRY *glFogf )( GLenum pname, GLfloat param ); - void (APIENTRY *glFogfv )( GLenum pname, const GLfloat *params ); - void (APIENTRY *glFogi )( GLenum pname, GLint param ); - void (APIENTRY *glFogiv )( GLenum pname, const GLint *params ); - void (APIENTRY *glFrontFace )( GLenum mode ); - void (APIENTRY *glHint )( GLenum target, GLenum mode ); - void (APIENTRY *glLightf )( GLenum light, GLenum pname, GLfloat param ); - void (APIENTRY *glLightfv )( GLenum light, GLenum pname, const GLfloat *params ); - void (APIENTRY *glLighti )( GLenum light, GLenum pname, GLint param ); - void (APIENTRY *glLightiv )( GLenum light, GLenum pname, const GLint *params ); - void (APIENTRY *glLightModelf )( GLenum pname, GLfloat param ); - void (APIENTRY *glLightModelfv )( GLenum pname, const GLfloat *params ); - void (APIENTRY *glLightModeli )( GLenum pname, GLint param ); - void (APIENTRY *glLightModeliv )( GLenum pname, const GLint *params ); - void (APIENTRY *glLineStipple )( GLint factor, GLushort pattern ); - void (APIENTRY *glLineWidth )( GLfloat width ); - void (APIENTRY *glMaterialf )( GLenum face, GLenum pname, GLfloat param ); - void (APIENTRY *glMaterialfv )( GLenum face, GLenum pname, const GLfloat *params ); - void (APIENTRY *glMateriali )( GLenum face, GLenum pname, GLint param ); - void (APIENTRY *glMaterialiv )( GLenum face, GLenum pname, const GLint *params ); - void (APIENTRY *glPointSize )( GLfloat size ); - void (APIENTRY *glPolygonMode )( GLenum face, GLenum mode ); - void (APIENTRY *glPolygonStipple )( const GLubyte *mask ); - void (APIENTRY *glScissor )( GLint x, GLint y, GLsizei width, GLsizei height ); - void (APIENTRY *glShadeModel )( GLenum mode ); - void (APIENTRY *glTexParameterf )( GLenum target, GLenum pname, GLfloat param ); - void (APIENTRY *glTexParameterfv )( GLenum target, GLenum pname, const GLfloat *params ); - void (APIENTRY *glTexParameteri )( GLenum target, GLenum pname, GLint param ); - void (APIENTRY *glTexParameteriv )( GLenum target, GLenum pname, const GLint *params ); - void (APIENTRY *glTexImage1D )( GLenum target, GLint level, GLint components, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels ); - void (APIENTRY *glTexImage2D )( GLenum target, GLint level, GLint components, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels ); - void (APIENTRY *glTexEnvf )( GLenum target, GLenum pname, GLfloat param ); - void (APIENTRY *glTexEnvfv )( GLenum target, GLenum pname, const GLfloat *params ); - void (APIENTRY *glTexEnvi )( GLenum target, GLenum pname, GLint param ); - void (APIENTRY *glTexEnviv )( GLenum target, GLenum pname, const GLint *params ); - void (APIENTRY *glTexGend )( GLenum coord, GLenum pname, GLdouble param ); - void (APIENTRY *glTexGendv )( GLenum coord, GLenum pname, const GLdouble *params ); - void (APIENTRY *glTexGenf )( GLenum coord, GLenum pname, GLfloat param ); - void (APIENTRY *glTexGenfv )( GLenum coord, GLenum pname, const GLfloat *params ); - void (APIENTRY *glTexGeni )( GLenum coord, GLenum pname, GLint param ); - void (APIENTRY *glTexGeniv )( GLenum coord, GLenum pname, const GLint *params ); - void (APIENTRY *glFeedbackBuffer )( GLsizei size, GLenum type, GLfloat *buffer ); - void (APIENTRY *glSelectBuffer )( GLsizei size, GLuint *buffer ); - GLint (APIENTRY *glRenderMode )( GLenum mode ); - void (APIENTRY *glInitNames )( void ); - void (APIENTRY *glLoadName )( GLuint name ); - void (APIENTRY *glPassThrough )( GLfloat token ); - void (APIENTRY *glPopName )( void ); - void (APIENTRY *glPushName )( GLuint name ); - void (APIENTRY *glDrawBuffer )( GLenum mode ); - void (APIENTRY *glClear )( GLbitfield mask ); - void (APIENTRY *glClearAccum )( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha ); - void (APIENTRY *glClearIndex )( GLfloat c ); - void (APIENTRY *glClearColor )( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha ); - void (APIENTRY *glClearStencil )( GLint s ); - void (APIENTRY *glClearDepth )( GLclampd depth ); - void (APIENTRY *glStencilMask )( GLuint mask ); - void (APIENTRY *glColorMask )( GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha ); - void (APIENTRY *glDepthMask )( GLboolean flag ); - void (APIENTRY *glIndexMask )( GLuint mask ); - void (APIENTRY *glAccum )( GLenum op, GLfloat value ); - void (APIENTRY *glDisable )( GLenum cap ); - void (APIENTRY *glEnable )( GLenum cap ); - void (APIENTRY *glFinish )( void ); - void (APIENTRY *glFlush )( void ); - void (APIENTRY *glPopAttrib )( void ); - void (APIENTRY *glPushAttrib )( GLbitfield mask ); - void (APIENTRY *glMap1d )( GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points ); - void (APIENTRY *glMap1f )( GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points ); - void (APIENTRY *glMap2d )( GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points ); - void (APIENTRY *glMap2f )( GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points ); - void (APIENTRY *glMapGrid1d )( GLint un, GLdouble u1, GLdouble u2 ); - void (APIENTRY *glMapGrid1f )( GLint un, GLfloat u1, GLfloat u2 ); - void (APIENTRY *glMapGrid2d )( GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2 ); - void (APIENTRY *glMapGrid2f )( GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2 ); - void (APIENTRY *glEvalCoord1d )( GLdouble u ); - void (APIENTRY *glEvalCoord1dv )( const GLdouble *u ); - void (APIENTRY *glEvalCoord1f )( GLfloat u ); - void (APIENTRY *glEvalCoord1fv )( const GLfloat *u ); - void (APIENTRY *glEvalCoord2d )( GLdouble u, GLdouble v ); - void (APIENTRY *glEvalCoord2dv )( const GLdouble *u ); - void (APIENTRY *glEvalCoord2f )( GLfloat u, GLfloat v ); - void (APIENTRY *glEvalCoord2fv )( const GLfloat *u ); - void (APIENTRY *glEvalMesh1 )( GLenum mode, GLint i1, GLint i2 ); - void (APIENTRY *glEvalPoint1 )( GLint i ); - void (APIENTRY *glEvalMesh2 )( GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2 ); - void (APIENTRY *glEvalPoint2 )( GLint i, GLint j ); - void (APIENTRY *glAlphaFunc )( GLenum func, GLclampf ref ); - void (APIENTRY *glBlendFunc )( GLenum sfactor, GLenum dfactor ); - void (APIENTRY *glLogicOp )( GLenum opcode ); - void (APIENTRY *glStencilFunc )( GLenum func, GLint ref, GLuint mask ); - void (APIENTRY *glStencilOp )( GLenum fail, GLenum zfail, GLenum zpass ); - void (APIENTRY *glDepthFunc )( GLenum func ); - void (APIENTRY *glPixelZoom )( GLfloat xfactor, GLfloat yfactor ); - void (APIENTRY *glPixelTransferf )( GLenum pname, GLfloat param ); - void (APIENTRY *glPixelTransferi )( GLenum pname, GLint param ); - void (APIENTRY *glPixelStoref )( GLenum pname, GLfloat param ); - void (APIENTRY *glPixelStorei )( GLenum pname, GLint param ); - void (APIENTRY *glPixelMapfv )( GLenum map, GLint mapsize, const GLfloat *values ); - void (APIENTRY *glPixelMapuiv )( GLenum map, GLint mapsize, const GLuint *values ); - void (APIENTRY *glPixelMapusv )( GLenum map, GLint mapsize, const GLushort *values ); - void (APIENTRY *glReadBuffer )( GLenum mode ); - void (APIENTRY *glCopyPixels )( GLint x, GLint y, GLsizei width, GLsizei height, GLenum type ); - void (APIENTRY *glReadPixels )( GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels ); - void (APIENTRY *glDrawPixels )( GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels ); - void (APIENTRY *glGetBooleanv )( GLenum pname, GLboolean *params ); - void (APIENTRY *glGetClipPlane )( GLenum plane, GLdouble *equation ); - void (APIENTRY *glGetDoublev )( GLenum pname, GLdouble *params ); - GLenum (APIENTRY *glGetError )( void ); - void (APIENTRY *glGetFloatv )( GLenum pname, GLfloat *params ); - void (APIENTRY *glGetIntegerv )( GLenum pname, GLint *params ); - void (APIENTRY *glGetLightfv )( GLenum light, GLenum pname, GLfloat *params ); - void (APIENTRY *glGetLightiv )( GLenum light, GLenum pname, GLint *params ); - void (APIENTRY *glGetMapdv )( GLenum target, GLenum query, GLdouble *v ); - void (APIENTRY *glGetMapfv )( GLenum target, GLenum query, GLfloat *v ); - void (APIENTRY *glGetMapiv )( GLenum target, GLenum query, GLint *v ); - void (APIENTRY *glGetMaterialfv )( GLenum face, GLenum pname, GLfloat *params ); - void (APIENTRY *glGetMaterialiv )( GLenum face, GLenum pname, GLint *params ); - void (APIENTRY *glGetPixelMapfv )( GLenum map, GLfloat *values ); - void (APIENTRY *glGetPixelMapuiv )( GLenum map, GLuint *values ); - void (APIENTRY *glGetPixelMapusv )( GLenum map, GLushort *values ); - void (APIENTRY *glGetPolygonStipple )( GLubyte *mask ); - const GLubyte * (APIENTRY *glGetString )( GLenum name ); - void (APIENTRY *glGetTexEnvfv )( GLenum target, GLenum pname, GLfloat *params ); - void (APIENTRY *glGetTexEnviv )( GLenum target, GLenum pname, GLint *params ); - void (APIENTRY *glGetTexGendv )( GLenum coord, GLenum pname, GLdouble *params ); - void (APIENTRY *glGetTexGenfv )( GLenum coord, GLenum pname, GLfloat *params ); - void (APIENTRY *glGetTexGeniv )( GLenum coord, GLenum pname, GLint *params ); - void (APIENTRY *glGetTexImage )( GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels ); - void (APIENTRY *glGetTexParameterfv )( GLenum target, GLenum pname, GLfloat *params ); - void (APIENTRY *glGetTexParameteriv )( GLenum target, GLenum pname, GLint *params ); - void (APIENTRY *glGetTexLevelParameterfv )( GLenum target, GLint level, GLenum pname, GLfloat *params ); - void (APIENTRY *glGetTexLevelParameteriv )( GLenum target, GLint level, GLenum pname, GLint *params ); - GLboolean (APIENTRY *glIsEnabled )( GLenum cap ); - GLboolean (APIENTRY *glIsList )( GLuint list ); - void (APIENTRY *glDepthRange )( GLclampd zNear, GLclampd zFar ); - void (APIENTRY *glFrustum )( GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar ); - void (APIENTRY *glLoadIdentity )( void ); - void (APIENTRY *glLoadMatrixf )( const GLfloat *m ); - void (APIENTRY *glLoadMatrixd )( const GLdouble *m ); - void (APIENTRY *glMatrixMode )( GLenum mode ); - void (APIENTRY *glMultMatrixf )( const GLfloat *m ); - void (APIENTRY *glMultMatrixd )( const GLdouble *m ); - void (APIENTRY *glOrtho )( GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar ); - void (APIENTRY *glPopMatrix )( void ); - void (APIENTRY *glPushMatrix )( void ); - void (APIENTRY *glRotated )( GLdouble angle, GLdouble x, GLdouble y, GLdouble z ); - void (APIENTRY *glRotatef )( GLfloat angle, GLfloat x, GLfloat y, GLfloat z ); - void (APIENTRY *glScaled )( GLdouble x, GLdouble y, GLdouble z ); - void (APIENTRY *glScalef )( GLfloat x, GLfloat y, GLfloat z ); - void (APIENTRY *glTranslated )( GLdouble x, GLdouble y, GLdouble z ); - void (APIENTRY *glTranslatef )( GLfloat x, GLfloat y, GLfloat z ); - void (APIENTRY *glViewport )( GLint x, GLint y, GLsizei width, GLsizei height ); - // OpenGL version 1.0 entries end here - - // OpenGL version 1.1 entries begin here - void (APIENTRY *glArrayElement )(GLint i); - void (APIENTRY *glBindTexture )(GLenum target, GLuint texture); - void (APIENTRY *glColorPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); - void (APIENTRY *glDisableClientState )(GLenum array); - void (APIENTRY *glDrawArrays )(GLenum mode, GLint first, GLsizei count); - void (APIENTRY *glDrawElements )(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); - void (APIENTRY *glEdgeFlagPointer )(GLsizei stride, const GLvoid *pointer); - void (APIENTRY *glEnableClientState )(GLenum array); - void (APIENTRY *glIndexPointer )(GLenum type, GLsizei stride, const GLvoid *pointer); - void (APIENTRY *glIndexub )(GLubyte c); - void (APIENTRY *glIndexubv )(const GLubyte *c); - void (APIENTRY *glInterleavedArrays )(GLenum format, GLsizei stride, const GLvoid *pointer); - void (APIENTRY *glNormalPointer )(GLenum type, GLsizei stride, const GLvoid *pointer); - void (APIENTRY *glPolygonOffset )(GLfloat factor, GLfloat units); - void (APIENTRY *glTexCoordPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); - void (APIENTRY *glVertexPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); - GLboolean (APIENTRY *glAreTexturesResident )(GLsizei n, const GLuint *textures, GLboolean *residences); - void (APIENTRY *glCopyTexImage1D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border); - void (APIENTRY *glCopyTexImage2D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); - void (APIENTRY *glCopyTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); - void (APIENTRY *glCopyTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); - void (APIENTRY *glDeleteTextures )(GLsizei n, const GLuint *textures); - void (APIENTRY *glGenTextures )(GLsizei n, GLuint *textures); - void (APIENTRY *glGetPointerv )(GLenum pname, GLvoid* *params); - GLboolean (APIENTRY *glIsTexture )(GLuint texture); - void (APIENTRY *glPrioritizeTextures )(GLsizei n, const GLuint *textures, const GLclampf *priorities); - void (APIENTRY *glTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); - void (APIENTRY *glTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); - void (APIENTRY *glPopClientAttrib )(void); - void (APIENTRY *glPushClientAttrib )(GLbitfield mask); -} GLDISPATCHTABLE, *PGLDISPATCHTABLE; - -// OpenGL Client/Driver Procedure Table. - -typedef struct _GLCLTPROCTABLE { - _In_range_(0,OPENGL_VERSION_110_ENTRIES) int cEntries; // Number of function entries in table - GLDISPATCHTABLE glDispatchTable; // OpenGL function dispatch table -} GLCLTPROCTABLE, *PGLCLTPROCTABLE; - -// Driver GLRC handle. - -typedef ULONG DHGLRC; - -// SetProcTable function prototype for DrvSetContext. - -typedef VOID (APIENTRY *PFN_SETPROCTABLE)(PGLCLTPROCTABLE); - -// DrvSetCallbackProcs prototypes -typedef VOID (APIENTRY *PFN_SETCURRENTVALUE)(VOID *pv); -typedef VOID *(APIENTRY *PFN_GETCURRENTVALUE)(VOID); -typedef DHGLRC (APIENTRY *PFN_GETDHGLRC)(HGLRC hrc); -#if WINVER >= 0x600 -typedef struct _PRESENTBUFFERSCB { - IN UINT nVersion; - IN UINT syncType; // See PRESCB_SYNCTYPE_NONE and PRESCB_SYNCTYPE_VSYNC - IN LUID luidAdapter; - IN LPVOID pPrivData; - IN RECT updateRect; // Update rectangle in the coordinate system of the window, whose HDC is passed to PFN_PRESENTBUFFERS -} PRESENTBUFFERSCB, *LPPRESENTBUFFERSCB; -typedef BOOL (APIENTRY *PFN_PRESENTBUFFERS)(HDC hdc, LPPRESENTBUFFERSCB pprsbcbData); -#endif -#if WINVER >= 0xA00 -typedef VOID (APIENTRY *PFN_GETADAPTERLUID)(HDC hdc, OUT LUID* pLuid); -typedef struct _CHECKFULLSCREENSUPPORTCB { - IN UINT nVersion; - IN LUID luidAdapter; - IN UINT hDevice; - IN HMONITOR hMonitor; - OUT UINT VidPnSourceId; -} CHECKFULLSCREENSUPPORTCB, *LPCHECKFULLSCREENSUPPORTCB; -typedef BOOL (APIENTRY *PFN_CHECKFULLSCREENSUPPORT)(HDC hdc, LPCHECKFULLSCREENSUPPORTCB pArgs); -typedef struct _PRESENTTOREDIRECTIONSURFACECB { - IN UINT nVersion; - IN UINT hContext; - IN UINT hSource; - IN UINT hDestination; - IN HANDLE hSharedHandle; - IN UINT64 updateId; - IN RECT updateRect; - IN UINT broadcastContextCount; - IN UINT broadcastContext[64]; - IN UINT broadcastSrcAllocation[64]; - IN UINT broadcastDstAllocation[64]; - IN UINT cbPrivateDriverDataSize; - IN VOID *pPrivateDriverData; -} PRESENTTOREDIRECTIONSURFACECB, *LPPRESENTTOREDIRECTIONSURFACECB; -typedef BOOL (APIENTRY *PFN_PRESENTTOREDIRECTIONSURFACE)(HDC hdc, LPPRESENTTOREDIRECTIONSURFACECB pArgs); -typedef struct _SUBMITPRESENTTOREDIRECTIONSURFACECB { - IN UINT nVersion; - IN HANDLE hSharedHandle; - IN UINT64 updateId; - IN RECT updateRect; - IN UINT broadcastHwQueueCount; - - _Field_size_(broadcastHwQueueCount) - IN UINT *broadcastHwQueue; - - _Field_size_(broadcastHwQueueCount) - IN UINT *broadcastSrcAllocation; - - _Field_size_opt_(broadcastHwQueueCount) - IN UINT *broadcastDstAllocation; - - IN UINT cbPrivateDriverDataSize; - IN VOID *pPrivateDriverData; -} SUBMITPRESENTTOREDIRECTIONSURFACECB, *LPSUBMITPRESENTTOREDIRECTIONSURFACECB; -typedef BOOL (APIENTRY *PFN_SUBMITPRESENTTOREDIRECTIONSURFACE)(HDC hdc, LPSUBMITPRESENTTOREDIRECTIONSURFACECB pArgs); -#endif - -// Note: Structure not referenced directly, simply present to document the expected order/count of -// callbacks received through DrvSetCallbackProcs. -struct WGLCALLBACKS -{ - PFN_SETCURRENTVALUE pfnSetCurrentValue; - PFN_GETCURRENTVALUE pfnGetCurrentValue; - PFN_GETDHGLRC pfnGetDhglrc; - PROC pfnUnused; -#if WINVER >= 0x600 - PFN_PRESENTBUFFERS pfnPresentBuffers; -#endif -#if WINVER >= 0xA00 - PFN_GETADAPTERLUID pfnGetAdapterLuid; - PFN_CHECKFULLSCREENSUPPORT pfnCheckFullscreenSupport; - PFN_PRESENTTOREDIRECTIONSURFACE pfnPresentToRedirectionSurface; - PFN_SUBMITPRESENTTOREDIRECTIONSURFACE pfnSubmitPresentToRedirectionSurface; -#endif -}; - -// Driver context function prototypes. - -BOOL APIENTRY DrvCopyContext(DHGLRC, DHGLRC, UINT); -DHGLRC APIENTRY DrvCreateContext(HDC); -DHGLRC APIENTRY DrvCreateLayerContext(HDC, int); -BOOL APIENTRY DrvDeleteContext(DHGLRC); -PGLCLTPROCTABLE APIENTRY DrvSetContext(HDC,DHGLRC,PFN_SETPROCTABLE); -BOOL APIENTRY DrvReleaseContext(DHGLRC); -BOOL APIENTRY DrvValidateVersion(ULONG); -BOOL APIENTRY DrvShareLists(DHGLRC, DHGLRC); -PROC APIENTRY DrvGetProcAddress(LPCSTR); -VOID APIENTRY DrvSetCallbackProcs(INT, PROC *); // See WGLCALLBACKS for expected order/count per OS. -BOOL APIENTRY DrvDescribeLayerPlane(HDC, INT, INT, UINT, - LPLAYERPLANEDESCRIPTOR); -INT APIENTRY DrvSetLayerPaletteEntries(HDC, INT, INT, INT, - CONST COLORREF *); -INT APIENTRY DrvGetLayerPaletteEntries(HDC, INT, INT, INT, - COLORREF *); -BOOL APIENTRY DrvRealizeLayerPalette(HDC, INT, BOOL); -BOOL APIENTRY DrvSwapLayerBuffers(HDC, UINT); - -#if WINVER >= 0x500 - -typedef struct IDirectDrawSurface *LPDIRECTDRAWSURFACE; -typedef struct _DDSURFACEDESC *LPDDSURFACEDESC; - -DHGLRC APIENTRY DrvCreateDirectDrawContext(HDC, LPDIRECTDRAWSURFACE, - int); -int APIENTRY DrvEnumTextureFormats(int, LPDDSURFACEDESC); -BOOL APIENTRY DrvBindDirectDrawTexture(LPDIRECTDRAWSURFACE); -DWORD APIENTRY DrvSwapMultipleBuffers(UINT cBuffers, - CONST WGLSWAP *pgswap); - -LONG APIENTRY DrvDescribePixelFormat(HDC, INT, ULONG, PIXELFORMATDESCRIPTOR*); -BOOL APIENTRY DrvSetPixelFormat(HDC, LONG); -BOOL APIENTRY DrvSwapBuffers(HDC); - -#endif // WINVER >= 0x500 - -#if WINVER >= 0x600 -typedef struct _PRESENTBUFFERS { - IN HANDLE hSurface; - IN LUID luidAdapter; - IN ULONGLONG ullPresentToken; - IN LPVOID pPrivData; -} PRESENTBUFFERS, *LPPRESENTBUFFERS; -typedef BOOL (APIENTRY *PFN_PRESENTBUFFERS)(HDC hdc, LPPRESENTBUFFERSCB pprsbcbData); - -#define PRESCB_SYNCTYPE_NONE 0 -#define PRESCB_SYNCTYPE_VSYNC 1 - -BOOL APIENTRY DrvPresentBuffers(HDC hdc, LPPRESENTBUFFERS pprsbData); - -#endif - -// Input structure for OPENGL_CMD ExtEscape. - -typedef struct _WNDOBJ WNDOBJ; -typedef struct _XLATEOBJ XLATEOBJ; - -typedef struct _OPENGLCMD -{ - ULONG ulSubEsc; - FLONG fl; - WNDOBJ *pwo; - XLATEOBJ *pxo; -} OPENGLCMD, *POPENGLCMD; - -#if WINVER >= 0x500 - -#define OPENGLCMD_MAXMULTI WGL_SWAPMULTIPLE_MAX - -typedef struct _OPENGLCMDMULTI -{ - ULONG ulSubEsc; - FLONG fl; - ULONG cMulti; - XLATEOBJ *pxo; -} OPENGLCMDMULTI, *POPENGLCMDMULTI; - -#endif // WINVER >= 0x500 - -// Flags for OPENGL_CMD ExtEscape. - -#define OGLCMD_NEEDWNDOBJ 0x01 -#define OGLCMD_NEEDXLATEOBJ 0x02 - -#if WINVER >= 0x500 -#define OGLCMD_MULTIWNDOBJ 0x04 -#endif // WINVER >= 0x500 - -// OPENGL_GETINFO ExtEscape sub-escape numbers. They are defined by Microsoft. - -#define OPENGL_GETINFO_DRVNAME 0 - -// Input structure for OPENGL_GETINFO ExtEscape. - -typedef struct _OPENGLGETINFO -{ - ULONG ulSubEsc; -} OPENGLGETINFO, *POPENGLGETINFO; - -// Input structure for OPENGL_GETINFO_DRVNAME ExtEscape. - -typedef struct _GLDRVNAME -{ - OPENGLGETINFO oglget; -} GLDRVNAME, *PGLDRVNAME; - -// Output structure for OPENGL_GETINFO_DRVNAME ExtEscape. - -typedef struct _GLDRVNAMERET -{ - ULONG ulVersion; // must be 1 for this version - ULONG ulDriverVersion; // driver specific version number - WCHAR awch[MAX_PATH+1]; -} GLDRVNAMERET, *PGLDRVNAMERET; - -#endif /* _GLDRV_ */ diff --git a/src/gallium/state_trackers/wgl/meson.build b/src/gallium/state_trackers/wgl/meson.build deleted file mode 100644 index ce6e9883e00..00000000000 --- a/src/gallium/state_trackers/wgl/meson.build +++ /dev/null @@ -1,57 +0,0 @@ -# Copyright © 2018 Intel Corporation - -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: - -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. - -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -inc_wgl = include_directories('.') -_c_args_wgl = [] -if not with_shared_glapi - # prevent _glapi_* from being declared __declspec(dllimport) - _c_args_wgl += '-D_GLAPI_NO_EXPORTS' -endif - -libwgl = static_library( - 'wgl', - files( - 'stw_context.c', - 'stw_device.c', - 'stw_ext_context.c', - 'stw_ext_extensionsstring.c', - 'stw_ext_pbuffer.c', - 'stw_ext_pixelformat.c', - 'stw_ext_rendertexture.c', - 'stw_ext_swapinterval.c', - 'stw_framebuffer.c', - 'stw_getprocaddress.c', - 'stw_nopfuncs.c', - 'stw_nopfuncs.h', - 'stw_pixelformat.c', - 'stw_st.c', - 'stw_tls.c', - 'stw_wgl.c', - ), - c_args : [ - '-D_GDI32_', # prevent wgl* being declared __declspec(dllimport) - '-DBUILD_GL32', # declare gl* as __declspec(dllexport) in Mesa headers - '-DWIN32_LEAN_AND_MEAN', # http://msdn2.microsoft.com/en-us/library/6dwk3a1z.aspx - _c_args_wgl - ], - include_directories : [ - inc_include, inc_src, inc_gallium, inc_gallium_aux, inc_mapi, inc_mesa, - ], -) diff --git a/src/gallium/state_trackers/wgl/opengl32.def b/src/gallium/state_trackers/wgl/opengl32.def deleted file mode 100644 index c35c23b55e1..00000000000 --- a/src/gallium/state_trackers/wgl/opengl32.def +++ /dev/null @@ -1,388 +0,0 @@ -EXPORTS -; GlmfBeginGlsBlock -; GlmfCloseMetaFile -; GlmfEndGlsBlock -; GlmfEndPlayback -; GlmfInitPlayback -; GlmfPlayGlsRecord - glAccum - glAlphaFunc - glAreTexturesResident - glArrayElement - glBegin - glBindTexture - glBitmap - glBlendFunc - glCallList - glCallLists - glClear - glClearAccum - glClearColor - glClearDepth - glClearIndex - glClearStencil - glClipPlane - glColor3b - glColor3bv - glColor3d - glColor3dv - glColor3f - glColor3fv - glColor3i - glColor3iv - glColor3s - glColor3sv - glColor3ub - glColor3ubv - glColor3ui - glColor3uiv - glColor3us - glColor3usv - glColor4b - glColor4bv - glColor4d - glColor4dv - glColor4f - glColor4fv - glColor4i - glColor4iv - glColor4s - glColor4sv - glColor4ub - glColor4ubv - glColor4ui - glColor4uiv - glColor4us - glColor4usv - glColorMask - glColorMaterial - glColorPointer - glCopyPixels - glCopyTexImage1D - glCopyTexImage2D - glCopyTexSubImage1D - glCopyTexSubImage2D - glCullFace -; glDebugEntry - glDeleteLists - glDeleteTextures - glDepthFunc - glDepthMask - glDepthRange - glDisable - glDisableClientState - glDrawArrays - glDrawBuffer - glDrawElements - glDrawPixels - glEdgeFlag - glEdgeFlagPointer - glEdgeFlagv - glEnable - glEnableClientState - glEnd - glEndList - glEvalCoord1d - glEvalCoord1dv - glEvalCoord1f - glEvalCoord1fv - glEvalCoord2d - glEvalCoord2dv - glEvalCoord2f - glEvalCoord2fv - glEvalMesh1 - glEvalMesh2 - glEvalPoint1 - glEvalPoint2 - glFeedbackBuffer - glFinish - glFlush - glFogf - glFogfv - glFogi - glFogiv - glFrontFace - glFrustum - glGenLists - glGenTextures - glGetBooleanv - glGetClipPlane - glGetDoublev - glGetError - glGetFloatv - glGetIntegerv - glGetLightfv - glGetLightiv - glGetMapdv - glGetMapfv - glGetMapiv - glGetMaterialfv - glGetMaterialiv - glGetPixelMapfv - glGetPixelMapuiv - glGetPixelMapusv - glGetPointerv - glGetPolygonStipple - glGetString - glGetTexEnvfv - glGetTexEnviv - glGetTexGendv - glGetTexGenfv - glGetTexGeniv - glGetTexImage - glGetTexLevelParameterfv - glGetTexLevelParameteriv - glGetTexParameterfv - glGetTexParameteriv - glHint - glIndexMask - glIndexPointer - glIndexd - glIndexdv - glIndexf - glIndexfv - glIndexi - glIndexiv - glIndexs - glIndexsv - glIndexub - glIndexubv - glInitNames - glInterleavedArrays - glIsEnabled - glIsList - glIsTexture - glLightModelf - glLightModelfv - glLightModeli - glLightModeliv - glLightf - glLightfv - glLighti - glLightiv - glLineStipple - glLineWidth - glListBase - glLoadIdentity - glLoadMatrixd - glLoadMatrixf - glLoadName - glLogicOp - glMap1d - glMap1f - glMap2d - glMap2f - glMapGrid1d - glMapGrid1f - glMapGrid2d - glMapGrid2f - glMaterialf - glMaterialfv - glMateriali - glMaterialiv - glMatrixMode - glMultMatrixd - glMultMatrixf - glNewList - glNormal3b - glNormal3bv - glNormal3d - glNormal3dv - glNormal3f - glNormal3fv - glNormal3i - glNormal3iv - glNormal3s - glNormal3sv - glNormalPointer - glOrtho - glPassThrough - glPixelMapfv - glPixelMapuiv - glPixelMapusv - glPixelStoref - glPixelStorei - glPixelTransferf - glPixelTransferi - glPixelZoom - glPointSize - glPolygonMode - glPolygonOffset - glPolygonStipple - glPopAttrib - glPopClientAttrib - glPopMatrix - glPopName - glPrioritizeTextures - glPushAttrib - glPushClientAttrib - glPushMatrix - glPushName - glRasterPos2d - glRasterPos2dv - glRasterPos2f - glRasterPos2fv - glRasterPos2i - glRasterPos2iv - glRasterPos2s - glRasterPos2sv - glRasterPos3d - glRasterPos3dv - glRasterPos3f - glRasterPos3fv - glRasterPos3i - glRasterPos3iv - glRasterPos3s - glRasterPos3sv - glRasterPos4d - glRasterPos4dv - glRasterPos4f - glRasterPos4fv - glRasterPos4i - glRasterPos4iv - glRasterPos4s - glRasterPos4sv - glReadBuffer - glReadPixels - glRectd - glRectdv - glRectf - glRectfv - glRecti - glRectiv - glRects - glRectsv - glRenderMode - glRotated - glRotatef - glScaled - glScalef - glScissor - glSelectBuffer - glShadeModel - glStencilFunc - glStencilMask - glStencilOp - glTexCoord1d - glTexCoord1dv - glTexCoord1f - glTexCoord1fv - glTexCoord1i - glTexCoord1iv - glTexCoord1s - glTexCoord1sv - glTexCoord2d - glTexCoord2dv - glTexCoord2f - glTexCoord2fv - glTexCoord2i - glTexCoord2iv - glTexCoord2s - glTexCoord2sv - glTexCoord3d - glTexCoord3dv - glTexCoord3f - glTexCoord3fv - glTexCoord3i - glTexCoord3iv - glTexCoord3s - glTexCoord3sv - glTexCoord4d - glTexCoord4dv - glTexCoord4f - glTexCoord4fv - glTexCoord4i - glTexCoord4iv - glTexCoord4s - glTexCoord4sv - glTexCoordPointer - glTexEnvf - glTexEnvfv - glTexEnvi - glTexEnviv - glTexGend - glTexGendv - glTexGenf - glTexGenfv - glTexGeni - glTexGeniv - glTexImage1D - glTexImage2D - glTexParameterf - glTexParameterfv - glTexParameteri - glTexParameteriv - glTexSubImage1D - glTexSubImage2D - glTranslated - glTranslatef - glVertex2d - glVertex2dv - glVertex2f - glVertex2fv - glVertex2i - glVertex2iv - glVertex2s - glVertex2sv - glVertex3d - glVertex3dv - glVertex3f - glVertex3fv - glVertex3i - glVertex3iv - glVertex3s - glVertex3sv - glVertex4d - glVertex4dv - glVertex4f - glVertex4fv - glVertex4i - glVertex4iv - glVertex4s - glVertex4sv - glVertexPointer - glViewport - wglChoosePixelFormat - wglCopyContext - wglCreateContext - wglCreateLayerContext - wglDeleteContext - wglDescribeLayerPlane - wglDescribePixelFormat - wglGetCurrentContext - wglGetCurrentDC -; wglGetDefaultProcAddress - wglGetLayerPaletteEntries - wglGetPixelFormat - wglGetProcAddress - wglMakeCurrent - wglRealizeLayerPalette - wglSetLayerPaletteEntries - wglSetPixelFormat - wglShareLists - wglSwapBuffers - wglSwapLayerBuffers - wglSwapMultipleBuffers - wglUseFontBitmapsA - wglUseFontBitmapsW - wglUseFontOutlinesA - wglUseFontOutlinesW - DrvCopyContext - DrvCreateContext - DrvCreateLayerContext - DrvDeleteContext - DrvDescribeLayerPlane - DrvDescribePixelFormat - DrvGetLayerPaletteEntries - DrvGetProcAddress - DrvPresentBuffers - DrvRealizeLayerPalette - DrvReleaseContext - DrvSetCallbackProcs - DrvSetContext - DrvSetLayerPaletteEntries - DrvSetPixelFormat - DrvShareLists - DrvSwapBuffers - DrvSwapLayerBuffers - DrvValidateVersion diff --git a/src/gallium/state_trackers/wgl/opengl32.mingw.def b/src/gallium/state_trackers/wgl/opengl32.mingw.def deleted file mode 100644 index 0bceee06979..00000000000 --- a/src/gallium/state_trackers/wgl/opengl32.mingw.def +++ /dev/null @@ -1,388 +0,0 @@ -EXPORTS -; GlmfBeginGlsBlock = GlmfBeginGlsBlock@4 -; GlmfCloseMetaFile = GlmfCloseMetaFile@4 -; GlmfEndGlsBlock = GlmfEndGlsBlock@4 -; GlmfEndPlayback = GlmfEndPlayback@4 -; GlmfInitPlayback = GlmfInitPlayback@12 -; GlmfPlayGlsRecord = GlmfPlayGlsRecord@16 - glAccum = glAccum@8 - glAlphaFunc = glAlphaFunc@8 - glAreTexturesResident = glAreTexturesResident@12 - glArrayElement = glArrayElement@4 - glBegin = glBegin@4 - glBindTexture = glBindTexture@8 - glBitmap = glBitmap@28 - glBlendFunc = glBlendFunc@8 - glCallList = glCallList@4 - glCallLists = glCallLists@12 - glClear = glClear@4 - glClearAccum = glClearAccum@16 - glClearColor = glClearColor@16 - glClearDepth = glClearDepth@8 - glClearIndex = glClearIndex@4 - glClearStencil = glClearStencil@4 - glClipPlane = glClipPlane@8 - glColor3b = glColor3b@12 - glColor3bv = glColor3bv@4 - glColor3d = glColor3d@24 - glColor3dv = glColor3dv@4 - glColor3f = glColor3f@12 - glColor3fv = glColor3fv@4 - glColor3i = glColor3i@12 - glColor3iv = glColor3iv@4 - glColor3s = glColor3s@12 - glColor3sv = glColor3sv@4 - glColor3ub = glColor3ub@12 - glColor3ubv = glColor3ubv@4 - glColor3ui = glColor3ui@12 - glColor3uiv = glColor3uiv@4 - glColor3us = glColor3us@12 - glColor3usv = glColor3usv@4 - glColor4b = glColor4b@16 - glColor4bv = glColor4bv@4 - glColor4d = glColor4d@32 - glColor4dv = glColor4dv@4 - glColor4f = glColor4f@16 - glColor4fv = glColor4fv@4 - glColor4i = glColor4i@16 - glColor4iv = glColor4iv@4 - glColor4s = glColor4s@16 - glColor4sv = glColor4sv@4 - glColor4ub = glColor4ub@16 - glColor4ubv = glColor4ubv@4 - glColor4ui = glColor4ui@16 - glColor4uiv = glColor4uiv@4 - glColor4us = glColor4us@16 - glColor4usv = glColor4usv@4 - glColorMask = glColorMask@16 - glColorMaterial = glColorMaterial@8 - glColorPointer = glColorPointer@16 - glCopyPixels = glCopyPixels@20 - glCopyTexImage1D = glCopyTexImage1D@28 - glCopyTexImage2D = glCopyTexImage2D@32 - glCopyTexSubImage1D = glCopyTexSubImage1D@24 - glCopyTexSubImage2D = glCopyTexSubImage2D@32 - glCullFace = glCullFace@4 -; glDebugEntry = glDebugEntry@8 - glDeleteLists = glDeleteLists@8 - glDeleteTextures = glDeleteTextures@8 - glDepthFunc = glDepthFunc@4 - glDepthMask = glDepthMask@4 - glDepthRange = glDepthRange@16 - glDisable = glDisable@4 - glDisableClientState = glDisableClientState@4 - glDrawArrays = glDrawArrays@12 - glDrawBuffer = glDrawBuffer@4 - glDrawElements = glDrawElements@16 - glDrawPixels = glDrawPixels@20 - glEdgeFlag = glEdgeFlag@4 - glEdgeFlagPointer = glEdgeFlagPointer@8 - glEdgeFlagv = glEdgeFlagv@4 - glEnable = glEnable@4 - glEnableClientState = glEnableClientState@4 - glEnd = glEnd@0 - glEndList = glEndList@0 - glEvalCoord1d = glEvalCoord1d@8 - glEvalCoord1dv = glEvalCoord1dv@4 - glEvalCoord1f = glEvalCoord1f@4 - glEvalCoord1fv = glEvalCoord1fv@4 - glEvalCoord2d = glEvalCoord2d@16 - glEvalCoord2dv = glEvalCoord2dv@4 - glEvalCoord2f = glEvalCoord2f@8 - glEvalCoord2fv = glEvalCoord2fv@4 - glEvalMesh1 = glEvalMesh1@12 - glEvalMesh2 = glEvalMesh2@20 - glEvalPoint1 = glEvalPoint1@4 - glEvalPoint2 = glEvalPoint2@8 - glFeedbackBuffer = glFeedbackBuffer@12 - glFinish = glFinish@0 - glFlush = glFlush@0 - glFogf = glFogf@8 - glFogfv = glFogfv@8 - glFogi = glFogi@8 - glFogiv = glFogiv@8 - glFrontFace = glFrontFace@4 - glFrustum = glFrustum@48 - glGenLists = glGenLists@4 - glGenTextures = glGenTextures@8 - glGetBooleanv = glGetBooleanv@8 - glGetClipPlane = glGetClipPlane@8 - glGetDoublev = glGetDoublev@8 - glGetError = glGetError@0 - glGetFloatv = glGetFloatv@8 - glGetIntegerv = glGetIntegerv@8 - glGetLightfv = glGetLightfv@12 - glGetLightiv = glGetLightiv@12 - glGetMapdv = glGetMapdv@12 - glGetMapfv = glGetMapfv@12 - glGetMapiv = glGetMapiv@12 - glGetMaterialfv = glGetMaterialfv@12 - glGetMaterialiv = glGetMaterialiv@12 - glGetPixelMapfv = glGetPixelMapfv@8 - glGetPixelMapuiv = glGetPixelMapuiv@8 - glGetPixelMapusv = glGetPixelMapusv@8 - glGetPointerv = glGetPointerv@8 - glGetPolygonStipple = glGetPolygonStipple@4 - glGetString = glGetString@4 - glGetTexEnvfv = glGetTexEnvfv@12 - glGetTexEnviv = glGetTexEnviv@12 - glGetTexGendv = glGetTexGendv@12 - glGetTexGenfv = glGetTexGenfv@12 - glGetTexGeniv = glGetTexGeniv@12 - glGetTexImage = glGetTexImage@20 - glGetTexLevelParameterfv = glGetTexLevelParameterfv@16 - glGetTexLevelParameteriv = glGetTexLevelParameteriv@16 - glGetTexParameterfv = glGetTexParameterfv@12 - glGetTexParameteriv = glGetTexParameteriv@12 - glHint = glHint@8 - glIndexMask = glIndexMask@4 - glIndexPointer = glIndexPointer@12 - glIndexd = glIndexd@8 - glIndexdv = glIndexdv@4 - glIndexf = glIndexf@4 - glIndexfv = glIndexfv@4 - glIndexi = glIndexi@4 - glIndexiv = glIndexiv@4 - glIndexs = glIndexs@4 - glIndexsv = glIndexsv@4 - glIndexub = glIndexub@4 - glIndexubv = glIndexubv@4 - glInitNames = glInitNames@0 - glInterleavedArrays = glInterleavedArrays@12 - glIsEnabled = glIsEnabled@4 - glIsList = glIsList@4 - glIsTexture = glIsTexture@4 - glLightModelf = glLightModelf@8 - glLightModelfv = glLightModelfv@8 - glLightModeli = glLightModeli@8 - glLightModeliv = glLightModeliv@8 - glLightf = glLightf@12 - glLightfv = glLightfv@12 - glLighti = glLighti@12 - glLightiv = glLightiv@12 - glLineStipple = glLineStipple@8 - glLineWidth = glLineWidth@4 - glListBase = glListBase@4 - glLoadIdentity = glLoadIdentity@0 - glLoadMatrixd = glLoadMatrixd@4 - glLoadMatrixf = glLoadMatrixf@4 - glLoadName = glLoadName@4 - glLogicOp = glLogicOp@4 - glMap1d = glMap1d@32 - glMap1f = glMap1f@24 - glMap2d = glMap2d@56 - glMap2f = glMap2f@40 - glMapGrid1d = glMapGrid1d@20 - glMapGrid1f = glMapGrid1f@12 - glMapGrid2d = glMapGrid2d@40 - glMapGrid2f = glMapGrid2f@24 - glMaterialf = glMaterialf@12 - glMaterialfv = glMaterialfv@12 - glMateriali = glMateriali@12 - glMaterialiv = glMaterialiv@12 - glMatrixMode = glMatrixMode@4 - glMultMatrixd = glMultMatrixd@4 - glMultMatrixf = glMultMatrixf@4 - glNewList = glNewList@8 - glNormal3b = glNormal3b@12 - glNormal3bv = glNormal3bv@4 - glNormal3d = glNormal3d@24 - glNormal3dv = glNormal3dv@4 - glNormal3f = glNormal3f@12 - glNormal3fv = glNormal3fv@4 - glNormal3i = glNormal3i@12 - glNormal3iv = glNormal3iv@4 - glNormal3s = glNormal3s@12 - glNormal3sv = glNormal3sv@4 - glNormalPointer = glNormalPointer@12 - glOrtho = glOrtho@48 - glPassThrough = glPassThrough@4 - glPixelMapfv = glPixelMapfv@12 - glPixelMapuiv = glPixelMapuiv@12 - glPixelMapusv = glPixelMapusv@12 - glPixelStoref = glPixelStoref@8 - glPixelStorei = glPixelStorei@8 - glPixelTransferf = glPixelTransferf@8 - glPixelTransferi = glPixelTransferi@8 - glPixelZoom = glPixelZoom@8 - glPointSize = glPointSize@4 - glPolygonMode = glPolygonMode@8 - glPolygonOffset = glPolygonOffset@8 - glPolygonStipple = glPolygonStipple@4 - glPopAttrib = glPopAttrib@0 - glPopClientAttrib = glPopClientAttrib@0 - glPopMatrix = glPopMatrix@0 - glPopName = glPopName@0 - glPrioritizeTextures = glPrioritizeTextures@12 - glPushAttrib = glPushAttrib@4 - glPushClientAttrib = glPushClientAttrib@4 - glPushMatrix = glPushMatrix@0 - glPushName = glPushName@4 - glRasterPos2d = glRasterPos2d@16 - glRasterPos2dv = glRasterPos2dv@4 - glRasterPos2f = glRasterPos2f@8 - glRasterPos2fv = glRasterPos2fv@4 - glRasterPos2i = glRasterPos2i@8 - glRasterPos2iv = glRasterPos2iv@4 - glRasterPos2s = glRasterPos2s@8 - glRasterPos2sv = glRasterPos2sv@4 - glRasterPos3d = glRasterPos3d@24 - glRasterPos3dv = glRasterPos3dv@4 - glRasterPos3f = glRasterPos3f@12 - glRasterPos3fv = glRasterPos3fv@4 - glRasterPos3i = glRasterPos3i@12 - glRasterPos3iv = glRasterPos3iv@4 - glRasterPos3s = glRasterPos3s@12 - glRasterPos3sv = glRasterPos3sv@4 - glRasterPos4d = glRasterPos4d@32 - glRasterPos4dv = glRasterPos4dv@4 - glRasterPos4f = glRasterPos4f@16 - glRasterPos4fv = glRasterPos4fv@4 - glRasterPos4i = glRasterPos4i@16 - glRasterPos4iv = glRasterPos4iv@4 - glRasterPos4s = glRasterPos4s@16 - glRasterPos4sv = glRasterPos4sv@4 - glReadBuffer = glReadBuffer@4 - glReadPixels = glReadPixels@28 - glRectd = glRectd@32 - glRectdv = glRectdv@8 - glRectf = glRectf@16 - glRectfv = glRectfv@8 - glRecti = glRecti@16 - glRectiv = glRectiv@8 - glRects = glRects@16 - glRectsv = glRectsv@8 - glRenderMode = glRenderMode@4 - glRotated = glRotated@32 - glRotatef = glRotatef@16 - glScaled = glScaled@24 - glScalef = glScalef@12 - glScissor = glScissor@16 - glSelectBuffer = glSelectBuffer@8 - glShadeModel = glShadeModel@4 - glStencilFunc = glStencilFunc@12 - glStencilMask = glStencilMask@4 - glStencilOp = glStencilOp@12 - glTexCoord1d = glTexCoord1d@8 - glTexCoord1dv = glTexCoord1dv@4 - glTexCoord1f = glTexCoord1f@4 - glTexCoord1fv = glTexCoord1fv@4 - glTexCoord1i = glTexCoord1i@4 - glTexCoord1iv = glTexCoord1iv@4 - glTexCoord1s = glTexCoord1s@4 - glTexCoord1sv = glTexCoord1sv@4 - glTexCoord2d = glTexCoord2d@16 - glTexCoord2dv = glTexCoord2dv@4 - glTexCoord2f = glTexCoord2f@8 - glTexCoord2fv = glTexCoord2fv@4 - glTexCoord2i = glTexCoord2i@8 - glTexCoord2iv = glTexCoord2iv@4 - glTexCoord2s = glTexCoord2s@8 - glTexCoord2sv = glTexCoord2sv@4 - glTexCoord3d = glTexCoord3d@24 - glTexCoord3dv = glTexCoord3dv@4 - glTexCoord3f = glTexCoord3f@12 - glTexCoord3fv = glTexCoord3fv@4 - glTexCoord3i = glTexCoord3i@12 - glTexCoord3iv = glTexCoord3iv@4 - glTexCoord3s = glTexCoord3s@12 - glTexCoord3sv = glTexCoord3sv@4 - glTexCoord4d = glTexCoord4d@32 - glTexCoord4dv = glTexCoord4dv@4 - glTexCoord4f = glTexCoord4f@16 - glTexCoord4fv = glTexCoord4fv@4 - glTexCoord4i = glTexCoord4i@16 - glTexCoord4iv = glTexCoord4iv@4 - glTexCoord4s = glTexCoord4s@16 - glTexCoord4sv = glTexCoord4sv@4 - glTexCoordPointer = glTexCoordPointer@16 - glTexEnvf = glTexEnvf@12 - glTexEnvfv = glTexEnvfv@12 - glTexEnvi = glTexEnvi@12 - glTexEnviv = glTexEnviv@12 - glTexGend = glTexGend@16 - glTexGendv = glTexGendv@12 - glTexGenf = glTexGenf@12 - glTexGenfv = glTexGenfv@12 - glTexGeni = glTexGeni@12 - glTexGeniv = glTexGeniv@12 - glTexImage1D = glTexImage1D@32 - glTexImage2D = glTexImage2D@36 - glTexParameterf = glTexParameterf@12 - glTexParameterfv = glTexParameterfv@12 - glTexParameteri = glTexParameteri@12 - glTexParameteriv = glTexParameteriv@12 - glTexSubImage1D = glTexSubImage1D@28 - glTexSubImage2D = glTexSubImage2D@36 - glTranslated = glTranslated@24 - glTranslatef = glTranslatef@12 - glVertex2d = glVertex2d@16 - glVertex2dv = glVertex2dv@4 - glVertex2f = glVertex2f@8 - glVertex2fv = glVertex2fv@4 - glVertex2i = glVertex2i@8 - glVertex2iv = glVertex2iv@4 - glVertex2s = glVertex2s@8 - glVertex2sv = glVertex2sv@4 - glVertex3d = glVertex3d@24 - glVertex3dv = glVertex3dv@4 - glVertex3f = glVertex3f@12 - glVertex3fv = glVertex3fv@4 - glVertex3i = glVertex3i@12 - glVertex3iv = glVertex3iv@4 - glVertex3s = glVertex3s@12 - glVertex3sv = glVertex3sv@4 - glVertex4d = glVertex4d@32 - glVertex4dv = glVertex4dv@4 - glVertex4f = glVertex4f@16 - glVertex4fv = glVertex4fv@4 - glVertex4i = glVertex4i@16 - glVertex4iv = glVertex4iv@4 - glVertex4s = glVertex4s@16 - glVertex4sv = glVertex4sv@4 - glVertexPointer = glVertexPointer@16 - glViewport = glViewport@16 - wglChoosePixelFormat = wglChoosePixelFormat@8 - wglCopyContext = wglCopyContext@12 - wglCreateContext = wglCreateContext@4 - wglCreateLayerContext = wglCreateLayerContext@8 - wglDeleteContext = wglDeleteContext@4 - wglDescribeLayerPlane = wglDescribeLayerPlane@20 - wglDescribePixelFormat = wglDescribePixelFormat@16 - wglGetCurrentContext = wglGetCurrentContext@0 - wglGetCurrentDC = wglGetCurrentDC@0 -; wglGetDefaultProcAddress = wglGetDefaultProcAddress@4 - wglGetLayerPaletteEntries = wglGetLayerPaletteEntries@20 - wglGetPixelFormat = wglGetPixelFormat@4 - wglGetProcAddress = wglGetProcAddress@4 - wglMakeCurrent = wglMakeCurrent@8 - wglRealizeLayerPalette = wglRealizeLayerPalette@12 - wglSetLayerPaletteEntries = wglSetLayerPaletteEntries@20 - wglSetPixelFormat = wglSetPixelFormat@12 - wglShareLists = wglShareLists@8 - wglSwapBuffers = wglSwapBuffers@4 - wglSwapLayerBuffers = wglSwapLayerBuffers@8 - wglSwapMultipleBuffers = wglSwapMultipleBuffers@8 - wglUseFontBitmapsA = wglUseFontBitmapsA@16 - wglUseFontBitmapsW = wglUseFontBitmapsW@16 - wglUseFontOutlinesA = wglUseFontOutlinesA@32 - wglUseFontOutlinesW = wglUseFontOutlinesW@32 - DrvCopyContext = DrvCopyContext@12 - DrvCreateContext = DrvCreateContext@4 - DrvCreateLayerContext = DrvCreateLayerContext@8 - DrvDeleteContext = DrvDeleteContext@4 - DrvDescribeLayerPlane = DrvDescribeLayerPlane@20 - DrvDescribePixelFormat = DrvDescribePixelFormat@16 - DrvGetLayerPaletteEntries = DrvGetLayerPaletteEntries@20 - DrvGetProcAddress = DrvGetProcAddress@4 - DrvPresentBuffers = DrvPresentBuffers@8 - DrvRealizeLayerPalette = DrvRealizeLayerPalette@12 - DrvReleaseContext = DrvReleaseContext@4 - DrvSetCallbackProcs = DrvSetCallbackProcs@8 - DrvSetContext = DrvSetContext@12 - DrvSetLayerPaletteEntries = DrvSetLayerPaletteEntries@20 - DrvSetPixelFormat = DrvSetPixelFormat@8 - DrvShareLists = DrvShareLists@8 - DrvSwapBuffers = DrvSwapBuffers@4 - DrvSwapLayerBuffers = DrvSwapLayerBuffers@8 - DrvValidateVersion = DrvValidateVersion@4 diff --git a/src/gallium/state_trackers/wgl/stw_context.c b/src/gallium/state_trackers/wgl/stw_context.c deleted file mode 100644 index fe9b2e06e00..00000000000 --- a/src/gallium/state_trackers/wgl/stw_context.c +++ /dev/null @@ -1,954 +0,0 @@ -/************************************************************************** - * - * Copyright 2008 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include - -#define WGL_WGLEXT_PROTOTYPES - -#include -#include - -#include "pipe/p_compiler.h" -#include "pipe/p_context.h" -#include "pipe/p_state.h" -#include "util/u_memory.h" -#include "util/u_atomic.h" -#include "state_tracker/st_api.h" -#include "hud/hud_context.h" - -#include "gldrv.h" -#include "stw_device.h" -#include "stw_winsys.h" -#include "stw_framebuffer.h" -#include "stw_pixelformat.h" -#include "stw_context.h" -#include "stw_tls.h" - - -struct stw_context * -stw_current_context(void) -{ - struct st_context_iface *st; - - st = (stw_dev) ? stw_dev->stapi->get_current(stw_dev->stapi) : NULL; - - return (struct stw_context *) ((st) ? st->st_manager_private : NULL); -} - - -BOOL APIENTRY -DrvCopyContext(DHGLRC dhrcSource, DHGLRC dhrcDest, UINT fuMask) -{ - struct stw_context *src; - struct stw_context *dst; - BOOL ret = FALSE; - - if (!stw_dev) - return FALSE; - - stw_lock_contexts(stw_dev); - - src = stw_lookup_context_locked( dhrcSource ); - dst = stw_lookup_context_locked( dhrcDest ); - - if (src && dst) { - /* FIXME */ - assert(0); - (void) src; - (void) dst; - (void) fuMask; - } - - stw_unlock_contexts(stw_dev); - - return ret; -} - - -BOOL APIENTRY -DrvShareLists(DHGLRC dhglrc1, DHGLRC dhglrc2) -{ - struct stw_context *ctx1; - struct stw_context *ctx2; - BOOL ret = FALSE; - - if (!stw_dev) - return FALSE; - - stw_lock_contexts(stw_dev); - - ctx1 = stw_lookup_context_locked( dhglrc1 ); - ctx2 = stw_lookup_context_locked( dhglrc2 ); - - if (ctx1 && ctx2 && ctx2->st->share) { - ret = ctx2->st->share(ctx2->st, ctx1->st); - ctx1->shared = TRUE; - ctx2->shared = TRUE; - } - - stw_unlock_contexts(stw_dev); - - return ret; -} - - -DHGLRC APIENTRY -DrvCreateContext(HDC hdc) -{ - return DrvCreateLayerContext( hdc, 0 ); -} - - -DHGLRC APIENTRY -DrvCreateLayerContext(HDC hdc, INT iLayerPlane) -{ - return stw_create_context_attribs(hdc, iLayerPlane, 0, 1, 0, 0, - WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, - 0); -} - - -/** - * Return the stw pixel format that most closely matches the pixel format - * on HDC. - * Used to get a pixel format when SetPixelFormat() hasn't been called before. - */ -static int -get_matching_pixel_format(HDC hdc) -{ - int iPixelFormat = GetPixelFormat(hdc); - PIXELFORMATDESCRIPTOR pfd; - - if (!iPixelFormat) - return 0; - if (!DescribePixelFormat(hdc, iPixelFormat, sizeof(pfd), &pfd)) - return 0; - return stw_pixelformat_choose(hdc, &pfd); -} - - -/** - * Called via DrvCreateContext(), DrvCreateLayerContext() and - * wglCreateContextAttribsARB() to actually create a rendering context. - * \param handle the desired DHGLRC handle to use for the context, or zero - * if a new handle should be allocated. - * \return the handle for the new context or zero if there was a problem. - */ -DHGLRC -stw_create_context_attribs(HDC hdc, INT iLayerPlane, DHGLRC hShareContext, - int majorVersion, int minorVersion, - int contextFlags, int profileMask, - DHGLRC handle) -{ - int iPixelFormat; - struct stw_framebuffer *fb; - const struct stw_pixelformat_info *pfi; - struct st_context_attribs attribs; - struct stw_context *ctx = NULL; - struct stw_context *shareCtx = NULL; - enum st_context_error ctx_err = 0; - - if (!stw_dev) - return 0; - - if (iLayerPlane != 0) - return 0; - - /* - * GDI only knows about displayable pixel formats, so determine the pixel - * format from the framebuffer. - * - * This also allows to use a OpenGL DLL / ICD without installing. - */ - fb = stw_framebuffer_from_hdc( hdc ); - if (fb) { - iPixelFormat = fb->iPixelFormat; - stw_framebuffer_unlock(fb); - } else { - /* Applications should call SetPixelFormat before creating a context, - * but not all do, and the opengl32 runtime seems to use a default - * pixel format in some cases, so use that. - */ - iPixelFormat = get_matching_pixel_format(hdc); - if (!iPixelFormat) - return 0; - } - - pfi = stw_pixelformat_get_info( iPixelFormat ); - - if (hShareContext != 0) { - stw_lock_contexts(stw_dev); - shareCtx = stw_lookup_context_locked( hShareContext ); - shareCtx->shared = TRUE; - stw_unlock_contexts(stw_dev); - } - - ctx = CALLOC_STRUCT( stw_context ); - if (ctx == NULL) - goto no_ctx; - - ctx->hDrawDC = hdc; - ctx->hReadDC = hdc; - ctx->iPixelFormat = iPixelFormat; - ctx->shared = shareCtx != NULL; - - memset(&attribs, 0, sizeof(attribs)); - attribs.visual = pfi->stvis; - attribs.major = majorVersion; - attribs.minor = minorVersion; - if (contextFlags & WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB) - attribs.flags |= ST_CONTEXT_FLAG_FORWARD_COMPATIBLE; - if (contextFlags & WGL_CONTEXT_DEBUG_BIT_ARB) - attribs.flags |= ST_CONTEXT_FLAG_DEBUG; - - switch (profileMask) { - case WGL_CONTEXT_CORE_PROFILE_BIT_ARB: - /* There are no profiles before OpenGL 3.2. The - * WGL_ARB_create_context_profile spec says: - * - * "If the requested OpenGL version is less than 3.2, - * WGL_CONTEXT_PROFILE_MASK_ARB is ignored and the functionality - * of the context is determined solely by the requested version." - */ - if (majorVersion > 3 || (majorVersion == 3 && minorVersion >= 2)) { - attribs.profile = ST_PROFILE_OPENGL_CORE; - break; - } - /* fall-through */ - case WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB: - /* - * The spec also says: - * - * "If version 3.1 is requested, the context returned may implement - * any of the following versions: - * - * * Version 3.1. The GL_ARB_compatibility extension may or may not - * be implemented, as determined by the implementation. - * * The core profile of version 3.2 or greater." - * - * But Mesa doesn't support GL_ARB_compatibility, while most prevalent - * Windows OpenGL implementations do, and unfortunately many Windows - * applications don't check whether they receive or not a context with - * GL_ARB_compatibility, so returning a core profile here does more harm - * than good. - */ - attribs.profile = ST_PROFILE_DEFAULT; - break; - case WGL_CONTEXT_ES_PROFILE_BIT_EXT: - if (majorVersion >= 2) { - attribs.profile = ST_PROFILE_OPENGL_ES2; - } else { - attribs.profile = ST_PROFILE_OPENGL_ES1; - } - break; - default: - assert(0); - goto no_st_ctx; - } - - ctx->st = stw_dev->stapi->create_context(stw_dev->stapi, - stw_dev->smapi, &attribs, &ctx_err, shareCtx ? shareCtx->st : NULL); - if (ctx->st == NULL) - goto no_st_ctx; - - ctx->st->st_manager_private = (void *) ctx; - - if (ctx->st->cso_context) { - ctx->hud = hud_create(ctx->st->cso_context, NULL); - } - - stw_lock_contexts(stw_dev); - if (handle) { - /* We're replacing the context data for this handle. See the - * wglCreateContextAttribsARB() function. - */ - struct stw_context *old_ctx = - stw_lookup_context_locked((unsigned) handle); - if (old_ctx) { - /* free the old context data associated with this handle */ - if (old_ctx->hud) { - hud_destroy(old_ctx->hud, NULL); - } - ctx->st->destroy(old_ctx->st); - FREE(old_ctx); - } - - /* replace table entry */ - handle_table_set(stw_dev->ctx_table, (unsigned) handle, ctx); - } - else { - /* create new table entry */ - handle = (DHGLRC) handle_table_add(stw_dev->ctx_table, ctx); - } - - ctx->dhglrc = handle; - - stw_unlock_contexts(stw_dev); - - if (!ctx->dhglrc) - goto no_hglrc; - - return ctx->dhglrc; - -no_hglrc: - if (ctx->hud) { - hud_destroy(ctx->hud, NULL); - } - ctx->st->destroy(ctx->st); -no_st_ctx: - FREE(ctx); -no_ctx: - return 0; -} - - -BOOL APIENTRY -DrvDeleteContext(DHGLRC dhglrc) -{ - struct stw_context *ctx ; - BOOL ret = FALSE; - - if (!stw_dev) - return FALSE; - - stw_lock_contexts(stw_dev); - ctx = stw_lookup_context_locked(dhglrc); - handle_table_remove(stw_dev->ctx_table, dhglrc); - stw_unlock_contexts(stw_dev); - - if (ctx) { - struct stw_context *curctx = stw_current_context(); - - /* Unbind current if deleting current context. */ - if (curctx == ctx) - stw_dev->stapi->make_current(stw_dev->stapi, NULL, NULL, NULL); - - if (ctx->hud) { - hud_destroy(ctx->hud, NULL); - } - - ctx->st->destroy(ctx->st); - FREE(ctx); - - ret = TRUE; - } - - return ret; -} - - -BOOL APIENTRY -DrvReleaseContext(DHGLRC dhglrc) -{ - struct stw_context *ctx; - - if (!stw_dev) - return FALSE; - - stw_lock_contexts(stw_dev); - ctx = stw_lookup_context_locked( dhglrc ); - stw_unlock_contexts(stw_dev); - - if (!ctx) - return FALSE; - - /* The expectation is that ctx is the same context which is - * current for this thread. We should check that and return False - * if not the case. - */ - if (ctx != stw_current_context()) - return FALSE; - - if (stw_make_current( NULL, NULL, 0 ) == FALSE) - return FALSE; - - return TRUE; -} - - -DHGLRC -stw_get_current_context( void ) -{ - struct stw_context *ctx; - - ctx = stw_current_context(); - if (!ctx) - return 0; - - return ctx->dhglrc; -} - - -HDC -stw_get_current_dc( void ) -{ - struct stw_context *ctx; - - ctx = stw_current_context(); - if (!ctx) - return NULL; - - return ctx->hDrawDC; -} - -HDC -stw_get_current_read_dc( void ) -{ - struct stw_context *ctx; - - ctx = stw_current_context(); - if (!ctx) - return NULL; - - return ctx->hReadDC; -} - -BOOL -stw_make_current(HDC hDrawDC, HDC hReadDC, DHGLRC dhglrc) -{ - struct stw_context *old_ctx = NULL; - struct stw_context *ctx = NULL; - BOOL ret = FALSE; - - if (!stw_dev) - return FALSE; - - old_ctx = stw_current_context(); - if (old_ctx != NULL) { - if (old_ctx->dhglrc == dhglrc) { - if (old_ctx->hDrawDC == hDrawDC && old_ctx->hReadDC == hReadDC) { - /* Return if already current. */ - return TRUE; - } - } else { - if (old_ctx->shared) { - struct pipe_fence_handle *fence = NULL; - old_ctx->st->flush(old_ctx->st, - ST_FLUSH_FRONT | ST_FLUSH_WAIT, &fence, - NULL, NULL); - } - else { - old_ctx->st->flush(old_ctx->st, ST_FLUSH_FRONT, NULL, NULL, NULL); - } - } - } - - if (dhglrc) { - struct stw_framebuffer *fb = NULL; - struct stw_framebuffer *fbRead = NULL; - stw_lock_contexts(stw_dev); - ctx = stw_lookup_context_locked( dhglrc ); - stw_unlock_contexts(stw_dev); - if (!ctx) { - goto fail; - } - - /* This call locks fb's mutex */ - fb = stw_framebuffer_from_hdc( hDrawDC ); - if (fb) { - stw_framebuffer_update(fb); - } - else { - /* Applications should call SetPixelFormat before creating a context, - * but not all do, and the opengl32 runtime seems to use a default - * pixel format in some cases, so we must create a framebuffer for - * those here. - */ - int iPixelFormat = get_matching_pixel_format(hDrawDC); - if (iPixelFormat) - fb = stw_framebuffer_create( hDrawDC, iPixelFormat ); - if (!fb) - goto fail; - } - - if (fb->iPixelFormat != ctx->iPixelFormat) { - stw_framebuffer_unlock(fb); - SetLastError(ERROR_INVALID_PIXEL_FORMAT); - goto fail; - } - - /* Bind the new framebuffer */ - ctx->hDrawDC = hDrawDC; - ctx->hReadDC = hReadDC; - - struct stw_framebuffer *old_fb = ctx->current_framebuffer; - if (old_fb != fb) { - stw_framebuffer_reference_locked(fb); - ctx->current_framebuffer = fb; - } - stw_framebuffer_unlock(fb); - - if (hReadDC) { - if (hReadDC == hDrawDC) { - fbRead = fb; - } - else { - fbRead = stw_framebuffer_from_hdc( hReadDC ); - - if (fbRead) { - stw_framebuffer_update(fbRead); - } - else { - /* Applications should call SetPixelFormat before creating a - * context, but not all do, and the opengl32 runtime seems to - * use a default pixel format in some cases, so we must create - * a framebuffer for those here. - */ - int iPixelFormat = GetPixelFormat(hReadDC); - if (iPixelFormat) - fbRead = stw_framebuffer_create( hReadDC, iPixelFormat ); - if (!fbRead) - goto fail; - } - - if (fbRead->iPixelFormat != ctx->iPixelFormat) { - stw_framebuffer_unlock(fbRead); - SetLastError(ERROR_INVALID_PIXEL_FORMAT); - goto fail; - } - stw_framebuffer_unlock(fbRead); - } - ret = stw_dev->stapi->make_current(stw_dev->stapi, ctx->st, - fb->stfb, fbRead->stfb); - } - else { - /* Note: when we call this function we will wind up in the - * stw_st_framebuffer_validate_locked() function which will incur - * a recursive fb->mutex lock. - */ - ret = stw_dev->stapi->make_current(stw_dev->stapi, ctx->st, - fb->stfb, fb->stfb); - } - - if (old_fb && old_fb != fb) { - stw_lock_framebuffers(stw_dev); - stw_framebuffer_lock(old_fb); - stw_framebuffer_release_locked(old_fb); - stw_unlock_framebuffers(stw_dev); - } - -fail: - if (fb) { - /* fb must be unlocked at this point. */ - assert(!stw_own_mutex(&fb->mutex)); - } - - /* On failure, make the thread's current rendering context not current - * before returning. - */ - if (!ret) { - stw_make_current(NULL, NULL, 0); - } - } else { - ret = stw_dev->stapi->make_current(stw_dev->stapi, NULL, NULL, NULL); - } - - /* Unreference the previous framebuffer if any. It must be done after - * make_current, as it can be referenced inside. - */ - if (old_ctx && old_ctx != ctx) { - struct stw_framebuffer *old_fb = old_ctx->current_framebuffer; - if (old_fb) { - old_ctx->current_framebuffer = NULL; - stw_lock_framebuffers(stw_dev); - stw_framebuffer_lock(old_fb); - stw_framebuffer_release_locked(old_fb); - stw_unlock_framebuffers(stw_dev); - } - } - - return ret; -} - - -/** - * Notify the current context that the framebuffer has become invalid. - */ -void -stw_notify_current_locked( struct stw_framebuffer *fb ) -{ - p_atomic_inc(&fb->stfb->stamp); -} - - -/** - * Although WGL allows different dispatch entrypoints per context - */ -static const GLCLTPROCTABLE cpt = -{ - OPENGL_VERSION_110_ENTRIES, - { - &glNewList, - &glEndList, - &glCallList, - &glCallLists, - &glDeleteLists, - &glGenLists, - &glListBase, - &glBegin, - &glBitmap, - &glColor3b, - &glColor3bv, - &glColor3d, - &glColor3dv, - &glColor3f, - &glColor3fv, - &glColor3i, - &glColor3iv, - &glColor3s, - &glColor3sv, - &glColor3ub, - &glColor3ubv, - &glColor3ui, - &glColor3uiv, - &glColor3us, - &glColor3usv, - &glColor4b, - &glColor4bv, - &glColor4d, - &glColor4dv, - &glColor4f, - &glColor4fv, - &glColor4i, - &glColor4iv, - &glColor4s, - &glColor4sv, - &glColor4ub, - &glColor4ubv, - &glColor4ui, - &glColor4uiv, - &glColor4us, - &glColor4usv, - &glEdgeFlag, - &glEdgeFlagv, - &glEnd, - &glIndexd, - &glIndexdv, - &glIndexf, - &glIndexfv, - &glIndexi, - &glIndexiv, - &glIndexs, - &glIndexsv, - &glNormal3b, - &glNormal3bv, - &glNormal3d, - &glNormal3dv, - &glNormal3f, - &glNormal3fv, - &glNormal3i, - &glNormal3iv, - &glNormal3s, - &glNormal3sv, - &glRasterPos2d, - &glRasterPos2dv, - &glRasterPos2f, - &glRasterPos2fv, - &glRasterPos2i, - &glRasterPos2iv, - &glRasterPos2s, - &glRasterPos2sv, - &glRasterPos3d, - &glRasterPos3dv, - &glRasterPos3f, - &glRasterPos3fv, - &glRasterPos3i, - &glRasterPos3iv, - &glRasterPos3s, - &glRasterPos3sv, - &glRasterPos4d, - &glRasterPos4dv, - &glRasterPos4f, - &glRasterPos4fv, - &glRasterPos4i, - &glRasterPos4iv, - &glRasterPos4s, - &glRasterPos4sv, - &glRectd, - &glRectdv, - &glRectf, - &glRectfv, - &glRecti, - &glRectiv, - &glRects, - &glRectsv, - &glTexCoord1d, - &glTexCoord1dv, - &glTexCoord1f, - &glTexCoord1fv, - &glTexCoord1i, - &glTexCoord1iv, - &glTexCoord1s, - &glTexCoord1sv, - &glTexCoord2d, - &glTexCoord2dv, - &glTexCoord2f, - &glTexCoord2fv, - &glTexCoord2i, - &glTexCoord2iv, - &glTexCoord2s, - &glTexCoord2sv, - &glTexCoord3d, - &glTexCoord3dv, - &glTexCoord3f, - &glTexCoord3fv, - &glTexCoord3i, - &glTexCoord3iv, - &glTexCoord3s, - &glTexCoord3sv, - &glTexCoord4d, - &glTexCoord4dv, - &glTexCoord4f, - &glTexCoord4fv, - &glTexCoord4i, - &glTexCoord4iv, - &glTexCoord4s, - &glTexCoord4sv, - &glVertex2d, - &glVertex2dv, - &glVertex2f, - &glVertex2fv, - &glVertex2i, - &glVertex2iv, - &glVertex2s, - &glVertex2sv, - &glVertex3d, - &glVertex3dv, - &glVertex3f, - &glVertex3fv, - &glVertex3i, - &glVertex3iv, - &glVertex3s, - &glVertex3sv, - &glVertex4d, - &glVertex4dv, - &glVertex4f, - &glVertex4fv, - &glVertex4i, - &glVertex4iv, - &glVertex4s, - &glVertex4sv, - &glClipPlane, - &glColorMaterial, - &glCullFace, - &glFogf, - &glFogfv, - &glFogi, - &glFogiv, - &glFrontFace, - &glHint, - &glLightf, - &glLightfv, - &glLighti, - &glLightiv, - &glLightModelf, - &glLightModelfv, - &glLightModeli, - &glLightModeliv, - &glLineStipple, - &glLineWidth, - &glMaterialf, - &glMaterialfv, - &glMateriali, - &glMaterialiv, - &glPointSize, - &glPolygonMode, - &glPolygonStipple, - &glScissor, - &glShadeModel, - &glTexParameterf, - &glTexParameterfv, - &glTexParameteri, - &glTexParameteriv, - &glTexImage1D, - &glTexImage2D, - &glTexEnvf, - &glTexEnvfv, - &glTexEnvi, - &glTexEnviv, - &glTexGend, - &glTexGendv, - &glTexGenf, - &glTexGenfv, - &glTexGeni, - &glTexGeniv, - &glFeedbackBuffer, - &glSelectBuffer, - &glRenderMode, - &glInitNames, - &glLoadName, - &glPassThrough, - &glPopName, - &glPushName, - &glDrawBuffer, - &glClear, - &glClearAccum, - &glClearIndex, - &glClearColor, - &glClearStencil, - &glClearDepth, - &glStencilMask, - &glColorMask, - &glDepthMask, - &glIndexMask, - &glAccum, - &glDisable, - &glEnable, - &glFinish, - &glFlush, - &glPopAttrib, - &glPushAttrib, - &glMap1d, - &glMap1f, - &glMap2d, - &glMap2f, - &glMapGrid1d, - &glMapGrid1f, - &glMapGrid2d, - &glMapGrid2f, - &glEvalCoord1d, - &glEvalCoord1dv, - &glEvalCoord1f, - &glEvalCoord1fv, - &glEvalCoord2d, - &glEvalCoord2dv, - &glEvalCoord2f, - &glEvalCoord2fv, - &glEvalMesh1, - &glEvalPoint1, - &glEvalMesh2, - &glEvalPoint2, - &glAlphaFunc, - &glBlendFunc, - &glLogicOp, - &glStencilFunc, - &glStencilOp, - &glDepthFunc, - &glPixelZoom, - &glPixelTransferf, - &glPixelTransferi, - &glPixelStoref, - &glPixelStorei, - &glPixelMapfv, - &glPixelMapuiv, - &glPixelMapusv, - &glReadBuffer, - &glCopyPixels, - &glReadPixels, - &glDrawPixels, - &glGetBooleanv, - &glGetClipPlane, - &glGetDoublev, - &glGetError, - &glGetFloatv, - &glGetIntegerv, - &glGetLightfv, - &glGetLightiv, - &glGetMapdv, - &glGetMapfv, - &glGetMapiv, - &glGetMaterialfv, - &glGetMaterialiv, - &glGetPixelMapfv, - &glGetPixelMapuiv, - &glGetPixelMapusv, - &glGetPolygonStipple, - &glGetString, - &glGetTexEnvfv, - &glGetTexEnviv, - &glGetTexGendv, - &glGetTexGenfv, - &glGetTexGeniv, - &glGetTexImage, - &glGetTexParameterfv, - &glGetTexParameteriv, - &glGetTexLevelParameterfv, - &glGetTexLevelParameteriv, - &glIsEnabled, - &glIsList, - &glDepthRange, - &glFrustum, - &glLoadIdentity, - &glLoadMatrixf, - &glLoadMatrixd, - &glMatrixMode, - &glMultMatrixf, - &glMultMatrixd, - &glOrtho, - &glPopMatrix, - &glPushMatrix, - &glRotated, - &glRotatef, - &glScaled, - &glScalef, - &glTranslated, - &glTranslatef, - &glViewport, - &glArrayElement, - &glBindTexture, - &glColorPointer, - &glDisableClientState, - &glDrawArrays, - &glDrawElements, - &glEdgeFlagPointer, - &glEnableClientState, - &glIndexPointer, - &glIndexub, - &glIndexubv, - &glInterleavedArrays, - &glNormalPointer, - &glPolygonOffset, - &glTexCoordPointer, - &glVertexPointer, - &glAreTexturesResident, - &glCopyTexImage1D, - &glCopyTexImage2D, - &glCopyTexSubImage1D, - &glCopyTexSubImage2D, - &glDeleteTextures, - &glGenTextures, - &glGetPointerv, - &glIsTexture, - &glPrioritizeTextures, - &glTexSubImage1D, - &glTexSubImage2D, - &glPopClientAttrib, - &glPushClientAttrib - } -}; - - -PGLCLTPROCTABLE APIENTRY -DrvSetContext(HDC hdc, DHGLRC dhglrc, PFN_SETPROCTABLE pfnSetProcTable) -{ - PGLCLTPROCTABLE r = (PGLCLTPROCTABLE)&cpt; - - if (!stw_make_current(hdc, hdc, dhglrc)) - r = NULL; - - return r; -} diff --git a/src/gallium/state_trackers/wgl/stw_context.h b/src/gallium/state_trackers/wgl/stw_context.h deleted file mode 100644 index b630fc307df..00000000000 --- a/src/gallium/state_trackers/wgl/stw_context.h +++ /dev/null @@ -1,69 +0,0 @@ -/************************************************************************** - * - * Copyright 2008 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#ifndef STW_CONTEXT_H -#define STW_CONTEXT_H - -#include - -struct hud_context; -struct stw_framebuffer; -struct st_context_iface; - -struct stw_context -{ - struct st_context_iface *st; - DHGLRC dhglrc; - int iPixelFormat; - HDC hDrawDC; - HDC hReadDC; - BOOL shared; - - struct stw_framebuffer *current_framebuffer; - - struct hud_context *hud; -}; - -DHGLRC stw_create_context_attribs(HDC hdc, INT iLayerPlane, - DHGLRC hShareContext, - int majorVersion, int minorVersion, - int contextFlags, int profileMask, - DHGLRC handle); - -DHGLRC stw_get_current_context( void ); - -struct stw_context *stw_current_context(void); - -HDC stw_get_current_dc( void ); - -HDC stw_get_current_read_dc( void ); - -BOOL stw_make_current( HDC hDrawDC, HDC hReadDC, DHGLRC dhglrc ); - -void stw_notify_current_locked( struct stw_framebuffer *fb ); - -#endif /* STW_CONTEXT_H */ diff --git a/src/gallium/state_trackers/wgl/stw_device.c b/src/gallium/state_trackers/wgl/stw_device.c deleted file mode 100644 index f5064da9f29..00000000000 --- a/src/gallium/state_trackers/wgl/stw_device.c +++ /dev/null @@ -1,263 +0,0 @@ -/************************************************************************** - * - * Copyright 2008 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include - -#include "glapi/glapi.h" -#include "util/u_debug.h" -#include "util/u_math.h" -#include "util/u_memory.h" -#include "pipe/p_screen.h" - -#include "stw_device.h" -#include "stw_winsys.h" -#include "stw_pixelformat.h" -#include "gldrv.h" -#include "stw_tls.h" -#include "stw_framebuffer.h" -#include "stw_st.h" - - -struct stw_device *stw_dev = NULL; - -static int -stw_get_param(struct st_manager *smapi, - enum st_manager_param param) -{ - switch (param) { - case ST_MANAGER_BROKEN_INVALIDATE: - /* - * Force framebuffer validation on glViewport. - * - * Certain applications, like Rhinoceros 4, uses glReadPixels - * exclusively (never uses SwapBuffers), so framebuffers never get - * resized unless we check on glViewport. - */ - return 1; - default: - return 0; - } -} - - -/** Get the refresh rate for the monitor, in Hz */ -static int -get_refresh_rate(void) -{ - DEVMODE devModes; - - if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &devModes)) { - /* clamp the value, just in case we get garbage */ - return CLAMP(devModes.dmDisplayFrequency, 30, 120); - } - else { - /* reasonable default */ - return 60; - } -} - -static bool -init_screen(const struct stw_winsys *stw_winsys) -{ - struct pipe_screen *screen = stw_winsys->create_screen(); - if (!screen) - return false; - - if (stw_winsys->get_adapter_luid) - stw_winsys->get_adapter_luid(screen, &stw_dev->AdapterLuid); - - stw_dev->smapi->screen = screen; - stw_dev->screen = screen; - - stw_dev->max_2d_length = screen->get_param(screen, - PIPE_CAP_MAX_TEXTURE_2D_SIZE); - return true; -} - -boolean -stw_init(const struct stw_winsys *stw_winsys) -{ - static struct stw_device stw_dev_storage; - - debug_disable_error_message_boxes(); - - assert(!stw_dev); - - stw_tls_init(); - - stw_dev = &stw_dev_storage; - memset(stw_dev, 0, sizeof(*stw_dev)); - - stw_dev->stw_winsys = stw_winsys; - - stw_dev->stapi = stw_st_create_api(); - stw_dev->smapi = CALLOC_STRUCT(st_manager); - if (!stw_dev->stapi || !stw_dev->smapi) - goto error1; - - stw_dev->smapi->get_param = stw_get_param; - - InitializeCriticalSection(&stw_dev->screen_mutex); - InitializeCriticalSection(&stw_dev->ctx_mutex); - InitializeCriticalSection(&stw_dev->fb_mutex); - - stw_dev->ctx_table = handle_table_create(); - if (!stw_dev->ctx_table) { - goto error1; - } - - /* env var override for WGL_EXT_swap_control, useful for testing/debugging */ - const char *s = os_get_option("WGL_SWAP_INTERVAL"); - if (s) { - stw_dev->swap_interval = atoi(s); - } - stw_dev->refresh_rate = get_refresh_rate(); - - stw_dev->initialized = true; - - return TRUE; - -error1: - FREE(stw_dev->smapi); - if (stw_dev->stapi) - stw_dev->stapi->destroy(stw_dev->stapi); - - stw_dev = NULL; - return FALSE; -} - -boolean -stw_init_screen() -{ - EnterCriticalSection(&stw_dev->screen_mutex); - - if (!stw_dev->screen_initialized) { - stw_dev->screen_initialized = true; - if (!init_screen(stw_dev->stw_winsys)) { - LeaveCriticalSection(&stw_dev->screen_mutex); - return false; - } - stw_pixelformat_init(); - } - - LeaveCriticalSection(&stw_dev->screen_mutex); - return stw_dev->screen != NULL; -} - -boolean -stw_init_thread(void) -{ - return stw_tls_init_thread(); -} - - -void -stw_cleanup_thread(void) -{ - stw_tls_cleanup_thread(); -} - - -void -stw_cleanup(void) -{ - DHGLRC dhglrc; - - debug_printf("%s\n", __FUNCTION__); - - if (!stw_dev) - return; - - /* - * Abort cleanup if there are still active contexts. In some situations - * this DLL may be unloaded before the DLL that is using GL contexts is. - */ - stw_lock_contexts(stw_dev); - dhglrc = handle_table_get_first_handle(stw_dev->ctx_table); - stw_unlock_contexts(stw_dev); - if (dhglrc) { - debug_printf("%s: contexts still active -- cleanup aborted\n", __FUNCTION__); - stw_dev = NULL; - return; - } - - handle_table_destroy(stw_dev->ctx_table); - - stw_framebuffer_cleanup(); - - DeleteCriticalSection(&stw_dev->fb_mutex); - DeleteCriticalSection(&stw_dev->ctx_mutex); - DeleteCriticalSection(&stw_dev->screen_mutex); - - if (stw_dev->smapi->destroy) - stw_dev->smapi->destroy(stw_dev->smapi); - - FREE(stw_dev->smapi); - stw_dev->stapi->destroy(stw_dev->stapi); - - stw_dev->screen->destroy(stw_dev->screen); - - /* glapi is statically linked: we can call the local destroy function. */ -#ifdef _GLAPI_NO_EXPORTS - _glapi_destroy_multithread(); -#endif - - stw_tls_cleanup(); - - stw_dev = NULL; -} - - -void APIENTRY -DrvSetCallbackProcs(INT nProcs, PROC *pProcs) -{ - size_t size; - - if (stw_dev == NULL) - return; - - size = MIN2(nProcs * sizeof *pProcs, sizeof stw_dev->callbacks); - memcpy(&stw_dev->callbacks, pProcs, size); - - return; -} - - -BOOL APIENTRY -DrvValidateVersion(ULONG ulVersion) -{ - /* ulVersion is the version reported by the KMD: - * - via D3DKMTQueryAdapterInfo(KMTQAITYPE_UMOPENGLINFO) on WDDM, - * - or ExtEscape on XPDM and can be used to ensure the KMD and OpenGL ICD - * versions match. - * - * We should get the expected version number from the winsys, but for now - * ignore it. - */ - (void)ulVersion; - return TRUE; -} diff --git a/src/gallium/state_trackers/wgl/stw_device.h b/src/gallium/state_trackers/wgl/stw_device.h deleted file mode 100644 index a2cd6c7487c..00000000000 --- a/src/gallium/state_trackers/wgl/stw_device.h +++ /dev/null @@ -1,133 +0,0 @@ -/************************************************************************** - * - * Copyright 2008 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#ifndef STW_DEVICE_H_ -#define STW_DEVICE_H_ - - -#include "pipe/p_compiler.h" -#include "util/u_handle_table.h" -#include -#include "gldrv.h" -#include "stw_pixelformat.h" - - -#define STW_MAX_PIXELFORMATS 256 - - -struct pipe_screen; -struct st_api; -struct st_manager; -struct stw_framebuffer; - -struct stw_device -{ - const struct stw_winsys *stw_winsys; - - CRITICAL_SECTION screen_mutex; - bool screen_initialized; - struct pipe_screen *screen; - - /* Cache some PIPE_CAP_* */ - unsigned max_2d_length; - - struct st_api *stapi; - struct st_manager *smapi; - - LUID AdapterLuid; - - struct stw_pixelformat_info pixelformats[STW_MAX_PIXELFORMATS]; - unsigned pixelformat_count; - unsigned pixelformat_extended_count; - - struct WGLCALLBACKS callbacks; - - CRITICAL_SECTION ctx_mutex; - struct handle_table *ctx_table; - - /* TODO: use an atomic counter to track the number of locked - * stw_framebuffer objects. Assert that the counter is zero when - * trying to lock this mutex. - */ - CRITICAL_SECTION fb_mutex; - struct stw_framebuffer *fb_head; - -#ifdef DEBUG - unsigned long memdbg_no; -#endif - - /** WGL_EXT_swap_control */ - int refresh_rate; - int swap_interval; - - bool initialized; -}; - - -extern struct stw_device *stw_dev; - -boolean -stw_init_screen(void); - -static inline struct stw_context * -stw_lookup_context_locked( DHGLRC dhglrc ) -{ - if (dhglrc == 0 || stw_dev == NULL) - return NULL; - return (struct stw_context *) handle_table_get(stw_dev->ctx_table, dhglrc); -} - - -static inline void -stw_lock_contexts(struct stw_device *stw_dev) -{ - EnterCriticalSection(&stw_dev->ctx_mutex); -} - - -static inline void -stw_unlock_contexts(struct stw_device *stw_dev) -{ - LeaveCriticalSection(&stw_dev->ctx_mutex); -} - - -static inline void -stw_lock_framebuffers(struct stw_device *stw_dev) -{ - EnterCriticalSection(&stw_dev->fb_mutex); -} - - -static inline void -stw_unlock_framebuffers(struct stw_device *stw_dev) -{ - LeaveCriticalSection(&stw_dev->fb_mutex); -} - - -#endif /* STW_DEVICE_H_ */ diff --git a/src/gallium/state_trackers/wgl/stw_ext_context.c b/src/gallium/state_trackers/wgl/stw_ext_context.c deleted file mode 100644 index 4171987f89c..00000000000 --- a/src/gallium/state_trackers/wgl/stw_ext_context.c +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Mesa 3-D graphics library - * - * Copyright (C) 2011 Morgan Armand - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#include -#include - -#define WGL_WGLEXT_PROTOTYPES - -#include -#include - -#include "gldrv.h" -#include "stw_context.h" -#include "stw_device.h" -#include "stw_ext_context.h" - -#include "util/u_debug.h" - - -wglCreateContext_t wglCreateContext_func = 0; -wglDeleteContext_t wglDeleteContext_func = 0; - - -/** - * The implementation of this function is tricky. The OPENGL32.DLL library - * remaps the context IDs returned by our stw_create_context_attribs() - * function to different values returned to the caller of wglCreateContext(). - * That is, DHGLRC (driver) handles are not equivalent to HGLRC (public) - * handles. - * - * So we need to generate a new HGLRC ID here. We do that by calling - * the regular wglCreateContext() function. Then, we replace the newly- - * created stw_context with a new stw_context that reflects the arguments - * to this function. - */ -HGLRC WINAPI -wglCreateContextAttribsARB(HDC hDC, HGLRC hShareContext, const int *attribList) -{ - HGLRC context; - - int majorVersion = 1, minorVersion = 0, layerPlane = 0; - int contextFlags = 0x0; - int profileMask = WGL_CONTEXT_CORE_PROFILE_BIT_ARB; - int i; - BOOL done = FALSE; - const int contextFlagsAll = (WGL_CONTEXT_DEBUG_BIT_ARB | - WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB); - - /* parse attrib_list */ - if (attribList) { - for (i = 0; !done && attribList[i]; i++) { - switch (attribList[i]) { - case WGL_CONTEXT_MAJOR_VERSION_ARB: - majorVersion = attribList[++i]; - break; - case WGL_CONTEXT_MINOR_VERSION_ARB: - minorVersion = attribList[++i]; - break; - case WGL_CONTEXT_LAYER_PLANE_ARB: - layerPlane = attribList[++i]; - break; - case WGL_CONTEXT_FLAGS_ARB: - contextFlags = attribList[++i]; - break; - case WGL_CONTEXT_PROFILE_MASK_ARB: - profileMask = attribList[++i]; - break; - case 0: - /* end of list */ - done = TRUE; - break; - default: - /* bad attribute */ - SetLastError(ERROR_INVALID_PARAMETER); - return 0; - } - } - } - - /* check contextFlags */ - if (contextFlags & ~contextFlagsAll) { - SetLastError(ERROR_INVALID_PARAMETER); - return NULL; - } - - /* check profileMask */ - if (profileMask != WGL_CONTEXT_CORE_PROFILE_BIT_ARB && - profileMask != WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB && - profileMask != WGL_CONTEXT_ES_PROFILE_BIT_EXT) { - SetLastError(ERROR_INVALID_PROFILE_ARB); - return NULL; - } - - /* check version (generate ERROR_INVALID_VERSION_ARB if bad) */ - if (majorVersion <= 0 || - minorVersion < 0 || - (profileMask != WGL_CONTEXT_ES_PROFILE_BIT_EXT && - ((majorVersion == 1 && minorVersion > 5) || - (majorVersion == 2 && minorVersion > 1) || - (majorVersion == 3 && minorVersion > 3) || - (majorVersion == 4 && minorVersion > 5) || - majorVersion > 4)) || - (profileMask == WGL_CONTEXT_ES_PROFILE_BIT_EXT && - ((majorVersion == 1 && minorVersion > 1) || - (majorVersion == 2 && minorVersion > 0) || - (majorVersion == 3 && minorVersion > 1) || - majorVersion > 3))) { - SetLastError(ERROR_INVALID_VERSION_ARB); - return NULL; - } - - if ((contextFlags & WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB) && - majorVersion < 3) { - SetLastError(ERROR_INVALID_VERSION_ARB); - return 0; - } - - /* Get pointer to OPENGL32.DLL's wglCreate/DeleteContext() functions */ - if (!wglCreateContext_func || !wglDeleteContext_func) { - /* Get the OPENGL32.DLL library */ - HMODULE opengl_lib = GetModuleHandleA("opengl32.dll"); - if (!opengl_lib) { - _debug_printf("wgl: GetModuleHandleA(\"opengl32.dll\") failed\n"); - return 0; - } - - /* Get pointer to wglCreateContext() function */ - wglCreateContext_func = (wglCreateContext_t) - GetProcAddress(opengl_lib, "wglCreateContext"); - if (!wglCreateContext_func) { - _debug_printf("wgl: failed to get wglCreateContext()\n"); - return 0; - } - - /* Get pointer to wglDeleteContext() function */ - wglDeleteContext_func = (wglDeleteContext_t) - GetProcAddress(opengl_lib, "wglDeleteContext"); - if (!wglDeleteContext_func) { - _debug_printf("wgl: failed to get wglDeleteContext()\n"); - return 0; - } - } - - /* Call wglCreateContext to get a valid context ID */ - context = wglCreateContext_func(hDC); - - if (context) { - /* Now replace the context we just created with a new one that reflects - * the attributes passed to this function. - */ - DHGLRC dhglrc, c, share_dhglrc = 0; - - /* Convert public HGLRC to driver DHGLRC */ - if (stw_dev && stw_dev->callbacks.pfnGetDhglrc) { - dhglrc = stw_dev->callbacks.pfnGetDhglrc(context); - if (hShareContext) - share_dhglrc = stw_dev->callbacks.pfnGetDhglrc(hShareContext); - } - else { - /* not using ICD */ - dhglrc = (DHGLRC)(INT_PTR)context; - share_dhglrc = (DHGLRC)(INT_PTR)hShareContext; - } - - c = stw_create_context_attribs(hDC, layerPlane, share_dhglrc, - majorVersion, minorVersion, - contextFlags, profileMask, - dhglrc); - if (!c) { - wglDeleteContext_func(context); - context = 0; - } - } - - return context; -} - - -/** Defined by WGL_ARB_make_current_read */ -BOOL APIENTRY -wglMakeContextCurrentARB(HDC hDrawDC, HDC hReadDC, HGLRC hglrc) -{ - DHGLRC dhglrc = 0; - - if (stw_dev && stw_dev->callbacks.pfnGetDhglrc) { - /* Convert HGLRC to DHGLRC */ - dhglrc = stw_dev->callbacks.pfnGetDhglrc(hglrc); - } - - return stw_make_current(hDrawDC, hReadDC, dhglrc); -} diff --git a/src/gallium/state_trackers/wgl/stw_ext_context.h b/src/gallium/state_trackers/wgl/stw_ext_context.h deleted file mode 100644 index d0337490436..00000000000 --- a/src/gallium/state_trackers/wgl/stw_ext_context.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Mesa 3-D graphics library - * - * Copyright (C) 2011 Morgan Armand - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef STW_EXT_CONTEXT_H -#define STW_EXT_CONTEXT_H - -#include -#include - - -typedef HGLRC (WINAPI *wglCreateContext_t)(HDC hdc); -typedef BOOL (WINAPI *wglDeleteContext_t)(HGLRC hglrc); - -extern wglCreateContext_t wglCreateContext_func; -extern wglDeleteContext_t wglDeleteContext_func; - -#endif /* STW_EXT_CONTEXT_H */ diff --git a/src/gallium/state_trackers/wgl/stw_ext_extensionsstring.c b/src/gallium/state_trackers/wgl/stw_ext_extensionsstring.c deleted file mode 100644 index 904ac151490..00000000000 --- a/src/gallium/state_trackers/wgl/stw_ext_extensionsstring.c +++ /dev/null @@ -1,68 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 VMware, Inc. - * Copyright 2008 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include - -#define WGL_WGLEXT_PROTOTYPES - -#include -#include - - -static const char *stw_extension_string = - "WGL_ARB_create_context " - "WGL_ARB_create_context_profile " - "WGL_ARB_extensions_string " - "WGL_ARB_make_current_read " - "WGL_ARB_multisample " - "WGL_ARB_pbuffer " - "WGL_ARB_pixel_format " - "WGL_ARB_render_texture " - "WGL_EXT_create_context_es_profile " - "WGL_EXT_create_context_es2_profile " - "WGL_EXT_extensions_string " - "WGL_EXT_swap_control"; - - -WINGDIAPI const char * APIENTRY -wglGetExtensionsStringARB( - HDC hdc ) -{ - if (!hdc) { - return NULL; - } - - return stw_extension_string; -} - - -WINGDIAPI const char * APIENTRY -wglGetExtensionsStringEXT( void ) -{ - return stw_extension_string; -} diff --git a/src/gallium/state_trackers/wgl/stw_ext_pbuffer.c b/src/gallium/state_trackers/wgl/stw_ext_pbuffer.c deleted file mode 100644 index 02ccb76e277..00000000000 --- a/src/gallium/state_trackers/wgl/stw_ext_pbuffer.c +++ /dev/null @@ -1,377 +0,0 @@ -/************************************************************************** - * - * Copyright 2010 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include - -#define WGL_WGLEXT_PROTOTYPES - -#include -#include - -#include "pipe/p_defines.h" -#include "pipe/p_screen.h" - -#include "util/u_debug.h" - -#include "stw_device.h" -#include "stw_pixelformat.h" -#include "stw_framebuffer.h" - - -#define LARGE_WINDOW_SIZE 60000 - - -static LRESULT CALLBACK -WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - MINMAXINFO *pMMI; - switch (uMsg) { - case WM_GETMINMAXINFO: - // Allow to create a window bigger than the desktop - pMMI = (MINMAXINFO *)lParam; - pMMI->ptMaxSize.x = LARGE_WINDOW_SIZE; - pMMI->ptMaxSize.y = LARGE_WINDOW_SIZE; - pMMI->ptMaxTrackSize.x = LARGE_WINDOW_SIZE; - pMMI->ptMaxTrackSize.y = LARGE_WINDOW_SIZE; - break; - default: - break; - } - - return DefWindowProc(hWnd, uMsg, wParam, lParam); -} - - -HPBUFFERARB WINAPI -wglCreatePbufferARB(HDC hCurrentDC, - int iPixelFormat, - int iWidth, - int iHeight, - const int *piAttribList) -{ - static boolean first = TRUE; - const int *piAttrib; - int useLargest = 0; - const struct stw_pixelformat_info *info; - struct stw_framebuffer *fb; - DWORD dwExStyle; - DWORD dwStyle; - RECT rect; - HWND hWnd; - HDC hDC; - int iDisplayablePixelFormat; - PIXELFORMATDESCRIPTOR pfd; - BOOL bRet; - int textureFormat = WGL_NO_TEXTURE_ARB; - int textureTarget = WGL_NO_TEXTURE_ARB; - BOOL textureMipmap = FALSE; - - info = stw_pixelformat_get_info(iPixelFormat - 1); - if (!info) { - SetLastError(ERROR_INVALID_PIXEL_FORMAT); - return 0; - } - - if (iWidth <= 0 || iHeight <= 0) { - SetLastError(ERROR_INVALID_DATA); - return 0; - } - - if (piAttribList) { - for (piAttrib = piAttribList; *piAttrib; piAttrib++) { - switch (*piAttrib) { - case WGL_PBUFFER_LARGEST_ARB: - piAttrib++; - useLargest = *piAttrib; - break; - case WGL_TEXTURE_FORMAT_ARB: - /* WGL_ARB_render_texture */ - piAttrib++; - textureFormat = *piAttrib; - if (textureFormat != WGL_TEXTURE_RGB_ARB && - textureFormat != WGL_TEXTURE_RGBA_ARB && - textureFormat != WGL_NO_TEXTURE_ARB) { - SetLastError(ERROR_INVALID_DATA); - return 0; - } - break; - case WGL_TEXTURE_TARGET_ARB: - /* WGL_ARB_render_texture */ - piAttrib++; - textureTarget = *piAttrib; - if (textureTarget != WGL_TEXTURE_CUBE_MAP_ARB && - textureTarget != WGL_TEXTURE_1D_ARB && - textureTarget != WGL_TEXTURE_2D_ARB && - textureTarget != WGL_NO_TEXTURE_ARB) { - SetLastError(ERROR_INVALID_DATA); - return 0; - } - break; - case WGL_MIPMAP_TEXTURE_ARB: - /* WGL_ARB_render_texture */ - piAttrib++; - textureMipmap = !!*piAttrib; - break; - default: - SetLastError(ERROR_INVALID_DATA); - debug_printf("wgl: Unsupported attribute 0x%x in %s\n", - *piAttrib, __func__); - return 0; - } - } - } - - if (iWidth > stw_dev->max_2d_length) { - if (useLargest) { - iWidth = stw_dev->max_2d_length; - } else { - SetLastError(ERROR_NO_SYSTEM_RESOURCES); - return 0; - } - } - - if (iHeight > stw_dev->max_2d_length) { - if (useLargest) { - iHeight = stw_dev->max_2d_length; - } else { - SetLastError(ERROR_NO_SYSTEM_RESOURCES); - return 0; - } - } - - /* - * Implement pbuffers through invisible windows - */ - - if (first) { - WNDCLASS wc; - memset(&wc, 0, sizeof wc); - wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1); - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); - wc.lpfnWndProc = WndProc; - wc.lpszClassName = "wglpbuffer"; - wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW; - RegisterClass(&wc); - first = FALSE; - } - - dwExStyle = 0; - dwStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN; - - if (0) { - /* - * Don't hide the window -- useful for debugging what the application is - * drawing - */ - - dwStyle |= WS_VISIBLE | WS_OVERLAPPEDWINDOW; - } else { - dwStyle |= WS_POPUPWINDOW; - } - - rect.left = 0; - rect.top = 0; - rect.right = rect.left + iWidth; - rect.bottom = rect.top + iHeight; - - /* - * The CreateWindowEx parameters are the total (outside) dimensions of the - * window, which can vary with Windows version and user settings. Use - * AdjustWindowRect to get the required total area for the given client area. - * - * AdjustWindowRectEx does not accept WS_OVERLAPPED style (which is defined - * as 0), which means we need to use some other style instead, e.g., - * WS_OVERLAPPEDWINDOW or WS_POPUPWINDOW as above. - */ - - AdjustWindowRectEx(&rect, dwStyle, FALSE, dwExStyle); - - hWnd = CreateWindowEx(dwExStyle, - "wglpbuffer", /* wc.lpszClassName */ - NULL, - dwStyle, - CW_USEDEFAULT, /* x */ - CW_USEDEFAULT, /* y */ - rect.right - rect.left, /* width */ - rect.bottom - rect.top, /* height */ - NULL, - NULL, - NULL, - NULL); - if (!hWnd) { - return 0; - } - -#ifdef DEBUG - /* - * Verify the client area size matches the specified size. - */ - - GetClientRect(hWnd, &rect); - assert(rect.left == 0); - assert(rect.top == 0); - assert(rect.right - rect.left == iWidth); - assert(rect.bottom - rect.top == iHeight); -#endif - - hDC = GetDC(hWnd); - if (!hDC) { - return 0; - } - - /* - * We can't pass non-displayable pixel formats to GDI, which is why we - * create the framebuffer object before calling SetPixelFormat(). - */ - fb = stw_framebuffer_create(hDC, iPixelFormat); - if (!fb) { - SetLastError(ERROR_NO_SYSTEM_RESOURCES); - return NULL; - } - - fb->bPbuffer = TRUE; - - /* WGL_ARB_render_texture fields */ - fb->textureTarget = textureTarget; - fb->textureFormat = textureFormat; - fb->textureMipmap = textureMipmap; - - iDisplayablePixelFormat = fb->iDisplayablePixelFormat; - - stw_framebuffer_unlock(fb); - - /* - * We need to set a displayable pixel format on the hidden window DC - * so that wglCreateContext and wglMakeCurrent are not overruled by GDI. - */ - bRet = SetPixelFormat(hDC, iDisplayablePixelFormat, &pfd); - assert(bRet); - - return (HPBUFFERARB)fb; -} - - -HDC WINAPI -wglGetPbufferDCARB(HPBUFFERARB hPbuffer) -{ - struct stw_framebuffer *fb; - HDC hDC; - - if (!hPbuffer) { - SetLastError(ERROR_INVALID_HANDLE); - return NULL; - } - - fb = stw_framebuffer_from_HPBUFFERARB(hPbuffer); - - hDC = GetDC(fb->hWnd); - - return hDC; -} - - -int WINAPI -wglReleasePbufferDCARB(HPBUFFERARB hPbuffer, - HDC hDC) -{ - struct stw_framebuffer *fb; - - if (!hPbuffer) { - SetLastError(ERROR_INVALID_HANDLE); - return 0; - } - - fb = stw_framebuffer_from_HPBUFFERARB(hPbuffer); - - return ReleaseDC(fb->hWnd, hDC); -} - - -BOOL WINAPI -wglDestroyPbufferARB(HPBUFFERARB hPbuffer) -{ - struct stw_framebuffer *fb; - - if (!hPbuffer) { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - - fb = stw_framebuffer_from_HPBUFFERARB(hPbuffer); - - /* This will destroy all our data */ - return DestroyWindow(fb->hWnd); -} - - -BOOL WINAPI -wglQueryPbufferARB(HPBUFFERARB hPbuffer, - int iAttribute, - int *piValue) -{ - struct stw_framebuffer *fb; - - if (!hPbuffer) { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - - fb = stw_framebuffer_from_HPBUFFERARB(hPbuffer); - - switch (iAttribute) { - case WGL_PBUFFER_WIDTH_ARB: - *piValue = fb->width; - return TRUE; - case WGL_PBUFFER_HEIGHT_ARB: - *piValue = fb->height; - return TRUE; - case WGL_PBUFFER_LOST_ARB: - /* We assume that no content is ever lost due to display mode change */ - *piValue = FALSE; - return TRUE; - /* WGL_ARB_render_texture */ - case WGL_TEXTURE_TARGET_ARB: - *piValue = fb->textureTarget; - return TRUE; - case WGL_TEXTURE_FORMAT_ARB: - *piValue = fb->textureFormat; - return TRUE; - case WGL_MIPMAP_TEXTURE_ARB: - *piValue = fb->textureMipmap; - return TRUE; - case WGL_MIPMAP_LEVEL_ARB: - *piValue = fb->textureLevel; - return TRUE; - case WGL_CUBE_MAP_FACE_ARB: - *piValue = fb->textureFace + WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB; - return TRUE; - default: - SetLastError(ERROR_INVALID_DATA); - return FALSE; - } -} diff --git a/src/gallium/state_trackers/wgl/stw_ext_pixelformat.c b/src/gallium/state_trackers/wgl/stw_ext_pixelformat.c deleted file mode 100644 index 8fc6da1df2e..00000000000 --- a/src/gallium/state_trackers/wgl/stw_ext_pixelformat.c +++ /dev/null @@ -1,518 +0,0 @@ -/************************************************************************** - * - * Copyright 2008 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/** - * @file - * - * WGL_ARB_pixel_format extension implementation. - * - * @sa http://www.opengl.org/registry/specs/ARB/wgl_pixel_format.txt - */ - - -#include - -#define WGL_WGLEXT_PROTOTYPES - -#include -#include - -#include "pipe/p_compiler.h" -#include "util/format/u_format.h" -#include "util/u_memory.h" -#include "stw_device.h" -#include "stw_pixelformat.h" - - -static boolean -stw_query_attrib(int iPixelFormat, int iLayerPlane, int attrib, int *pvalue) -{ - uint count; - const struct stw_pixelformat_info *pfi; - - count = stw_pixelformat_get_extended_count(); - - if (attrib == WGL_NUMBER_PIXEL_FORMATS_ARB) { - *pvalue = (int) count; - return TRUE; - } - - pfi = stw_pixelformat_get_info(iPixelFormat); - if (!pfi) { - return FALSE; - } - - switch (attrib) { - case WGL_DRAW_TO_WINDOW_ARB: - *pvalue = pfi->pfd.dwFlags & PFD_DRAW_TO_WINDOW ? TRUE : FALSE; - return TRUE; - - case WGL_DRAW_TO_BITMAP_ARB: - *pvalue = pfi->pfd.dwFlags & PFD_DRAW_TO_BITMAP ? TRUE : FALSE; - return TRUE; - - case WGL_NEED_PALETTE_ARB: - *pvalue = pfi->pfd.dwFlags & PFD_NEED_PALETTE ? TRUE : FALSE; - return TRUE; - - case WGL_NEED_SYSTEM_PALETTE_ARB: - *pvalue = pfi->pfd.dwFlags & PFD_NEED_SYSTEM_PALETTE ? TRUE : FALSE; - return TRUE; - - case WGL_SWAP_METHOD_ARB: - if (pfi->pfd.dwFlags & PFD_SWAP_COPY) - *pvalue = WGL_SWAP_COPY_ARB; - else if (pfi->pfd.dwFlags & PFD_SWAP_EXCHANGE) - *pvalue = WGL_SWAP_EXCHANGE_EXT; - else - *pvalue = WGL_SWAP_UNDEFINED_ARB; - return TRUE; - - case WGL_SWAP_LAYER_BUFFERS_ARB: - *pvalue = FALSE; - return TRUE; - - case WGL_NUMBER_OVERLAYS_ARB: - *pvalue = 0; - return TRUE; - - case WGL_NUMBER_UNDERLAYS_ARB: - *pvalue = 0; - return TRUE; - - case WGL_BIND_TO_TEXTURE_RGB_ARB: - /* WGL_ARB_render_texture */ - *pvalue = pfi->bindToTextureRGB; - return TRUE; - - case WGL_BIND_TO_TEXTURE_RGBA_ARB: - /* WGL_ARB_render_texture */ - *pvalue = pfi->bindToTextureRGBA; - return TRUE; - } - - if (iLayerPlane != 0) - return FALSE; - - switch (attrib) { - case WGL_ACCELERATION_ARB: - *pvalue = WGL_FULL_ACCELERATION_ARB; - break; - - case WGL_TRANSPARENT_ARB: - *pvalue = FALSE; - break; - - case WGL_TRANSPARENT_RED_VALUE_ARB: - case WGL_TRANSPARENT_GREEN_VALUE_ARB: - case WGL_TRANSPARENT_BLUE_VALUE_ARB: - case WGL_TRANSPARENT_ALPHA_VALUE_ARB: - case WGL_TRANSPARENT_INDEX_VALUE_ARB: - break; - - case WGL_SHARE_DEPTH_ARB: - case WGL_SHARE_STENCIL_ARB: - case WGL_SHARE_ACCUM_ARB: - *pvalue = TRUE; - break; - - case WGL_SUPPORT_GDI_ARB: - *pvalue = pfi->pfd.dwFlags & PFD_SUPPORT_GDI ? TRUE : FALSE; - break; - - case WGL_SUPPORT_OPENGL_ARB: - *pvalue = pfi->pfd.dwFlags & PFD_SUPPORT_OPENGL ? TRUE : FALSE; - break; - - case WGL_DOUBLE_BUFFER_ARB: - *pvalue = pfi->pfd.dwFlags & PFD_DOUBLEBUFFER ? TRUE : FALSE; - break; - - case WGL_STEREO_ARB: - *pvalue = pfi->pfd.dwFlags & PFD_STEREO ? TRUE : FALSE; - break; - - case WGL_PIXEL_TYPE_ARB: - switch (pfi->pfd.iPixelType) { - case PFD_TYPE_RGBA: - if (util_format_is_float(pfi->stvis.color_format)) { - *pvalue = WGL_TYPE_RGBA_FLOAT_ARB; - } - else { - *pvalue = WGL_TYPE_RGBA_ARB; - } - break; - case PFD_TYPE_COLORINDEX: - *pvalue = WGL_TYPE_COLORINDEX_ARB; - break; - default: - return FALSE; - } - break; - - case WGL_COLOR_BITS_ARB: - *pvalue = pfi->pfd.cColorBits; - break; - - case WGL_RED_BITS_ARB: - *pvalue = pfi->pfd.cRedBits; - break; - - case WGL_RED_SHIFT_ARB: - *pvalue = pfi->pfd.cRedShift; - break; - - case WGL_GREEN_BITS_ARB: - *pvalue = pfi->pfd.cGreenBits; - break; - - case WGL_GREEN_SHIFT_ARB: - *pvalue = pfi->pfd.cGreenShift; - break; - - case WGL_BLUE_BITS_ARB: - *pvalue = pfi->pfd.cBlueBits; - break; - - case WGL_BLUE_SHIFT_ARB: - *pvalue = pfi->pfd.cBlueShift; - break; - - case WGL_ALPHA_BITS_ARB: - *pvalue = pfi->pfd.cAlphaBits; - break; - - case WGL_ALPHA_SHIFT_ARB: - *pvalue = pfi->pfd.cAlphaShift; - break; - - case WGL_ACCUM_BITS_ARB: - *pvalue = pfi->pfd.cAccumBits; - break; - - case WGL_ACCUM_RED_BITS_ARB: - *pvalue = pfi->pfd.cAccumRedBits; - break; - - case WGL_ACCUM_GREEN_BITS_ARB: - *pvalue = pfi->pfd.cAccumGreenBits; - break; - - case WGL_ACCUM_BLUE_BITS_ARB: - *pvalue = pfi->pfd.cAccumBlueBits; - break; - - case WGL_ACCUM_ALPHA_BITS_ARB: - *pvalue = pfi->pfd.cAccumAlphaBits; - break; - - case WGL_DEPTH_BITS_ARB: - *pvalue = pfi->pfd.cDepthBits; - break; - - case WGL_STENCIL_BITS_ARB: - *pvalue = pfi->pfd.cStencilBits; - break; - - case WGL_AUX_BUFFERS_ARB: - *pvalue = pfi->pfd.cAuxBuffers; - break; - - case WGL_SAMPLE_BUFFERS_ARB: - *pvalue = (pfi->stvis.samples > 1); - break; - - case WGL_SAMPLES_ARB: - *pvalue = pfi->stvis.samples; - break; - - - /* WGL_ARB_pbuffer */ - - case WGL_MAX_PBUFFER_WIDTH_ARB: - case WGL_MAX_PBUFFER_HEIGHT_ARB: - *pvalue = stw_dev->max_2d_length; - break; - - case WGL_MAX_PBUFFER_PIXELS_ARB: - *pvalue = stw_dev->max_2d_length * stw_dev->max_2d_length; - break; - - case WGL_DRAW_TO_PBUFFER_ARB: - *pvalue = 1; - break; - - - default: - return FALSE; - } - - return TRUE; -} - -struct attrib_match_info -{ - int attribute; - int weight; - BOOL exact; -}; - -static const struct attrib_match_info attrib_match[] = { - /* WGL_ARB_pixel_format */ - { WGL_DRAW_TO_WINDOW_ARB, 0, TRUE }, - { WGL_DRAW_TO_BITMAP_ARB, 0, TRUE }, - { WGL_ACCELERATION_ARB, 0, TRUE }, - { WGL_NEED_PALETTE_ARB, 0, TRUE }, - { WGL_NEED_SYSTEM_PALETTE_ARB, 0, TRUE }, - { WGL_SWAP_LAYER_BUFFERS_ARB, 0, TRUE }, - { WGL_SWAP_METHOD_ARB, 0, TRUE }, - { WGL_NUMBER_OVERLAYS_ARB, 4, FALSE }, - { WGL_NUMBER_UNDERLAYS_ARB, 4, FALSE }, - /*{ WGL_SHARE_DEPTH_ARB, 0, TRUE },*/ /* no overlays -- ignore */ - /*{ WGL_SHARE_STENCIL_ARB, 0, TRUE },*/ /* no overlays -- ignore */ - /*{ WGL_SHARE_ACCUM_ARB, 0, TRUE },*/ /* no overlays -- ignore */ - { WGL_SUPPORT_GDI_ARB, 0, TRUE }, - { WGL_SUPPORT_OPENGL_ARB, 0, TRUE }, - { WGL_DOUBLE_BUFFER_ARB, 0, TRUE }, - { WGL_STEREO_ARB, 0, TRUE }, - { WGL_PIXEL_TYPE_ARB, 0, TRUE }, - { WGL_COLOR_BITS_ARB, 1, FALSE }, - { WGL_RED_BITS_ARB, 1, FALSE }, - { WGL_GREEN_BITS_ARB, 1, FALSE }, - { WGL_BLUE_BITS_ARB, 1, FALSE }, - { WGL_ALPHA_BITS_ARB, 1, FALSE }, - { WGL_ACCUM_BITS_ARB, 1, FALSE }, - { WGL_ACCUM_RED_BITS_ARB, 1, FALSE }, - { WGL_ACCUM_GREEN_BITS_ARB, 1, FALSE }, - { WGL_ACCUM_BLUE_BITS_ARB, 1, FALSE }, - { WGL_ACCUM_ALPHA_BITS_ARB, 1, FALSE }, - { WGL_DEPTH_BITS_ARB, 1, FALSE }, - { WGL_STENCIL_BITS_ARB, 1, FALSE }, - { WGL_AUX_BUFFERS_ARB, 2, FALSE }, - - /* WGL_ARB_multisample */ - { WGL_SAMPLE_BUFFERS_ARB, 2, FALSE }, - { WGL_SAMPLES_ARB, 2, FALSE }, - - /* WGL_ARB_render_texture */ - { WGL_BIND_TO_TEXTURE_RGB_ARB, 0, FALSE }, - { WGL_BIND_TO_TEXTURE_RGBA_ARB, 0, FALSE }, -}; - -struct stw_pixelformat_score -{ - int points; - uint index; -}; - - -static BOOL -score_pixelformats(struct stw_pixelformat_score *scores, - uint count, - int attribute, - int expected_value) -{ - uint i; - const struct attrib_match_info *ami = NULL; - uint index; - - /* Find out if a given attribute should be considered for score calculation. - */ - for (i = 0; i < ARRAY_SIZE(attrib_match); i++) { - if (attrib_match[i].attribute == attribute) { - ami = &attrib_match[i]; - break; - } - } - if (ami == NULL) - return TRUE; - - /* Iterate all pixelformats, query the requested attribute and calculate - * score points. - */ - for (index = 0; index < count; index++) { - int actual_value; - - if (!stw_query_attrib(index + 1, 0, attribute, &actual_value)) - return FALSE; - - if (ami->exact) { - /* For an exact match criteria, if the actual and expected values - * differ, the score is set to 0 points, effectively removing the - * pixelformat from a list of matching pixelformats. - */ - if (actual_value != expected_value) - scores[index].points = 0; - } - else { - /* For a minimum match criteria, if the actual value is smaller than - * the expected value, the pixelformat is rejected (score set to - * 0). However, if the actual value is bigger, the pixelformat is - * given a penalty to favour pixelformats that more closely match the - * expected values. - */ - if (actual_value < expected_value) - scores[index].points = 0; - else if (actual_value > expected_value) - scores[index].points -= (actual_value - expected_value) - * ami->weight; - } - } - - return TRUE; -} - - -WINGDIAPI BOOL APIENTRY -wglChoosePixelFormatARB(HDC hdc, const int *piAttribIList, - const FLOAT *pfAttribFList, UINT nMaxFormats, - int *piFormats, UINT *nNumFormats) -{ - uint count; - struct stw_pixelformat_score *scores; - uint i; - - *nNumFormats = 0; - - /* Allocate and initialize pixelformat score table -- better matches - * have higher scores. Start with a high score and take out penalty - * points for a mismatch when the match does not have to be exact. - * Set a score to 0 if there is a mismatch for an exact match criteria. - */ - count = stw_pixelformat_get_extended_count(); - scores = (struct stw_pixelformat_score *) - MALLOC(count * sizeof(struct stw_pixelformat_score)); - if (scores == NULL) - return FALSE; - for (i = 0; i < count; i++) { - scores[i].points = 0x7fffffff; - scores[i].index = i; - } - - /* Given the attribute list calculate a score for each pixelformat. - */ - if (piAttribIList != NULL) { - while (*piAttribIList != 0) { - if (!score_pixelformats(scores, count, piAttribIList[0], - piAttribIList[1])) { - FREE(scores); - return FALSE; - } - piAttribIList += 2; - } - } - if (pfAttribFList != NULL) { - while (*pfAttribFList != 0) { - if (!score_pixelformats(scores, count, (int) pfAttribFList[0], - (int) pfAttribFList[1])) { - FREE(scores); - return FALSE; - } - pfAttribFList += 2; - } - } - - /* Bubble-sort the resulting scores. Pixelformats with higher scores go - * first. TODO: Find out if there are any patent issues with it. - */ - if (count > 1) { - uint n = count; - boolean swapped; - - do { - swapped = FALSE; - for (i = 1; i < n; i++) { - if (scores[i - 1].points < scores[i].points) { - struct stw_pixelformat_score score = scores[i - 1]; - - scores[i - 1] = scores[i]; - scores[i] = score; - swapped = TRUE; - } - } - n--; - } - while (swapped); - } - - /* Return a list of pixelformats that are the best match. - * Reject pixelformats with non-positive scores. - */ - for (i = 0; i < count; i++) { - if (scores[i].points > 0) { - piFormats[*nNumFormats] = scores[i].index + 1; - (*nNumFormats)++; - if (*nNumFormats >= nMaxFormats) { - break; - } - } - } - - FREE(scores); - return TRUE; -} - - -WINGDIAPI BOOL APIENTRY -wglGetPixelFormatAttribfvARB(HDC hdc, int iPixelFormat, int iLayerPlane, - UINT nAttributes, const int *piAttributes, - FLOAT *pfValues) -{ - UINT i; - - (void) hdc; - - for (i = 0; i < nAttributes; i++) { - int value = 0; - - if (!stw_query_attrib(iPixelFormat, iLayerPlane, - piAttributes[i], &value)) - return FALSE; - pfValues[i] = (FLOAT) value; - } - - return TRUE; -} - - -WINGDIAPI BOOL APIENTRY -wglGetPixelFormatAttribivARB(HDC hdc, int iPixelFormat, int iLayerPlane, - UINT nAttributes, const int *piAttributes, - int *piValues) -{ - UINT i; - - (void) hdc; - - for (i = 0; i < nAttributes; i++) { - if (!stw_query_attrib(iPixelFormat, iLayerPlane, - piAttributes[i], &piValues[i])) - return FALSE; - } - - return TRUE; -} diff --git a/src/gallium/state_trackers/wgl/stw_ext_rendertexture.c b/src/gallium/state_trackers/wgl/stw_ext_rendertexture.c deleted file mode 100644 index 48b2b1f61a4..00000000000 --- a/src/gallium/state_trackers/wgl/stw_ext_rendertexture.c +++ /dev/null @@ -1,264 +0,0 @@ -/************************************************************************** - * Copyright 2015 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include - -#define WGL_WGLEXT_PROTOTYPES - -#include -#include - -#include "state_tracker/st_copytex.h" - -#include "pipe/p_defines.h" -#include "pipe/p_screen.h" -#include "pipe/p_state.h" - -#include "gldrv.h" -#include "stw_context.h" -#include "stw_device.h" -#include "stw_pixelformat.h" -#include "stw_framebuffer.h" -#include "stw_st.h" - - -/** Translate a WGL buffer name to a GLenum */ -static GLenum -translate_ibuffer(int iBuffer) -{ - switch (iBuffer) { - case WGL_FRONT_LEFT_ARB: - return GL_FRONT_LEFT; - case WGL_BACK_LEFT_ARB: - return GL_BACK_LEFT; - case WGL_FRONT_RIGHT_ARB: - return GL_FRONT_RIGHT; - case WGL_BACK_RIGHT_ARB: - return GL_BACK_RIGHT; - case WGL_AUX0_ARB: - return GL_AUX0; - default: - return GL_NONE; - } -} - - -/** Translate a WGL texture target type to a GLenum */ -static GLenum -translate_target(unsigned textureTarget) -{ - switch (textureTarget) { - case WGL_TEXTURE_1D_ARB: - return GL_TEXTURE_1D; - case WGL_TEXTURE_2D_ARB: - return GL_TEXTURE_2D; - case WGL_TEXTURE_CUBE_MAP_ARB: - return GL_TEXTURE_CUBE_MAP; - case WGL_NO_TEXTURE_ARB: - default: - return GL_NONE; - } -} - - -/** Translate a WGL texture format to a GLenum */ -static GLenum -translate_texture_format(unsigned wgl_format) -{ - switch (wgl_format) { - case WGL_TEXTURE_RGB_ARB: - return GL_RGB; - case WGL_TEXTURE_RGBA_ARB: - return GL_RGBA; - case WGL_NO_TEXTURE_ARB: - default: - return GL_NONE; - } -} - - -BOOL WINAPI -wglBindTexImageARB(HPBUFFERARB hPbuffer, int iBuffer) -{ - HDC prevDrawable = stw_get_current_dc(); - HDC prevReadable = stw_get_current_read_dc(); - HDC dc; - struct stw_context *curctx = stw_current_context(); - struct stw_framebuffer *fb; - GLenum texFormat, srcBuffer, target; - boolean retVal; - int pixelFormatSave; - - /* - * Implementation notes: - * Ideally, we'd implement this function with the - * st_context_iface::teximage() function which replaces a specific - * texture image with a different resource (the pbuffer). - * The main problem however, is the pbuffer image is upside down relative - * to the texture image. - * Window system drawing surfaces (windows & pbuffers) are "top to bottom" - * while OpenGL texture images are "bottom to top". One possible solution - * to this is to invert rendering to pbuffers (as we do for renderbuffers) - * but that could lead to other issues (and would require extensive - * testing). - * - * The simple alternative is to use a copy-based approach which copies the - * pbuffer image into the texture via glCopyTex[Sub]Image. That's what - * we do here. - */ - - if (!curctx) { - debug_printf("No rendering context in wglBindTexImageARB()\n"); - SetLastError(ERROR_INVALID_OPERATION); - return FALSE; - } - - fb = stw_framebuffer_from_HPBUFFERARB(hPbuffer); - if (!fb) { - debug_printf("Invalid pbuffer handle in wglBindTexImageARB()\n"); - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - - srcBuffer = translate_ibuffer(iBuffer); - if (srcBuffer == GL_NONE) { - debug_printf("Invalid buffer 0x%x in wglBindTexImageARB()\n", iBuffer); - SetLastError(ERROR_INVALID_DATA); - return FALSE; - } - - target = translate_target(fb->textureTarget); - if (target == GL_NONE) { - debug_printf("no texture target in wglBindTexImageARB()\n"); - return FALSE; - } - - texFormat = translate_texture_format(fb->textureFormat); - if (texFormat == GL_NONE) { - debug_printf("no texture format in wglBindTexImageARB()\n"); - return FALSE; - } - - /* - * Bind the pbuffer surface so we can read/copy from it. - * - * Before we can call stw_make_current() we have to temporarily - * change the pbuffer's pixel format to match the context to avoid - * an error condition. After the stw_make_current() we restore the - * buffer's pixel format. - */ - pixelFormatSave = fb->iPixelFormat; - fb->iPixelFormat = curctx->iPixelFormat; - dc = wglGetPbufferDCARB(hPbuffer); - retVal = stw_make_current(dc, dc, curctx->dhglrc); - fb->iPixelFormat = pixelFormatSave; - if (!retVal) { - debug_printf("stw_make_current(#1) failed in wglBindTexImageARB()\n"); - wglReleasePbufferDCARB(hPbuffer, dc); - return FALSE; - } - - st_copy_framebuffer_to_texture(srcBuffer, fb->width, fb->height, - target, fb->textureLevel, - fb->textureFace, texFormat); - - /* rebind previous drawing surface */ - retVal = stw_make_current(prevDrawable, prevReadable, curctx->dhglrc); - if (!retVal) { - debug_printf("stw_make_current(#2) failed in wglBindTexImageARB()\n"); - } - - wglReleasePbufferDCARB(hPbuffer, dc); - - return retVal; -} - - -BOOL WINAPI -wglReleaseTexImageARB(HPBUFFERARB hPbuffer, int iBuffer) -{ - struct stw_framebuffer *fb = stw_framebuffer_from_HPBUFFERARB(hPbuffer); - GLenum srcBuffer; - - /* nothing to do here, but we do error checking anyway */ - - if (!fb) { - debug_printf("Invalid pbuffer handle in wglReleaseTexImageARB()\n"); - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - - srcBuffer = translate_ibuffer(iBuffer); - if (srcBuffer == GL_NONE) { - debug_printf("Invalid buffer 0x%x in wglReleaseTexImageARB()\n", iBuffer); - SetLastError(ERROR_INVALID_DATA); - return FALSE; - } - - return TRUE; -} - - -BOOL WINAPI -wglSetPbufferAttribARB(HPBUFFERARB hPbuffer, const int *piAttribList) -{ - struct stw_framebuffer *fb = stw_framebuffer_from_HPBUFFERARB(hPbuffer); - int face, i; - - if (!fb) { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - - for (i = 0; piAttribList[i]; i += 2) { - switch (piAttribList[i]) { - case WGL_MIPMAP_LEVEL_ARB: - fb->textureLevel = piAttribList[i+1]; - break; - case WGL_CUBE_MAP_FACE_ARB: - face = piAttribList[i+1]; - if (face >= WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && - face <= WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { - fb->textureFace = face - WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB; - } - else { - debug_printf("Invalid cube face 0x%x in " - "wglSetPbufferAttribARB()\n", - piAttribList[i]); - SetLastError(ERROR_INVALID_DATA); - return FALSE; - } - break; - default: - debug_printf("Invalid attribute 0x%x in wglSetPbufferAttribARB()\n", - piAttribList[i]); - SetLastError(ERROR_INVALID_DATA); - return FALSE; - } - } - - return TRUE; -} diff --git a/src/gallium/state_trackers/wgl/stw_ext_swapinterval.c b/src/gallium/state_trackers/wgl/stw_ext_swapinterval.c deleted file mode 100644 index 3b913e7db93..00000000000 --- a/src/gallium/state_trackers/wgl/stw_ext_swapinterval.c +++ /dev/null @@ -1,62 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 VMware, Inc. - * Copyright 2008 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include - -#define WGL_WGLEXT_PROTOTYPES - -#include -#include -#include "util/u_debug.h" -#include "stw_device.h" - - -/** - * Note that our implementation of swap intervals is a bit of a hack. - * We implement it based on querying the time and Sleep()'ing. We don't - * sync to the vblank. - */ -WINGDIAPI BOOL APIENTRY -wglSwapIntervalEXT(int interval) -{ - if (interval < 0) { - SetLastError(ERROR_INVALID_DATA); - return FALSE; - } - if (stw_dev && !os_get_option("WGL_SWAP_INTERVAL")) { - stw_dev->swap_interval = interval; - } - return TRUE; -} - - -WINGDIAPI int APIENTRY -wglGetSwapIntervalEXT(void) -{ - return stw_dev ? stw_dev->swap_interval : 0; -} diff --git a/src/gallium/state_trackers/wgl/stw_framebuffer.c b/src/gallium/state_trackers/wgl/stw_framebuffer.c deleted file mode 100644 index 4078d95287b..00000000000 --- a/src/gallium/state_trackers/wgl/stw_framebuffer.c +++ /dev/null @@ -1,670 +0,0 @@ -/************************************************************************** - * - * Copyright 2008-2009 Vmware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include - -#include "pipe/p_screen.h" -#include "util/u_memory.h" -#include "hud/hud_context.h" -#include "util/os_time.h" -#include "state_tracker/st_api.h" - -#include -#include "gldrv.h" -#include "stw_framebuffer.h" -#include "stw_device.h" -#include "stw_winsys.h" -#include "stw_tls.h" -#include "stw_context.h" -#include "stw_st.h" - - -/** - * Search the framebuffer with the matching HWND while holding the - * stw_dev::fb_mutex global lock. - * If a stw_framebuffer is found, lock it and return the pointer. - * Else, return NULL. - */ -static struct stw_framebuffer * -stw_framebuffer_from_hwnd_locked(HWND hwnd) -{ - struct stw_framebuffer *fb; - - for (fb = stw_dev->fb_head; fb != NULL; fb = fb->next) - if (fb->hWnd == hwnd) { - stw_framebuffer_lock(fb); - assert(fb->mutex.RecursionCount == 1); - return fb; - } - - return NULL; -} - - -/** - * Decrement the reference count on the given stw_framebuffer object. - * If the reference count hits zero, destroy the object. - * - * Note: Both stw_dev::fb_mutex and stw_framebuffer::mutex must already be - * locked. After this function completes, the fb's mutex will be unlocked. - */ -void -stw_framebuffer_release_locked(struct stw_framebuffer *fb) -{ - struct stw_framebuffer **link; - - assert(fb); - assert(stw_own_mutex(&fb->mutex)); - assert(stw_own_mutex(&stw_dev->fb_mutex)); - - /* check the reference count */ - fb->refcnt--; - if (fb->refcnt) { - stw_framebuffer_unlock(fb); - return; - } - - /* remove this stw_framebuffer from the device's linked list */ - link = &stw_dev->fb_head; - while (*link != fb) - link = &(*link)->next; - assert(*link); - *link = fb->next; - fb->next = NULL; - - if (fb->shared_surface) - stw_dev->stw_winsys->shared_surface_close(stw_dev->screen, - fb->shared_surface); - - stw_st_destroy_framebuffer_locked(fb->stfb); - - stw_framebuffer_unlock(fb); - - DeleteCriticalSection(&fb->mutex); - - FREE( fb ); -} - - -/** - * Query the size of the given framebuffer's on-screen window and update - * the stw_framebuffer's width/height. - */ -static void -stw_framebuffer_get_size(struct stw_framebuffer *fb) -{ - LONG width, height; - RECT client_rect; - RECT window_rect; - POINT client_pos; - - /* - * Sanity checking. - */ - assert(fb->hWnd); - assert(fb->width && fb->height); - assert(fb->client_rect.right == fb->client_rect.left + fb->width); - assert(fb->client_rect.bottom == fb->client_rect.top + fb->height); - - /* - * Get the client area size. - */ - if (!GetClientRect(fb->hWnd, &client_rect)) { - return; - } - - assert(client_rect.left == 0); - assert(client_rect.top == 0); - width = client_rect.right - client_rect.left; - height = client_rect.bottom - client_rect.top; - - fb->minimized = width == 0 || height == 0; - - if (width <= 0 || height <= 0) { - /* - * When the window is minimized GetClientRect will return zeros. Simply - * preserve the current window size, until the window is restored or - * maximized again. - */ - return; - } - - if (width != fb->width || height != fb->height) { - fb->must_resize = TRUE; - fb->width = width; - fb->height = height; - } - - client_pos.x = 0; - client_pos.y = 0; - if (ClientToScreen(fb->hWnd, &client_pos) && - GetWindowRect(fb->hWnd, &window_rect)) { - fb->client_rect.left = client_pos.x - window_rect.left; - fb->client_rect.top = client_pos.y - window_rect.top; - } - - fb->client_rect.right = fb->client_rect.left + fb->width; - fb->client_rect.bottom = fb->client_rect.top + fb->height; - -#if 0 - debug_printf("\n"); - debug_printf("%s: hwnd = %p\n", __FUNCTION__, fb->hWnd); - debug_printf("%s: client_position = (%li, %li)\n", - __FUNCTION__, client_pos.x, client_pos.y); - debug_printf("%s: window_rect = (%li, %li) - (%li, %li)\n", - __FUNCTION__, - window_rect.left, window_rect.top, - window_rect.right, window_rect.bottom); - debug_printf("%s: client_rect = (%li, %li) - (%li, %li)\n", - __FUNCTION__, - fb->client_rect.left, fb->client_rect.top, - fb->client_rect.right, fb->client_rect.bottom); -#endif -} - - -/** - * @sa http://msdn.microsoft.com/en-us/library/ms644975(VS.85).aspx - * @sa http://msdn.microsoft.com/en-us/library/ms644960(VS.85).aspx - */ -LRESULT CALLBACK -stw_call_window_proc(int nCode, WPARAM wParam, LPARAM lParam) -{ - struct stw_tls_data *tls_data; - PCWPSTRUCT pParams = (PCWPSTRUCT)lParam; - struct stw_framebuffer *fb; - - tls_data = stw_tls_get_data(); - if (!tls_data) - return 0; - - if (nCode < 0 || !stw_dev) - return CallNextHookEx(tls_data->hCallWndProcHook, nCode, wParam, lParam); - - /* We check that the stw_dev object is initialized before we try to do - * anything with it. Otherwise, in multi-threaded programs there's a - * chance of executing this code before the stw_dev object is fully - * initialized. - */ - if (stw_dev && stw_dev->initialized) { - if (pParams->message == WM_WINDOWPOSCHANGED) { - /* We handle WM_WINDOWPOSCHANGED instead of WM_SIZE because according - * to http://blogs.msdn.com/oldnewthing/archive/2008/01/15/7113860.aspx - * WM_SIZE is generated from WM_WINDOWPOSCHANGED by DefWindowProc so it - * can be masked out by the application. - */ - LPWINDOWPOS lpWindowPos = (LPWINDOWPOS)pParams->lParam; - if ((lpWindowPos->flags & SWP_SHOWWINDOW) || - !(lpWindowPos->flags & SWP_NOMOVE) || - !(lpWindowPos->flags & SWP_NOSIZE)) { - fb = stw_framebuffer_from_hwnd( pParams->hwnd ); - if (fb) { - /* Size in WINDOWPOS includes the window frame, so get the size - * of the client area via GetClientRect. - */ - stw_framebuffer_get_size(fb); - stw_framebuffer_unlock(fb); - } - } - } - else if (pParams->message == WM_DESTROY) { - stw_lock_framebuffers(stw_dev); - fb = stw_framebuffer_from_hwnd_locked( pParams->hwnd ); - if (fb) - stw_framebuffer_release_locked(fb); - stw_unlock_framebuffers(stw_dev); - } - } - - return CallNextHookEx(tls_data->hCallWndProcHook, nCode, wParam, lParam); -} - - -/** - * Create a new stw_framebuffer object which corresponds to the given - * HDC/window. If successful, we return the new stw_framebuffer object - * with its mutex locked. - */ -struct stw_framebuffer * -stw_framebuffer_create(HDC hdc, int iPixelFormat) -{ - HWND hWnd; - struct stw_framebuffer *fb; - const struct stw_pixelformat_info *pfi; - - /* We only support drawing to a window. */ - hWnd = WindowFromDC( hdc ); - if (!hWnd) - return NULL; - - fb = CALLOC_STRUCT( stw_framebuffer ); - if (fb == NULL) - return NULL; - - fb->hWnd = hWnd; - fb->iPixelFormat = iPixelFormat; - - /* - * We often need a displayable pixel format to make GDI happy. Set it - * here (always 1, i.e., out first pixel format) where appropriate. - */ - fb->iDisplayablePixelFormat = iPixelFormat <= stw_dev->pixelformat_count - ? iPixelFormat : 1; - - fb->pfi = pfi = stw_pixelformat_get_info( iPixelFormat ); - fb->stfb = stw_st_create_framebuffer( fb ); - if (!fb->stfb) { - FREE( fb ); - return NULL; - } - - fb->refcnt = 1; - - /* - * Windows can be sometimes have zero width and or height, but we ensure - * a non-zero framebuffer size at all times. - */ - - fb->must_resize = TRUE; - fb->width = 1; - fb->height = 1; - fb->client_rect.left = 0; - fb->client_rect.top = 0; - fb->client_rect.right = fb->client_rect.left + fb->width; - fb->client_rect.bottom = fb->client_rect.top + fb->height; - - stw_framebuffer_get_size(fb); - - InitializeCriticalSection(&fb->mutex); - - /* This is the only case where we lock the stw_framebuffer::mutex before - * stw_dev::fb_mutex, since no other thread can know about this framebuffer - * and we must prevent any other thread from destroying it before we return. - */ - stw_framebuffer_lock(fb); - - stw_lock_framebuffers(stw_dev); - fb->next = stw_dev->fb_head; - stw_dev->fb_head = fb; - stw_unlock_framebuffers(stw_dev); - - return fb; -} - - -/** - * Update the framebuffer's size if necessary. - */ -void -stw_framebuffer_update(struct stw_framebuffer *fb) -{ - assert(fb->stfb); - assert(fb->height); - assert(fb->width); - - /* XXX: It would be nice to avoid checking the size again -- in theory - * stw_call_window_proc would have cought the resize and stored the right - * size already, but unfortunately threads created before the DllMain is - * called don't get a DLL_THREAD_ATTACH notification, and there is no way - * to know of their existing without using the not very portable PSAPI. - */ - stw_framebuffer_get_size(fb); -} - - -/** - * Try to free all stw_framebuffer objects associated with the device. - */ -void -stw_framebuffer_cleanup(void) -{ - struct stw_framebuffer *fb; - struct stw_framebuffer *next; - - if (!stw_dev) - return; - - stw_lock_framebuffers(stw_dev); - - fb = stw_dev->fb_head; - while (fb) { - next = fb->next; - - stw_framebuffer_lock(fb); - stw_framebuffer_release_locked(fb); - - fb = next; - } - stw_dev->fb_head = NULL; - - stw_unlock_framebuffers(stw_dev); -} - - -/** - * Given an hdc, return the corresponding stw_framebuffer. - * The returned stw_framebuffer will have its mutex locked. - */ -static struct stw_framebuffer * -stw_framebuffer_from_hdc_locked(HDC hdc) -{ - HWND hwnd; - - hwnd = WindowFromDC(hdc); - if (!hwnd) { - return NULL; - } - - return stw_framebuffer_from_hwnd_locked(hwnd); -} - - -/** - * Given an HDC, return the corresponding stw_framebuffer. - * The returned stw_framebuffer will have its mutex locked. - */ -struct stw_framebuffer * -stw_framebuffer_from_hdc(HDC hdc) -{ - struct stw_framebuffer *fb; - - if (!stw_dev) - return NULL; - - stw_lock_framebuffers(stw_dev); - fb = stw_framebuffer_from_hdc_locked(hdc); - stw_unlock_framebuffers(stw_dev); - - return fb; -} - - -/** - * Given an HWND, return the corresponding stw_framebuffer. - * The returned stw_framebuffer will have its mutex locked. - */ -struct stw_framebuffer * -stw_framebuffer_from_hwnd(HWND hwnd) -{ - struct stw_framebuffer *fb; - - stw_lock_framebuffers(stw_dev); - fb = stw_framebuffer_from_hwnd_locked(hwnd); - stw_unlock_framebuffers(stw_dev); - - return fb; -} - - -BOOL APIENTRY -DrvSetPixelFormat(HDC hdc, LONG iPixelFormat) -{ - uint count; - uint index; - struct stw_framebuffer *fb; - - if (!stw_dev) - return FALSE; - - index = (uint) iPixelFormat - 1; - count = stw_pixelformat_get_count(); - if (index >= count) - return FALSE; - - fb = stw_framebuffer_from_hdc_locked(hdc); - if (fb) { - /* - * SetPixelFormat must be called only once. However ignore - * pbuffers, for which the framebuffer object is created first. - */ - boolean bPbuffer = fb->bPbuffer; - - stw_framebuffer_unlock( fb ); - - return bPbuffer; - } - - fb = stw_framebuffer_create(hdc, iPixelFormat); - if (!fb) { - return FALSE; - } - - stw_framebuffer_unlock( fb ); - - /* Some applications mistakenly use the undocumented wglSetPixelFormat - * function instead of SetPixelFormat, so we call SetPixelFormat here to - * avoid opengl32.dll's wglCreateContext to fail */ - if (GetPixelFormat(hdc) == 0) { - BOOL bRet = SetPixelFormat(hdc, iPixelFormat, NULL); - if (!bRet) { - debug_printf("SetPixelFormat failed\n"); - } - } - - return TRUE; -} - - -int -stw_pixelformat_get(HDC hdc) -{ - int iPixelFormat = 0; - struct stw_framebuffer *fb; - - fb = stw_framebuffer_from_hdc(hdc); - if (fb) { - iPixelFormat = fb->iPixelFormat; - stw_framebuffer_unlock(fb); - } - - return iPixelFormat; -} - - -BOOL APIENTRY -DrvPresentBuffers(HDC hdc, LPPRESENTBUFFERS data) -{ - struct stw_framebuffer *fb; - struct pipe_screen *screen; - struct pipe_resource *res; - - if (!stw_dev) - return FALSE; - - fb = stw_framebuffer_from_hdc( hdc ); - if (fb == NULL) - return FALSE; - - screen = stw_dev->screen; - - res = (struct pipe_resource *)data->pPrivData; - - if (data->hSurface != fb->hSharedSurface) { - if (fb->shared_surface) { - stw_dev->stw_winsys->shared_surface_close(screen, fb->shared_surface); - fb->shared_surface = NULL; - } - - fb->hSharedSurface = data->hSurface; - - if (data->hSurface && - stw_dev->stw_winsys->shared_surface_open) { - fb->shared_surface = - stw_dev->stw_winsys->shared_surface_open(screen, - fb->hSharedSurface); - } - } - - if (!fb->minimized) { - if (fb->shared_surface) { - stw_dev->stw_winsys->compose(screen, - res, - fb->shared_surface, - &fb->client_rect, - data->ullPresentToken); - } - else { - stw_dev->stw_winsys->present( screen, res, hdc ); - } - } - - stw_framebuffer_update(fb); - stw_notify_current_locked(fb); - - stw_framebuffer_unlock(fb); - - return TRUE; -} - - -/** - * Queue a composition. - * - * The stw_framebuffer object must have its mutex locked. The mutex will - * be unlocked here before returning. - */ -BOOL -stw_framebuffer_present_locked(HDC hdc, - struct stw_framebuffer *fb, - struct pipe_resource *res) -{ - if (stw_dev->callbacks.pfnPresentBuffers && - stw_dev->stw_winsys->compose) { - PRESENTBUFFERSCB data; - - memset(&data, 0, sizeof data); - data.nVersion = 2; - data.syncType = PRESCB_SYNCTYPE_NONE; - data.luidAdapter = stw_dev->AdapterLuid; - data.updateRect = fb->client_rect; - data.pPrivData = (void *)res; - - stw_notify_current_locked(fb); - stw_framebuffer_unlock(fb); - - return stw_dev->callbacks.pfnPresentBuffers(hdc, &data); - } - else { - struct pipe_screen *screen = stw_dev->screen; - - stw_dev->stw_winsys->present( screen, res, hdc ); - - stw_framebuffer_update(fb); - stw_notify_current_locked(fb); - stw_framebuffer_unlock(fb); - - return TRUE; - } -} - - -/** - * This is called just before issuing the buffer swap/present. - * We query the current time and determine if we should sleep before - * issuing the swap/present. - * This is a bit of a hack and is certainly not very accurate but it - * basically works. - * This is for the WGL_ARB_swap_interval extension. - */ -static void -wait_swap_interval(struct stw_framebuffer *fb) -{ - /* Note: all time variables here are in units of microseconds */ - int64_t cur_time = os_time_get_nano() / 1000; - - if (fb->prev_swap_time != 0) { - /* Compute time since previous swap */ - int64_t delta = cur_time - fb->prev_swap_time; - int64_t min_swap_period = - 1.0e6 / stw_dev->refresh_rate * stw_dev->swap_interval; - - /* If time since last swap is less than wait period, wait. - * Note that it's possible for the delta to be negative because of - * rollover. See https://bugs.freedesktop.org/show_bug.cgi?id=102241 - */ - if ((delta >= 0) && (delta < min_swap_period)) { - float fudge = 1.75f; /* emperical fudge factor */ - int64_t wait = (min_swap_period - delta) * fudge; - os_time_sleep(wait); - } - } - - fb->prev_swap_time = cur_time; -} - - -BOOL APIENTRY -DrvSwapBuffers(HDC hdc) -{ - struct stw_context *ctx; - struct stw_framebuffer *fb; - - if (!stw_dev) - return FALSE; - - fb = stw_framebuffer_from_hdc( hdc ); - if (fb == NULL) - return FALSE; - - if (!(fb->pfi->pfd.dwFlags & PFD_DOUBLEBUFFER)) { - stw_framebuffer_unlock(fb); - return TRUE; - } - - ctx = stw_current_context(); - if (ctx) { - if (ctx->hud) { - /* Display the HUD */ - struct pipe_resource *back = - stw_get_framebuffer_resource(fb->stfb, ST_ATTACHMENT_BACK_LEFT); - if (back) { - hud_run(ctx->hud, NULL, back); - } - } - - if (ctx->current_framebuffer == fb) { - /* flush current context */ - ctx->st->flush(ctx->st, ST_FLUSH_END_OF_FRAME, NULL, NULL, NULL); - } - } - - if (stw_dev->swap_interval != 0) { - wait_swap_interval(fb); - } - - return stw_st_swap_framebuffer_locked(hdc, ctx->st, fb->stfb); -} - - -BOOL APIENTRY -DrvSwapLayerBuffers(HDC hdc, UINT fuPlanes) -{ - if (fuPlanes & WGL_SWAP_MAIN_PLANE) - return DrvSwapBuffers(hdc); - - return FALSE; -} diff --git a/src/gallium/state_trackers/wgl/stw_framebuffer.h b/src/gallium/state_trackers/wgl/stw_framebuffer.h deleted file mode 100644 index d44c3a6634a..00000000000 --- a/src/gallium/state_trackers/wgl/stw_framebuffer.h +++ /dev/null @@ -1,227 +0,0 @@ -/************************************************************************** - * - * Copyright 2008 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#ifndef STW_FRAMEBUFFER_H -#define STW_FRAMEBUFFER_H - -#include - -#include -#include - -#include "util/u_debug.h" -#include "stw_st.h" - - -struct pipe_resource; -struct st_framebuffer_iface; -struct stw_pixelformat_info; - -/** - * Windows framebuffer. - */ -struct stw_framebuffer -{ - /** - * This mutex has two purposes: - * - protect the access to the mutable data members below - * - prevent the framebuffer from being deleted while being accessed. - * - * Note: if both this mutex and the stw_device::fb_mutex need to be locked, - * the stw_device::fb_mutex needs to be locked first. - */ - CRITICAL_SECTION mutex; - - /* - * Immutable members. - * - * Note that even access to immutable members implies acquiring the mutex - * above, to prevent the framebuffer from being destroyed. - */ - - HWND hWnd; - - int iPixelFormat; - const struct stw_pixelformat_info *pfi; - - /* A pixel format that can be used by GDI */ - int iDisplayablePixelFormat; - boolean bPbuffer; - - struct st_framebuffer_iface *stfb; - - /* - * Mutable members. - */ - - unsigned refcnt; - - - /* FIXME: Make this work for multiple contexts bound to the same framebuffer */ - boolean must_resize; - - boolean minimized; /**< Is the window currently minimized? */ - - unsigned width; - unsigned height; - - /** WGL_ARB_render_texture - set at Pbuffer creation time */ - unsigned textureFormat; /**< WGL_NO_TEXTURE or WGL_TEXTURE_RGB[A]_ARB */ - unsigned textureTarget; /**< WGL_NO_TEXTURE or WGL_TEXTURE_1D/2D/ - CUBE_MAP_ARB */ - boolean textureMipmap; /**< TRUE/FALSE */ - /** WGL_ARB_render_texture - set with wglSetPbufferAttribARB() */ - unsigned textureLevel; - unsigned textureFace; /**< [0..6] */ - - /** - * Client area rectangle, relative to the window upper-left corner. - * - * @sa GLCBPRESENTBUFFERSDATA::rect. - */ - RECT client_rect; - - HANDLE hSharedSurface; - struct stw_shared_surface *shared_surface; - - /* For WGL_EXT_swap_control */ - int64_t prev_swap_time; - - /** - * This is protected by stw_device::fb_mutex, not the mutex above. - * - * Deletions must be done by first acquiring stw_device::fb_mutex, and then - * acquiring the stw_framebuffer::mutex of the framebuffer to be deleted. - * This ensures that nobody else is reading/writing to the. - * - * It is not necessary to acquire the mutex above to navigate the linked list - * given that deletions are done with stw_device::fb_mutex held, so no other - * thread can delete. - */ - struct stw_framebuffer *next; -}; - - -/** - * Create a new framebuffer object which will correspond to the given HDC. - * - * This function will acquire stw_framebuffer::mutex. stw_framebuffer_unlock - * must be called when done - */ -struct stw_framebuffer * -stw_framebuffer_create(HDC hdc, int iPixelFormat); - - -/** - * Increase fb reference count. The referenced framebuffer should be locked. - * - * It's not necessary to hold stw_dev::fb_mutex global lock. - */ -static inline void -stw_framebuffer_reference_locked(struct stw_framebuffer *fb) -{ - if (fb) { - assert(stw_own_mutex(&fb->mutex)); - fb->refcnt++; - } -} - - -void -stw_framebuffer_release_locked(struct stw_framebuffer *fb); - -/** - * Search a framebuffer with a matching HWND. - * - * This function will acquire stw_framebuffer::mutex. stw_framebuffer_unlock - * must be called when done - */ -struct stw_framebuffer * -stw_framebuffer_from_hwnd(HWND hwnd); - -/** - * Search a framebuffer with a matching HDC. - * - * This function will acquire stw_framebuffer::mutex. stw_framebuffer_unlock - * must be called when done - */ -struct stw_framebuffer * -stw_framebuffer_from_hdc(HDC hdc); - -BOOL -stw_framebuffer_present_locked(HDC hdc, - struct stw_framebuffer *fb, - struct pipe_resource *res); - -void -stw_framebuffer_update(struct stw_framebuffer *fb); - - -static inline void -stw_framebuffer_lock(struct stw_framebuffer *fb) -{ - assert(fb); - EnterCriticalSection(&fb->mutex); -} - - -/** - * Release stw_framebuffer::mutex lock. This framebuffer must not be accessed - * after calling this function, as it may have been deleted by another thread - * in the meanwhile. - */ -static inline void -stw_framebuffer_unlock(struct stw_framebuffer *fb) -{ - assert(fb); - assert(stw_own_mutex(&fb->mutex)); - LeaveCriticalSection(&fb->mutex); -} - - -/** - * Cleanup any existing framebuffers when exiting application. - */ -void -stw_framebuffer_cleanup(void); - - -static inline struct stw_st_framebuffer * -stw_st_framebuffer(struct st_framebuffer_iface *stfb) -{ - return (struct stw_st_framebuffer *) stfb; -} - - -static inline struct stw_framebuffer * -stw_framebuffer_from_HPBUFFERARB(HPBUFFERARB hPbuffer) -{ - return (struct stw_framebuffer *) hPbuffer; -} - - -#endif /* STW_FRAMEBUFFER_H */ diff --git a/src/gallium/state_trackers/wgl/stw_getprocaddress.c b/src/gallium/state_trackers/wgl/stw_getprocaddress.c deleted file mode 100644 index f062cd38aed..00000000000 --- a/src/gallium/state_trackers/wgl/stw_getprocaddress.c +++ /dev/null @@ -1,122 +0,0 @@ -/************************************************************************** - * - * Copyright 2008 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include - -#define WGL_WGLEXT_PROTOTYPES - -#include -#include - -#include "glapi/glapi.h" -#include "stw_device.h" -#include "gldrv.h" -#include "stw_nopfuncs.h" - -#include "util/u_debug.h" - -struct stw_extension_entry -{ - const char *name; - PROC proc; -}; - -#define STW_EXTENSION_ENTRY(P) { #P, (PROC) P } - -static const struct stw_extension_entry stw_extension_entries[] = { - - /* WGL_ARB_extensions_string */ - STW_EXTENSION_ENTRY( wglGetExtensionsStringARB ), - - /* WGL_ARB_pbuffer */ - STW_EXTENSION_ENTRY( wglCreatePbufferARB ), - STW_EXTENSION_ENTRY( wglGetPbufferDCARB ), - STW_EXTENSION_ENTRY( wglReleasePbufferDCARB ), - STW_EXTENSION_ENTRY( wglDestroyPbufferARB ), - STW_EXTENSION_ENTRY( wglQueryPbufferARB ), - - /* WGL_ARB_pixel_format */ - STW_EXTENSION_ENTRY( wglChoosePixelFormatARB ), - STW_EXTENSION_ENTRY( wglGetPixelFormatAttribfvARB ), - STW_EXTENSION_ENTRY( wglGetPixelFormatAttribivARB ), - - /* WGL_EXT_extensions_string */ - STW_EXTENSION_ENTRY( wglGetExtensionsStringEXT ), - - /* WGL_EXT_swap_control */ - STW_EXTENSION_ENTRY( wglGetSwapIntervalEXT ), - STW_EXTENSION_ENTRY( wglSwapIntervalEXT ), - - /* WGL_ARB_create_context */ - STW_EXTENSION_ENTRY( wglCreateContextAttribsARB ), - - /* WGL_ARB_render_texture */ - STW_EXTENSION_ENTRY( wglBindTexImageARB ), - STW_EXTENSION_ENTRY( wglReleaseTexImageARB ), - STW_EXTENSION_ENTRY( wglSetPbufferAttribARB ), - - /* WGL_ARB_make_current_read */ - STW_EXTENSION_ENTRY( wglMakeContextCurrentARB ), - STW_EXTENSION_ENTRY( wglGetCurrentReadDCARB ), - { NULL, NULL } -}; - -PROC APIENTRY -DrvGetProcAddress( - LPCSTR lpszProc ) -{ - const struct stw_extension_entry *entry; - PROC p; - - if (!stw_dev) - return NULL; - - if (lpszProc[0] == 'w' && lpszProc[1] == 'g' && lpszProc[2] == 'l') - for (entry = stw_extension_entries; entry->name; entry++) - if (strcmp( lpszProc, entry->name ) == 0) - return entry->proc; - - if (lpszProc[0] == 'g' && lpszProc[1] == 'l') { - p = (PROC) _glapi_get_proc_address(lpszProc); - if (p) - return p; - } - - /* If we get here, we'd normally just return NULL, but since some apps - * (like Viewperf12) crash when they try to use the null pointer, try - * returning a pointer to a no-op function instead. - */ - p = stw_get_nop_function(lpszProc); - if (p) { - debug_printf("wglGetProcAddress(\"%s\") returning no-op function\n", - lpszProc); - return p; - } - - debug_printf("wglGetProcAddress(\"%s\") returning NULL\n", lpszProc); - return NULL; -} diff --git a/src/gallium/state_trackers/wgl/stw_nopfuncs.c b/src/gallium/state_trackers/wgl/stw_nopfuncs.c deleted file mode 100644 index d69c0134f37..00000000000 --- a/src/gallium/state_trackers/wgl/stw_nopfuncs.c +++ /dev/null @@ -1,464 +0,0 @@ -/************************************************************************** - * - * Copyright 2015 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/** - * No-op GL API functions. - * - * Some OpenGL apps (like Viewperf12) call wglGetProcAddress() to get - * a pointer to an extension function, get a NULL pointer, but don't bother - * to check for NULL before jumping through the pointer. This causes a - * crash. - * - * As a work-around we provide some no-op functions here to avoid those - * crashes. - */ - -#include -#include "stw_nopfuncs.h" -#include "util/u_debug.h" - - -static void -warning(const char *name) -{ - /* use name+4 to skip "nop_" prefix */ - _debug_printf("Application calling unsupported %s function\n", name+4); -} - -static void APIENTRY -nop_glBindMultiTextureEXT(GLenum texunit, GLenum target, GLuint texture) -{ - warning(__func__); -} - -static void APIENTRY -nop_glColor3hNV(GLhalfNV red, GLhalfNV green, GLhalfNV blue) -{ - warning(__func__); -} - -static void APIENTRY -nop_glColor3hvNV(const GLhalfNV *v) -{ - warning(__func__); -} - -static void APIENTRY -nop_glColor4hNV(GLhalfNV red, GLhalfNV green, GLhalfNV blue, GLhalfNV alpha) -{ - warning(__func__); -} - -static void APIENTRY -nop_glColor4hvNV(const GLhalfNV *v) -{ - warning(__func__); -} - -static void APIENTRY -nop_glDisableClientStateIndexedEXT(GLenum array, GLuint index) -{ - warning(__func__); -} - -static void APIENTRY -nop_glEnableClientStateIndexedEXT(GLenum array, GLuint index) -{ - warning(__func__); -} - -static void APIENTRY -nop_glFogCoordhNV(GLhalfNV fog) -{ - warning(__func__); -} - -static void APIENTRY -nop_glFogCoordhvNV(const GLhalfNV *fog) -{ - warning(__func__); -} - -static void APIENTRY -nop_glGetNamedBufferParameterivEXT(GLuint buffer, GLenum pname, GLint *params) -{ - warning(__func__); -} - -static void APIENTRY -nop_glGetNamedBufferSubDataEXT(GLuint buffer, GLintptr offset, GLsizeiptr size, void *data) -{ - warning(__func__); -} - -static void *APIENTRY -nop_glMapNamedBufferEXT(GLuint buffer, GLenum access) -{ - warning(__func__); - return NULL; -} - -static void APIENTRY -nop_glMatrixLoadfEXT(GLenum mode, const GLfloat *m) -{ - warning(__func__); -} - -static void APIENTRY -nop_glMatrixLoadIdentityEXT(GLenum mode) -{ - warning(__func__); -} - -static void APIENTRY -nop_glMultiTexCoord1hNV(GLenum target, GLhalfNV s) -{ - warning(__func__); -} - -static void APIENTRY -nop_glMultiTexCoord1hvNV(GLenum target, const GLhalfNV *v) -{ - warning(__func__); -} - -static void APIENTRY -nop_glMultiTexCoord2hNV(GLenum target, GLhalfNV s, GLhalfNV t) -{ - warning(__func__); -} - -static void APIENTRY -nop_glMultiTexCoord2hvNV(GLenum target, const GLhalfNV *v) -{ - warning(__func__); -} - -static void APIENTRY -nop_glMultiTexCoord3hNV(GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r) -{ - warning(__func__); -} - -static void APIENTRY -nop_glMultiTexCoord3hvNV(GLenum target, const GLhalfNV *v) -{ - warning(__func__); -} - -static void APIENTRY -nop_glMultiTexCoord4hNV(GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q) -{ - warning(__func__); -} - -static void APIENTRY -nop_glMultiTexCoord4hvNV(GLenum target, const GLhalfNV *v) -{ - warning(__func__); -} - -static void APIENTRY -nop_glMultiTexCoordPointerEXT(GLenum texunit, GLint size, GLenum type, GLsizei stride, const void *pointer) -{ - warning(__func__); -} - -static void APIENTRY -nop_glMultiTexEnvfEXT(GLenum texunit, GLenum target, GLenum pname, GLfloat param) -{ - warning(__func__); -} - -static void APIENTRY -nop_glMultiTexEnvfvEXT(GLenum texunit, GLenum target, GLenum pname, const GLfloat *params) -{ - warning(__func__); -} - -static void APIENTRY -nop_glMultiTexEnviEXT(GLenum texunit, GLenum target, GLenum pname, GLint param) -{ - warning(__func__); -} - -static void APIENTRY -nop_glMultiTexGenfvEXT(GLenum texunit, GLenum coord, GLenum pname, const GLfloat *params) -{ - warning(__func__); -} - -static void APIENTRY -nop_glMultiTexGeniEXT(GLenum texunit, GLenum coord, GLenum pname, GLint param) -{ - warning(__func__); -} - -static void APIENTRY -nop_glNamedBufferDataEXT(GLuint buffer, GLsizeiptr size, const void *data, GLenum usage) -{ - warning(__func__); -} - -static void APIENTRY -nop_glNamedBufferSubDataEXT(GLuint buffer, GLintptr offset, GLsizeiptr size, const void *data) -{ - warning(__func__); -} - -static void APIENTRY -nop_glNamedProgramLocalParameter4fvEXT(GLuint program, GLenum target, GLuint index, const GLfloat *params) -{ - warning(__func__); -} - -static void APIENTRY -nop_glNamedProgramLocalParameters4fvEXT(GLuint program, GLenum target, GLuint index, GLsizei count, const GLfloat *params) -{ - warning(__func__); -} - -static void APIENTRY -nop_glNormal3hNV(GLhalfNV nx, GLhalfNV ny, GLhalfNV nz) -{ - warning(__func__); -} - -static void APIENTRY -nop_glNormal3hvNV(const GLhalfNV *v) -{ - warning(__func__); -} - -static void APIENTRY -nop_glPatchParameterfv(GLenum pname, const GLfloat *values) -{ - warning(__func__); -} - -static void APIENTRY -nop_glPatchParameteri(GLenum pname, GLint value) -{ - warning(__func__); -} - -static void APIENTRY -nop_glSecondaryColor3hNV(GLhalfNV red, GLhalfNV green, GLhalfNV blue) -{ - warning(__func__); -} - -static void APIENTRY -nop_glSecondaryColor3hvNV(const GLhalfNV *v) -{ - warning(__func__); -} - -static void APIENTRY -nop_glTexCoord1hNV(GLhalfNV s) -{ - warning(__func__); -} - -static void APIENTRY -nop_glTexCoord1hvNV(const GLhalfNV *v) -{ - warning(__func__); -} - -static void APIENTRY -nop_glTexCoord2hNV(GLhalfNV s, GLhalfNV t) -{ - warning(__func__); -} - -static void APIENTRY -nop_glTexCoord2hvNV(const GLhalfNV *v) -{ - warning(__func__); -} - -static void APIENTRY -nop_glTexCoord3hNV(GLhalfNV s, GLhalfNV t, GLhalfNV r) -{ - warning(__func__); -} - -static void APIENTRY -nop_glTexCoord3hvNV(const GLhalfNV *v) -{ - warning(__func__); -} - -static void APIENTRY -nop_glTexCoord4hNV(GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q) -{ - warning(__func__); -} - -static void APIENTRY -nop_glTexCoord4hvNV(const GLhalfNV *v) -{ - warning(__func__); -} - -static void APIENTRY -nop_glTextureParameterfEXT(GLuint texture, GLenum target, GLenum pname, GLfloat param) -{ - warning(__func__); -} - -static void APIENTRY -nop_glTextureParameterfvEXT(GLuint texture, GLenum target, GLenum pname, const GLfloat *params) -{ - warning(__func__); -} - -static void APIENTRY -nop_glTextureParameteriEXT(GLuint texture, GLenum target, GLenum pname, GLint param) -{ - warning(__func__); -} - -static GLboolean APIENTRY -nop_glUnmapNamedBufferEXT(GLuint buffer) -{ - warning(__func__); - return GL_FALSE; -} - -static void APIENTRY -nop_glVertex2hNV(GLhalfNV x, GLhalfNV y) -{ - warning(__func__); -} - -static void APIENTRY -nop_glVertex2hvNV(const GLhalfNV *v) -{ - warning(__func__); -} - -static void APIENTRY -nop_glVertex3hNV(GLhalfNV x, GLhalfNV y, GLhalfNV z) -{ - warning(__func__); -} - -static void APIENTRY -nop_glVertex3hvNV(const GLhalfNV *v) -{ - warning(__func__); -} - -static void APIENTRY -nop_glVertex4hNV(GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w) -{ - warning(__func__); -} - -static void APIENTRY -nop_glVertex4hvNV(const GLhalfNV *v) -{ - warning(__func__); -} - - -PROC -stw_get_nop_function(const char *name) -{ - struct { - const char *name; - PROC p; - } table[] = { - { "glBindMultiTextureEXT", (PROC) nop_glBindMultiTextureEXT }, - { "glColor3hNV", (PROC) nop_glColor3hNV }, - { "glColor3hvNV", (PROC) nop_glColor3hvNV }, - { "glColor4hNV", (PROC) nop_glColor4hNV }, - { "glColor4hvNV", (PROC) nop_glColor4hvNV }, - { "glDisableClientStateIndexedEXT", (PROC) nop_glDisableClientStateIndexedEXT }, - { "glEnableClientStateIndexedEXT", (PROC) nop_glEnableClientStateIndexedEXT }, - { "glFogCoordhNV", (PROC) nop_glFogCoordhNV }, - { "glFogCoordhvNV", (PROC) nop_glFogCoordhvNV }, - { "glGetNamedBufferParameterivEXT", (PROC) nop_glGetNamedBufferParameterivEXT }, - { "glGetNamedBufferSubDataEXT", (PROC) nop_glGetNamedBufferSubDataEXT }, - { "glMapNamedBufferEXT", (PROC) nop_glMapNamedBufferEXT }, - { "glMatrixLoadfEXT", (PROC) nop_glMatrixLoadfEXT }, - { "glMatrixLoadIdentityEXT", (PROC) nop_glMatrixLoadIdentityEXT }, - { "glMultiTexCoord1hNV", (PROC) nop_glMultiTexCoord1hNV }, - { "glMultiTexCoord1hvNV", (PROC) nop_glMultiTexCoord1hvNV }, - { "glMultiTexCoord2hNV", (PROC) nop_glMultiTexCoord2hNV }, - { "glMultiTexCoord2hvNV", (PROC) nop_glMultiTexCoord2hvNV }, - { "glMultiTexCoord3hNV", (PROC) nop_glMultiTexCoord3hNV }, - { "glMultiTexCoord3hvNV", (PROC) nop_glMultiTexCoord3hvNV }, - { "glMultiTexCoord4hNV", (PROC) nop_glMultiTexCoord4hNV }, - { "glMultiTexCoord4hvNV", (PROC) nop_glMultiTexCoord4hvNV }, - { "glMultiTexCoordPointerEXT", (PROC) nop_glMultiTexCoordPointerEXT }, - { "glMultiTexEnvfEXT", (PROC) nop_glMultiTexEnvfEXT }, - { "glMultiTexEnvfvEXT", (PROC) nop_glMultiTexEnvfvEXT }, - { "glMultiTexEnviEXT", (PROC) nop_glMultiTexEnviEXT }, - { "glMultiTexGenfvEXT", (PROC) nop_glMultiTexGenfvEXT }, - { "glMultiTexGeniEXT", (PROC) nop_glMultiTexGeniEXT }, - { "glNamedBufferDataEXT", (PROC) nop_glNamedBufferDataEXT }, - { "glNamedBufferSubDataEXT", (PROC) nop_glNamedBufferSubDataEXT }, - { "glNamedProgramLocalParameter4fvEXT", (PROC) nop_glNamedProgramLocalParameter4fvEXT }, - { "glNamedProgramLocalParameters4fvEXT", (PROC) nop_glNamedProgramLocalParameters4fvEXT }, - { "glNormal3hNV", (PROC) nop_glNormal3hNV }, - { "glNormal3hvNV", (PROC) nop_glNormal3hvNV }, - { "glPatchParameterfv", (PROC) nop_glPatchParameterfv }, - { "glPatchParameteri", (PROC) nop_glPatchParameteri }, - { "glSecondaryColor3hNV", (PROC) nop_glSecondaryColor3hNV }, - { "glSecondaryColor3hvNV", (PROC) nop_glSecondaryColor3hvNV }, - { "glTexCoord1hNV", (PROC) nop_glTexCoord1hNV }, - { "glTexCoord1hvNV", (PROC) nop_glTexCoord1hvNV }, - { "glTexCoord2hNV", (PROC) nop_glTexCoord2hNV }, - { "glTexCoord2hvNV", (PROC) nop_glTexCoord2hvNV }, - { "glTexCoord3hNV", (PROC) nop_glTexCoord3hNV }, - { "glTexCoord3hvNV", (PROC) nop_glTexCoord3hvNV }, - { "glTexCoord4hNV", (PROC) nop_glTexCoord4hNV }, - { "glTexCoord4hvNV", (PROC) nop_glTexCoord4hvNV }, - { "glTextureParameterfEXT", (PROC) nop_glTextureParameterfEXT }, - { "glTextureParameterfvEXT", (PROC) nop_glTextureParameterfvEXT }, - { "glTextureParameteriEXT", (PROC) nop_glTextureParameteriEXT }, - { "glUnmapNamedBufferEXT", (PROC) nop_glUnmapNamedBufferEXT }, - { "glVertex2hNV", (PROC) nop_glVertex2hNV }, - { "glVertex2hvNV", (PROC) nop_glVertex2hvNV }, - { "glVertex3hNV", (PROC) nop_glVertex3hNV }, - { "glVertex3hvNV", (PROC) nop_glVertex3hvNV }, - { "glVertex4hNV", (PROC) nop_glVertex4hNV }, - { "glVertex4hvNV", (PROC) nop_glVertex4hvNV }, - { NULL, NULL } - }; - - int i; - - for (i = 0; table[i].name; i++) { - if (strcmp(table[i].name, name) == 0) - return table[i].p; - } - return NULL; -} diff --git a/src/gallium/state_trackers/wgl/stw_nopfuncs.h b/src/gallium/state_trackers/wgl/stw_nopfuncs.h deleted file mode 100644 index f00d420accf..00000000000 --- a/src/gallium/state_trackers/wgl/stw_nopfuncs.h +++ /dev/null @@ -1,11 +0,0 @@ - - -#ifndef STW_NOPFUNCS_H -#define STW_NOPFUNCS_H - - -PROC -stw_get_nop_function(const char *name); - - -#endif /* STW_NOPFUNCS_H */ diff --git a/src/gallium/state_trackers/wgl/stw_pixelformat.c b/src/gallium/state_trackers/wgl/stw_pixelformat.c deleted file mode 100644 index 8696300f3e0..00000000000 --- a/src/gallium/state_trackers/wgl/stw_pixelformat.c +++ /dev/null @@ -1,487 +0,0 @@ -/************************************************************************** - * - * Copyright 2008 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include "pipe/p_format.h" -#include "pipe/p_defines.h" -#include "pipe/p_screen.h" - -#include "util/format/u_format.h" -#include "util/u_debug.h" -#include "util/u_memory.h" - -#include -#include "gldrv.h" -#include "stw_device.h" -#include "stw_pixelformat.h" -#include "stw_tls.h" - - -struct stw_pf_color_info -{ - enum pipe_format format; - struct { - unsigned char red; - unsigned char green; - unsigned char blue; - unsigned char alpha; - } bits; - struct { - unsigned char red; - unsigned char green; - unsigned char blue; - unsigned char alpha; - } shift; -}; - -struct stw_pf_depth_info -{ - enum pipe_format format; - struct { - unsigned char depth; - unsigned char stencil; - } bits; -}; - - -/* NOTE: order matters, since in otherwise equal circumstances the first - * format listed will get chosen */ - -static const struct stw_pf_color_info -stw_pf_color[] = { - /* no-alpha */ - { PIPE_FORMAT_B8G8R8X8_UNORM, { 8, 8, 8, 0}, {16, 8, 0, 0} }, - { PIPE_FORMAT_X8R8G8B8_UNORM, { 8, 8, 8, 0}, { 8, 16, 24, 0} }, - /* alpha */ - { PIPE_FORMAT_B8G8R8A8_UNORM, { 8, 8, 8, 8}, {16, 8, 0, 24} }, - { PIPE_FORMAT_A8R8G8B8_UNORM, { 8, 8, 8, 8}, { 8, 16, 24, 0} }, - /* shallow bit depths */ - { PIPE_FORMAT_B5G6R5_UNORM, { 5, 6, 5, 0}, {11, 5, 0, 0} }, -#if 0 - { PIPE_FORMAT_R10G10B10A2_UNORM, {10, 10, 10, 2}, { 0, 10, 20, 30} }, -#endif - { PIPE_FORMAT_B5G5R5A1_UNORM, { 5, 5, 5, 1}, {10, 5, 0, 15} }, - { PIPE_FORMAT_B4G4R4A4_UNORM, { 4, 4, 4, 4}, {16, 4, 0, 12} } -}; - -static const struct stw_pf_color_info -stw_pf_color_extended[] = { - { PIPE_FORMAT_R32G32B32A32_FLOAT, {32, 32, 32, 32}, {0, 32, 64, 96} } -}; - -static const struct stw_pf_depth_info -stw_pf_depth_stencil[] = { - /* pure depth */ - { PIPE_FORMAT_Z32_UNORM, {32, 0} }, - { PIPE_FORMAT_X8Z24_UNORM, {24, 0} }, - { PIPE_FORMAT_Z24X8_UNORM, {24, 0} }, - { PIPE_FORMAT_Z16_UNORM, {16, 0} }, - /* combined depth-stencil */ - { PIPE_FORMAT_Z24_UNORM_S8_UINT, {24, 8} }, - { PIPE_FORMAT_S8_UINT_Z24_UNORM, {24, 8} } -}; - - -static const boolean -stw_pf_doublebuffer[] = { - FALSE, - TRUE, -}; - - -const unsigned -stw_pf_multisample[] = { - 0, - 4, - 8, - 16 -}; - - -static void -stw_pixelformat_add(struct stw_device *stw_dev, - boolean extended, - const struct stw_pf_color_info *color, - const struct stw_pf_depth_info *depth, - unsigned accum, - boolean doublebuffer, - unsigned samples) -{ - struct stw_pixelformat_info *pfi; - - assert(stw_dev->pixelformat_extended_count < STW_MAX_PIXELFORMATS); - if (stw_dev->pixelformat_extended_count >= STW_MAX_PIXELFORMATS) - return; - - assert(util_format_get_component_bits(color->format, UTIL_FORMAT_COLORSPACE_RGB, 0) == color->bits.red); - assert(util_format_get_component_bits(color->format, UTIL_FORMAT_COLORSPACE_RGB, 1) == color->bits.green); - assert(util_format_get_component_bits(color->format, UTIL_FORMAT_COLORSPACE_RGB, 2) == color->bits.blue); - assert(util_format_get_component_bits(color->format, UTIL_FORMAT_COLORSPACE_RGB, 3) == color->bits.alpha); - assert(util_format_get_component_bits(depth->format, UTIL_FORMAT_COLORSPACE_ZS, 0) == depth->bits.depth); - assert(util_format_get_component_bits(depth->format, UTIL_FORMAT_COLORSPACE_ZS, 1) == depth->bits.stencil); - - pfi = &stw_dev->pixelformats[stw_dev->pixelformat_extended_count]; - - memset(pfi, 0, sizeof *pfi); - - pfi->pfd.nSize = sizeof pfi->pfd; - pfi->pfd.nVersion = 1; - - pfi->pfd.dwFlags = PFD_SUPPORT_OPENGL; - - /* TODO: also support non-native pixel formats */ - if (!extended) { - pfi->pfd.dwFlags |= PFD_DRAW_TO_WINDOW; - } - - /* See http://www.opengl.org/pipeline/article/vol003_7/ */ - pfi->pfd.dwFlags |= PFD_SUPPORT_COMPOSITION; - - if (doublebuffer) - pfi->pfd.dwFlags |= PFD_DOUBLEBUFFER | PFD_SWAP_EXCHANGE; - - pfi->pfd.iPixelType = PFD_TYPE_RGBA; - - pfi->pfd.cColorBits = - color->bits.red + color->bits.green + color->bits.blue + color->bits.alpha; - pfi->pfd.cRedBits = color->bits.red; - pfi->pfd.cRedShift = color->shift.red; - pfi->pfd.cGreenBits = color->bits.green; - pfi->pfd.cGreenShift = color->shift.green; - pfi->pfd.cBlueBits = color->bits.blue; - pfi->pfd.cBlueShift = color->shift.blue; - pfi->pfd.cAlphaBits = color->bits.alpha; - pfi->pfd.cAlphaShift = color->shift.alpha; - pfi->pfd.cAccumBits = 4*accum; - pfi->pfd.cAccumRedBits = accum; - pfi->pfd.cAccumGreenBits = accum; - pfi->pfd.cAccumBlueBits = accum; - pfi->pfd.cAccumAlphaBits = accum; - pfi->pfd.cDepthBits = depth->bits.depth; - pfi->pfd.cStencilBits = depth->bits.stencil; - pfi->pfd.cAuxBuffers = 0; - pfi->pfd.iLayerType = 0; - pfi->pfd.bReserved = 0; - pfi->pfd.dwLayerMask = 0; - pfi->pfd.dwVisibleMask = 0; - pfi->pfd.dwDamageMask = 0; - - /* - * since state trackers can allocate depth/stencil/accum buffers, we provide - * only color buffers here - */ - pfi->stvis.buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK; - if (doublebuffer) - pfi->stvis.buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK; - - pfi->stvis.color_format = color->format; - pfi->stvis.depth_stencil_format = depth->format; - - pfi->stvis.accum_format = (accum) ? - PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE; - - pfi->stvis.samples = samples; - pfi->stvis.render_buffer = ST_ATTACHMENT_INVALID; - - /* WGL_ARB_render_texture */ - if (color->bits.alpha) - pfi->bindToTextureRGBA = TRUE; - - pfi->bindToTextureRGB = TRUE; - - ++stw_dev->pixelformat_extended_count; - - if (!extended) { - ++stw_dev->pixelformat_count; - assert(stw_dev->pixelformat_count == stw_dev->pixelformat_extended_count); - } -} - - -/** - * Add the depth/stencil/accum/ms variants for a list of color formats. - */ -static unsigned -add_color_format_variants(const struct stw_pf_color_info *color_formats, - unsigned num_color_formats, boolean extended) -{ - struct pipe_screen *screen = stw_dev->screen; - unsigned cfmt, ms, db, ds, acc; - unsigned bind_flags = PIPE_BIND_RENDER_TARGET; - unsigned num_added = 0; - int force_samples = 0; - - /* Since GLUT for Windows doesn't support MSAA we have an env var - * to force all pixel formats to have a particular number of samples. - */ - { - const char *samples= getenv("SVGA_FORCE_MSAA"); - if (samples) - force_samples = atoi(samples); - } - - if (!extended) { - bind_flags |= PIPE_BIND_DISPLAY_TARGET; - } - - for (ms = 0; ms < ARRAY_SIZE(stw_pf_multisample); ms++) { - unsigned samples = stw_pf_multisample[ms]; - - if (force_samples && samples != force_samples) - continue; - - for (cfmt = 0; cfmt < num_color_formats; cfmt++) { - if (!screen->is_format_supported(screen, color_formats[cfmt].format, - PIPE_TEXTURE_2D, samples, samples, - bind_flags)) { - continue; - } - - for (db = 0; db < ARRAY_SIZE(stw_pf_doublebuffer); db++) { - unsigned doublebuffer = stw_pf_doublebuffer[db]; - - for (ds = 0; ds < ARRAY_SIZE(stw_pf_depth_stencil); ds++) { - const struct stw_pf_depth_info *depth = &stw_pf_depth_stencil[ds]; - - if (!screen->is_format_supported(screen, depth->format, - PIPE_TEXTURE_2D, samples, - samples, - PIPE_BIND_DEPTH_STENCIL)) { - continue; - } - - for (acc = 0; acc < 2; acc++) { - stw_pixelformat_add(stw_dev, extended, &color_formats[cfmt], - depth, - acc * 16, doublebuffer, samples); - num_added++; - } - } - } - } - } - - return num_added; -} - - -void -stw_pixelformat_init(void) -{ - unsigned num_formats; - - assert(!stw_dev->pixelformat_count); - assert(!stw_dev->pixelformat_extended_count); - - /* normal, displayable formats */ - num_formats = add_color_format_variants(stw_pf_color, - ARRAY_SIZE(stw_pf_color), FALSE); - assert(num_formats > 0); - - /* extended, pbuffer-only formats */ - add_color_format_variants(stw_pf_color_extended, - ARRAY_SIZE(stw_pf_color_extended), TRUE); - - assert(stw_dev->pixelformat_count <= stw_dev->pixelformat_extended_count); - assert(stw_dev->pixelformat_extended_count <= STW_MAX_PIXELFORMATS); -} - - -uint -stw_pixelformat_get_count(void) -{ - if (!stw_init_screen()) - return 0; - - return stw_dev->pixelformat_count; -} - - -uint -stw_pixelformat_get_extended_count(void) -{ - if (!stw_init_screen()) - return 0; - - return stw_dev->pixelformat_extended_count; -} - - -const struct stw_pixelformat_info * -stw_pixelformat_get_info(int iPixelFormat) -{ - unsigned index; - - if (iPixelFormat <= 0) { - return NULL; - } - - index = iPixelFormat - 1; - if (index >= stw_dev->pixelformat_extended_count) { - return NULL; - } - - return &stw_dev->pixelformats[index]; -} - - -LONG APIENTRY -DrvDescribePixelFormat(HDC hdc, INT iPixelFormat, ULONG cjpfd, - PIXELFORMATDESCRIPTOR *ppfd) -{ - uint count; - const struct stw_pixelformat_info *pfi; - - (void) hdc; - - if (!stw_dev) - return 0; - - count = stw_pixelformat_get_count(); - - if (ppfd == NULL) - return count; - - if (cjpfd != sizeof(PIXELFORMATDESCRIPTOR)) - return 0; - - pfi = stw_pixelformat_get_info(iPixelFormat); - if (!pfi) { - return 0; - } - - memcpy(ppfd, &pfi->pfd, sizeof(PIXELFORMATDESCRIPTOR)); - - return count; -} - - -BOOL APIENTRY -DrvDescribeLayerPlane(HDC hdc, INT iPixelFormat, INT iLayerPlane, - UINT nBytes, LPLAYERPLANEDESCRIPTOR plpd) -{ - assert(0); - return FALSE; -} - - -int APIENTRY -DrvGetLayerPaletteEntries(HDC hdc, INT iLayerPlane, INT iStart, - INT cEntries, COLORREF *pcr) -{ - assert(0); - return 0; -} - - -int APIENTRY -DrvSetLayerPaletteEntries(HDC hdc, INT iLayerPlane, INT iStart, - INT cEntries, CONST COLORREF *pcr) -{ - assert(0); - return 0; -} - - -BOOL APIENTRY -DrvRealizeLayerPalette(HDC hdc, INT iLayerPlane, BOOL bRealize) -{ - assert(0); - return FALSE; -} - - -/* Only used by the wgl code, but have it here to avoid exporting the - * pixelformat.h functionality. - */ -int -stw_pixelformat_choose(HDC hdc, CONST PIXELFORMATDESCRIPTOR *ppfd) -{ - uint count; - uint index; - uint bestindex; - uint bestdelta; - - (void) hdc; - - count = stw_pixelformat_get_extended_count(); - bestindex = 0; - bestdelta = ~0U; - - for (index = 1; index <= count; index++) { - uint delta = 0; - const struct stw_pixelformat_info *pfi = stw_pixelformat_get_info(index); - - if (!(ppfd->dwFlags & PFD_DOUBLEBUFFER_DONTCARE) && - !!(ppfd->dwFlags & PFD_DOUBLEBUFFER) != - !!(pfi->pfd.dwFlags & PFD_DOUBLEBUFFER)) - continue; - - /* Selection logic: - * - Enabling a feature (depth, stencil...) is given highest priority. - * - Giving as many bits as requested is given medium priority. - * - Giving no more bits than requested is given lowest priority. - */ - - /* FIXME: Take in account individual channel bits */ - if (ppfd->cColorBits && !pfi->pfd.cColorBits) - delta += 10000; - else if (ppfd->cColorBits > pfi->pfd.cColorBits) - delta += 100; - else if (ppfd->cColorBits < pfi->pfd.cColorBits) - delta++; - - if (ppfd->cDepthBits && !pfi->pfd.cDepthBits) - delta += 10000; - else if (ppfd->cDepthBits > pfi->pfd.cDepthBits) - delta += 200; - else if (ppfd->cDepthBits < pfi->pfd.cDepthBits) - delta += 2; - - if (ppfd->cStencilBits && !pfi->pfd.cStencilBits) - delta += 10000; - else if (ppfd->cStencilBits > pfi->pfd.cStencilBits) - delta += 400; - else if (ppfd->cStencilBits < pfi->pfd.cStencilBits) - delta++; - - if (ppfd->cAlphaBits && !pfi->pfd.cAlphaBits) - delta += 10000; - else if (ppfd->cAlphaBits > pfi->pfd.cAlphaBits) - delta += 100; - else if (ppfd->cAlphaBits < pfi->pfd.cAlphaBits) - delta++; - - if (delta < bestdelta) { - bestindex = index; - bestdelta = delta; - if (bestdelta == 0) - break; - } - } - - return bestindex; -} diff --git a/src/gallium/state_trackers/wgl/stw_pixelformat.h b/src/gallium/state_trackers/wgl/stw_pixelformat.h deleted file mode 100644 index 06753b09e16..00000000000 --- a/src/gallium/state_trackers/wgl/stw_pixelformat.h +++ /dev/null @@ -1,71 +0,0 @@ -/************************************************************************** - * - * Copyright 2008 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#ifndef STW_PIXELFORMAT_H -#define STW_PIXELFORMAT_H - -#include - -#ifndef PFD_SUPPORT_COMPOSITION -#define PFD_SUPPORT_COMPOSITION 0x00008000 -#endif - -#include "pipe/p_compiler.h" -#include "pipe/p_format.h" -#include "state_tracker/st_api.h" - -struct stw_pixelformat_info -{ - PIXELFORMATDESCRIPTOR pfd; - - struct st_visual stvis; - - /** WGL_ARB_render_texture */ - boolean bindToTextureRGB; - boolean bindToTextureRGBA; -}; - -void -stw_pixelformat_init( void ); - -uint -stw_pixelformat_get_count( void ); - -uint -stw_pixelformat_get_extended_count( void ); - -const struct stw_pixelformat_info * -stw_pixelformat_get_info( int iPixelFormat ); - -int -stw_pixelformat_choose( HDC hdc, - CONST PIXELFORMATDESCRIPTOR *ppfd ); - -int -stw_pixelformat_get(HDC hdc); - -#endif /* STW_PIXELFORMAT_H */ diff --git a/src/gallium/state_trackers/wgl/stw_st.c b/src/gallium/state_trackers/wgl/stw_st.c deleted file mode 100644 index e173c816c7c..00000000000 --- a/src/gallium/state_trackers/wgl/stw_st.c +++ /dev/null @@ -1,394 +0,0 @@ -/* - * Mesa 3-D graphics library - * - * Copyright (C) 2010 LunarG Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: - * Chia-I Wu - */ - -#include "util/u_memory.h" -#include "util/u_inlines.h" -#include "util/u_atomic.h" -#include "state_tracker/st_gl_api.h" /* for st_gl_api_create */ - -#include "stw_st.h" -#include "stw_device.h" -#include "stw_framebuffer.h" -#include "stw_pixelformat.h" - -struct stw_st_framebuffer { - struct st_framebuffer_iface base; - - struct stw_framebuffer *fb; - struct st_visual stvis; - - struct pipe_resource *textures[ST_ATTACHMENT_COUNT]; - struct pipe_resource *msaa_textures[ST_ATTACHMENT_COUNT]; - unsigned texture_width, texture_height; - unsigned texture_mask; -}; - -static uint32_t stwfb_ID = 0; - -/** - * Is the given mutex held by the calling thread? - */ -bool -stw_own_mutex(const CRITICAL_SECTION *cs) -{ - // We can't compare OwningThread with our thread handle/id (see - // http://stackoverflow.com/a/12675635 ) but we can compare with the - // OwningThread member of a critical section we know we own. - CRITICAL_SECTION dummy; - InitializeCriticalSection(&dummy); - EnterCriticalSection(&dummy); - if (0) - _debug_printf("%p %p\n", cs->OwningThread, dummy.OwningThread); - bool ret = cs->OwningThread == dummy.OwningThread; - LeaveCriticalSection(&dummy); - DeleteCriticalSection(&dummy); - return ret; -} - - -/** - * Remove outdated textures and create the requested ones. - */ -static void -stw_st_framebuffer_validate_locked(struct st_framebuffer_iface *stfb, - unsigned width, unsigned height, - unsigned mask) -{ - struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb); - struct pipe_resource templ; - unsigned i; - - /* remove outdated textures */ - if (stwfb->texture_width != width || stwfb->texture_height != height) { - for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { - pipe_resource_reference(&stwfb->msaa_textures[i], NULL); - pipe_resource_reference(&stwfb->textures[i], NULL); - } - } - - memset(&templ, 0, sizeof(templ)); - templ.target = PIPE_TEXTURE_2D; - templ.width0 = width; - templ.height0 = height; - templ.depth0 = 1; - templ.array_size = 1; - templ.last_level = 0; - - for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { - enum pipe_format format; - unsigned bind; - - /* the texture already exists or not requested */ - if (stwfb->textures[i] || !(mask & (1 << i))) { - /* remember the texture */ - if (stwfb->textures[i]) - mask |= (1 << i); - continue; - } - - switch (i) { - case ST_ATTACHMENT_FRONT_LEFT: - case ST_ATTACHMENT_BACK_LEFT: - format = stwfb->stvis.color_format; - bind = PIPE_BIND_DISPLAY_TARGET | - PIPE_BIND_SAMPLER_VIEW | - PIPE_BIND_RENDER_TARGET; - break; - case ST_ATTACHMENT_DEPTH_STENCIL: - format = stwfb->stvis.depth_stencil_format; - bind = PIPE_BIND_DEPTH_STENCIL; - break; - default: - format = PIPE_FORMAT_NONE; - break; - } - - if (format != PIPE_FORMAT_NONE) { - templ.format = format; - - if (bind != PIPE_BIND_DEPTH_STENCIL && stwfb->stvis.samples > 1) { - templ.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; - templ.nr_samples = templ.nr_storage_samples = - stwfb->stvis.samples; - - stwfb->msaa_textures[i] = - stw_dev->screen->resource_create(stw_dev->screen, &templ); - } - - templ.bind = bind; - templ.nr_samples = templ.nr_storage_samples = 1; - stwfb->textures[i] = - stw_dev->screen->resource_create(stw_dev->screen, &templ); - } - } - - stwfb->texture_width = width; - stwfb->texture_height = height; - stwfb->texture_mask = mask; -} - -static bool -stw_st_framebuffer_validate(struct st_context_iface *stctx, - struct st_framebuffer_iface *stfb, - const enum st_attachment_type *statts, - unsigned count, - struct pipe_resource **out) -{ - struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb); - unsigned statt_mask, i; - - statt_mask = 0x0; - for (i = 0; i < count; i++) - statt_mask |= 1 << statts[i]; - - stw_framebuffer_lock(stwfb->fb); - - if (stwfb->fb->must_resize || (statt_mask & ~stwfb->texture_mask)) { - stw_st_framebuffer_validate_locked(&stwfb->base, - stwfb->fb->width, stwfb->fb->height, statt_mask); - stwfb->fb->must_resize = FALSE; - } - - struct pipe_resource **textures = - stwfb->stvis.samples > 1 ? stwfb->msaa_textures - : stwfb->textures; - - for (i = 0; i < count; i++) - pipe_resource_reference(&out[i], textures[statts[i]]); - - stw_framebuffer_unlock(stwfb->fb); - - return true; -} - -static void -stw_pipe_blit(struct pipe_context *pipe, - struct pipe_resource *dst, - struct pipe_resource *src) -{ - struct pipe_blit_info blit; - - /* From the GL spec, version 4.2, section 4.1.11 (Additional Multisample - * Fragment Operations): - * - * If a framebuffer object is not bound, after all operations have - * been completed on the multisample buffer, the sample values for - * each color in the multisample buffer are combined to produce a - * single color value, and that value is written into the - * corresponding color buffers selected by DrawBuffer or - * DrawBuffers. An implementation may defer the writing of the color - * buffers until a later time, but the state of the framebuffer must - * behave as if the color buffers were updated as each fragment was - * processed. The method of combination is not specified. If the - * framebuffer contains sRGB values, then it is recommended that the - * an average of sample values is computed in a linearized space, as - * for blending (see section 4.1.7). - * - * In other words, to do a resolve operation in a linear space, we have - * to set sRGB formats if the original resources were sRGB, so don't use - * util_format_linear. - */ - - memset(&blit, 0, sizeof(blit)); - blit.dst.resource = dst; - blit.dst.box.width = dst->width0; - blit.dst.box.height = dst->height0; - blit.dst.box.depth = 1; - blit.dst.format = dst->format; - blit.src.resource = src; - blit.src.box.width = src->width0; - blit.src.box.height = src->height0; - blit.src.box.depth = 1; - blit.src.format = src->format; - blit.mask = PIPE_MASK_RGBA; - blit.filter = PIPE_TEX_FILTER_NEAREST; - - pipe->blit(pipe, &blit); -} - -/** - * Present an attachment of the framebuffer. - */ -static bool -stw_st_framebuffer_present_locked(HDC hdc, - struct st_context_iface *stctx, - struct st_framebuffer_iface *stfb, - enum st_attachment_type statt) -{ - struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb); - struct pipe_resource *resource; - - assert(stw_own_mutex(&stwfb->fb->mutex)); - - if (stwfb->stvis.samples > 1) { - stw_pipe_blit(stctx->pipe, - stwfb->textures[statt], - stwfb->msaa_textures[statt]); - } - - resource = stwfb->textures[statt]; - if (resource) { - stw_framebuffer_present_locked(hdc, stwfb->fb, resource); - } - else { - stw_framebuffer_unlock(stwfb->fb); - } - - assert(!stw_own_mutex(&stwfb->fb->mutex)); - - return true; -} - -static bool -stw_st_framebuffer_flush_front(struct st_context_iface *stctx, - struct st_framebuffer_iface *stfb, - enum st_attachment_type statt) -{ - struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb); - bool ret; - HDC hDC; - - stw_framebuffer_lock(stwfb->fb); - - /* We must not cache HDCs anywhere, as they can be invalidated by the - * application, or screen resolution changes. */ - - hDC = GetDC(stwfb->fb->hWnd); - - ret = stw_st_framebuffer_present_locked(hDC, stctx, &stwfb->base, statt); - - ReleaseDC(stwfb->fb->hWnd, hDC); - - return ret; -} - -/** - * Create a framebuffer interface. - */ -struct st_framebuffer_iface * -stw_st_create_framebuffer(struct stw_framebuffer *fb) -{ - struct stw_st_framebuffer *stwfb; - - stwfb = CALLOC_STRUCT(stw_st_framebuffer); - if (!stwfb) - return NULL; - - stwfb->fb = fb; - stwfb->stvis = fb->pfi->stvis; - stwfb->base.ID = p_atomic_inc_return(&stwfb_ID); - stwfb->base.state_manager = stw_dev->smapi; - - stwfb->base.visual = &stwfb->stvis; - p_atomic_set(&stwfb->base.stamp, 1); - stwfb->base.flush_front = stw_st_framebuffer_flush_front; - stwfb->base.validate = stw_st_framebuffer_validate; - - return &stwfb->base; -} - -/** - * Destroy a framebuffer interface. - */ -void -stw_st_destroy_framebuffer_locked(struct st_framebuffer_iface *stfb) -{ - struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb); - int i; - - for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { - pipe_resource_reference(&stwfb->msaa_textures[i], NULL); - pipe_resource_reference(&stwfb->textures[i], NULL); - } - - /* Notify the st manager that the framebuffer interface is no - * longer valid. - */ - stw_dev->stapi->destroy_drawable(stw_dev->stapi, &stwfb->base); - - FREE(stwfb); -} - -/** - * Swap the buffers of the given framebuffer. - */ -bool -stw_st_swap_framebuffer_locked(HDC hdc, struct st_context_iface *stctx, - struct st_framebuffer_iface *stfb) -{ - struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb); - unsigned front = ST_ATTACHMENT_FRONT_LEFT, back = ST_ATTACHMENT_BACK_LEFT; - struct pipe_resource *ptex; - unsigned mask; - - /* swap the textures */ - ptex = stwfb->textures[front]; - stwfb->textures[front] = stwfb->textures[back]; - stwfb->textures[back] = ptex; - - /* swap msaa_textures */ - ptex = stwfb->msaa_textures[front]; - stwfb->msaa_textures[front] = stwfb->msaa_textures[back]; - stwfb->msaa_textures[back] = ptex; - - /* convert to mask */ - front = 1 << front; - back = 1 << back; - - /* swap the bits in mask */ - mask = stwfb->texture_mask & ~(front | back); - if (stwfb->texture_mask & front) - mask |= back; - if (stwfb->texture_mask & back) - mask |= front; - stwfb->texture_mask = mask; - - front = ST_ATTACHMENT_FRONT_LEFT; - return stw_st_framebuffer_present_locked(hdc, stctx, &stwfb->base, front); -} - - -/** - * Return the pipe_resource that correspond to given buffer. - */ -struct pipe_resource * -stw_get_framebuffer_resource(struct st_framebuffer_iface *stfb, - enum st_attachment_type att) -{ - struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb); - return stwfb->textures[att]; -} - - -/** - * Create an st_api of the state tracker. - */ -struct st_api * -stw_st_create_api(void) -{ - return st_gl_api_create(); -} diff --git a/src/gallium/state_trackers/wgl/stw_st.h b/src/gallium/state_trackers/wgl/stw_st.h deleted file mode 100644 index 20d491fa609..00000000000 --- a/src/gallium/state_trackers/wgl/stw_st.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Mesa 3-D graphics library - * - * Copyright (C) 2010 LunarG Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: - * Chia-I Wu - */ - -#ifndef STW_ST_H -#define STW_ST_H - -#include - -#include "state_tracker/st_api.h" - -struct stw_framebuffer; - -bool -stw_own_mutex(const CRITICAL_SECTION *cs); - -struct st_api * -stw_st_create_api(void); - -struct st_framebuffer_iface * -stw_st_create_framebuffer(struct stw_framebuffer *fb); - -void -stw_st_destroy_framebuffer_locked(struct st_framebuffer_iface *stfb); - -bool -stw_st_swap_framebuffer_locked(HDC hdc, struct st_context_iface *stctx, - struct st_framebuffer_iface *stfb); - -struct pipe_resource * -stw_get_framebuffer_resource(struct st_framebuffer_iface *stfb, - enum st_attachment_type att); - -#endif /* STW_ST_H */ diff --git a/src/gallium/state_trackers/wgl/stw_tls.c b/src/gallium/state_trackers/wgl/stw_tls.c deleted file mode 100644 index 9b7d60c6d8c..00000000000 --- a/src/gallium/state_trackers/wgl/stw_tls.c +++ /dev/null @@ -1,305 +0,0 @@ -/************************************************************************** - * - * Copyright 2009-2013 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include -#include - -#include "pipe/p_compiler.h" -#include "util/u_debug.h" -#include "stw_tls.h" - -static DWORD tlsIndex = TLS_OUT_OF_INDEXES; - - -/** - * Static mutex to protect the access to g_pendingTlsData global and - * stw_tls_data::next member. - */ -static CRITICAL_SECTION g_mutex = { - (PCRITICAL_SECTION_DEBUG)-1, -1, 0, 0, 0, 0 -}; - -/** - * There is no way to invoke TlsSetValue for a different thread, so we - * temporarily put the thread data for non-current threads here. - */ -static struct stw_tls_data *g_pendingTlsData = NULL; - - -static struct stw_tls_data * -stw_tls_data_create(DWORD dwThreadId); - -static struct stw_tls_data * -stw_tls_lookup_pending_data(DWORD dwThreadId); - - -boolean -stw_tls_init(void) -{ - tlsIndex = TlsAlloc(); - if (tlsIndex == TLS_OUT_OF_INDEXES) { - return FALSE; - } - - /* - * DllMain is called with DLL_THREAD_ATTACH only for threads created after - * the DLL is loaded by the process. So enumerate and add our hook to all - * previously existing threads. - * - * XXX: Except for the current thread since it there is an explicit - * stw_tls_init_thread() call for it later on. - */ - if (1) { - DWORD dwCurrentProcessId = GetCurrentProcessId(); - DWORD dwCurrentThreadId = GetCurrentThreadId(); - HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, dwCurrentProcessId); - if (hSnapshot != INVALID_HANDLE_VALUE) { - THREADENTRY32 te; - te.dwSize = sizeof te; - if (Thread32First(hSnapshot, &te)) { - do { - if (te.dwSize >= FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) + - sizeof te.th32OwnerProcessID) { - if (te.th32OwnerProcessID == dwCurrentProcessId) { - if (te.th32ThreadID != dwCurrentThreadId) { - struct stw_tls_data *data; - data = stw_tls_data_create(te.th32ThreadID); - if (data) { - EnterCriticalSection(&g_mutex); - data->next = g_pendingTlsData; - g_pendingTlsData = data; - LeaveCriticalSection(&g_mutex); - } - } - } - } - te.dwSize = sizeof te; - } while (Thread32Next(hSnapshot, &te)); - } - CloseHandle(hSnapshot); - } - } - - return TRUE; -} - - -/** - * Install windows hook for a given thread (not necessarily the current one). - */ -static struct stw_tls_data * -stw_tls_data_create(DWORD dwThreadId) -{ - struct stw_tls_data *data; - - if (0) { - debug_printf("%s(0x%04lx)\n", __FUNCTION__, dwThreadId); - } - - data = calloc(1, sizeof *data); - if (!data) { - goto no_data; - } - - data->dwThreadId = dwThreadId; - - data->hCallWndProcHook = SetWindowsHookEx(WH_CALLWNDPROC, - stw_call_window_proc, - NULL, - dwThreadId); - if (data->hCallWndProcHook == NULL) { - goto no_hook; - } - - return data; - -no_hook: - free(data); -no_data: - return NULL; -} - -/** - * Destroy the per-thread data/hook. - * - * It is important to remove all hooks when unloading our DLL, otherwise our - * hook function might be called after it is no longer there. - */ -static void -stw_tls_data_destroy(struct stw_tls_data *data) -{ - assert(data); - if (!data) { - return; - } - - if (0) { - debug_printf("%s(0x%04lx)\n", __FUNCTION__, data->dwThreadId); - } - - if (data->hCallWndProcHook) { - UnhookWindowsHookEx(data->hCallWndProcHook); - data->hCallWndProcHook = NULL; - } - - free(data); -} - -boolean -stw_tls_init_thread(void) -{ - struct stw_tls_data *data; - - if (tlsIndex == TLS_OUT_OF_INDEXES) { - return FALSE; - } - - data = stw_tls_data_create(GetCurrentThreadId()); - if (!data) { - return FALSE; - } - - TlsSetValue(tlsIndex, data); - - return TRUE; -} - -void -stw_tls_cleanup_thread(void) -{ - struct stw_tls_data *data; - - if (tlsIndex == TLS_OUT_OF_INDEXES) { - return; - } - - data = (struct stw_tls_data *) TlsGetValue(tlsIndex); - if (data) { - TlsSetValue(tlsIndex, NULL); - } else { - /* See if there this thread's data in on the pending list */ - data = stw_tls_lookup_pending_data(GetCurrentThreadId()); - } - - if (data) { - stw_tls_data_destroy(data); - } -} - -void -stw_tls_cleanup(void) -{ - if (tlsIndex != TLS_OUT_OF_INDEXES) { - /* - * Destroy all items in g_pendingTlsData linked list. - */ - EnterCriticalSection(&g_mutex); - while (g_pendingTlsData) { - struct stw_tls_data * data = g_pendingTlsData; - g_pendingTlsData = data->next; - stw_tls_data_destroy(data); - } - LeaveCriticalSection(&g_mutex); - - TlsFree(tlsIndex); - tlsIndex = TLS_OUT_OF_INDEXES; - } -} - -/* - * Search for the current thread in the g_pendingTlsData linked list. - * - * It will remove and return the node on success, or return NULL on failure. - */ -static struct stw_tls_data * -stw_tls_lookup_pending_data(DWORD dwThreadId) -{ - struct stw_tls_data ** p_data; - struct stw_tls_data *data = NULL; - - EnterCriticalSection(&g_mutex); - for (p_data = &g_pendingTlsData; *p_data; p_data = &(*p_data)->next) { - if ((*p_data)->dwThreadId == dwThreadId) { - data = *p_data; - - /* - * Unlink the node. - */ - *p_data = data->next; - data->next = NULL; - - break; - } - } - LeaveCriticalSection(&g_mutex); - - return data; -} - -struct stw_tls_data * -stw_tls_get_data(void) -{ - struct stw_tls_data *data; - - if (tlsIndex == TLS_OUT_OF_INDEXES) { - return NULL; - } - - data = (struct stw_tls_data *) TlsGetValue(tlsIndex); - if (!data) { - DWORD dwCurrentThreadId = GetCurrentThreadId(); - - /* - * Search for the current thread in the g_pendingTlsData linked list. - */ - data = stw_tls_lookup_pending_data(dwCurrentThreadId); - - if (!data) { - /* - * This should be impossible now. - */ - assert(!"Failed to find thread data for thread id"); - - /* - * DllMain is called with DLL_THREAD_ATTACH only by threads created - * after the DLL is loaded by the process - */ - data = stw_tls_data_create(dwCurrentThreadId); - if (!data) { - return NULL; - } - } - - TlsSetValue(tlsIndex, data); - } - - assert(data); - assert(data->dwThreadId = GetCurrentThreadId()); - assert(data->next == NULL); - - return data; -} diff --git a/src/gallium/state_trackers/wgl/stw_tls.h b/src/gallium/state_trackers/wgl/stw_tls.h deleted file mode 100644 index 07cfe3168d9..00000000000 --- a/src/gallium/state_trackers/wgl/stw_tls.h +++ /dev/null @@ -1,63 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#ifndef STW_TLS_H -#define STW_TLS_H - -#include - -struct stw_tls_data -{ - DWORD dwThreadId; - - HHOOK hCallWndProcHook; - - struct stw_tls_data *next; -}; - -boolean -stw_tls_init(void); - -boolean -stw_tls_init_thread(void); - -void -stw_tls_cleanup_thread(void); - -void -stw_tls_cleanup(void); - -struct stw_tls_data * -stw_tls_get_data(void); - -LRESULT CALLBACK -stw_call_window_proc( - int nCode, - WPARAM wParam, - LPARAM lParam ); - -#endif /* STW_TLS_H */ diff --git a/src/gallium/state_trackers/wgl/stw_wgl.c b/src/gallium/state_trackers/wgl/stw_wgl.c deleted file mode 100644 index 9103c750ea9..00000000000 --- a/src/gallium/state_trackers/wgl/stw_wgl.c +++ /dev/null @@ -1,400 +0,0 @@ -/************************************************************************** - * - * Copyright 2008 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/** - * @file - * - * Fake WGL API implementation. - * - * These functions implement the WGL API, on top of the ICD DDI, so that the - * resulting DLL can be used as a drop-in replacement for the system's - * opengl32.dll. - * - * These functions never get called for ICD drivers, which use exclusively the - * ICD DDI, i.e., the Drv* entrypoints. - */ - -#include -#include - -#include "util/u_debug.h" -#include "gldrv.h" -#include "stw_context.h" -#include "stw_pixelformat.h" -#include "stw_wgl.h" -#include "stw_ext_context.h" - - -static void -overrideOpenGL32EntryPoints(void); - -WINGDIAPI BOOL APIENTRY -wglCopyContext( - HGLRC hglrcSrc, - HGLRC hglrcDst, - UINT mask ) -{ - return DrvCopyContext( (DHGLRC)(UINT_PTR)hglrcSrc, - (DHGLRC)(UINT_PTR)hglrcDst, - mask ); -} - -WINGDIAPI HGLRC APIENTRY -wglCreateContext( - HDC hdc ) -{ - overrideOpenGL32EntryPoints(); - return (HGLRC)(UINT_PTR)DrvCreateContext(hdc); -} - -WINGDIAPI HGLRC APIENTRY -wglCreateLayerContext( - HDC hdc, - int iLayerPlane ) -{ - overrideOpenGL32EntryPoints(); - return (HGLRC)(UINT_PTR)DrvCreateLayerContext( hdc, iLayerPlane ); -} - -WINGDIAPI BOOL APIENTRY -wglDeleteContext( - HGLRC hglrc ) -{ - return DrvDeleteContext((DHGLRC)(UINT_PTR)hglrc ); -} - - -WINGDIAPI HGLRC APIENTRY -wglGetCurrentContext( VOID ) -{ - return (HGLRC)(UINT_PTR)stw_get_current_context(); -} - -WINGDIAPI HDC APIENTRY -wglGetCurrentDC( VOID ) -{ - return stw_get_current_dc(); -} - -WINGDIAPI HDC APIENTRY -wglGetCurrentReadDCARB( VOID ) -{ - return stw_get_current_read_dc(); -} - - -WINGDIAPI BOOL APIENTRY -wglMakeCurrent( - HDC hdc, - HGLRC hglrc ) -{ - return DrvSetContext( hdc, (DHGLRC)(UINT_PTR)hglrc, NULL ) ? TRUE : FALSE; -} - - -WINGDIAPI BOOL APIENTRY -wglSwapBuffers( - HDC hdc ) -{ - return DrvSwapBuffers( hdc ); -} - - -WINGDIAPI DWORD WINAPI -wglSwapMultipleBuffers(UINT n, - CONST WGLSWAP *ps) -{ - UINT i; - - for (i =0; i < n; ++i) - wglSwapBuffers(ps->hdc); - - return 0; -} - - -WINGDIAPI BOOL APIENTRY -wglSwapLayerBuffers( - HDC hdc, - UINT fuPlanes ) -{ - return DrvSwapLayerBuffers( hdc, fuPlanes ); -} - -WINGDIAPI PROC APIENTRY -wglGetProcAddress( - LPCSTR lpszProc ) -{ - return DrvGetProcAddress( lpszProc ); -} - - -WINGDIAPI int APIENTRY -wglChoosePixelFormat( - HDC hdc, - CONST PIXELFORMATDESCRIPTOR *ppfd ) -{ - if (ppfd->nSize != sizeof( PIXELFORMATDESCRIPTOR ) || ppfd->nVersion != 1) - return 0; - if (ppfd->iPixelType != PFD_TYPE_RGBA) - return 0; - if (!(ppfd->dwFlags & PFD_DRAW_TO_WINDOW)) - return 0; - if (!(ppfd->dwFlags & PFD_SUPPORT_OPENGL)) - return 0; - if (ppfd->dwFlags & PFD_DRAW_TO_BITMAP) - return 0; - if (ppfd->dwFlags & PFD_SUPPORT_GDI) - return 0; - if (!(ppfd->dwFlags & PFD_STEREO_DONTCARE) && (ppfd->dwFlags & PFD_STEREO)) - return 0; - - return stw_pixelformat_choose( hdc, ppfd ); -} - -WINGDIAPI int APIENTRY -wglDescribePixelFormat( - HDC hdc, - int iPixelFormat, - UINT nBytes, - LPPIXELFORMATDESCRIPTOR ppfd ) -{ - return DrvDescribePixelFormat( hdc, iPixelFormat, nBytes, ppfd ); -} - -WINGDIAPI int APIENTRY -wglGetPixelFormat( - HDC hdc ) -{ - return stw_pixelformat_get( hdc ); -} - -WINGDIAPI BOOL APIENTRY -wglSetPixelFormat( - HDC hdc, - int iPixelFormat, - const PIXELFORMATDESCRIPTOR *ppfd ) -{ - /* SetPixelFormat (hence wglSetPixelFormat) must not touch ppfd, per - * http://msdn.microsoft.com/en-us/library/dd369049(v=vs.85).aspx - */ - (void) ppfd; - - return DrvSetPixelFormat( hdc, iPixelFormat ); -} - - -WINGDIAPI BOOL APIENTRY -wglUseFontBitmapsA( - HDC hdc, - DWORD first, - DWORD count, - DWORD listBase ) -{ - return wglUseFontBitmapsW(hdc, first, count, listBase); -} - -WINGDIAPI BOOL APIENTRY -wglShareLists( - HGLRC hglrc1, - HGLRC hglrc2 ) -{ - return DrvShareLists((DHGLRC)(UINT_PTR)hglrc1, - (DHGLRC)(UINT_PTR)hglrc2); -} - -WINGDIAPI BOOL APIENTRY -wglUseFontBitmapsW( - HDC hdc, - DWORD first, - DWORD count, - DWORD listBase ) -{ - GLYPHMETRICS gm; - MAT2 tra; - FIXED one, minus_one, zero; - void *buffer = NULL; - BOOL result = TRUE; - - one.value = 1; - one.fract = 0; - minus_one.value = -1; - minus_one.fract = 0; - zero.value = 0; - zero.fract = 0; - - tra.eM11 = one; - tra.eM22 = minus_one; - tra.eM12 = tra.eM21 = zero; - - for (int i = 0; i < count; i++) { - DWORD size = GetGlyphOutline(hdc, first + i, GGO_BITMAP, &gm, 0, - NULL, &tra); - - glNewList(listBase + i, GL_COMPILE); - - if (size != GDI_ERROR) { - if (size == 0) { - glBitmap(0, 0, (GLfloat)-gm.gmptGlyphOrigin.x, - (GLfloat)gm.gmptGlyphOrigin.y, - (GLfloat)gm.gmCellIncX, - (GLfloat)gm.gmCellIncY, NULL); - } - else { - buffer = realloc(buffer, size); - size = GetGlyphOutline(hdc, first + i, GGO_BITMAP, &gm, - size, buffer, &tra); - - glBitmap(gm.gmBlackBoxX, gm.gmBlackBoxY, - -gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y, - gm.gmCellIncX, gm.gmCellIncY, buffer); - } - } - else { - result = FALSE; - } - - glEndList(); - } - - free(buffer); - - return result; -} - -WINGDIAPI BOOL APIENTRY -wglUseFontOutlinesA( - HDC hdc, - DWORD first, - DWORD count, - DWORD listBase, - FLOAT deviation, - FLOAT extrusion, - int format, - LPGLYPHMETRICSFLOAT lpgmf ) -{ - (void) hdc; - (void) first; - (void) count; - (void) listBase; - (void) deviation; - (void) extrusion; - (void) format; - (void) lpgmf; - - assert( 0 ); - - return FALSE; -} - -WINGDIAPI BOOL APIENTRY -wglUseFontOutlinesW( - HDC hdc, - DWORD first, - DWORD count, - DWORD listBase, - FLOAT deviation, - FLOAT extrusion, - int format, - LPGLYPHMETRICSFLOAT lpgmf ) -{ - (void) hdc; - (void) first; - (void) count; - (void) listBase; - (void) deviation; - (void) extrusion; - (void) format; - (void) lpgmf; - - assert( 0 ); - - return FALSE; -} - -WINGDIAPI BOOL APIENTRY -wglDescribeLayerPlane( - HDC hdc, - int iPixelFormat, - int iLayerPlane, - UINT nBytes, - LPLAYERPLANEDESCRIPTOR plpd ) -{ - return DrvDescribeLayerPlane(hdc, iPixelFormat, iLayerPlane, nBytes, plpd); -} - -WINGDIAPI int APIENTRY -wglSetLayerPaletteEntries( - HDC hdc, - int iLayerPlane, - int iStart, - int cEntries, - CONST COLORREF *pcr ) -{ - return DrvSetLayerPaletteEntries(hdc, iLayerPlane, iStart, cEntries, pcr); -} - -WINGDIAPI int APIENTRY -wglGetLayerPaletteEntries( - HDC hdc, - int iLayerPlane, - int iStart, - int cEntries, - COLORREF *pcr ) -{ - return DrvGetLayerPaletteEntries(hdc, iLayerPlane, iStart, cEntries, pcr); -} - -WINGDIAPI BOOL APIENTRY -wglRealizeLayerPalette( - HDC hdc, - int iLayerPlane, - BOOL bRealize ) -{ - (void) hdc; - (void) iLayerPlane; - (void) bRealize; - - assert( 0 ); - - return FALSE; -} - - -/* When this library is used as a opengl32.dll drop-in replacement, ensure we - * use the wglCreate/Destroy entrypoints above, and not the true opengl32.dll, - * which could happen if this library's name is not opengl32.dll exactly. - * - * For example, Qt 5.4 bundles this as opengl32sw.dll: - * https://blog.qt.io/blog/2014/11/27/qt-weekly-21-dynamic-opengl-implementation-loading-in-qt-5-4/ - */ -static void -overrideOpenGL32EntryPoints(void) -{ - wglCreateContext_func = &wglCreateContext; - wglDeleteContext_func = &wglDeleteContext; -} diff --git a/src/gallium/state_trackers/wgl/stw_wgl.h b/src/gallium/state_trackers/wgl/stw_wgl.h deleted file mode 100644 index 92d70b5da9e..00000000000 --- a/src/gallium/state_trackers/wgl/stw_wgl.h +++ /dev/null @@ -1,89 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#ifndef STW_WGL_H_ -#define STW_WGL_H_ - - -#include - -#include - - -/* - * Undeclared APIs exported by opengl32.dll - */ - -WINGDIAPI BOOL WINAPI -wglSwapBuffers(HDC hdc); - -WINGDIAPI int WINAPI -wglChoosePixelFormat(HDC hdc, - CONST PIXELFORMATDESCRIPTOR *ppfd); - -WINGDIAPI int WINAPI -wglDescribePixelFormat(HDC hdc, - int iPixelFormat, - UINT nBytes, - LPPIXELFORMATDESCRIPTOR ppfd); - -WINGDIAPI int WINAPI -wglGetPixelFormat(HDC hdc); - -WINGDIAPI BOOL WINAPI -wglSetPixelFormat(HDC hdc, - int iPixelFormat, - CONST PIXELFORMATDESCRIPTOR *ppfd); - -WINGDIAPI HDC APIENTRY -wglGetCurrentReadDCARB( VOID ); - -WINGDIAPI BOOL APIENTRY -wglMakeContextCurrentARB( - HDC hDrawDC, - HDC hReadDC, - HGLRC hglrc ); - - -#ifndef WGL_SWAPMULTIPLE_MAX - -typedef struct _WGLSWAP -{ - HDC hdc; - UINT uiFlags; -} WGLSWAP; - -#define WGL_SWAPMULTIPLE_MAX 16 - -WINGDIAPI DWORD WINAPI -wglSwapMultipleBuffers(UINT n, - CONST WGLSWAP *ps); - -#endif /* !WGL_SWAPMULTIPLE_MAX */ - - -#endif /* STW_WGL_H_ */ diff --git a/src/gallium/state_trackers/wgl/stw_winsys.h b/src/gallium/state_trackers/wgl/stw_winsys.h deleted file mode 100644 index 281b201bc22..00000000000 --- a/src/gallium/state_trackers/wgl/stw_winsys.h +++ /dev/null @@ -1,107 +0,0 @@ -/************************************************************************** - * - * Copyright 2008-2009 Vmware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#ifndef STW_WINSYS_H -#define STW_WINSYS_H - -#include /* for HDC */ - -#include "pipe/p_compiler.h" - -struct pipe_screen; -struct pipe_context; -struct pipe_resource; - -struct stw_shared_surface; - -struct stw_winsys -{ - struct pipe_screen * - (*create_screen)( void ); - - /* XXX is it actually possible to have non-zero level/layer ??? */ - /** - * Present the color buffer to the window associated with the device context. - */ - void - (*present)( struct pipe_screen *screen, - struct pipe_resource *res, - HDC hDC ); - - /** - * Locally unique identifier (LUID) of the graphics adapter. - * - * @sa GLCBPRESENTBUFFERSDATA::AdapterLuid; - */ - boolean - (*get_adapter_luid)( struct pipe_screen *screen, - LUID *pAdapterLuid ); - - /** - * Open a shared surface (optional). - * - * @sa GLCBPRESENTBUFFERSDATA::hSharedSurface; - */ - struct stw_shared_surface * - (*shared_surface_open)(struct pipe_screen *screen, - HANDLE hSharedSurface); - - /** - * Close a shared surface (optional). - */ - void - (*shared_surface_close)(struct pipe_screen *screen, - struct stw_shared_surface *surface); - - /** - * Compose into a shared surface (optional). - * - * Blit the color buffer into a shared surface. - * - * @sa GLPRESENTBUFFERSDATA::PresentHistoryToken. - */ - void - (*compose)( struct pipe_screen *screen, - struct pipe_resource *res, - struct stw_shared_surface *dest, - LPCRECT pRect, - ULONGLONG PresentHistoryToken ); -}; - -boolean -stw_init(const struct stw_winsys *stw_winsys); - -boolean -stw_init_thread(void); - -void -stw_cleanup_thread(void); - -void -stw_cleanup(void); - -#endif /* STW_WINSYS_H */ diff --git a/src/gallium/state_trackers/xa/.editorconfig b/src/gallium/state_trackers/xa/.editorconfig deleted file mode 100644 index 7b12a40ca00..00000000000 --- a/src/gallium/state_trackers/xa/.editorconfig +++ /dev/null @@ -1,3 +0,0 @@ -[*.{c,h}] -indent_style = space -indent_size = 4 diff --git a/src/gallium/state_trackers/xa/Makefile.sources b/src/gallium/state_trackers/xa/Makefile.sources deleted file mode 100644 index cdcc4187ac1..00000000000 --- a/src/gallium/state_trackers/xa/Makefile.sources +++ /dev/null @@ -1,8 +0,0 @@ -C_SOURCES := \ - xa_composite.c \ - xa_context.c \ - xa_priv.h \ - xa_renderer.c \ - xa_tgsi.c \ - xa_tracker.c \ - xa_yuv.c diff --git a/src/gallium/state_trackers/xa/README b/src/gallium/state_trackers/xa/README deleted file mode 100644 index 1f08861588c..00000000000 --- a/src/gallium/state_trackers/xa/README +++ /dev/null @@ -1,72 +0,0 @@ -/********************************************************** - * Copyright 2009-2011 VMware, Inc. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - ********************************************************* - * Authors: - * Zack Rusin - * Thomas Hellstrom - */ - -The XA state tracker is intended as a versioned interface to gallium for -xorg driver writers. Initially it's mostly based on Zack Rusin's -composite / video work for the Xorg state tracker. - -The motivation behind this state tracker is that the Xorg state tracker has -a number of interfaces to work with: - -1) The Xorg sdk (versioned) -2) Gallium3D (not versioned) -3) KMS modesetting (versioned) -4) Driver-private (hopefully versioned) - -Since Gallium3D is not versioned, the Xorg state tracker needs to be compiled -with Gallium, but it's really beneficial to be able to compile xorg drivers -standalone. - -Therefore the xa state tracker is intended to supply the following -functionality: - -1) Versioning. -2) Surface functionality (creation and copying for a basic dri2 implementation) -3) YUV blits for textured Xv. -4) Solid fills without ROP functionality. -5) Copies with format conversion and - reinterpretation but without ROP -6) Xrender- type compositing for general acceleration. - - -The first user will be the vmwgfx xorg driver. When there are more users, -we need to be able to load the appropriate gallium pipe driver, and we -should investigate sharing the loadig mechanism with the EGL state tracker. - -IMPORTANT: -Version compatibilities: -While this library remains OUTSIDE any mesa release branch, -and the major version number is still 0. Any minor bump should be viewed as -an incompatibility event, and any user of this library should test for that -and refuse to use the library if minor versions differ. -As soon as the library enters a mesa release branch, if not earlier, major -will be bumped to 1, and normal incompatibility rules (major bump) -will be followed. -It is allowed to add function interfaces while only bumping minor. Any -user that uses these function interfaces must therefore use lazy symbol -lookups and test minor for compatibility before using such a function. diff --git a/src/gallium/state_trackers/xa/meson.build b/src/gallium/state_trackers/xa/meson.build deleted file mode 100644 index 0c3540f0359..00000000000 --- a/src/gallium/state_trackers/xa/meson.build +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright © 2017 Intel Corporation - -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: - -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. - -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -xa_version = ['2', '5', '0'] - -xa_conf = configuration_data() -xa_conf.set('XA_MAJOR', xa_version[0]) -xa_conf.set('XA_MINOR', xa_version[1]) -xa_conf.set('XA_PATCH', xa_version[2]) - -xa_tracker_h = configure_file( - configuration : xa_conf, - input : 'xa_tracker.h.in', - output : 'xa_tracker.h', - install_dir : get_option('includedir'), -) - -libxa_st = static_library( - 'xa_st', - [xa_tracker_h, files( - 'xa_composite.c', 'xa_context.c', 'xa_renderer.c', 'xa_tgsi.c', - 'xa_tracker.c', 'xa_yuv.c', - )], - c_args : [c_vis_args, '-pedantic'], - include_directories : [inc_include, inc_src, inc_mapi, inc_mesa, inc_gallium, inc_gallium_aux], -) - -install_headers('xa_composite.h', 'xa_context.h') diff --git a/src/gallium/state_trackers/xa/xa-indent.sh b/src/gallium/state_trackers/xa/xa-indent.sh deleted file mode 100755 index 90241a3772e..00000000000 --- a/src/gallium/state_trackers/xa/xa-indent.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -indent --linux-style -i4 -ip4 -bad -bap -psl $* - diff --git a/src/gallium/state_trackers/xa/xa_composite.c b/src/gallium/state_trackers/xa/xa_composite.c deleted file mode 100644 index 34d78027e27..00000000000 --- a/src/gallium/state_trackers/xa/xa_composite.c +++ /dev/null @@ -1,592 +0,0 @@ -/********************************************************** - * Copyright 2009-2011 VMware, Inc. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - ********************************************************* - * Authors: - * Zack Rusin - * Thomas Hellstrom - */ - -#include "xa_composite.h" -#include "xa_context.h" -#include "xa_priv.h" -#include "cso_cache/cso_context.h" -#include "util/u_sampler.h" -#include "util/u_inlines.h" - - -/*XXX also in Xrender.h but the including it here breaks compilition */ -#define XFixedToDouble(f) (((double) (f)) / 65536.) - -struct xa_composite_blend { - unsigned op : 8; - - unsigned alpha_dst : 4; - unsigned alpha_src : 4; - - unsigned rgb_src : 8; /**< PIPE_BLENDFACTOR_x */ - unsigned rgb_dst : 8; /**< PIPE_BLENDFACTOR_x */ -}; - -#define XA_BLEND_OP_OVER 3 -static const struct xa_composite_blend xa_blends[] = { - { xa_op_clear, - 0, 0, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO}, - { xa_op_src, - 0, 0, PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ZERO}, - { xa_op_dst, - 0, 0, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ONE}, - { xa_op_over, - 0, 1, PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_INV_SRC_ALPHA}, - { xa_op_over_reverse, - 1, 0, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_ONE}, - { xa_op_in, - 1, 0, PIPE_BLENDFACTOR_DST_ALPHA, PIPE_BLENDFACTOR_ZERO}, - { xa_op_in_reverse, - 0, 1, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_SRC_ALPHA}, - { xa_op_out, - 1, 0, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_ZERO}, - { xa_op_out_reverse, - 0, 1, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_INV_SRC_ALPHA}, - { xa_op_atop, - 1, 1, PIPE_BLENDFACTOR_DST_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA}, - { xa_op_atop_reverse, - 1, 1, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_SRC_ALPHA}, - { xa_op_xor, - 1, 1, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA}, - { xa_op_add, - 0, 0, PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ONE}, -}; - -/* - * The alpha value stored in a L8 texture is read by the - * hardware as color, and R8 is read as red. The source alpha value - * at the end of the fragment shader is stored in all color channels, - * so the correct approach is to blend using DST_COLOR instead of - * DST_ALPHA and then output any color channel (L8) or the red channel (R8). - */ -static unsigned -xa_convert_blend_for_luminance(unsigned factor) -{ - switch(factor) { - case PIPE_BLENDFACTOR_DST_ALPHA: - return PIPE_BLENDFACTOR_DST_COLOR; - case PIPE_BLENDFACTOR_INV_DST_ALPHA: - return PIPE_BLENDFACTOR_INV_DST_COLOR; - default: - break; - } - return factor; -} - -static boolean -blend_for_op(struct xa_composite_blend *blend, - enum xa_composite_op op, - struct xa_picture *src_pic, - struct xa_picture *mask_pic, - struct xa_picture *dst_pic) -{ - const int num_blends = - sizeof(xa_blends)/sizeof(struct xa_composite_blend); - int i; - boolean supported = FALSE; - - /* - * our default in case something goes wrong - */ - *blend = xa_blends[XA_BLEND_OP_OVER]; - - for (i = 0; i < num_blends; ++i) { - if (xa_blends[i].op == op) { - *blend = xa_blends[i]; - supported = TRUE; - break; - } - } - - /* - * No component alpha yet. - */ - if (mask_pic && mask_pic->component_alpha && blend->alpha_src) - return FALSE; - - if (!dst_pic->srf) - return supported; - - if ((dst_pic->srf->tex->format == PIPE_FORMAT_L8_UNORM || - dst_pic->srf->tex->format == PIPE_FORMAT_R8_UNORM)) { - blend->rgb_src = xa_convert_blend_for_luminance(blend->rgb_src); - blend->rgb_dst = xa_convert_blend_for_luminance(blend->rgb_dst); - } - - /* - * If there's no dst alpha channel, adjust the blend op so that we'll treat - * it as always 1. - */ - - if (xa_format_a(dst_pic->pict_format) == 0 && blend->alpha_dst) { - if (blend->rgb_src == PIPE_BLENDFACTOR_DST_ALPHA) - blend->rgb_src = PIPE_BLENDFACTOR_ONE; - else if (blend->rgb_src == PIPE_BLENDFACTOR_INV_DST_ALPHA) - blend->rgb_src = PIPE_BLENDFACTOR_ZERO; - } - - return supported; -} - - -static inline int -xa_repeat_to_gallium(int mode) -{ - switch(mode) { - case xa_wrap_clamp_to_border: - return PIPE_TEX_WRAP_CLAMP_TO_BORDER; - case xa_wrap_repeat: - return PIPE_TEX_WRAP_REPEAT; - case xa_wrap_mirror_repeat: - return PIPE_TEX_WRAP_MIRROR_REPEAT; - case xa_wrap_clamp_to_edge: - return PIPE_TEX_WRAP_CLAMP_TO_EDGE; - default: - break; - } - return PIPE_TEX_WRAP_REPEAT; -} - -static inline boolean -xa_filter_to_gallium(int xrender_filter, int *out_filter) -{ - - switch (xrender_filter) { - case xa_filter_nearest: - *out_filter = PIPE_TEX_FILTER_NEAREST; - break; - case xa_filter_linear: - *out_filter = PIPE_TEX_FILTER_LINEAR; - break; - default: - *out_filter = PIPE_TEX_FILTER_NEAREST; - return FALSE; - } - return TRUE; -} - -static int -xa_is_filter_accelerated(struct xa_picture *pic) -{ - int filter; - if (pic && !xa_filter_to_gallium(pic->filter, &filter)) - return 0; - return 1; -} - -/** - * xa_src_pict_is_accelerated - Check whether we support acceleration - * of the given src_pict type - * - * \param src_pic[in]: Pointer to a union xa_source_pict to check. - * - * \returns TRUE if accelerated, FALSE otherwise. - */ -static boolean -xa_src_pict_is_accelerated(const union xa_source_pict *src_pic) -{ - if (!src_pic) - return TRUE; - - if (src_pic->type == xa_src_pict_solid_fill || - src_pic->type == xa_src_pict_float_solid_fill) - return TRUE; - - return FALSE; -} - -XA_EXPORT int -xa_composite_check_accelerated(const struct xa_composite *comp) -{ - struct xa_picture *src_pic = comp->src; - struct xa_picture *mask_pic = comp->mask; - struct xa_composite_blend blend; - - if (!xa_is_filter_accelerated(src_pic) || - !xa_is_filter_accelerated(comp->mask)) { - return -XA_ERR_INVAL; - } - - if (!xa_src_pict_is_accelerated(src_pic->src_pict) || - (mask_pic && !xa_src_pict_is_accelerated(mask_pic->src_pict))) - return -XA_ERR_INVAL; - - if (!blend_for_op(&blend, comp->op, comp->src, comp->mask, comp->dst)) - return -XA_ERR_INVAL; - - /* - * No component alpha yet. - */ - if (mask_pic && mask_pic->component_alpha && blend.alpha_src) - return -XA_ERR_INVAL; - - return XA_ERR_NONE; -} - -static int -bind_composite_blend_state(struct xa_context *ctx, - const struct xa_composite *comp) -{ - struct xa_composite_blend blend_opt; - struct pipe_blend_state blend; - - if (!blend_for_op(&blend_opt, comp->op, comp->src, comp->mask, comp->dst)) - return -XA_ERR_INVAL; - - memset(&blend, 0, sizeof(struct pipe_blend_state)); - blend.rt[0].blend_enable = 1; - blend.rt[0].colormask = PIPE_MASK_RGBA; - - blend.rt[0].rgb_src_factor = blend_opt.rgb_src; - blend.rt[0].alpha_src_factor = blend_opt.rgb_src; - blend.rt[0].rgb_dst_factor = blend_opt.rgb_dst; - blend.rt[0].alpha_dst_factor = blend_opt.rgb_dst; - - cso_set_blend(ctx->cso, &blend); - return XA_ERR_NONE; -} - -static unsigned int -picture_format_fixups(struct xa_picture *src_pic, - int mask) -{ - boolean set_alpha = FALSE; - boolean swizzle = FALSE; - unsigned ret = 0; - struct xa_surface *src = src_pic->srf; - enum xa_formats src_hw_format, src_pic_format; - enum xa_surface_type src_hw_type, src_pic_type; - - if (!src) - return 0; - - src_hw_format = xa_surface_format(src); - src_pic_format = src_pic->pict_format; - - set_alpha = (xa_format_type_is_color(src_hw_format) && - xa_format_a(src_pic_format) == 0); - - if (set_alpha) - ret |= mask ? FS_MASK_SET_ALPHA : FS_SRC_SET_ALPHA; - - if (src_hw_format == src_pic_format) { - if (src->tex->format == PIPE_FORMAT_L8_UNORM || - src->tex->format == PIPE_FORMAT_R8_UNORM) - return ((mask) ? FS_MASK_LUMINANCE : FS_SRC_LUMINANCE); - - return ret; - } - - src_hw_type = xa_format_type(src_hw_format); - src_pic_type = xa_format_type(src_pic_format); - - swizzle = ((src_hw_type == xa_type_argb && - src_pic_type == xa_type_abgr) || - ((src_hw_type == xa_type_abgr && - src_pic_type == xa_type_argb))); - - if (!swizzle && (src_hw_type != src_pic_type)) - return ret; - - if (swizzle) - ret |= mask ? FS_MASK_SWIZZLE_RGB : FS_SRC_SWIZZLE_RGB; - - return ret; -} - -static void -xa_src_in_mask(float src[4], const float mask[4]) -{ - src[0] *= mask[3]; - src[1] *= mask[3]; - src[2] *= mask[3]; - src[3] *= mask[3]; -} - -/** - * xa_handle_src_pict - Set up xa_context state and fragment shader - * input based on scr_pict type - * - * \param ctx[in, out]: Pointer to the xa context. - * \param src_pict[in]: Pointer to the union xa_source_pict to consider. - * \param is_mask[in]: Whether we're considering a mask picture. - * - * \returns TRUE if succesful, FALSE otherwise. - * - * This function computes some xa_context state used to determine whether - * to upload the solid color and also the solid color itself used as an input - * to the fragment shader. - */ -static boolean -xa_handle_src_pict(struct xa_context *ctx, - const union xa_source_pict *src_pict, - boolean is_mask) -{ - float solid_color[4]; - - switch(src_pict->type) { - case xa_src_pict_solid_fill: - xa_pixel_to_float4(src_pict->solid_fill.color, solid_color); - break; - case xa_src_pict_float_solid_fill: - memcpy(solid_color, src_pict->float_solid_fill.color, - sizeof(solid_color)); - break; - default: - return FALSE; - } - - if (is_mask && ctx->has_solid_src) - xa_src_in_mask(ctx->solid_color, solid_color); - else - memcpy(ctx->solid_color, solid_color, sizeof(solid_color)); - - if (is_mask) - ctx->has_solid_mask = TRUE; - else - ctx->has_solid_src = TRUE; - - return TRUE; -} - -static int -bind_shaders(struct xa_context *ctx, const struct xa_composite *comp) -{ - unsigned vs_traits = 0, fs_traits = 0; - struct xa_shader shader; - struct xa_picture *src_pic = comp->src; - struct xa_picture *mask_pic = comp->mask; - struct xa_picture *dst_pic = comp->dst; - - ctx->has_solid_src = FALSE; - ctx->has_solid_mask = FALSE; - - if (dst_pic && xa_format_type(dst_pic->pict_format) != - xa_format_type(xa_surface_format(dst_pic->srf))) - return -XA_ERR_INVAL; - - if (src_pic) { - if (src_pic->wrap == xa_wrap_clamp_to_border && src_pic->has_transform) - fs_traits |= FS_SRC_REPEAT_NONE; - - fs_traits |= FS_COMPOSITE; - vs_traits |= VS_COMPOSITE; - - if (src_pic->src_pict) { - if (!xa_handle_src_pict(ctx, src_pic->src_pict, false)) - return -XA_ERR_INVAL; - fs_traits |= FS_SRC_SRC; - vs_traits |= VS_SRC_SRC; - } else - fs_traits |= picture_format_fixups(src_pic, 0); - } - - if (mask_pic) { - vs_traits |= VS_MASK; - fs_traits |= FS_MASK; - if (mask_pic->component_alpha) - fs_traits |= FS_CA; - if (mask_pic->src_pict) { - if (!xa_handle_src_pict(ctx, mask_pic->src_pict, true)) - return -XA_ERR_INVAL; - - if (ctx->has_solid_src) { - vs_traits &= ~VS_MASK; - fs_traits &= ~FS_MASK; - } else { - vs_traits |= VS_MASK_SRC; - fs_traits |= FS_MASK_SRC; - } - } else { - if (mask_pic->wrap == xa_wrap_clamp_to_border && - mask_pic->has_transform) - fs_traits |= FS_MASK_REPEAT_NONE; - - fs_traits |= picture_format_fixups(mask_pic, 1); - } - } - - if (ctx->srf->format == PIPE_FORMAT_L8_UNORM || - ctx->srf->format == PIPE_FORMAT_R8_UNORM) - fs_traits |= FS_DST_LUMINANCE; - - shader = xa_shaders_get(ctx->shaders, vs_traits, fs_traits); - cso_set_vertex_shader_handle(ctx->cso, shader.vs); - cso_set_fragment_shader_handle(ctx->cso, shader.fs); - return XA_ERR_NONE; -} - -static void -bind_samplers(struct xa_context *ctx, - const struct xa_composite *comp) -{ - struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; - struct pipe_sampler_state src_sampler, mask_sampler; - struct pipe_sampler_view view_templ; - struct pipe_sampler_view *src_view; - struct pipe_context *pipe = ctx->pipe; - struct xa_picture *src_pic = comp->src; - struct xa_picture *mask_pic = comp->mask; - int num_samplers = 0; - - xa_ctx_sampler_views_destroy(ctx); - memset(&src_sampler, 0, sizeof(struct pipe_sampler_state)); - memset(&mask_sampler, 0, sizeof(struct pipe_sampler_state)); - - if (src_pic && !ctx->has_solid_src) { - unsigned src_wrap = xa_repeat_to_gallium(src_pic->wrap); - int filter; - - (void) xa_filter_to_gallium(src_pic->filter, &filter); - - src_sampler.wrap_s = src_wrap; - src_sampler.wrap_t = src_wrap; - src_sampler.min_img_filter = filter; - src_sampler.mag_img_filter = filter; - src_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST; - src_sampler.normalized_coords = 1; - samplers[0] = &src_sampler; - u_sampler_view_default_template(&view_templ, - src_pic->srf->tex,+ src_pic->srf->tex->format); - src_view = pipe->create_sampler_view(pipe, src_pic->srf->tex, - &view_templ); - ctx->bound_sampler_views[0] = src_view; - num_samplers++; - } - - if (mask_pic && !ctx->has_solid_mask) { - unsigned mask_wrap = xa_repeat_to_gallium(mask_pic->wrap); - int filter; - - (void) xa_filter_to_gallium(mask_pic->filter, &filter); - - mask_sampler.wrap_s = mask_wrap; - mask_sampler.wrap_t = mask_wrap; - mask_sampler.min_img_filter = filter; - mask_sampler.mag_img_filter = filter; - src_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST; - mask_sampler.normalized_coords = 1; - samplers[num_samplers] = &mask_sampler; - u_sampler_view_default_template(&view_templ, - mask_pic->srf->tex, - mask_pic->srf->tex->format); - src_view = pipe->create_sampler_view(pipe, mask_pic->srf->tex, - &view_templ); - ctx->bound_sampler_views[num_samplers] = src_view; - num_samplers++; - } - - cso_set_samplers(ctx->cso, PIPE_SHADER_FRAGMENT, num_samplers, - (const struct pipe_sampler_state **)samplers); - cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, num_samplers, - ctx->bound_sampler_views); - ctx->num_bound_samplers = num_samplers; -} - -XA_EXPORT int -xa_composite_prepare(struct xa_context *ctx, - const struct xa_composite *comp) -{ - struct xa_surface *dst_srf = comp->dst->srf; - int ret; - - ret = xa_ctx_srf_create(ctx, dst_srf); - if (ret != XA_ERR_NONE) - return ret; - - ctx->dst = dst_srf; - renderer_bind_destination(ctx, ctx->srf); - - ret = bind_composite_blend_state(ctx, comp); - if (ret != XA_ERR_NONE) - return ret; - ret = bind_shaders(ctx, comp); - if (ret != XA_ERR_NONE) - return ret; - bind_samplers(ctx, comp); - - if (ctx->num_bound_samplers == 0 ) { /* solid fill */ - renderer_begin_solid(ctx); - } else { - renderer_begin_textures(ctx); - ctx->comp = comp; - } - - xa_ctx_srf_destroy(ctx); - return XA_ERR_NONE; -} - -XA_EXPORT void -xa_composite_rect(struct xa_context *ctx, - int srcX, int srcY, int maskX, int maskY, - int dstX, int dstY, int width, int height) -{ - if (ctx->num_bound_samplers == 0 ) { /* solid fill */ - xa_scissor_update(ctx, dstX, dstY, dstX + width, dstY + height); - renderer_solid(ctx, dstX, dstY, dstX + width, dstY + height); - } else { - const struct xa_composite *comp = ctx->comp; - int pos[6] = {srcX, srcY, maskX, maskY, dstX, dstY}; - const float *src_matrix = NULL; - const float *mask_matrix = NULL; - - xa_scissor_update(ctx, dstX, dstY, dstX + width, dstY + height); - - if (comp->src->has_transform) - src_matrix = comp->src->transform; - if (comp->mask && comp->mask->has_transform) - mask_matrix = comp->mask->transform; - - renderer_texture(ctx, pos, width, height, - src_matrix, mask_matrix); - } -} - -XA_EXPORT void -xa_composite_done(struct xa_context *ctx) -{ - renderer_draw_flush(ctx); - - ctx->comp = NULL; - ctx->has_solid_src = FALSE; - ctx->has_solid_mask = FALSE; - xa_ctx_sampler_views_destroy(ctx); -} - -static const struct xa_composite_allocation a = { - .xa_composite_size = sizeof(struct xa_composite), - .xa_picture_size = sizeof(struct xa_picture), - .xa_source_pict_size = sizeof(union xa_source_pict), -}; - -XA_EXPORT const struct xa_composite_allocation * -xa_composite_allocation(void) -{ - return &a; -} diff --git a/src/gallium/state_trackers/xa/xa_composite.h b/src/gallium/state_trackers/xa/xa_composite.h deleted file mode 100644 index 7e3737a63d2..00000000000 --- a/src/gallium/state_trackers/xa/xa_composite.h +++ /dev/null @@ -1,156 +0,0 @@ -/********************************************************** - * Copyright 2009-2011 VMware, Inc. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - ********************************************************* - * Authors: - * Zack Rusin - * Thomas Hellstrom - */ - -#ifndef _XA_COMPOSITE_H_ -#define _XA_COMPOSITE_H_ - -#include "xa_tracker.h" -#include "xa_context.h" - -/* - * Supported composite ops. - */ -enum xa_composite_op { - xa_op_clear, - xa_op_src, - xa_op_dst, - xa_op_over, - xa_op_over_reverse, - xa_op_in, - xa_op_in_reverse, - xa_op_out, - xa_op_out_reverse, - xa_op_atop, - xa_op_atop_reverse, - xa_op_xor, - xa_op_add -}; - -/* - * Supported filters. - */ -enum xa_composite_filter { - xa_filter_nearest, - xa_filter_linear -}; - -/* - * Supported clamp methods. - */ -enum xa_composite_wrap { - xa_wrap_clamp_to_border, - xa_wrap_repeat, - xa_wrap_mirror_repeat, - xa_wrap_clamp_to_edge -}; - -/* - * Src picture types. - */ -enum xa_composite_src_pict_type { - xa_src_pict_solid_fill, - xa_src_pict_float_solid_fill -}; - - -/* - * struct xa_pict_solid_fill - Description of a solid_fill picture - * Deprecated. Use struct xa_pict_float_solid_fill instead. - */ -struct xa_pict_solid_fill { - enum xa_composite_src_pict_type type; - unsigned int class; - uint32_t color; -}; - -/* - * struct xa_pict_solid_fill - Description of a solid_fill picture - * with color channels represented by floats. - */ -struct xa_pict_float_solid_fill { - enum xa_composite_src_pict_type type; - float color[4]; /* R, G, B, A */ -}; - -union xa_source_pict { - enum xa_composite_src_pict_type type; - struct xa_pict_solid_fill solid_fill; - struct xa_pict_float_solid_fill float_solid_fill; -}; - -struct xa_picture { - enum xa_formats pict_format; - struct xa_surface *srf; - struct xa_surface *alpha_map; - float transform[9]; - int has_transform; - int component_alpha; - enum xa_composite_wrap wrap; - enum xa_composite_filter filter; - union xa_source_pict *src_pict; -}; - -struct xa_composite { - struct xa_picture *src, *mask, *dst; - int op; - int no_solid; -}; - -struct xa_composite_allocation { - unsigned int xa_composite_size; - unsigned int xa_picture_size; - unsigned int xa_source_pict_size; -}; - -/* - * Get allocation sizes for minor bump compatibility. - */ - -extern const struct xa_composite_allocation * -xa_composite_allocation(void); - -/* - * This function checks most things except the format of the hardware - * surfaces, since they are generally not available at the time this - * function is called. Returns usual XA error codes. - */ -extern int -xa_composite_check_accelerated(const struct xa_composite *comp); - -extern int -xa_composite_prepare(struct xa_context *ctx, const struct xa_composite *comp); - -extern void -xa_composite_rect(struct xa_context *ctx, - int srcX, int srcY, int maskX, int maskY, - int dstX, int dstY, int width, int height); -extern void -xa_composite_done(struct xa_context *ctx); - -#endif diff --git a/src/gallium/state_trackers/xa/xa_context.c b/src/gallium/state_trackers/xa/xa_context.c deleted file mode 100644 index a4630cf09ca..00000000000 --- a/src/gallium/state_trackers/xa/xa_context.c +++ /dev/null @@ -1,419 +0,0 @@ -/********************************************************** - * Copyright 2009-2011 VMware, Inc. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - ********************************************************* - * Authors: - * Zack Rusin - * Thomas Hellstrom - */ -#include "xa_context.h" -#include "xa_priv.h" -#include "cso_cache/cso_context.h" -#include "util/u_inlines.h" -#include "util/u_rect.h" -#include "util/u_surface.h" -#include "pipe/p_context.h" - -XA_EXPORT void -xa_context_flush(struct xa_context *ctx) -{ - if (ctx->last_fence) { - struct pipe_screen *screen = ctx->xa->screen; - screen->fence_reference(screen, &ctx->last_fence, NULL); - } - ctx->pipe->flush(ctx->pipe, &ctx->last_fence, 0); -} - -XA_EXPORT struct xa_context * -xa_context_default(struct xa_tracker *xa) -{ - return xa->default_ctx; -} - -XA_EXPORT struct xa_context * -xa_context_create(struct xa_tracker *xa) -{ - struct xa_context *ctx = calloc(1, sizeof(*ctx)); - - ctx->xa = xa; - ctx->pipe = xa->screen->context_create(xa->screen, NULL, 0); - ctx->cso = cso_create_context(ctx->pipe, 0); - ctx->shaders = xa_shaders_create(ctx); - renderer_init_state(ctx); - - return ctx; -} - -XA_EXPORT void -xa_context_destroy(struct xa_context *r) -{ - struct pipe_resource **vsbuf = &r->vs_const_buffer; - struct pipe_resource **fsbuf = &r->fs_const_buffer; - - if (*vsbuf) - pipe_resource_reference(vsbuf, NULL); - - if (*fsbuf) - pipe_resource_reference(fsbuf, NULL); - - if (r->shaders) { - xa_shaders_destroy(r->shaders); - r->shaders = NULL; - } - - xa_ctx_sampler_views_destroy(r); - if (r->srf) - pipe_surface_reference(&r->srf, NULL); - - if (r->cso) { - cso_destroy_context(r->cso); - r->cso = NULL; - } - - r->pipe->destroy(r->pipe); - free(r); -} - -XA_EXPORT int -xa_surface_dma(struct xa_context *ctx, - struct xa_surface *srf, - void *data, - unsigned int pitch, - int to_surface, struct xa_box *boxes, unsigned int num_boxes) -{ - struct pipe_transfer *transfer; - void *map; - int w, h, i; - enum pipe_transfer_usage transfer_direction; - struct pipe_context *pipe = ctx->pipe; - - transfer_direction = (to_surface ? PIPE_TRANSFER_WRITE : - PIPE_TRANSFER_READ); - - for (i = 0; i < num_boxes; ++i, ++boxes) { - w = boxes->x2 - boxes->x1; - h = boxes->y2 - boxes->y1; - - map = pipe_transfer_map(pipe, srf->tex, 0, 0, - transfer_direction, boxes->x1, boxes->y1, - w, h, &transfer); - if (!map) - return -XA_ERR_NORES; - - if (to_surface) { - util_copy_rect(map, srf->tex->format, transfer->stride, - 0, 0, w, h, data, pitch, boxes->x1, boxes->y1); - } else { - util_copy_rect(data, srf->tex->format, pitch, - boxes->x1, boxes->y1, w, h, map, transfer->stride, 0, - 0); - } - pipe->transfer_unmap(pipe, transfer); - } - return XA_ERR_NONE; -} - -XA_EXPORT void * -xa_surface_map(struct xa_context *ctx, - struct xa_surface *srf, unsigned int usage) -{ - void *map; - unsigned int gallium_usage = 0; - struct pipe_context *pipe = ctx->pipe; - - /* - * A surface may only have a single map. - */ - if (srf->transfer) - return NULL; - - if (usage & XA_MAP_READ) - gallium_usage |= PIPE_TRANSFER_READ; - if (usage & XA_MAP_WRITE) - gallium_usage |= PIPE_TRANSFER_WRITE; - if (usage & XA_MAP_MAP_DIRECTLY) - gallium_usage |= PIPE_TRANSFER_MAP_DIRECTLY; - if (usage & XA_MAP_UNSYNCHRONIZED) - gallium_usage |= PIPE_TRANSFER_UNSYNCHRONIZED; - if (usage & XA_MAP_DONTBLOCK) - gallium_usage |= PIPE_TRANSFER_DONTBLOCK; - if (usage & XA_MAP_DISCARD_WHOLE_RESOURCE) - gallium_usage |= PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE; - - if (!(gallium_usage & (PIPE_TRANSFER_READ_WRITE))) - return NULL; - - map = pipe_transfer_map(pipe, srf->tex, 0, 0, - gallium_usage, 0, 0, - srf->tex->width0, srf->tex->height0, - &srf->transfer); - if (!map) - return NULL; - - srf->mapping_pipe = pipe; - return map; -} - -XA_EXPORT void -xa_surface_unmap(struct xa_surface *srf) -{ - if (srf->transfer) { - struct pipe_context *pipe = srf->mapping_pipe; - - pipe->transfer_unmap(pipe, srf->transfer); - srf->transfer = NULL; - } -} - -int -xa_ctx_srf_create(struct xa_context *ctx, struct xa_surface *dst) -{ - struct pipe_screen *screen = ctx->pipe->screen; - struct pipe_surface srf_templ; - - /* - * Cache surfaces unless we change render target - */ - if (ctx->srf) { - if (ctx->srf->texture == dst->tex) - return XA_ERR_NONE; - - pipe_surface_reference(&ctx->srf, NULL); - } - - if (!screen->is_format_supported(screen, dst->tex->format, - PIPE_TEXTURE_2D, 0, 0, - PIPE_BIND_RENDER_TARGET)) - return -XA_ERR_INVAL; - - u_surface_default_template(&srf_templ, dst->tex); - ctx->srf = ctx->pipe->create_surface(ctx->pipe, dst->tex, &srf_templ); - if (!ctx->srf) - return -XA_ERR_NORES; - - return XA_ERR_NONE; -} - -void -xa_ctx_srf_destroy(struct xa_context *ctx) -{ - /* - * Cache surfaces unless we change render target. - * Final destruction on context destroy. - */ -} - -XA_EXPORT int -xa_copy_prepare(struct xa_context *ctx, - struct xa_surface *dst, struct xa_surface *src) -{ - if (src == dst) - return -XA_ERR_INVAL; - - if (src->tex->format != dst->tex->format) { - int ret = xa_ctx_srf_create(ctx, dst); - if (ret != XA_ERR_NONE) - return ret; - renderer_copy_prepare(ctx, ctx->srf, src->tex, - src->fdesc.xa_format, - dst->fdesc.xa_format); - ctx->simple_copy = 0; - } else - ctx->simple_copy = 1; - - ctx->src = src; - ctx->dst = dst; - xa_ctx_srf_destroy(ctx); - - return 0; -} - -XA_EXPORT void -xa_copy(struct xa_context *ctx, - int dx, int dy, int sx, int sy, int width, int height) -{ - struct pipe_box src_box; - - xa_scissor_update(ctx, dx, dy, dx + width, dy + height); - - if (ctx->simple_copy) { - u_box_2d(sx, sy, width, height, &src_box); - ctx->pipe->resource_copy_region(ctx->pipe, - ctx->dst->tex, 0, dx, dy, 0, - ctx->src->tex, - 0, &src_box); - } else - renderer_copy(ctx, dx, dy, sx, sy, width, height, - (float) ctx->src->tex->width0, - (float) ctx->src->tex->height0); -} - -XA_EXPORT void -xa_copy_done(struct xa_context *ctx) -{ - if (!ctx->simple_copy) { - renderer_draw_flush(ctx); - } -} - -static void -bind_solid_blend_state(struct xa_context *ctx) -{ - struct pipe_blend_state blend; - - memset(&blend, 0, sizeof(struct pipe_blend_state)); - blend.rt[0].blend_enable = 0; - blend.rt[0].colormask = PIPE_MASK_RGBA; - - blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; - blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; - blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; - blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; - - cso_set_blend(ctx->cso, &blend); -} - -XA_EXPORT int -xa_solid_prepare(struct xa_context *ctx, struct xa_surface *dst, - uint32_t fg) -{ - unsigned vs_traits, fs_traits; - struct xa_shader shader; - int ret; - - ret = xa_ctx_srf_create(ctx, dst); - if (ret != XA_ERR_NONE) - return ret; - - if (ctx->srf->format == PIPE_FORMAT_L8_UNORM) - xa_pixel_to_float4_a8(fg, ctx->solid_color); - else - xa_pixel_to_float4(fg, ctx->solid_color); - ctx->has_solid_src = 1; - - ctx->dst = dst; - -#if 0 - debug_printf("Color Pixel=(%d, %d, %d, %d), RGBA=(%f, %f, %f, %f)\n", - (fg >> 24) & 0xff, (fg >> 16) & 0xff, - (fg >> 8) & 0xff, (fg >> 0) & 0xff, - exa->solid_color[0], exa->solid_color[1], - exa->solid_color[2], exa->solid_color[3]); -#endif - - vs_traits = VS_SRC_SRC | VS_COMPOSITE; - fs_traits = FS_SRC_SRC | VS_COMPOSITE; - - renderer_bind_destination(ctx, ctx->srf); - bind_solid_blend_state(ctx); - cso_set_samplers(ctx->cso, PIPE_SHADER_FRAGMENT, 0, NULL); - cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, 0, NULL); - - shader = xa_shaders_get(ctx->shaders, vs_traits, fs_traits); - cso_set_vertex_shader_handle(ctx->cso, shader.vs); - cso_set_fragment_shader_handle(ctx->cso, shader.fs); - - renderer_begin_solid(ctx); - - xa_ctx_srf_destroy(ctx); - return XA_ERR_NONE; -} - -XA_EXPORT void -xa_solid(struct xa_context *ctx, int x, int y, int width, int height) -{ - xa_scissor_update(ctx, x, y, x + width, y + height); - renderer_solid(ctx, x, y, x + width, y + height); -} - -XA_EXPORT void -xa_solid_done(struct xa_context *ctx) -{ - renderer_draw_flush(ctx); - ctx->comp = NULL; - ctx->has_solid_src = FALSE; - ctx->num_bound_samplers = 0; -} - -XA_EXPORT struct xa_fence * -xa_fence_get(struct xa_context *ctx) -{ - struct xa_fence *fence = calloc(1, sizeof(*fence)); - struct pipe_screen *screen = ctx->xa->screen; - - if (!fence) - return NULL; - - fence->xa = ctx->xa; - - if (ctx->last_fence == NULL) - fence->pipe_fence = NULL; - else - screen->fence_reference(screen, &fence->pipe_fence, ctx->last_fence); - - return fence; -} - -XA_EXPORT int -xa_fence_wait(struct xa_fence *fence, uint64_t timeout) -{ - if (!fence) - return XA_ERR_NONE; - - if (fence->pipe_fence) { - struct pipe_screen *screen = fence->xa->screen; - boolean timed_out; - - timed_out = !screen->fence_finish(screen, NULL, fence->pipe_fence, timeout); - if (timed_out) - return -XA_ERR_BUSY; - - screen->fence_reference(screen, &fence->pipe_fence, NULL); - } - return XA_ERR_NONE; -} - -XA_EXPORT void -xa_fence_destroy(struct xa_fence *fence) -{ - if (!fence) - return; - - if (fence->pipe_fence) { - struct pipe_screen *screen = fence->xa->screen; - - screen->fence_reference(screen, &fence->pipe_fence, NULL); - } - - free(fence); -} - -void -xa_ctx_sampler_views_destroy(struct xa_context *ctx) -{ - int i; - - for (i = 0; i < ctx->num_bound_samplers; ++i) - pipe_sampler_view_reference(&ctx->bound_sampler_views[i], NULL); - ctx->num_bound_samplers = 0; -} diff --git a/src/gallium/state_trackers/xa/xa_context.h b/src/gallium/state_trackers/xa/xa_context.h deleted file mode 100644 index 202b8e56e23..00000000000 --- a/src/gallium/state_trackers/xa/xa_context.h +++ /dev/null @@ -1,101 +0,0 @@ -/********************************************************** - * Copyright 2009-2011 VMware, Inc. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - ********************************************************* - * Authors: - * Zack Rusin - * Thomas Hellstrom - */ - -#ifndef _XA_CONTEXT_H_ -#define _XA_CONTEXT_H_ -#include "xa_tracker.h" -#include - -struct xa_context; - -extern struct xa_context *xa_context_default(struct xa_tracker *xa); - -extern struct xa_context *xa_context_create(struct xa_tracker *xa); - -extern void xa_context_destroy(struct xa_context *r); - -extern void xa_context_flush(struct xa_context *ctx); - -/** - * xa_yuv_planar_blit - 2D blit with color conversion and scaling. - * - * Performs a scaled blit with color conversion according to - * (R,G,B,A)^T = (CM)^T (Y,U,V,1)^T, where @conversion_matrix or CM in the - * formula is a four by four coefficient matrix. The input variable - * @yuv is an array of three xa_yuv_component surfaces. - */ -extern int xa_yuv_planar_blit(struct xa_context *r, - int src_x, - int src_y, - int src_w, - int src_h, - int dst_x, - int dst_y, - int dst_w, - int dst_h, - struct xa_box *box, - unsigned int num_boxes, - const float conversion_matrix[], - struct xa_surface *dst, struct xa_surface *yuv[]); - -extern int xa_copy_prepare(struct xa_context *ctx, - struct xa_surface *dst, struct xa_surface *src); - -extern void xa_copy(struct xa_context *ctx, - int dx, int dy, int sx, int sy, int width, int height); - -extern void xa_copy_done(struct xa_context *ctx); - -extern int xa_surface_dma(struct xa_context *ctx, - struct xa_surface *srf, - void *data, - unsigned int byte_pitch, - int to_surface, struct xa_box *boxes, - unsigned int num_boxes); - -extern void *xa_surface_map(struct xa_context *ctx, - struct xa_surface *srf, unsigned int usage); - -extern void xa_surface_unmap(struct xa_surface *srf); - -extern int -xa_solid_prepare(struct xa_context *ctx, struct xa_surface *dst, - uint32_t fg); -extern void -xa_solid(struct xa_context *ctx, int x, int y, int width, int height); - -extern void -xa_solid_done(struct xa_context *ctx); - -extern struct xa_fence *xa_fence_get(struct xa_context *ctx); - -extern int xa_fence_wait(struct xa_fence *fence, uint64_t timeout); - -extern void xa_fence_destroy(struct xa_fence *fence); -#endif diff --git a/src/gallium/state_trackers/xa/xa_priv.h b/src/gallium/state_trackers/xa/xa_priv.h deleted file mode 100644 index f368de3b81f..00000000000 --- a/src/gallium/state_trackers/xa/xa_priv.h +++ /dev/null @@ -1,289 +0,0 @@ -/********************************************************** - * Copyright 2009-2011 VMware, Inc. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - ********************************************************* - * Authors: - * Zack Rusin - * Thomas Hellstrom - */ - -#ifndef _XA_PRIV_H_ -#define _XA_PRIV_H_ - -#include "xa_tracker.h" -#include "xa_context.h" -#include "xa_composite.h" - -#include "pipe/p_screen.h" -#include "pipe/p_context.h" -#include "pipe/p_state.h" - -#include "util/u_math.h" - -#if defined(__GNUC__) -#define XA_EXPORT __attribute__ ((visibility("default"))) -#else -#define XA_EXPORT -#endif - -#define XA_VB_SIZE (100 * 4 * 3 * 4) -#define XA_LAST_SURFACE_TYPE (xa_type_yuv_component + 1) -#define XA_MAX_SAMPLERS 3 - -struct xa_fence { - struct pipe_fence_handle *pipe_fence; - struct xa_tracker *xa; -}; - -struct xa_format_descriptor { - enum pipe_format format; - enum xa_formats xa_format; -}; - -struct xa_surface { - int refcount; - struct pipe_resource template; - struct xa_tracker *xa; - struct pipe_resource *tex; - struct pipe_transfer *transfer; - unsigned int flags; - struct xa_format_descriptor fdesc; - struct pipe_context *mapping_pipe; -}; - -struct xa_tracker { - enum xa_formats *supported_formats; - unsigned int format_map[XA_LAST_SURFACE_TYPE][2]; - struct pipe_loader_device *dev; - struct pipe_screen *screen; - struct xa_context *default_ctx; -}; - -struct xa_context { - struct xa_tracker *xa; - struct pipe_context *pipe; - - struct cso_context *cso; - struct xa_shaders *shaders; - - struct pipe_resource *vs_const_buffer; - struct pipe_resource *fs_const_buffer; - - float buffer[XA_VB_SIZE]; - unsigned int buffer_size; - struct pipe_vertex_element velems[3]; - - /* number of attributes per vertex for the current - * draw operation */ - unsigned int attrs_per_vertex; - - unsigned int fb_width; - unsigned int fb_height; - - struct pipe_fence_handle *last_fence; - struct xa_surface *src; - struct xa_surface *dst; - struct pipe_surface *srf; - - /* destination scissor state.. we scissor out untouched parts - * of the dst for the benefit of tilers: - */ - struct pipe_scissor_state scissor; - int scissor_valid; - - int simple_copy; - - int has_solid_src; - int has_solid_mask; - float solid_color[4]; - - unsigned int num_bound_samplers; - struct pipe_sampler_view *bound_sampler_views[XA_MAX_SAMPLERS]; - const struct xa_composite *comp; -}; - -static inline void -xa_scissor_reset(struct xa_context *ctx) -{ - ctx->scissor.maxx = 0; - ctx->scissor.maxy = 0; - ctx->scissor.minx = ~0; - ctx->scissor.miny = ~0; - ctx->scissor_valid = FALSE; -} - -static inline void -xa_scissor_update(struct xa_context *ctx, unsigned minx, unsigned miny, - unsigned maxx, unsigned maxy) -{ - ctx->scissor.maxx = MAX2(ctx->scissor.maxx, maxx); - ctx->scissor.maxy = MAX2(ctx->scissor.maxy, maxy); - ctx->scissor.minx = MIN2(ctx->scissor.minx, minx); - ctx->scissor.miny = MIN2(ctx->scissor.miny, miny); - ctx->scissor_valid = TRUE; -} - -enum xa_vs_traits { - VS_COMPOSITE = 1 << 0, - VS_MASK = 1 << 1, - VS_SRC_SRC = 1 << 2, - VS_MASK_SRC = 1 << 3, - VS_YUV = 1 << 4, -}; - -enum xa_fs_traits { - FS_COMPOSITE = 1 << 0, - FS_MASK = 1 << 1, - FS_SRC_SRC = 1 << 2, - FS_MASK_SRC = 1 << 3, - FS_YUV = 1 << 4, - FS_SRC_REPEAT_NONE = 1 << 5, - FS_MASK_REPEAT_NONE = 1 << 6, - FS_SRC_SWIZZLE_RGB = 1 << 7, - FS_MASK_SWIZZLE_RGB = 1 << 8, - FS_SRC_SET_ALPHA = 1 << 9, - FS_MASK_SET_ALPHA = 1 << 10, - FS_SRC_LUMINANCE = 1 << 11, - FS_MASK_LUMINANCE = 1 << 12, - FS_DST_LUMINANCE = 1 << 13, - FS_CA = 1 << 14, -}; - -struct xa_shader { - void *fs; - void *vs; -}; - -struct xa_shaders; - -/* - * Inline utilities - */ - -static inline int -xa_min(int a, int b) -{ - return ((a <= b) ? a : b); -} - -static inline void -xa_pixel_to_float4(uint32_t pixel, float *color) -{ - uint32_t r, g, b, a; - - a = (pixel >> 24) & 0xff; - r = (pixel >> 16) & 0xff; - g = (pixel >> 8) & 0xff; - b = (pixel >> 0) & 0xff; - color[0] = ((float)r) / 255.; - color[1] = ((float)g) / 255.; - color[2] = ((float)b) / 255.; - color[3] = ((float)a) / 255.; -} - -static inline void -xa_pixel_to_float4_a8(uint32_t pixel, float *color) -{ - uint32_t a; - - a = (pixel >> 24) & 0xff; - color[0] = ((float)a) / 255.; - color[1] = ((float)a) / 255.; - color[2] = ((float)a) / 255.; - color[3] = ((float)a) / 255.; -} - -/* - * xa_tgsi.c - */ - -extern struct xa_shaders *xa_shaders_create(struct xa_context *); - -void xa_shaders_destroy(struct xa_shaders *shaders); - -struct xa_shader xa_shaders_get(struct xa_shaders *shaders, - unsigned vs_traits, unsigned fs_traits); - -/* - * xa_context.c - */ -extern void -xa_context_flush(struct xa_context *ctx); - -extern int -xa_ctx_srf_create(struct xa_context *ctx, struct xa_surface *dst); - -extern void -xa_ctx_srf_destroy(struct xa_context *ctx); - -extern void -xa_ctx_sampler_views_destroy(struct xa_context *ctx); - -/* - * xa_renderer.c - */ -void renderer_set_constants(struct xa_context *r, - int shader_type, const float *params, - int param_bytes); - -void renderer_draw_yuv(struct xa_context *r, - float src_x, - float src_y, - float src_w, - float src_h, - int dst_x, - int dst_y, int dst_w, int dst_h, - struct xa_surface *srf[]); - -void renderer_bind_destination(struct xa_context *r, - struct pipe_surface *surface); - -void renderer_init_state(struct xa_context *r); -void renderer_copy_prepare(struct xa_context *r, - struct pipe_surface *dst_surface, - struct pipe_resource *src_texture, - const enum xa_formats src_xa_format, - const enum xa_formats dst_xa_format); - -void renderer_copy(struct xa_context *r, int dx, - int dy, - int sx, - int sy, - int width, int height, float src_width, float src_height); - -void renderer_draw_flush(struct xa_context *r); - -void renderer_begin_solid(struct xa_context *r); -void renderer_solid(struct xa_context *r, - int x0, int y0, int x1, int y1); -void -renderer_begin_textures(struct xa_context *r); - -void -renderer_texture(struct xa_context *r, - int *pos, - int width, int height, - const float *src_matrix, - const float *mask_matrix); - -#endif diff --git a/src/gallium/state_trackers/xa/xa_renderer.c b/src/gallium/state_trackers/xa/xa_renderer.c deleted file mode 100644 index 89548ad7019..00000000000 --- a/src/gallium/state_trackers/xa/xa_renderer.c +++ /dev/null @@ -1,636 +0,0 @@ -/********************************************************** - * Copyright 2009-2011 VMware, Inc. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - ********************************************************* - * Authors: - * Zack Rusin - */ - -#include "xa_context.h" -#include "xa_priv.h" -#include -#include "cso_cache/cso_context.h" -#include "util/u_inlines.h" -#include "util/u_sampler.h" -#include "util/u_draw_quad.h" - -#define floatsEqual(x, y) (fabsf(x - y) <= 0.00001f * MIN2(fabsf(x), fabsf(y))) -#define floatIsZero(x) (floatsEqual((x) + 1, 1)) - -#define NUM_COMPONENTS 4 - -void - - -renderer_set_constants(struct xa_context *r, - int shader_type, const float *params, int param_bytes); - -static inline boolean -is_affine(const float *matrix) -{ - return floatIsZero(matrix[2]) && floatIsZero(matrix[5]) - && floatsEqual(matrix[8], 1); -} - -static inline void -map_point(const float *mat, float x, float y, float *out_x, float *out_y) -{ - if (!mat) { - *out_x = x; - *out_y = y; - return; - } - - *out_x = mat[0] * x + mat[3] * y + mat[6]; - *out_y = mat[1] * x + mat[4] * y + mat[7]; - if (!is_affine(mat)) { - float w = 1 / (mat[2] * x + mat[5] * y + mat[8]); - - *out_x *= w; - *out_y *= w; - } -} - -static inline void -renderer_draw(struct xa_context *r) -{ - int num_verts = r->buffer_size / (r->attrs_per_vertex * NUM_COMPONENTS); - - if (!r->buffer_size) - return; - - if (!r->scissor_valid) { - r->scissor.minx = 0; - r->scissor.miny = 0; - r->scissor.maxx = r->dst->tex->width0; - r->scissor.maxy = r->dst->tex->height0; - } - - r->pipe->set_scissor_states(r->pipe, 0, 1, &r->scissor); - - struct cso_velems_state velems; - velems.count = r->attrs_per_vertex; - memcpy(velems.velems, r->velems, sizeof(r->velems[0]) * velems.count); - - cso_set_vertex_elements(r->cso, &velems); - util_draw_user_vertex_buffer(r->cso, r->buffer, PIPE_PRIM_QUADS, - num_verts, /* verts */ - r->attrs_per_vertex); /* attribs/vert */ - r->buffer_size = 0; - - xa_scissor_reset(r); -} - -static inline void -renderer_draw_conditional(struct xa_context *r, int next_batch) -{ - if (r->buffer_size + next_batch >= XA_VB_SIZE || - (next_batch == 0 && r->buffer_size)) { - renderer_draw(r); - } -} - -void -renderer_init_state(struct xa_context *r) -{ - struct pipe_depth_stencil_alpha_state dsa; - struct pipe_rasterizer_state raster; - unsigned i; - - /* set common initial clip state */ - memset(&dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state)); - cso_set_depth_stencil_alpha(r->cso, &dsa); - - /* XXX: move to renderer_init_state? */ - memset(&raster, 0, sizeof(struct pipe_rasterizer_state)); - raster.half_pixel_center = 1; - raster.bottom_edge_rule = 1; - raster.depth_clip_near = 1; - raster.depth_clip_far = 1; - raster.scissor = 1; - cso_set_rasterizer(r->cso, &raster); - - /* vertex elements state */ - memset(&r->velems[0], 0, sizeof(r->velems[0]) * 3); - for (i = 0; i < 3; i++) { - r->velems[i].src_offset = i * 4 * sizeof(float); - r->velems[i].instance_divisor = 0; - r->velems[i].vertex_buffer_index = 0; - r->velems[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; - } -} - -static inline void -add_vertex_none(struct xa_context *r, float x, float y) -{ - float *vertex = r->buffer + r->buffer_size; - - vertex[0] = x; - vertex[1] = y; - vertex[2] = 0.f; /*z */ - vertex[3] = 1.f; /*w */ - - r->buffer_size += 4; -} - -static inline void -add_vertex_1tex(struct xa_context *r, float x, float y, float s, float t) -{ - float *vertex = r->buffer + r->buffer_size; - - vertex[0] = x; - vertex[1] = y; - vertex[2] = 0.f; /*z */ - vertex[3] = 1.f; /*w */ - - vertex[4] = s; /*s */ - vertex[5] = t; /*t */ - vertex[6] = 0.f; /*r */ - vertex[7] = 1.f; /*q */ - - r->buffer_size += 8; -} - -static inline void -add_vertex_2tex(struct xa_context *r, - float x, float y, float s0, float t0, float s1, float t1) -{ - float *vertex = r->buffer + r->buffer_size; - - vertex[0] = x; - vertex[1] = y; - vertex[2] = 0.f; /*z */ - vertex[3] = 1.f; /*w */ - - vertex[4] = s0; /*s */ - vertex[5] = t0; /*t */ - vertex[6] = 0.f; /*r */ - vertex[7] = 1.f; /*q */ - - vertex[8] = s1; /*s */ - vertex[9] = t1; /*t */ - vertex[10] = 0.f; /*r */ - vertex[11] = 1.f; /*q */ - - r->buffer_size += 12; -} - -static void -compute_src_coords(float sx, float sy, const struct pipe_resource *src, - const float *src_matrix, - float width, float height, - float tc0[2], float tc1[2], float tc2[2], float tc3[2]) -{ - tc0[0] = sx; - tc0[1] = sy; - tc1[0] = sx + width; - tc1[1] = sy; - tc2[0] = sx + width; - tc2[1] = sy + height; - tc3[0] = sx; - tc3[1] = sy + height; - - if (src_matrix) { - map_point(src_matrix, tc0[0], tc0[1], &tc0[0], &tc0[1]); - map_point(src_matrix, tc1[0], tc1[1], &tc1[0], &tc1[1]); - map_point(src_matrix, tc2[0], tc2[1], &tc2[0], &tc2[1]); - map_point(src_matrix, tc3[0], tc3[1], &tc3[0], &tc3[1]); - } - - tc0[0] /= src->width0; - tc1[0] /= src->width0; - tc2[0] /= src->width0; - tc3[0] /= src->width0; - tc0[1] /= src->height0; - tc1[1] /= src->height0; - tc2[1] /= src->height0; - tc3[1] /= src->height0; -} - -static void -add_vertex_data1(struct xa_context *r, - float srcX, float srcY, float dstX, float dstY, - float width, float height, - const struct pipe_resource *src, const float *src_matrix) -{ - float tc0[2], tc1[2], tc2[2], tc3[2]; - - compute_src_coords(srcX, srcY, src, src_matrix, width, height, - tc0, tc1, tc2, tc3); - /* 1st vertex */ - add_vertex_1tex(r, dstX, dstY, tc0[0], tc0[1]); - /* 2nd vertex */ - add_vertex_1tex(r, dstX + width, dstY, tc1[0], tc1[1]); - /* 3rd vertex */ - add_vertex_1tex(r, dstX + width, dstY + height, tc2[0], tc2[1]); - /* 4th vertex */ - add_vertex_1tex(r, dstX, dstY + height, tc3[0], tc3[1]); -} - -static void -add_vertex_data2(struct xa_context *r, - float srcX, float srcY, float maskX, float maskY, - float dstX, float dstY, float width, float height, - struct pipe_resource *src, - struct pipe_resource *mask, - const float *src_matrix, const float *mask_matrix) -{ - float spt0[2], spt1[2], spt2[2], spt3[2]; - float mpt0[2], mpt1[2], mpt2[2], mpt3[2]; - - compute_src_coords(srcX, srcY, src, src_matrix, width, height, - spt0, spt1, spt2, spt3); - compute_src_coords(maskX, maskY, mask, mask_matrix, width, height, - mpt0, mpt1, mpt2, mpt3); - - /* 1st vertex */ - add_vertex_2tex(r, dstX, dstY, - spt0[0], spt0[1], mpt0[0], mpt0[1]); - /* 2nd vertex */ - add_vertex_2tex(r, dstX + width, dstY, - spt1[0], spt1[1], mpt1[0], mpt1[1]); - /* 3rd vertex */ - add_vertex_2tex(r, dstX + width, dstY + height, - spt2[0], spt2[1], mpt2[0], mpt2[1]); - /* 4th vertex */ - add_vertex_2tex(r, dstX, dstY + height, - spt3[0], spt3[1], mpt3[0], mpt3[1]); -} - -static void -setup_vertex_data_yuv(struct xa_context *r, - float srcX, - float srcY, - float srcW, - float srcH, - float dstX, - float dstY, - float dstW, float dstH, struct xa_surface *srf[]) -{ - float s0, t0, s1, t1; - float spt0[2], spt1[2]; - struct pipe_resource *tex; - - spt0[0] = srcX; - spt0[1] = srcY; - spt1[0] = srcX + srcW; - spt1[1] = srcY + srcH; - - tex = srf[0]->tex; - s0 = spt0[0] / tex->width0; - t0 = spt0[1] / tex->height0; - s1 = spt1[0] / tex->width0; - t1 = spt1[1] / tex->height0; - - /* 1st vertex */ - add_vertex_1tex(r, dstX, dstY, s0, t0); - /* 2nd vertex */ - add_vertex_1tex(r, dstX + dstW, dstY, s1, t0); - /* 3rd vertex */ - add_vertex_1tex(r, dstX + dstW, dstY + dstH, s1, t1); - /* 4th vertex */ - add_vertex_1tex(r, dstX, dstY + dstH, s0, t1); -} - -/* Set up framebuffer, viewport and vertex shader constant buffer - * state for a particular destinaton surface. In all our rendering, - * these concepts are linked. - */ -void -renderer_bind_destination(struct xa_context *r, - struct pipe_surface *surface) -{ - int width = surface->width; - int height = surface->height; - - struct pipe_framebuffer_state fb; - struct pipe_viewport_state viewport; - - xa_scissor_reset(r); - - /* Framebuffer uses actual surface width/height - */ - memset(&fb, 0, sizeof fb); - fb.width = surface->width; - fb.height = surface->height; - fb.nr_cbufs = 1; - fb.cbufs[0] = surface; - fb.zsbuf = 0; - - /* Viewport just touches the bit we're interested in: - */ - viewport.scale[0] = width / 2.f; - viewport.scale[1] = height / 2.f; - viewport.scale[2] = 1.0; - viewport.translate[0] = width / 2.f; - viewport.translate[1] = height / 2.f; - viewport.translate[2] = 0.0; - - /* Constant buffer set up to match viewport dimensions: - */ - if (r->fb_width != width || r->fb_height != height) { - float vs_consts[8] = { - 2.f / width, 2.f / height, 1, 1, - -1, -1, 0, 0 - }; - - r->fb_width = width; - r->fb_height = height; - - renderer_set_constants(r, PIPE_SHADER_VERTEX, - vs_consts, sizeof vs_consts); - } - - cso_set_framebuffer(r->cso, &fb); - cso_set_viewport(r->cso, &viewport); -} - -void -renderer_set_constants(struct xa_context *r, - int shader_type, const float *params, int param_bytes) -{ - struct pipe_resource **cbuf = - (shader_type == PIPE_SHADER_VERTEX) ? &r->vs_const_buffer : - &r->fs_const_buffer; - - pipe_resource_reference(cbuf, NULL); - *cbuf = pipe_buffer_create_const0(r->pipe->screen, - PIPE_BIND_CONSTANT_BUFFER, - PIPE_USAGE_DEFAULT, - param_bytes); - - if (*cbuf) { - pipe_buffer_write(r->pipe, *cbuf, 0, param_bytes, params); - } - pipe_set_constant_buffer(r->pipe, shader_type, 0, *cbuf); -} - -void -renderer_copy_prepare(struct xa_context *r, - struct pipe_surface *dst_surface, - struct pipe_resource *src_texture, - const enum xa_formats src_xa_format, - const enum xa_formats dst_xa_format) -{ - struct pipe_context *pipe = r->pipe; - struct pipe_screen *screen = pipe->screen; - struct xa_shader shader; - uint32_t fs_traits = FS_COMPOSITE; - - assert(screen->is_format_supported(screen, dst_surface->format, - PIPE_TEXTURE_2D, 0, 0, - PIPE_BIND_RENDER_TARGET)); - (void)screen; - - renderer_bind_destination(r, dst_surface); - - /* set misc state we care about */ - { - struct pipe_blend_state blend; - - memset(&blend, 0, sizeof(blend)); - blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; - blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; - blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; - blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; - blend.rt[0].colormask = PIPE_MASK_RGBA; - cso_set_blend(r->cso, &blend); - } - - /* sampler */ - { - struct pipe_sampler_state sampler; - const struct pipe_sampler_state *p_sampler = &sampler; - - memset(&sampler, 0, sizeof(sampler)); - sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; - sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; - sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; - sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; - sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; - sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; - sampler.normalized_coords = 1; - cso_set_samplers(r->cso, PIPE_SHADER_FRAGMENT, 1, &p_sampler); - r->num_bound_samplers = 1; - } - - /* texture/sampler view */ - { - struct pipe_sampler_view templ; - struct pipe_sampler_view *src_view; - - u_sampler_view_default_template(&templ, - src_texture, src_texture->format); - src_view = pipe->create_sampler_view(pipe, src_texture, &templ); - cso_set_sampler_views(r->cso, PIPE_SHADER_FRAGMENT, 1, &src_view); - pipe_sampler_view_reference(&src_view, NULL); - } - - /* shaders */ - if (src_texture->format == PIPE_FORMAT_L8_UNORM || - src_texture->format == PIPE_FORMAT_R8_UNORM) - fs_traits |= FS_SRC_LUMINANCE; - if (dst_surface->format == PIPE_FORMAT_L8_UNORM || - dst_surface->format == PIPE_FORMAT_R8_UNORM) - fs_traits |= FS_DST_LUMINANCE; - if (xa_format_a(dst_xa_format) != 0 && - xa_format_a(src_xa_format) == 0) - fs_traits |= FS_SRC_SET_ALPHA; - - shader = xa_shaders_get(r->shaders, VS_COMPOSITE, fs_traits); - cso_set_vertex_shader_handle(r->cso, shader.vs); - cso_set_fragment_shader_handle(r->cso, shader.fs); - - r->buffer_size = 0; - r->attrs_per_vertex = 2; -} - -void -renderer_copy(struct xa_context *r, - int dx, - int dy, - int sx, - int sy, - int width, int height, float src_width, float src_height) -{ - float s0, t0, s1, t1; - float x0, y0, x1, y1; - - /* XXX: could put the texcoord scaling calculation into the vertex - * shader. - */ - s0 = sx / src_width; - s1 = (sx + width) / src_width; - t0 = sy / src_height; - t1 = (sy + height) / src_height; - - x0 = dx; - x1 = dx + width; - y0 = dy; - y1 = dy + height; - - /* draw quad */ - renderer_draw_conditional(r, 4 * 8); - add_vertex_1tex(r, x0, y0, s0, t0); - add_vertex_1tex(r, x1, y0, s1, t0); - add_vertex_1tex(r, x1, y1, s1, t1); - add_vertex_1tex(r, x0, y1, s0, t1); -} - -void -renderer_draw_yuv(struct xa_context *r, - float src_x, - float src_y, - float src_w, - float src_h, - int dst_x, - int dst_y, int dst_w, int dst_h, struct xa_surface *srf[]) -{ - const int num_attribs = 2; /*pos + tex coord */ - - setup_vertex_data_yuv(r, - src_x, src_y, src_w, src_h, - dst_x, dst_y, dst_w, dst_h, srf); - - if (!r->scissor_valid) { - r->scissor.minx = 0; - r->scissor.miny = 0; - r->scissor.maxx = r->dst->tex->width0; - r->scissor.maxy = r->dst->tex->height0; - } - - r->pipe->set_scissor_states(r->pipe, 0, 1, &r->scissor); - - struct cso_velems_state velems; - velems.count = num_attribs; - memcpy(velems.velems, r->velems, sizeof(r->velems[0]) * velems.count); - - cso_set_vertex_elements(r->cso, &velems); - util_draw_user_vertex_buffer(r->cso, r->buffer, PIPE_PRIM_QUADS, - 4, /* verts */ - num_attribs); /* attribs/vert */ - r->buffer_size = 0; - - xa_scissor_reset(r); -} - -void -renderer_begin_solid(struct xa_context *r) -{ - r->buffer_size = 0; - r->attrs_per_vertex = 1; - renderer_set_constants(r, PIPE_SHADER_FRAGMENT, r->solid_color, - 4 * sizeof(float)); -} - -void -renderer_solid(struct xa_context *r, - int x0, int y0, int x1, int y1) -{ - /* - * debug_printf("solid rect[(%d, %d), (%d, %d)], rgba[%f, %f, %f, %f]\n", - * x0, y0, x1, y1, color[0], color[1], color[2], color[3]); */ - - renderer_draw_conditional(r, 4 * 4); - - /* 1st vertex */ - add_vertex_none(r, x0, y0); - /* 2nd vertex */ - add_vertex_none(r, x1, y0); - /* 3rd vertex */ - add_vertex_none(r, x1, y1); - /* 4th vertex */ - add_vertex_none(r, x0, y1); -} - -void -renderer_draw_flush(struct xa_context *r) -{ - renderer_draw_conditional(r, 0); -} - -void -renderer_begin_textures(struct xa_context *r) -{ - r->attrs_per_vertex = 1 + r->num_bound_samplers; - r->buffer_size = 0; - if (r->has_solid_src || r->has_solid_mask) - renderer_set_constants(r, PIPE_SHADER_FRAGMENT, r->solid_color, - 4 * sizeof(float)); -} - -void -renderer_texture(struct xa_context *r, - int *pos, - int width, int height, - const float *src_matrix, - const float *mask_matrix) -{ - struct pipe_sampler_view **sampler_view = r->bound_sampler_views; - -#if 0 - if (src_matrix) { - debug_printf("src_matrix = \n"); - debug_printf("%f, %f, %f\n", src_matrix[0], src_matrix[1], src_matrix[2]); - debug_printf("%f, %f, %f\n", src_matrix[3], src_matrix[4], src_matrix[5]); - debug_printf("%f, %f, %f\n", src_matrix[6], src_matrix[7], src_matrix[8]); - } - if (mask_matrix) { - debug_printf("mask_matrix = \n"); - debug_printf("%f, %f, %f\n", mask_matrix[0], mask_matrix[1], mask_matrix[2]); - debug_printf("%f, %f, %f\n", mask_matrix[3], mask_matrix[4], mask_matrix[5]); - debug_printf("%f, %f, %f\n", mask_matrix[6], mask_matrix[7], mask_matrix[8]); - } -#endif - - switch(r->attrs_per_vertex) { - case 2: - renderer_draw_conditional(r, 4 * 8); - if (!r->has_solid_src) { - add_vertex_data1(r, - pos[0], pos[1], /* src */ - pos[4], pos[5], /* dst */ - width, height, - sampler_view[0]->texture, src_matrix); - } else { - add_vertex_data1(r, - pos[2], pos[3], /* mask */ - pos[4], pos[5], /* dst */ - width, height, - sampler_view[0]->texture, mask_matrix); - } - break; - case 3: - renderer_draw_conditional(r, 4 * 12); - add_vertex_data2(r, - pos[0], pos[1], /* src */ - pos[2], pos[3], /* mask */ - pos[4], pos[5], /* dst */ - width, height, - sampler_view[0]->texture, sampler_view[1]->texture, - src_matrix, mask_matrix); - break; - default: - break; - } -} diff --git a/src/gallium/state_trackers/xa/xa_tgsi.c b/src/gallium/state_trackers/xa/xa_tgsi.c deleted file mode 100644 index 83f6db128c3..00000000000 --- a/src/gallium/state_trackers/xa/xa_tgsi.c +++ /dev/null @@ -1,500 +0,0 @@ -/********************************************************** - * Copyright 2009-2011 VMware, Inc. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - ********************************************************* - * Authors: - * Zack Rusin - */ -#include "xa_priv.h" - -#include "pipe/p_format.h" -#include "pipe/p_context.h" -#include "pipe/p_state.h" -#include "pipe/p_shader_tokens.h" - -#include "util/u_memory.h" - -#include "tgsi/tgsi_ureg.h" - -#include "cso_cache/cso_context.h" -#include "cso_cache/cso_hash.h" - -/* Vertex shader: - * IN[0] = vertex pos - * IN[1] = src tex coord | solid fill color - * IN[2] = mask tex coord - * IN[3] = dst tex coord - * CONST[0] = (2/dst_width, 2/dst_height, 1, 1) - * CONST[1] = (-1, -1, 0, 0) - * - * OUT[0] = vertex pos - * OUT[1] = src tex coord - * OUT[2] = mask tex coord - * OUT[3] = dst tex coord - */ - -/* Fragment shader. Samplers are allocated when needed. - * SAMP[0] = sampler for first texture (src or mask if src is solid) - * SAMP[1] = sampler for second texture (mask or none) - * IN[0] = first texture coordinates if present - * IN[1] = second texture coordinates if present - * CONST[0] = Solid color (src if src solid or mask if mask solid - * or src in mask if both solid). - * - * OUT[0] = color - */ - -static void -print_fs_traits(int fs_traits) -{ - const char *strings[] = { - "FS_COMPOSITE", /* = 1 << 0, */ - "FS_MASK", /* = 1 << 1, */ - "FS_SRC_SRC", /* = 1 << 2, */ - "FS_MASK_SRC", /* = 1 << 3, */ - "FS_YUV", /* = 1 << 4, */ - "FS_SRC_REPEAT_NONE", /* = 1 << 5, */ - "FS_MASK_REPEAT_NONE", /* = 1 << 6, */ - "FS_SRC_SWIZZLE_RGB", /* = 1 << 7, */ - "FS_MASK_SWIZZLE_RGB", /* = 1 << 8, */ - "FS_SRC_SET_ALPHA", /* = 1 << 9, */ - "FS_MASK_SET_ALPHA", /* = 1 << 10, */ - "FS_SRC_LUMINANCE", /* = 1 << 11, */ - "FS_MASK_LUMINANCE", /* = 1 << 12, */ - "FS_DST_LUMINANCE", /* = 1 << 13, */ - "FS_CA", /* = 1 << 14, */ - }; - int i, k; - - debug_printf("%s: ", __func__); - - for (i = 0, k = 1; k < (1 << 16); i++, k <<= 1) { - if (fs_traits & k) - debug_printf("%s, ", strings[i]); - } - - debug_printf("\n"); -} - -struct xa_shaders { - struct xa_context *r; - - struct cso_hash vs_hash; - struct cso_hash fs_hash; -}; - -static inline void -src_in_mask(struct ureg_program *ureg, - struct ureg_dst dst, - struct ureg_src src, - struct ureg_src mask, - unsigned mask_luminance, boolean component_alpha) -{ - if (mask_luminance) - if (component_alpha) { - ureg_MOV(ureg, dst, src); - ureg_MUL(ureg, ureg_writemask(dst, TGSI_WRITEMASK_W), - src, ureg_scalar(mask, TGSI_SWIZZLE_X)); - } else { - ureg_MUL(ureg, dst, src, ureg_scalar(mask, TGSI_SWIZZLE_X)); - } - else if (!component_alpha) - ureg_MUL(ureg, dst, src, ureg_scalar(mask, TGSI_SWIZZLE_W)); - else - ureg_MUL(ureg, dst, src, mask); -} - -static struct ureg_src -vs_normalize_coords(struct ureg_program *ureg, - struct ureg_src coords, - struct ureg_src const0, struct ureg_src const1) -{ - struct ureg_dst tmp = ureg_DECL_temporary(ureg); - struct ureg_src ret; - - ureg_MAD(ureg, tmp, coords, const0, const1); - ret = ureg_src(tmp); - ureg_release_temporary(ureg, tmp); - return ret; -} - -static void * -create_vs(struct pipe_context *pipe, unsigned vs_traits) -{ - struct ureg_program *ureg; - struct ureg_src src; - struct ureg_dst dst; - struct ureg_src const0, const1; - boolean is_composite = (vs_traits & VS_COMPOSITE) != 0; - boolean has_mask = (vs_traits & VS_MASK) != 0; - boolean is_yuv = (vs_traits & VS_YUV) != 0; - boolean is_src_src = (vs_traits & VS_SRC_SRC) != 0; - boolean is_mask_src = (vs_traits & VS_MASK_SRC) != 0; - unsigned input_slot = 0; - - ureg = ureg_create(PIPE_SHADER_VERTEX); - if (ureg == NULL) - return 0; - - const0 = ureg_DECL_constant(ureg, 0); - const1 = ureg_DECL_constant(ureg, 1); - - /* it has to be either a fill or a composite op */ - src = ureg_DECL_vs_input(ureg, input_slot++); - dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0); - src = vs_normalize_coords(ureg, src, const0, const1); - ureg_MOV(ureg, dst, src); - - if (is_yuv) { - src = ureg_DECL_vs_input(ureg, input_slot++); - dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 0); - ureg_MOV(ureg, dst, src); - } - - if (is_composite) { - if (!is_src_src || (has_mask && !is_mask_src)) { - src = ureg_DECL_vs_input(ureg, input_slot++); - dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 0); - ureg_MOV(ureg, dst, src); - } - - if (!is_src_src && (has_mask && !is_mask_src)) { - src = ureg_DECL_vs_input(ureg, input_slot++); - dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 1); - ureg_MOV(ureg, dst, src); - } - } - - ureg_END(ureg); - - return ureg_create_shader_and_destroy(ureg, pipe); -} - -static void * -create_yuv_shader(struct pipe_context *pipe, struct ureg_program *ureg) -{ - struct ureg_src y_sampler, u_sampler, v_sampler; - struct ureg_src pos; - struct ureg_src matrow0, matrow1, matrow2, matrow3; - struct ureg_dst y, u, v, rgb; - struct ureg_dst out = ureg_DECL_output(ureg, - TGSI_SEMANTIC_COLOR, - 0); - - pos = ureg_DECL_fs_input(ureg, - TGSI_SEMANTIC_GENERIC, 0, - TGSI_INTERPOLATE_PERSPECTIVE); - - rgb = ureg_DECL_temporary(ureg); - y = ureg_DECL_temporary(ureg); - u = ureg_DECL_temporary(ureg); - v = ureg_DECL_temporary(ureg); - - y_sampler = ureg_DECL_sampler(ureg, 0); - u_sampler = ureg_DECL_sampler(ureg, 1); - v_sampler = ureg_DECL_sampler(ureg, 2); - - ureg_DECL_sampler_view(ureg, 0, TGSI_TEXTURE_2D, - TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT, - TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT); - ureg_DECL_sampler_view(ureg, 1, TGSI_TEXTURE_2D, - TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT, - TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT); - ureg_DECL_sampler_view(ureg, 2, TGSI_TEXTURE_2D, - TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT, - TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT); - - matrow0 = ureg_DECL_constant(ureg, 0); - matrow1 = ureg_DECL_constant(ureg, 1); - matrow2 = ureg_DECL_constant(ureg, 2); - matrow3 = ureg_DECL_constant(ureg, 3); - - ureg_TEX(ureg, y, TGSI_TEXTURE_2D, pos, y_sampler); - ureg_TEX(ureg, u, TGSI_TEXTURE_2D, pos, u_sampler); - ureg_TEX(ureg, v, TGSI_TEXTURE_2D, pos, v_sampler); - - ureg_MOV(ureg, rgb, matrow3); - ureg_MAD(ureg, rgb, - ureg_scalar(ureg_src(y), TGSI_SWIZZLE_X), matrow0, ureg_src(rgb)); - ureg_MAD(ureg, rgb, - ureg_scalar(ureg_src(u), TGSI_SWIZZLE_X), matrow1, ureg_src(rgb)); - ureg_MAD(ureg, rgb, - ureg_scalar(ureg_src(v), TGSI_SWIZZLE_X), matrow2, ureg_src(rgb)); - - ureg_MOV(ureg, out, ureg_src(rgb)); - - ureg_release_temporary(ureg, rgb); - ureg_release_temporary(ureg, y); - ureg_release_temporary(ureg, u); - ureg_release_temporary(ureg, v); - - ureg_END(ureg); - - return ureg_create_shader_and_destroy(ureg, pipe); -} - -static inline void -xrender_tex(struct ureg_program *ureg, - struct ureg_dst dst, - struct ureg_src coords, - struct ureg_src sampler, - const struct ureg_src *imm0, - boolean repeat_none, boolean swizzle, boolean set_alpha) -{ - if (repeat_none) { - struct ureg_dst tmp0 = ureg_DECL_temporary(ureg); - struct ureg_dst tmp1 = ureg_DECL_temporary(ureg); - - ureg_SGT(ureg, tmp1, ureg_swizzle(coords, - TGSI_SWIZZLE_X, - TGSI_SWIZZLE_Y, - TGSI_SWIZZLE_X, - TGSI_SWIZZLE_Y), ureg_scalar(*imm0, - TGSI_SWIZZLE_X)); - ureg_SLT(ureg, tmp0, - ureg_swizzle(coords, TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y, - TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y), ureg_scalar(*imm0, - TGSI_SWIZZLE_W)); - ureg_MIN(ureg, tmp0, ureg_src(tmp0), ureg_src(tmp1)); - ureg_MIN(ureg, tmp0, ureg_scalar(ureg_src(tmp0), TGSI_SWIZZLE_X), - ureg_scalar(ureg_src(tmp0), TGSI_SWIZZLE_Y)); - ureg_TEX(ureg, tmp1, TGSI_TEXTURE_2D, coords, sampler); - if (swizzle) - ureg_MOV(ureg, tmp1, ureg_swizzle(ureg_src(tmp1), - TGSI_SWIZZLE_Z, - TGSI_SWIZZLE_Y, TGSI_SWIZZLE_X, - TGSI_SWIZZLE_W)); - if (set_alpha) - ureg_MOV(ureg, - ureg_writemask(tmp1, TGSI_WRITEMASK_W), - ureg_scalar(*imm0, TGSI_SWIZZLE_W)); - ureg_MUL(ureg, dst, ureg_src(tmp1), ureg_src(tmp0)); - ureg_release_temporary(ureg, tmp0); - ureg_release_temporary(ureg, tmp1); - } else { - if (swizzle) { - struct ureg_dst tmp = ureg_DECL_temporary(ureg); - - ureg_TEX(ureg, tmp, TGSI_TEXTURE_2D, coords, sampler); - ureg_MOV(ureg, dst, ureg_swizzle(ureg_src(tmp), - TGSI_SWIZZLE_Z, - TGSI_SWIZZLE_Y, TGSI_SWIZZLE_X, - TGSI_SWIZZLE_W)); - ureg_release_temporary(ureg, tmp); - } else { - ureg_TEX(ureg, dst, TGSI_TEXTURE_2D, coords, sampler); - } - if (set_alpha) - ureg_MOV(ureg, - ureg_writemask(dst, TGSI_WRITEMASK_W), - ureg_scalar(*imm0, TGSI_SWIZZLE_W)); - } -} - -static void -read_input(struct ureg_program *ureg, - struct ureg_dst dst, - const struct ureg_src *imm0, - boolean repeat_none, boolean swizzle, boolean set_alpha, - boolean is_src, unsigned *cur_constant, unsigned *cur_sampler) -{ - struct ureg_src input, sampler; - - if (is_src) { - input = ureg_DECL_constant(ureg, (*cur_constant)++); - ureg_MOV(ureg, dst, input); - } else { - sampler = ureg_DECL_sampler(ureg, *cur_sampler); - ureg_DECL_sampler_view(ureg, *cur_sampler, TGSI_TEXTURE_2D, - TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT, - TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT); - input = ureg_DECL_fs_input(ureg, - TGSI_SEMANTIC_GENERIC, (*cur_sampler)++, - TGSI_INTERPOLATE_PERSPECTIVE); - xrender_tex(ureg, dst, input, sampler, imm0, - repeat_none, swizzle, set_alpha); - } -} - -static void * -create_fs(struct pipe_context *pipe, unsigned fs_traits) -{ - struct ureg_program *ureg; - struct ureg_dst src, mask; - struct ureg_dst out; - struct ureg_src imm0 = { 0 }; - unsigned has_mask = (fs_traits & FS_MASK) != 0; - unsigned is_yuv = (fs_traits & FS_YUV) != 0; - unsigned src_repeat_none = (fs_traits & FS_SRC_REPEAT_NONE) != 0; - unsigned mask_repeat_none = (fs_traits & FS_MASK_REPEAT_NONE) != 0; - unsigned src_swizzle = (fs_traits & FS_SRC_SWIZZLE_RGB) != 0; - unsigned mask_swizzle = (fs_traits & FS_MASK_SWIZZLE_RGB) != 0; - unsigned src_set_alpha = (fs_traits & FS_SRC_SET_ALPHA) != 0; - unsigned mask_set_alpha = (fs_traits & FS_MASK_SET_ALPHA) != 0; - unsigned src_luminance = (fs_traits & FS_SRC_LUMINANCE) != 0; - unsigned mask_luminance = (fs_traits & FS_MASK_LUMINANCE) != 0; - unsigned dst_luminance = (fs_traits & FS_DST_LUMINANCE) != 0; - unsigned is_src_src = (fs_traits & FS_SRC_SRC) != 0; - unsigned is_mask_src = (fs_traits & FS_MASK_SRC) != 0; - boolean component_alpha = (fs_traits & FS_CA) != 0; - unsigned cur_sampler = 0; - unsigned cur_constant = 0; - -#if 0 - print_fs_traits(fs_traits); -#else - (void)print_fs_traits; -#endif - - ureg = ureg_create(PIPE_SHADER_FRAGMENT); - if (ureg == NULL) - return 0; - - if (is_yuv) - return create_yuv_shader(pipe, ureg); - - out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0); - - if (src_repeat_none || mask_repeat_none || - src_set_alpha || mask_set_alpha || src_luminance) { - imm0 = ureg_imm4f(ureg, 0, 0, 0, 1); - } - - src = (has_mask || src_luminance || dst_luminance) ? - ureg_DECL_temporary(ureg) : out; - - read_input(ureg, src, &imm0, src_repeat_none, src_swizzle, - src_set_alpha, is_src_src, &cur_constant, &cur_sampler); - - if (src_luminance) { - ureg_MOV(ureg, src, ureg_scalar(ureg_src(src), TGSI_SWIZZLE_X)); - ureg_MOV(ureg, ureg_writemask(src, TGSI_WRITEMASK_XYZ), - ureg_scalar(imm0, TGSI_SWIZZLE_X)); - if (!has_mask && !dst_luminance) - ureg_MOV(ureg, out, ureg_src(src)); - } - - if (has_mask) { - mask = ureg_DECL_temporary(ureg); - read_input(ureg, mask, &imm0, mask_repeat_none, - mask_swizzle, mask_set_alpha, is_mask_src, &cur_constant, - &cur_sampler); - - src_in_mask(ureg, (dst_luminance) ? src : out, ureg_src(src), - ureg_src(mask), mask_luminance, component_alpha); - - ureg_release_temporary(ureg, mask); - } - - if (dst_luminance) { - /* - * Make sure the alpha channel goes into the output L8 surface. - */ - ureg_MOV(ureg, out, ureg_scalar(ureg_src(src), TGSI_SWIZZLE_W)); - } - - ureg_END(ureg); - - return ureg_create_shader_and_destroy(ureg, pipe); -} - -struct xa_shaders * -xa_shaders_create(struct xa_context *r) -{ - struct xa_shaders *sc = CALLOC_STRUCT(xa_shaders); - - sc->r = r; - cso_hash_init(&sc->vs_hash); - cso_hash_init(&sc->fs_hash); - - return sc; -} - -static void -cache_destroy(struct pipe_context *pipe, - struct cso_hash *hash, unsigned processor) -{ - struct cso_hash_iter iter = cso_hash_first_node(hash); - - while (!cso_hash_iter_is_null(iter)) { - void *shader = (void *)cso_hash_iter_data(iter); - - if (processor == PIPE_SHADER_FRAGMENT) { - pipe->delete_fs_state(pipe, shader); - } else if (processor == PIPE_SHADER_VERTEX) { - pipe->delete_vs_state(pipe, shader); - } - iter = cso_hash_erase(hash, iter); - } - cso_hash_deinit(hash); -} - -void -xa_shaders_destroy(struct xa_shaders *sc) -{ - cache_destroy(sc->r->pipe, &sc->vs_hash, PIPE_SHADER_VERTEX); - cache_destroy(sc->r->pipe, &sc->fs_hash, PIPE_SHADER_FRAGMENT); - - FREE(sc); -} - -static inline void * -shader_from_cache(struct pipe_context *pipe, - unsigned type, struct cso_hash *hash, unsigned key) -{ - void *shader = 0; - - struct cso_hash_iter iter = cso_hash_find(hash, key); - - if (cso_hash_iter_is_null(iter)) { - if (type == PIPE_SHADER_VERTEX) - shader = create_vs(pipe, key); - else - shader = create_fs(pipe, key); - cso_hash_insert(hash, key, shader); - } else - shader = (void *)cso_hash_iter_data(iter); - - return shader; -} - -struct xa_shader -xa_shaders_get(struct xa_shaders *sc, unsigned vs_traits, unsigned fs_traits) -{ - struct xa_shader shader = { NULL, NULL }; - void *vs, *fs; - - vs = shader_from_cache(sc->r->pipe, PIPE_SHADER_VERTEX, - &sc->vs_hash, vs_traits); - fs = shader_from_cache(sc->r->pipe, PIPE_SHADER_FRAGMENT, - &sc->fs_hash, fs_traits); - - debug_assert(vs && fs); - if (!vs || !fs) - return shader; - - shader.vs = vs; - shader.fs = fs; - - return shader; -} diff --git a/src/gallium/state_trackers/xa/xa_tracker.c b/src/gallium/state_trackers/xa/xa_tracker.c deleted file mode 100644 index 0909044fb91..00000000000 --- a/src/gallium/state_trackers/xa/xa_tracker.c +++ /dev/null @@ -1,578 +0,0 @@ -/********************************************************** - * Copyright 2009-2011 VMware, Inc. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - ********************************************************* - * Authors: - * Thomas Hellstrom - */ - -#include -#include "xa_tracker.h" -#include "xa_priv.h" -#include "pipe/p_state.h" -#include "pipe/p_format.h" -#include "pipe-loader/pipe_loader.h" -#include "state_tracker/drm_driver.h" -#include "util/u_inlines.h" - -/* - * format_map [xa_surface_type][first..last in list]. - * Needs to be updated when enum xa_formats is updated. - */ - -static const enum xa_formats preferred_a[] = { xa_format_a8 }; - -static const enum xa_formats preferred_argb[] = - { xa_format_a8r8g8b8, xa_format_x8r8g8b8, xa_format_r5g6b5, - xa_format_x1r5g5b5 -}; -static const enum xa_formats preferred_z[] = - { xa_format_z32, xa_format_z24, xa_format_z16 }; -static const enum xa_formats preferred_sz[] = - { xa_format_x8z24, xa_format_s8z24 }; -static const enum xa_formats preferred_zs[] = - { xa_format_z24x8, xa_format_z24s8 }; -static const enum xa_formats preferred_yuv[] = { xa_format_yuv8 }; - -static const enum xa_formats *preferred[] = - { NULL, preferred_a, preferred_argb, NULL, NULL, - preferred_z, preferred_zs, preferred_sz, preferred_yuv -}; - -static const unsigned int num_preferred[] = { 0, - sizeof(preferred_a) / sizeof(enum xa_formats), - sizeof(preferred_argb) / sizeof(enum xa_formats), - 0, - 0, - sizeof(preferred_z) / sizeof(enum xa_formats), - sizeof(preferred_zs) / sizeof(enum xa_formats), - sizeof(preferred_sz) / sizeof(enum xa_formats), - sizeof(preferred_yuv) / sizeof(enum xa_formats) -}; - -static const unsigned int stype_bind[XA_LAST_SURFACE_TYPE] = { 0, - PIPE_BIND_SAMPLER_VIEW, - PIPE_BIND_SAMPLER_VIEW, - PIPE_BIND_SAMPLER_VIEW, - PIPE_BIND_SAMPLER_VIEW, - PIPE_BIND_DEPTH_STENCIL, - PIPE_BIND_DEPTH_STENCIL, - PIPE_BIND_DEPTH_STENCIL, - PIPE_BIND_SAMPLER_VIEW -}; - -static struct xa_format_descriptor -xa_get_pipe_format(struct xa_tracker *xa, enum xa_formats xa_format) -{ - struct xa_format_descriptor fdesc; - - fdesc.xa_format = xa_format; - - switch (xa_format) { - case xa_format_a8: - if (xa->screen->is_format_supported(xa->screen, PIPE_FORMAT_R8_UNORM, - PIPE_TEXTURE_2D, 0, 0, - stype_bind[xa_type_a] | - PIPE_BIND_RENDER_TARGET)) - fdesc.format = PIPE_FORMAT_R8_UNORM; - else - fdesc.format = PIPE_FORMAT_L8_UNORM; - break; - case xa_format_a8r8g8b8: - fdesc.format = PIPE_FORMAT_B8G8R8A8_UNORM; - break; - case xa_format_x8r8g8b8: - fdesc.format = PIPE_FORMAT_B8G8R8X8_UNORM; - break; - case xa_format_r5g6b5: - fdesc.format = PIPE_FORMAT_B5G6R5_UNORM; - break; - case xa_format_x1r5g5b5: - fdesc.format = PIPE_FORMAT_B5G5R5A1_UNORM; - break; - case xa_format_a4r4g4b4: - fdesc.format = PIPE_FORMAT_B4G4R4A4_UNORM; - break; - case xa_format_a2b10g10r10: - fdesc.format = PIPE_FORMAT_R10G10B10A2_UNORM; - break; - case xa_format_x2b10g10r10: - fdesc.format = PIPE_FORMAT_R10G10B10X2_UNORM; - break; - case xa_format_b8g8r8a8: - fdesc.format = PIPE_FORMAT_A8R8G8B8_UNORM; - break; - case xa_format_b8g8r8x8: - fdesc.format = PIPE_FORMAT_X8R8G8B8_UNORM; - break; - case xa_format_z24: - fdesc.format = PIPE_FORMAT_Z24X8_UNORM; - break; - case xa_format_z16: - fdesc.format = PIPE_FORMAT_Z16_UNORM; - break; - case xa_format_z32: - fdesc.format = PIPE_FORMAT_Z32_UNORM; - break; - case xa_format_x8z24: - fdesc.format = PIPE_FORMAT_Z24X8_UNORM; - break; - case xa_format_z24x8: - fdesc.format = PIPE_FORMAT_X8Z24_UNORM; - break; - case xa_format_s8z24: - fdesc.format = PIPE_FORMAT_Z24_UNORM_S8_UINT; - break; - case xa_format_z24s8: - fdesc.format = PIPE_FORMAT_S8_UINT_Z24_UNORM; - break; - case xa_format_yuv8: - if (xa->screen->is_format_supported(xa->screen, PIPE_FORMAT_R8_UNORM, - PIPE_TEXTURE_2D, 0, 0, - stype_bind[xa_type_yuv_component])) - fdesc.format = PIPE_FORMAT_R8_UNORM; - else - fdesc.format = PIPE_FORMAT_L8_UNORM; - break; - default: - fdesc.xa_format = xa_format_unknown; - break; - } - return fdesc; -} - -XA_EXPORT struct xa_tracker * -xa_tracker_create(int drm_fd) -{ - struct xa_tracker *xa = calloc(1, sizeof(struct xa_tracker)); - enum xa_surface_type stype; - unsigned int num_formats; - - if (!xa) - return NULL; - - if (pipe_loader_drm_probe_fd(&xa->dev, drm_fd)) - xa->screen = pipe_loader_create_screen(xa->dev); - - if (!xa->screen) - goto out_no_screen; - - xa->default_ctx = xa_context_create(xa); - if (!xa->default_ctx) - goto out_no_pipe; - - num_formats = 0; - for (stype = 0; stype < XA_LAST_SURFACE_TYPE; ++stype) - num_formats += num_preferred[stype]; - - num_formats += 1; - xa->supported_formats = calloc(num_formats, sizeof(*xa->supported_formats)); - if (!xa->supported_formats) - goto out_sf_alloc_fail; - - xa->supported_formats[0] = xa_format_unknown; - num_formats = 1; - memset(xa->format_map, 0, sizeof(xa->format_map)); - - for (stype = 0; stype < XA_LAST_SURFACE_TYPE; ++stype) { - unsigned int bind = stype_bind[stype]; - enum xa_formats xa_format; - int i; - - for (i = 0; i < num_preferred[stype]; ++i) { - xa_format = preferred[stype][i]; - - struct xa_format_descriptor fdesc = - xa_get_pipe_format(xa, xa_format); - - if (xa->screen->is_format_supported(xa->screen, fdesc.format, - PIPE_TEXTURE_2D, 0, 0, bind)) { - if (xa->format_map[stype][0] == 0) - xa->format_map[stype][0] = num_formats; - xa->format_map[stype][1] = num_formats; - xa->supported_formats[num_formats++] = xa_format; - } - } - } - return xa; - - out_sf_alloc_fail: - xa_context_destroy(xa->default_ctx); - out_no_pipe: - xa->screen->destroy(xa->screen); - out_no_screen: - if (xa->dev) - pipe_loader_release(&xa->dev, 1); - - free(xa); - return NULL; -} - -XA_EXPORT void -xa_tracker_destroy(struct xa_tracker *xa) -{ - free(xa->supported_formats); - xa_context_destroy(xa->default_ctx); - xa->screen->destroy(xa->screen); - pipe_loader_release(&xa->dev, 1); - /* CHECK: The XA API user preserves ownership of the original fd */ - free(xa); -} - -static int -xa_flags_compat(unsigned int old_flags, unsigned int new_flags) -{ - unsigned int flag_diff = (old_flags ^ new_flags); - - if (flag_diff == 0) - return 1; - - if (flag_diff & XA_FLAG_SHARED) - return 0; - /* - * Don't recreate if we're dropping the render target flag. - */ - if (flag_diff & XA_FLAG_RENDER_TARGET) - return ((new_flags & XA_FLAG_RENDER_TARGET) == 0); - - /* - * Don't recreate if we're dropping the scanout flag. - */ - if (flag_diff & XA_FLAG_SCANOUT) - return ((new_flags & XA_FLAG_SCANOUT) == 0); - - /* - * Always recreate for unknown / unimplemented flags. - */ - return 0; -} - -static struct xa_format_descriptor -xa_get_format_stype_depth(struct xa_tracker *xa, - enum xa_surface_type stype, unsigned int depth) -{ - unsigned int i; - struct xa_format_descriptor fdesc; - int found = 0; - - for (i = xa->format_map[stype][0]; i <= xa->format_map[stype][1]; ++i) { - fdesc = xa_get_pipe_format(xa, xa->supported_formats[i]); - if (fdesc.xa_format != xa_format_unknown && - xa_format_depth(fdesc.xa_format) == depth) { - found = 1; - break; - } - } - - if (!found) - fdesc.xa_format = xa_format_unknown; - - return fdesc; -} - -XA_EXPORT int -xa_format_check_supported(struct xa_tracker *xa, - enum xa_formats xa_format, unsigned int flags) -{ - struct xa_format_descriptor fdesc = xa_get_pipe_format(xa, xa_format); - unsigned int bind; - - if (fdesc.xa_format == xa_format_unknown) - return -XA_ERR_INVAL; - - bind = stype_bind[xa_format_type(fdesc.xa_format)]; - if (flags & XA_FLAG_SHARED) - bind |= PIPE_BIND_SHARED; - if (flags & XA_FLAG_RENDER_TARGET) - bind |= PIPE_BIND_RENDER_TARGET; - if (flags & XA_FLAG_SCANOUT) - bind |= PIPE_BIND_SCANOUT; - - if (!xa->screen->is_format_supported(xa->screen, fdesc.format, - PIPE_TEXTURE_2D, 0, 0, bind)) - return -XA_ERR_INVAL; - - return XA_ERR_NONE; -} - -static unsigned -handle_type(enum xa_handle_type type) -{ - switch (type) { - case xa_handle_type_kms: - return WINSYS_HANDLE_TYPE_KMS; - case xa_handle_type_fd: - return WINSYS_HANDLE_TYPE_FD; - case xa_handle_type_shared: - default: - return WINSYS_HANDLE_TYPE_SHARED; - } -} - -static struct xa_surface * -surface_create(struct xa_tracker *xa, - int width, - int height, - int depth, - enum xa_surface_type stype, - enum xa_formats xa_format, unsigned int flags, - struct winsys_handle *whandle) -{ - struct pipe_resource *template; - struct xa_surface *srf; - struct xa_format_descriptor fdesc; - - if (xa_format == xa_format_unknown) - fdesc = xa_get_format_stype_depth(xa, stype, depth); - else - fdesc = xa_get_pipe_format(xa, xa_format); - - if (fdesc.xa_format == xa_format_unknown) - return NULL; - - srf = calloc(1, sizeof(*srf)); - if (!srf) - return NULL; - - template = &srf->template; - template->format = fdesc.format; - template->target = PIPE_TEXTURE_2D; - template->width0 = width; - template->height0 = height; - template->depth0 = 1; - template->array_size = 1; - template->last_level = 0; - template->bind = stype_bind[xa_format_type(fdesc.xa_format)]; - - if (flags & XA_FLAG_SHARED) - template->bind |= PIPE_BIND_SHARED; - if (flags & XA_FLAG_RENDER_TARGET) - template->bind |= PIPE_BIND_RENDER_TARGET; - if (flags & XA_FLAG_SCANOUT) - template->bind |= PIPE_BIND_SCANOUT; - - if (whandle) - srf->tex = xa->screen->resource_from_handle(xa->screen, template, whandle, - PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE); - else - srf->tex = xa->screen->resource_create(xa->screen, template); - if (!srf->tex) - goto out_no_tex; - - srf->refcount = 1; - srf->xa = xa; - srf->flags = flags; - srf->fdesc = fdesc; - - return srf; - out_no_tex: - free(srf); - return NULL; -} - - -XA_EXPORT struct xa_surface * -xa_surface_create(struct xa_tracker *xa, - int width, - int height, - int depth, - enum xa_surface_type stype, - enum xa_formats xa_format, unsigned int flags) -{ - return surface_create(xa, width, height, depth, stype, xa_format, flags, NULL); -} - - -XA_EXPORT struct xa_surface * -xa_surface_from_handle(struct xa_tracker *xa, - int width, - int height, - int depth, - enum xa_surface_type stype, - enum xa_formats xa_format, unsigned int flags, - uint32_t handle, uint32_t stride) -{ - return xa_surface_from_handle2(xa, width, height, depth, stype, xa_format, - WINSYS_HANDLE_TYPE_SHARED, flags, handle, - stride); -} - -XA_EXPORT struct xa_surface * -xa_surface_from_handle2(struct xa_tracker *xa, - int width, - int height, - int depth, - enum xa_surface_type stype, - enum xa_formats xa_format, unsigned int flags, - enum xa_handle_type type, - uint32_t handle, uint32_t stride) -{ - struct winsys_handle whandle; - memset(&whandle, 0, sizeof(whandle)); - whandle.type = handle_type(type); - whandle.handle = handle; - whandle.stride = stride; - return surface_create(xa, width, height, depth, stype, xa_format, flags, &whandle); -} - -XA_EXPORT int -xa_surface_redefine(struct xa_surface *srf, - int width, - int height, - int depth, - enum xa_surface_type stype, - enum xa_formats xa_format, - unsigned int new_flags, - int copy_contents) -{ - struct pipe_resource *template = &srf->template; - struct pipe_resource *texture; - struct pipe_box src_box; - struct xa_tracker *xa = srf->xa; - int save_width; - int save_height; - unsigned int save_format; - struct xa_format_descriptor fdesc; - - - if (xa_format == xa_format_unknown) - fdesc = xa_get_format_stype_depth(xa, stype, depth); - else - fdesc = xa_get_pipe_format(xa, xa_format); - - if (width == template->width0 && height == template->height0 && - template->format == fdesc.format && - xa_flags_compat(srf->flags, new_flags)) - return XA_ERR_NONE; - - template->bind = stype_bind[xa_format_type(fdesc.xa_format)]; - if (new_flags & XA_FLAG_SHARED) - template->bind |= PIPE_BIND_SHARED; - if (new_flags & XA_FLAG_RENDER_TARGET) - template->bind |= PIPE_BIND_RENDER_TARGET; - if (new_flags & XA_FLAG_SCANOUT) - template->bind |= PIPE_BIND_SCANOUT; - - if (copy_contents) { - if (!xa_format_type_is_color(fdesc.xa_format) || - xa_format_type(fdesc.xa_format) == xa_type_a) - return -XA_ERR_INVAL; - - if (!xa->screen->is_format_supported(xa->screen, fdesc.format, - PIPE_TEXTURE_2D, 0, 0, - template->bind | - PIPE_BIND_RENDER_TARGET)) - return -XA_ERR_INVAL; - } - - save_width = template->width0; - save_height = template->height0; - save_format = template->format; - - template->width0 = width; - template->height0 = height; - template->format = fdesc.format; - - texture = xa->screen->resource_create(xa->screen, template); - if (!texture) { - template->width0 = save_width; - template->height0 = save_height; - template->format = save_format; - return -XA_ERR_NORES; - } - - if (copy_contents) { - struct pipe_context *pipe = xa->default_ctx->pipe; - - u_box_origin_2d(xa_min(save_width, template->width0), - xa_min(save_height, template->height0), &src_box); - pipe->resource_copy_region(pipe, texture, - 0, 0, 0, 0, srf->tex, 0, &src_box); - xa_context_flush(xa->default_ctx); - } - - pipe_resource_reference(&srf->tex, texture); - pipe_resource_reference(&texture, NULL); - srf->fdesc = fdesc; - srf->flags = new_flags; - - return XA_ERR_NONE; -} - -XA_EXPORT struct xa_surface* -xa_surface_ref(struct xa_surface *srf) -{ - if (srf == NULL) { - return NULL; - } - srf->refcount++; - return srf; -} - -XA_EXPORT void -xa_surface_unref(struct xa_surface *srf) -{ - if (srf == NULL || --srf->refcount) { - return; - } - pipe_resource_reference(&srf->tex, NULL); - free(srf); -} - -XA_EXPORT void -xa_tracker_version(int *major, int *minor, int *patch) -{ - *major = XA_TRACKER_VERSION_MAJOR; - *minor = XA_TRACKER_VERSION_MINOR; - *patch = XA_TRACKER_VERSION_PATCH; -} - -XA_EXPORT int -xa_surface_handle(struct xa_surface *srf, - enum xa_handle_type type, - uint32_t * handle, unsigned int *stride) -{ - struct winsys_handle whandle; - - struct pipe_screen *screen = srf->xa->screen; - boolean res; - - memset(&whandle, 0, sizeof(whandle)); - whandle.type = handle_type(type); - res = screen->resource_get_handle(screen, srf->xa->default_ctx->pipe, - srf->tex, &whandle, - PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE); - if (!res) - return -XA_ERR_INVAL; - - *handle = whandle.handle; - *stride = whandle.stride; - - return XA_ERR_NONE; -} - -XA_EXPORT enum xa_formats -xa_surface_format(const struct xa_surface *srf) -{ - return srf->fdesc.xa_format; -} diff --git a/src/gallium/state_trackers/xa/xa_tracker.h.in b/src/gallium/state_trackers/xa/xa_tracker.h.in deleted file mode 100644 index 3d136707152..00000000000 --- a/src/gallium/state_trackers/xa/xa_tracker.h.in +++ /dev/null @@ -1,217 +0,0 @@ -/********************************************************** - * Copyright 2009-2011 VMware, Inc. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * The format encoding idea is partially borrowed from libpixman, but it is not - * considered a "substantial part of the software", so the pixman copyright - * is left out for simplicity, and acknowledgment is instead given in this way. - * - ********************************************************* - * Authors: - * Zack Rusin - * Thomas Hellstrom - */ - -#ifndef _XA_TRACKER_H_ -#define _XA_TRACKER_H_ - -#include - -#define XA_TRACKER_VERSION_MAJOR @XA_MAJOR@ -#define XA_TRACKER_VERSION_MINOR @XA_MINOR@ -#define XA_TRACKER_VERSION_PATCH @XA_PATCH@ - -#define XA_FLAG_SHARED (1 << 0) -#define XA_FLAG_RENDER_TARGET (1 << 1) -#define XA_FLAG_SCANOUT (1 << 2) - -#define XA_MAP_READ (1 << 0) -#define XA_MAP_WRITE (1 << 1) -#define XA_MAP_MAP_DIRECTLY (1 << 2) -#define XA_MAP_UNSYNCHRONIZED (1 << 3) -#define XA_MAP_DONTBLOCK (1 << 4) -#define XA_MAP_DISCARD_WHOLE_RESOURCE (1 << 5) - -#define XA_ERR_NONE 0 -#define XA_ERR_NORES 1 -#define XA_ERR_INVAL 2 -#define XA_ERR_BUSY 3 - -enum xa_surface_type { - xa_type_other, - xa_type_a, - xa_type_argb, - xa_type_abgr, - xa_type_bgra, - xa_type_z, - xa_type_zs, - xa_type_sz, - xa_type_yuv_component -}; - -/* - * Note that these formats should not be assumed to be binary compatible with - * pixman formats, but with the below macros and a format type map, - * conversion should be simple. Macros for now. We might replace with - * inline functions. - */ - -#define xa_format(bpp,type,a,r,g,b) (((bpp) << 24) | \ - ((type) << 16) | \ - ((a) << 12) | \ - ((r) << 8) | \ - ((g) << 4) | \ - ((b))) -/* - * Non-RGBA one- and two component formats. - */ - -#define xa_format_c(bpp,type,c1,c2) (((bpp) << 24) | \ - ((type) << 16) | \ - ((c1) << 8) | \ - ((c2))) -#define xa_format_bpp(f) (((f) >> 24) ) -#define xa_format_type(f) (((f) >> 16) & 0xff) -#define xa_format_a(f) (((f) >> 12) & 0x0f) -#define xa_format_r(f) (((f) >> 8) & 0x0f) -#define xa_format_g(f) (((f) >> 4) & 0x0f) -#define xa_format_b(f) (((f) ) & 0x0f) -#define xa_format_rgb(f) (((f) ) & 0xfff) -#define xa_format_c1(f) (((f) >> 8 ) & 0xff) -#define xa_format_c2(f) (((f) ) & 0xff) -#define xa_format_argb_depth(f) (xa_format_a(f) + \ - xa_format_r(f) + \ - xa_format_g(f) + \ - xa_format_b(f)) -#define xa_format_c_depth(f) (xa_format_c1(f) + \ - xa_format_c2(f)) - -static inline int -xa_format_type_is_color(uint32_t xa_format) -{ - return (xa_format_type(xa_format) < xa_type_z); -} - -static inline unsigned int -xa_format_depth(uint32_t xa_format) -{ - return ((xa_format_type_is_color(xa_format)) ? - xa_format_argb_depth(xa_format) : xa_format_c_depth(xa_format)); -} - -enum xa_formats { - xa_format_unknown = 0, - xa_format_a8 = xa_format(8, xa_type_a, 8, 0, 0, 0), - - xa_format_a8r8g8b8 = xa_format(32, xa_type_argb, 8, 8, 8, 8), - xa_format_x8r8g8b8 = xa_format(32, xa_type_argb, 0, 8, 8, 8), - xa_format_r5g6b5 = xa_format(16, xa_type_argb, 0, 5, 6, 5), - xa_format_x1r5g5b5 = xa_format(16, xa_type_argb, 0, 5, 5, 5), - xa_format_a4r4g4b4 = xa_format(16, xa_type_argb, 4, 4, 4, 4), - xa_format_a2b10g10r10 = xa_format(32, xa_type_abgr, 2, 10, 10, 10), - xa_format_x2b10g10r10 = xa_format(32, xa_type_abgr, 0, 10, 10, 10), - xa_format_b8g8r8a8 = xa_format(32, xa_type_bgra, 8, 8, 8, 8), - xa_format_b8g8r8x8 = xa_format(32, xa_type_bgra, 0, 8, 8, 8), - - xa_format_z16 = xa_format_c(16, xa_type_z, 16, 0), - xa_format_z32 = xa_format_c(32, xa_type_z, 32, 0), - xa_format_z24 = xa_format_c(32, xa_type_z, 24, 0), - - xa_format_x8z24 = xa_format_c(32, xa_type_sz, 24, 0), - xa_format_s8z24 = xa_format_c(32, xa_type_sz, 24, 8), - xa_format_z24x8 = xa_format_c(32, xa_type_zs, 24, 0), - xa_format_z24s8 = xa_format_c(32, xa_type_zs, 24, 8), - - xa_format_yuv8 = xa_format_c(8, xa_type_yuv_component, 8, 0) -}; - -struct xa_tracker; -struct xa_surface; - -struct xa_box { - uint16_t x1, y1, x2, y2; -}; - -enum xa_handle_type { - xa_handle_type_shared, - xa_handle_type_kms, - xa_handle_type_fd, -}; - -extern void xa_tracker_version(int *major, int *minor, int *patch); - -extern struct xa_tracker *xa_tracker_create(int drm_fd); - -extern void xa_tracker_destroy(struct xa_tracker *xa); - -extern int xa_format_check_supported(struct xa_tracker *xa, - enum xa_formats xa_format, - unsigned int flags); - -extern struct xa_surface *xa_surface_create(struct xa_tracker *xa, - int width, - int height, - int depth, - enum xa_surface_type stype, - enum xa_formats pform, - unsigned int flags); - -extern struct xa_surface * xa_surface_from_handle(struct xa_tracker *xa, - int width, - int height, - int depth, - enum xa_surface_type stype, - enum xa_formats pform, - unsigned int flags, - uint32_t handle, uint32_t stride); -extern struct xa_surface * -xa_surface_from_handle2(struct xa_tracker *xa, - int width, - int height, - int depth, - enum xa_surface_type stype, - enum xa_formats xa_format, - unsigned int flags, - enum xa_handle_type type, - uint32_t handle, - uint32_t stride); - -enum xa_formats xa_surface_format(const struct xa_surface *srf); - -extern struct xa_surface *xa_surface_ref(struct xa_surface *srf); -extern void xa_surface_unref(struct xa_surface *srf); - -extern int xa_surface_redefine(struct xa_surface *srf, - int width, - int height, - int depth, - enum xa_surface_type stype, - enum xa_formats rgb_format, - unsigned int new_flags, - int copy_contents); - -extern int xa_surface_handle(struct xa_surface *srf, - enum xa_handle_type type, - uint32_t * handle, - unsigned int *byte_stride); - -#endif diff --git a/src/gallium/state_trackers/xa/xa_yuv.c b/src/gallium/state_trackers/xa/xa_yuv.c deleted file mode 100644 index 97a1833ff15..00000000000 --- a/src/gallium/state_trackers/xa/xa_yuv.c +++ /dev/null @@ -1,163 +0,0 @@ -/********************************************************** - * Copyright 2009-2011 VMware, Inc. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - ********************************************************* - * Authors: - * Zack Rusin - * Thomas Hellstrom - */ - -#include "xa_context.h" -#include "xa_priv.h" -#include "util/u_inlines.h" -#include "util/u_sampler.h" -#include "util/u_surface.h" -#include "cso_cache/cso_context.h" - -static void -xa_yuv_bind_blend_state(struct xa_context *r) -{ - struct pipe_blend_state blend; - - memset(&blend, 0, sizeof(struct pipe_blend_state)); - blend.rt[0].blend_enable = 0; - blend.rt[0].colormask = PIPE_MASK_RGBA; - - /* porter&duff src */ - blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; - blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; - blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; - blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; - - cso_set_blend(r->cso, &blend); -} - -static void -xa_yuv_bind_shaders(struct xa_context *r) -{ - unsigned vs_traits = 0, fs_traits = 0; - struct xa_shader shader; - - vs_traits |= VS_YUV; - fs_traits |= FS_YUV; - - shader = xa_shaders_get(r->shaders, vs_traits, fs_traits); - cso_set_vertex_shader_handle(r->cso, shader.vs); - cso_set_fragment_shader_handle(r->cso, shader.fs); -} - -static void -xa_yuv_bind_samplers(struct xa_context *r, struct xa_surface *yuv[]) -{ - struct pipe_sampler_state *samplers[3]; - struct pipe_sampler_state sampler; - struct pipe_sampler_view view_templ; - unsigned int i; - - memset(&sampler, 0, sizeof(struct pipe_sampler_state)); - - sampler.wrap_s = PIPE_TEX_WRAP_CLAMP; - sampler.wrap_t = PIPE_TEX_WRAP_CLAMP; - sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR; - sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR; - sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST; - sampler.normalized_coords = 1; - - for (i = 0; i < 3; ++i) { - samplers[i] = &sampler; - u_sampler_view_default_template(&view_templ, yuv[i]->tex, - yuv[i]->tex->format); - - r->bound_sampler_views[i] = - r->pipe->create_sampler_view(r->pipe, yuv[i]->tex, &view_templ); - } - r->num_bound_samplers = 3; - cso_set_samplers(r->cso, PIPE_SHADER_FRAGMENT, 3, (const struct pipe_sampler_state **)samplers); - cso_set_sampler_views(r->cso, PIPE_SHADER_FRAGMENT, 3, r->bound_sampler_views); -} - -static void -xa_yuv_fs_constants(struct xa_context *r, const float conversion_matrix[]) -{ - const int param_bytes = 16 * sizeof(float); - - renderer_set_constants(r, PIPE_SHADER_FRAGMENT, - conversion_matrix, param_bytes); -} - -XA_EXPORT int -xa_yuv_planar_blit(struct xa_context *r, - int src_x, - int src_y, - int src_w, - int src_h, - int dst_x, - int dst_y, - int dst_w, - int dst_h, - struct xa_box *box, - unsigned int num_boxes, - const float conversion_matrix[], - struct xa_surface *dst, struct xa_surface *yuv[]) -{ - float scale_x; - float scale_y; - int ret; - - if (dst_w == 0 || dst_h == 0) - return XA_ERR_NONE; - - ret = xa_ctx_srf_create(r, dst); - if (ret != XA_ERR_NONE) - return -XA_ERR_NORES; - - renderer_bind_destination(r, r->srf); - xa_yuv_bind_blend_state(r); - xa_yuv_bind_shaders(r); - xa_yuv_bind_samplers(r, yuv); - xa_yuv_fs_constants(r, conversion_matrix); - - scale_x = (float)src_w / (float)dst_w; - scale_y = (float)src_h / (float)dst_h; - - while (num_boxes--) { - int x = box->x1; - int y = box->y1; - int w = box->x2 - box->x1; - int h = box->y2 - box->y1; - - xa_scissor_update(r, x, y, box->x2, box->y2); - renderer_draw_yuv(r, - (float)src_x + scale_x * (x - dst_x), - (float)src_y + scale_y * (y - dst_y), - scale_x * w, scale_y * h, x, y, w, h, yuv); - box++; - } - - xa_context_flush(r); - - xa_ctx_sampler_views_destroy(r); - xa_ctx_srf_destroy(r); - - return XA_ERR_NONE; -} diff --git a/src/gallium/state_trackers/xvmc/Makefile.sources b/src/gallium/state_trackers/xvmc/Makefile.sources deleted file mode 100644 index 814357bf25d..00000000000 --- a/src/gallium/state_trackers/xvmc/Makefile.sources +++ /dev/null @@ -1,7 +0,0 @@ -C_SOURCES := \ - attributes.c \ - block.c \ - context.c \ - surface.c \ - subpicture.c \ - xvmc_private.h diff --git a/src/gallium/state_trackers/xvmc/attributes.c b/src/gallium/state_trackers/xvmc/attributes.c deleted file mode 100644 index 6e4d78a9a29..00000000000 --- a/src/gallium/state_trackers/xvmc/attributes.c +++ /dev/null @@ -1,153 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 Younes Manton. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include -#include - -#include -#include -#include - -#include "vl/vl_compositor.h" - -#include "xvmc_private.h" - -#define XV_BRIGHTNESS "XV_BRIGHTNESS" -#define XV_CONTRAST "XV_CONTRAST" -#define XV_SATURATION "XV_SATURATION" -#define XV_HUE "XV_HUE" -#define XV_COLORSPACE "XV_COLORSPACE" - -static const XvAttribute attributes[] = { - { XvGettable | XvSettable, -1000, 1000, XV_BRIGHTNESS }, - { XvGettable | XvSettable, -1000, 1000, XV_CONTRAST }, - { XvGettable | XvSettable, -1000, 1000, XV_SATURATION }, - { XvGettable | XvSettable, -1000, 1000, XV_HUE }, - { XvGettable | XvSettable, 0, 1, XV_COLORSPACE } -}; - -PUBLIC -XvAttribute* XvMCQueryAttributes(Display *dpy, XvMCContext *context, int *number) -{ - XvAttribute *result; - - assert(dpy && number); - - if (!context || !context->privData) - return NULL; - - result = malloc(sizeof(attributes)); - if (!result) - return NULL; - - memcpy(result, attributes, sizeof(attributes)); - *number = sizeof(attributes) / sizeof(XvAttribute); - - XVMC_MSG(XVMC_TRACE, "[XvMC] Returning %d attributes for context %p.\n", *number, context); - - return result; -} - -PUBLIC -Status XvMCSetAttribute(Display *dpy, XvMCContext *context, Atom attribute, int value) -{ - XvMCContextPrivate *context_priv; - const char *attr; - vl_csc_matrix csc; - - assert(dpy); - - if (!context || !context->privData) - return XvMCBadContext; - - context_priv = context->privData; - - attr = XGetAtomName(dpy, attribute); - if (!attr) - return XvMCBadContext; - - if (strcmp(attr, XV_BRIGHTNESS) == 0) - context_priv->procamp.brightness = value / 1000.0f; - else if (strcmp(attr, XV_CONTRAST) == 0) - context_priv->procamp.contrast = value / 1000.0f + 1.0f; - else if (strcmp(attr, XV_SATURATION) == 0) - context_priv->procamp.saturation = value / 1000.0f + 1.0f; - else if (strcmp(attr, XV_HUE) == 0) - context_priv->procamp.hue = value / 1000.0f; - else if (strcmp(attr, XV_COLORSPACE) == 0) - context_priv->color_standard = value ? - VL_CSC_COLOR_STANDARD_BT_601 : - VL_CSC_COLOR_STANDARD_BT_709; - else - return BadName; - - vl_csc_get_matrix - ( - context_priv->color_standard, - &context_priv->procamp, true, &csc - ); - vl_compositor_set_csc_matrix(&context_priv->cstate, (const vl_csc_matrix *)&csc, 1.0f, 0.0f); - - XVMC_MSG(XVMC_TRACE, "[XvMC] Set attribute %s to value %d.\n", attr, value); - - return Success; -} - -PUBLIC -Status XvMCGetAttribute(Display *dpy, XvMCContext *context, Atom attribute, int *value) -{ - XvMCContextPrivate *context_priv; - const char *attr; - - assert(dpy); - - if (!context || !context->privData) - return XvMCBadContext; - - context_priv = context->privData; - - attr = XGetAtomName(dpy, attribute); - if (!attr) - return XvMCBadContext; - - if (strcmp(attr, XV_BRIGHTNESS) == 0) - *value = context_priv->procamp.brightness * 1000; - else if (strcmp(attr, XV_CONTRAST) == 0) - *value = context_priv->procamp.contrast * 1000 - 1000; - else if (strcmp(attr, XV_SATURATION) == 0) - *value = context_priv->procamp.saturation * 1000 + 1000; - else if (strcmp(attr, XV_HUE) == 0) - *value = context_priv->procamp.hue * 1000; - else if (strcmp(attr, XV_COLORSPACE) == 0) - *value = context_priv->color_standard == VL_CSC_COLOR_STANDARD_BT_709; - else - return BadName; - - XVMC_MSG(XVMC_TRACE, "[XvMC] Got value %d for attribute %s.\n", *value, attr); - - return Success; -} diff --git a/src/gallium/state_trackers/xvmc/block.c b/src/gallium/state_trackers/xvmc/block.c deleted file mode 100644 index 80296280247..00000000000 --- a/src/gallium/state_trackers/xvmc/block.c +++ /dev/null @@ -1,95 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 Younes Manton. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include - -#include -#include - -#include "util/u_memory.h" - -#include "xvmc_private.h" - -PUBLIC -Status XvMCCreateBlocks(Display *dpy, XvMCContext *context, unsigned int num_blocks, XvMCBlockArray *blocks) -{ - assert(dpy); - - if (!context) - return XvMCBadContext; - if (num_blocks == 0) - return BadValue; - - assert(blocks); - - blocks->context_id = context->context_id; - blocks->num_blocks = num_blocks; - blocks->blocks = MALLOC(BLOCK_SIZE_BYTES * num_blocks); - blocks->privData = NULL; - - return Success; -} - -PUBLIC -Status XvMCDestroyBlocks(Display *dpy, XvMCBlockArray *blocks) -{ - assert(dpy); - assert(blocks); - FREE(blocks->blocks); - - return Success; -} - -PUBLIC -Status XvMCCreateMacroBlocks(Display *dpy, XvMCContext *context, unsigned int num_blocks, XvMCMacroBlockArray *blocks) -{ - assert(dpy); - - if (!context) - return XvMCBadContext; - if (num_blocks == 0) - return BadValue; - - assert(blocks); - - blocks->context_id = context->context_id; - blocks->num_blocks = num_blocks; - blocks->macro_blocks = MALLOC(sizeof(XvMCMacroBlock) * num_blocks); - blocks->privData = NULL; - - return Success; -} - -PUBLIC -Status XvMCDestroyMacroBlocks(Display *dpy, XvMCMacroBlockArray *blocks) -{ - assert(dpy); - assert(blocks); - FREE(blocks->macro_blocks); - - return Success; -} diff --git a/src/gallium/state_trackers/xvmc/context.c b/src/gallium/state_trackers/xvmc/context.c deleted file mode 100644 index 1ecff5e8ac1..00000000000 --- a/src/gallium/state_trackers/xvmc/context.c +++ /dev/null @@ -1,344 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 Younes Manton. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include - -#include -#include - -#include "pipe/p_screen.h" -#include "pipe/p_video_codec.h" -#include "pipe/p_video_state.h" -#include "pipe/p_state.h" - -#include "util/u_memory.h" - -#include "vl/vl_csc.h" -#include "vl/vl_winsys.h" - -#include "xvmc_private.h" - -static Status Validate(Display *dpy, XvPortID port, int surface_type_id, - unsigned int width, unsigned int height, int flags, - bool *found_port, int *screen, int *chroma_format, - int *mc_type, int *surface_flags, - unsigned short *subpic_max_w, - unsigned short *subpic_max_h) -{ - bool found_surface = false; - XvAdaptorInfo *adaptor_info; - unsigned int num_adaptors; - int num_types; - unsigned int max_width = 0, max_height = 0; - Status ret; - - assert(dpy); - assert(found_port); - assert(screen); - assert(chroma_format); - assert(mc_type); - assert(surface_flags); - assert(subpic_max_w); - assert(subpic_max_h); - - *found_port = false; - - for (int i = 0; i < XScreenCount(dpy); ++i) { - ret = XvQueryAdaptors(dpy, XRootWindow(dpy, i), &num_adaptors, &adaptor_info); - if (ret != Success) - return ret; - - for (unsigned int j = 0; j < num_adaptors && !*found_port; ++j) { - for (unsigned int k = 0; k < adaptor_info[j].num_ports && !*found_port; ++k) { - XvMCSurfaceInfo *surface_info; - - if (adaptor_info[j].base_id + k != port) - continue; - - *found_port = true; - - surface_info = XvMCListSurfaceTypes(dpy, adaptor_info[j].base_id, &num_types); - if (!surface_info) { - XvFreeAdaptorInfo(adaptor_info); - return BadAlloc; - } - - for (int l = 0; l < num_types && !found_surface; ++l) { - if (surface_info[l].surface_type_id != surface_type_id) - continue; - - found_surface = true; - max_width = surface_info[l].max_width; - max_height = surface_info[l].max_height; - *chroma_format = surface_info[l].chroma_format; - *mc_type = surface_info[l].mc_type; - *surface_flags = surface_info[l].flags; - *subpic_max_w = surface_info[l].subpicture_max_width; - *subpic_max_h = surface_info[l].subpicture_max_height; - *screen = i; - - XVMC_MSG(XVMC_TRACE, "[XvMC] Found requested context surface format.\n" \ - "[XvMC] screen=%u, port=%u\n" \ - "[XvMC] id=0x%08X\n" \ - "[XvMC] max width=%u, max height=%u\n" \ - "[XvMC] chroma format=0x%08X\n" \ - "[XvMC] acceleration level=0x%08X\n" \ - "[XvMC] flags=0x%08X\n" \ - "[XvMC] subpicture max width=%u, max height=%u\n", - i, port, surface_type_id, max_width, max_height, *chroma_format, - *mc_type, *surface_flags, *subpic_max_w, *subpic_max_h); - } - - free(surface_info); - } - } - - XvFreeAdaptorInfo(adaptor_info); - } - - if (!*found_port) { - XVMC_MSG(XVMC_ERR, "[XvMC] Could not find a suitable port.\n"); - return XvBadPort; - } - if (!found_surface) { - XVMC_MSG(XVMC_ERR, "[XvMC] Could not find a suitable surface.\n"); - return BadMatch; - } - if (width > max_width || height > max_height) { - XVMC_MSG(XVMC_ERR, "[XvMC] Requested context dimensions (w=%u,h=%u) too large (max w=%u,h=%u).\n", - width, height, max_width, max_height); - return BadValue; - } - if (flags != XVMC_DIRECT && flags != 0) { - XVMC_MSG(XVMC_ERR, "[XvMC] Invalid context flags 0x%08X.\n", flags); - return BadValue; - } - - return Success; -} - -static enum pipe_video_profile ProfileToPipe(int xvmc_profile) -{ - if (xvmc_profile & XVMC_MPEG_1) - assert(0); - if (xvmc_profile & XVMC_MPEG_2) - return PIPE_VIDEO_PROFILE_MPEG2_MAIN; - if (xvmc_profile & XVMC_H263) - assert(0); - if (xvmc_profile & XVMC_MPEG_4) - assert(0); - - assert(0); - - XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized profile 0x%08X.\n", xvmc_profile); - - return -1; -} - -static enum pipe_video_chroma_format FormatToPipe(int xvmc_format) -{ - switch (xvmc_format) { - case XVMC_CHROMA_FORMAT_420: - return PIPE_VIDEO_CHROMA_FORMAT_420; - case XVMC_CHROMA_FORMAT_422: - return PIPE_VIDEO_CHROMA_FORMAT_422; - case XVMC_CHROMA_FORMAT_444: - return PIPE_VIDEO_CHROMA_FORMAT_444; - default: - assert(0); - } - - XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized format 0x%08X.\n", xvmc_format); - - return -1; -} - -PUBLIC -Status XvMCCreateContext(Display *dpy, XvPortID port, int surface_type_id, - int width, int height, int flags, XvMCContext *context) -{ - bool found_port; - int scrn = 0; - int chroma_format = 0; - int mc_type = 0; - int surface_flags = 0; - unsigned short subpic_max_w = 0; - unsigned short subpic_max_h = 0; - Status ret; - struct vl_screen *vscreen; - struct pipe_context *pipe; - struct pipe_video_codec templat = {0}; - XvMCContextPrivate *context_priv; - vl_csc_matrix csc; - - XVMC_MSG(XVMC_TRACE, "[XvMC] Creating context %p.\n", context); - - assert(dpy); - - if (!context) - return XvMCBadContext; - - ret = Validate(dpy, port, surface_type_id, width, height, flags, - &found_port, &scrn, &chroma_format, &mc_type, &surface_flags, - &subpic_max_w, &subpic_max_h); - - /* Success and XvBadPort have the same value */ - if (ret != Success || !found_port) - return ret; - - /* XXX: Current limits */ - if (chroma_format != XVMC_CHROMA_FORMAT_420) { - XVMC_MSG(XVMC_ERR, "[XvMC] Cannot decode requested surface type. Unsupported chroma format.\n"); - return BadImplementation; - } - if ((mc_type & ~XVMC_IDCT) != (XVMC_MOCOMP | XVMC_MPEG_2)) { - XVMC_MSG(XVMC_ERR, "[XvMC] Cannot decode requested surface type. Non-MPEG2/Mocomp/iDCT acceleration unsupported.\n"); - return BadImplementation; - } - if (surface_flags & XVMC_INTRA_UNSIGNED) { - XVMC_MSG(XVMC_ERR, "[XvMC] Cannot decode requested surface type. Unsigned intra unsupported.\n"); - return BadImplementation; - } - - context_priv = CALLOC(1, sizeof(XvMCContextPrivate)); - if (!context_priv) - return BadAlloc; - - /* TODO: Reuse screen if process creates another context */ - vscreen = vl_dri3_screen_create(dpy, scrn); - if (!vscreen) - vscreen = vl_dri2_screen_create(dpy, scrn); - - if (!vscreen) { - XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL screen.\n"); - FREE(context_priv); - return BadAlloc; - } - - pipe = vscreen->pscreen->context_create(vscreen->pscreen, NULL, 0); - if (!pipe) { - XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL context.\n"); - vscreen->destroy(vscreen); - FREE(context_priv); - return BadAlloc; - } - - templat.profile = ProfileToPipe(mc_type); - templat.entrypoint = (mc_type & XVMC_IDCT) ? PIPE_VIDEO_ENTRYPOINT_IDCT : PIPE_VIDEO_ENTRYPOINT_MC; - templat.chroma_format = FormatToPipe(chroma_format); - templat.width = width; - templat.height = height; - templat.max_references = 2; - templat.expect_chunked_decode = true; - - context_priv->decoder = pipe->create_video_codec(pipe, &templat); - - if (!context_priv->decoder) { - XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL decoder.\n"); - pipe->destroy(pipe); - vscreen->destroy(vscreen); - FREE(context_priv); - return BadAlloc; - } - - if (!vl_compositor_init(&context_priv->compositor, pipe)) { - XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL compositor.\n"); - context_priv->decoder->destroy(context_priv->decoder); - pipe->destroy(pipe); - vscreen->destroy(vscreen); - FREE(context_priv); - return BadAlloc; - } - - if (!vl_compositor_init_state(&context_priv->cstate, pipe)) { - XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL compositor state.\n"); - vl_compositor_cleanup(&context_priv->compositor); - context_priv->decoder->destroy(context_priv->decoder); - pipe->destroy(pipe); - vscreen->destroy(vscreen); - FREE(context_priv); - return BadAlloc; - } - - - context_priv->color_standard = - debug_get_bool_option("G3DVL_NO_CSC", FALSE) ? - VL_CSC_COLOR_STANDARD_IDENTITY : VL_CSC_COLOR_STANDARD_BT_601; - context_priv->procamp = vl_default_procamp; - - vl_csc_get_matrix - ( - context_priv->color_standard, - &context_priv->procamp, true, &csc - ); - vl_compositor_set_csc_matrix(&context_priv->cstate, (const vl_csc_matrix *)&csc, 1.0f, 0.0f); - - context_priv->vscreen = vscreen; - context_priv->pipe = pipe; - context_priv->subpicture_max_width = subpic_max_w; - context_priv->subpicture_max_height = subpic_max_h; - - context->context_id = XAllocID(dpy); - context->surface_type_id = surface_type_id; - context->width = width; - context->height = height; - context->flags = flags; - context->port = port; - context->privData = context_priv; - - SyncHandle(); - - XVMC_MSG(XVMC_TRACE, "[XvMC] Context %p created.\n", context); - - return Success; -} - -PUBLIC -Status XvMCDestroyContext(Display *dpy, XvMCContext *context) -{ - XvMCContextPrivate *context_priv; - - XVMC_MSG(XVMC_TRACE, "[XvMC] Destroying context %p.\n", context); - - assert(dpy); - - if (!context || !context->privData) - return XvMCBadContext; - - context_priv = context->privData; - context_priv->decoder->destroy(context_priv->decoder); - vl_compositor_cleanup_state(&context_priv->cstate); - vl_compositor_cleanup(&context_priv->compositor); - context_priv->pipe->destroy(context_priv->pipe); - context_priv->vscreen->destroy(context_priv->vscreen); - FREE(context_priv); - context->privData = NULL; - - XVMC_MSG(XVMC_TRACE, "[XvMC] Context %p destroyed.\n", context); - - return Success; -} diff --git a/src/gallium/state_trackers/xvmc/meson.build b/src/gallium/state_trackers/xvmc/meson.build deleted file mode 100644 index 9022bf4d0a6..00000000000 --- a/src/gallium/state_trackers/xvmc/meson.build +++ /dev/null @@ -1,63 +0,0 @@ -# Copyright © 2017, 2019 Intel Corporation - -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: - -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. - -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -libxvmc_st = static_library( - 'xvmc_st', - files('attributes.c', 'block.c', 'context.c', 'surface.c', 'subpicture.c'), - c_args : [c_vis_args], - include_directories : [inc_include, inc_src, inc_mapi, inc_mesa, inc_gallium, inc_gallium_aux], - dependencies : [ - dep_xvmc, dep_x11_xcb, dep_xcb, dep_xcb_dri2, dep_xcb_dri3, dep_xv, - dep_libdrm, - ], -) - -# These tests will not work without a working xvmc configuration. -if with_tools.contains('xvmc') - # pkg-config was added in 1.0.12, so allow fallback - dep_xvmcw = dependency('xvmc-wrapper', required : false) - if not dep_xvmcw.found() - dep_xvmcw = cc.find_library('XvMCW') - endif - dep_real_xvmc = dependency('xvmc') - - foreach x : ['context', 'surface', 'subpicture', 'blocks', 'rendering'] - _name = 'xvmc_@0@'.format(x) - executable( - _name, - files('tests/test_@0@.c'.format(x), 'tests/testlib.c'), - dependencies : [ - dep_real_xvmc, dep_x11_xcb, dep_xcb, dep_xcb_dri2, dep_xcb_dri3, - dep_xvmcw, dep_xv, - ], - install: true, - ) - endforeach - - executable( - 'xvmc_bench', - files('tests/xvmc_bench.c', 'tests/testlib.c'), - dependencies : [ - dep_real_xvmc, dep_x11_xcb, dep_xcb, dep_xcb_dri2, dep_xcb_dri3, - dep_xvmcw, dep_xv, - ], - install: true, - ) -endif diff --git a/src/gallium/state_trackers/xvmc/subpicture.c b/src/gallium/state_trackers/xvmc/subpicture.c deleted file mode 100644 index 42eefe74e69..00000000000 --- a/src/gallium/state_trackers/xvmc/subpicture.c +++ /dev/null @@ -1,602 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 Younes Manton. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include - -#include -#include - -#include "pipe/p_screen.h" -#include "pipe/p_video_codec.h" -#include "pipe/p_state.h" - -#include "util/u_memory.h" -#include "util/u_math.h" -#include "util/format/u_format.h" -#include "util/u_sampler.h" -#include "util/u_surface.h" -#include "util/u_rect.h" -#include "vl/vl_winsys.h" - -#include "xvmc_private.h" - -#define FOURCC_RGB 0x0000003 -#define FOURCC_AI44 0x34344941 -#define FOURCC_IA44 0x34344149 - -static enum pipe_format XvIDToPipe(struct pipe_screen *screen, - int xvimage_id) -{ - enum pipe_format ret; - assert(screen); - - switch (xvimage_id) { - case FOURCC_RGB: - ret = PIPE_FORMAT_B8G8R8X8_UNORM; - break; - - case FOURCC_AI44: - ret = PIPE_FORMAT_R4A4_UNORM; - if (!screen->is_format_supported( - screen, ret, PIPE_TEXTURE_2D, 0, 0, PIPE_BIND_SAMPLER_VIEW)) - ret = PIPE_FORMAT_B4G4R4A4_UNORM; - break; - - case FOURCC_IA44: - ret = PIPE_FORMAT_A4R4_UNORM; - if (!screen->is_format_supported( - screen, ret, PIPE_TEXTURE_2D, 0, 0, PIPE_BIND_SAMPLER_VIEW)) - ret = PIPE_FORMAT_B4G4R4A4_UNORM; - break; - - default: - XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized Xv image ID 0x%08X.\n", xvimage_id); - return PIPE_FORMAT_NONE; - } - - if (!screen->is_format_supported( - screen, ret, PIPE_TEXTURE_2D, 0, 0, PIPE_BIND_SAMPLER_VIEW)) { - XVMC_MSG(XVMC_ERR, "[XvMC] Unsupported 2D format %s for Xv image ID 0x%08X.\n", util_format_name(ret), xvimage_id); - ret = PIPE_FORMAT_NONE; - } - return ret; - -} - -static unsigned NumPaletteEntries4XvID(int xvimage_id) -{ - switch (xvimage_id) { - case FOURCC_RGB: - return 0; - - case FOURCC_AI44: - case FOURCC_IA44: - return 16; - - default: - XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized Xv image ID 0x%08X.\n", xvimage_id); - return 0; - } -} - -static int PipeToComponentOrder(struct pipe_screen *screen, - enum pipe_format format, - enum pipe_format *palette_format, - char *component_order) -{ - assert(screen); - assert(component_order); - assert(palette_format); - - switch (format) { - case PIPE_FORMAT_B8G8R8X8_UNORM: - return 0; - - case PIPE_FORMAT_A4R4_UNORM: - case PIPE_FORMAT_R4A4_UNORM: - case PIPE_FORMAT_B4G4R4A4_UNORM: - *palette_format = PIPE_FORMAT_R8G8B8X8_UNORM; - component_order[0] = 'Y'; - component_order[1] = 'U'; - component_order[2] = 'V'; - component_order[3] = 'A'; - if (!screen->is_format_supported( - screen, *palette_format, PIPE_TEXTURE_1D, 0, 0, - PIPE_BIND_SAMPLER_VIEW)) { - /* One of these formats better be supported... */ - *palette_format = PIPE_FORMAT_B8G8R8X8_UNORM; - component_order[0] = 'V'; - component_order[2] = 'Y'; - } - return 4; - - default: - XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized PIPE_FORMAT 0x%08X.\n", format); - component_order[0] = 0; - component_order[1] = 0; - component_order[2] = 0; - component_order[3] = 0; - return 0; - } -} - -static Status Validate(Display *dpy, XvPortID port, int surface_type_id, int xvimage_id) -{ - XvImageFormatValues *subpictures; - int num_subpics; - int i; - - subpictures = XvMCListSubpictureTypes(dpy, port, surface_type_id, &num_subpics); - if (num_subpics < 1) { - free(subpictures); - return BadMatch; - } - if (!subpictures) - return BadAlloc; - - for (i = 0; i < num_subpics; ++i) { - if (subpictures[i].id == xvimage_id) { - XVMC_MSG(XVMC_TRACE, "[XvMC] Found requested subpicture format.\n" \ - "[XvMC] port=%u\n" \ - "[XvMC] surface id=0x%08X\n" \ - "[XvMC] image id=0x%08X\n" \ - "[XvMC] type=%08X\n" \ - "[XvMC] byte order=%08X\n" \ - "[XvMC] bits per pixel=%u\n" \ - "[XvMC] format=%08X\n" \ - "[XvMC] num planes=%d\n", - port, surface_type_id, xvimage_id, subpictures[i].type, subpictures[i].byte_order, - subpictures[i].bits_per_pixel, subpictures[i].format, subpictures[i].num_planes); - if (subpictures[i].type == XvRGB) { - XVMC_MSG(XVMC_TRACE, "[XvMC] depth=%d\n" \ - "[XvMC] red mask=0x%08X\n" \ - "[XvMC] green mask=0x%08X\n" \ - "[XvMC] blue mask=0x%08X\n", - subpictures[i].depth, subpictures[i].red_mask, - subpictures[i].green_mask, subpictures[i].blue_mask); - } - else if (subpictures[i].type == XvYUV) { - XVMC_MSG(XVMC_TRACE, "[XvMC] y sample bits=0x%08X\n" \ - "[XvMC] u sample bits=0x%08X\n" \ - "[XvMC] v sample bits=0x%08X\n" \ - "[XvMC] horz y period=%u\n" \ - "[XvMC] horz u period=%u\n" \ - "[XvMC] horz v period=%u\n" \ - "[XvMC] vert y period=%u\n" \ - "[XvMC] vert u period=%u\n" \ - "[XvMC] vert v period=%u\n", - subpictures[i].y_sample_bits, subpictures[i].u_sample_bits, subpictures[i].v_sample_bits, - subpictures[i].horz_y_period, subpictures[i].horz_u_period, subpictures[i].horz_v_period, - subpictures[i].vert_y_period, subpictures[i].vert_u_period, subpictures[i].vert_v_period); - } - break; - } - } - - free(subpictures); - - return i < num_subpics ? Success : BadMatch; -} - -static void -upload_sampler(struct pipe_context *pipe, struct pipe_sampler_view *dst, - const struct pipe_box *dst_box, const void *src, unsigned src_stride, - unsigned src_x, unsigned src_y) -{ - struct pipe_transfer *transfer; - void *map; - - map = pipe->transfer_map(pipe, dst->texture, 0, PIPE_TRANSFER_WRITE, - dst_box, &transfer); - if (!map) - return; - - util_copy_rect(map, dst->texture->format, transfer->stride, 0, 0, - dst_box->width, dst_box->height, - src, src_stride, src_x, src_y); - - pipe->transfer_unmap(pipe, transfer); -} - -static void -upload_sampler_convert(struct pipe_context *pipe, struct pipe_sampler_view *dst, - const struct pipe_box *dst_box, const XvImage *image, - unsigned src_x, unsigned src_y) -{ - struct pipe_transfer *transfer; - int i, j; - char *map, *src; - - map = pipe->transfer_map(pipe, dst->texture, 0, PIPE_TRANSFER_WRITE, - dst_box, &transfer); - if (!map) - return; - - src = image->data; - src += src_y * image->width + src_x; - if (image->id == FOURCC_AI44) { - /* The format matches what we want, we just have to insert dummy - * bytes. So just copy the same value in twice. - */ - for (i = 0; i < dst_box->height; i++, map += transfer->stride, src += image->width) - for (j = 0; j < dst_box->width; j++) - map[j * 2 + 0] = map[j * 2 + 1] = src[j]; - } else { - assert(image->id == FOURCC_IA44); - /* Same idea as above, but we have to swap the low and high nibbles. - */ - for (i = 0; i < dst_box->height; i++, map += transfer->stride, src += image->width) - for (j = 0; j < dst_box->width; j++) - map[j * 2 + 0] = map[j * 2 + 1] = (src[j] >> 4) | (src[j] << 4); - } - - pipe->transfer_unmap(pipe, transfer); -} - -PUBLIC -Status XvMCCreateSubpicture(Display *dpy, XvMCContext *context, XvMCSubpicture *subpicture, - unsigned short width, unsigned short height, int xvimage_id) -{ - XvMCContextPrivate *context_priv; - XvMCSubpicturePrivate *subpicture_priv; - struct pipe_context *pipe; - struct pipe_resource tex_templ, *tex; - struct pipe_sampler_view sampler_templ; - enum pipe_format palette_format; - Status ret; - - XVMC_MSG(XVMC_TRACE, "[XvMC] Creating subpicture %p.\n", subpicture); - - assert(dpy); - - if (!context) - return XvMCBadContext; - - context_priv = context->privData; - pipe = context_priv->pipe; - - if (!subpicture) - return XvMCBadSubpicture; - - if (width > context_priv->subpicture_max_width || - height > context_priv->subpicture_max_height) - return BadValue; - - ret = Validate(dpy, context->port, context->surface_type_id, xvimage_id); - if (ret != Success) - return ret; - - subpicture_priv = CALLOC(1, sizeof(XvMCSubpicturePrivate)); - if (!subpicture_priv) - return BadAlloc; - - memset(&tex_templ, 0, sizeof(tex_templ)); - tex_templ.target = PIPE_TEXTURE_2D; - tex_templ.format = XvIDToPipe(pipe->screen, xvimage_id); - tex_templ.last_level = 0; - if (pipe->screen->get_video_param(pipe->screen, - PIPE_VIDEO_PROFILE_UNKNOWN, - PIPE_VIDEO_ENTRYPOINT_UNKNOWN, - PIPE_VIDEO_CAP_NPOT_TEXTURES)) { - tex_templ.width0 = width; - tex_templ.height0 = height; - } - else { - tex_templ.width0 = util_next_power_of_two(width); - tex_templ.height0 = util_next_power_of_two(height); - } - tex_templ.depth0 = 1; - tex_templ.array_size = 1; - tex_templ.usage = PIPE_USAGE_DYNAMIC; - tex_templ.bind = PIPE_BIND_SAMPLER_VIEW; - tex_templ.flags = 0; - - tex = pipe->screen->resource_create(pipe->screen, &tex_templ); - - memset(&sampler_templ, 0, sizeof(sampler_templ)); - u_sampler_view_default_template(&sampler_templ, tex, tex->format); - - subpicture_priv->sampler = pipe->create_sampler_view(pipe, tex, &sampler_templ); - pipe_resource_reference(&tex, NULL); - if (!subpicture_priv->sampler) { - FREE(subpicture_priv); - return BadAlloc; - } - - subpicture_priv->context = context; - subpicture->subpicture_id = XAllocID(dpy); - subpicture->context_id = context->context_id; - subpicture->xvimage_id = xvimage_id; - subpicture->width = width; - subpicture->height = height; - subpicture->num_palette_entries = NumPaletteEntries4XvID(xvimage_id); - subpicture->entry_bytes = PipeToComponentOrder( - pipe->screen, tex_templ.format, &palette_format, - subpicture->component_order); - subpicture->privData = subpicture_priv; - - if (subpicture->num_palette_entries > 0) { - tex_templ.target = PIPE_TEXTURE_1D; - tex_templ.format = palette_format; - tex_templ.width0 = subpicture->num_palette_entries; - tex_templ.height0 = 1; - tex_templ.usage = PIPE_USAGE_DEFAULT; - - tex = pipe->screen->resource_create(pipe->screen, &tex_templ); - - memset(&sampler_templ, 0, sizeof(sampler_templ)); - u_sampler_view_default_template(&sampler_templ, tex, tex->format); - sampler_templ.swizzle_a = PIPE_SWIZZLE_1; - subpicture_priv->palette = pipe->create_sampler_view(pipe, tex, &sampler_templ); - pipe_resource_reference(&tex, NULL); - if (!subpicture_priv->sampler) { - FREE(subpicture_priv); - return BadAlloc; - } - } - - SyncHandle(); - - XVMC_MSG(XVMC_TRACE, "[XvMC] Subpicture %p created.\n", subpicture); - - return Success; -} - -PUBLIC -Status XvMCClearSubpicture(Display *dpy, XvMCSubpicture *subpicture, short x, short y, - unsigned short width, unsigned short height, unsigned int color) -{ - XvMCSubpicturePrivate *subpicture_priv; - XvMCContextPrivate *context_priv; - struct pipe_context *pipe; - struct pipe_sampler_view *dst; - struct pipe_box dst_box = {x, y, 0, width, height, 1}; - struct pipe_transfer *transfer; - union util_color uc; - void *map; - - assert(dpy); - - if (!subpicture) - return XvMCBadSubpicture; - - /* Convert color to float */ - util_format_unpack_rgba(PIPE_FORMAT_B8G8R8A8_UNORM, uc.f, &color, 1); - - subpicture_priv = subpicture->privData; - context_priv = subpicture_priv->context->privData; - pipe = context_priv->pipe; - dst = subpicture_priv->sampler; - - /* TODO: Assert clear rect is within bounds? Or clip? */ - map = pipe->transfer_map(pipe, dst->texture, 0, PIPE_TRANSFER_WRITE, - &dst_box, &transfer); - if (!map) - return XvMCBadSubpicture; - - util_fill_rect(map, dst->texture->format, transfer->stride, 0, 0, - dst_box.width, dst_box.height, &uc); - - pipe->transfer_unmap(pipe, transfer); - return Success; -} - -PUBLIC -Status XvMCCompositeSubpicture(Display *dpy, XvMCSubpicture *subpicture, XvImage *image, - short srcx, short srcy, unsigned short width, unsigned short height, - short dstx, short dsty) -{ - XvMCSubpicturePrivate *subpicture_priv; - XvMCContextPrivate *context_priv; - struct pipe_context *pipe; - struct pipe_box dst_box = {dstx, dsty, 0, width, height, 1}; - unsigned src_stride; - - XVMC_MSG(XVMC_TRACE, "[XvMC] Compositing subpicture %p.\n", subpicture); - - assert(dpy); - - if (!subpicture) - return XvMCBadSubpicture; - - assert(image); - - if (subpicture->xvimage_id != image->id) - return BadMatch; - - /* No planar support for now */ - if (image->num_planes != 1) - return BadMatch; - - subpicture_priv = subpicture->privData; - context_priv = subpicture_priv->context->privData; - pipe = context_priv->pipe; - - /* clipping should be done by upload_sampler and regardles what the documentation - says image->pitches[0] doesn't seems to be in bytes, so don't use it */ - if ((image->id == FOURCC_IA44 || image->id == FOURCC_AI44) && - subpicture_priv->sampler->texture->format == PIPE_FORMAT_B4G4R4A4_UNORM) { - upload_sampler_convert(pipe, subpicture_priv->sampler, &dst_box, image, srcx, srcy); - } else { - src_stride = image->width * util_format_get_blocksize(subpicture_priv->sampler->texture->format); - upload_sampler(pipe, subpicture_priv->sampler, &dst_box, image->data, src_stride, srcx, srcy); - } - - XVMC_MSG(XVMC_TRACE, "[XvMC] Subpicture %p composited.\n", subpicture); - - return Success; -} - -PUBLIC -Status XvMCDestroySubpicture(Display *dpy, XvMCSubpicture *subpicture) -{ - XvMCSubpicturePrivate *subpicture_priv; - - XVMC_MSG(XVMC_TRACE, "[XvMC] Destroying subpicture %p.\n", subpicture); - - assert(dpy); - - if (!subpicture) - return XvMCBadSubpicture; - - subpicture_priv = subpicture->privData; - pipe_sampler_view_reference(&subpicture_priv->sampler, NULL); - pipe_sampler_view_reference(&subpicture_priv->palette, NULL); - FREE(subpicture_priv); - - XVMC_MSG(XVMC_TRACE, "[XvMC] Subpicture %p destroyed.\n", subpicture); - - return Success; -} - -PUBLIC -Status XvMCSetSubpicturePalette(Display *dpy, XvMCSubpicture *subpicture, unsigned char *palette) -{ - XvMCSubpicturePrivate *subpicture_priv; - XvMCContextPrivate *context_priv; - struct pipe_context *pipe; - struct pipe_box dst_box = {0, 0, 0, 0, 1, 1}; - - assert(dpy); - assert(palette); - - if (!subpicture) - return XvMCBadSubpicture; - - subpicture_priv = subpicture->privData; - context_priv = subpicture_priv->context->privData; - pipe = context_priv->pipe; - - dst_box.width = subpicture->num_palette_entries; - - upload_sampler(pipe, subpicture_priv->palette, &dst_box, palette, 0, 0, 0); - - XVMC_MSG(XVMC_TRACE, "[XvMC] Palette of Subpicture %p set.\n", subpicture); - - return Success; -} - -PUBLIC -Status XvMCBlendSubpicture(Display *dpy, XvMCSurface *target_surface, XvMCSubpicture *subpicture, - short subx, short suby, unsigned short subw, unsigned short subh, - short surfx, short surfy, unsigned short surfw, unsigned short surfh) -{ - struct u_rect src_rect = {subx, subx + subw, suby, suby + subh}; - struct u_rect dst_rect = {surfx, surfx + surfw, surfy, surfy + surfh}; - - XvMCSurfacePrivate *surface_priv; - XvMCSubpicturePrivate *subpicture_priv; - - XVMC_MSG(XVMC_TRACE, "[XvMC] Associating subpicture %p with surface %p.\n", subpicture, target_surface); - - assert(dpy); - - if (!target_surface) - return XvMCBadSurface; - - if (!subpicture) - return XvMCBadSubpicture; - - if (target_surface->context_id != subpicture->context_id) - return BadMatch; - - /* TODO: Verify against subpicture independent scaling */ - - surface_priv = target_surface->privData; - subpicture_priv = subpicture->privData; - - /* TODO: Assert rects are within bounds? Or clip? */ - subpicture_priv->src_rect = src_rect; - subpicture_priv->dst_rect = dst_rect; - - surface_priv->subpicture = subpicture; - subpicture_priv->surface = target_surface; - - return Success; -} - -PUBLIC -Status XvMCBlendSubpicture2(Display *dpy, XvMCSurface *source_surface, XvMCSurface *target_surface, - XvMCSubpicture *subpicture, short subx, short suby, unsigned short subw, unsigned short subh, - short surfx, short surfy, unsigned short surfw, unsigned short surfh) -{ - assert(dpy); - - if (!source_surface || !target_surface) - return XvMCBadSurface; - - if (!subpicture) - return XvMCBadSubpicture; - - if (source_surface->context_id != subpicture->context_id) - return BadMatch; - - if (source_surface->context_id != subpicture->context_id) - return BadMatch; - - /* TODO: Assert rects are within bounds? Or clip? */ - - return Success; -} - -PUBLIC -Status XvMCSyncSubpicture(Display *dpy, XvMCSubpicture *subpicture) -{ - assert(dpy); - - if (!subpicture) - return XvMCBadSubpicture; - - return Success; -} - -PUBLIC -Status XvMCFlushSubpicture(Display *dpy, XvMCSubpicture *subpicture) -{ - assert(dpy); - - if (!subpicture) - return XvMCBadSubpicture; - - return Success; -} - -PUBLIC -Status XvMCGetSubpictureStatus(Display *dpy, XvMCSubpicture *subpicture, int *status) -{ - assert(dpy); - - if (!subpicture) - return XvMCBadSubpicture; - - assert(status); - - /* TODO */ - *status = 0; - - return Success; -} diff --git a/src/gallium/state_trackers/xvmc/surface.c b/src/gallium/state_trackers/xvmc/surface.c deleted file mode 100644 index 03ee59482c6..00000000000 --- a/src/gallium/state_trackers/xvmc/surface.c +++ /dev/null @@ -1,539 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 Younes Manton. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include -#include - -#include - -#include "pipe/p_video_codec.h" -#include "pipe/p_video_state.h" -#include "pipe/p_state.h" - -#include "util/macros.h" -#include "util/u_inlines.h" -#include "util/u_memory.h" -#include "util/u_math.h" -#include "vl/vl_winsys.h" - -#include "xvmc_private.h" - -static void -MacroBlocksToPipe(XvMCContextPrivate *context, - XvMCSurfacePrivate *surface, - unsigned int xvmc_picture_structure, - const XvMCMacroBlock *xvmc_mb, - const XvMCBlockArray *xvmc_blocks, - struct pipe_mpeg12_macroblock *mb, - unsigned int num_macroblocks) -{ - unsigned int i, j, k; - - assert(xvmc_mb); - assert(xvmc_blocks); - assert(num_macroblocks); - - for (; num_macroblocks > 0; --num_macroblocks) { - mb->base.codec = PIPE_VIDEO_FORMAT_MPEG12; - mb->x = xvmc_mb->x; - mb->y = xvmc_mb->y; - mb->macroblock_type = xvmc_mb->macroblock_type; - - switch (xvmc_picture_structure) { - case XVMC_FRAME_PICTURE: - mb->macroblock_modes.bits.frame_motion_type = xvmc_mb->motion_type; - mb->macroblock_modes.bits.field_motion_type = 0; - break; - - case XVMC_TOP_FIELD: - case XVMC_BOTTOM_FIELD: - mb->macroblock_modes.bits.frame_motion_type = 0; - mb->macroblock_modes.bits.field_motion_type = xvmc_mb->motion_type; - break; - - default: - assert(0); - } - - mb->macroblock_modes.bits.dct_type = xvmc_mb->dct_type; - mb->motion_vertical_field_select = xvmc_mb->motion_vertical_field_select; - - for (i = 0; i < 2; ++i) - for (j = 0; j < 2; ++j) - for (k = 0; k < 2; ++k) - mb->PMV[i][j][k] = xvmc_mb->PMV[i][j][k]; - - mb->coded_block_pattern = xvmc_mb->coded_block_pattern; - mb->blocks = xvmc_blocks->blocks + xvmc_mb->index * BLOCK_SIZE_SAMPLES; - mb->num_skipped_macroblocks = 0; - - ++xvmc_mb; - ++mb; - } -} - -static void -GetPictureDescription(XvMCSurfacePrivate *surface, struct pipe_mpeg12_picture_desc *desc) -{ - unsigned i, num_refs = 0; - - assert(surface && desc); - - memset(desc, 0, sizeof(*desc)); - desc->base.profile = PIPE_VIDEO_PROFILE_MPEG1; - desc->picture_structure = surface->picture_structure; - for (i = 0; i < 2; ++i) { - if (surface->ref[i]) { - XvMCSurfacePrivate *ref = surface->ref[i]->privData; - - if (ref) - desc->ref[num_refs++] = ref->video_buffer; - } - } -} - -static void -RecursiveEndFrame(XvMCSurfacePrivate *surface) -{ - XvMCContextPrivate *context_priv; - unsigned i; - - assert(surface); - - context_priv = surface->context->privData; - - for ( i = 0; i < 2; ++i ) { - if (surface->ref[i]) { - XvMCSurface *ref = surface->ref[i]; - - assert(ref); - - surface->ref[i] = NULL; - RecursiveEndFrame(ref->privData); - surface->ref[i] = ref; - } - } - - if (surface->picture_structure) { - struct pipe_mpeg12_picture_desc desc; - GetPictureDescription(surface, &desc); - surface->picture_structure = 0; - - for (i = 0; i < 2; ++i) - surface->ref[i] = NULL; - - context_priv->decoder->end_frame(context_priv->decoder, surface->video_buffer, &desc.base); - } -} - -PUBLIC -Status XvMCCreateSurface(Display *dpy, XvMCContext *context, XvMCSurface *surface) -{ - XvMCContextPrivate *context_priv; - struct pipe_context *pipe; - XvMCSurfacePrivate *surface_priv; - struct pipe_video_buffer tmpl; - - XVMC_MSG(XVMC_TRACE, "[XvMC] Creating surface %p.\n", surface); - - assert(dpy); - - if (!context) - return XvMCBadContext; - if (!surface) - return XvMCBadSurface; - - context_priv = context->privData; - pipe = context_priv->pipe; - - surface_priv = CALLOC(1, sizeof(XvMCSurfacePrivate)); - if (!surface_priv) - return BadAlloc; - - memset(&tmpl, 0, sizeof(tmpl)); - tmpl.buffer_format = pipe->screen->get_video_param - ( - pipe->screen, - context_priv->decoder->profile, - context_priv->decoder->entrypoint, - PIPE_VIDEO_CAP_PREFERED_FORMAT - ); - assert(pipe_format_to_chroma_format(tmpl.buffer_format) == context_priv->decoder->chroma_format); - tmpl.width = context_priv->decoder->width; - tmpl.height = context_priv->decoder->height; - tmpl.interlaced = pipe->screen->get_video_param - ( - pipe->screen, - context_priv->decoder->profile, - context_priv->decoder->entrypoint, - PIPE_VIDEO_CAP_PREFERS_INTERLACED - ); - - surface_priv->video_buffer = pipe->create_video_buffer(pipe, &tmpl); - if (!surface_priv->video_buffer) { - FREE(surface_priv); - return BadAlloc; - } - surface_priv->context = context; - - surface->surface_id = XAllocID(dpy); - surface->context_id = context->context_id; - surface->surface_type_id = context->surface_type_id; - surface->width = context->width; - surface->height = context->height; - surface->privData = surface_priv; - - SyncHandle(); - - XVMC_MSG(XVMC_TRACE, "[XvMC] Surface %p created.\n", surface); - - return Success; -} - -PUBLIC -Status XvMCRenderSurface(Display *dpy, XvMCContext *context, unsigned int picture_structure, - XvMCSurface *target_surface, XvMCSurface *past_surface, XvMCSurface *future_surface, - unsigned int flags, unsigned int num_macroblocks, unsigned int first_macroblock, - XvMCMacroBlockArray *macroblocks, XvMCBlockArray *blocks -) -{ - struct pipe_mpeg12_macroblock mb[num_macroblocks]; - struct pipe_video_codec *decoder; - struct pipe_mpeg12_picture_desc desc; - - XvMCContextPrivate *context_priv; - XvMCSurfacePrivate *target_surface_priv; - ASSERTED XvMCSurfacePrivate *past_surface_priv; - ASSERTED XvMCSurfacePrivate *future_surface_priv; - XvMCMacroBlock *xvmc_mb; - - XVMC_MSG(XVMC_TRACE, "[XvMC] Rendering to surface %p, with past %p and future %p\n", - target_surface, past_surface, future_surface); - - assert(dpy); - - if (!context || !context->privData) - return XvMCBadContext; - if (!target_surface || !target_surface->privData) - return XvMCBadSurface; - - if (picture_structure != XVMC_TOP_FIELD && - picture_structure != XVMC_BOTTOM_FIELD && - picture_structure != XVMC_FRAME_PICTURE) - return BadValue; - /* Bkwd pred equivalent to fwd (past && !future) */ - if (future_surface && !past_surface) - return BadMatch; - - assert(context->context_id == target_surface->context_id); - assert(!past_surface || context->context_id == past_surface->context_id); - assert(!future_surface || context->context_id == future_surface->context_id); - - assert(macroblocks); - assert(blocks); - - assert(macroblocks->context_id == context->context_id); - assert(blocks->context_id == context->context_id); - - assert(flags == 0 || flags == XVMC_SECOND_FIELD); - - context_priv = context->privData; - decoder = context_priv->decoder; - - target_surface_priv = target_surface->privData; - past_surface_priv = past_surface ? past_surface->privData : NULL; - future_surface_priv = future_surface ? future_surface->privData : NULL; - - assert(target_surface_priv->context == context); - assert(!past_surface || past_surface_priv->context == context); - assert(!future_surface || future_surface_priv->context == context); - - // call end frame on all referenced frames - if (past_surface) - RecursiveEndFrame(past_surface->privData); - - if (future_surface) - RecursiveEndFrame(future_surface->privData); - - xvmc_mb = macroblocks->macro_blocks + first_macroblock; - - /* If the surface we're rendering hasn't changed the ref frames shouldn't change. */ - if (target_surface_priv->picture_structure > 0 && ( - target_surface_priv->picture_structure != picture_structure || - target_surface_priv->ref[0] != past_surface || - target_surface_priv->ref[1] != future_surface || - (xvmc_mb->x == 0 && xvmc_mb->y == 0))) { - - // If they change anyway we must assume that the current frame is ended - RecursiveEndFrame(target_surface_priv); - } - - target_surface_priv->ref[0] = past_surface; - target_surface_priv->ref[1] = future_surface; - - if (target_surface_priv->picture_structure) - GetPictureDescription(target_surface_priv, &desc); - else { - target_surface_priv->picture_structure = picture_structure; - GetPictureDescription(target_surface_priv, &desc); - decoder->begin_frame(decoder, target_surface_priv->video_buffer, &desc.base); - } - - MacroBlocksToPipe(context_priv, target_surface_priv, picture_structure, - xvmc_mb, blocks, mb, num_macroblocks); - - context_priv->decoder->decode_macroblock(context_priv->decoder, - target_surface_priv->video_buffer, - &desc.base, - &mb[0].base, num_macroblocks); - - XVMC_MSG(XVMC_TRACE, "[XvMC] Submitted surface %p for rendering.\n", target_surface); - - return Success; -} - -PUBLIC -Status XvMCFlushSurface(Display *dpy, XvMCSurface *surface) -{ - assert(dpy); - - if (!surface) - return XvMCBadSurface; - - // don't call flush here, because this is usually - // called once for every slice instead of every frame - - XVMC_MSG(XVMC_TRACE, "[XvMC] Flushing surface %p\n", surface); - - return Success; -} - -PUBLIC -Status XvMCSyncSurface(Display *dpy, XvMCSurface *surface) -{ - assert(dpy); - - if (!surface) - return XvMCBadSurface; - - XVMC_MSG(XVMC_TRACE, "[XvMC] Syncing surface %p\n", surface); - - return Success; -} - -PUBLIC -Status XvMCPutSurface(Display *dpy, XvMCSurface *surface, Drawable drawable, - short srcx, short srcy, unsigned short srcw, unsigned short srch, - short destx, short desty, unsigned short destw, unsigned short desth, - int flags) -{ - static int dump_window = -1; - - struct pipe_context *pipe; - struct vl_compositor *compositor; - struct vl_compositor_state *cstate; - struct vl_screen *vscreen; - - XvMCSurfacePrivate *surface_priv; - XvMCContextPrivate *context_priv; - XvMCSubpicturePrivate *subpicture_priv; - XvMCContext *context; - struct u_rect src_rect = {srcx, srcx + srcw, srcy, srcy + srch}; - struct u_rect dst_rect = {destx, destx + destw, desty, desty + desth}; - - struct pipe_resource *tex; - struct pipe_surface surf_templ, *surf; - struct u_rect *dirty_area; - - XVMC_MSG(XVMC_TRACE, "[XvMC] Displaying surface %p.\n", surface); - - assert(dpy); - - if (!surface || !surface->privData) - return XvMCBadSurface; - - surface_priv = surface->privData; - context = surface_priv->context; - context_priv = context->privData; - - assert(flags == XVMC_TOP_FIELD || flags == XVMC_BOTTOM_FIELD || flags == XVMC_FRAME_PICTURE); - assert(srcx + srcw - 1 < surface->width); - assert(srcy + srch - 1 < surface->height); - - subpicture_priv = surface_priv->subpicture ? surface_priv->subpicture->privData : NULL; - pipe = context_priv->pipe; - compositor = &context_priv->compositor; - cstate = &context_priv->cstate; - vscreen = context_priv->vscreen; - - tex = vscreen->texture_from_drawable(vscreen, (void *)drawable); - dirty_area = vscreen->get_dirty_area(vscreen); - - memset(&surf_templ, 0, sizeof(surf_templ)); - surf_templ.format = tex->format; - surf = pipe->create_surface(pipe, tex, &surf_templ); - - if (!surf) - return BadDrawable; - - /* - * Some apps (mplayer) hit these asserts because they call - * this function after the window has been resized by the WM - * but before they've handled the corresponding XEvent and - * know about the new dimensions. The output should be clipped - * until the app updates destw and desth. - */ - /* - assert(destx + destw - 1 < drawable_surface->width); - assert(desty + desth - 1 < drawable_surface->height); - */ - - RecursiveEndFrame(surface_priv); - - context_priv->decoder->flush(context_priv->decoder); - - vl_compositor_clear_layers(cstate); - vl_compositor_set_buffer_layer(cstate, compositor, 0, surface_priv->video_buffer, - &src_rect, NULL, VL_COMPOSITOR_WEAVE); - - if (subpicture_priv) { - XVMC_MSG(XVMC_TRACE, "[XvMC] Surface %p has subpicture %p.\n", surface, surface_priv->subpicture); - - assert(subpicture_priv->surface == surface); - - if (subpicture_priv->palette) - vl_compositor_set_palette_layer(cstate, compositor, 1, subpicture_priv->sampler, subpicture_priv->palette, - &subpicture_priv->src_rect, &subpicture_priv->dst_rect, true); - else - vl_compositor_set_rgba_layer(cstate, compositor, 1, subpicture_priv->sampler, - &subpicture_priv->src_rect, &subpicture_priv->dst_rect, NULL); - - surface_priv->subpicture = NULL; - subpicture_priv->surface = NULL; - } - - // Workaround for r600g, there seems to be a bug in the fence refcounting code - pipe->screen->fence_reference(pipe->screen, &surface_priv->fence, NULL); - - vl_compositor_set_layer_dst_area(cstate, 0, &dst_rect); - vl_compositor_set_layer_dst_area(cstate, 1, &dst_rect); - vl_compositor_render(cstate, compositor, surf, dirty_area, true); - - pipe->flush(pipe, &surface_priv->fence, 0); - - XVMC_MSG(XVMC_TRACE, "[XvMC] Submitted surface %p for display. Pushing to front buffer.\n", surface); - - pipe->screen->flush_frontbuffer(pipe->screen, tex, 0, 0, - vscreen->get_private(vscreen), NULL); - - if(dump_window == -1) { - dump_window = debug_get_num_option("XVMC_DUMP", 0); - } - - if(dump_window) { - static unsigned int framenum = 0; - char cmd[256]; - - sprintf(cmd, "xwd -id %d -out xvmc_frame_%08d.xwd", (int)drawable, ++framenum); - if (system(cmd) != 0) - XVMC_MSG(XVMC_ERR, "[XvMC] Dumping surface %p failed.\n", surface); - } - - XVMC_MSG(XVMC_TRACE, "[XvMC] Pushed surface %p to front buffer.\n", surface); - - return Success; -} - -PUBLIC -Status XvMCGetSurfaceStatus(Display *dpy, XvMCSurface *surface, int *status) -{ - struct pipe_context *pipe; - XvMCSurfacePrivate *surface_priv; - XvMCContextPrivate *context_priv; - - assert(dpy); - - if (!surface) - return XvMCBadSurface; - - assert(status); - - surface_priv = surface->privData; - context_priv = surface_priv->context->privData; - pipe = context_priv->pipe; - - *status = 0; - - if (surface_priv->fence) - if (!pipe->screen->fence_finish(pipe->screen, NULL, surface_priv->fence, 0)) - *status |= XVMC_RENDERING; - - return Success; -} - -PUBLIC -Status XvMCDestroySurface(Display *dpy, XvMCSurface *surface) -{ - XvMCSurfacePrivate *surface_priv; - XvMCContextPrivate *context_priv; - - XVMC_MSG(XVMC_TRACE, "[XvMC] Destroying surface %p.\n", surface); - - assert(dpy); - - if (!surface || !surface->privData) - return XvMCBadSurface; - - surface_priv = surface->privData; - context_priv = surface_priv->context->privData; - - if (surface_priv->picture_structure) { - struct pipe_mpeg12_picture_desc desc; - GetPictureDescription(surface_priv, &desc); - context_priv->decoder->end_frame(context_priv->decoder, surface_priv->video_buffer, &desc.base); - } - surface_priv->video_buffer->destroy(surface_priv->video_buffer); - FREE(surface_priv); - surface->privData = NULL; - - XVMC_MSG(XVMC_TRACE, "[XvMC] Surface %p destroyed.\n", surface); - - return Success; -} - -PUBLIC -Status XvMCHideSurface(Display *dpy, XvMCSurface *surface) -{ - assert(dpy); - - if (!surface || !surface->privData) - return XvMCBadSurface; - - /* No op, only for overlaid rendering */ - - return Success; -} diff --git a/src/gallium/state_trackers/xvmc/tests/test_blocks.c b/src/gallium/state_trackers/xvmc/tests/test_blocks.c deleted file mode 100644 index 53c29bc5ae1..00000000000 --- a/src/gallium/state_trackers/xvmc/tests/test_blocks.c +++ /dev/null @@ -1,115 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 Younes Manton. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/* Force assertions, even on release builds. */ -#undef NDEBUG -#include -#include -#include -#include "testlib.h" - -int main(int argc, char **argv) -{ - const unsigned int width = 16, height = 16; - const unsigned int min_required_blocks = 1, min_required_macroblocks = 1; - const unsigned int mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2}; - - Display *display; - XvPortID port_num; - int surface_type_id; - unsigned int is_overlay, intra_unsigned; - int colorkey; - XvMCContext context; - XvMCSurface surface; - XvMCBlockArray blocks = {0}; - XvMCMacroBlockArray macroblocks = {0}; - - display = XOpenDisplay(NULL); - - if (!GetPort - ( - display, - width, - height, - XVMC_CHROMA_FORMAT_420, - mc_types, - 2, - &port_num, - &surface_type_id, - &is_overlay, - &intra_unsigned - )) - { - XCloseDisplay(display); - fprintf(stderr, "Error, unable to find a good port.\n"); - exit(1); - } - - if (is_overlay) - { - Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0); - XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey); - } - - assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, &context) == Success); - assert(XvMCCreateSurface(display, &context, &surface) == Success); - - /* Test NULL context */ - assert(XvMCCreateBlocks(display, NULL, 1, &blocks) == XvMCBadContext); - /* Test 0 blocks */ - assert(XvMCCreateBlocks(display, &context, 0, &blocks) == BadValue); - /* Test valid params */ - assert(XvMCCreateBlocks(display, &context, min_required_blocks, &blocks) == Success); - /* Test context id assigned and correct */ - assert(blocks.context_id == context.context_id); - /* Test number of blocks assigned and correct */ - assert(blocks.num_blocks == min_required_blocks); - /* Test block pointer valid */ - assert(blocks.blocks != NULL); - /* Test NULL context */ - assert(XvMCCreateMacroBlocks(display, NULL, 1, ¯oblocks) == XvMCBadContext); - /* Test 0 macroblocks */ - assert(XvMCCreateMacroBlocks(display, &context, 0, ¯oblocks) == BadValue); - /* Test valid params */ - assert(XvMCCreateMacroBlocks(display, &context, min_required_macroblocks, ¯oblocks) == Success); - /* Test context id assigned and correct */ - assert(macroblocks.context_id == context.context_id); - /* Test macroblock pointer valid */ - assert(macroblocks.macro_blocks != NULL); - /* Test valid params */ - assert(XvMCDestroyMacroBlocks(display, ¯oblocks) == Success); - /* Test valid params */ - assert(XvMCDestroyBlocks(display, &blocks) == Success); - - assert(XvMCDestroySurface(display, &surface) == Success); - assert(XvMCDestroyContext(display, &context) == Success); - - XvUngrabPort(display, port_num, CurrentTime); - XCloseDisplay(display); - - return 0; -} diff --git a/src/gallium/state_trackers/xvmc/tests/test_context.c b/src/gallium/state_trackers/xvmc/tests/test_context.c deleted file mode 100644 index 81d26fcffd5..00000000000 --- a/src/gallium/state_trackers/xvmc/tests/test_context.c +++ /dev/null @@ -1,123 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 Younes Manton. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/* Force assertions, even on release builds. */ -#undef NDEBUG -#include -#include -#include -#include "testlib.h" - -int main(int argc, char **argv) -{ - const unsigned int width = 16, height = 16; - const unsigned int mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2}; - - Display *display; - XvPortID port_num; - int surface_type_id; - unsigned int is_overlay, intra_unsigned; - int colorkey; - XvMCContext context = {0}; - - display = XOpenDisplay(NULL); - - if (!GetPort - ( - display, - width, - height, - XVMC_CHROMA_FORMAT_420, - mc_types, - 2, - &port_num, - &surface_type_id, - &is_overlay, - &intra_unsigned - )) - { - XCloseDisplay(display); - fprintf(stderr, "Error, unable to find a good port.\n"); - exit(1); - } - - if (is_overlay) - { - Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0); - XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey); - } - - /* Test NULL context */ - /* XXX: XvMCBadContext not a valid return for XvMCCreateContext in the XvMC API, but openChrome driver returns it */ - assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, NULL) == XvMCBadContext); - /* Test invalid port */ - /* XXX: Success and XvBadPort have the same value, if this call actually gets passed the validation step as of now we'll crash later */ - assert(XvMCCreateContext(display, -1, surface_type_id, width, height, XVMC_DIRECT, &context) == XvBadPort); - /* Test invalid surface */ - assert(XvMCCreateContext(display, port_num, -1, width, height, XVMC_DIRECT, &context) == BadMatch); - /* Test invalid flags */ - assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, -1, &context) == BadValue); - /* Test huge width */ - assert(XvMCCreateContext(display, port_num, surface_type_id, 16384, height, XVMC_DIRECT, &context) == BadValue); - /* Test huge height */ - assert(XvMCCreateContext(display, port_num, surface_type_id, width, 16384, XVMC_DIRECT, &context) == BadValue); - /* Test huge width & height */ - assert(XvMCCreateContext(display, port_num, surface_type_id, 16384, 16384, XVMC_DIRECT, &context) == BadValue); - /* Test valid params */ - assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, &context) == Success); - /* Test context id assigned */ - assert(context.context_id != 0); - /* Test surface type id assigned and correct */ - assert(context.surface_type_id == surface_type_id); - /* Test width & height assigned and correct */ - assert(context.width == width && context.height == height); - /* Test port assigned and correct */ - assert(context.port == port_num); - /* Test flags assigned and correct */ - assert(context.flags == XVMC_DIRECT); - /* Test NULL context */ - assert(XvMCDestroyContext(display, NULL) == XvMCBadContext); - /* Test valid params */ - assert(XvMCDestroyContext(display, &context) == Success); - /* Test awkward but valid width */ - assert(XvMCCreateContext(display, port_num, surface_type_id, width + 1, height, XVMC_DIRECT, &context) == Success); - assert(context.width >= width + 1); - assert(XvMCDestroyContext(display, &context) == Success); - /* Test awkward but valid height */ - assert(XvMCCreateContext(display, port_num, surface_type_id, width, height + 1, XVMC_DIRECT, &context) == Success); - assert(context.height >= height + 1); - assert(XvMCDestroyContext(display, &context) == Success); - /* Test awkward but valid width & height */ - assert(XvMCCreateContext(display, port_num, surface_type_id, width + 1, height + 1, XVMC_DIRECT, &context) == Success); - assert(context.width >= width + 1 && context.height >= height + 1); - assert(XvMCDestroyContext(display, &context) == Success); - - XvUngrabPort(display, port_num, CurrentTime); - XCloseDisplay(display); - - return 0; -} diff --git a/src/gallium/state_trackers/xvmc/tests/test_rendering.c b/src/gallium/state_trackers/xvmc/tests/test_rendering.c deleted file mode 100644 index c5494ecc8c2..00000000000 --- a/src/gallium/state_trackers/xvmc/tests/test_rendering.c +++ /dev/null @@ -1,330 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 Younes Manton. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/* Force assertions, even on release builds. */ -#undef NDEBUG -#include -#include -#include -#include -#include "testlib.h" - -#define BLOCK_WIDTH 8 -#define BLOCK_HEIGHT 8 -#define BLOCK_SIZE (BLOCK_WIDTH * BLOCK_HEIGHT) -#define MACROBLOCK_WIDTH 16 -#define MACROBLOCK_HEIGHT 16 -#define MACROBLOCK_WIDTH_IN_BLOCKS (MACROBLOCK_WIDTH / BLOCK_WIDTH) -#define MACROBLOCK_HEIGHT_IN_BLOCKS (MACROBLOCK_HEIGHT / BLOCK_HEIGHT) -#define BLOCKS_PER_MACROBLOCK 6 - -#define INPUT_WIDTH 64 -#define INPUT_HEIGHT 64 -#define INPUT_WIDTH_IN_MACROBLOCKS (INPUT_WIDTH / MACROBLOCK_WIDTH) -#define INPUT_HEIGHT_IN_MACROBLOCKS (INPUT_HEIGHT / MACROBLOCK_HEIGHT) -#define NUM_MACROBLOCKS (INPUT_WIDTH_IN_MACROBLOCKS * INPUT_HEIGHT_IN_MACROBLOCKS) - -#define DEFAULT_OUTPUT_WIDTH INPUT_WIDTH -#define DEFAULT_OUTPUT_HEIGHT INPUT_HEIGHT -#define DEFAULT_ACCEPTABLE_ERR 0.01 - -static void ParseArgs(int argc, char **argv, unsigned int *output_width, unsigned int *output_height, double *acceptable_error, int *prompt) -{ - int fail = 0; - int i; - - *output_width = DEFAULT_OUTPUT_WIDTH; - *output_height = DEFAULT_OUTPUT_HEIGHT; - *acceptable_error = DEFAULT_ACCEPTABLE_ERR; - *prompt = 0; - - for (i = 1; i < argc && !fail; ++i) - { - if (!strcmp(argv[i], "-w")) - { - if (sscanf(argv[++i], "%u", output_width) != 1) - fail = 1; - } - else if (!strcmp(argv[i], "-h")) - { - if (sscanf(argv[++i], "%u", output_height) != 1) - fail = 1; - } - else if (!strcmp(argv[i], "-e")) - { - if (sscanf(argv[++i], "%lf", acceptable_error) != 1) - fail = 1; - } - else if (!strcmp(argv[i], "-p")) - *prompt = 1; - else - fail = 1; - } - - if (fail) - { - fprintf( - stderr, - "Bad argument.\n" - "\n" - "Usage: %s [options]\n" - "\t-w \tOutput width\n" - "\t-h \tOutput height\n" - "\t-e \tAcceptable margin of error per pixel, from 0 to 1\n" - "\t-p\tPrompt for quit\n", - argv[0] - ); - exit(1); - } -} - -static void Gradient(short *block, unsigned int start, unsigned int stop, int horizontal, unsigned int intra_unsigned) -{ - unsigned int x, y; - unsigned int range = stop - start; - - if (horizontal) - { - for (y = 0; y < BLOCK_HEIGHT; ++y) - for (x = 0; x < BLOCK_WIDTH; ++x) { - *block = (short)(start + range * (x / (float)(BLOCK_WIDTH - 1))); - if (intra_unsigned) - *block += 1 << 10; - block++; - } - } - else - { - for (y = 0; y < BLOCK_HEIGHT; ++y) - for (x = 0; x < BLOCK_WIDTH; ++x) { - *block = (short)(start + range * (y / (float)(BLOCK_WIDTH - 1))); - if (intra_unsigned) - *block += 1 << 10; - block++; - } - } -} - -int main(int argc, char **argv) -{ - unsigned int output_width; - unsigned int output_height; - double acceptable_error; - int prompt; - Display *display; - Window root, window; - const unsigned int mc_types[] = {XVMC_MOCOMP | XVMC_MPEG_2}; - XvPortID port_num; - int surface_type_id; - unsigned int is_overlay, intra_unsigned; - int colorkey; - XvMCContext context; - XvMCSurface surface; - XvMCBlockArray block_array; - XvMCMacroBlockArray mb_array; - int mbx, mby, bx, by; - XvMCMacroBlock *mb; - short *blocks; - int quit = 0; - - ParseArgs(argc, argv, &output_width, &output_height, &acceptable_error, &prompt); - - display = XOpenDisplay(NULL); - - if (!GetPort - ( - display, - INPUT_WIDTH, - INPUT_HEIGHT, - XVMC_CHROMA_FORMAT_420, - mc_types, - sizeof(mc_types)/sizeof(*mc_types), - &port_num, - &surface_type_id, - &is_overlay, - &intra_unsigned - )) - { - XCloseDisplay(display); - fprintf(stderr, "Error, unable to find a good port.\n"); - exit(1); - } - - if (is_overlay) - { - Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0); - XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey); - } - - root = XDefaultRootWindow(display); - window = XCreateSimpleWindow(display, root, 0, 0, output_width, output_height, 0, 0, colorkey); - - assert(XvMCCreateContext(display, port_num, surface_type_id, INPUT_WIDTH, INPUT_HEIGHT, XVMC_DIRECT, &context) == Success); - assert(XvMCCreateSurface(display, &context, &surface) == Success); - assert(XvMCCreateBlocks(display, &context, NUM_MACROBLOCKS * BLOCKS_PER_MACROBLOCK, &block_array) == Success); - assert(XvMCCreateMacroBlocks(display, &context, NUM_MACROBLOCKS, &mb_array) == Success); - - mb = mb_array.macro_blocks; - blocks = block_array.blocks; - - for (mby = 0; mby < INPUT_HEIGHT_IN_MACROBLOCKS; ++mby) - for (mbx = 0; mbx < INPUT_WIDTH_IN_MACROBLOCKS; ++mbx) - { - mb->x = mbx; - mb->y = mby; - mb->macroblock_type = XVMC_MB_TYPE_INTRA; - /*mb->motion_type = ;*/ - /*mb->motion_vertical_field_select = ;*/ - mb->dct_type = XVMC_DCT_TYPE_FRAME; - /*mb->PMV[0][0][0] = ; - mb->PMV[0][0][1] = ; - mb->PMV[0][1][0] = ; - mb->PMV[0][1][1] = ; - mb->PMV[1][0][0] = ; - mb->PMV[1][0][1] = ; - mb->PMV[1][1][0] = ; - mb->PMV[1][1][1] = ;*/ - mb->index = (mby * INPUT_WIDTH_IN_MACROBLOCKS + mbx) * BLOCKS_PER_MACROBLOCK; - mb->coded_block_pattern = 0x3F; - - mb++; - - for (by = 0; by < MACROBLOCK_HEIGHT_IN_BLOCKS; ++by) - for (bx = 0; bx < MACROBLOCK_WIDTH_IN_BLOCKS; ++bx) - { - const int start = 16, stop = 235, range = stop - start; - - Gradient - ( - blocks, - (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))), - (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))), - 1, - intra_unsigned - ); - - blocks += BLOCK_SIZE; - } - - for (by = 0; by < MACROBLOCK_HEIGHT_IN_BLOCKS / 2; ++by) - for (bx = 0; bx < MACROBLOCK_WIDTH_IN_BLOCKS / 2; ++bx) - { - const int start = 16, stop = 240, range = stop - start; - - Gradient - ( - blocks, - (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))), - (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))), - 1, - intra_unsigned - ); - - blocks += BLOCK_SIZE; - - Gradient - ( - blocks, - (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))), - (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))), - 1, - intra_unsigned - ); - - blocks += BLOCK_SIZE; - } - } - - XSelectInput(display, window, ExposureMask | KeyPressMask); - XMapWindow(display, window); - XSync(display, 0); - - /* Test NULL context */ - assert(XvMCRenderSurface(display, NULL, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == XvMCBadContext); - /* Test NULL surface */ - assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, NULL, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == XvMCBadSurface); - /* Test bad picture structure */ - assert(XvMCRenderSurface(display, &context, 0, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == BadValue); - /* Test valid params */ - assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == Success); - - /* Test NULL surface */ - assert(XvMCPutSurface(display, NULL, window, 0, 0, INPUT_WIDTH, INPUT_HEIGHT, 0, 0, output_width, output_height, XVMC_FRAME_PICTURE) == XvMCBadSurface); - /* Test bad window */ - /* XXX: X halts with a bad drawable for some reason, doesn't return BadDrawable as expected */ - /*assert(XvMCPutSurface(display, &surface, 0, 0, 0, width, height, 0, 0, width, height, XVMC_FRAME_PICTURE) == BadDrawable);*/ - - if (prompt) - { - puts("Press any button to quit..."); - - while (!quit) - { - if (XPending(display) > 0) - { - XEvent event; - - XNextEvent(display, &event); - - switch (event.type) - { - case Expose: - { - /* Test valid params */ - assert - ( - XvMCPutSurface - ( - display, &surface, window, - 0, 0, INPUT_WIDTH, INPUT_HEIGHT, - 0, 0, output_width, output_height, - XVMC_FRAME_PICTURE - ) == Success - ); - break; - } - case KeyPress: - { - quit = 1; - break; - } - } - } - } - } - - assert(XvMCDestroyBlocks(display, &block_array) == Success); - assert(XvMCDestroyMacroBlocks(display, &mb_array) == Success); - assert(XvMCDestroySurface(display, &surface) == Success); - assert(XvMCDestroyContext(display, &context) == Success); - - XvUngrabPort(display, port_num, CurrentTime); - XDestroyWindow(display, window); - XCloseDisplay(display); - - return 0; -} diff --git a/src/gallium/state_trackers/xvmc/tests/test_subpicture.c b/src/gallium/state_trackers/xvmc/tests/test_subpicture.c deleted file mode 100644 index 006972fa8ee..00000000000 --- a/src/gallium/state_trackers/xvmc/tests/test_subpicture.c +++ /dev/null @@ -1,189 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 Younes Manton. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/* Force assertions, even on release builds. */ -#undef NDEBUG -#include -#include -#include -#include "testlib.h" - -static void PrintGUID(const char *guid) -{ - int i; - printf("\tguid: "); - for (i = 0; i < 4; ++i) - printf("%c,", guid[i] == 0 ? '0' : guid[i]); - for (; i < 15; ++i) - printf("%x,", (unsigned char)guid[i]); - printf("%x\n", (unsigned int)guid[15]); -} - -static void PrintComponentOrder(const char *co) -{ - int i; - printf("\tcomponent_order:\n\t "); - for (i = 0; i < 4; ++i) - printf("%c,", co[i] == 0 ? '0' : co[i]); - for (; i < 31; ++i) - printf("%x,", (unsigned int)co[i]); - printf("%x\n", (unsigned int)co[31]); -} - -int main(int argc, char **argv) -{ - const unsigned int width = 16, height = 16; - const unsigned int mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2}; - const unsigned int subpic_width = 16, subpic_height = 16; - - Display *display; - XvPortID port_num; - int surface_type_id; - unsigned int is_overlay, intra_unsigned; - int colorkey; - XvMCContext context; - XvImageFormatValues *subpics; - int num_subpics; - XvMCSubpicture subpicture = {0}; - int i; - - display = XOpenDisplay(NULL); - - if (!GetPort - ( - display, - width, - height, - XVMC_CHROMA_FORMAT_420, - mc_types, - 2, - &port_num, - &surface_type_id, - &is_overlay, - &intra_unsigned - )) - { - XCloseDisplay(display); - fprintf(stderr, "Error, unable to find a good port.\n"); - exit(1); - } - - if (is_overlay) - { - Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0); - XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey); - } - - assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, &context) == Success); - - subpics = XvMCListSubpictureTypes(display, port_num, surface_type_id, &num_subpics); - assert((subpics && num_subpics) > 0 || (!subpics && num_subpics == 0)); - - for (i = 0; i < num_subpics; ++i) - { - printf("Subpicture %d:\n", i); - printf("\tid: 0x%08x\n", subpics[i].id); - printf("\ttype: %s\n", subpics[i].type == XvRGB ? "XvRGB" : (subpics[i].type == XvYUV ? "XvYUV" : "Unknown")); - printf("\tbyte_order: %s\n", subpics[i].byte_order == LSBFirst ? "LSB First" : (subpics[i].byte_order == MSBFirst ? "MSB First" : "Unknown")); - PrintGUID(subpics[i].guid); - printf("\tbpp: %u\n", subpics[i].bits_per_pixel); - printf("\tformat: %s\n", subpics[i].format == XvPacked ? "XvPacked" : (subpics[i].format == XvPlanar ? "XvPlanar" : "Unknown")); - printf("\tnum_planes: %u\n", subpics[i].num_planes); - - if (subpics[i].type == XvRGB) - { - printf("\tdepth: %u\n", subpics[i].depth); - printf("\tred_mask: 0x%08x\n", subpics[i].red_mask); - printf("\tgreen_mask: 0x%08x\n", subpics[i].green_mask); - printf("\tblue_mask: 0x%08x\n", subpics[i].blue_mask); - } - else if (subpics[i].type == XvYUV) - { - printf("\ty_sample_bits: %u\n", subpics[i].y_sample_bits); - printf("\tu_sample_bits: %u\n", subpics[i].u_sample_bits); - printf("\tv_sample_bits: %u\n", subpics[i].v_sample_bits); - printf("\thorz_y_period: %u\n", subpics[i].horz_y_period); - printf("\thorz_u_period: %u\n", subpics[i].horz_u_period); - printf("\thorz_v_period: %u\n", subpics[i].horz_v_period); - printf("\tvert_y_period: %u\n", subpics[i].vert_y_period); - printf("\tvert_u_period: %u\n", subpics[i].vert_u_period); - printf("\tvert_v_period: %u\n", subpics[i].vert_v_period); - } - PrintComponentOrder(subpics[i].component_order); - printf("\tscanline_order: %s\n", subpics[i].scanline_order == XvTopToBottom ? "XvTopToBottom" : (subpics[i].scanline_order == XvBottomToTop ? "XvBottomToTop" : "Unknown")); - } - - if (num_subpics == 0) - { - printf("Subpictures not supported, nothing to test.\n"); - return 0; - } - - /* Test NULL context */ - assert(XvMCCreateSubpicture(display, NULL, &subpicture, subpic_width, subpic_height, subpics[0].id) == XvMCBadContext); - /* Test NULL subpicture */ - assert(XvMCCreateSubpicture(display, &context, NULL, subpic_width, subpic_height, subpics[0].id) == XvMCBadSubpicture); - /* Test invalid subpicture */ - assert(XvMCCreateSubpicture(display, &context, &subpicture, subpic_width, subpic_height, -1) == BadMatch); - /* Test huge width */ - assert(XvMCCreateSubpicture(display, &context, &subpicture, 16384, subpic_height, subpics[0].id) == BadValue); - /* Test huge height */ - assert(XvMCCreateSubpicture(display, &context, &subpicture, subpic_width, 16384, subpics[0].id) == BadValue); - /* Test huge width & height */ - assert(XvMCCreateSubpicture(display, &context, &subpicture, 16384, 16384, subpics[0].id) == BadValue); - for (i = 0; i < num_subpics; ++i) - { - /* Test valid params */ - assert(XvMCCreateSubpicture(display, &context, &subpicture, subpic_width, subpic_height, subpics[i].id) == Success); - /* Test subpicture id assigned */ - assert(subpicture.subpicture_id != 0); - /* Test context id assigned and correct */ - assert(subpicture.context_id == context.context_id); - /* Test subpicture type id assigned and correct */ - assert(subpicture.xvimage_id == subpics[i].id); - /* Test width & height assigned and correct */ - assert(subpicture.width == width && subpicture.height == height); - if (subpics[i].type == XvRGB) - /* Test no palette support */ - assert(subpicture.num_palette_entries == 0 && subpicture.entry_bytes == 0); - else - /* Test palette support */ - assert(subpicture.num_palette_entries == 16 && subpicture.entry_bytes == 4); - /* Test valid params */ - assert(XvMCDestroySubpicture(display, &subpicture) == Success); - } - /* Test NULL surface */ - assert(XvMCDestroySubpicture(display, NULL) == XvMCBadSubpicture); - - assert(XvMCDestroyContext(display, &context) == Success); - - free(subpics); - XvUngrabPort(display, port_num, CurrentTime); - XCloseDisplay(display); - - return 0; -} diff --git a/src/gallium/state_trackers/xvmc/tests/test_surface.c b/src/gallium/state_trackers/xvmc/tests/test_surface.c deleted file mode 100644 index d5a121d5ab0..00000000000 --- a/src/gallium/state_trackers/xvmc/tests/test_surface.c +++ /dev/null @@ -1,102 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 Younes Manton. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/* Force assertions, even on release builds. */ -#undef NDEBUG -#include -#include -#include -#include "testlib.h" - -int main(int argc, char **argv) -{ - const unsigned int width = 16, height = 16; - const unsigned int mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2}; - - Display *display; - XvPortID port_num; - int surface_type_id; - unsigned int is_overlay, intra_unsigned; - int colorkey; - XvMCContext context; - XvMCSurface surface = {0}; - - display = XOpenDisplay(NULL); - - if (!GetPort - ( - display, - width, - height, - XVMC_CHROMA_FORMAT_420, - mc_types, - 2, - &port_num, - &surface_type_id, - &is_overlay, - &intra_unsigned - )) - { - XCloseDisplay(display); - fprintf(stderr, "Error, unable to find a good port.\n"); - exit(1); - } - - if (is_overlay) - { - Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0); - XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey); - } - - assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, &context) == Success); - - /* Test NULL context */ - assert(XvMCCreateSurface(display, NULL, &surface) == XvMCBadContext); - /* Test NULL surface */ - assert(XvMCCreateSurface(display, &context, NULL) == XvMCBadSurface); - /* Test valid params */ - assert(XvMCCreateSurface(display, &context, &surface) == Success); - /* Test surface id assigned */ - assert(surface.surface_id != 0); - /* Test context id assigned and correct */ - assert(surface.context_id == context.context_id); - /* Test surface type id assigned and correct */ - assert(surface.surface_type_id == surface_type_id); - /* Test width & height assigned and correct */ - assert(surface.width == width && surface.height == height); - /* Test valid params */ - assert(XvMCDestroySurface(display, &surface) == Success); - /* Test NULL surface */ - assert(XvMCDestroySurface(display, NULL) == XvMCBadSurface); - - assert(XvMCDestroyContext(display, &context) == Success); - - XvUngrabPort(display, port_num, CurrentTime); - XCloseDisplay(display); - - return 0; -} diff --git a/src/gallium/state_trackers/xvmc/tests/testlib.c b/src/gallium/state_trackers/xvmc/tests/testlib.c deleted file mode 100644 index a943f6bcd95..00000000000 --- a/src/gallium/state_trackers/xvmc/tests/testlib.c +++ /dev/null @@ -1,147 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 Younes Manton. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include "testlib.h" -#include -#include - -/* -void test(int pred, const char *pred_string, const char *doc_string, const char *file, unsigned int line) -{ - fputs(doc_string, stderr); - if (!pred) - fprintf(stderr, " FAIL!\n\t\"%s\" at %s:%u\n", pred_string, file, line); - else - fputs(" PASS!\n", stderr); -} -*/ - -int GetPort -( - Display *display, - unsigned int width, - unsigned int height, - unsigned int chroma_format, - const unsigned int *mc_types, - unsigned int num_mc_types, - XvPortID *port_id, - int *surface_type_id, - unsigned int *is_overlay, - unsigned int *intra_unsigned -) -{ - unsigned int found_port = 0; - XvAdaptorInfo *adaptor_info; - unsigned int num_adaptors; - int num_types; - int ev_base, err_base; - unsigned int i, j, k, l; - - if (!XvMCQueryExtension(display, &ev_base, &err_base)) - return 0; - if (XvQueryAdaptors(display, XDefaultRootWindow(display), &num_adaptors, &adaptor_info) != Success) - return 0; - - for (i = 0; i < num_adaptors && !found_port; ++i) - { - if (adaptor_info[i].type & XvImageMask) - { - XvMCSurfaceInfo *surface_info = XvMCListSurfaceTypes(display, adaptor_info[i].base_id, &num_types); - - if (surface_info) - { - for (j = 0; j < num_types && !found_port; ++j) - { - if - ( - surface_info[j].chroma_format == chroma_format && - surface_info[j].max_width >= width && - surface_info[j].max_height >= height - ) - { - for (k = 0; k < num_mc_types && !found_port; ++k) - { - if ((surface_info[j].mc_type & mc_types[k]) == mc_types[k]) - { - for (l = 0; l < adaptor_info[i].num_ports && !found_port; ++l) - { - if (XvGrabPort(display, adaptor_info[i].base_id + l, CurrentTime) == Success) - { - *port_id = adaptor_info[i].base_id + l; - *surface_type_id = surface_info[j].surface_type_id; - *is_overlay = surface_info[j].flags & XVMC_OVERLAID_SURFACE; - *intra_unsigned = surface_info[j].flags & XVMC_INTRA_UNSIGNED; - found_port = 1; - } - } - } - } - } - } - - free(surface_info); - } - } - } - - XvFreeAdaptorInfo(adaptor_info); - - return found_port; -} - -unsigned int align(unsigned int value, unsigned int alignment) -{ - return (value + alignment - 1) & ~(alignment - 1); -} - -/* From the glibc manual */ -int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y) -{ - /* Perform the carry for the later subtraction by updating y. */ - if (x->tv_usec < y->tv_usec) - { - int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1; - y->tv_usec -= 1000000 * nsec; - y->tv_sec += nsec; - } - if (x->tv_usec - y->tv_usec > 1000000) - { - int nsec = (x->tv_usec - y->tv_usec) / 1000000; - y->tv_usec += 1000000 * nsec; - y->tv_sec -= nsec; - } - - /* - * Compute the time remaining to wait. - * tv_usec is certainly positive. - */ - result->tv_sec = x->tv_sec - y->tv_sec; - result->tv_usec = x->tv_usec - y->tv_usec; - - /* Return 1 if result is negative. */ - return x->tv_sec < y->tv_sec; -} diff --git a/src/gallium/state_trackers/xvmc/tests/testlib.h b/src/gallium/state_trackers/xvmc/tests/testlib.h deleted file mode 100644 index 783f35a4b18..00000000000 --- a/src/gallium/state_trackers/xvmc/tests/testlib.h +++ /dev/null @@ -1,69 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 Younes Manton. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#ifndef testlib_h -#define testlib_h - -/* -#define TEST(pred, doc) test(pred, #pred, doc, __FILE__, __LINE__) - -void test(int pred, const char *pred_string, const char *doc_string, const char *file, unsigned int line); -*/ - -#include -#include -#include - -/* - * display: IN A valid X display - * width, height: IN Surface size that the port must display - * chroma_format: IN Chroma format that the port must display - * mc_types, num_mc_types: IN List of MC types that the port must support, first port that matches the first mc_type will be returned - * port_id: OUT Your port's ID - * surface_type_id: OUT Your port's surface ID - * is_overlay: OUT If 1, port uses overlay surfaces, you need to set a colorkey - * intra_unsigned: OUT If 1, port uses unsigned values for intra-coded blocks - */ -int GetPort -( - Display *display, - unsigned int width, - unsigned int height, - unsigned int chroma_format, - const unsigned int *mc_types, - unsigned int num_mc_types, - XvPortID *port_id, - int *surface_type_id, - unsigned int *is_overlay, - unsigned int *intra_unsigned -); - -unsigned int align(unsigned int value, unsigned int alignment); - -int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y); - -#endif diff --git a/src/gallium/state_trackers/xvmc/tests/xvmc_bench.c b/src/gallium/state_trackers/xvmc/tests/xvmc_bench.c deleted file mode 100644 index dbd705639f6..00000000000 --- a/src/gallium/state_trackers/xvmc/tests/xvmc_bench.c +++ /dev/null @@ -1,309 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 Younes Manton. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/* Force assertions, even on release builds. */ -#undef NDEBUG -#include -#include -#include -#include -#include -#include "testlib.h" - -#define MACROBLOCK_WIDTH 16 -#define MACROBLOCK_HEIGHT 16 -#define BLOCKS_PER_MACROBLOCK 6 - -#define DEFAULT_INPUT_WIDTH 720 -#define DEFAULT_INPUT_HEIGHT 480 -#define DEFAULT_REPS 100 - -#define PIPELINE_STEP_MC 1 -#define PIPELINE_STEP_CSC 2 -#define PIPELINE_STEP_SWAP 4 - -#define MB_TYPE_I 1 -#define MB_TYPE_P 2 -#define MB_TYPE_B 4 - -struct Config -{ - unsigned int input_width; - unsigned int input_height; - unsigned int output_width; - unsigned int output_height; - unsigned int pipeline; - unsigned int mb_types; - unsigned int reps; -}; - -void ParseArgs(int argc, char **argv, struct Config *config); - -void ParseArgs(int argc, char **argv, struct Config *config) -{ - int fail = 0; - int i; - - config->input_width = DEFAULT_INPUT_WIDTH; - config->input_height = DEFAULT_INPUT_HEIGHT; - config->output_width = 0; - config->output_height = 0; - config->pipeline = 0; - config->mb_types = 0; - config->reps = DEFAULT_REPS; - - for (i = 1; i < argc && !fail; ++i) - { - if (!strcmp(argv[i], "-iw")) - { - if (sscanf(argv[++i], "%u", &config->input_width) != 1) - fail = 1; - } - else if (!strcmp(argv[i], "-ih")) - { - if (sscanf(argv[++i], "%u", &config->input_height) != 1) - fail = 1; - } - else if (!strcmp(argv[i], "-ow")) - { - if (sscanf(argv[++i], "%u", &config->output_width) != 1) - fail = 1; - } - else if (!strcmp(argv[i], "-oh")) - { - if (sscanf(argv[++i], "%u", &config->output_height) != 1) - fail = 1; - } - else if (!strcmp(argv[i], "-p")) - { - char *token = strtok(argv[++i], ","); - - while (token && !fail) - { - if (!strcmp(token, "mc")) - config->pipeline |= PIPELINE_STEP_MC; - else if (!strcmp(token, "csc")) - config->pipeline |= PIPELINE_STEP_CSC; - else if (!strcmp(token, "swp")) - config->pipeline |= PIPELINE_STEP_SWAP; - else - fail = 1; - - if (!fail) - token = strtok(NULL, ","); - } - } - else if (!strcmp(argv[i], "-mb")) - { - char *token = strtok(argv[++i], ","); - - while (token && !fail) - { - if (strcmp(token, "i") == 0) - config->mb_types |= MB_TYPE_I; - else if (strcmp(token, "p") == 0) - config->mb_types |= MB_TYPE_P; - else if (strcmp(token, "b") == 0) - config->mb_types |= MB_TYPE_B; - else - fail = 1; - - if (!fail) - token = strtok(NULL, ","); - } - } - else if (!strcmp(argv[i], "-r")) - { - if (sscanf(argv[++i], "%u", &config->reps) != 1) - fail = 1; - } - else - fail = 1; - } - - if (fail) - { - fprintf( - stderr, - "Bad argument.\n" - "\n" - "Usage: %s [options]\n" - "\t-iw \tInput width\n" - "\t-ih \tInput height\n" - "\t-ow \tOutput width\n" - "\t-oh \tOutput height\n" - "\t-p \tPipeline to test\n" - "\t-mb \tMacroBlock types to use\n" - "\t-r \tRepetitions\n\n" - "\tPipeline steps: mc,csc,swap\n" - "\tMB types: i,p,b\n", - argv[0] - ); - exit(1); - } - - if (config->output_width == 0) - config->output_width = config->input_width; - if (config->output_height == 0) - config->output_height = config->input_height; - if (!config->pipeline) - config->pipeline = PIPELINE_STEP_MC | PIPELINE_STEP_CSC | PIPELINE_STEP_SWAP; - if (!config->mb_types) - config->mb_types = MB_TYPE_I | MB_TYPE_P | MB_TYPE_B; -} - -int main(int argc, char **argv) -{ - struct Config config; - Display *display; - Window root, window; - const unsigned int mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2}; - XvPortID port_num; - int surface_type_id; - unsigned int is_overlay, intra_unsigned; - int colorkey; - XvMCContext context; - XvMCSurface surface; - XvMCBlockArray block_array; - XvMCMacroBlockArray mb_array; - unsigned int mbw, mbh; - unsigned int mbx, mby; - unsigned int reps; - struct timeval start, stop, diff; - double diff_secs; - - ParseArgs(argc, argv, &config); - - mbw = align(config.input_width, MACROBLOCK_WIDTH) / MACROBLOCK_WIDTH; - mbh = align(config.input_height, MACROBLOCK_HEIGHT) / MACROBLOCK_HEIGHT; - - display = XOpenDisplay(NULL); - - if (!GetPort - ( - display, - config.input_width, - config.input_height, - XVMC_CHROMA_FORMAT_420, - mc_types, - 2, - &port_num, - &surface_type_id, - &is_overlay, - &intra_unsigned - )) - { - XCloseDisplay(display); - fprintf(stderr, "Error, unable to find a good port.\n"); - exit(1); - } - - if (is_overlay) - { - Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0); - XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey); - } - else - { - colorkey = 0; - } - - root = XDefaultRootWindow(display); - window = XCreateSimpleWindow(display, root, 0, 0, config.output_width, config.output_height, 0, 0, colorkey); - - assert(XvMCCreateContext(display, port_num, surface_type_id, config.input_width, config.input_height, XVMC_DIRECT, &context) == Success); - assert(XvMCCreateSurface(display, &context, &surface) == Success); - assert(XvMCCreateBlocks(display, &context, mbw * mbh * BLOCKS_PER_MACROBLOCK, &block_array) == Success); - assert(XvMCCreateMacroBlocks(display, &context, mbw * mbh, &mb_array) == Success); - - for (mby = 0; mby < mbh; ++mby) - for (mbx = 0; mbx < mbw; ++mbx) - { - mb_array.macro_blocks[mby * mbw + mbx].x = mbx; - mb_array.macro_blocks[mby * mbw + mbx].y = mby; - mb_array.macro_blocks[mby * mbw + mbx].macroblock_type = XVMC_MB_TYPE_INTRA; - /*mb->motion_type = ;*/ - /*mb->motion_vertical_field_select = ;*/ - mb_array.macro_blocks[mby * mbw + mbx].dct_type = XVMC_DCT_TYPE_FRAME; - /*mb->PMV[0][0][0] = ; - mb->PMV[0][0][1] = ; - mb->PMV[0][1][0] = ; - mb->PMV[0][1][1] = ; - mb->PMV[1][0][0] = ; - mb->PMV[1][0][1] = ; - mb->PMV[1][1][0] = ; - mb->PMV[1][1][1] = ;*/ - mb_array.macro_blocks[mby * mbw + mbx].index = (mby * mbw + mbx) * BLOCKS_PER_MACROBLOCK; - mb_array.macro_blocks[mby * mbw + mbx].coded_block_pattern = 0x3F; - } - - XSelectInput(display, window, ExposureMask | KeyPressMask); - XMapWindow(display, window); - XSync(display, 0); - - gettimeofday(&start, NULL); - - for (reps = 0; reps < config.reps; ++reps) - { - if (config.pipeline & PIPELINE_STEP_MC) - { - assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, mbw * mbh, 0, &mb_array, &block_array) == Success); - assert(XvMCFlushSurface(display, &surface) == Success); - } - if (config.pipeline & PIPELINE_STEP_CSC) - assert(XvMCPutSurface(display, &surface, window, 0, 0, config.input_width, config.input_height, 0, 0, config.output_width, config.output_height, XVMC_FRAME_PICTURE) == Success); - } - - gettimeofday(&stop, NULL); - - timeval_subtract(&diff, &stop, &start); - diff_secs = (double)diff.tv_sec + (double)diff.tv_usec / 1000000.0; - - printf("XvMC Benchmark\n"); - printf("Input: %u,%u\nOutput: %u,%u\n", config.input_width, config.input_height, config.output_width, config.output_height); - printf("Pipeline: "); - if (config.pipeline & PIPELINE_STEP_MC) - printf("|mc|"); - if (config.pipeline & PIPELINE_STEP_CSC) - printf("|csc|"); - if (config.pipeline & PIPELINE_STEP_SWAP) - printf("|swap|"); - printf("\n"); - printf("Reps: %u\n", config.reps); - printf("Total time: %.2lf (%.2lf reps / sec)\n", diff_secs, config.reps / diff_secs); - - assert(XvMCDestroyBlocks(display, &block_array) == Success); - assert(XvMCDestroyMacroBlocks(display, &mb_array) == Success); - assert(XvMCDestroySurface(display, &surface) == Success); - assert(XvMCDestroyContext(display, &context) == Success); - - XvUngrabPort(display, port_num, CurrentTime); - XDestroyWindow(display, window); - XCloseDisplay(display); - - return 0; -} diff --git a/src/gallium/state_trackers/xvmc/xvmc_private.h b/src/gallium/state_trackers/xvmc/xvmc_private.h deleted file mode 100644 index a1d026f704e..00000000000 --- a/src/gallium/state_trackers/xvmc/xvmc_private.h +++ /dev/null @@ -1,125 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 Younes Manton. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#ifndef xvmc_private_h -#define xvmc_private_h - -#include -#include - -#include "pipe/p_video_state.h" - -#include "util/u_debug.h" -#include "util/u_math.h" - -#include "vl/vl_csc.h" -#include "vl/vl_compositor.h" - -#define BLOCK_SIZE_SAMPLES 64 -#define BLOCK_SIZE_BYTES (BLOCK_SIZE_SAMPLES * 2) - -struct pipe_video_codec; -struct pipe_video_buffer; - -struct pipe_sampler_view; -struct pipe_fence_handle; - -typedef struct -{ - struct vl_screen *vscreen; - struct pipe_context *pipe; - struct pipe_video_codec *decoder; - - enum VL_CSC_COLOR_STANDARD color_standard; - struct vl_procamp procamp; - struct vl_compositor compositor; - struct vl_compositor_state cstate; - - unsigned short subpicture_max_width; - unsigned short subpicture_max_height; - -} XvMCContextPrivate; - -typedef struct -{ - struct pipe_video_buffer *video_buffer; - - /* nonzero if this picture is already being decoded */ - unsigned picture_structure; - - XvMCSurface *ref[2]; - - struct pipe_fence_handle *fence; - - /* The subpicture associated with this surface, if any. */ - XvMCSubpicture *subpicture; - - /* Some XvMC functions take a surface but not a context, - so we keep track of which context each surface belongs to. */ - XvMCContext *context; -} XvMCSurfacePrivate; - -typedef struct -{ - struct pipe_sampler_view *sampler; - - /* optional palette for this subpicture */ - struct pipe_sampler_view *palette; - - struct u_rect src_rect; - struct u_rect dst_rect; - - /* The surface this subpicture is currently associated with, if any. */ - XvMCSurface *surface; - - /* Some XvMC functions take a subpicture but not a context, - so we keep track of which context each subpicture belongs to. */ - XvMCContext *context; -} XvMCSubpicturePrivate; - -#define XVMC_OUT 0 -#define XVMC_ERR 1 -#define XVMC_WARN 2 -#define XVMC_TRACE 3 - -static inline void XVMC_MSG(int level, const char *fmt, ...) -{ - static int debug_level = -1; - - if (debug_level == -1) { - debug_level = MAX2(debug_get_num_option("XVMC_DEBUG", 0), 0); - } - - if (level <= debug_level) { - va_list ap; - va_start(ap, fmt); - _debug_vprintf(fmt, ap); - va_end(ap); - } -} - -#endif /* xvmc_private_h */ diff --git a/src/gallium/targets/d3dadapter9/drm.c b/src/gallium/targets/d3dadapter9/drm.c index 819aa59468c..a230475d7de 100644 --- a/src/gallium/targets/d3dadapter9/drm.c +++ b/src/gallium/targets/d3dadapter9/drm.c @@ -32,7 +32,7 @@ #include "target-helpers/drm_helper.h" #include "target-helpers/sw_helper.h" -#include "state_tracker/drm_driver.h" +#include "frontend/drm_driver.h" #include "d3dadapter/d3dadapter9.h" #include "d3dadapter/drm.h" diff --git a/src/gallium/targets/d3dadapter9/meson.build b/src/gallium/targets/d3dadapter9/meson.build index 55b514f5add..23a19c77508 100644 --- a/src/gallium/targets/d3dadapter9/meson.build +++ b/src/gallium/targets/d3dadapter9/meson.build @@ -53,7 +53,7 @@ libgallium_nine = shared_library( inc_include, inc_src, inc_loader, inc_mapi, inc_mesa, inc_util, inc_dri_common, inc_gallium, inc_gallium_aux, inc_gallium_winsys, inc_gallium_drivers, inc_d3d9, - include_directories('../../state_trackers/nine'), + include_directories('../../frontends/nine'), ], c_args : [c_vis_args, gallium_nine_c_args], cpp_args : [cpp_vis_args], diff --git a/src/gallium/targets/dri/SConscript b/src/gallium/targets/dri/SConscript new file mode 100644 index 00000000000..835038dd639 --- /dev/null +++ b/src/gallium/targets/dri/SConscript @@ -0,0 +1,59 @@ +Import('*') + +env = drienv.Clone() + +if env['suncc']: + print('warning: not building dri-vmwgfx') + Return() + +env.Append(CPPPATH = [ + '#/src/loader', + '#/src/mapi', + '#/src/mesa', + '#/src/mesa/drivers/dri/common', + '#/src/gallium/frontends/dri', +]) + +if env['llvm']: + env.Append(CPPDEFINES = 'GALLIUM_LLVMPIPE') + env.Prepend(LIBS = [llvmpipe]) + +env.PkgUseModules('DRM') + +env.Append(CPPDEFINES = [ + 'GALLIUM_VMWGFX', + 'GALLIUM_SOFTPIPE', +]) + +env.Prepend(LIBS = [ + st_dri, + svgadrm, + svga, + ws_dri, + softpipe, + pipe_loader, + libloader, + mesautil, + compiler, + mesa, + glsl, + nir, + spirv, + gallium, + megadrivers_stub, + dri_common, +]) + +module = env.LoadableModule( + target = 'gallium_dri.so', + source = 'target.c', + SHLIBPREFIX = '', +) + +# vmwgfx_dri.so +env.Command('vmwgfx_dri.so', 'gallium_dri.so', "ln -f ${SOURCE} ${TARGET}") +# swrast_dri.so +env.Command('swrast_dri.so', 'gallium_dri.so', "ln -f ${SOURCE} ${TARGET}") + +env.Alias('dri-vmwgfx', module) +env.Alias('dri-swrast', module) diff --git a/src/gallium/targets/dri/meson.build b/src/gallium/targets/dri/meson.build index 8da21b3394a..2c80bf12090 100644 --- a/src/gallium/targets/dri/meson.build +++ b/src/gallium/targets/dri/meson.build @@ -42,7 +42,7 @@ libgallium_dri = shared_library( files('target.c'), include_directories : [ inc_include, inc_src, inc_mapi, inc_mesa, inc_gallium, inc_gallium_aux, inc_util, inc_dri_common, inc_gallium_drivers, - inc_gallium_winsys, include_directories('../../state_trackers/dri'), + inc_gallium_winsys, include_directories('../../frontends/dri'), ], c_args : [c_vis_args], cpp_args : [cpp_vis_args], diff --git a/src/gallium/targets/graw-gdi/graw_gdi.c b/src/gallium/targets/graw-gdi/graw_gdi.c index 99d8641d6b1..aa75c73b980 100644 --- a/src/gallium/targets/graw-gdi/graw_gdi.c +++ b/src/gallium/targets/graw-gdi/graw_gdi.c @@ -28,7 +28,7 @@ #include "gdi/gdi_sw_winsys.h" #include "pipe/p_screen.h" -#include "state_tracker/graw.h" +#include "frontend/graw.h" #include "target-helpers/inline_debug_helper.h" #include "target-helpers/inline_sw_helper.h" #include diff --git a/src/gallium/targets/graw-null/graw_null.c b/src/gallium/targets/graw-null/graw_null.c index f1fe3872c94..6b42fdb463a 100644 --- a/src/gallium/targets/graw-null/graw_null.c +++ b/src/gallium/targets/graw-null/graw_null.c @@ -1,4 +1,4 @@ -#include "state_tracker/graw.h" +#include "frontend/graw.h" diff --git a/src/gallium/targets/graw-null/graw_util.c b/src/gallium/targets/graw-null/graw_util.c index 6d4d960d297..a7692c1646f 100644 --- a/src/gallium/targets/graw-null/graw_util.c +++ b/src/gallium/targets/graw-null/graw_util.c @@ -7,7 +7,7 @@ #include "util/u_debug.h" #include "util/u_debug_image.h" #include "util/u_memory.h" -#include "state_tracker/graw.h" +#include "frontend/graw.h" /* Helper functions. These are the same for all graw implementations. diff --git a/src/gallium/targets/graw-xlib/graw_xlib.c b/src/gallium/targets/graw-xlib/graw_xlib.c index db2637bd3c9..48c3d2915cc 100644 --- a/src/gallium/targets/graw-xlib/graw_xlib.c +++ b/src/gallium/targets/graw-xlib/graw_xlib.c @@ -5,8 +5,8 @@ #include "util/u_memory.h" #include "target-helpers/inline_sw_helper.h" #include "target-helpers/inline_debug_helper.h" -#include "state_tracker/xlibsw_api.h" -#include "state_tracker/graw.h" +#include "frontend/xlibsw_api.h" +#include "frontend/graw.h" #include "sw/xlib/xlib_sw_winsys.h" #include diff --git a/src/gallium/targets/haiku-softpipe/GalliumContext.cpp b/src/gallium/targets/haiku-softpipe/GalliumContext.cpp index 13378d1a375..ead238194bf 100644 --- a/src/gallium/targets/haiku-softpipe/GalliumContext.cpp +++ b/src/gallium/targets/haiku-softpipe/GalliumContext.cpp @@ -22,7 +22,7 @@ //#include "state_tracker/st_cb_flush.h" #include "state_tracker/st_context.h" #include "state_tracker/st_gl_api.h" -#include "state_tracker/sw_winsys.h" +#include "frontend/sw_winsys.h" #include "sw/hgl/hgl_sw_winsys.h" #include "util/u_atomic.h" #include "util/u_memory.h" diff --git a/src/gallium/targets/haiku-softpipe/SConscript b/src/gallium/targets/haiku-softpipe/SConscript new file mode 100644 index 00000000000..312155abe14 --- /dev/null +++ b/src/gallium/targets/haiku-softpipe/SConscript @@ -0,0 +1,47 @@ +Import('*') + +env.Prepend(LIBS = [ + ws_haiku, + st_haiku, + mesautil, + compiler, + mesa, + glsl, + nir, + spirv, + gallium +]) + +if True: + env.Append(CPPDEFINES = [ + 'GALLIUM_SOFTPIPE', + ]) + env.Prepend(LIBS = [softpipe]) + +env.Prepend(LIBS = [libgl]) + +env.Append(CPPPATH = [ + '#/src/mapi', + '#/src/mesa', + '#/src/mesa/main', + '#/include/HaikuGL', + '#/src/gallium/winsys', + '#/src/gallium/frontends/hgl', + '/boot/system/develop/headers/private', +]) + +if env['llvm']: + env.Append(CPPDEFINES = ['GALLIUM_LLVMPIPE']) + env.Prepend(LIBS = [llvmpipe]) + +softpipe_sources = [ + 'GalliumContext.cpp', + 'SoftwareRenderer.cpp' +] + +# libswpipe gets turned into "Softpipe" by the haiku package system +module = env.LoadableModule( + target ='swpipe', + source = softpipe_sources, +) + diff --git a/src/gallium/targets/haiku-softpipe/meson.build b/src/gallium/targets/haiku-softpipe/meson.build index e35fab5dacf..addea41538a 100644 --- a/src/gallium/targets/haiku-softpipe/meson.build +++ b/src/gallium/targets/haiku-softpipe/meson.build @@ -23,7 +23,7 @@ libswpipe = shared_library( files('SoftwareRenderer.cpp', 'GalliumContext.cpp'), include_directories : [ inc_include, inc_src, inc_mapi, inc_mesa, inc_gallium, inc_gallium_aux, inc_util, inc_haikugl, inc_gallium_drivers, inc_gallium_winsys, - include_directories('../../state_trackers/hgl'), + include_directories('../../frontends/hgl'), include_directories('/boot/system/develop/headers/private') ], c_args : [c_vis_args], diff --git a/src/gallium/targets/libgl-gdi/SConscript b/src/gallium/targets/libgl-gdi/SConscript index efc0c5b2ea1..5255125ca09 100644 --- a/src/gallium/targets/libgl-gdi/SConscript +++ b/src/gallium/targets/libgl-gdi/SConscript @@ -7,7 +7,7 @@ env = env.Clone() env.Append(CPPPATH = [ '#src', - '#src/gallium/state_trackers/wgl', + '#src/gallium/frontends/wgl', '#src/gallium/winsys/sw', ]) @@ -38,9 +38,9 @@ if env['llvm']: if env['gcc'] and env['machine'] != 'x86_64': # DEF parser in certain versions of MinGW is busted, as does not behave as # MSVC. mingw-w64 works fine. - sources += ['#src/gallium/state_trackers/wgl/opengl32.mingw.def'] + sources += ['#src/gallium/frontends/wgl/opengl32.mingw.def'] else: - sources += ['#src/gallium/state_trackers/wgl/opengl32.def'] + sources += ['#src/gallium/frontends/wgl/opengl32.def'] env['no_import_lib'] = 1 diff --git a/src/gallium/targets/libgl-gdi/meson.build b/src/gallium/targets/libgl-gdi/meson.build index 6332267fff4..d7539442df4 100644 --- a/src/gallium/targets/libgl-gdi/meson.build +++ b/src/gallium/targets/libgl-gdi/meson.build @@ -21,9 +21,9 @@ # DEF parser in certain versions of MinGW is busted, as does not behave as # MSVC. mingw-w64 works fine. if cc.get_id() == 'gcc' and host_machine.cpu_family() != 'x86_64' - ogldef = files('../../state_trackers/wgl/opengl32.mingw.def')[0] + ogldef = files('../../frontends/wgl/opengl32.mingw.def')[0] else - ogldef = files('../../state_trackers/wgl/opengl32.def')[0] + ogldef = files('../../frontends/wgl/opengl32.def')[0] endif libopengl32 = shared_library( diff --git a/src/gallium/targets/libgl-xlib/SConscript b/src/gallium/targets/libgl-xlib/SConscript index edd14a8da41..c1b787d95af 100644 --- a/src/gallium/targets/libgl-xlib/SConscript +++ b/src/gallium/targets/libgl-xlib/SConscript @@ -9,7 +9,7 @@ env.Append(CPPPATH = [ '#/src/mapi', '#/src/mesa', '#/src/mesa/main', - '#src/gallium/state_trackers/glx/xlib', + '#src/gallium/frontends/glx/xlib', Dir('../../../mapi'), # src/mapi build path for python-generated GL API files/headers Dir('../../../mapi/glapi/gen'), # src/mapi build path for python-generated GL API files/headers ]) diff --git a/src/gallium/targets/libgl-xlib/meson.build b/src/gallium/targets/libgl-xlib/meson.build index 8aec6219a87..4cd673ed34e 100644 --- a/src/gallium/targets/libgl-xlib/meson.build +++ b/src/gallium/targets/libgl-xlib/meson.build @@ -42,7 +42,7 @@ libgl = shared_library( files('xlib.c'), include_directories : [ inc_include, inc_src, inc_mapi, inc_mesa, inc_gallium, inc_gallium_aux, inc_gallium_winsys, inc_gallium_drivers, - include_directories('../../state_trackers/glx/xlib'), + include_directories('../../frontends/glx/xlib'), ], c_args : [c_vis_args, gallium_xlib_c_args], link_args : [ld_args_bsymbolic, ld_args_gc_sections, gallium_xlib_ld_args], diff --git a/src/gallium/targets/pipe-loader/pipe_i915.c b/src/gallium/targets/pipe-loader/pipe_i915.c index b4f5a72f296..927bad0de2c 100644 --- a/src/gallium/targets/pipe-loader/pipe_i915.c +++ b/src/gallium/targets/pipe-loader/pipe_i915.c @@ -1,6 +1,6 @@ #include "target-helpers/inline_debug_helper.h" -#include "state_tracker/drm_driver.h" +#include "frontend/drm_driver.h" #include "i915/drm/i915_drm_public.h" #include "i915/i915_public.h" diff --git a/src/gallium/targets/pipe-loader/pipe_kmsro.c b/src/gallium/targets/pipe-loader/pipe_kmsro.c index 1c1a8d24561..79c66bd3695 100644 --- a/src/gallium/targets/pipe-loader/pipe_kmsro.c +++ b/src/gallium/targets/pipe-loader/pipe_kmsro.c @@ -1,6 +1,6 @@ #include "target-helpers/inline_debug_helper.h" -#include "state_tracker/drm_driver.h" +#include "frontend/drm_driver.h" #include "kmsro/drm/kmsro_drm_public.h" static struct pipe_screen * diff --git a/src/gallium/targets/pipe-loader/pipe_msm.c b/src/gallium/targets/pipe-loader/pipe_msm.c index 43b8f0b4ea4..4868a8bcd8d 100644 --- a/src/gallium/targets/pipe-loader/pipe_msm.c +++ b/src/gallium/targets/pipe-loader/pipe_msm.c @@ -1,6 +1,6 @@ #include "target-helpers/inline_debug_helper.h" -#include "state_tracker/drm_driver.h" +#include "frontend/drm_driver.h" #include "freedreno/drm/freedreno_drm_public.h" static struct pipe_screen * diff --git a/src/gallium/targets/pipe-loader/pipe_nouveau.c b/src/gallium/targets/pipe-loader/pipe_nouveau.c index 06fe95624d1..6b5ee18408c 100644 --- a/src/gallium/targets/pipe-loader/pipe_nouveau.c +++ b/src/gallium/targets/pipe-loader/pipe_nouveau.c @@ -1,6 +1,6 @@ #include "target-helpers/inline_debug_helper.h" -#include "state_tracker/drm_driver.h" +#include "frontend/drm_driver.h" #include "nouveau/drm/nouveau_drm_public.h" static struct pipe_screen * diff --git a/src/gallium/targets/pipe-loader/pipe_r300.c b/src/gallium/targets/pipe-loader/pipe_r300.c index 17b310ee189..268a5eee287 100644 --- a/src/gallium/targets/pipe-loader/pipe_r300.c +++ b/src/gallium/targets/pipe-loader/pipe_r300.c @@ -1,5 +1,5 @@ #include "target-helpers/inline_debug_helper.h" -#include "state_tracker/drm_driver.h" +#include "frontend/drm_driver.h" #include "radeon/drm/radeon_drm_public.h" #include "radeon/radeon_winsys.h" #include "r300/r300_public.h" diff --git a/src/gallium/targets/pipe-loader/pipe_r600.c b/src/gallium/targets/pipe-loader/pipe_r600.c index 855aa9e4bd3..871dff3f7e1 100644 --- a/src/gallium/targets/pipe-loader/pipe_r600.c +++ b/src/gallium/targets/pipe-loader/pipe_r600.c @@ -1,4 +1,4 @@ -#include "state_tracker/drm_driver.h" +#include "frontend/drm_driver.h" #include "target-helpers/inline_debug_helper.h" #include "radeon/drm/radeon_drm_public.h" #include "radeon/radeon_winsys.h" diff --git a/src/gallium/targets/pipe-loader/pipe_radeonsi.c b/src/gallium/targets/pipe-loader/pipe_radeonsi.c index 9d925c727f1..f5c5770af08 100644 --- a/src/gallium/targets/pipe-loader/pipe_radeonsi.c +++ b/src/gallium/targets/pipe-loader/pipe_radeonsi.c @@ -1,4 +1,4 @@ -#include "state_tracker/drm_driver.h" +#include "frontend/drm_driver.h" #include "target-helpers/inline_debug_helper.h" #include "radeonsi/si_public.h" #include "util/xmlpool.h" diff --git a/src/gallium/targets/pipe-loader/pipe_swrast.c b/src/gallium/targets/pipe-loader/pipe_swrast.c index 0a980b3b1a9..ebfc11c8936 100644 --- a/src/gallium/targets/pipe-loader/pipe_swrast.c +++ b/src/gallium/targets/pipe-loader/pipe_swrast.c @@ -1,7 +1,7 @@ #include "target-helpers/inline_sw_helper.h" #include "target-helpers/inline_debug_helper.h" -#include "state_tracker/sw_driver.h" +#include "frontend/sw_driver.h" #include "sw/dri/dri_sw_winsys.h" #include "sw/kms-dri/kms_dri_sw_winsys.h" #include "sw/null/null_sw_winsys.h" diff --git a/src/gallium/targets/pipe-loader/pipe_vmwgfx.c b/src/gallium/targets/pipe-loader/pipe_vmwgfx.c index a60a5e89814..73c6bda9879 100644 --- a/src/gallium/targets/pipe-loader/pipe_vmwgfx.c +++ b/src/gallium/targets/pipe-loader/pipe_vmwgfx.c @@ -1,6 +1,6 @@ #include "target-helpers/inline_debug_helper.h" -#include "state_tracker/drm_driver.h" +#include "frontend/drm_driver.h" #include "svga/drm/svga_drm_public.h" #include "svga/svga_public.h" diff --git a/src/gallium/tests/graw/clear.c b/src/gallium/tests/graw/clear.c index 522799c1e1a..3c16f5211a6 100644 --- a/src/gallium/tests/graw/clear.c +++ b/src/gallium/tests/graw/clear.c @@ -3,7 +3,7 @@ */ #include -#include "state_tracker/graw.h" +#include "frontend/graw.h" #include "pipe/p_screen.h" #include "pipe/p_context.h" #include "pipe/p_state.h" diff --git a/src/gallium/tests/graw/fs-test.c b/src/gallium/tests/graw/fs-test.c index 346bbedd61a..8c40ecd705d 100644 --- a/src/gallium/tests/graw/fs-test.c +++ b/src/gallium/tests/graw/fs-test.c @@ -2,7 +2,7 @@ * any utility code, just the graw interface and gallium. */ -#include "state_tracker/graw.h" +#include "frontend/graw.h" #include "pipe/p_screen.h" #include "pipe/p_context.h" #include "pipe/p_shader_tokens.h" diff --git a/src/gallium/tests/graw/graw_util.h b/src/gallium/tests/graw/graw_util.h index 7cd22416a9f..bb5d53d24bf 100644 --- a/src/gallium/tests/graw/graw_util.h +++ b/src/gallium/tests/graw/graw_util.h @@ -1,5 +1,5 @@ -#include "state_tracker/graw.h" +#include "frontend/graw.h" #include "pipe/p_context.h" #include "pipe/p_defines.h" diff --git a/src/gallium/tests/graw/gs-test.c b/src/gallium/tests/graw/gs-test.c index 5d3739c7281..34f1decdd66 100644 --- a/src/gallium/tests/graw/gs-test.c +++ b/src/gallium/tests/graw/gs-test.c @@ -2,7 +2,7 @@ * any utility code, just the graw interface and gallium. */ -#include "state_tracker/graw.h" +#include "frontend/graw.h" #include "pipe/p_screen.h" #include "pipe/p_context.h" #include "pipe/p_shader_tokens.h" diff --git a/src/gallium/tests/graw/quad-sample.c b/src/gallium/tests/graw/quad-sample.c index 043abdf5044..160c8db5301 100644 --- a/src/gallium/tests/graw/quad-sample.c +++ b/src/gallium/tests/graw/quad-sample.c @@ -2,7 +2,7 @@ * any utility code, just the graw interface and gallium. */ -#include "state_tracker/graw.h" +#include "frontend/graw.h" #include "pipe/p_screen.h" #include "pipe/p_context.h" #include "pipe/p_shader_tokens.h" diff --git a/src/gallium/tests/graw/shader-leak.c b/src/gallium/tests/graw/shader-leak.c index 90d674745fd..cc5cd8a4bcd 100644 --- a/src/gallium/tests/graw/shader-leak.c +++ b/src/gallium/tests/graw/shader-leak.c @@ -3,7 +3,7 @@ */ #include -#include "state_tracker/graw.h" +#include "frontend/graw.h" #include "pipe/p_screen.h" #include "pipe/p_context.h" #include "pipe/p_state.h" diff --git a/src/gallium/tests/graw/tri-gs.c b/src/gallium/tests/graw/tri-gs.c index 6820bc530ea..97075f988ce 100644 --- a/src/gallium/tests/graw/tri-gs.c +++ b/src/gallium/tests/graw/tri-gs.c @@ -3,7 +3,7 @@ */ #include -#include "state_tracker/graw.h" +#include "frontend/graw.h" #include "pipe/p_screen.h" #include "pipe/p_context.h" #include "pipe/p_state.h" diff --git a/src/gallium/tests/graw/tri-instanced.c b/src/gallium/tests/graw/tri-instanced.c index 72dce01980c..8294147e040 100644 --- a/src/gallium/tests/graw/tri-instanced.c +++ b/src/gallium/tests/graw/tri-instanced.c @@ -5,7 +5,7 @@ #include #include -#include "state_tracker/graw.h" +#include "frontend/graw.h" #include "pipe/p_screen.h" #include "pipe/p_context.h" #include "pipe/p_state.h" diff --git a/src/gallium/tests/graw/vs-test.c b/src/gallium/tests/graw/vs-test.c index 1b96914ad2a..a48e83f6923 100644 --- a/src/gallium/tests/graw/vs-test.c +++ b/src/gallium/tests/graw/vs-test.c @@ -2,7 +2,7 @@ * any utility code, just the graw interface and gallium. */ -#include "state_tracker/graw.h" +#include "frontend/graw.h" #include "pipe/p_screen.h" #include "pipe/p_context.h" #include "pipe/p_shader_tokens.h" diff --git a/src/gallium/winsys/amdgpu/drm/amdgpu_bo.c b/src/gallium/winsys/amdgpu/drm/amdgpu_bo.c index 3568d8229cd..1a30c9a3cf3 100644 --- a/src/gallium/winsys/amdgpu/drm/amdgpu_bo.c +++ b/src/gallium/winsys/amdgpu/drm/amdgpu_bo.c @@ -30,7 +30,7 @@ #include "util/hash_table.h" #include "util/os_time.h" #include "util/u_hash_table.h" -#include "state_tracker/drm_driver.h" +#include "frontend/drm_driver.h" #include "drm-uapi/amdgpu_drm.h" #include #include diff --git a/src/gallium/winsys/i915/drm/i915_drm_buffer.c b/src/gallium/winsys/i915/drm/i915_drm_buffer.c index 9b525f9809c..3d24b64e679 100644 --- a/src/gallium/winsys/i915/drm/i915_drm_buffer.c +++ b/src/gallium/winsys/i915/drm/i915_drm_buffer.c @@ -1,4 +1,4 @@ -#include "state_tracker/drm_driver.h" +#include "frontend/drm_driver.h" #include "i915_drm_winsys.h" #include "util/u_memory.h" diff --git a/src/gallium/winsys/i915/drm/i915_drm_winsys.c b/src/gallium/winsys/i915/drm/i915_drm_winsys.c index d07ee496e48..add8ff83e2b 100644 --- a/src/gallium/winsys/i915/drm/i915_drm_winsys.c +++ b/src/gallium/winsys/i915/drm/i915_drm_winsys.c @@ -3,7 +3,7 @@ #include "drm-uapi/i915_drm.h" -#include "state_tracker/drm_driver.h" +#include "frontend/drm_driver.h" #include "i915_drm_winsys.h" #include "i915_drm_public.h" diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c index f802d858eac..948e0b20ce3 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c +++ b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c @@ -33,7 +33,7 @@ #include "os/os_mman.h" #include "util/os_time.h" -#include "state_tracker/drm_driver.h" +#include "frontend/drm_driver.h" #include #include diff --git a/src/gallium/winsys/svga/drm/vmw_screen_dri.c b/src/gallium/winsys/svga/drm/vmw_screen_dri.c index 62d1b18b9e3..0a6e586e013 100644 --- a/src/gallium/winsys/svga/drm/vmw_screen_dri.c +++ b/src/gallium/winsys/svga/drm/vmw_screen_dri.c @@ -36,7 +36,7 @@ #include "svga_drm_public.h" #include "svga3d_surfacedefs.h" -#include "state_tracker/drm_driver.h" +#include "frontend/drm_driver.h" #include "vmwgfx_drm.h" #include diff --git a/src/gallium/winsys/svga/drm/vmw_screen_ioctl.c b/src/gallium/winsys/svga/drm/vmw_screen_ioctl.c index bb3a1adedc1..ed267e9ad68 100644 --- a/src/gallium/winsys/svga/drm/vmw_screen_ioctl.c +++ b/src/gallium/winsys/svga/drm/vmw_screen_ioctl.c @@ -37,7 +37,7 @@ #include "util/u_memory.h" #include "util/u_math.h" #include "svgadump/svga_dump.h" -#include "state_tracker/drm_driver.h" +#include "frontend/drm_driver.h" #include "vmw_screen.h" #include "vmw_context.h" #include "vmw_fence.h" diff --git a/src/gallium/winsys/sw/dri/dri_sw_winsys.c b/src/gallium/winsys/sw/dri/dri_sw_winsys.c index 6173147a1ff..c889e968534 100644 --- a/src/gallium/winsys/sw/dri/dri_sw_winsys.c +++ b/src/gallium/winsys/sw/dri/dri_sw_winsys.c @@ -39,7 +39,7 @@ #include "util/u_math.h" #include "util/u_memory.h" -#include "state_tracker/sw_winsys.h" +#include "frontend/sw_winsys.h" #include "dri_sw_winsys.h" diff --git a/src/gallium/winsys/sw/dri/dri_sw_winsys.h b/src/gallium/winsys/sw/dri/dri_sw_winsys.h index 47e3777d4cd..e9fbac0c187 100644 --- a/src/gallium/winsys/sw/dri/dri_sw_winsys.h +++ b/src/gallium/winsys/sw/dri/dri_sw_winsys.h @@ -29,7 +29,7 @@ #ifndef DRI_SW_WINSYS #define DRI_SW_WINSYS -#include "state_tracker/drisw_api.h" +#include "frontend/drisw_api.h" struct sw_winsys; diff --git a/src/gallium/winsys/sw/gdi/gdi_sw_winsys.c b/src/gallium/winsys/sw/gdi/gdi_sw_winsys.c index ed22e82ee6d..87ffbcc0689 100644 --- a/src/gallium/winsys/sw/gdi/gdi_sw_winsys.c +++ b/src/gallium/winsys/sw/gdi/gdi_sw_winsys.c @@ -42,7 +42,7 @@ #include "util/format/u_format.h" #include "util/u_math.h" #include "util/u_memory.h" -#include "state_tracker/sw_winsys.h" +#include "frontend/sw_winsys.h" #include "gdi_sw_winsys.h" diff --git a/src/gallium/winsys/sw/gdi/gdi_sw_winsys.h b/src/gallium/winsys/sw/gdi/gdi_sw_winsys.h index 4bbcb47848b..c882b1d8d35 100644 --- a/src/gallium/winsys/sw/gdi/gdi_sw_winsys.h +++ b/src/gallium/winsys/sw/gdi/gdi_sw_winsys.h @@ -4,7 +4,7 @@ #include #include "pipe/p_compiler.h" -#include "state_tracker/sw_winsys.h" +#include "frontend/sw_winsys.h" void gdi_sw_display( struct sw_winsys *winsys, struct sw_displaytarget *dt, diff --git a/src/gallium/winsys/sw/hgl/SConscript b/src/gallium/winsys/sw/hgl/SConscript index 7755b00ea8c..776dd831a4b 100644 --- a/src/gallium/winsys/sw/hgl/SConscript +++ b/src/gallium/winsys/sw/hgl/SConscript @@ -12,7 +12,7 @@ if env['platform'] in ('haiku'): '#/src/gallium/include', '#/src/gallium/auxiliary', '#/src/gallium/drivers', - '#/src/gallium/state_trackers/hgl', + '#/src/gallium/frontend/hgl', ]) ws_haiku = env.ConvenienceLibrary( diff --git a/src/gallium/winsys/sw/hgl/hgl_sw_winsys.c b/src/gallium/winsys/sw/hgl/hgl_sw_winsys.c index 35e7137b549..bcbaf9cabe5 100644 --- a/src/gallium/winsys/sw/hgl/hgl_sw_winsys.c +++ b/src/gallium/winsys/sw/hgl/hgl_sw_winsys.c @@ -34,8 +34,8 @@ #include "util/format/u_format.h" #include "util/u_math.h" #include "util/u_memory.h" -#include "state_tracker/st_api.h" -#include "state_tracker/sw_winsys.h" +#include "frontend/api.h" +#include "frontend/sw_winsys.h" #include "bitmap_wrapper.h" #include "hgl_sw_winsys.h" diff --git a/src/gallium/winsys/sw/hgl/meson.build b/src/gallium/winsys/sw/hgl/meson.build index 8901096bd12..10096651c99 100644 --- a/src/gallium/winsys/sw/hgl/meson.build +++ b/src/gallium/winsys/sw/hgl/meson.build @@ -23,7 +23,7 @@ libswhgl = static_library( files('hgl_sw_winsys.c'), c_args : c_vis_args, include_directories : [inc_gallium, inc_include, inc_src, inc_gallium_aux, - include_directories('../../../state_trackers/hgl') + include_directories('../../../frontends/hgl') ], build_by_default : false, ) diff --git a/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c b/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c index da11be2333a..b501ba0403a 100644 --- a/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c +++ b/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c @@ -50,8 +50,8 @@ #include "util/u_memory.h" #include "util/list.h" -#include "state_tracker/sw_winsys.h" -#include "state_tracker/drm_driver.h" +#include "frontend/sw_winsys.h" +#include "frontend/drm_driver.h" #include "kms_dri_sw_winsys.h" #ifdef DEBUG diff --git a/src/gallium/winsys/sw/null/null_sw_winsys.c b/src/gallium/winsys/sw/null/null_sw_winsys.c index e897f246d26..a39f74c879c 100644 --- a/src/gallium/winsys/sw/null/null_sw_winsys.c +++ b/src/gallium/winsys/sw/null/null_sw_winsys.c @@ -39,7 +39,7 @@ #include "pipe/p_format.h" #include "util/u_memory.h" -#include "state_tracker/sw_winsys.h" +#include "frontend/sw_winsys.h" #include "null_sw_winsys.h" diff --git a/src/gallium/winsys/sw/wrapper/wrapper_sw_winsys.c b/src/gallium/winsys/sw/wrapper/wrapper_sw_winsys.c index 37c499b9485..b042d4a56c4 100644 --- a/src/gallium/winsys/sw/wrapper/wrapper_sw_winsys.c +++ b/src/gallium/winsys/sw/wrapper/wrapper_sw_winsys.c @@ -29,7 +29,7 @@ #include "pipe/p_format.h" #include "pipe/p_state.h" -#include "state_tracker/sw_winsys.h" +#include "frontend/sw_winsys.h" #include "util/u_memory.h" #include "util/u_inlines.h" diff --git a/src/gallium/winsys/sw/xlib/xlib_sw_winsys.c b/src/gallium/winsys/sw/xlib/xlib_sw_winsys.c index 8e97f0a24af..0eea71b7523 100644 --- a/src/gallium/winsys/sw/xlib/xlib_sw_winsys.c +++ b/src/gallium/winsys/sw/xlib/xlib_sw_winsys.c @@ -39,7 +39,7 @@ #include "util/u_math.h" #include "util/u_memory.h" -#include "state_tracker/xlibsw_api.h" +#include "frontend/xlibsw_api.h" #include "xlib_sw_winsys.h" #include diff --git a/src/gallium/winsys/virgl/drm/virgl_drm_winsys.c b/src/gallium/winsys/virgl/drm/virgl_drm_winsys.c index 7b20636ad20..b19bdf4b6f8 100644 --- a/src/gallium/winsys/virgl/drm/virgl_drm_winsys.c +++ b/src/gallium/winsys/virgl/drm/virgl_drm_winsys.c @@ -35,7 +35,7 @@ #include "util/u_hash_table.h" #include "util/u_inlines.h" #include "util/u_pointer.h" -#include "state_tracker/drm_driver.h" +#include "frontend/drm_driver.h" #include "virgl/virgl_screen.h" #include "virgl/virgl_public.h" diff --git a/src/gallium/winsys/virgl/vtest/virgl_vtest_winsys.c b/src/gallium/winsys/virgl/vtest/virgl_vtest_winsys.c index dbe3afe9f80..2f79909d540 100644 --- a/src/gallium/winsys/virgl/vtest/virgl_vtest_winsys.c +++ b/src/gallium/winsys/virgl/vtest/virgl_vtest_winsys.c @@ -26,7 +26,7 @@ #include "util/format/u_format.h" #include "util/u_inlines.h" #include "util/os_time.h" -#include "state_tracker/sw_winsys.h" +#include "frontend/sw_winsys.h" #include "os/os_mman.h" #include "virgl_vtest_winsys.h" diff --git a/src/mesa/state_tracker/st_cb_memoryobjects.c b/src/mesa/state_tracker/st_cb_memoryobjects.c index d81c7692c1f..b193eb37cb2 100644 --- a/src/mesa/state_tracker/st_cb_memoryobjects.c +++ b/src/mesa/state_tracker/st_cb_memoryobjects.c @@ -31,7 +31,7 @@ #include "st_cb_memoryobjects.h" #include "st_util.h" -#include "state_tracker/drm_driver.h" +#include "frontend/drm_driver.h" #include "pipe/p_context.h" #include "pipe/p_screen.h" diff --git a/src/mesa/state_tracker/st_cb_semaphoreobjects.c b/src/mesa/state_tracker/st_cb_semaphoreobjects.c index 7a32d9b138f..51288a87342 100644 --- a/src/mesa/state_tracker/st_cb_semaphoreobjects.c +++ b/src/mesa/state_tracker/st_cb_semaphoreobjects.c @@ -34,7 +34,7 @@ #include "st_cb_bufferobjects.h" #include "st_cb_semaphoreobjects.h" -#include "state_tracker/drm_driver.h" +#include "frontend/drm_driver.h" #include "pipe/p_context.h" #include "pipe/p_screen.h" diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h index a4a1ce5d4ad..31539d9db7d 100644 --- a/src/mesa/state_tracker/st_context.h +++ b/src/mesa/state_tracker/st_context.h @@ -30,7 +30,7 @@ #include "main/arrayobj.h" #include "main/mtypes.h" -#include "state_tracker/st_api.h" +#include "frontend/api.h" #include "main/fbobject.h" #include "state_tracker/st_atom.h" #include "util/u_helpers.h" diff --git a/src/mesa/state_tracker/st_vdpau.c b/src/mesa/state_tracker/st_vdpau.c index 56075457073..e519ce9a1d9 100644 --- a/src/mesa/state_tracker/st_vdpau.c +++ b/src/mesa/state_tracker/st_vdpau.c @@ -50,10 +50,10 @@ #include "st_format.h" #include "st_cb_flush.h" -#include "state_tracker/vdpau_interop.h" -#include "state_tracker/vdpau_dmabuf.h" -#include "state_tracker/vdpau_funcs.h" -#include "state_tracker/drm_driver.h" +#include "frontend/vdpau_interop.h" +#include "frontend/vdpau_dmabuf.h" +#include "frontend/vdpau_funcs.h" +#include "frontend/drm_driver.h" static struct pipe_resource * st_vdpau_video_surface_gallium(struct gl_context *ctx, const void *vdpSurface,