From 0402d388cb9803652c0f9a52ba7dcb6029fdd0b9 Mon Sep 17 00:00:00 2001 From: marha Date: Sat, 30 Apr 2011 15:25:48 +0000 Subject: Added extra needed files --- mesalib/src/gallium/auxiliary/util/dbghelp.h | 1265 +++++++++++++++ mesalib/src/gallium/auxiliary/util/u_atomic.h | 352 ++++ mesalib/src/gallium/auxiliary/util/u_bitmask.c | 328 ++++ mesalib/src/gallium/auxiliary/util/u_bitmask.h | 117 ++ mesalib/src/gallium/auxiliary/util/u_blit.c | 790 +++++++++ mesalib/src/gallium/auxiliary/util/u_blit.h | 98 ++ mesalib/src/gallium/auxiliary/util/u_blitter.c | 1036 ++++++++++++ mesalib/src/gallium/auxiliary/util/u_blitter.h | 338 ++++ mesalib/src/gallium/auxiliary/util/u_box.h | 80 + mesalib/src/gallium/auxiliary/util/u_cache.c | 351 ++++ mesalib/src/gallium/auxiliary/util/u_cache.h | 91 ++ mesalib/src/gallium/auxiliary/util/u_caps.c | 270 ++++ mesalib/src/gallium/auxiliary/util/u_caps.h | 71 + mesalib/src/gallium/auxiliary/util/u_clear.h | 59 + mesalib/src/gallium/auxiliary/util/u_cpu_detect.c | 343 ++++ mesalib/src/gallium/auxiliary/util/u_cpu_detect.h | 69 + mesalib/src/gallium/auxiliary/util/u_debug.c | 744 +++++++++ mesalib/src/gallium/auxiliary/util/u_debug.h | 431 +++++ .../src/gallium/auxiliary/util/u_debug_describe.c | 81 + .../src/gallium/auxiliary/util/u_debug_describe.h | 49 + .../src/gallium/auxiliary/util/u_debug_memory.c | 307 ++++ .../src/gallium/auxiliary/util/u_debug_refcnt.c | 191 +++ .../src/gallium/auxiliary/util/u_debug_refcnt.h | 63 + mesalib/src/gallium/auxiliary/util/u_debug_stack.c | 110 ++ mesalib/src/gallium/auxiliary/util/u_debug_stack.h | 65 + .../src/gallium/auxiliary/util/u_debug_symbol.c | 243 +++ .../src/gallium/auxiliary/util/u_debug_symbol.h | 58 + mesalib/src/gallium/auxiliary/util/u_dirty_flags.h | 32 + .../src/gallium/auxiliary/util/u_dirty_surfaces.h | 119 ++ mesalib/src/gallium/auxiliary/util/u_dl.c | 94 ++ mesalib/src/gallium/auxiliary/util/u_dl.h | 83 + mesalib/src/gallium/auxiliary/util/u_double_list.h | 141 ++ mesalib/src/gallium/auxiliary/util/u_draw.c | 99 ++ mesalib/src/gallium/auxiliary/util/u_draw.h | 158 ++ mesalib/src/gallium/auxiliary/util/u_draw_quad.c | 135 ++ mesalib/src/gallium/auxiliary/util/u_draw_quad.h | 61 + mesalib/src/gallium/auxiliary/util/u_dump.h | 179 +++ .../src/gallium/auxiliary/util/u_dump_defines.c | 336 ++++ mesalib/src/gallium/auxiliary/util/u_dump_state.c | 708 ++++++++ mesalib/src/gallium/auxiliary/util/u_dynarray.h | 114 ++ mesalib/src/gallium/auxiliary/util/u_fifo.h | 94 ++ mesalib/src/gallium/auxiliary/util/u_format.c | 392 +++++ mesalib/src/gallium/auxiliary/util/u_format.csv | 261 +++ mesalib/src/gallium/auxiliary/util/u_format.h | 822 ++++++++++ mesalib/src/gallium/auxiliary/util/u_format_latc.c | 328 ++++ mesalib/src/gallium/auxiliary/util/u_format_latc.h | 108 ++ .../src/gallium/auxiliary/util/u_format_other.c | 472 ++++++ .../src/gallium/auxiliary/util/u_format_other.h | 134 ++ .../src/gallium/auxiliary/util/u_format_pack.py | 670 ++++++++ .../src/gallium/auxiliary/util/u_format_parse.py | 291 ++++ .../gallium/auxiliary/util/u_format_r11g11b10f.h | 190 +++ .../src/gallium/auxiliary/util/u_format_rgb9e5.h | 164 ++ mesalib/src/gallium/auxiliary/util/u_format_rgtc.c | 464 ++++++ mesalib/src/gallium/auxiliary/util/u_format_rgtc.h | 114 ++ mesalib/src/gallium/auxiliary/util/u_format_s3tc.c | 728 +++++++++ mesalib/src/gallium/auxiliary/util/u_format_s3tc.h | 218 +++ mesalib/src/gallium/auxiliary/util/u_format_srgb.h | 106 ++ .../src/gallium/auxiliary/util/u_format_srgb.py | 100 ++ .../src/gallium/auxiliary/util/u_format_table.py | 197 +++ .../src/gallium/auxiliary/util/u_format_tests.c | 970 +++++++++++ .../src/gallium/auxiliary/util/u_format_tests.h | 71 + mesalib/src/gallium/auxiliary/util/u_format_yuv.c | 1047 ++++++++++++ mesalib/src/gallium/auxiliary/util/u_format_yuv.h | 223 +++ mesalib/src/gallium/auxiliary/util/u_format_zs.c | 973 +++++++++++ mesalib/src/gallium/auxiliary/util/u_format_zs.h | 212 +++ mesalib/src/gallium/auxiliary/util/u_framebuffer.c | 148 ++ mesalib/src/gallium/auxiliary/util/u_framebuffer.h | 54 + mesalib/src/gallium/auxiliary/util/u_gen_mipmap.c | 1688 ++++++++++++++++++++ mesalib/src/gallium/auxiliary/util/u_gen_mipmap.h | 70 + mesalib/src/gallium/auxiliary/util/u_half.h | 90 ++ mesalib/src/gallium/auxiliary/util/u_half.py | 179 +++ .../src/gallium/auxiliary/util/u_handle_table.c | 298 ++++ .../src/gallium/auxiliary/util/u_handle_table.h | 116 ++ mesalib/src/gallium/auxiliary/util/u_hash.c | 121 ++ mesalib/src/gallium/auxiliary/util/u_hash.h | 55 + mesalib/src/gallium/auxiliary/util/u_hash_table.c | 293 ++++ mesalib/src/gallium/auxiliary/util/u_hash_table.h | 96 ++ .../src/gallium/auxiliary/util/u_index_modify.c | 182 +++ .../src/gallium/auxiliary/util/u_index_modify.h | 68 + mesalib/src/gallium/auxiliary/util/u_init.h | 52 + mesalib/src/gallium/auxiliary/util/u_inlines.h | 459 ++++++ mesalib/src/gallium/auxiliary/util/u_keymap.c | 318 ++++ mesalib/src/gallium/auxiliary/util/u_keymap.h | 68 + mesalib/src/gallium/auxiliary/util/u_linear.c | 101 ++ mesalib/src/gallium/auxiliary/util/u_linear.h | 106 ++ mesalib/src/gallium/auxiliary/util/u_linkage.c | 149 ++ mesalib/src/gallium/auxiliary/util/u_linkage.h | 66 + mesalib/src/gallium/auxiliary/util/u_math.c | 73 + mesalib/src/gallium/auxiliary/util/u_math.h | 660 ++++++++ mesalib/src/gallium/auxiliary/util/u_memory.h | 100 ++ mesalib/src/gallium/auxiliary/util/u_mm.c | 296 ++++ mesalib/src/gallium/auxiliary/util/u_mm.h | 91 ++ mesalib/src/gallium/auxiliary/util/u_network.c | 188 +++ mesalib/src/gallium/auxiliary/util/u_network.h | 24 + mesalib/src/gallium/auxiliary/util/u_pack_color.h | 584 +++++++ mesalib/src/gallium/auxiliary/util/u_pointer.h | 130 ++ mesalib/src/gallium/auxiliary/util/u_prim.h | 234 +++ mesalib/src/gallium/auxiliary/util/u_pstipple.c | 434 +++++ mesalib/src/gallium/auxiliary/util/u_pstipple.h | 56 + mesalib/src/gallium/auxiliary/util/u_rect.c | 164 ++ mesalib/src/gallium/auxiliary/util/u_rect.h | 103 ++ mesalib/src/gallium/auxiliary/util/u_resource.c | 88 + mesalib/src/gallium/auxiliary/util/u_ringbuffer.c | 160 ++ mesalib/src/gallium/auxiliary/util/u_ringbuffer.h | 29 + mesalib/src/gallium/auxiliary/util/u_sampler.c | 103 ++ mesalib/src/gallium/auxiliary/util/u_sampler.h | 57 + mesalib/src/gallium/auxiliary/util/u_simple_list.h | 199 +++ .../src/gallium/auxiliary/util/u_simple_screen.h | 180 +++ .../src/gallium/auxiliary/util/u_simple_shaders.c | 243 +++ .../src/gallium/auxiliary/util/u_simple_shaders.h | 83 + mesalib/src/gallium/auxiliary/util/u_slab.c | 169 ++ mesalib/src/gallium/auxiliary/util/u_slab.h | 87 + mesalib/src/gallium/auxiliary/util/u_snprintf.c | 1497 +++++++++++++++++ mesalib/src/gallium/auxiliary/util/u_split_prim.h | 114 ++ mesalib/src/gallium/auxiliary/util/u_sse.h | 255 +++ mesalib/src/gallium/auxiliary/util/u_staging.c | 132 ++ mesalib/src/gallium/auxiliary/util/u_staging.h | 63 + mesalib/src/gallium/auxiliary/util/u_string.h | 220 +++ mesalib/src/gallium/auxiliary/util/u_surface.c | 371 +++++ mesalib/src/gallium/auxiliary/util/u_surface.h | 90 ++ mesalib/src/gallium/auxiliary/util/u_surfaces.c | 124 ++ mesalib/src/gallium/auxiliary/util/u_surfaces.h | 101 ++ mesalib/src/gallium/auxiliary/util/u_texture.c | 103 ++ mesalib/src/gallium/auxiliary/util/u_texture.h | 54 + mesalib/src/gallium/auxiliary/util/u_tile.c | 655 ++++++++ mesalib/src/gallium/auxiliary/util/u_tile.h | 126 ++ mesalib/src/gallium/auxiliary/util/u_time.h | 150 ++ mesalib/src/gallium/auxiliary/util/u_transfer.c | 114 ++ mesalib/src/gallium/auxiliary/util/u_transfer.h | 132 ++ mesalib/src/gallium/auxiliary/util/u_upload_mgr.c | 251 +++ mesalib/src/gallium/auxiliary/util/u_upload_mgr.h | 122 ++ mesalib/src/gallium/auxiliary/util/u_vbuf_mgr.c | 613 +++++++ mesalib/src/gallium/auxiliary/util/u_vbuf_mgr.h | 121 ++ 133 files changed, 34328 insertions(+) create mode 100644 mesalib/src/gallium/auxiliary/util/dbghelp.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_atomic.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_bitmask.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_bitmask.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_blit.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_blit.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_blitter.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_blitter.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_box.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_cache.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_cache.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_caps.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_caps.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_clear.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_cpu_detect.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_cpu_detect.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_debug.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_debug.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_debug_describe.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_debug_describe.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_debug_memory.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_debug_refcnt.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_debug_refcnt.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_debug_stack.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_debug_stack.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_debug_symbol.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_debug_symbol.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_dirty_flags.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_dirty_surfaces.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_dl.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_dl.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_double_list.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_draw.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_draw.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_draw_quad.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_draw_quad.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_dump.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_dump_defines.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_dump_state.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_dynarray.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_fifo.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_format.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_format.csv create mode 100644 mesalib/src/gallium/auxiliary/util/u_format.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_format_latc.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_format_latc.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_format_other.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_format_other.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_format_pack.py create mode 100644 mesalib/src/gallium/auxiliary/util/u_format_parse.py create mode 100644 mesalib/src/gallium/auxiliary/util/u_format_r11g11b10f.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_format_rgb9e5.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_format_rgtc.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_format_rgtc.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_format_s3tc.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_format_s3tc.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_format_srgb.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_format_srgb.py create mode 100644 mesalib/src/gallium/auxiliary/util/u_format_table.py create mode 100644 mesalib/src/gallium/auxiliary/util/u_format_tests.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_format_tests.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_format_yuv.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_format_yuv.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_format_zs.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_format_zs.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_framebuffer.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_framebuffer.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_gen_mipmap.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_gen_mipmap.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_half.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_half.py create mode 100644 mesalib/src/gallium/auxiliary/util/u_handle_table.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_handle_table.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_hash.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_hash.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_hash_table.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_hash_table.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_index_modify.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_index_modify.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_init.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_inlines.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_keymap.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_keymap.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_linear.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_linear.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_linkage.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_linkage.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_math.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_math.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_memory.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_mm.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_mm.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_network.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_network.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_pack_color.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_pointer.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_prim.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_pstipple.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_pstipple.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_rect.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_rect.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_resource.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_ringbuffer.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_ringbuffer.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_sampler.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_sampler.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_simple_list.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_simple_screen.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_simple_shaders.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_simple_shaders.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_slab.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_slab.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_snprintf.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_split_prim.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_sse.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_staging.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_staging.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_string.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_surface.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_surface.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_surfaces.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_surfaces.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_texture.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_texture.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_tile.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_tile.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_time.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_transfer.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_transfer.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_upload_mgr.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_upload_mgr.h create mode 100644 mesalib/src/gallium/auxiliary/util/u_vbuf_mgr.c create mode 100644 mesalib/src/gallium/auxiliary/util/u_vbuf_mgr.h (limited to 'mesalib/src/gallium/auxiliary/util') diff --git a/mesalib/src/gallium/auxiliary/util/dbghelp.h b/mesalib/src/gallium/auxiliary/util/dbghelp.h new file mode 100644 index 000000000..da5e3ad08 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/dbghelp.h @@ -0,0 +1,1265 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the w64 mingw-runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#ifndef _DBGHELP_ +#define _DBGHELP_ + +#ifdef _WIN64 +#ifndef _IMAGEHLP64 +#define _IMAGEHLP64 +#endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define IMAGEAPI DECLSPEC_IMPORT WINAPI +#define DBHLP_DEPRECIATED __declspec(deprecated) + +#define DBHLPAPI IMAGEAPI + +#define IMAGE_SEPARATION (64*1024) + + typedef struct _LOADED_IMAGE { + PSTR ModuleName; + HANDLE hFile; + PUCHAR MappedAddress; +#ifdef _IMAGEHLP64 + PIMAGE_NT_HEADERS64 FileHeader; +#else + PIMAGE_NT_HEADERS32 FileHeader; +#endif + PIMAGE_SECTION_HEADER LastRvaSection; + ULONG NumberOfSections; + PIMAGE_SECTION_HEADER Sections; + ULONG Characteristics; + BOOLEAN fSystemImage; + BOOLEAN fDOSImage; + LIST_ENTRY Links; + ULONG SizeOfImage; + } LOADED_IMAGE,*PLOADED_IMAGE; + +#define MAX_SYM_NAME 2000 + + typedef BOOL (CALLBACK *PFIND_DEBUG_FILE_CALLBACK)(HANDLE FileHandle,PSTR FileName,PVOID CallerData); + typedef BOOL (CALLBACK *PFINDFILEINPATHCALLBACK)(PSTR filename,PVOID context); + typedef BOOL (CALLBACK *PFIND_EXE_FILE_CALLBACK)(HANDLE FileHandle,PSTR FileName,PVOID CallerData); + + typedef BOOL (WINAPI *PSYMBOLSERVERPROC)(LPCSTR,LPCSTR,PVOID,DWORD,DWORD,LPSTR); + typedef BOOL (WINAPI *PSYMBOLSERVEROPENPROC)(VOID); + typedef BOOL (WINAPI *PSYMBOLSERVERCLOSEPROC)(VOID); + typedef BOOL (WINAPI *PSYMBOLSERVERSETOPTIONSPROC)(UINT_PTR,ULONG64); + typedef BOOL (CALLBACK WINAPI *PSYMBOLSERVERCALLBACKPROC)(UINT_PTR action,ULONG64 data,ULONG64 context); + typedef UINT_PTR (WINAPI *PSYMBOLSERVERGETOPTIONSPROC)(); + typedef BOOL (WINAPI *PSYMBOLSERVERPINGPROC)(LPCSTR); + + HANDLE IMAGEAPI FindDebugInfoFile(PSTR FileName,PSTR SymbolPath,PSTR DebugFilePath); + HANDLE IMAGEAPI FindDebugInfoFileEx(PSTR FileName,PSTR SymbolPath,PSTR DebugFilePath,PFIND_DEBUG_FILE_CALLBACK Callback,PVOID CallerData); + BOOL IMAGEAPI SymFindFileInPath(HANDLE hprocess,LPSTR SearchPath,LPSTR FileName,PVOID id,DWORD two,DWORD three,DWORD flags,LPSTR FoundFile,PFINDFILEINPATHCALLBACK callback,PVOID context); + HANDLE IMAGEAPI FindExecutableImage(PSTR FileName,PSTR SymbolPath,PSTR ImageFilePath); + HANDLE IMAGEAPI FindExecutableImageEx(PSTR FileName,PSTR SymbolPath,PSTR ImageFilePath,PFIND_EXE_FILE_CALLBACK Callback,PVOID CallerData); + PIMAGE_NT_HEADERS IMAGEAPI ImageNtHeader(PVOID Base); + PVOID IMAGEAPI ImageDirectoryEntryToDataEx(PVOID Base,BOOLEAN MappedAsImage,USHORT DirectoryEntry,PULONG Size,PIMAGE_SECTION_HEADER *FoundHeader); + PVOID IMAGEAPI ImageDirectoryEntryToData(PVOID Base,BOOLEAN MappedAsImage,USHORT DirectoryEntry,PULONG Size); + PIMAGE_SECTION_HEADER IMAGEAPI ImageRvaToSection(PIMAGE_NT_HEADERS NtHeaders,PVOID Base,ULONG Rva); + PVOID IMAGEAPI ImageRvaToVa(PIMAGE_NT_HEADERS NtHeaders,PVOID Base,ULONG Rva,PIMAGE_SECTION_HEADER *LastRvaSection); + +#define SSRVOPT_CALLBACK 0x0001 +#define SSRVOPT_DWORD 0x0002 +#define SSRVOPT_DWORDPTR 0x0004 +#define SSRVOPT_GUIDPTR 0x0008 +#define SSRVOPT_OLDGUIDPTR 0x0010 +#define SSRVOPT_UNATTENDED 0x0020 +#define SSRVOPT_NOCOPY 0x0040 +#define SSRVOPT_PARENTWIN 0x0080 +#define SSRVOPT_PARAMTYPE 0x0100 +#define SSRVOPT_SECURE 0x0200 +#define SSRVOPT_TRACE 0x0400 +#define SSRVOPT_SETCONTEXT 0x0800 +#define SSRVOPT_PROXY 0x1000 +#define SSRVOPT_DOWNSTREAM_STORE 0x2000 +#define SSRVOPT_RESET ((ULONG_PTR)-1) + +#define SSRVACTION_TRACE 1 +#define SSRVACTION_QUERYCANCEL 2 +#define SSRVACTION_EVENT 3 + +#ifndef _WIN64 + + typedef struct _IMAGE_DEBUG_INFORMATION { + LIST_ENTRY List; + DWORD ReservedSize; + PVOID ReservedMappedBase; + USHORT ReservedMachine; + USHORT ReservedCharacteristics; + DWORD ReservedCheckSum; + DWORD ImageBase; + DWORD SizeOfImage; + DWORD ReservedNumberOfSections; + PIMAGE_SECTION_HEADER ReservedSections; + DWORD ReservedExportedNamesSize; + PSTR ReservedExportedNames; + DWORD ReservedNumberOfFunctionTableEntries; + PIMAGE_FUNCTION_ENTRY ReservedFunctionTableEntries; + DWORD ReservedLowestFunctionStartingAddress; + DWORD ReservedHighestFunctionEndingAddress; + DWORD ReservedNumberOfFpoTableEntries; + PFPO_DATA ReservedFpoTableEntries; + DWORD SizeOfCoffSymbols; + PIMAGE_COFF_SYMBOLS_HEADER CoffSymbols; + DWORD ReservedSizeOfCodeViewSymbols; + PVOID ReservedCodeViewSymbols; + PSTR ImageFilePath; + PSTR ImageFileName; + PSTR ReservedDebugFilePath; + DWORD ReservedTimeDateStamp; + BOOL ReservedRomImage; + PIMAGE_DEBUG_DIRECTORY ReservedDebugDirectory; + DWORD ReservedNumberOfDebugDirectories; + DWORD ReservedOriginalFunctionTableBaseAddress; + DWORD Reserved[2 ]; + } IMAGE_DEBUG_INFORMATION,*PIMAGE_DEBUG_INFORMATION; + + PIMAGE_DEBUG_INFORMATION IMAGEAPI MapDebugInformation(HANDLE FileHandle,PSTR FileName,PSTR SymbolPath,DWORD ImageBase); + BOOL IMAGEAPI UnmapDebugInformation(PIMAGE_DEBUG_INFORMATION DebugInfo); +#endif + + typedef BOOL (CALLBACK *PENUMDIRTREE_CALLBACK)(LPCSTR FilePath,PVOID CallerData); + + BOOL IMAGEAPI SearchTreeForFile(PSTR RootPath,PSTR InputPathName,PSTR OutputPathBuffer); + BOOL IMAGEAPI EnumDirTree(HANDLE hProcess,PSTR RootPath,PSTR InputPathName,PSTR OutputPathBuffer,PENUMDIRTREE_CALLBACK Callback,PVOID CallbackData); + BOOL IMAGEAPI MakeSureDirectoryPathExists(PCSTR DirPath); + +#define UNDNAME_COMPLETE (0x0000) +#define UNDNAME_NO_LEADING_UNDERSCORES (0x0001) +#define UNDNAME_NO_MS_KEYWORDS (0x0002) +#define UNDNAME_NO_FUNCTION_RETURNS (0x0004) +#define UNDNAME_NO_ALLOCATION_MODEL (0x0008) +#define UNDNAME_NO_ALLOCATION_LANGUAGE (0x0010) +#define UNDNAME_NO_MS_THISTYPE (0x0020) +#define UNDNAME_NO_CV_THISTYPE (0x0040) +#define UNDNAME_NO_THISTYPE (0x0060) +#define UNDNAME_NO_ACCESS_SPECIFIERS (0x0080) +#define UNDNAME_NO_THROW_SIGNATURES (0x0100) +#define UNDNAME_NO_MEMBER_TYPE (0x0200) +#define UNDNAME_NO_RETURN_UDT_MODEL (0x0400) +#define UNDNAME_32_BIT_DECODE (0x0800) +#define UNDNAME_NAME_ONLY (0x1000) +#define UNDNAME_NO_ARGUMENTS (0x2000) +#define UNDNAME_NO_SPECIAL_SYMS (0x4000) + + DWORD IMAGEAPI WINAPI UnDecorateSymbolName(PCSTR DecoratedName,PSTR UnDecoratedName,DWORD UndecoratedLength,DWORD Flags); + +#define DBHHEADER_DEBUGDIRS 0x1 + + typedef struct _MODLOAD_DATA { + DWORD ssize; + DWORD ssig; + PVOID data; + DWORD size; + DWORD flags; + } MODLOAD_DATA,*PMODLOAD_DATA; + + typedef enum { + AddrMode1616,AddrMode1632,AddrModeReal,AddrModeFlat + } ADDRESS_MODE; + + typedef struct _tagADDRESS64 { + DWORD64 Offset; + WORD Segment; + ADDRESS_MODE Mode; + } ADDRESS64,*LPADDRESS64; + +#ifdef _IMAGEHLP64 +#define ADDRESS ADDRESS64 +#define LPADDRESS LPADDRESS64 +#else + typedef struct _tagADDRESS { + DWORD Offset; + WORD Segment; + ADDRESS_MODE Mode; + } ADDRESS,*LPADDRESS; + + static __inline void Address32To64(LPADDRESS a32,LPADDRESS64 a64) { + a64->Offset = (ULONG64)(LONG64)(LONG)a32->Offset; + a64->Segment = a32->Segment; + a64->Mode = a32->Mode; + } + + static __inline void Address64To32(LPADDRESS64 a64,LPADDRESS a32) { + a32->Offset = (ULONG)a64->Offset; + a32->Segment = a64->Segment; + a32->Mode = a64->Mode; + } +#endif + + typedef struct _KDHELP64 { + DWORD64 Thread; + DWORD ThCallbackStack; + DWORD ThCallbackBStore; + DWORD NextCallback; + DWORD FramePointer; + DWORD64 KiCallUserMode; + DWORD64 KeUserCallbackDispatcher; + DWORD64 SystemRangeStart; + DWORD64 Reserved[8]; + } KDHELP64,*PKDHELP64; + +#ifdef _IMAGEHLP64 +#define KDHELP KDHELP64 +#define PKDHELP PKDHELP64 +#else + typedef struct _KDHELP { + DWORD Thread; + DWORD ThCallbackStack; + DWORD NextCallback; + DWORD FramePointer; + DWORD KiCallUserMode; + DWORD KeUserCallbackDispatcher; + DWORD SystemRangeStart; + DWORD ThCallbackBStore; + DWORD Reserved[8]; + } KDHELP,*PKDHELP; + + static __inline void KdHelp32To64(PKDHELP p32,PKDHELP64 p64) { + p64->Thread = p32->Thread; + p64->ThCallbackStack = p32->ThCallbackStack; + p64->NextCallback = p32->NextCallback; + p64->FramePointer = p32->FramePointer; + p64->KiCallUserMode = p32->KiCallUserMode; + p64->KeUserCallbackDispatcher = p32->KeUserCallbackDispatcher; + p64->SystemRangeStart = p32->SystemRangeStart; + } +#endif + + typedef struct _tagSTACKFRAME64 { + ADDRESS64 AddrPC; + ADDRESS64 AddrReturn; + ADDRESS64 AddrFrame; + ADDRESS64 AddrStack; + ADDRESS64 AddrBStore; + PVOID FuncTableEntry; + DWORD64 Params[4]; + BOOL Far; + BOOL Virtual; + DWORD64 Reserved[3]; + KDHELP64 KdHelp; + } STACKFRAME64,*LPSTACKFRAME64; + +#ifdef _IMAGEHLP64 +#define STACKFRAME STACKFRAME64 +#define LPSTACKFRAME LPSTACKFRAME64 +#else + typedef struct _tagSTACKFRAME { + ADDRESS AddrPC; + ADDRESS AddrReturn; + ADDRESS AddrFrame; + ADDRESS AddrStack; + PVOID FuncTableEntry; + DWORD Params[4]; + BOOL Far; + BOOL Virtual; + DWORD Reserved[3]; + KDHELP KdHelp; + ADDRESS AddrBStore; + } STACKFRAME,*LPSTACKFRAME; +#endif + + typedef BOOL (WINAPI *PREAD_PROCESS_MEMORY_ROUTINE64)(HANDLE hProcess,DWORD64 qwBaseAddress,PVOID lpBuffer,DWORD nSize,LPDWORD lpNumberOfBytesRead); + typedef PVOID (WINAPI *PFUNCTION_TABLE_ACCESS_ROUTINE64)(HANDLE hProcess,DWORD64 AddrBase); + typedef DWORD64 (WINAPI *PGET_MODULE_BASE_ROUTINE64)(HANDLE hProcess,DWORD64 Address); + typedef DWORD64 (WINAPI *PTRANSLATE_ADDRESS_ROUTINE64)(HANDLE hProcess,HANDLE hThread,LPADDRESS64 lpaddr); + + BOOL IMAGEAPI StackWalk64(DWORD MachineType,HANDLE hProcess,HANDLE hThread,LPSTACKFRAME64 StackFrame,PVOID ContextRecord,PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress); + +#ifdef _IMAGEHLP64 +#define PREAD_PROCESS_MEMORY_ROUTINE PREAD_PROCESS_MEMORY_ROUTINE64 +#define PFUNCTION_TABLE_ACCESS_ROUTINE PFUNCTION_TABLE_ACCESS_ROUTINE64 +#define PGET_MODULE_BASE_ROUTINE PGET_MODULE_BASE_ROUTINE64 +#define PTRANSLATE_ADDRESS_ROUTINE PTRANSLATE_ADDRESS_ROUTINE64 +#define StackWalk StackWalk64 +#else + typedef BOOL (WINAPI *PREAD_PROCESS_MEMORY_ROUTINE)(HANDLE hProcess,DWORD lpBaseAddress,PVOID lpBuffer,DWORD nSize,PDWORD lpNumberOfBytesRead); + typedef PVOID (WINAPI *PFUNCTION_TABLE_ACCESS_ROUTINE)(HANDLE hProcess,DWORD AddrBase); + typedef DWORD (WINAPI *PGET_MODULE_BASE_ROUTINE)(HANDLE hProcess,DWORD Address); + typedef DWORD (WINAPI *PTRANSLATE_ADDRESS_ROUTINE)(HANDLE hProcess,HANDLE hThread,LPADDRESS lpaddr); + + BOOL IMAGEAPI StackWalk(DWORD MachineType,HANDLE hProcess,HANDLE hThread,LPSTACKFRAME StackFrame,PVOID ContextRecord,PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine,PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine,PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine,PTRANSLATE_ADDRESS_ROUTINE TranslateAddress); +#endif + +#define API_VERSION_NUMBER 9 + + typedef struct API_VERSION { + USHORT MajorVersion; + USHORT MinorVersion; + USHORT Revision; + USHORT Reserved; + } API_VERSION,*LPAPI_VERSION; + + LPAPI_VERSION IMAGEAPI ImagehlpApiVersion(VOID); + LPAPI_VERSION IMAGEAPI ImagehlpApiVersionEx(LPAPI_VERSION AppVersion); + DWORD IMAGEAPI GetTimestampForLoadedLibrary(HMODULE Module); + + typedef BOOL (CALLBACK *PSYM_ENUMMODULES_CALLBACK64)(PSTR ModuleName,DWORD64 BaseOfDll,PVOID UserContext); + typedef BOOL (CALLBACK *PSYM_ENUMSYMBOLS_CALLBACK64)(PSTR SymbolName,DWORD64 SymbolAddress,ULONG SymbolSize,PVOID UserContext); + typedef BOOL (CALLBACK *PSYM_ENUMSYMBOLS_CALLBACK64W)(PWSTR SymbolName,DWORD64 SymbolAddress,ULONG SymbolSize,PVOID UserContext); + typedef BOOL (CALLBACK *PENUMLOADED_MODULES_CALLBACK64)(PSTR ModuleName,DWORD64 ModuleBase,ULONG ModuleSize,PVOID UserContext); + typedef BOOL (CALLBACK *PSYMBOL_REGISTERED_CALLBACK64)(HANDLE hProcess,ULONG ActionCode,ULONG64 CallbackData,ULONG64 UserContext); + typedef PVOID (CALLBACK *PSYMBOL_FUNCENTRY_CALLBACK)(HANDLE hProcess,DWORD AddrBase,PVOID UserContext); + typedef PVOID (CALLBACK *PSYMBOL_FUNCENTRY_CALLBACK64)(HANDLE hProcess,ULONG64 AddrBase,ULONG64 UserContext); + +#ifdef _IMAGEHLP64 +#define PSYM_ENUMMODULES_CALLBACK PSYM_ENUMMODULES_CALLBACK64 +#define PSYM_ENUMSYMBOLS_CALLBACK PSYM_ENUMSYMBOLS_CALLBACK64 +#define PSYM_ENUMSYMBOLS_CALLBACKW PSYM_ENUMSYMBOLS_CALLBACK64W +#define PENUMLOADED_MODULES_CALLBACK PENUMLOADED_MODULES_CALLBACK64 +#define PSYMBOL_REGISTERED_CALLBACK PSYMBOL_REGISTERED_CALLBACK64 +#define PSYMBOL_FUNCENTRY_CALLBACK PSYMBOL_FUNCENTRY_CALLBACK64 +#else + typedef BOOL (CALLBACK *PSYM_ENUMMODULES_CALLBACK)(PSTR ModuleName,ULONG BaseOfDll,PVOID UserContext); + typedef BOOL (CALLBACK *PSYM_ENUMSYMBOLS_CALLBACK)(PSTR SymbolName,ULONG SymbolAddress,ULONG SymbolSize,PVOID UserContext); + typedef BOOL (CALLBACK *PSYM_ENUMSYMBOLS_CALLBACKW)(PWSTR SymbolName,ULONG SymbolAddress,ULONG SymbolSize,PVOID UserContext); + typedef BOOL (CALLBACK *PENUMLOADED_MODULES_CALLBACK)(PSTR ModuleName,ULONG ModuleBase,ULONG ModuleSize,PVOID UserContext); + typedef BOOL (CALLBACK *PSYMBOL_REGISTERED_CALLBACK)(HANDLE hProcess,ULONG ActionCode,PVOID CallbackData,PVOID UserContext); +#endif + +#define SYMFLAG_VALUEPRESENT 0x00000001 +#define SYMFLAG_REGISTER 0x00000008 +#define SYMFLAG_REGREL 0x00000010 +#define SYMFLAG_FRAMEREL 0x00000020 +#define SYMFLAG_PARAMETER 0x00000040 +#define SYMFLAG_LOCAL 0x00000080 +#define SYMFLAG_CONSTANT 0x00000100 +#define SYMFLAG_EXPORT 0x00000200 +#define SYMFLAG_FORWARDER 0x00000400 +#define SYMFLAG_FUNCTION 0x00000800 +#define SYMFLAG_VIRTUAL 0x00001000 +#define SYMFLAG_THUNK 0x00002000 +#define SYMFLAG_TLSREL 0x00004000 + + typedef enum { + SymNone = 0,SymCoff,SymCv,SymPdb,SymExport,SymDeferred,SymSym,SymDia,SymVirtual,NumSymTypes + } SYM_TYPE; + + typedef struct _IMAGEHLP_SYMBOL64 { + DWORD SizeOfStruct; + DWORD64 Address; + DWORD Size; + DWORD Flags; + DWORD MaxNameLength; + CHAR Name[1]; + } IMAGEHLP_SYMBOL64,*PIMAGEHLP_SYMBOL64; + + typedef struct _IMAGEHLP_SYMBOL64_PACKAGE { + IMAGEHLP_SYMBOL64 sym; + CHAR name[MAX_SYM_NAME + 1]; + } IMAGEHLP_SYMBOL64_PACKAGE,*PIMAGEHLP_SYMBOL64_PACKAGE; + +#ifdef _IMAGEHLP64 + +#define IMAGEHLP_SYMBOL IMAGEHLP_SYMBOL64 +#define PIMAGEHLP_SYMBOL PIMAGEHLP_SYMBOL64 +#define IMAGEHLP_SYMBOL_PACKAGE IMAGEHLP_SYMBOL64_PACKAGE +#define PIMAGEHLP_SYMBOL_PACKAGE PIMAGEHLP_SYMBOL64_PACKAGE +#else + + typedef struct _IMAGEHLP_SYMBOL { + DWORD SizeOfStruct; + DWORD Address; + DWORD Size; + DWORD Flags; + DWORD MaxNameLength; + CHAR Name[1]; + } IMAGEHLP_SYMBOL,*PIMAGEHLP_SYMBOL; + + typedef struct _IMAGEHLP_SYMBOL_PACKAGE { + IMAGEHLP_SYMBOL sym; + CHAR name[MAX_SYM_NAME + 1]; + } IMAGEHLP_SYMBOL_PACKAGE,*PIMAGEHLP_SYMBOL_PACKAGE; +#endif + + typedef struct _IMAGEHLP_MODULE64 { + DWORD SizeOfStruct; + DWORD64 BaseOfImage; + DWORD ImageSize; + DWORD TimeDateStamp; + DWORD CheckSum; + DWORD NumSyms; + SYM_TYPE SymType; + CHAR ModuleName[32]; + CHAR ImageName[256]; + CHAR LoadedImageName[256]; + CHAR LoadedPdbName[256]; + DWORD CVSig; + CHAR CVData[MAX_PATH*3]; + DWORD PdbSig; + GUID PdbSig70; + DWORD PdbAge; + BOOL PdbUnmatched; + BOOL DbgUnmatched; + BOOL LineNumbers; + BOOL GlobalSymbols; + BOOL TypeInfo; + } IMAGEHLP_MODULE64,*PIMAGEHLP_MODULE64; + + typedef struct _IMAGEHLP_MODULE64W { + DWORD SizeOfStruct; + DWORD64 BaseOfImage; + DWORD ImageSize; + DWORD TimeDateStamp; + DWORD CheckSum; + DWORD NumSyms; + SYM_TYPE SymType; + WCHAR ModuleName[32]; + WCHAR ImageName[256]; + WCHAR LoadedImageName[256]; + WCHAR LoadedPdbName[256]; + DWORD CVSig; + WCHAR CVData[MAX_PATH*3]; + DWORD PdbSig; + GUID PdbSig70; + DWORD PdbAge; + BOOL PdbUnmatched; + BOOL DbgUnmatched; + BOOL LineNumbers; + BOOL GlobalSymbols; + BOOL TypeInfo; + } IMAGEHLP_MODULEW64,*PIMAGEHLP_MODULEW64; + +#ifdef _IMAGEHLP64 +#define IMAGEHLP_MODULE IMAGEHLP_MODULE64 +#define PIMAGEHLP_MODULE PIMAGEHLP_MODULE64 +#define IMAGEHLP_MODULEW IMAGEHLP_MODULEW64 +#define PIMAGEHLP_MODULEW PIMAGEHLP_MODULEW64 +#else + typedef struct _IMAGEHLP_MODULE { + DWORD SizeOfStruct; + DWORD BaseOfImage; + DWORD ImageSize; + DWORD TimeDateStamp; + DWORD CheckSum; + DWORD NumSyms; + SYM_TYPE SymType; + CHAR ModuleName[32]; + CHAR ImageName[256]; + CHAR LoadedImageName[256]; + } IMAGEHLP_MODULE,*PIMAGEHLP_MODULE; + + typedef struct _IMAGEHLP_MODULEW { + DWORD SizeOfStruct; + DWORD BaseOfImage; + DWORD ImageSize; + DWORD TimeDateStamp; + DWORD CheckSum; + DWORD NumSyms; + SYM_TYPE SymType; + WCHAR ModuleName[32]; + WCHAR ImageName[256]; + WCHAR LoadedImageName[256]; + } IMAGEHLP_MODULEW,*PIMAGEHLP_MODULEW; +#endif + + typedef struct _IMAGEHLP_LINE64 { + DWORD SizeOfStruct; + PVOID Key; + DWORD LineNumber; + PCHAR FileName; + DWORD64 Address; + } IMAGEHLP_LINE64,*PIMAGEHLP_LINE64; + +#ifdef _IMAGEHLP64 +#define IMAGEHLP_LINE IMAGEHLP_LINE64 +#define PIMAGEHLP_LINE PIMAGEHLP_LINE64 +#else + typedef struct _IMAGEHLP_LINE { + DWORD SizeOfStruct; + PVOID Key; + DWORD LineNumber; + PCHAR FileName; + DWORD Address; + } IMAGEHLP_LINE,*PIMAGEHLP_LINE; +#endif + + typedef struct _SOURCEFILE { + DWORD64 ModBase; + PCHAR FileName; + } SOURCEFILE,*PSOURCEFILE; + +#define CBA_DEFERRED_SYMBOL_LOAD_START 0x00000001 +#define CBA_DEFERRED_SYMBOL_LOAD_COMPLETE 0x00000002 +#define CBA_DEFERRED_SYMBOL_LOAD_FAILURE 0x00000003 +#define CBA_SYMBOLS_UNLOADED 0x00000004 +#define CBA_DUPLICATE_SYMBOL 0x00000005 +#define CBA_READ_MEMORY 0x00000006 +#define CBA_DEFERRED_SYMBOL_LOAD_CANCEL 0x00000007 +#define CBA_SET_OPTIONS 0x00000008 +#define CBA_EVENT 0x00000010 +#define CBA_DEFERRED_SYMBOL_LOAD_PARTIAL 0x00000020 +#define CBA_DEBUG_INFO 0x10000000 + + typedef struct _IMAGEHLP_CBA_READ_MEMORY { + DWORD64 addr; + PVOID buf; + DWORD bytes; + DWORD *bytesread; + } IMAGEHLP_CBA_READ_MEMORY,*PIMAGEHLP_CBA_READ_MEMORY; + + enum { + sevInfo = 0,sevProblem,sevAttn,sevFatal,sevMax + }; + + typedef struct _IMAGEHLP_CBA_EVENT { + DWORD severity; + DWORD code; + PCHAR desc; + PVOID object; + } IMAGEHLP_CBA_EVENT,*PIMAGEHLP_CBA_EVENT; + + typedef struct _IMAGEHLP_DEFERRED_SYMBOL_LOAD64 { + DWORD SizeOfStruct; + DWORD64 BaseOfImage; + DWORD CheckSum; + DWORD TimeDateStamp; + CHAR FileName[MAX_PATH]; + BOOLEAN Reparse; + HANDLE hFile; + DWORD Flags; + } IMAGEHLP_DEFERRED_SYMBOL_LOAD64,*PIMAGEHLP_DEFERRED_SYMBOL_LOAD64; + +#define DSLFLAG_MISMATCHED_PDB 0x1 +#define DSLFLAG_MISMATCHED_DBG 0x2 + +#ifdef _IMAGEHLP64 +#define IMAGEHLP_DEFERRED_SYMBOL_LOAD IMAGEHLP_DEFERRED_SYMBOL_LOAD64 +#define PIMAGEHLP_DEFERRED_SYMBOL_LOAD PIMAGEHLP_DEFERRED_SYMBOL_LOAD64 +#else + typedef struct _IMAGEHLP_DEFERRED_SYMBOL_LOAD { + DWORD SizeOfStruct; + DWORD BaseOfImage; + DWORD CheckSum; + DWORD TimeDateStamp; + CHAR FileName[MAX_PATH]; + BOOLEAN Reparse; + HANDLE hFile; + } IMAGEHLP_DEFERRED_SYMBOL_LOAD,*PIMAGEHLP_DEFERRED_SYMBOL_LOAD; +#endif + + typedef struct _IMAGEHLP_DUPLICATE_SYMBOL64 { + DWORD SizeOfStruct; + DWORD NumberOfDups; + PIMAGEHLP_SYMBOL64 Symbol; + DWORD SelectedSymbol; + } IMAGEHLP_DUPLICATE_SYMBOL64,*PIMAGEHLP_DUPLICATE_SYMBOL64; + +#ifdef _IMAGEHLP64 +#define IMAGEHLP_DUPLICATE_SYMBOL IMAGEHLP_DUPLICATE_SYMBOL64 +#define PIMAGEHLP_DUPLICATE_SYMBOL PIMAGEHLP_DUPLICATE_SYMBOL64 +#else + typedef struct _IMAGEHLP_DUPLICATE_SYMBOL { + DWORD SizeOfStruct; + DWORD NumberOfDups; + PIMAGEHLP_SYMBOL Symbol; + DWORD SelectedSymbol; + } IMAGEHLP_DUPLICATE_SYMBOL,*PIMAGEHLP_DUPLICATE_SYMBOL; +#endif + + BOOL IMAGEAPI SymSetParentWindow(HWND hwnd); + PCHAR IMAGEAPI SymSetHomeDirectory(PCSTR dir); + PCHAR IMAGEAPI SymGetHomeDirectory(DWORD type,PSTR dir,size_t size); + + enum { + hdBase = 0,hdSym,hdSrc,hdMax + }; + +#define SYMOPT_CASE_INSENSITIVE 0x00000001 +#define SYMOPT_UNDNAME 0x00000002 +#define SYMOPT_DEFERRED_LOADS 0x00000004 +#define SYMOPT_NO_CPP 0x00000008 +#define SYMOPT_LOAD_LINES 0x00000010 +#define SYMOPT_OMAP_FIND_NEAREST 0x00000020 +#define SYMOPT_LOAD_ANYTHING 0x00000040 +#define SYMOPT_IGNORE_CVREC 0x00000080 +#define SYMOPT_NO_UNQUALIFIED_LOADS 0x00000100 +#define SYMOPT_FAIL_CRITICAL_ERRORS 0x00000200 +#define SYMOPT_EXACT_SYMBOLS 0x00000400 +#define SYMOPT_ALLOW_ABSOLUTE_SYMBOLS 0x00000800 +#define SYMOPT_IGNORE_NT_SYMPATH 0x00001000 +#define SYMOPT_INCLUDE_32BIT_MODULES 0x00002000 +#define SYMOPT_PUBLICS_ONLY 0x00004000 +#define SYMOPT_NO_PUBLICS 0x00008000 +#define SYMOPT_AUTO_PUBLICS 0x00010000 +#define SYMOPT_NO_IMAGE_SEARCH 0x00020000 +#define SYMOPT_SECURE 0x00040000 +#define SYMOPT_NO_PROMPTS 0x00080000 + +#define SYMOPT_DEBUG 0x80000000 + + DWORD IMAGEAPI SymSetOptions(DWORD SymOptions); + DWORD IMAGEAPI SymGetOptions(VOID); + BOOL IMAGEAPI SymCleanup(HANDLE hProcess); + BOOL IMAGEAPI SymMatchString(LPSTR string,LPSTR expression,BOOL fCase); + + typedef BOOL (CALLBACK *PSYM_ENUMSOURCFILES_CALLBACK)(PSOURCEFILE pSourceFile,PVOID UserContext); + + BOOL IMAGEAPI SymEnumSourceFiles(HANDLE hProcess,ULONG64 ModBase,LPSTR Mask,PSYM_ENUMSOURCFILES_CALLBACK cbSrcFiles,PVOID UserContext); + BOOL IMAGEAPI SymEnumerateModules64(HANDLE hProcess,PSYM_ENUMMODULES_CALLBACK64 EnumModulesCallback,PVOID UserContext); + +#ifdef _IMAGEHLP64 +#define SymEnumerateModules SymEnumerateModules64 +#else + BOOL IMAGEAPI SymEnumerateModules(HANDLE hProcess,PSYM_ENUMMODULES_CALLBACK EnumModulesCallback,PVOID UserContext); +#endif + + BOOL IMAGEAPI SymEnumerateSymbols64(HANDLE hProcess,DWORD64 BaseOfDll,PSYM_ENUMSYMBOLS_CALLBACK64 EnumSymbolsCallback,PVOID UserContext); + BOOL IMAGEAPI SymEnumerateSymbolsW64(HANDLE hProcess,DWORD64 BaseOfDll,PSYM_ENUMSYMBOLS_CALLBACK64W EnumSymbolsCallback,PVOID UserContext); + +#ifdef _IMAGEHLP64 +#define SymEnumerateSymbols SymEnumerateSymbols64 +#define SymEnumerateSymbolsW SymEnumerateSymbolsW64 +#else + BOOL IMAGEAPI SymEnumerateSymbols(HANDLE hProcess,DWORD BaseOfDll,PSYM_ENUMSYMBOLS_CALLBACK EnumSymbolsCallback,PVOID UserContext); + BOOL IMAGEAPI SymEnumerateSymbolsW(HANDLE hProcess,DWORD BaseOfDll,PSYM_ENUMSYMBOLS_CALLBACKW EnumSymbolsCallback,PVOID UserContext); +#endif + + BOOL IMAGEAPI EnumerateLoadedModules64(HANDLE hProcess,PENUMLOADED_MODULES_CALLBACK64 EnumLoadedModulesCallback,PVOID UserContext); +#ifdef _IMAGEHLP64 +#define EnumerateLoadedModules EnumerateLoadedModules64 +#else + BOOL IMAGEAPI EnumerateLoadedModules(HANDLE hProcess,PENUMLOADED_MODULES_CALLBACK EnumLoadedModulesCallback,PVOID UserContext); +#endif + + PVOID IMAGEAPI SymFunctionTableAccess64(HANDLE hProcess,DWORD64 AddrBase); + +#ifdef _IMAGEHLP64 +#define SymFunctionTableAccess SymFunctionTableAccess64 +#else + PVOID IMAGEAPI SymFunctionTableAccess(HANDLE hProcess,DWORD AddrBase); +#endif + + BOOL IMAGEAPI SymGetModuleInfo64(HANDLE hProcess,DWORD64 qwAddr,PIMAGEHLP_MODULE64 ModuleInfo); + BOOL IMAGEAPI SymGetModuleInfoW64(HANDLE hProcess,DWORD64 qwAddr,PIMAGEHLP_MODULEW64 ModuleInfo); + +#ifdef _IMAGEHLP64 +#define SymGetModuleInfo SymGetModuleInfo64 +#define SymGetModuleInfoW SymGetModuleInfoW64 +#else + BOOL IMAGEAPI SymGetModuleInfo(HANDLE hProcess,DWORD dwAddr,PIMAGEHLP_MODULE ModuleInfo); + BOOL IMAGEAPI SymGetModuleInfoW(HANDLE hProcess,DWORD dwAddr,PIMAGEHLP_MODULEW ModuleInfo); +#endif + + DWORD64 IMAGEAPI SymGetModuleBase64(HANDLE hProcess,DWORD64 qwAddr); + +#ifdef _IMAGEHLP64 +#define SymGetModuleBase SymGetModuleBase64 +#else + DWORD IMAGEAPI SymGetModuleBase(HANDLE hProcess,DWORD dwAddr); +#endif + + BOOL IMAGEAPI SymGetSymNext64(HANDLE hProcess,PIMAGEHLP_SYMBOL64 Symbol); + +#ifdef _IMAGEHLP64 +#define SymGetSymNext SymGetSymNext64 +#else + BOOL IMAGEAPI SymGetSymNext(HANDLE hProcess,PIMAGEHLP_SYMBOL Symbol); +#endif + + BOOL IMAGEAPI SymGetSymPrev64(HANDLE hProcess,PIMAGEHLP_SYMBOL64 Symbol); + +#ifdef _IMAGEHLP64 +#define SymGetSymPrev SymGetSymPrev64 +#else + BOOL IMAGEAPI SymGetSymPrev(HANDLE hProcess,PIMAGEHLP_SYMBOL Symbol); +#endif + + typedef struct _SRCCODEINFO { + DWORD SizeOfStruct; + PVOID Key; + DWORD64 ModBase; + CHAR Obj[MAX_PATH + 1]; + CHAR FileName[MAX_PATH + 1]; + DWORD LineNumber; + DWORD64 Address; + } SRCCODEINFO,*PSRCCODEINFO; + + typedef BOOL (CALLBACK *PSYM_ENUMLINES_CALLBACK)(PSRCCODEINFO LineInfo,PVOID UserContext); + + BOOL IMAGEAPI SymEnumLines(HANDLE hProcess,ULONG64 Base,PCSTR Obj,PCSTR File,PSYM_ENUMLINES_CALLBACK EnumLinesCallback,PVOID UserContext); + BOOL IMAGEAPI SymGetLineFromAddr64(HANDLE hProcess,DWORD64 qwAddr,PDWORD pdwDisplacement,PIMAGEHLP_LINE64 Line64); + +#ifdef _IMAGEHLP64 +#define SymGetLineFromAddr SymGetLineFromAddr64 +#else + BOOL IMAGEAPI SymGetLineFromAddr(HANDLE hProcess,DWORD dwAddr,PDWORD pdwDisplacement,PIMAGEHLP_LINE Line); +#endif + + BOOL IMAGEAPI SymGetLineFromName64(HANDLE hProcess,PSTR ModuleName,PSTR FileName,DWORD dwLineNumber,PLONG plDisplacement,PIMAGEHLP_LINE64 Line); + +#ifdef _IMAGEHLP64 +#define SymGetLineFromName SymGetLineFromName64 +#else + BOOL IMAGEAPI SymGetLineFromName(HANDLE hProcess,PSTR ModuleName,PSTR FileName,DWORD dwLineNumber,PLONG plDisplacement,PIMAGEHLP_LINE Line); +#endif + + BOOL IMAGEAPI SymGetLineNext64(HANDLE hProcess,PIMAGEHLP_LINE64 Line); + +#ifdef _IMAGEHLP64 +#define SymGetLineNext SymGetLineNext64 +#else + BOOL IMAGEAPI SymGetLineNext(HANDLE hProcess,PIMAGEHLP_LINE Line); +#endif + + BOOL IMAGEAPI SymGetLinePrev64(HANDLE hProcess,PIMAGEHLP_LINE64 Line); + +#ifdef _IMAGEHLP64 +#define SymGetLinePrev SymGetLinePrev64 +#else + BOOL IMAGEAPI SymGetLinePrev(HANDLE hProcess,PIMAGEHLP_LINE Line); +#endif + + BOOL IMAGEAPI SymMatchFileName(PSTR FileName,PSTR Match,PSTR *FileNameStop,PSTR *MatchStop); + BOOL IMAGEAPI SymInitialize(HANDLE hProcess,PSTR UserSearchPath,BOOL fInvadeProcess); + BOOL IMAGEAPI SymGetSearchPath(HANDLE hProcess,PSTR SearchPath,DWORD SearchPathLength); + BOOL IMAGEAPI SymSetSearchPath(HANDLE hProcess,PSTR SearchPath); + DWORD64 IMAGEAPI SymLoadModule64(HANDLE hProcess,HANDLE hFile,PSTR ImageName,PSTR ModuleName,DWORD64 BaseOfDll,DWORD SizeOfDll); + +#define SLMFLAG_VIRTUAL 0x1 + + DWORD64 IMAGEAPI SymLoadModuleEx(HANDLE hProcess,HANDLE hFile,PSTR ImageName,PSTR ModuleName,DWORD64 BaseOfDll,DWORD DllSize,PMODLOAD_DATA Data,DWORD Flags); + +#ifdef _IMAGEHLP64 +#define SymLoadModule SymLoadModule64 +#else + DWORD IMAGEAPI SymLoadModule(HANDLE hProcess,HANDLE hFile,PSTR ImageName,PSTR ModuleName,DWORD BaseOfDll,DWORD SizeOfDll); +#endif + + BOOL IMAGEAPI SymUnloadModule64(HANDLE hProcess,DWORD64 BaseOfDll); + +#ifdef _IMAGEHLP64 +#define SymUnloadModule SymUnloadModule64 +#else + BOOL IMAGEAPI SymUnloadModule(HANDLE hProcess,DWORD BaseOfDll); +#endif + + BOOL IMAGEAPI SymUnDName64(PIMAGEHLP_SYMBOL64 sym,PSTR UnDecName,DWORD UnDecNameLength); + +#ifdef _IMAGEHLP64 +#define SymUnDName SymUnDName64 +#else + BOOL IMAGEAPI SymUnDName(PIMAGEHLP_SYMBOL sym,PSTR UnDecName,DWORD UnDecNameLength); +#endif + + BOOL IMAGEAPI SymRegisterCallback64(HANDLE hProcess,PSYMBOL_REGISTERED_CALLBACK64 CallbackFunction,ULONG64 UserContext); + + BOOL IMAGEAPI SymRegisterFunctionEntryCallback64(HANDLE hProcess,PSYMBOL_FUNCENTRY_CALLBACK64 CallbackFunction,ULONG64 UserContext); + +#ifdef _IMAGEHLP64 +#define SymRegisterCallback SymRegisterCallback64 +#define SymRegisterFunctionEntryCallback SymRegisterFunctionEntryCallback64 +#else + BOOL IMAGEAPI SymRegisterCallback(HANDLE hProcess,PSYMBOL_REGISTERED_CALLBACK CallbackFunction,PVOID UserContext); + BOOL IMAGEAPI SymRegisterFunctionEntryCallback(HANDLE hProcess,PSYMBOL_FUNCENTRY_CALLBACK CallbackFunction,PVOID UserContext); +#endif + + typedef struct _IMAGEHLP_SYMBOL_SRC { + DWORD sizeofstruct; + DWORD type; + char file[MAX_PATH]; + } IMAGEHLP_SYMBOL_SRC,*PIMAGEHLP_SYMBOL_SRC; + + typedef struct _MODULE_TYPE_INFO { + USHORT dataLength; + USHORT leaf; + BYTE data[1]; + } MODULE_TYPE_INFO,*PMODULE_TYPE_INFO; + + typedef struct _SYMBOL_INFO { + ULONG SizeOfStruct; + ULONG TypeIndex; + ULONG64 Reserved[2]; + ULONG info; + ULONG Size; + ULONG64 ModBase; + ULONG Flags; + ULONG64 Value; + ULONG64 Address; + ULONG Register; + ULONG Scope; + ULONG Tag; + ULONG NameLen; + ULONG MaxNameLen; + CHAR Name[1]; + } SYMBOL_INFO,*PSYMBOL_INFO; + + typedef struct _SYMBOL_INFO_PACKAGE { + SYMBOL_INFO si; + CHAR name[MAX_SYM_NAME + 1]; + } SYMBOL_INFO_PACKAGE,*PSYMBOL_INFO_PACKAGE; + + typedef struct _IMAGEHLP_STACK_FRAME + { + ULONG64 InstructionOffset; + ULONG64 ReturnOffset; + ULONG64 FrameOffset; + ULONG64 StackOffset; + ULONG64 BackingStoreOffset; + ULONG64 FuncTableEntry; + ULONG64 Params[4]; + ULONG64 Reserved[5]; + BOOL Virtual; + ULONG Reserved2; + } IMAGEHLP_STACK_FRAME,*PIMAGEHLP_STACK_FRAME; + + typedef VOID IMAGEHLP_CONTEXT,*PIMAGEHLP_CONTEXT; + + BOOL IMAGEAPI SymSetContext(HANDLE hProcess,PIMAGEHLP_STACK_FRAME StackFrame,PIMAGEHLP_CONTEXT Context); + BOOL IMAGEAPI SymFromAddr(HANDLE hProcess,DWORD64 Address,PDWORD64 Displacement,PSYMBOL_INFO Symbol); + BOOL IMAGEAPI SymFromToken(HANDLE hProcess,DWORD64 Base,DWORD Token,PSYMBOL_INFO Symbol); + BOOL IMAGEAPI SymFromName(HANDLE hProcess,LPSTR Name,PSYMBOL_INFO Symbol); + + typedef BOOL (CALLBACK *PSYM_ENUMERATESYMBOLS_CALLBACK)(PSYMBOL_INFO pSymInfo,ULONG SymbolSize,PVOID UserContext); + + BOOL IMAGEAPI SymEnumSymbols(HANDLE hProcess,ULONG64 BaseOfDll,PCSTR Mask,PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,PVOID UserContext); + BOOL IMAGEAPI SymEnumSymbolsForAddr(HANDLE hProcess,DWORD64 Address,PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,PVOID UserContext); + +#define SYMENUMFLAG_FULLSRCH 1 +#define SYMENUMFLAG_SPEEDSRCH 2 + + typedef enum _IMAGEHLP_SYMBOL_TYPE_INFO { + TI_GET_SYMTAG,TI_GET_SYMNAME,TI_GET_LENGTH,TI_GET_TYPE,TI_GET_TYPEID,TI_GET_BASETYPE,TI_GET_ARRAYINDEXTYPEID,TI_FINDCHILDREN, + TI_GET_DATAKIND,TI_GET_ADDRESSOFFSET,TI_GET_OFFSET,TI_GET_VALUE,TI_GET_COUNT,TI_GET_CHILDRENCOUNT,TI_GET_BITPOSITION,TI_GET_VIRTUALBASECLASS, + TI_GET_VIRTUALTABLESHAPEID,TI_GET_VIRTUALBASEPOINTEROFFSET,TI_GET_CLASSPARENTID,TI_GET_NESTED,TI_GET_SYMINDEX,TI_GET_LEXICALPARENT, + TI_GET_ADDRESS,TI_GET_THISADJUST,TI_GET_UDTKIND,TI_IS_EQUIV_TO,TI_GET_CALLING_CONVENTION + } IMAGEHLP_SYMBOL_TYPE_INFO; + + typedef struct _TI_FINDCHILDREN_PARAMS { + ULONG Count; + ULONG Start; + ULONG ChildId[1]; + } TI_FINDCHILDREN_PARAMS; + + BOOL IMAGEAPI SymGetTypeInfo(HANDLE hProcess,DWORD64 ModBase,ULONG TypeId,IMAGEHLP_SYMBOL_TYPE_INFO GetType,PVOID pInfo); + BOOL IMAGEAPI SymEnumTypes(HANDLE hProcess,ULONG64 BaseOfDll,PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,PVOID UserContext); + BOOL IMAGEAPI SymGetTypeFromName(HANDLE hProcess,ULONG64 BaseOfDll,LPSTR Name,PSYMBOL_INFO Symbol); + BOOL IMAGEAPI SymAddSymbol(HANDLE hProcess,ULONG64 BaseOfDll,PCSTR Name,DWORD64 Address,DWORD Size,DWORD Flags); + BOOL IMAGEAPI SymDeleteSymbol(HANDLE hProcess,ULONG64 BaseOfDll,PCSTR Name,DWORD64 Address,DWORD Flags); + + typedef BOOL (WINAPI *PDBGHELP_CREATE_USER_DUMP_CALLBACK)(DWORD DataType,PVOID *Data,LPDWORD DataLength,PVOID UserData); + + BOOL WINAPI DbgHelpCreateUserDump(LPSTR FileName,PDBGHELP_CREATE_USER_DUMP_CALLBACK Callback,PVOID UserData); + BOOL WINAPI DbgHelpCreateUserDumpW(LPWSTR FileName,PDBGHELP_CREATE_USER_DUMP_CALLBACK Callback,PVOID UserData); + BOOL IMAGEAPI SymGetSymFromAddr64(HANDLE hProcess,DWORD64 qwAddr,PDWORD64 pdwDisplacement,PIMAGEHLP_SYMBOL64 Symbol); + +#ifdef _IMAGEHLP64 +#define SymGetSymFromAddr SymGetSymFromAddr64 +#else + BOOL IMAGEAPI SymGetSymFromAddr(HANDLE hProcess,DWORD dwAddr,PDWORD pdwDisplacement,PIMAGEHLP_SYMBOL Symbol); +#endif + + BOOL IMAGEAPI SymGetSymFromName64(HANDLE hProcess,PSTR Name,PIMAGEHLP_SYMBOL64 Symbol); + +#ifdef _IMAGEHLP64 +#define SymGetSymFromName SymGetSymFromName64 +#else + BOOL IMAGEAPI SymGetSymFromName(HANDLE hProcess,PSTR Name,PIMAGEHLP_SYMBOL Symbol); +#endif + + DBHLP_DEPRECIATED BOOL IMAGEAPI FindFileInPath(HANDLE hprocess,LPSTR SearchPath,LPSTR FileName,PVOID id,DWORD two,DWORD three,DWORD flags,LPSTR FilePath); + DBHLP_DEPRECIATED BOOL IMAGEAPI FindFileInSearchPath(HANDLE hprocess,LPSTR SearchPath,LPSTR FileName,DWORD one,DWORD two,DWORD three,LPSTR FilePath); + DBHLP_DEPRECIATED BOOL IMAGEAPI SymEnumSym(HANDLE hProcess,ULONG64 BaseOfDll,PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,PVOID UserContext); + +#define SYMF_OMAP_GENERATED 0x00000001 +#define SYMF_OMAP_MODIFIED 0x00000002 +#define SYMF_REGISTER 0x00000008 +#define SYMF_REGREL 0x00000010 +#define SYMF_FRAMEREL 0x00000020 +#define SYMF_PARAMETER 0x00000040 +#define SYMF_LOCAL 0x00000080 +#define SYMF_CONSTANT 0x00000100 +#define SYMF_EXPORT 0x00000200 +#define SYMF_FORWARDER 0x00000400 +#define SYMF_FUNCTION 0x00000800 +#define SYMF_VIRTUAL 0x00001000 +#define SYMF_THUNK 0x00002000 +#define SYMF_TLSREL 0x00004000 + +#define IMAGEHLP_SYMBOL_INFO_VALUEPRESENT 1 +#define IMAGEHLP_SYMBOL_INFO_REGISTER SYMF_REGISTER +#define IMAGEHLP_SYMBOL_INFO_REGRELATIVE SYMF_REGREL +#define IMAGEHLP_SYMBOL_INFO_FRAMERELATIVE SYMF_FRAMEREL +#define IMAGEHLP_SYMBOL_INFO_PARAMETER SYMF_PARAMETER +#define IMAGEHLP_SYMBOL_INFO_LOCAL SYMF_LOCAL +#define IMAGEHLP_SYMBOL_INFO_CONSTANT SYMF_CONSTANT +#define IMAGEHLP_SYMBOL_FUNCTION SYMF_FUNCTION +#define IMAGEHLP_SYMBOL_VIRTUAL SYMF_VIRTUAL +#define IMAGEHLP_SYMBOL_THUNK SYMF_THUNK +#define IMAGEHLP_SYMBOL_INFO_TLSRELATIVE SYMF_TLSREL + +#include + +#define MINIDUMP_SIGNATURE ('PMDM') +#define MINIDUMP_VERSION (42899) + typedef DWORD RVA; + typedef ULONG64 RVA64; + + typedef struct _MINIDUMP_LOCATION_DESCRIPTOR { + ULONG32 DataSize; + RVA Rva; + } MINIDUMP_LOCATION_DESCRIPTOR; + + typedef struct _MINIDUMP_LOCATION_DESCRIPTOR64 { + ULONG64 DataSize; + RVA64 Rva; + } MINIDUMP_LOCATION_DESCRIPTOR64; + + typedef struct _MINIDUMP_MEMORY_DESCRIPTOR { + ULONG64 StartOfMemoryRange; + MINIDUMP_LOCATION_DESCRIPTOR Memory; + } MINIDUMP_MEMORY_DESCRIPTOR,*PMINIDUMP_MEMORY_DESCRIPTOR; + + typedef struct _MINIDUMP_MEMORY_DESCRIPTOR64 { + ULONG64 StartOfMemoryRange; + ULONG64 DataSize; + } MINIDUMP_MEMORY_DESCRIPTOR64,*PMINIDUMP_MEMORY_DESCRIPTOR64; + + typedef struct _MINIDUMP_HEADER { + ULONG32 Signature; + ULONG32 Version; + ULONG32 NumberOfStreams; + RVA StreamDirectoryRva; + ULONG32 CheckSum; + union { + ULONG32 Reserved; + ULONG32 TimeDateStamp; + } DUMMYUNIONNAME; + ULONG64 Flags; + } MINIDUMP_HEADER,*PMINIDUMP_HEADER; + + typedef struct _MINIDUMP_DIRECTORY { + ULONG32 StreamType; + MINIDUMP_LOCATION_DESCRIPTOR Location; + } MINIDUMP_DIRECTORY,*PMINIDUMP_DIRECTORY; + + typedef struct _MINIDUMP_STRING { + ULONG32 Length; + WCHAR Buffer [0]; + } MINIDUMP_STRING,*PMINIDUMP_STRING; + + typedef enum _MINIDUMP_STREAM_TYPE { + UnusedStream = 0,ReservedStream0 = 1,ReservedStream1 = 2,ThreadListStream = 3,ModuleListStream = 4,MemoryListStream = 5, + ExceptionStream = 6,SystemInfoStream = 7,ThreadExListStream = 8,Memory64ListStream = 9,CommentStreamA = 10,CommentStreamW = 11, + HandleDataStream = 12,FunctionTableStream = 13,UnloadedModuleListStream = 14,MiscInfoStream = 15,LastReservedStream = 0xffff + } MINIDUMP_STREAM_TYPE; + + typedef union _CPU_INFORMATION { + struct { + ULONG32 VendorId [3 ]; + ULONG32 VersionInformation; + ULONG32 FeatureInformation; + ULONG32 AMDExtendedCpuFeatures; + } X86CpuInfo; + struct { + ULONG64 ProcessorFeatures [2 ]; + } OtherCpuInfo; + } CPU_INFORMATION,*PCPU_INFORMATION; + + typedef struct _MINIDUMP_SYSTEM_INFO { + USHORT ProcessorArchitecture; + USHORT ProcessorLevel; + USHORT ProcessorRevision; + union { + USHORT Reserved0; + struct { + UCHAR NumberOfProcessors; + UCHAR ProductType; + } DUMMYSTRUCTNAME; + } DUMMYUNIONNAME; + ULONG32 MajorVersion; + ULONG32 MinorVersion; + ULONG32 BuildNumber; + ULONG32 PlatformId; + RVA CSDVersionRva; + union { + ULONG32 Reserved1; + struct { + USHORT SuiteMask; + USHORT Reserved2; + } DUMMYSTRUCTNAME; + } DUMMYUNIONNAME1; + CPU_INFORMATION Cpu; + } MINIDUMP_SYSTEM_INFO,*PMINIDUMP_SYSTEM_INFO; + + C_ASSERT (sizeof (((PPROCESS_INFORMATION)0)->dwThreadId)==4); + + typedef struct _MINIDUMP_THREAD { + ULONG32 ThreadId; + ULONG32 SuspendCount; + ULONG32 PriorityClass; + ULONG32 Priority; + ULONG64 Teb; + MINIDUMP_MEMORY_DESCRIPTOR Stack; + MINIDUMP_LOCATION_DESCRIPTOR ThreadContext; + } MINIDUMP_THREAD,*PMINIDUMP_THREAD; + + typedef struct _MINIDUMP_THREAD_LIST { + ULONG32 NumberOfThreads; + MINIDUMP_THREAD Threads [0]; + } MINIDUMP_THREAD_LIST,*PMINIDUMP_THREAD_LIST; + + typedef struct _MINIDUMP_THREAD_EX { + ULONG32 ThreadId; + ULONG32 SuspendCount; + ULONG32 PriorityClass; + ULONG32 Priority; + ULONG64 Teb; + MINIDUMP_MEMORY_DESCRIPTOR Stack; + MINIDUMP_LOCATION_DESCRIPTOR ThreadContext; + MINIDUMP_MEMORY_DESCRIPTOR BackingStore; + } MINIDUMP_THREAD_EX,*PMINIDUMP_THREAD_EX; + + typedef struct _MINIDUMP_THREAD_EX_LIST { + ULONG32 NumberOfThreads; + MINIDUMP_THREAD_EX Threads [0]; + } MINIDUMP_THREAD_EX_LIST,*PMINIDUMP_THREAD_EX_LIST; + + typedef struct _MINIDUMP_EXCEPTION { + ULONG32 ExceptionCode; + ULONG32 ExceptionFlags; + ULONG64 ExceptionRecord; + ULONG64 ExceptionAddress; + ULONG32 NumberParameters; + ULONG32 __unusedAlignment; + ULONG64 ExceptionInformation [EXCEPTION_MAXIMUM_PARAMETERS ]; + } MINIDUMP_EXCEPTION,*PMINIDUMP_EXCEPTION; + + typedef struct MINIDUMP_EXCEPTION_STREAM { + ULONG32 ThreadId; + ULONG32 __alignment; + MINIDUMP_EXCEPTION ExceptionRecord; + MINIDUMP_LOCATION_DESCRIPTOR ThreadContext; + } MINIDUMP_EXCEPTION_STREAM,*PMINIDUMP_EXCEPTION_STREAM; + + typedef struct _MINIDUMP_MODULE { + ULONG64 BaseOfImage; + ULONG32 SizeOfImage; + ULONG32 CheckSum; + ULONG32 TimeDateStamp; + RVA ModuleNameRva; + VS_FIXEDFILEINFO VersionInfo; + MINIDUMP_LOCATION_DESCRIPTOR CvRecord; + MINIDUMP_LOCATION_DESCRIPTOR MiscRecord; + ULONG64 Reserved0; + ULONG64 Reserved1; + } MINIDUMP_MODULE,*PMINIDUMP_MODULE; + + typedef struct _MINIDUMP_MODULE_LIST { + ULONG32 NumberOfModules; + MINIDUMP_MODULE Modules [0 ]; + } MINIDUMP_MODULE_LIST,*PMINIDUMP_MODULE_LIST; + + typedef struct _MINIDUMP_MEMORY_LIST { + ULONG32 NumberOfMemoryRanges; + MINIDUMP_MEMORY_DESCRIPTOR MemoryRanges [0]; + } MINIDUMP_MEMORY_LIST,*PMINIDUMP_MEMORY_LIST; + + typedef struct _MINIDUMP_MEMORY64_LIST { + ULONG64 NumberOfMemoryRanges; + RVA64 BaseRva; + MINIDUMP_MEMORY_DESCRIPTOR64 MemoryRanges [0]; + } MINIDUMP_MEMORY64_LIST,*PMINIDUMP_MEMORY64_LIST; + + typedef struct _MINIDUMP_EXCEPTION_INFORMATION { + DWORD ThreadId; + PEXCEPTION_POINTERS ExceptionPointers; + BOOL ClientPointers; + } MINIDUMP_EXCEPTION_INFORMATION,*PMINIDUMP_EXCEPTION_INFORMATION; + + typedef struct _MINIDUMP_EXCEPTION_INFORMATION64 { + DWORD ThreadId; + ULONG64 ExceptionRecord; + ULONG64 ContextRecord; + BOOL ClientPointers; + } MINIDUMP_EXCEPTION_INFORMATION64,*PMINIDUMP_EXCEPTION_INFORMATION64; + + typedef struct _MINIDUMP_HANDLE_DESCRIPTOR { + ULONG64 Handle; + RVA TypeNameRva; + RVA ObjectNameRva; + ULONG32 Attributes; + ULONG32 GrantedAccess; + ULONG32 HandleCount; + ULONG32 PointerCount; + } MINIDUMP_HANDLE_DESCRIPTOR,*PMINIDUMP_HANDLE_DESCRIPTOR; + + typedef struct _MINIDUMP_HANDLE_DATA_STREAM { + ULONG32 SizeOfHeader; + ULONG32 SizeOfDescriptor; + ULONG32 NumberOfDescriptors; + ULONG32 Reserved; + } MINIDUMP_HANDLE_DATA_STREAM,*PMINIDUMP_HANDLE_DATA_STREAM; + + typedef struct _MINIDUMP_FUNCTION_TABLE_DESCRIPTOR { + ULONG64 MinimumAddress; + ULONG64 MaximumAddress; + ULONG64 BaseAddress; + ULONG32 EntryCount; + ULONG32 SizeOfAlignPad; + } MINIDUMP_FUNCTION_TABLE_DESCRIPTOR,*PMINIDUMP_FUNCTION_TABLE_DESCRIPTOR; + + typedef struct _MINIDUMP_FUNCTION_TABLE_STREAM { + ULONG32 SizeOfHeader; + ULONG32 SizeOfDescriptor; + ULONG32 SizeOfNativeDescriptor; + ULONG32 SizeOfFunctionEntry; + ULONG32 NumberOfDescriptors; + ULONG32 SizeOfAlignPad; + } MINIDUMP_FUNCTION_TABLE_STREAM,*PMINIDUMP_FUNCTION_TABLE_STREAM; + + typedef struct _MINIDUMP_UNLOADED_MODULE { + ULONG64 BaseOfImage; + ULONG32 SizeOfImage; + ULONG32 CheckSum; + ULONG32 TimeDateStamp; + RVA ModuleNameRva; + } MINIDUMP_UNLOADED_MODULE,*PMINIDUMP_UNLOADED_MODULE; + + typedef struct _MINIDUMP_UNLOADED_MODULE_LIST { + ULONG32 SizeOfHeader; + ULONG32 SizeOfEntry; + ULONG32 NumberOfEntries; + } MINIDUMP_UNLOADED_MODULE_LIST,*PMINIDUMP_UNLOADED_MODULE_LIST; + +#define MINIDUMP_MISC1_PROCESS_ID 0x00000001 +#define MINIDUMP_MISC1_PROCESS_TIMES 0x00000002 + + typedef struct _MINIDUMP_MISC_INFO { + ULONG32 SizeOfInfo; + ULONG32 Flags1; + ULONG32 ProcessId; + ULONG32 ProcessCreateTime; + ULONG32 ProcessUserTime; + ULONG32 ProcessKernelTime; + } MINIDUMP_MISC_INFO,*PMINIDUMP_MISC_INFO; + + typedef struct _MINIDUMP_USER_RECORD { + ULONG32 Type; + MINIDUMP_LOCATION_DESCRIPTOR Memory; + } MINIDUMP_USER_RECORD,*PMINIDUMP_USER_RECORD; + + typedef struct _MINIDUMP_USER_STREAM { + ULONG32 Type; + ULONG BufferSize; + PVOID Buffer; + } MINIDUMP_USER_STREAM,*PMINIDUMP_USER_STREAM; + + typedef struct _MINIDUMP_USER_STREAM_INFORMATION { + ULONG UserStreamCount; + PMINIDUMP_USER_STREAM UserStreamArray; + } MINIDUMP_USER_STREAM_INFORMATION,*PMINIDUMP_USER_STREAM_INFORMATION; + + typedef enum _MINIDUMP_CALLBACK_TYPE { + ModuleCallback,ThreadCallback,ThreadExCallback,IncludeThreadCallback,IncludeModuleCallback,MemoryCallback + } MINIDUMP_CALLBACK_TYPE; + + typedef struct _MINIDUMP_THREAD_CALLBACK { + ULONG ThreadId; + HANDLE ThreadHandle; + CONTEXT Context; + ULONG SizeOfContext; + ULONG64 StackBase; + ULONG64 StackEnd; + } MINIDUMP_THREAD_CALLBACK,*PMINIDUMP_THREAD_CALLBACK; + + typedef struct _MINIDUMP_THREAD_EX_CALLBACK { + ULONG ThreadId; + HANDLE ThreadHandle; + CONTEXT Context; + ULONG SizeOfContext; + ULONG64 StackBase; + ULONG64 StackEnd; + ULONG64 BackingStoreBase; + ULONG64 BackingStoreEnd; + } MINIDUMP_THREAD_EX_CALLBACK,*PMINIDUMP_THREAD_EX_CALLBACK; + + typedef struct _MINIDUMP_INCLUDE_THREAD_CALLBACK { + ULONG ThreadId; + } MINIDUMP_INCLUDE_THREAD_CALLBACK,*PMINIDUMP_INCLUDE_THREAD_CALLBACK; + + typedef enum _THREAD_WRITE_FLAGS { + ThreadWriteThread = 0x0001,ThreadWriteStack = 0x0002,ThreadWriteContext = 0x0004,ThreadWriteBackingStore = 0x0008, + ThreadWriteInstructionWindow = 0x0010,ThreadWriteThreadData = 0x0020 + } THREAD_WRITE_FLAGS; + + typedef struct _MINIDUMP_MODULE_CALLBACK { + PWCHAR FullPath; + ULONG64 BaseOfImage; + ULONG SizeOfImage; + ULONG CheckSum; + ULONG TimeDateStamp; + VS_FIXEDFILEINFO VersionInfo; + PVOID CvRecord; + ULONG SizeOfCvRecord; + PVOID MiscRecord; + ULONG SizeOfMiscRecord; + } MINIDUMP_MODULE_CALLBACK,*PMINIDUMP_MODULE_CALLBACK; + + typedef struct _MINIDUMP_INCLUDE_MODULE_CALLBACK { + ULONG64 BaseOfImage; + } MINIDUMP_INCLUDE_MODULE_CALLBACK,*PMINIDUMP_INCLUDE_MODULE_CALLBACK; + + typedef enum _MODULE_WRITE_FLAGS { + ModuleWriteModule = 0x0001,ModuleWriteDataSeg = 0x0002,ModuleWriteMiscRecord = 0x0004,ModuleWriteCvRecord = 0x0008, + ModuleReferencedByMemory = 0x0010 + } MODULE_WRITE_FLAGS; + + typedef struct _MINIDUMP_CALLBACK_INPUT { + ULONG ProcessId; + HANDLE ProcessHandle; + ULONG CallbackType; + union { + MINIDUMP_THREAD_CALLBACK Thread; + MINIDUMP_THREAD_EX_CALLBACK ThreadEx; + MINIDUMP_MODULE_CALLBACK Module; + MINIDUMP_INCLUDE_THREAD_CALLBACK IncludeThread; + MINIDUMP_INCLUDE_MODULE_CALLBACK IncludeModule; + } DUMMYUNIONNAME; + } MINIDUMP_CALLBACK_INPUT,*PMINIDUMP_CALLBACK_INPUT; + + typedef struct _MINIDUMP_CALLBACK_OUTPUT { + union { + ULONG ModuleWriteFlags; + ULONG ThreadWriteFlags; + struct { + ULONG64 MemoryBase; + ULONG MemorySize; + } DUMMYSTRUCTNAME; + } DUMMYUNIONNAME; + } MINIDUMP_CALLBACK_OUTPUT,*PMINIDUMP_CALLBACK_OUTPUT; + + typedef enum _MINIDUMP_TYPE { + MiniDumpNormal = 0x0000,MiniDumpWithDataSegs = 0x0001,MiniDumpWithFullMemory = 0x0002,MiniDumpWithHandleData = 0x0004, + MiniDumpFilterMemory = 0x0008,MiniDumpScanMemory = 0x0010,MiniDumpWithUnloadedModules = 0x0020,MiniDumpWithIndirectlyReferencedMemory = 0x0040, + MiniDumpFilterModulePaths = 0x0080,MiniDumpWithProcessThreadData = 0x0100,MiniDumpWithPrivateReadWriteMemory = 0x0200, + MiniDumpWithoutOptionalData = 0x0400 + } MINIDUMP_TYPE; + + typedef BOOL (WINAPI *MINIDUMP_CALLBACK_ROUTINE)(PVOID CallbackParam,CONST PMINIDUMP_CALLBACK_INPUT CallbackInput,PMINIDUMP_CALLBACK_OUTPUT CallbackOutput); + + typedef struct _MINIDUMP_CALLBACK_INFORMATION { + MINIDUMP_CALLBACK_ROUTINE CallbackRoutine; + PVOID CallbackParam; + } MINIDUMP_CALLBACK_INFORMATION,*PMINIDUMP_CALLBACK_INFORMATION; + +#define RVA_TO_ADDR(Mapping,Rva) ((PVOID)(((ULONG_PTR) (Mapping)) + (Rva))) + + BOOL WINAPI MiniDumpWriteDump(HANDLE hProcess,DWORD ProcessId,HANDLE hFile,MINIDUMP_TYPE DumpType,CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam); + BOOL WINAPI MiniDumpReadDumpStream(PVOID BaseOfDump,ULONG StreamNumber,PMINIDUMP_DIRECTORY *Dir,PVOID *StreamPointer,ULONG *StreamSize); + +#include + +#ifdef __cplusplus +} +#endif +#endif diff --git a/mesalib/src/gallium/auxiliary/util/u_atomic.h b/mesalib/src/gallium/auxiliary/util/u_atomic.h new file mode 100644 index 000000000..e8c0fdf75 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_atomic.h @@ -0,0 +1,352 @@ +/** + * Many similar implementations exist. See for example libwsbm + * or the linux kernel include/atomic.h + * + * No copyright claimed on this file. + * + */ + +#ifndef U_ATOMIC_H +#define U_ATOMIC_H + +#include "pipe/p_compiler.h" +#include "pipe/p_defines.h" + +/* Favor OS-provided implementations. + * + * Where no OS-provided implementation is available, fall back to + * locally coded assembly, compiler intrinsic or ultimately a + * mutex-based implementation. + */ +#if (defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY) || \ + defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT)) +#define PIPE_ATOMIC_OS_UNLOCKED +#elif defined(PIPE_OS_SOLARIS) +#define PIPE_ATOMIC_OS_SOLARIS +#elif defined(PIPE_CC_MSVC) +#define PIPE_ATOMIC_MSVC_INTRINSIC +#elif (defined(PIPE_CC_MSVC) && defined(PIPE_ARCH_X86)) +#define PIPE_ATOMIC_ASM_MSVC_X86 +#elif (defined(PIPE_CC_GCC) && defined(PIPE_ARCH_X86)) +#define PIPE_ATOMIC_ASM_GCC_X86 +#elif (defined(PIPE_CC_GCC) && defined(PIPE_ARCH_X86_64)) +#define PIPE_ATOMIC_ASM_GCC_X86_64 +#elif defined(PIPE_CC_GCC) && (PIPE_CC_GCC_VERSION >= 401) +#define PIPE_ATOMIC_GCC_INTRINSIC +#else +#error "Unsupported platform" +#endif + + +#if defined(PIPE_ATOMIC_ASM_GCC_X86_64) +#define PIPE_ATOMIC "GCC x86_64 assembly" + +#ifdef __cplusplus +extern "C" { +#endif + +#define p_atomic_set(_v, _i) (*(_v) = (_i)) +#define p_atomic_read(_v) (*(_v)) + +static INLINE boolean +p_atomic_dec_zero(int32_t *v) +{ + unsigned char c; + + __asm__ __volatile__("lock; decl %0; sete %1":"+m"(*v), "=qm"(c) + ::"memory"); + + return c != 0; +} + +static INLINE void +p_atomic_inc(int32_t *v) +{ + __asm__ __volatile__("lock; incl %0":"+m"(*v)); +} + +static INLINE void +p_atomic_dec(int32_t *v) +{ + __asm__ __volatile__("lock; decl %0":"+m"(*v)); +} + +static INLINE int32_t +p_atomic_cmpxchg(int32_t *v, int32_t old, int32_t _new) +{ + return __sync_val_compare_and_swap(v, old, _new); +} + +#ifdef __cplusplus +} +#endif + +#endif /* PIPE_ATOMIC_ASM_GCC_X86_64 */ + + +#if defined(PIPE_ATOMIC_ASM_GCC_X86) + +#define PIPE_ATOMIC "GCC x86 assembly" + +#ifdef __cplusplus +extern "C" { +#endif + +#define p_atomic_set(_v, _i) (*(_v) = (_i)) +#define p_atomic_read(_v) (*(_v)) + +static INLINE boolean +p_atomic_dec_zero(int32_t *v) +{ + unsigned char c; + + __asm__ __volatile__("lock; decl %0; sete %1":"+m"(*v), "=qm"(c) + ::"memory"); + + return c != 0; +} + +static INLINE void +p_atomic_inc(int32_t *v) +{ + __asm__ __volatile__("lock; incl %0":"+m"(*v)); +} + +static INLINE void +p_atomic_dec(int32_t *v) +{ + __asm__ __volatile__("lock; decl %0":"+m"(*v)); +} + +static INLINE int32_t +p_atomic_cmpxchg(int32_t *v, int32_t old, int32_t _new) +{ + return __sync_val_compare_and_swap(v, old, _new); +} + +#ifdef __cplusplus +} +#endif + +#endif + + + +/* Implementation using GCC-provided synchronization intrinsics + */ +#if defined(PIPE_ATOMIC_GCC_INTRINSIC) + +#define PIPE_ATOMIC "GCC Sync Intrinsics" + +#ifdef __cplusplus +extern "C" { +#endif + +#define p_atomic_set(_v, _i) (*(_v) = (_i)) +#define p_atomic_read(_v) (*(_v)) + +static INLINE boolean +p_atomic_dec_zero(int32_t *v) +{ + return (__sync_sub_and_fetch(v, 1) == 0); +} + +static INLINE void +p_atomic_inc(int32_t *v) +{ + (void) __sync_add_and_fetch(v, 1); +} + +static INLINE void +p_atomic_dec(int32_t *v) +{ + (void) __sync_sub_and_fetch(v, 1); +} + +static INLINE int32_t +p_atomic_cmpxchg(int32_t *v, int32_t old, int32_t _new) +{ + return __sync_val_compare_and_swap(v, old, _new); +} + +#ifdef __cplusplus +} +#endif + +#endif + + + +/* Unlocked version for single threaded environments, such as some + * windows kernel modules. + */ +#if defined(PIPE_ATOMIC_OS_UNLOCKED) + +#define PIPE_ATOMIC "Unlocked" + +#define p_atomic_set(_v, _i) (*(_v) = (_i)) +#define p_atomic_read(_v) (*(_v)) +#define p_atomic_dec_zero(_v) ((boolean) --(*(_v))) +#define p_atomic_inc(_v) ((void) (*(_v))++) +#define p_atomic_dec(_v) ((void) (*(_v))--) +#define p_atomic_cmpxchg(_v, old, _new) (*(_v) == old ? *(_v) = (_new) : *(_v)) + +#endif + + +/* Locally coded assembly for MSVC on x86: + */ +#if defined(PIPE_ATOMIC_ASM_MSVC_X86) + +#define PIPE_ATOMIC "MSVC x86 assembly" + +#ifdef __cplusplus +extern "C" { +#endif + +#define p_atomic_set(_v, _i) (*(_v) = (_i)) +#define p_atomic_read(_v) (*(_v)) + +static INLINE boolean +p_atomic_dec_zero(int32_t *v) +{ + unsigned char c; + + __asm { + mov eax, [v] + lock dec dword ptr [eax] + sete byte ptr [c] + } + + return c != 0; +} + +static INLINE void +p_atomic_inc(int32_t *v) +{ + __asm { + mov eax, [v] + lock inc dword ptr [eax] + } +} + +static INLINE void +p_atomic_dec(int32_t *v) +{ + __asm { + mov eax, [v] + lock dec dword ptr [eax] + } +} + +static INLINE int32_t +p_atomic_cmpxchg(int32_t *v, int32_t old, int32_t _new) +{ + int32_t orig; + + __asm { + mov ecx, [v] + mov eax, [old] + mov edx, [_new] + lock cmpxchg [ecx], edx + mov [orig], eax + } + + return orig; +} + +#ifdef __cplusplus +} +#endif + +#endif + + +#if defined(PIPE_ATOMIC_MSVC_INTRINSIC) + +#define PIPE_ATOMIC "MSVC Intrinsics" + +#include + +#pragma intrinsic(_InterlockedIncrement) +#pragma intrinsic(_InterlockedDecrement) +#pragma intrinsic(_InterlockedCompareExchange) + +#ifdef __cplusplus +extern "C" { +#endif + +#define p_atomic_set(_v, _i) (*(_v) = (_i)) +#define p_atomic_read(_v) (*(_v)) + +static INLINE boolean +p_atomic_dec_zero(int32_t *v) +{ + return _InterlockedDecrement((long *)v) == 0; +} + +static INLINE void +p_atomic_inc(int32_t *v) +{ + _InterlockedIncrement((long *)v); +} + +static INLINE void +p_atomic_dec(int32_t *v) +{ + _InterlockedDecrement((long *)v); +} + +static INLINE int32_t +p_atomic_cmpxchg(int32_t *v, int32_t old, int32_t _new) +{ + return _InterlockedCompareExchange((long *)v, _new, old); +} + +#ifdef __cplusplus +} +#endif + +#endif + +#if defined(PIPE_ATOMIC_OS_SOLARIS) + +#define PIPE_ATOMIC "Solaris OS atomic functions" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define p_atomic_set(_v, _i) (*(_v) = (_i)) +#define p_atomic_read(_v) (*(_v)) + +static INLINE boolean +p_atomic_dec_zero(int32_t *v) +{ + uint32_t n = atomic_dec_32_nv((uint32_t *) v); + + return n != 0; +} + +#define p_atomic_inc(_v) atomic_inc_32((uint32_t *) _v) +#define p_atomic_dec(_v) atomic_dec_32((uint32_t *) _v) + +#define p_atomic_cmpxchg(_v, _old, _new) \ + atomic_cas_32( (uint32_t *) _v, (uint32_t) _old, (uint32_t) _new) + +#ifdef __cplusplus +} +#endif + +#endif + + +#ifndef PIPE_ATOMIC +#error "No pipe_atomic implementation selected" +#endif + + + +#endif /* U_ATOMIC_H */ diff --git a/mesalib/src/gallium/auxiliary/util/u_bitmask.c b/mesalib/src/gallium/auxiliary/util/u_bitmask.c new file mode 100644 index 000000000..c2952a30d --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_bitmask.c @@ -0,0 +1,328 @@ +/************************************************************************** + * + * 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. + * + **************************************************************************/ + +/** + * @file + * Generic bitmask implementation. + * + * @author Jose Fonseca + */ + + +#include "pipe/p_compiler.h" +#include "util/u_debug.h" + +#include "util/u_memory.h" +#include "util/u_bitmask.h" + + +typedef uint32_t util_bitmask_word; + + +#define UTIL_BITMASK_INITIAL_WORDS 16 +#define UTIL_BITMASK_BITS_PER_BYTE 8 +#define UTIL_BITMASK_BITS_PER_WORD (sizeof(util_bitmask_word) * UTIL_BITMASK_BITS_PER_BYTE) + + +struct util_bitmask +{ + util_bitmask_word *words; + + /** Number of bits we can currently hold */ + unsigned size; + + /** Number of consecutive bits set at the start of the bitmask */ + unsigned filled; +}; + + +struct util_bitmask * +util_bitmask_create(void) +{ + struct util_bitmask *bm; + + bm = MALLOC_STRUCT(util_bitmask); + if(!bm) + return NULL; + + bm->words = (util_bitmask_word *)CALLOC(UTIL_BITMASK_INITIAL_WORDS, sizeof(util_bitmask_word)); + if(!bm->words) { + FREE(bm); + return NULL; + } + + bm->size = UTIL_BITMASK_INITIAL_WORDS * UTIL_BITMASK_BITS_PER_WORD; + bm->filled = 0; + + return bm; +} + + +/** + * Resize the bitmask if necessary + */ +static INLINE boolean +util_bitmask_resize(struct util_bitmask *bm, + unsigned minimum_index) +{ + unsigned minimum_size = minimum_index + 1; + unsigned new_size; + util_bitmask_word *new_words; + + /* Check integer overflow */ + if(!minimum_size) + return FALSE; + + if(bm->size >= minimum_size) + return TRUE; + + assert(bm->size % UTIL_BITMASK_BITS_PER_WORD == 0); + new_size = bm->size; + while(new_size < minimum_size) { + new_size *= 2; + /* Check integer overflow */ + if(new_size < bm->size) + return FALSE; + } + assert(new_size); + assert(new_size % UTIL_BITMASK_BITS_PER_WORD == 0); + + new_words = (util_bitmask_word *)REALLOC((void *)bm->words, + bm->size / UTIL_BITMASK_BITS_PER_BYTE, + new_size / UTIL_BITMASK_BITS_PER_BYTE); + if(!new_words) + return FALSE; + + memset(new_words + bm->size/UTIL_BITMASK_BITS_PER_WORD, + 0, + (new_size - bm->size)/UTIL_BITMASK_BITS_PER_BYTE); + + bm->size = new_size; + bm->words = new_words; + + return TRUE; +} + + +/** + * Lazily update the filled. + */ +static INLINE void +util_bitmask_filled_set(struct util_bitmask *bm, + unsigned index) +{ + assert(bm->filled <= bm->size); + assert(index < bm->size); + + if(index == bm->filled) { + ++bm->filled; + assert(bm->filled <= bm->size); + } +} + +static INLINE void +util_bitmask_filled_unset(struct util_bitmask *bm, + unsigned index) +{ + assert(bm->filled <= bm->size); + assert(index < bm->size); + + if(index < bm->filled) + bm->filled = index; +} + + +unsigned +util_bitmask_add(struct util_bitmask *bm) +{ + unsigned word; + unsigned bit; + util_bitmask_word mask; + + assert(bm); + + /* linear search for an empty index */ + word = bm->filled / UTIL_BITMASK_BITS_PER_WORD; + bit = bm->filled % UTIL_BITMASK_BITS_PER_WORD; + mask = 1 << bit; + while(word < bm->size / UTIL_BITMASK_BITS_PER_WORD) { + while(bit < UTIL_BITMASK_BITS_PER_WORD) { + if(!(bm->words[word] & mask)) + goto found; + ++bm->filled; + ++bit; + mask <<= 1; + } + ++word; + bit = 0; + mask = 1; + } +found: + + /* grow the bitmask if necessary */ + if(!util_bitmask_resize(bm, bm->filled)) + return UTIL_BITMASK_INVALID_INDEX; + + assert(!(bm->words[word] & mask)); + bm->words[word] |= mask; + + return bm->filled++; +} + + +unsigned +util_bitmask_set(struct util_bitmask *bm, + unsigned index) +{ + unsigned word; + unsigned bit; + util_bitmask_word mask; + + assert(bm); + + /* grow the bitmask if necessary */ + if(!util_bitmask_resize(bm, index)) + return UTIL_BITMASK_INVALID_INDEX; + + word = index / UTIL_BITMASK_BITS_PER_WORD; + bit = index % UTIL_BITMASK_BITS_PER_WORD; + mask = 1 << bit; + + bm->words[word] |= mask; + + util_bitmask_filled_set(bm, index); + + return index; +} + + +void +util_bitmask_clear(struct util_bitmask *bm, + unsigned index) +{ + unsigned word; + unsigned bit; + util_bitmask_word mask; + + assert(bm); + + if(index >= bm->size) + return; + + word = index / UTIL_BITMASK_BITS_PER_WORD; + bit = index % UTIL_BITMASK_BITS_PER_WORD; + mask = 1 << bit; + + bm->words[word] &= ~mask; + + util_bitmask_filled_unset(bm, index); +} + + +boolean +util_bitmask_get(struct util_bitmask *bm, + unsigned index) +{ + unsigned word = index / UTIL_BITMASK_BITS_PER_WORD; + unsigned bit = index % UTIL_BITMASK_BITS_PER_WORD; + util_bitmask_word mask = 1 << bit; + + assert(bm); + + if(index < bm->filled) { + assert(bm->words[word] & mask); + return TRUE; + } + + if(index >= bm->size) + return FALSE; + + if(bm->words[word] & mask) { + util_bitmask_filled_set(bm, index); + return TRUE; + } + else + return FALSE; +} + + +unsigned +util_bitmask_get_next_index(struct util_bitmask *bm, + unsigned index) +{ + unsigned word = index / UTIL_BITMASK_BITS_PER_WORD; + unsigned bit = index % UTIL_BITMASK_BITS_PER_WORD; + util_bitmask_word mask = 1 << bit; + + if(index < bm->filled) { + assert(bm->words[word] & mask); + return index; + } + + if(index >= bm->size) { + return UTIL_BITMASK_INVALID_INDEX; + } + + /* Do a linear search */ + while(word < bm->size / UTIL_BITMASK_BITS_PER_WORD) { + while(bit < UTIL_BITMASK_BITS_PER_WORD) { + if(bm->words[word] & mask) { + if(index == bm->filled) { + ++bm->filled; + assert(bm->filled <= bm->size); + } + return index; + } + ++index; + ++bit; + mask <<= 1; + } + ++word; + bit = 0; + mask = 1; + } + + return UTIL_BITMASK_INVALID_INDEX; +} + + +unsigned +util_bitmask_get_first_index(struct util_bitmask *bm) +{ + return util_bitmask_get_next_index(bm, 0); +} + + +void +util_bitmask_destroy(struct util_bitmask *bm) +{ + assert(bm); + + FREE(bm->words); + FREE(bm); +} + diff --git a/mesalib/src/gallium/auxiliary/util/u_bitmask.h b/mesalib/src/gallium/auxiliary/util/u_bitmask.h new file mode 100644 index 000000000..179328ae9 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_bitmask.h @@ -0,0 +1,117 @@ +/************************************************************************** + * + * 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. + * + **************************************************************************/ + +/** + * @file + * Generic bitmask. + * + * @author Jose Fonseca + */ + +#ifndef U_HANDLE_BITMASK_H_ +#define U_HANDLE_BITMASK_H_ + + +#include "pipe/p_compiler.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +#define UTIL_BITMASK_INVALID_INDEX (~0U) + + +/** + * Abstract data type to represent arbitrary set of bits. + */ +struct util_bitmask; + + +struct util_bitmask * +util_bitmask_create(void); + + +/** + * Search a cleared bit and set it. + * + * It searches for the first cleared bit. + * + * Returns the bit index on success, or UTIL_BITMASK_INVALID_INDEX on out of + * memory growing the bitmask. + */ +unsigned +util_bitmask_add(struct util_bitmask *bm); + +/** + * Set a bit. + * + * Returns the input index on success, or UTIL_BITMASK_INVALID_INDEX on out of + * memory growing the bitmask. + */ +unsigned +util_bitmask_set(struct util_bitmask *bm, + unsigned index); + +void +util_bitmask_clear(struct util_bitmask *bm, + unsigned index); + +boolean +util_bitmask_get(struct util_bitmask *bm, + unsigned index); + + +void +util_bitmask_destroy(struct util_bitmask *bm); + + +/** + * Search for the first set bit. + * + * Returns UTIL_BITMASK_INVALID_INDEX if a set bit cannot be found. + */ +unsigned +util_bitmask_get_first_index(struct util_bitmask *bm); + + +/** + * Search for the first set bit, starting from the giving index. + * + * Returns UTIL_BITMASK_INVALID_INDEX if a set bit cannot be found. + */ +unsigned +util_bitmask_get_next_index(struct util_bitmask *bm, + unsigned index); + + +#ifdef __cplusplus +} +#endif + +#endif /* U_HANDLE_BITMASK_H_ */ diff --git a/mesalib/src/gallium/auxiliary/util/u_blit.c b/mesalib/src/gallium/auxiliary/util/u_blit.c new file mode 100644 index 000000000..e892a4a77 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_blit.c @@ -0,0 +1,790 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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 TUNGSTEN GRAPHICS 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 + * Copy/blit pixel rect between surfaces + * + * @author Brian Paul + */ + + +#include "pipe/p_context.h" +#include "util/u_debug.h" +#include "pipe/p_defines.h" +#include "util/u_inlines.h" +#include "pipe/p_shader_tokens.h" +#include "pipe/p_state.h" + +#include "util/u_blit.h" +#include "util/u_draw_quad.h" +#include "util/u_format.h" +#include "util/u_math.h" +#include "util/u_memory.h" +#include "util/u_sampler.h" +#include "util/u_simple_shaders.h" + +#include "cso_cache/cso_context.h" + + +struct blit_state +{ + struct pipe_context *pipe; + struct cso_context *cso; + + struct pipe_blend_state blend; + struct pipe_depth_stencil_alpha_state depthstencil_keep; + struct pipe_depth_stencil_alpha_state depthstencil_write; + struct pipe_rasterizer_state rasterizer; + struct pipe_sampler_state sampler; + struct pipe_viewport_state viewport; + struct pipe_clip_state clip; + struct pipe_vertex_element velem[2]; + enum pipe_texture_target internal_target; + + void *vs; + void *fs[TGSI_WRITEMASK_XYZW + 1]; + void *fs_depth; + + struct pipe_resource *vbuf; /**< quad vertices */ + unsigned vbuf_slot; + + float vertices[4][2][4]; /**< vertex/texcoords for quad */ +}; + + +/** + * Create state object for blit. + * Intended to be created once and re-used for many blit() calls. + */ +struct blit_state * +util_create_blit(struct pipe_context *pipe, struct cso_context *cso) +{ + struct blit_state *ctx; + uint i; + + ctx = CALLOC_STRUCT(blit_state); + if (!ctx) + return NULL; + + ctx->pipe = pipe; + ctx->cso = cso; + + /* disabled blending/masking */ + memset(&ctx->blend, 0, sizeof(ctx->blend)); + ctx->blend.rt[0].colormask = PIPE_MASK_RGBA; + + /* no-op depth/stencil/alpha */ + memset(&ctx->depthstencil_keep, 0, sizeof(ctx->depthstencil_keep)); + memset(&ctx->depthstencil_write, 0, sizeof(ctx->depthstencil_write)); + ctx->depthstencil_write.depth.enabled = 1; + ctx->depthstencil_write.depth.writemask = 1; + ctx->depthstencil_write.depth.func = PIPE_FUNC_ALWAYS; + + /* rasterizer */ + memset(&ctx->rasterizer, 0, sizeof(ctx->rasterizer)); + ctx->rasterizer.cull_face = PIPE_FACE_NONE; + ctx->rasterizer.gl_rasterization_rules = 1; + + /* samplers */ + memset(&ctx->sampler, 0, sizeof(ctx->sampler)); + ctx->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + ctx->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + ctx->sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + ctx->sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; + ctx->sampler.min_img_filter = 0; /* set later */ + ctx->sampler.mag_img_filter = 0; /* set later */ + + /* vertex elements state */ + memset(&ctx->velem[0], 0, sizeof(ctx->velem[0]) * 2); + for (i = 0; i < 2; i++) { + ctx->velem[i].src_offset = i * 4 * sizeof(float); + ctx->velem[i].instance_divisor = 0; + ctx->velem[i].vertex_buffer_index = 0; + ctx->velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + } + + ctx->vbuf = NULL; + + /* init vertex data that doesn't change */ + for (i = 0; i < 4; i++) { + ctx->vertices[i][0][3] = 1.0f; /* w */ + ctx->vertices[i][1][2] = 0.0f; /* r */ + ctx->vertices[i][1][3] = 1.0f; /* q */ + } + + if(pipe->screen->get_param(pipe->screen, PIPE_CAP_NPOT_TEXTURES)) + ctx->internal_target = PIPE_TEXTURE_2D; + else + ctx->internal_target = PIPE_TEXTURE_RECT; + + return ctx; +} + + +/** + * Destroy a blit context + */ +void +util_destroy_blit(struct blit_state *ctx) +{ + struct pipe_context *pipe = ctx->pipe; + unsigned i; + + if (ctx->vs) + pipe->delete_vs_state(pipe, ctx->vs); + + for (i = 0; i < Elements(ctx->fs); i++) + if (ctx->fs[i]) + pipe->delete_fs_state(pipe, ctx->fs[i]); + + if (ctx->fs_depth) + pipe->delete_fs_state(pipe, ctx->fs_depth); + + pipe_resource_reference(&ctx->vbuf, NULL); + + FREE(ctx); +} + + +/** + * Helper function to set the fragment shaders. + */ +static INLINE void +set_fragment_shader(struct blit_state *ctx, uint writemask) +{ + if (!ctx->fs[writemask]) + ctx->fs[writemask] = + util_make_fragment_tex_shader_writemask(ctx->pipe, TGSI_TEXTURE_2D, + TGSI_INTERPOLATE_LINEAR, + writemask); + + cso_set_fragment_shader_handle(ctx->cso, ctx->fs[writemask]); +} + + +/** + * Helper function to set the depthwrite shader. + */ +static INLINE void +set_depth_fragment_shader(struct blit_state *ctx) +{ + if (!ctx->fs_depth) + ctx->fs_depth = + util_make_fragment_tex_shader_writedepth(ctx->pipe, TGSI_TEXTURE_2D, + TGSI_INTERPOLATE_LINEAR); + + cso_set_fragment_shader_handle(ctx->cso, ctx->fs_depth); +} + + +/** + * Helper function to set the vertex shader. + */ +static INLINE void +set_vertex_shader(struct blit_state *ctx) +{ + /* vertex shader - still required to provide the linkage between + * fragment shader input semantics and vertex_element/buffers. + */ + if (!ctx->vs) { + const uint semantic_names[] = { TGSI_SEMANTIC_POSITION, + TGSI_SEMANTIC_GENERIC }; + const uint semantic_indexes[] = { 0, 0 }; + ctx->vs = util_make_vertex_passthrough_shader(ctx->pipe, 2, + semantic_names, + semantic_indexes); + } + + cso_set_vertex_shader_handle(ctx->cso, ctx->vs); +} + + +/** + * Get offset of next free slot in vertex buffer for quad vertices. + */ +static unsigned +get_next_slot( struct blit_state *ctx ) +{ + const unsigned max_slots = 4096 / sizeof ctx->vertices; + + if (ctx->vbuf_slot >= max_slots) + util_blit_flush( ctx ); + + if (!ctx->vbuf) { + ctx->vbuf = pipe_buffer_create(ctx->pipe->screen, + PIPE_BIND_VERTEX_BUFFER, + PIPE_USAGE_STREAM, + max_slots * sizeof ctx->vertices); + } + + return ctx->vbuf_slot++ * sizeof ctx->vertices; +} + + + + +/** + * Setup vertex data for the textured quad we'll draw. + * Note: y=0=top + */ +static unsigned +setup_vertex_data_tex(struct blit_state *ctx, + float x0, float y0, float x1, float y1, + float s0, float t0, float s1, float t1, + float z) +{ + unsigned offset; + + ctx->vertices[0][0][0] = x0; + ctx->vertices[0][0][1] = y0; + ctx->vertices[0][0][2] = z; + ctx->vertices[0][1][0] = s0; /*s*/ + ctx->vertices[0][1][1] = t0; /*t*/ + + ctx->vertices[1][0][0] = x1; + ctx->vertices[1][0][1] = y0; + ctx->vertices[1][0][2] = z; + ctx->vertices[1][1][0] = s1; /*s*/ + ctx->vertices[1][1][1] = t0; /*t*/ + + ctx->vertices[2][0][0] = x1; + ctx->vertices[2][0][1] = y1; + ctx->vertices[2][0][2] = z; + ctx->vertices[2][1][0] = s1; + ctx->vertices[2][1][1] = t1; + + ctx->vertices[3][0][0] = x0; + ctx->vertices[3][0][1] = y1; + ctx->vertices[3][0][2] = z; + ctx->vertices[3][1][0] = s0; + ctx->vertices[3][1][1] = t1; + + offset = get_next_slot( ctx ); + + pipe_buffer_write_nooverlap(ctx->pipe, ctx->vbuf, + offset, sizeof(ctx->vertices), ctx->vertices); + + return offset; +} + + +/** + * \return TRUE if two regions overlap, FALSE otherwise + */ +static boolean +regions_overlap(int srcX0, int srcY0, + int srcX1, int srcY1, + int dstX0, int dstY0, + int dstX1, int dstY1) +{ + if (MAX2(srcX0, srcX1) < MIN2(dstX0, dstX1)) + return FALSE; /* src completely left of dst */ + + if (MAX2(dstX0, dstX1) < MIN2(srcX0, srcX1)) + return FALSE; /* dst completely left of src */ + + if (MAX2(srcY0, srcY1) < MIN2(dstY0, dstY1)) + return FALSE; /* src completely above dst */ + + if (MAX2(dstY0, dstY1) < MIN2(srcY0, srcY1)) + return FALSE; /* dst completely above src */ + + return TRUE; /* some overlap */ +} + + +/** + * Copy pixel block from src surface to dst surface. + * Overlapping regions are acceptable. + * Flipping and stretching are supported. + * \param filter one of PIPE_TEX_MIPFILTER_NEAREST/LINEAR + * \param writemask controls which channels in the dest surface are sourced + * from the src surface. Disabled channels are sourced + * from (0,0,0,1). + * XXX need some control over blitting stencil. + */ +void +util_blit_pixels_writemask(struct blit_state *ctx, + struct pipe_resource *src_tex, + unsigned src_level, + int srcX0, int srcY0, + int srcX1, int srcY1, + int srcZ0, + struct pipe_surface *dst, + int dstX0, int dstY0, + int dstX1, int dstY1, + float z, uint filter, + uint writemask) +{ + struct pipe_context *pipe = ctx->pipe; + struct pipe_screen *screen = pipe->screen; + enum pipe_format src_format, dst_format; + struct pipe_sampler_view *sampler_view = NULL; + struct pipe_sampler_view sv_templ; + struct pipe_surface *dst_surface; + struct pipe_framebuffer_state fb; + const int srcW = abs(srcX1 - srcX0); + const int srcH = abs(srcY1 - srcY0); + unsigned offset; + boolean overlap, dst_is_depth; + float s0, t0, s1, t1; + boolean normalized; + + assert(filter == PIPE_TEX_MIPFILTER_NEAREST || + filter == PIPE_TEX_MIPFILTER_LINEAR); + + assert(src_level <= src_tex->last_level); + + /* do the regions overlap? */ + overlap = src_tex == dst->texture && + dst->u.tex.level == src_level && + dst->u.tex.first_layer == srcZ0 && + regions_overlap(srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1); + + src_format = util_format_linear(src_tex->format); + dst_format = util_format_linear(dst->format); + + /* + * Check for simple case: no format conversion, no flipping, no stretching, + * no overlapping. + * Filter mode should not matter since there's no stretching. + */ + if (dst_format == src_format && + srcX0 < srcX1 && + dstX0 < dstX1 && + srcY0 < srcY1 && + dstY0 < dstY1 && + (dstX1 - dstX0) == (srcX1 - srcX0) && + (dstY1 - dstY0) == (srcY1 - srcY0) && + !overlap) { + struct pipe_box src_box; + src_box.x = srcX0; + src_box.y = srcY0; + src_box.z = srcZ0; + src_box.width = srcW; + src_box.height = srcH; + src_box.depth = 1; + pipe->resource_copy_region(pipe, + dst->texture, dst->u.tex.level, + dstX0, dstY0, dst->u.tex.first_layer,/* dest */ + src_tex, src_level, + &src_box); + return; + } + + if (dst_format == dst->format) { + dst_surface = dst; + } else { + struct pipe_surface templ = *dst; + templ.format = dst_format; + dst_surface = pipe->create_surface(pipe, dst->texture, &templ); + } + + /* Create a temporary texture when src and dest alias or when src + * is anything other than a 2d texture. + * XXX should just use appropriate shader to access 1d / 3d slice / cube face, + * much like the u_blitter code does (should be pretty trivial). + * + * This can still be improved upon. + */ + if ((src_tex == dst_surface->texture && + dst_surface->u.tex.level == src_level && + dst_surface->u.tex.first_layer == srcZ0) || + (src_tex->target != PIPE_TEXTURE_2D && + src_tex->target != PIPE_TEXTURE_2D && + src_tex->target != PIPE_TEXTURE_RECT)) + { + struct pipe_resource texTemp; + struct pipe_resource *tex; + struct pipe_sampler_view sv_templ; + struct pipe_box src_box; + const int srcLeft = MIN2(srcX0, srcX1); + const int srcTop = MIN2(srcY0, srcY1); + + if (srcLeft != srcX0) { + /* left-right flip */ + int tmp = dstX0; + dstX0 = dstX1; + dstX1 = tmp; + } + + if (srcTop != srcY0) { + /* up-down flip */ + int tmp = dstY0; + dstY0 = dstY1; + dstY1 = tmp; + } + + /* create temp texture */ + memset(&texTemp, 0, sizeof(texTemp)); + texTemp.target = ctx->internal_target; + texTemp.format = src_format; + texTemp.last_level = 0; + texTemp.width0 = srcW; + texTemp.height0 = srcH; + texTemp.depth0 = 1; + texTemp.array_size = 1; + texTemp.bind = PIPE_BIND_SAMPLER_VIEW; + + tex = screen->resource_create(screen, &texTemp); + if (!tex) + return; + + src_box.x = srcLeft; + src_box.y = srcTop; + src_box.z = srcZ0; + src_box.width = srcW; + src_box.height = srcH; + src_box.depth = 1; + /* load temp texture */ + pipe->resource_copy_region(pipe, + tex, 0, 0, 0, 0, /* dest */ + src_tex, src_level, &src_box); + + normalized = tex->target != PIPE_TEXTURE_RECT; + if(normalized) { + s0 = 0.0f; + s1 = 1.0f; + t0 = 0.0f; + t1 = 1.0f; + } + else { + s0 = 0; + s1 = srcW; + t0 = 0; + t1 = srcH; + } + + u_sampler_view_default_template(&sv_templ, tex, tex->format); + sampler_view = pipe->create_sampler_view(pipe, tex, &sv_templ); + + if (!sampler_view) { + pipe_resource_reference(&tex, NULL); + return; + } + pipe_resource_reference(&tex, NULL); + } + else { + u_sampler_view_default_template(&sv_templ, src_tex, src_format); + sampler_view = pipe->create_sampler_view(pipe, src_tex, &sv_templ); + + if (!sampler_view) { + return; + } + + s0 = srcX0; + s1 = srcX1; + t0 = srcY0; + t1 = srcY1; + normalized = sampler_view->texture->target != PIPE_TEXTURE_RECT; + if(normalized) + { + s0 /= (float)(u_minify(sampler_view->texture->width0, src_level)); + s1 /= (float)(u_minify(sampler_view->texture->width0, src_level)); + t0 /= (float)(u_minify(sampler_view->texture->height0, src_level)); + t1 /= (float)(u_minify(sampler_view->texture->height0, src_level)); + } + } + + dst_is_depth = util_format_is_depth_or_stencil(dst_format); + + assert(screen->is_format_supported(screen, sampler_view->format, ctx->internal_target, + sampler_view->texture->nr_samples, + PIPE_BIND_SAMPLER_VIEW)); + assert(screen->is_format_supported(screen, dst_format, ctx->internal_target, + dst_surface->texture->nr_samples, + dst_is_depth ? PIPE_BIND_DEPTH_STENCIL : + PIPE_BIND_RENDER_TARGET)); + /* save state (restored below) */ + cso_save_blend(ctx->cso); + cso_save_depth_stencil_alpha(ctx->cso); + cso_save_rasterizer(ctx->cso); + cso_save_samplers(ctx->cso); + cso_save_fragment_sampler_views(ctx->cso); + cso_save_viewport(ctx->cso); + cso_save_framebuffer(ctx->cso); + cso_save_fragment_shader(ctx->cso); + cso_save_vertex_shader(ctx->cso); + cso_save_clip(ctx->cso); + cso_save_vertex_elements(ctx->cso); + cso_save_vertex_buffers(ctx->cso); + + /* set misc state we care about */ + cso_set_blend(ctx->cso, &ctx->blend); + cso_set_depth_stencil_alpha(ctx->cso, + dst_is_depth ? &ctx->depthstencil_write : + &ctx->depthstencil_keep); + cso_set_rasterizer(ctx->cso, &ctx->rasterizer); + cso_set_clip(ctx->cso, &ctx->clip); + cso_set_vertex_elements(ctx->cso, 2, ctx->velem); + + /* sampler */ + ctx->sampler.normalized_coords = normalized; + ctx->sampler.min_img_filter = filter; + ctx->sampler.mag_img_filter = filter; + ctx->sampler.min_lod = src_level; + ctx->sampler.max_lod = src_level; + cso_single_sampler(ctx->cso, 0, &ctx->sampler); + cso_single_sampler_done(ctx->cso); + + /* viewport */ + ctx->viewport.scale[0] = 0.5f * dst_surface->width; + ctx->viewport.scale[1] = 0.5f * dst_surface->height; + ctx->viewport.scale[2] = 0.5f; + ctx->viewport.scale[3] = 1.0f; + ctx->viewport.translate[0] = 0.5f * dst_surface->width; + ctx->viewport.translate[1] = 0.5f * dst_surface->height; + ctx->viewport.translate[2] = 0.5f; + ctx->viewport.translate[3] = 0.0f; + cso_set_viewport(ctx->cso, &ctx->viewport); + + /* texture */ + cso_set_fragment_sampler_views(ctx->cso, 1, &sampler_view); + + /* shaders */ + if (dst_is_depth) { + set_depth_fragment_shader(ctx); + } else { + set_fragment_shader(ctx, writemask); + } + set_vertex_shader(ctx); + + /* drawing dest */ + memset(&fb, 0, sizeof(fb)); + fb.width = dst_surface->width; + fb.height = dst_surface->height; + if (dst_is_depth) { + fb.zsbuf = dst_surface; + } else { + fb.nr_cbufs = 1; + fb.cbufs[0] = dst_surface; + } + cso_set_framebuffer(ctx->cso, &fb); + + /* draw quad */ + offset = setup_vertex_data_tex(ctx, + (float) dstX0 / dst_surface->width * 2.0f - 1.0f, + (float) dstY0 / dst_surface->height * 2.0f - 1.0f, + (float) dstX1 / dst_surface->width * 2.0f - 1.0f, + (float) dstY1 / dst_surface->height * 2.0f - 1.0f, + s0, t0, + s1, t1, + z); + + util_draw_vertex_buffer(ctx->pipe, ctx->cso, ctx->vbuf, offset, + PIPE_PRIM_TRIANGLE_FAN, + 4, /* verts */ + 2); /* attribs/vert */ + + /* restore state we changed */ + cso_restore_blend(ctx->cso); + cso_restore_depth_stencil_alpha(ctx->cso); + cso_restore_rasterizer(ctx->cso); + cso_restore_samplers(ctx->cso); + cso_restore_fragment_sampler_views(ctx->cso); + cso_restore_viewport(ctx->cso); + cso_restore_framebuffer(ctx->cso); + cso_restore_fragment_shader(ctx->cso); + cso_restore_vertex_shader(ctx->cso); + cso_restore_clip(ctx->cso); + cso_restore_vertex_elements(ctx->cso); + cso_restore_vertex_buffers(ctx->cso); + + pipe_sampler_view_reference(&sampler_view, NULL); + if (dst_surface != dst) + pipe_surface_reference(&dst_surface, NULL); +} + + +void +util_blit_pixels(struct blit_state *ctx, + struct pipe_resource *src_tex, + unsigned src_level, + int srcX0, int srcY0, + int srcX1, int srcY1, + int srcZ, + struct pipe_surface *dst, + int dstX0, int dstY0, + int dstX1, int dstY1, + float z, uint filter ) +{ + util_blit_pixels_writemask( ctx, src_tex, + src_level, + srcX0, srcY0, + srcX1, srcY1, + srcZ, + dst, + dstX0, dstY0, + dstX1, dstY1, + z, filter, + TGSI_WRITEMASK_XYZW ); +} + + +/* Release vertex buffer at end of frame to avoid synchronous + * rendering. + */ +void util_blit_flush( struct blit_state *ctx ) +{ + pipe_resource_reference(&ctx->vbuf, NULL); + ctx->vbuf_slot = 0; +} + + + +/** + * Copy pixel block from src texture to dst surface. + * + * XXX Should support selection of level. + * XXX need some control over blitting Z and/or stencil. + */ +void +util_blit_pixels_tex(struct blit_state *ctx, + struct pipe_sampler_view *src_sampler_view, + int srcX0, int srcY0, + int srcX1, int srcY1, + struct pipe_surface *dst, + int dstX0, int dstY0, + int dstX1, int dstY1, + float z, uint filter) +{ + boolean normalized = src_sampler_view->texture->target != PIPE_TEXTURE_RECT; + struct pipe_framebuffer_state fb; + float s0, t0, s1, t1; + unsigned offset; + struct pipe_resource *tex = src_sampler_view->texture; + + assert(filter == PIPE_TEX_MIPFILTER_NEAREST || + filter == PIPE_TEX_MIPFILTER_LINEAR); + + assert(tex); + assert(tex->width0 != 0); + assert(tex->height0 != 0); + + s0 = srcX0; + s1 = srcX1; + t0 = srcY0; + t1 = srcY1; + + if(normalized) + { + s0 /= (float)tex->width0; + s1 /= (float)tex->width0; + t0 /= (float)tex->height0; + t1 /= (float)tex->height0; + } + + assert(ctx->pipe->screen->is_format_supported(ctx->pipe->screen, dst->format, + PIPE_TEXTURE_2D, + dst->texture->nr_samples, + PIPE_BIND_RENDER_TARGET)); + + /* save state (restored below) */ + cso_save_blend(ctx->cso); + cso_save_depth_stencil_alpha(ctx->cso); + cso_save_rasterizer(ctx->cso); + cso_save_samplers(ctx->cso); + cso_save_fragment_sampler_views(ctx->cso); + cso_save_viewport(ctx->cso); + cso_save_framebuffer(ctx->cso); + cso_save_fragment_shader(ctx->cso); + cso_save_vertex_shader(ctx->cso); + cso_save_clip(ctx->cso); + cso_save_vertex_elements(ctx->cso); + cso_save_vertex_buffers(ctx->cso); + + /* set misc state we care about */ + cso_set_blend(ctx->cso, &ctx->blend); + cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil_keep); + cso_set_rasterizer(ctx->cso, &ctx->rasterizer); + cso_set_clip(ctx->cso, &ctx->clip); + cso_set_vertex_elements(ctx->cso, 2, ctx->velem); + + /* sampler */ + ctx->sampler.normalized_coords = normalized; + ctx->sampler.min_img_filter = filter; + ctx->sampler.mag_img_filter = filter; + cso_single_sampler(ctx->cso, 0, &ctx->sampler); + cso_single_sampler_done(ctx->cso); + + /* viewport */ + ctx->viewport.scale[0] = 0.5f * dst->width; + ctx->viewport.scale[1] = 0.5f * dst->height; + ctx->viewport.scale[2] = 0.5f; + ctx->viewport.scale[3] = 1.0f; + ctx->viewport.translate[0] = 0.5f * dst->width; + ctx->viewport.translate[1] = 0.5f * dst->height; + ctx->viewport.translate[2] = 0.5f; + ctx->viewport.translate[3] = 0.0f; + cso_set_viewport(ctx->cso, &ctx->viewport); + + /* texture */ + cso_set_fragment_sampler_views(ctx->cso, 1, &src_sampler_view); + + /* shaders */ + set_fragment_shader(ctx, TGSI_WRITEMASK_XYZW); + set_vertex_shader(ctx); + + /* drawing dest */ + memset(&fb, 0, sizeof(fb)); + fb.width = dst->width; + fb.height = dst->height; + fb.nr_cbufs = 1; + fb.cbufs[0] = dst; + cso_set_framebuffer(ctx->cso, &fb); + + /* draw quad */ + offset = setup_vertex_data_tex(ctx, + (float) dstX0 / dst->width * 2.0f - 1.0f, + (float) dstY0 / dst->height * 2.0f - 1.0f, + (float) dstX1 / dst->width * 2.0f - 1.0f, + (float) dstY1 / dst->height * 2.0f - 1.0f, + s0, t0, s1, t1, + z); + + util_draw_vertex_buffer(ctx->pipe, ctx->cso, + ctx->vbuf, offset, + PIPE_PRIM_TRIANGLE_FAN, + 4, /* verts */ + 2); /* attribs/vert */ + + /* restore state we changed */ + cso_restore_blend(ctx->cso); + cso_restore_depth_stencil_alpha(ctx->cso); + cso_restore_rasterizer(ctx->cso); + cso_restore_samplers(ctx->cso); + cso_restore_fragment_sampler_views(ctx->cso); + cso_restore_viewport(ctx->cso); + cso_restore_framebuffer(ctx->cso); + cso_restore_fragment_shader(ctx->cso); + cso_restore_vertex_shader(ctx->cso); + cso_restore_clip(ctx->cso); + cso_restore_vertex_elements(ctx->cso); + cso_restore_vertex_buffers(ctx->cso); +} diff --git a/mesalib/src/gallium/auxiliary/util/u_blit.h b/mesalib/src/gallium/auxiliary/util/u_blit.h new file mode 100644 index 000000000..23a427d34 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_blit.h @@ -0,0 +1,98 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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 TUNGSTEN GRAPHICS 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 U_BLIT_H +#define U_BLIT_H + + +#include "pipe/p_compiler.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +struct cso_context; +struct pipe_context; +struct pipe_resource; +struct pipe_sampler_view; +struct pipe_surface; + + +extern struct blit_state * +util_create_blit(struct pipe_context *pipe, struct cso_context *cso); + +extern void +util_destroy_blit(struct blit_state *ctx); + +extern void +util_blit_pixels(struct blit_state *ctx, + struct pipe_resource *src_tex, + unsigned src_level, + int srcX0, int srcY0, + int srcX1, int srcY1, + int srcZ0, + struct pipe_surface *dst, + int dstX0, int dstY0, + int dstX1, int dstY1, + float z, uint filter); + +void +util_blit_pixels_writemask(struct blit_state *ctx, + struct pipe_resource *src_tex, + unsigned src_level, + int srcX0, int srcY0, + int srcX1, int srcY1, + int srcZ0, + struct pipe_surface *dst, + int dstX0, int dstY0, + int dstX1, int dstY1, + float z, uint filter, + uint writemask); + +extern void +util_blit_pixels_tex(struct blit_state *ctx, + struct pipe_sampler_view *src_sampler_view, + int srcX0, int srcY0, + int srcX1, int srcY1, + struct pipe_surface *dst, + int dstX0, int dstY0, + int dstX1, int dstY1, + float z, uint filter); + +/* Call at end of frame to avoid synchronous rendering. + */ +extern void +util_blit_flush( struct blit_state *ctx ); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/mesalib/src/gallium/auxiliary/util/u_blitter.c b/mesalib/src/gallium/auxiliary/util/u_blitter.c new file mode 100644 index 000000000..0d9ce9ff7 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_blitter.c @@ -0,0 +1,1036 @@ +/************************************************************************** + * + * Copyright 2009 Marek Olšák + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and 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 TUNGSTEN GRAPHICS 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 + * Blitter utility to facilitate acceleration of the clear, clear_render_target, clear_depth_stencil + * resource_copy_region functions. + * + * @author Marek Olšák + */ + +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "util/u_inlines.h" +#include "pipe/p_shader_tokens.h" +#include "pipe/p_state.h" + +#include "util/u_format.h" +#include "util/u_memory.h" +#include "util/u_math.h" +#include "util/u_blitter.h" +#include "util/u_draw_quad.h" +#include "util/u_sampler.h" +#include "util/u_simple_shaders.h" +#include "util/u_surface.h" +#include "util/u_texture.h" + +#define INVALID_PTR ((void*)~0) + +struct blitter_context_priv +{ + struct blitter_context base; + + struct pipe_resource *vbuf; /**< quad */ + + float vertices[4][2][4]; /**< {pos, color} or {pos, texcoord} */ + + /* Templates for various state objects. */ + struct pipe_sampler_state template_sampler_state; + + /* Constant state objects. */ + /* Vertex shaders. */ + void *vs; /**< Vertex shader which passes {pos, generic} to the output.*/ + + /* Fragment shaders. */ + /* The shader at index i outputs color to color buffers 0,1,...,i-1. */ + void *fs_col[PIPE_MAX_COLOR_BUFS+1]; + + /* FS which outputs a color from a texture, + where the index is PIPE_TEXTURE_* to be sampled. */ + void *fs_texfetch_col[PIPE_MAX_TEXTURE_TYPES]; + + /* FS which outputs a depth from a texture, + where the index is PIPE_TEXTURE_* to be sampled. */ + void *fs_texfetch_depth[PIPE_MAX_TEXTURE_TYPES]; + + /* Blend state. */ + void *blend_write_color; /**< blend state with writemask of RGBA */ + void *blend_keep_color; /**< blend state with writemask of 0 */ + + /* Depth stencil alpha state. */ + void *dsa_write_depth_stencil; + void *dsa_write_depth_keep_stencil; + void *dsa_keep_depth_stencil; + void *dsa_keep_depth_write_stencil; + + void *velem_state; + + /* Sampler state for clamping to a miplevel. */ + void *sampler_state[PIPE_MAX_TEXTURE_LEVELS * 2]; + + /* Rasterizer state. */ + void *rs_state; + + /* Viewport state. */ + struct pipe_viewport_state viewport; + + /* Clip state. */ + struct pipe_clip_state clip; + + /* Destination surface dimensions. */ + unsigned dst_width; + unsigned dst_height; +}; + +static void blitter_draw_rectangle(struct blitter_context *blitter, + unsigned x, unsigned y, + unsigned width, unsigned height, + float depth, + enum blitter_attrib_type type, + const float attrib[4]); + + +struct blitter_context *util_blitter_create(struct pipe_context *pipe) +{ + struct blitter_context_priv *ctx; + struct pipe_blend_state blend; + struct pipe_depth_stencil_alpha_state dsa; + struct pipe_rasterizer_state rs_state; + struct pipe_sampler_state *sampler_state; + struct pipe_vertex_element velem[2]; + unsigned i; + + ctx = CALLOC_STRUCT(blitter_context_priv); + if (!ctx) + return NULL; + + ctx->base.pipe = pipe; + ctx->base.draw_rectangle = blitter_draw_rectangle; + + /* init state objects for them to be considered invalid */ + ctx->base.saved_blend_state = INVALID_PTR; + ctx->base.saved_dsa_state = INVALID_PTR; + ctx->base.saved_rs_state = INVALID_PTR; + ctx->base.saved_fs = INVALID_PTR; + ctx->base.saved_vs = INVALID_PTR; + ctx->base.saved_velem_state = INVALID_PTR; + ctx->base.saved_fb_state.nr_cbufs = ~0; + ctx->base.saved_num_sampler_views = ~0; + ctx->base.saved_num_sampler_states = ~0; + ctx->base.saved_num_vertex_buffers = ~0; + + /* blend state objects */ + memset(&blend, 0, sizeof(blend)); + ctx->blend_keep_color = pipe->create_blend_state(pipe, &blend); + + blend.rt[0].colormask = PIPE_MASK_RGBA; + ctx->blend_write_color = pipe->create_blend_state(pipe, &blend); + + /* depth stencil alpha state objects */ + memset(&dsa, 0, sizeof(dsa)); + ctx->dsa_keep_depth_stencil = + pipe->create_depth_stencil_alpha_state(pipe, &dsa); + + dsa.depth.enabled = 1; + dsa.depth.writemask = 1; + dsa.depth.func = PIPE_FUNC_ALWAYS; + ctx->dsa_write_depth_keep_stencil = + pipe->create_depth_stencil_alpha_state(pipe, &dsa); + + dsa.stencil[0].enabled = 1; + dsa.stencil[0].func = PIPE_FUNC_ALWAYS; + dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE; + dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE; + dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE; + dsa.stencil[0].valuemask = 0xff; + dsa.stencil[0].writemask = 0xff; + ctx->dsa_write_depth_stencil = + pipe->create_depth_stencil_alpha_state(pipe, &dsa); + + + dsa.depth.enabled = 0; + dsa.depth.writemask = 0; + ctx->dsa_keep_depth_write_stencil = + pipe->create_depth_stencil_alpha_state(pipe, &dsa); + + /* sampler state */ + sampler_state = &ctx->template_sampler_state; + sampler_state->wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + sampler_state->wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + sampler_state->wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + sampler_state->normalized_coords = TRUE; + /* The sampler state objects which sample from a specified mipmap level + * are created on-demand. */ + + /* rasterizer state */ + memset(&rs_state, 0, sizeof(rs_state)); + rs_state.cull_face = PIPE_FACE_NONE; + rs_state.gl_rasterization_rules = 1; + rs_state.flatshade = 1; + ctx->rs_state = pipe->create_rasterizer_state(pipe, &rs_state); + + /* vertex elements state */ + memset(&velem[0], 0, sizeof(velem[0]) * 2); + for (i = 0; i < 2; i++) { + velem[i].src_offset = i * 4 * sizeof(float); + velem[i].instance_divisor = 0; + velem[i].vertex_buffer_index = 0; + velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + } + ctx->velem_state = pipe->create_vertex_elements_state(pipe, 2, &velem[0]); + + /* fragment shaders are created on-demand */ + + /* vertex shader */ + { + const uint semantic_names[] = { TGSI_SEMANTIC_POSITION, + TGSI_SEMANTIC_GENERIC }; + const uint semantic_indices[] = { 0, 0 }; + ctx->vs = + util_make_vertex_passthrough_shader(pipe, 2, semantic_names, + semantic_indices); + } + + /* set invariant vertex coordinates */ + for (i = 0; i < 4; i++) + ctx->vertices[i][0][3] = 1; /*v.w*/ + + /* create the vertex buffer */ + ctx->vbuf = pipe_user_buffer_create(ctx->base.pipe->screen, + ctx->vertices, + sizeof(ctx->vertices), + PIPE_BIND_VERTEX_BUFFER); + + return &ctx->base; +} + +void util_blitter_destroy(struct blitter_context *blitter) +{ + struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; + struct pipe_context *pipe = blitter->pipe; + int i; + + pipe->delete_blend_state(pipe, ctx->blend_write_color); + pipe->delete_blend_state(pipe, ctx->blend_keep_color); + pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); + pipe->delete_depth_stencil_alpha_state(pipe, + ctx->dsa_write_depth_keep_stencil); + pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil); + pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil); + + pipe->delete_rasterizer_state(pipe, ctx->rs_state); + pipe->delete_vs_state(pipe, ctx->vs); + pipe->delete_vertex_elements_state(pipe, ctx->velem_state); + + for (i = 0; i < PIPE_MAX_TEXTURE_TYPES; i++) { + if (ctx->fs_texfetch_col[i]) + pipe->delete_fs_state(pipe, ctx->fs_texfetch_col[i]); + if (ctx->fs_texfetch_depth[i]) + pipe->delete_fs_state(pipe, ctx->fs_texfetch_depth[i]); + } + + for (i = 0; i <= PIPE_MAX_COLOR_BUFS; i++) + if (ctx->fs_col[i]) + pipe->delete_fs_state(pipe, ctx->fs_col[i]); + + for (i = 0; i < PIPE_MAX_TEXTURE_LEVELS * 2; i++) + if (ctx->sampler_state[i]) + pipe->delete_sampler_state(pipe, ctx->sampler_state[i]); + + pipe_resource_reference(&ctx->vbuf, NULL); + FREE(ctx); +} + +static void blitter_check_saved_CSOs(struct blitter_context_priv *ctx) +{ + if (ctx->base.running) { + _debug_printf("u_blitter: Caught recursion on save. " + "This is a driver bug.\n"); + } + ctx->base.running = TRUE; + + /* make sure these CSOs have been saved */ + assert(ctx->base.saved_blend_state != INVALID_PTR && + ctx->base.saved_dsa_state != INVALID_PTR && + ctx->base.saved_rs_state != INVALID_PTR && + ctx->base.saved_fs != INVALID_PTR && + ctx->base.saved_vs != INVALID_PTR && + ctx->base.saved_velem_state != INVALID_PTR); +} + +static void blitter_restore_CSOs(struct blitter_context_priv *ctx) +{ + struct pipe_context *pipe = ctx->base.pipe; + unsigned i; + + /* restore the state objects which are always required to be saved */ + pipe->bind_blend_state(pipe, ctx->base.saved_blend_state); + pipe->bind_depth_stencil_alpha_state(pipe, ctx->base.saved_dsa_state); + pipe->bind_rasterizer_state(pipe, ctx->base.saved_rs_state); + pipe->bind_fs_state(pipe, ctx->base.saved_fs); + pipe->bind_vs_state(pipe, ctx->base.saved_vs); + pipe->bind_vertex_elements_state(pipe, ctx->base.saved_velem_state); + + ctx->base.saved_blend_state = INVALID_PTR; + ctx->base.saved_dsa_state = INVALID_PTR; + ctx->base.saved_rs_state = INVALID_PTR; + ctx->base.saved_fs = INVALID_PTR; + ctx->base.saved_vs = INVALID_PTR; + ctx->base.saved_velem_state = INVALID_PTR; + + pipe->set_stencil_ref(pipe, &ctx->base.saved_stencil_ref); + pipe->set_viewport_state(pipe, &ctx->base.saved_viewport); + pipe->set_clip_state(pipe, &ctx->base.saved_clip); + + /* restore the state objects which are required to be saved before copy/fill + */ + if (ctx->base.saved_fb_state.nr_cbufs != ~0) { + pipe->set_framebuffer_state(pipe, &ctx->base.saved_fb_state); + util_unreference_framebuffer_state(&ctx->base.saved_fb_state); + ctx->base.saved_fb_state.nr_cbufs = ~0; + } + + if (ctx->base.saved_num_sampler_states != ~0) { + pipe->bind_fragment_sampler_states(pipe, + ctx->base.saved_num_sampler_states, + ctx->base.saved_sampler_states); + ctx->base.saved_num_sampler_states = ~0; + } + + if (ctx->base.saved_num_sampler_views != ~0) { + pipe->set_fragment_sampler_views(pipe, + ctx->base.saved_num_sampler_views, + ctx->base.saved_sampler_views); + + for (i = 0; i < ctx->base.saved_num_sampler_views; i++) + pipe_sampler_view_reference(&ctx->base.saved_sampler_views[i], + NULL); + + ctx->base.saved_num_sampler_views = ~0; + } + + if (ctx->base.saved_num_vertex_buffers != ~0) { + pipe->set_vertex_buffers(pipe, + ctx->base.saved_num_vertex_buffers, + ctx->base.saved_vertex_buffers); + + for (i = 0; i < ctx->base.saved_num_vertex_buffers; i++) { + if (ctx->base.saved_vertex_buffers[i].buffer) { + pipe_resource_reference(&ctx->base.saved_vertex_buffers[i].buffer, + NULL); + } + } + ctx->base.saved_num_vertex_buffers = ~0; + } + + if (!ctx->base.running) { + _debug_printf("u_blitter: Caught recursion on restore. " + "This is a driver bug.\n"); + } + ctx->base.running = FALSE; +} + +static void blitter_set_rectangle(struct blitter_context_priv *ctx, + unsigned x1, unsigned y1, + unsigned x2, unsigned y2, + float depth) +{ + int i; + + /* set vertex positions */ + ctx->vertices[0][0][0] = (float)x1 / ctx->dst_width * 2.0f - 1.0f; /*v0.x*/ + ctx->vertices[0][0][1] = (float)y1 / ctx->dst_height * 2.0f - 1.0f; /*v0.y*/ + + ctx->vertices[1][0][0] = (float)x2 / ctx->dst_width * 2.0f - 1.0f; /*v1.x*/ + ctx->vertices[1][0][1] = (float)y1 / ctx->dst_height * 2.0f - 1.0f; /*v1.y*/ + + ctx->vertices[2][0][0] = (float)x2 / ctx->dst_width * 2.0f - 1.0f; /*v2.x*/ + ctx->vertices[2][0][1] = (float)y2 / ctx->dst_height * 2.0f - 1.0f; /*v2.y*/ + + ctx->vertices[3][0][0] = (float)x1 / ctx->dst_width * 2.0f - 1.0f; /*v3.x*/ + ctx->vertices[3][0][1] = (float)y2 / ctx->dst_height * 2.0f - 1.0f; /*v3.y*/ + + for (i = 0; i < 4; i++) + ctx->vertices[i][0][2] = depth; /*z*/ + + /* viewport */ + ctx->viewport.scale[0] = 0.5f * ctx->dst_width; + ctx->viewport.scale[1] = 0.5f * ctx->dst_height; + ctx->viewport.scale[2] = 1.0f; + ctx->viewport.scale[3] = 1.0f; + ctx->viewport.translate[0] = 0.5f * ctx->dst_width; + ctx->viewport.translate[1] = 0.5f * ctx->dst_height; + ctx->viewport.translate[2] = 0.0f; + ctx->viewport.translate[3] = 0.0f; + ctx->base.pipe->set_viewport_state(ctx->base.pipe, &ctx->viewport); + + /* clip */ + ctx->base.pipe->set_clip_state(ctx->base.pipe, &ctx->clip); +} + +static void blitter_set_clear_color(struct blitter_context_priv *ctx, + const float *rgba) +{ + int i; + + if (rgba) { + for (i = 0; i < 4; i++) { + ctx->vertices[i][1][0] = rgba[0]; + ctx->vertices[i][1][1] = rgba[1]; + ctx->vertices[i][1][2] = rgba[2]; + ctx->vertices[i][1][3] = rgba[3]; + } + } else { + for (i = 0; i < 4; i++) { + ctx->vertices[i][1][0] = 0; + ctx->vertices[i][1][1] = 0; + ctx->vertices[i][1][2] = 0; + ctx->vertices[i][1][3] = 0; + } + } +} + +static void get_texcoords(struct pipe_resource *src, + unsigned level, + unsigned x1, unsigned y1, + unsigned x2, unsigned y2, + boolean normalized, float out[4]) +{ + if(normalized) + { + out[0] = x1 / (float)u_minify(src->width0, level); + out[1] = y1 / (float)u_minify(src->height0, level); + out[2] = x2 / (float)u_minify(src->width0, level); + out[3] = y2 / (float)u_minify(src->height0, level); + } + else + { + out[0] = x1; + out[1] = y1; + out[2] = x2; + out[3] = y2; + } +} + +static void set_texcoords_in_vertices(const float coord[4], + float *out, unsigned stride) +{ + out[0] = coord[0]; /*t0.s*/ + out[1] = coord[1]; /*t0.t*/ + out += stride; + out[0] = coord[2]; /*t1.s*/ + out[1] = coord[1]; /*t1.t*/ + out += stride; + out[0] = coord[2]; /*t2.s*/ + out[1] = coord[3]; /*t2.t*/ + out += stride; + out[0] = coord[0]; /*t3.s*/ + out[1] = coord[3]; /*t3.t*/ +} + +static void blitter_set_texcoords_2d(struct blitter_context_priv *ctx, + struct pipe_resource *src, + unsigned level, + unsigned x1, unsigned y1, + unsigned x2, unsigned y2) +{ + unsigned i; + float coord[4]; + + get_texcoords(src, level, x1, y1, x2, y2, TRUE, coord); + set_texcoords_in_vertices(coord, &ctx->vertices[0][1][0], 8); + + for (i = 0; i < 4; i++) { + ctx->vertices[i][1][2] = 0; /*r*/ + ctx->vertices[i][1][3] = 1; /*q*/ + } +} + +static void blitter_set_texcoords_3d(struct blitter_context_priv *ctx, + struct pipe_resource *src, + unsigned level, + unsigned zslice, + unsigned x1, unsigned y1, + unsigned x2, unsigned y2) +{ + int i; + float r = zslice / (float)u_minify(src->depth0, level); + + blitter_set_texcoords_2d(ctx, src, level, x1, y1, x2, y2); + + for (i = 0; i < 4; i++) + ctx->vertices[i][1][2] = r; /*r*/ +} + +static void blitter_set_texcoords_cube(struct blitter_context_priv *ctx, + struct pipe_resource *src, + unsigned level, unsigned face, + unsigned x1, unsigned y1, + unsigned x2, unsigned y2) +{ + int i; + float coord[4]; + float st[4][2]; + + get_texcoords(src, level, x1, y1, x2, y2, TRUE, coord); + set_texcoords_in_vertices(coord, &st[0][0], 2); + + util_map_texcoords2d_onto_cubemap(face, + /* pointer, stride in floats */ + &st[0][0], 2, + &ctx->vertices[0][1][0], 8); + + for (i = 0; i < 4; i++) + ctx->vertices[i][1][3] = 1; /*q*/ +} + +static void blitter_set_dst_dimensions(struct blitter_context_priv *ctx, + unsigned width, unsigned height) +{ + ctx->dst_width = width; + ctx->dst_height = height; +} + +static INLINE +void **blitter_get_sampler_state(struct blitter_context_priv *ctx, + int miplevel, boolean normalized) +{ + struct pipe_context *pipe = ctx->base.pipe; + struct pipe_sampler_state *sampler_state = &ctx->template_sampler_state; + + assert(miplevel < PIPE_MAX_TEXTURE_LEVELS); + + /* Create the sampler state on-demand. */ + if (!ctx->sampler_state[miplevel * 2 + normalized]) { + sampler_state->lod_bias = miplevel; + sampler_state->min_lod = miplevel; + sampler_state->max_lod = miplevel; + sampler_state->normalized_coords = normalized; + + ctx->sampler_state[miplevel * 2 + normalized] = pipe->create_sampler_state(pipe, + sampler_state); + } + + /* Return void** so that it can be passed to bind_fragment_sampler_states + * directly. */ + return &ctx->sampler_state[miplevel * 2 + normalized]; +} + +static INLINE +void *blitter_get_fs_col(struct blitter_context_priv *ctx, unsigned num_cbufs) +{ + struct pipe_context *pipe = ctx->base.pipe; + + assert(num_cbufs <= PIPE_MAX_COLOR_BUFS); + + if (!ctx->fs_col[num_cbufs]) + ctx->fs_col[num_cbufs] = + util_make_fragment_cloneinput_shader(pipe, num_cbufs, + TGSI_SEMANTIC_GENERIC, + TGSI_INTERPOLATE_LINEAR); + + return ctx->fs_col[num_cbufs]; +} + +/** Convert PIPE_TEXTURE_x to TGSI_TEXTURE_x */ +static unsigned +pipe_tex_to_tgsi_tex(enum pipe_texture_target pipe_tex_target) +{ + switch (pipe_tex_target) { + case PIPE_TEXTURE_1D: + return TGSI_TEXTURE_1D; + case PIPE_TEXTURE_2D: + return TGSI_TEXTURE_2D; + case PIPE_TEXTURE_RECT: + return TGSI_TEXTURE_RECT; + case PIPE_TEXTURE_3D: + return TGSI_TEXTURE_3D; + case PIPE_TEXTURE_CUBE: + return TGSI_TEXTURE_CUBE; + default: + assert(0 && "unexpected texture target"); + return TGSI_TEXTURE_UNKNOWN; + } +} + + +static INLINE +void *blitter_get_fs_texfetch_col(struct blitter_context_priv *ctx, + unsigned tex_target) +{ + struct pipe_context *pipe = ctx->base.pipe; + + assert(tex_target < PIPE_MAX_TEXTURE_TYPES); + + /* Create the fragment shader on-demand. */ + if (!ctx->fs_texfetch_col[tex_target]) { + unsigned tgsi_tex = pipe_tex_to_tgsi_tex(tex_target); + + ctx->fs_texfetch_col[tex_target] = + util_make_fragment_tex_shader(pipe, tgsi_tex, TGSI_INTERPOLATE_LINEAR); + } + + return ctx->fs_texfetch_col[tex_target]; +} + +static INLINE +void *blitter_get_fs_texfetch_depth(struct blitter_context_priv *ctx, + unsigned tex_target) +{ + struct pipe_context *pipe = ctx->base.pipe; + + assert(tex_target < PIPE_MAX_TEXTURE_TYPES); + + /* Create the fragment shader on-demand. */ + if (!ctx->fs_texfetch_depth[tex_target]) { + unsigned tgsi_tex = pipe_tex_to_tgsi_tex(tex_target); + + ctx->fs_texfetch_depth[tex_target] = + util_make_fragment_tex_shader_writedepth(pipe, tgsi_tex, + TGSI_INTERPOLATE_LINEAR); + } + + return ctx->fs_texfetch_depth[tex_target]; +} + +static void blitter_draw_rectangle(struct blitter_context *blitter, + unsigned x1, unsigned y1, + unsigned x2, unsigned y2, + float depth, + enum blitter_attrib_type type, + const float attrib[4]) +{ + struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; + + switch (type) { + case UTIL_BLITTER_ATTRIB_COLOR: + blitter_set_clear_color(ctx, attrib); + break; + + case UTIL_BLITTER_ATTRIB_TEXCOORD: + set_texcoords_in_vertices(attrib, &ctx->vertices[0][1][0], 8); + break; + + default:; + } + + blitter_set_rectangle(ctx, x1, y1, x2, y2, depth); + ctx->base.pipe->redefine_user_buffer(ctx->base.pipe, ctx->vbuf, + 0, ctx->vbuf->width0); + util_draw_vertex_buffer(ctx->base.pipe, NULL, ctx->vbuf, 0, + PIPE_PRIM_TRIANGLE_FAN, 4, 2); +} + +static void util_blitter_clear_custom(struct blitter_context *blitter, + unsigned width, unsigned height, + unsigned num_cbufs, + unsigned clear_buffers, + const float *rgba, + double depth, unsigned stencil, + void *custom_blend, void *custom_dsa) +{ + struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; + struct pipe_context *pipe = ctx->base.pipe; + struct pipe_stencil_ref sr = { { 0 } }; + + assert(num_cbufs <= PIPE_MAX_COLOR_BUFS); + + blitter_check_saved_CSOs(ctx); + + /* bind CSOs */ + if (custom_blend) { + pipe->bind_blend_state(pipe, custom_blend); + } else if (clear_buffers & PIPE_CLEAR_COLOR) { + pipe->bind_blend_state(pipe, ctx->blend_write_color); + } else { + pipe->bind_blend_state(pipe, ctx->blend_keep_color); + } + + if (custom_dsa) { + pipe->bind_depth_stencil_alpha_state(pipe, custom_dsa); + } else if ((clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL) { + pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil); + } else if (clear_buffers & PIPE_CLEAR_DEPTH) { + pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_keep_stencil); + } else if (clear_buffers & PIPE_CLEAR_STENCIL) { + pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil); + } else { + pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); + } + + sr.ref_value[0] = stencil & 0xff; + pipe->set_stencil_ref(pipe, &sr); + + pipe->bind_rasterizer_state(pipe, ctx->rs_state); + pipe->bind_vertex_elements_state(pipe, ctx->velem_state); + pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, num_cbufs)); + pipe->bind_vs_state(pipe, ctx->vs); + + blitter_set_dst_dimensions(ctx, width, height); + blitter->draw_rectangle(blitter, 0, 0, width, height, depth, + UTIL_BLITTER_ATTRIB_COLOR, rgba); + blitter_restore_CSOs(ctx); +} + +void util_blitter_clear(struct blitter_context *blitter, + unsigned width, unsigned height, + unsigned num_cbufs, + unsigned clear_buffers, + const float *rgba, + double depth, unsigned stencil) +{ + util_blitter_clear_custom(blitter, width, height, num_cbufs, + clear_buffers, rgba, depth, stencil, + NULL, NULL); +} + +void util_blitter_clear_depth_custom(struct blitter_context *blitter, + unsigned width, unsigned height, + double depth, void *custom_dsa) +{ + const float rgba[4] = {0, 0, 0, 0}; + util_blitter_clear_custom(blitter, width, height, 0, + 0, rgba, depth, 0, NULL, custom_dsa); +} + +static +boolean is_overlap(unsigned sx1, unsigned sx2, unsigned sy1, unsigned sy2, + unsigned dx1, unsigned dx2, unsigned dy1, unsigned dy2) +{ + return sx1 < dx2 && sx2 > dx1 && sy1 < dy2 && sy2 > dy1; +} + +void util_blitter_copy_region(struct blitter_context *blitter, + struct pipe_resource *dst, + unsigned dstlevel, + unsigned dstx, unsigned dsty, unsigned dstz, + struct pipe_resource *src, + unsigned srclevel, + const struct pipe_box *srcbox, + boolean ignore_stencil) +{ + struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; + struct pipe_context *pipe = ctx->base.pipe; + struct pipe_screen *screen = pipe->screen; + struct pipe_surface *dstsurf, surf_templ; + struct pipe_framebuffer_state fb_state; + struct pipe_sampler_view viewTempl, *view; + unsigned bind; + unsigned width = srcbox->width; + unsigned height = srcbox->height; + boolean is_stencil, is_depth; + boolean normalized; + + /* Give up if textures are not set. */ + assert(dst && src); + if (!dst || !src) + return; + + /* Sanity checks. */ + if (dst == src) { + assert(!is_overlap(srcbox->x, srcbox->x + width, srcbox->y, srcbox->y + height, + dstx, dstx + width, dsty, dsty + height)); + } + assert(src->target < PIPE_MAX_TEXTURE_TYPES); + /* XXX should handle 3d regions */ + assert(srcbox->depth == 1); + + /* Is this a ZS format? */ + is_depth = util_format_get_component_bits(src->format, UTIL_FORMAT_COLORSPACE_ZS, 0) != 0; + is_stencil = util_format_get_component_bits(src->format, UTIL_FORMAT_COLORSPACE_ZS, 1) != 0; + + if (is_depth || is_stencil) + bind = PIPE_BIND_DEPTH_STENCIL; + else + bind = PIPE_BIND_RENDER_TARGET; + + /* Check if we can sample from and render to the surfaces. */ + /* (assuming copying a stencil buffer is not possible) */ + if ((!ignore_stencil && is_stencil) || + !screen->is_format_supported(screen, dst->format, dst->target, + dst->nr_samples, bind) || + !screen->is_format_supported(screen, src->format, src->target, + src->nr_samples, PIPE_BIND_SAMPLER_VIEW)) { + ctx->base.running = TRUE; + util_resource_copy_region(pipe, dst, dstlevel, dstx, dsty, dstz, + src, srclevel, srcbox); + ctx->base.running = FALSE; + return; + } + + /* Get surface. */ + memset(&surf_templ, 0, sizeof(surf_templ)); + u_surface_default_template(&surf_templ, dst, bind); + surf_templ.format = util_format_linear(dst->format); + surf_templ.u.tex.level = dstlevel; + surf_templ.u.tex.first_layer = dstz; + surf_templ.u.tex.last_layer = dstz; + dstsurf = pipe->create_surface(pipe, dst, &surf_templ); + + /* Check whether the states are properly saved. */ + blitter_check_saved_CSOs(ctx); + assert(blitter->saved_fb_state.nr_cbufs != ~0); + assert(blitter->saved_num_sampler_views != ~0); + assert(blitter->saved_num_sampler_states != ~0); + + /* Initialize framebuffer state. */ + fb_state.width = dstsurf->width; + fb_state.height = dstsurf->height; + + if (is_depth) { + pipe->bind_blend_state(pipe, ctx->blend_keep_color); + pipe->bind_depth_stencil_alpha_state(pipe, + ctx->dsa_write_depth_keep_stencil); + pipe->bind_fs_state(pipe, + blitter_get_fs_texfetch_depth(ctx, src->target)); + + fb_state.nr_cbufs = 0; + fb_state.zsbuf = dstsurf; + } else { + pipe->bind_blend_state(pipe, ctx->blend_write_color); + pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); + pipe->bind_fs_state(pipe, + blitter_get_fs_texfetch_col(ctx, src->target)); + + fb_state.nr_cbufs = 1; + fb_state.cbufs[0] = dstsurf; + fb_state.zsbuf = 0; + } + + normalized = src->target != PIPE_TEXTURE_RECT; + + /* Initialize sampler view. */ + u_sampler_view_default_template(&viewTempl, src, util_format_linear(src->format)); + view = pipe->create_sampler_view(pipe, src, &viewTempl); + + /* Set rasterizer state, shaders, and textures. */ + pipe->bind_rasterizer_state(pipe, ctx->rs_state); + pipe->bind_vs_state(pipe, ctx->vs); + pipe->bind_fragment_sampler_states(pipe, 1, + blitter_get_sampler_state(ctx, srclevel, normalized)); + pipe->bind_vertex_elements_state(pipe, ctx->velem_state); + pipe->set_fragment_sampler_views(pipe, 1, &view); + pipe->set_framebuffer_state(pipe, &fb_state); + + blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height); + + switch (src->target) { + /* Draw the quad with the draw_rectangle callback. */ + case PIPE_TEXTURE_1D: + case PIPE_TEXTURE_2D: + case PIPE_TEXTURE_RECT: + { + /* Set texture coordinates. */ + float coord[4]; + get_texcoords(src, srclevel, srcbox->x, srcbox->y, + srcbox->x+width, srcbox->y+height, normalized, coord); + + /* Draw. */ + blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, 0, + UTIL_BLITTER_ATTRIB_TEXCOORD, coord); + } + break; + + /* Draw the quad with the generic codepath. */ + case PIPE_TEXTURE_3D: + case PIPE_TEXTURE_CUBE: + /* Set texture coordinates. */ + if (src->target == PIPE_TEXTURE_3D) + blitter_set_texcoords_3d(ctx, src, srclevel, srcbox->z, + srcbox->x, srcbox->y, + srcbox->x + width, srcbox->y + height); + else + blitter_set_texcoords_cube(ctx, src, srclevel, srcbox->z, + srcbox->x, srcbox->y, + srcbox->x + width, srcbox->y + height); + + /* Draw. */ + blitter_set_rectangle(ctx, dstx, dsty, dstx+width, dsty+height, 0); + ctx->base.pipe->redefine_user_buffer(ctx->base.pipe, ctx->vbuf, + 0, ctx->vbuf->width0); + util_draw_vertex_buffer(ctx->base.pipe, NULL, ctx->vbuf, 0, + PIPE_PRIM_TRIANGLE_FAN, 4, 2); + break; + + default: + assert(0); + return; + } + + blitter_restore_CSOs(ctx); + + pipe_surface_reference(&dstsurf, NULL); + pipe_sampler_view_reference(&view, NULL); +} + +/* Clear a region of a color surface to a constant value. */ +void util_blitter_clear_render_target(struct blitter_context *blitter, + struct pipe_surface *dstsurf, + const float *rgba, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height) +{ + struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; + struct pipe_context *pipe = ctx->base.pipe; + struct pipe_framebuffer_state fb_state; + + assert(dstsurf->texture); + if (!dstsurf->texture) + return; + + /* check the saved state */ + blitter_check_saved_CSOs(ctx); + assert(blitter->saved_fb_state.nr_cbufs != ~0); + + /* bind CSOs */ + pipe->bind_blend_state(pipe, ctx->blend_write_color); + pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); + pipe->bind_rasterizer_state(pipe, ctx->rs_state); + pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 1)); + pipe->bind_vs_state(pipe, ctx->vs); + pipe->bind_vertex_elements_state(pipe, ctx->velem_state); + + /* set a framebuffer state */ + fb_state.width = dstsurf->width; + fb_state.height = dstsurf->height; + fb_state.nr_cbufs = 1; + fb_state.cbufs[0] = dstsurf; + fb_state.zsbuf = 0; + pipe->set_framebuffer_state(pipe, &fb_state); + + blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height); + blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, 0, + UTIL_BLITTER_ATTRIB_COLOR, rgba); + blitter_restore_CSOs(ctx); +} + +/* Clear a region of a depth stencil surface. */ +void util_blitter_clear_depth_stencil(struct blitter_context *blitter, + struct pipe_surface *dstsurf, + unsigned clear_flags, + double depth, + unsigned stencil, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height) +{ + struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; + struct pipe_context *pipe = ctx->base.pipe; + struct pipe_framebuffer_state fb_state; + struct pipe_stencil_ref sr = { { 0 } }; + + assert(dstsurf->texture); + if (!dstsurf->texture) + return; + + /* check the saved state */ + blitter_check_saved_CSOs(ctx); + assert(blitter->saved_fb_state.nr_cbufs != ~0); + + /* bind CSOs */ + pipe->bind_blend_state(pipe, ctx->blend_keep_color); + if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL) { + sr.ref_value[0] = stencil & 0xff; + pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil); + pipe->set_stencil_ref(pipe, &sr); + } + else if (clear_flags & PIPE_CLEAR_DEPTH) { + pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_keep_stencil); + } + else if (clear_flags & PIPE_CLEAR_STENCIL) { + sr.ref_value[0] = stencil & 0xff; + pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil); + pipe->set_stencil_ref(pipe, &sr); + } + else + /* hmm that should be illegal probably, or make it a no-op somewhere */ + pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); + + pipe->bind_rasterizer_state(pipe, ctx->rs_state); + pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 0)); + pipe->bind_vs_state(pipe, ctx->vs); + pipe->bind_vertex_elements_state(pipe, ctx->velem_state); + + /* set a framebuffer state */ + fb_state.width = dstsurf->width; + fb_state.height = dstsurf->height; + fb_state.nr_cbufs = 0; + fb_state.cbufs[0] = 0; + fb_state.zsbuf = dstsurf; + pipe->set_framebuffer_state(pipe, &fb_state); + + blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height); + blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, depth, + UTIL_BLITTER_ATTRIB_NONE, NULL); + blitter_restore_CSOs(ctx); +} + +/* draw a rectangle across a region using a custom dsa stage - for r600g */ +void util_blitter_custom_depth_stencil(struct blitter_context *blitter, + struct pipe_surface *zsurf, + struct pipe_surface *cbsurf, + void *dsa_stage, float depth) +{ + struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; + struct pipe_context *pipe = ctx->base.pipe; + struct pipe_framebuffer_state fb_state; + + assert(zsurf->texture); + if (!zsurf->texture) + return; + + /* check the saved state */ + blitter_check_saved_CSOs(ctx); + assert(blitter->saved_fb_state.nr_cbufs != ~0); + + /* bind CSOs */ + pipe->bind_blend_state(pipe, ctx->blend_write_color); + pipe->bind_depth_stencil_alpha_state(pipe, dsa_stage); + + pipe->bind_rasterizer_state(pipe, ctx->rs_state); + pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 0)); + pipe->bind_vs_state(pipe, ctx->vs); + pipe->bind_vertex_elements_state(pipe, ctx->velem_state); + + /* set a framebuffer state */ + fb_state.width = zsurf->width; + fb_state.height = zsurf->height; + fb_state.nr_cbufs = 1; + if (cbsurf) { + fb_state.cbufs[0] = cbsurf; + fb_state.nr_cbufs = 1; + } else { + fb_state.cbufs[0] = NULL; + fb_state.nr_cbufs = 0; + } + fb_state.zsbuf = zsurf; + pipe->set_framebuffer_state(pipe, &fb_state); + + blitter_set_dst_dimensions(ctx, zsurf->width, zsurf->height); + blitter->draw_rectangle(blitter, 0, 0, zsurf->width, zsurf->height, depth, + UTIL_BLITTER_ATTRIB_NONE, NULL); + blitter_restore_CSOs(ctx); +} diff --git a/mesalib/src/gallium/auxiliary/util/u_blitter.h b/mesalib/src/gallium/auxiliary/util/u_blitter.h new file mode 100644 index 000000000..e59fe6b51 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_blitter.h @@ -0,0 +1,338 @@ +/************************************************************************** + * + * Copyright 2009 Marek Olšák + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and 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 TUNGSTEN GRAPHICS 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 U_BLITTER_H +#define U_BLITTER_H + +#include "util/u_framebuffer.h" +#include "util/u_inlines.h" +#include "util/u_memory.h" + +#include "pipe/p_state.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +struct pipe_context; + +enum blitter_attrib_type { + UTIL_BLITTER_ATTRIB_NONE, + UTIL_BLITTER_ATTRIB_COLOR, + UTIL_BLITTER_ATTRIB_TEXCOORD +}; + +struct blitter_context +{ + /** + * Draw a rectangle. + * + * \param x1 An X coordinate of the top-left corner. + * \param y1 A Y coordinate of the top-left corner. + * \param x2 An X coordinate of the bottom-right corner. + * \param y2 A Y coordinate of the bottom-right corner. + * \param depth A depth which the rectangle is rendered at. + * + * \param type Semantics of the attributes "attrib". + * If type is UTIL_BLITTER_ATTRIB_NONE, ignore them. + * If type is UTIL_BLITTER_ATTRIB_COLOR, the attributes + * make up a constant RGBA color, and should go + * to the GENERIC0 varying slot of a fragment shader. + * If type is UTIL_BLITTER_ATTRIB_TEXCOORD, {a1, a2} and + * {a3, a4} specify top-left and bottom-right texture + * coordinates of the rectangle, respectively, and should go + * to the GENERIC0 varying slot of a fragment shader. + * + * \param attrib See type. + * + * \note A driver may optionally override this callback to implement + * a specialized hardware path for drawing a rectangle, e.g. using + * a rectangular point sprite. + */ + void (*draw_rectangle)(struct blitter_context *blitter, + unsigned x1, unsigned y1, unsigned x2, unsigned y2, + float depth, + enum blitter_attrib_type type, + const float attrib[4]); + + /* Whether the blitter is running. */ + boolean running; + + /* Private members, really. */ + struct pipe_context *pipe; /**< pipe context */ + + void *saved_blend_state; /**< blend state */ + void *saved_dsa_state; /**< depth stencil alpha state */ + void *saved_velem_state; /**< vertex elements state */ + void *saved_rs_state; /**< rasterizer state */ + void *saved_fs, *saved_vs; /**< fragment shader, vertex shader */ + + struct pipe_framebuffer_state saved_fb_state; /**< framebuffer state */ + struct pipe_stencil_ref saved_stencil_ref; /**< stencil ref */ + struct pipe_viewport_state saved_viewport; + struct pipe_clip_state saved_clip; + + int saved_num_sampler_states; + void *saved_sampler_states[PIPE_MAX_SAMPLERS]; + + int saved_num_sampler_views; + struct pipe_sampler_view *saved_sampler_views[PIPE_MAX_SAMPLERS]; + + int saved_num_vertex_buffers; + struct pipe_vertex_buffer saved_vertex_buffers[PIPE_MAX_ATTRIBS]; +}; + +/** + * Create a blitter context. + */ +struct blitter_context *util_blitter_create(struct pipe_context *pipe); + +/** + * Destroy a blitter context. + */ +void util_blitter_destroy(struct blitter_context *blitter); + +/** + * Return the pipe context associated with a blitter context. + */ +static INLINE +struct pipe_context *util_blitter_get_pipe(struct blitter_context *blitter) +{ + return blitter->pipe; +} + +/* + * These CSOs must be saved before any of the following functions is called: + * - blend state + * - depth stencil alpha state + * - rasterizer state + * - vertex shader + * - fragment shader + */ + +/** + * Clear a specified set of currently bound buffers to specified values. + */ +void util_blitter_clear(struct blitter_context *blitter, + unsigned width, unsigned height, + unsigned num_cbufs, + unsigned clear_buffers, + const float *rgba, + double depth, unsigned stencil); + +void util_blitter_clear_depth_custom(struct blitter_context *blitter, + unsigned width, unsigned height, + double depth, void *custom_dsa); + +/** + * Copy a block of pixels from one surface to another. + * + * You can copy from any color format to any other color format provided + * the former can be sampled and the latter can be rendered to. Otherwise, + * a software fallback path is taken and both surfaces must be of the same + * format. + * + * The same holds for depth-stencil formats with the exception that stencil + * cannot be copied unless you set ignore_stencil to FALSE. In that case, + * a software fallback path is taken and both surfaces must be of the same + * format. + * + * Use pipe_screen->is_format_supported to know your options. + * + * These states must be saved in the blitter in addition to the state objects + * already required to be saved: + * - framebuffer state + * - fragment sampler states + * - fragment sampler textures + */ +void util_blitter_copy_region(struct blitter_context *blitter, + struct pipe_resource *dst, + unsigned dstlevel, + unsigned dstx, unsigned dsty, unsigned dstz, + struct pipe_resource *src, + unsigned srclevel, + const struct pipe_box *srcbox, + boolean ignore_stencil); + +/** + * Clear a region of a (color) surface to a constant value. + * + * These states must be saved in the blitter in addition to the state objects + * already required to be saved: + * - framebuffer state + */ +void util_blitter_clear_render_target(struct blitter_context *blitter, + struct pipe_surface *dst, + const float *rgba, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height); + +/** + * Clear a region of a depth-stencil surface, both stencil and depth + * or only one of them if this is a combined depth-stencil surface. + * + * These states must be saved in the blitter in addition to the state objects + * already required to be saved: + * - framebuffer state + */ +void util_blitter_clear_depth_stencil(struct blitter_context *blitter, + struct pipe_surface *dst, + unsigned clear_flags, + double depth, + unsigned stencil, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height); + +void util_blitter_custom_depth_stencil(struct blitter_context *blitter, + struct pipe_surface *zsurf, + struct pipe_surface *cbsurf, + void *dsa_stage, float depth); + +/* The functions below should be used to save currently bound constant state + * objects inside a driver. The objects are automatically restored at the end + * of the util_blitter_{clear, copy_region, fill_region} functions and then + * forgotten. + * + * CSOs not listed here are not affected by util_blitter. */ + +static INLINE +void util_blitter_save_blend(struct blitter_context *blitter, + void *state) +{ + blitter->saved_blend_state = state; +} + +static INLINE +void util_blitter_save_depth_stencil_alpha(struct blitter_context *blitter, + void *state) +{ + blitter->saved_dsa_state = state; +} + +static INLINE +void util_blitter_save_vertex_elements(struct blitter_context *blitter, + void *state) +{ + blitter->saved_velem_state = state; +} + +static INLINE +void util_blitter_save_stencil_ref(struct blitter_context *blitter, + const struct pipe_stencil_ref *state) +{ + blitter->saved_stencil_ref = *state; +} + +static INLINE +void util_blitter_save_rasterizer(struct blitter_context *blitter, + void *state) +{ + blitter->saved_rs_state = state; +} + +static INLINE +void util_blitter_save_fragment_shader(struct blitter_context *blitter, + void *fs) +{ + blitter->saved_fs = fs; +} + +static INLINE +void util_blitter_save_vertex_shader(struct blitter_context *blitter, + void *vs) +{ + blitter->saved_vs = vs; +} + +static INLINE +void util_blitter_save_framebuffer(struct blitter_context *blitter, + const struct pipe_framebuffer_state *state) +{ + blitter->saved_fb_state.nr_cbufs = 0; /* It's ~0 now, meaning it's unsaved. */ + util_copy_framebuffer_state(&blitter->saved_fb_state, state); +} + +static INLINE +void util_blitter_save_viewport(struct blitter_context *blitter, + struct pipe_viewport_state *state) +{ + blitter->saved_viewport = *state; +} + +static INLINE +void util_blitter_save_clip(struct blitter_context *blitter, + struct pipe_clip_state *state) +{ + blitter->saved_clip = *state; +} + +static INLINE +void util_blitter_save_fragment_sampler_states( + struct blitter_context *blitter, + int num_sampler_states, + void **sampler_states) +{ + assert(num_sampler_states <= Elements(blitter->saved_sampler_states)); + + blitter->saved_num_sampler_states = num_sampler_states; + memcpy(blitter->saved_sampler_states, sampler_states, + num_sampler_states * sizeof(void *)); +} + +static INLINE void +util_blitter_save_fragment_sampler_views(struct blitter_context *blitter, + int num_views, + struct pipe_sampler_view **views) +{ + unsigned i; + assert(num_views <= Elements(blitter->saved_sampler_views)); + + blitter->saved_num_sampler_views = num_views; + for (i = 0; i < num_views; i++) + pipe_sampler_view_reference(&blitter->saved_sampler_views[i], + views[i]); +} + +static INLINE void +util_blitter_save_vertex_buffers(struct blitter_context *blitter, + int num_vertex_buffers, + struct pipe_vertex_buffer *vertex_buffers) +{ + assert(num_vertex_buffers <= Elements(blitter->saved_vertex_buffers)); + + blitter->saved_num_vertex_buffers = 0; + util_copy_vertex_buffers(blitter->saved_vertex_buffers, + (unsigned*)&blitter->saved_num_vertex_buffers, + vertex_buffers, + num_vertex_buffers); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/mesalib/src/gallium/auxiliary/util/u_box.h b/mesalib/src/gallium/auxiliary/util/u_box.h new file mode 100644 index 000000000..f2f0829b5 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_box.h @@ -0,0 +1,80 @@ +#ifndef UTIL_BOX_INLINES_H +#define UTIL_BOX_INLINES_H + +#include "pipe/p_state.h" + +static INLINE +void u_box_1d( unsigned x, + unsigned w, + struct pipe_box *box ) +{ + box->x = x; + box->y = 0; + box->z = 0; + box->width = w; + box->height = 1; + box->depth = 1; +} + +static INLINE +void u_box_2d( unsigned x, + unsigned y, + unsigned w, + unsigned h, + struct pipe_box *box ) +{ + box->x = x; + box->y = y; + box->z = 0; + box->width = w; + box->height = h; + box->depth = 1; +} + +static INLINE +void u_box_origin_2d( unsigned w, + unsigned h, + struct pipe_box *box ) +{ + box->x = 0; + box->y = 0; + box->z = 0; + box->width = w; + box->height = h; + box->depth = 1; +} + +static INLINE +void u_box_2d_zslice( unsigned x, + unsigned y, + unsigned z, + unsigned w, + unsigned h, + struct pipe_box *box ) +{ + box->x = x; + box->y = y; + box->z = z; + box->width = w; + box->height = h; + box->depth = 1; +} + +static INLINE +void u_box_3d( unsigned x, + unsigned y, + unsigned z, + unsigned w, + unsigned h, + unsigned d, + struct pipe_box *box ) +{ + box->x = x; + box->y = y; + box->z = z; + box->width = w; + box->height = h; + box->depth = d; +} + +#endif diff --git a/mesalib/src/gallium/auxiliary/util/u_cache.c b/mesalib/src/gallium/auxiliary/util/u_cache.c new file mode 100644 index 000000000..215236818 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_cache.c @@ -0,0 +1,351 @@ +/************************************************************************** + * + * 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 + * Improved cache implementation. + * + * Fixed size array with linear probing on collision and LRU eviction + * on full. + * + * @author Jose Fonseca + */ + + +#include "pipe/p_compiler.h" +#include "util/u_debug.h" + +#include "util/u_math.h" +#include "util/u_memory.h" +#include "util/u_cache.h" +#include "util/u_simple_list.h" + + +struct util_cache_entry +{ + enum { EMPTY = 0, FILLED, DELETED } state; + uint32_t hash; + + struct util_cache_entry *next; + struct util_cache_entry *prev; + + void *key; + void *value; + +#ifdef DEBUG + unsigned count; +#endif +}; + + +struct util_cache +{ + /** Hash function */ + uint32_t (*hash)(const void *key); + + /** Compare two keys */ + int (*compare)(const void *key1, const void *key2); + + /** Destroy a (key, value) pair */ + void (*destroy)(void *key, void *value); + + uint32_t size; + + struct util_cache_entry *entries; + + unsigned count; + struct util_cache_entry lru; +}; + +static void +ensure_sanity(const struct util_cache *cache); + +#define CACHE_DEFAULT_ALPHA 2 + +struct util_cache * +util_cache_create(uint32_t (*hash)(const void *key), + int (*compare)(const void *key1, const void *key2), + void (*destroy)(void *key, void *value), + uint32_t size) +{ + struct util_cache *cache; + + cache = CALLOC_STRUCT(util_cache); + if(!cache) + return NULL; + + cache->hash = hash; + cache->compare = compare; + cache->destroy = destroy; + + make_empty_list(&cache->lru); + + size *= CACHE_DEFAULT_ALPHA; + cache->size = size; + + cache->entries = CALLOC(size, sizeof(struct util_cache_entry)); + if(!cache->entries) { + FREE(cache); + return NULL; + } + + ensure_sanity(cache); + return cache; +} + + +static struct util_cache_entry * +util_cache_entry_get(struct util_cache *cache, + uint32_t hash, + const void *key) +{ + struct util_cache_entry *first_unfilled = NULL; + uint32_t index = hash % cache->size; + uint32_t probe; + + /* Probe until we find either a matching FILLED entry or an EMPTY + * slot (which has never been occupied). + * + * Deleted or non-matching slots are not indicative of completion + * as a previous linear probe for the same key could have continued + * past this point. + */ + for (probe = 0; probe < cache->size; probe++) { + uint32_t i = (index + probe) % cache->size; + struct util_cache_entry *current = &cache->entries[i]; + + if (current->state == FILLED) { + if (current->hash == hash && + cache->compare(key, current->key) == 0) + return current; + } + else { + if (!first_unfilled) + first_unfilled = current; + + if (current->state == EMPTY) + return first_unfilled; + } + } + + return NULL; +} + +static INLINE void +util_cache_entry_destroy(struct util_cache *cache, + struct util_cache_entry *entry) +{ + void *key = entry->key; + void *value = entry->value; + + entry->key = NULL; + entry->value = NULL; + + if (entry->state == FILLED) { + remove_from_list(entry); + cache->count--; + + if(cache->destroy) + cache->destroy(key, value); + + entry->state = DELETED; + } +} + + +void +util_cache_set(struct util_cache *cache, + void *key, + void *value) +{ + struct util_cache_entry *entry; + uint32_t hash = cache->hash(key); + + assert(cache); + if (!cache) + return; + + entry = util_cache_entry_get(cache, hash, key); + if (!entry) + entry = cache->lru.prev; + + if (cache->count >= cache->size / CACHE_DEFAULT_ALPHA) + util_cache_entry_destroy(cache, cache->lru.prev); + + util_cache_entry_destroy(cache, entry); + +#ifdef DEBUG + ++entry->count; +#endif + + entry->key = key; + entry->hash = hash; + entry->value = value; + entry->state = FILLED; + insert_at_head(&cache->lru, entry); + cache->count++; + + ensure_sanity(cache); +} + + +void * +util_cache_get(struct util_cache *cache, + const void *key) +{ + struct util_cache_entry *entry; + uint32_t hash = cache->hash(key); + + assert(cache); + if (!cache) + return NULL; + + entry = util_cache_entry_get(cache, hash, key); + if (!entry) + return NULL; + + if (entry->state == FILLED) + move_to_head(&cache->lru, entry); + + return entry->value; +} + + +void +util_cache_clear(struct util_cache *cache) +{ + uint32_t i; + + assert(cache); + if (!cache) + return; + + for(i = 0; i < cache->size; ++i) { + util_cache_entry_destroy(cache, &cache->entries[i]); + cache->entries[i].state = EMPTY; + } + + assert(cache->count == 0); + assert(is_empty_list(&cache->lru)); + ensure_sanity(cache); +} + + +void +util_cache_destroy(struct util_cache *cache) +{ + assert(cache); + if (!cache) + return; + +#ifdef DEBUG + if(cache->count >= 20*cache->size) { + /* Normal approximation of the Poisson distribution */ + double mean = (double)cache->count/(double)cache->size; + double stddev = sqrt(mean); + unsigned i; + for(i = 0; i < cache->size; ++i) { + double z = fabs(cache->entries[i].count - mean)/stddev; + /* This assert should not fail 99.9999998027% of the times, unless + * the hash function is a poor one */ + assert(z <= 6.0); + } + } +#endif + + util_cache_clear(cache); + + FREE(cache->entries); + FREE(cache); +} + + +void +util_cache_remove(struct util_cache *cache, + const void *key) +{ + struct util_cache_entry *entry; + uint32_t hash; + + assert(cache); + if (!cache) + return; + + hash = cache->hash(key); + + entry = util_cache_entry_get(cache, hash, key); + if (!entry) + return; + + if (entry->state == FILLED) + util_cache_entry_destroy(cache, entry); + + ensure_sanity(cache); +} + + +static void +ensure_sanity(const struct util_cache *cache) +{ +#ifdef DEBUG + unsigned i, cnt = 0; + + assert(cache); + for (i = 0; i < cache->size; i++) { + struct util_cache_entry *header = &cache->entries[i]; + + assert(header); + assert(header->state == FILLED || + header->state == EMPTY || + header->state == DELETED); + if (header->state == FILLED) { + cnt++; + assert(header->hash == cache->hash(header->key)); + } + } + + assert(cnt == cache->count); + assert(cache->size >= cnt); + + if (cache->count == 0) { + assert (is_empty_list(&cache->lru)); + } + else { + struct util_cache_entry *header = cache->lru.next; + + assert (header); + assert (!is_empty_list(&cache->lru)); + + for (i = 0; i < cache->count; i++) + header = header->next; + + assert(header == &cache->lru); + } +#endif + + (void)cache; +} diff --git a/mesalib/src/gallium/auxiliary/util/u_cache.h b/mesalib/src/gallium/auxiliary/util/u_cache.h new file mode 100644 index 000000000..f88ccb2b2 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_cache.h @@ -0,0 +1,91 @@ +/************************************************************************** + * + * 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 + * Simple cache. + * + * @author Jose Fonseca + */ + +#ifndef U_CACHE_H_ +#define U_CACHE_H_ + + +#include "pipe/p_compiler.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Least Recently Used (LRU) cache. + */ +struct util_cache; + + +/** + * Create a cache. + * + * @param hash hash function + * @param compare should return 0 for two equal keys + * @param destroy destruction callback (optional) + * @param size maximum number of entries + */ +struct util_cache * +util_cache_create(uint32_t (*hash)(const void *key), + int (*compare)(const void *key1, const void *key2), + void (*destroy)(void *key, void *value), + uint32_t size); + +void +util_cache_set(struct util_cache *cache, + void *key, + void *value); + +void * +util_cache_get(struct util_cache *cache, + const void *key); + +void +util_cache_clear(struct util_cache *cache); + +void +util_cache_destroy(struct util_cache *cache); + +void +util_cache_remove(struct util_cache *cache, + const void *key); + + +#ifdef __cplusplus +} +#endif + +#endif /* U_CACHE_H_ */ diff --git a/mesalib/src/gallium/auxiliary/util/u_caps.c b/mesalib/src/gallium/auxiliary/util/u_caps.c new file mode 100644 index 000000000..fbe265d0e --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_caps.c @@ -0,0 +1,270 @@ +/************************************************************************** + * + * 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 "pipe/p_screen.h" +#include "util/u_format.h" +#include "util/u_debug.h" +#include "u_caps.h" + +/** + * Iterates over a list of caps checks as defined in u_caps.h. Should + * all checks pass returns TRUE and out is set to the last element of + * the list (TERMINATE). Should any check fail returns FALSE and set + * out to the index of the start of the first failing check. + */ +boolean +util_check_caps_out(struct pipe_screen *screen, const unsigned *list, int *out) +{ + int i, tmpi; + float tmpf; + + for (i = 0; list[i];) { + switch(list[i++]) { + case UTIL_CAPS_CHECK_CAP: + if (!screen->get_param(screen, list[i++])) { + *out = i - 2; + return FALSE; + } + break; + case UTIL_CAPS_CHECK_INT: + tmpi = screen->get_param(screen, list[i++]); + if (tmpi < (int)list[i++]) { + *out = i - 3; + return FALSE; + } + break; + case UTIL_CAPS_CHECK_FLOAT: + tmpf = screen->get_paramf(screen, list[i++]); + if (tmpf < (float)list[i++]) { + *out = i - 3; + return FALSE; + } + break; + case UTIL_CAPS_CHECK_FORMAT: + if (!screen->is_format_supported(screen, + list[i++], + PIPE_TEXTURE_2D, + 0, + PIPE_BIND_SAMPLER_VIEW)) { + *out = i - 2; + return FALSE; + } + break; + case UTIL_CAPS_CHECK_SHADER: + tmpi = screen->get_shader_param(screen, list[i] >> 24, list[i] & ((1 << 24) - 1)); + ++i; + if (tmpi < (int)list[i++]) { + *out = i - 3; + return FALSE; + } + break; + case UTIL_CAPS_CHECK_UNIMPLEMENTED: + *out = i - 1; + return FALSE; + default: + assert(!"Unsupported check"); + return FALSE; + } + } + + *out = i; + return TRUE; +} + +/** + * Iterates over a list of caps checks as defined in u_caps.h. + * Returns TRUE if all caps checks pass returns FALSE otherwise. + */ +boolean +util_check_caps(struct pipe_screen *screen, const unsigned *list) +{ + int out; + return util_check_caps_out(screen, list, &out); +} + + +/* + * Below follows some demo lists. + * + * None of these lists are exhausting lists of what is + * actually needed to support said API and more here for + * as example on how to uses the above functions. Especially + * for DX10 and DX11 where Gallium is missing features. + */ + +/* DX 9_1 */ +static unsigned caps_dx_9_1[] = { + UTIL_CHECK_INT(MAX_RENDER_TARGETS, 1), + UTIL_CHECK_INT(MAX_TEXTURE_2D_LEVELS, 12), /* 2048 */ + UTIL_CHECK_INT(MAX_TEXTURE_3D_LEVELS, 9), /* 256 */ + UTIL_CHECK_INT(MAX_TEXTURE_CUBE_LEVELS, 10), /* 512 */ + UTIL_CHECK_FLOAT(MAX_TEXTURE_ANISOTROPY, 2), + UTIL_CHECK_TERMINATE +}; + +/* DX 9_2 */ +static unsigned caps_dx_9_2[] = { + UTIL_CHECK_CAP(OCCLUSION_QUERY), + UTIL_CHECK_CAP(BLEND_EQUATION_SEPARATE), + UTIL_CHECK_INT(MAX_RENDER_TARGETS, 1), + UTIL_CHECK_INT(MAX_TEXTURE_2D_LEVELS, 12), /* 2048 */ + UTIL_CHECK_INT(MAX_TEXTURE_3D_LEVELS, 9), /* 256 */ + UTIL_CHECK_INT(MAX_TEXTURE_CUBE_LEVELS, 10), /* 512 */ + UTIL_CHECK_FLOAT(MAX_TEXTURE_ANISOTROPY, 16), + UTIL_CHECK_TERMINATE +}; + +/* DX 9_3 */ +static unsigned caps_dx_9_3[] = { + UTIL_CHECK_CAP(SM3), + //UTIL_CHECK_CAP(INSTANCING), + UTIL_CHECK_CAP(OCCLUSION_QUERY), + UTIL_CHECK_INT(MAX_RENDER_TARGETS, 4), + UTIL_CHECK_INT(MAX_TEXTURE_2D_LEVELS, 13), /* 4096 */ + UTIL_CHECK_INT(MAX_TEXTURE_3D_LEVELS, 9), /* 256 */ + UTIL_CHECK_INT(MAX_TEXTURE_CUBE_LEVELS, 10), /* 512 */ + UTIL_CHECK_FLOAT(MAX_TEXTURE_ANISOTROPY, 16), + UTIL_CHECK_TERMINATE +}; + +/* DX 10 */ +static unsigned caps_dx_10[] = { + UTIL_CHECK_CAP(SM3), + //UTIL_CHECK_CAP(INSTANCING), + UTIL_CHECK_CAP(OCCLUSION_QUERY), + UTIL_CHECK_INT(MAX_RENDER_TARGETS, 8), + UTIL_CHECK_INT(MAX_TEXTURE_2D_LEVELS, 14), /* 8192 */ + UTIL_CHECK_INT(MAX_TEXTURE_3D_LEVELS, 12), /* 2048 */ + UTIL_CHECK_INT(MAX_TEXTURE_CUBE_LEVELS, 14), /* 8192 */ + UTIL_CHECK_FLOAT(MAX_TEXTURE_ANISOTROPY, 16), + UTIL_CHECK_UNIMPLEMENTED, /* XXX Unimplemented features in Gallium */ + UTIL_CHECK_TERMINATE +}; + +/* DX11 */ +static unsigned caps_dx_11[] = { + UTIL_CHECK_CAP(SM3), + //UTIL_CHECK_CAP(INSTANCING), + UTIL_CHECK_CAP(OCCLUSION_QUERY), + UTIL_CHECK_INT(MAX_RENDER_TARGETS, 8), + UTIL_CHECK_INT(MAX_TEXTURE_2D_LEVELS, 14), /* 16384 */ + UTIL_CHECK_INT(MAX_TEXTURE_3D_LEVELS, 12), /* 2048 */ + UTIL_CHECK_INT(MAX_TEXTURE_CUBE_LEVELS, 14), /* 16384 */ + UTIL_CHECK_FLOAT(MAX_TEXTURE_ANISOTROPY, 16), + UTIL_CHECK_FORMAT(B8G8R8A8_UNORM), + UTIL_CHECK_UNIMPLEMENTED, /* XXX Unimplemented features in Gallium */ + UTIL_CHECK_TERMINATE +}; + +/* OpenGL 2.1 */ +static unsigned caps_opengl_2_1[] = { + UTIL_CHECK_CAP(GLSL), + UTIL_CHECK_CAP(OCCLUSION_QUERY), + UTIL_CHECK_CAP(TWO_SIDED_STENCIL), + UTIL_CHECK_CAP(BLEND_EQUATION_SEPARATE), + UTIL_CHECK_INT(MAX_RENDER_TARGETS, 2), + UTIL_CHECK_TERMINATE +}; + +/* OpenGL 3.0 */ +/* UTIL_CHECK_INT(MAX_RENDER_TARGETS, 8), */ + +/* Shader Model 3 */ +static unsigned caps_sm3[] = { + UTIL_CHECK_SHADER(FRAGMENT, MAX_INSTRUCTIONS, 512), + UTIL_CHECK_SHADER(FRAGMENT, MAX_INPUTS, 10), + UTIL_CHECK_SHADER(FRAGMENT, MAX_TEMPS, 32), + UTIL_CHECK_SHADER(FRAGMENT, MAX_ADDRS, 1), + UTIL_CHECK_SHADER(FRAGMENT, MAX_CONSTS, 224), + + UTIL_CHECK_SHADER(VERTEX, MAX_INSTRUCTIONS, 512), + UTIL_CHECK_SHADER(VERTEX, MAX_INPUTS, 16), + UTIL_CHECK_SHADER(VERTEX, MAX_TEMPS, 32), + UTIL_CHECK_SHADER(VERTEX, MAX_ADDRS, 2), + UTIL_CHECK_SHADER(VERTEX, MAX_CONSTS, 256), + + UTIL_CHECK_TERMINATE +}; + +/** + * Demo function which checks against theoretical caps needed for different APIs. + */ +void util_caps_demo_print(struct pipe_screen *screen) +{ + struct { + char* name; + unsigned *list; + } list[] = { + {"DX 9.1", caps_dx_9_1}, + {"DX 9.2", caps_dx_9_2}, + {"DX 9.3", caps_dx_9_3}, + {"DX 10", caps_dx_10}, + {"DX 11", caps_dx_11}, + {"OpenGL 2.1", caps_opengl_2_1}, +/* {"OpenGL 3.0", caps_opengl_3_0},*/ + {"SM3", caps_sm3}, + {NULL, NULL} + }; + int i, out = 0; + + for (i = 0; list[i].name; i++) { + if (util_check_caps_out(screen, list[i].list, &out)) { + debug_printf("%s: %s yes\n", __FUNCTION__, list[i].name); + continue; + } + switch (list[i].list[out]) { + case UTIL_CAPS_CHECK_CAP: + debug_printf("%s: %s no (cap %u not supported)\n", __FUNCTION__, + list[i].name, + list[i].list[out + 1]); + break; + case UTIL_CAPS_CHECK_INT: + debug_printf("%s: %s no (cap %u less then %u)\n", __FUNCTION__, + list[i].name, + list[i].list[out + 1], + list[i].list[out + 2]); + break; + case UTIL_CAPS_CHECK_FLOAT: + debug_printf("%s: %s no (cap %u less then %f)\n", __FUNCTION__, + list[i].name, + list[i].list[out + 1], + (double)(int)list[i].list[out + 2]); + break; + case UTIL_CAPS_CHECK_FORMAT: + debug_printf("%s: %s no (format %s not supported)\n", __FUNCTION__, + list[i].name, + util_format_name(list[i].list[out + 1]) + 12); + break; + case UTIL_CAPS_CHECK_UNIMPLEMENTED: + debug_printf("%s: %s no (not implemented in gallium or state tracker)\n", + __FUNCTION__, list[i].name); + break; + default: + assert(!"Unsupported check"); + } + } +} diff --git a/mesalib/src/gallium/auxiliary/util/u_caps.h b/mesalib/src/gallium/auxiliary/util/u_caps.h new file mode 100644 index 000000000..32a3aca5c --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_caps.h @@ -0,0 +1,71 @@ +/************************************************************************** + * + * 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 U_CAPS_H +#define U_CAPS_H + +#include "pipe/p_compiler.h" + +struct pipe_screen; + +enum u_caps_check_enum { + UTIL_CAPS_CHECK_TERMINATE = 0, + UTIL_CAPS_CHECK_CAP, + UTIL_CAPS_CHECK_INT, + UTIL_CAPS_CHECK_FLOAT, + UTIL_CAPS_CHECK_FORMAT, + UTIL_CAPS_CHECK_SHADER, + UTIL_CAPS_CHECK_UNIMPLEMENTED, +}; + +#define UTIL_CHECK_CAP(cap) \ + UTIL_CAPS_CHECK_CAP, PIPE_CAP_##cap + +#define UTIL_CHECK_INT(cap, higher) \ + UTIL_CAPS_CHECK_INT, PIPE_CAP_##cap, (unsigned)(higher) + +/* Floats currently lose precision */ +#define UTIL_CHECK_FLOAT(cap, higher) \ + UTIL_CAPS_CHECK_FLOAT, PIPE_CAP_##cap, (unsigned)(int)(higher) + +#define UTIL_CHECK_FORMAT(format) \ + UTIL_CAPS_CHECK_FORMAT, PIPE_FORMAT_##format + +#define UTIL_CHECK_SHADER(shader, cap, higher) \ + UTIL_CAPS_CHECK_SHADER, (PIPE_SHADER_##shader << 24) | PIPE_SHADER_CAP_##cap, (unsigned)(higher) + +#define UTIL_CHECK_UNIMPLEMENTED \ + UTIL_CAPS_CHECK_UNIMPLEMENTED + +#define UTIL_CHECK_TERMINATE \ + UTIL_CAPS_CHECK_TERMINATE + +boolean util_check_caps(struct pipe_screen *screen, const unsigned *list); +boolean util_check_caps_out(struct pipe_screen *screen, const unsigned *list, int *out); +void util_caps_demo_print(struct pipe_screen *screen); + +#endif diff --git a/mesalib/src/gallium/auxiliary/util/u_clear.h b/mesalib/src/gallium/auxiliary/util/u_clear.h new file mode 100644 index 000000000..c2f303261 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_clear.h @@ -0,0 +1,59 @@ +/************************************************************************** + * + * 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 TUNGSTEN GRAPHICS 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. + * + **************************************************************************/ + +/* Authors: + * Michel Dänzer + */ + + +#include "pipe/p_context.h" +#include "pipe/p_state.h" + + +/** + * Clear the given buffers to the specified values. + * No masking, no scissor (clear entire buffer). + */ +static INLINE void +util_clear(struct pipe_context *pipe, + struct pipe_framebuffer_state *framebuffer, unsigned buffers, + const float *rgba, double depth, unsigned stencil) +{ + if (buffers & PIPE_CLEAR_COLOR) { + unsigned i; + for (i = 0; i < framebuffer->nr_cbufs; i++) { + struct pipe_surface *ps = framebuffer->cbufs[i]; + pipe->clear_render_target(pipe, ps, rgba, 0, 0, ps->width, ps->height); + } + } + + if (buffers & PIPE_CLEAR_DEPTHSTENCIL) { + struct pipe_surface *ps = framebuffer->zsbuf; + pipe->clear_depth_stencil(pipe, ps, buffers & PIPE_CLEAR_DEPTHSTENCIL, + depth, stencil, + 0, 0, ps->width, ps->height); + } +} diff --git a/mesalib/src/gallium/auxiliary/util/u_cpu_detect.c b/mesalib/src/gallium/auxiliary/util/u_cpu_detect.c new file mode 100644 index 000000000..28929d174 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_cpu_detect.c @@ -0,0 +1,343 @@ +/************************************************************************** + * + * Copyright 2008 Dennis Smit + * 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 + * 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 + * AUTHORS, COPYRIGHT HOLDERS, 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. + * + **************************************************************************/ + +/** + * @file + * CPU feature detection. + * + * @author Dennis Smit + * @author Based on the work of Eric Anholt + */ + +#include "pipe/p_config.h" + +#include "u_debug.h" +#include "u_cpu_detect.h" + +#if defined(PIPE_ARCH_PPC) +#if defined(PIPE_OS_APPLE) +#include +#else +#include +#include +#endif +#endif + +#if defined(PIPE_OS_NETBSD) || defined(PIPE_OS_OPENBSD) +#include +#include +#include +#endif + +#if defined(PIPE_OS_FREEBSD) +#include +#include +#endif + +#if defined(PIPE_OS_LINUX) +#include +#endif + +#ifdef PIPE_OS_UNIX +#include +#endif + +#if defined(PIPE_OS_WINDOWS) +#include +#if defined(MSVC) +#include +#endif +#endif + + +#ifdef DEBUG +DEBUG_GET_ONCE_BOOL_OPTION(dump_cpu, "GALLIUM_DUMP_CPU", FALSE) +#endif + + +struct util_cpu_caps util_cpu_caps; + +#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64) +static int has_cpuid(void); +#endif + + +#if defined(PIPE_ARCH_PPC) && !defined(PIPE_OS_APPLE) +static jmp_buf __lv_powerpc_jmpbuf; +static volatile sig_atomic_t __lv_powerpc_canjump = 0; + +static void +sigill_handler(int sig) +{ + if (!__lv_powerpc_canjump) { + signal (sig, SIG_DFL); + raise (sig); + } + + __lv_powerpc_canjump = 0; + longjmp(__lv_powerpc_jmpbuf, 1); +} +#endif + +#if defined(PIPE_ARCH_PPC) +static void +check_os_altivec_support(void) +{ +#if defined(PIPE_OS_APPLE) + int sels[2] = {CTL_HW, HW_VECTORUNIT}; + int has_vu = 0; + int len = sizeof (has_vu); + int err; + + err = sysctl(sels, 2, &has_vu, &len, NULL, 0); + + if (err == 0) { + if (has_vu != 0) { + util_cpu_caps.has_altivec = 1; + } + } +#else /* !PIPE_OS_APPLE */ + /* not on Apple/Darwin, do it the brute-force way */ + /* this is borrowed from the libmpeg2 library */ + signal(SIGILL, sigill_handler); + if (setjmp(__lv_powerpc_jmpbuf)) { + signal(SIGILL, SIG_DFL); + } else { + __lv_powerpc_canjump = 1; + + __asm __volatile + ("mtspr 256, %0\n\t" + "vand %%v0, %%v0, %%v0" + : + : "r" (-1)); + + signal(SIGILL, SIG_DFL); + util_cpu_caps.has_altivec = 1; + } +#endif /* !PIPE_OS_APPLE */ +} +#endif /* PIPE_ARCH_PPC */ + + +#if defined(PIPE_ARCH_X86) || defined (PIPE_ARCH_X86_64) +static int has_cpuid(void) +{ +#if defined(PIPE_ARCH_X86) +#if defined(PIPE_OS_GCC) + int a, c; + + __asm __volatile + ("pushf\n" + "popl %0\n" + "movl %0, %1\n" + "xorl $0x200000, %0\n" + "push %0\n" + "popf\n" + "pushf\n" + "popl %0\n" + : "=a" (a), "=c" (c) + : + : "cc"); + + return a != c; +#else + /* FIXME */ + return 1; +#endif +#elif defined(PIPE_ARCH_X86_64) + return 1; +#else + return 0; +#endif +} + + +/** + * @sa cpuid.h included in gcc-4.3 onwards. + * @sa http://msdn.microsoft.com/en-us/library/hskdteyh.aspx + */ +static INLINE void +cpuid(uint32_t ax, uint32_t *p) +{ +#if defined(PIPE_CC_GCC) && defined(PIPE_ARCH_X86) + __asm __volatile ( + "xchgl %%ebx, %1\n\t" + "cpuid\n\t" + "xchgl %%ebx, %1" + : "=a" (p[0]), + "=S" (p[1]), + "=c" (p[2]), + "=d" (p[3]) + : "0" (ax) + ); +#elif defined(PIPE_CC_GCC) && defined(PIPE_ARCH_X86_64) + __asm __volatile ( + "cpuid\n\t" + : "=a" (p[0]), + "=b" (p[1]), + "=c" (p[2]), + "=d" (p[3]) + : "0" (ax) + ); +#elif defined(PIPE_CC_MSVC) + __cpuid(p, ax); +#else + p[0] = 0; + p[1] = 0; + p[2] = 0; + p[3] = 0; +#endif +} +#endif /* X86 or X86_64 */ + +void +util_cpu_detect(void) +{ + static boolean util_cpu_detect_initialized = FALSE; + + if(util_cpu_detect_initialized) + return; + + memset(&util_cpu_caps, 0, sizeof util_cpu_caps); + + /* Count the number of CPUs in system */ +#if defined(PIPE_OS_WINDOWS) + { + SYSTEM_INFO system_info; + GetSystemInfo(&system_info); + util_cpu_caps.nr_cpus = system_info.dwNumberOfProcessors; + } +#elif defined(PIPE_OS_UNIX) && defined(_SC_NPROCESSORS_ONLN) + util_cpu_caps.nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); + if (util_cpu_caps.nr_cpus == -1) + util_cpu_caps.nr_cpus = 1; +#elif defined(PIPE_OS_BSD) + { + int mib[2], ncpu; + int len; + + mib[0] = CTL_HW; + mib[1] = HW_NCPU; + + len = sizeof (ncpu); + sysctl(mib, 2, &ncpu, &len, NULL, 0); + util_cpu_caps.nr_cpus = ncpu; + } +#else + util_cpu_caps.nr_cpus = 1; +#endif + +#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64) + if (has_cpuid()) { + uint32_t regs[4]; + uint32_t regs2[4]; + + util_cpu_caps.cacheline = 32; + + /* Get max cpuid level */ + cpuid(0x00000000, regs); + + if (regs[0] >= 0x00000001) { + unsigned int cacheline; + + cpuid (0x00000001, regs2); + + util_cpu_caps.x86_cpu_type = (regs2[0] >> 8) & 0xf; + if (util_cpu_caps.x86_cpu_type == 0xf) + util_cpu_caps.x86_cpu_type = 8 + ((regs2[0] >> 20) & 255); /* use extended family (P4, IA64) */ + + /* general feature flags */ + util_cpu_caps.has_tsc = (regs2[3] >> 8) & 1; /* 0x0000010 */ + util_cpu_caps.has_mmx = (regs2[3] >> 23) & 1; /* 0x0800000 */ + util_cpu_caps.has_sse = (regs2[3] >> 25) & 1; /* 0x2000000 */ + util_cpu_caps.has_sse2 = (regs2[3] >> 26) & 1; /* 0x4000000 */ + util_cpu_caps.has_sse3 = (regs2[2] >> 0) & 1; /* 0x0000001 */ + util_cpu_caps.has_ssse3 = (regs2[2] >> 9) & 1; /* 0x0000020 */ + util_cpu_caps.has_sse4_1 = (regs2[2] >> 19) & 1; + util_cpu_caps.has_sse4_2 = (regs2[2] >> 20) & 1; + util_cpu_caps.has_avx = (regs2[2] >> 28) & 1; + util_cpu_caps.has_mmx2 = util_cpu_caps.has_sse; /* SSE cpus supports mmxext too */ + + cacheline = ((regs2[1] >> 8) & 0xFF) * 8; + if (cacheline > 0) + util_cpu_caps.cacheline = cacheline; + } + + cpuid(0x80000000, regs); + + if (regs[0] >= 0x80000001) { + + cpuid(0x80000001, regs2); + + util_cpu_caps.has_mmx |= (regs2[3] >> 23) & 1; + util_cpu_caps.has_mmx2 |= (regs2[3] >> 22) & 1; + util_cpu_caps.has_3dnow = (regs2[3] >> 31) & 1; + util_cpu_caps.has_3dnow_ext = (regs2[3] >> 30) & 1; + } + + if (regs[0] >= 0x80000006) { + cpuid(0x80000006, regs2); + util_cpu_caps.cacheline = regs2[2] & 0xFF; + } + + if (!util_cpu_caps.has_sse) { + util_cpu_caps.has_sse2 = 0; + util_cpu_caps.has_sse3 = 0; + util_cpu_caps.has_ssse3 = 0; + util_cpu_caps.has_sse4_1 = 0; + } + } +#endif /* PIPE_ARCH_X86 || PIPE_ARCH_X86_64 */ + +#if defined(PIPE_ARCH_PPC) + check_os_altivec_support(); +#endif /* PIPE_ARCH_PPC */ + +#ifdef DEBUG + if (debug_get_option_dump_cpu()) { + debug_printf("util_cpu_caps.nr_cpus = %u\n", util_cpu_caps.nr_cpus); + + debug_printf("util_cpu_caps.x86_cpu_type = %u\n", util_cpu_caps.x86_cpu_type); + debug_printf("util_cpu_caps.cacheline = %u\n", util_cpu_caps.cacheline); + + debug_printf("util_cpu_caps.has_tsc = %u\n", util_cpu_caps.has_tsc); + debug_printf("util_cpu_caps.has_mmx = %u\n", util_cpu_caps.has_mmx); + debug_printf("util_cpu_caps.has_mmx2 = %u\n", util_cpu_caps.has_mmx2); + debug_printf("util_cpu_caps.has_sse = %u\n", util_cpu_caps.has_sse); + debug_printf("util_cpu_caps.has_sse2 = %u\n", util_cpu_caps.has_sse2); + debug_printf("util_cpu_caps.has_sse3 = %u\n", util_cpu_caps.has_sse3); + debug_printf("util_cpu_caps.has_ssse3 = %u\n", util_cpu_caps.has_ssse3); + debug_printf("util_cpu_caps.has_sse4_1 = %u\n", util_cpu_caps.has_sse4_1); + debug_printf("util_cpu_caps.has_sse4_2 = %u\n", util_cpu_caps.has_sse4_2); + debug_printf("util_cpu_caps.has_avx = %u\n", util_cpu_caps.has_avx); + debug_printf("util_cpu_caps.has_3dnow = %u\n", util_cpu_caps.has_3dnow); + debug_printf("util_cpu_caps.has_3dnow_ext = %u\n", util_cpu_caps.has_3dnow_ext); + debug_printf("util_cpu_caps.has_altivec = %u\n", util_cpu_caps.has_altivec); + } +#endif + + util_cpu_detect_initialized = TRUE; +} diff --git a/mesalib/src/gallium/auxiliary/util/u_cpu_detect.h b/mesalib/src/gallium/auxiliary/util/u_cpu_detect.h new file mode 100644 index 000000000..fa2f769ae --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_cpu_detect.h @@ -0,0 +1,69 @@ +/************************************************************************** + * + * Copyright 2008 Dennis Smit + * 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 + * 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 + * AUTHORS, COPYRIGHT HOLDERS, 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. + * + ***************************************************************************/ + +/** + * @file + * CPU feature detection. + * + * @author Dennis Smit + * @author Based on the work of Eric Anholt + */ + +#ifndef _UTIL_CPU_DETECT_H +#define _UTIL_CPU_DETECT_H + +#include "pipe/p_compiler.h" +#include "pipe/p_config.h" + +struct util_cpu_caps { + unsigned nr_cpus; + + /* Feature flags */ + int x86_cpu_type; + unsigned cacheline; + + unsigned has_tsc:1; + unsigned has_mmx:1; + unsigned has_mmx2:1; + unsigned has_sse:1; + unsigned has_sse2:1; + unsigned has_sse3:1; + unsigned has_ssse3:1; + unsigned has_sse4_1:1; + unsigned has_sse4_2:1; + unsigned has_avx:1; + unsigned has_3dnow:1; + unsigned has_3dnow_ext:1; + unsigned has_altivec:1; +}; + +extern struct util_cpu_caps +util_cpu_caps; + +void util_cpu_detect(void); + + +#endif /* _UTIL_CPU_DETECT_H */ diff --git a/mesalib/src/gallium/auxiliary/util/u_debug.c b/mesalib/src/gallium/auxiliary/util/u_debug.c new file mode 100644 index 000000000..79b1fb3c1 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_debug.c @@ -0,0 +1,744 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * Copyright (c) 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 TUNGSTEN GRAPHICS 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_config.h" + +#include "pipe/p_compiler.h" +#include "os/os_stream.h" +#include "util/u_debug.h" +#include "pipe/p_format.h" +#include "pipe/p_state.h" +#include "util/u_inlines.h" +#include "util/u_format.h" +#include "util/u_memory.h" +#include "util/u_string.h" +#include "util/u_math.h" +#include "util/u_tile.h" +#include "util/u_prim.h" +#include "util/u_surface.h" + +#include /* CHAR_BIT */ +#include /* isalnum */ + +void _debug_vprintf(const char *format, va_list ap) +{ +#if defined(PIPE_OS_WINDOWS) || defined(PIPE_OS_EMBEDDED) + /* We buffer until we find a newline. */ + static char buf[4096] = {'\0'}; + size_t len = strlen(buf); + int ret = util_vsnprintf(buf + len, sizeof(buf) - len, format, ap); + if(ret > (int)(sizeof(buf) - len - 1) || util_strchr(buf + len, '\n')) { + os_log_message(buf); + buf[0] = '\0'; + } +#else + /* Just print as-is to stderr */ + vfprintf(stderr, format, ap); +#endif +} + + +#ifdef DEBUG +void debug_print_blob( const char *name, + const void *blob, + unsigned size ) +{ + const unsigned *ublob = (const unsigned *)blob; + unsigned i; + + debug_printf("%s (%d dwords%s)\n", name, size/4, + size%4 ? "... plus a few bytes" : ""); + + for (i = 0; i < size/4; i++) { + debug_printf("%d:\t%08x\n", i, ublob[i]); + } +} +#endif + + +static boolean +debug_get_option_should_print(void) +{ + static boolean first = TRUE; + static boolean value = FALSE; + + if (!first) + return value; + + /* Oh hey this will call into this function, + * but its cool since we set first to false + */ + first = FALSE; + value = debug_get_bool_option("GALLIUM_PRINT_OPTIONS", FALSE); + /* XXX should we print this option? Currently it wont */ + return value; +} + +const char * +debug_get_option(const char *name, const char *dfault) +{ + const char *result; + + result = os_get_option(name); + if(!result) + result = dfault; + + if (debug_get_option_should_print()) + debug_printf("%s: %s = %s\n", __FUNCTION__, name, result ? result : "(null)"); + + return result; +} + +boolean +debug_get_bool_option(const char *name, boolean dfault) +{ + const char *str = os_get_option(name); + boolean result; + + if(str == NULL) + result = dfault; + else if(!util_strcmp(str, "n")) + result = FALSE; + else if(!util_strcmp(str, "no")) + result = FALSE; + else if(!util_strcmp(str, "0")) + result = FALSE; + else if(!util_strcmp(str, "f")) + result = FALSE; + else if(!util_strcmp(str, "F")) + result = FALSE; + else if(!util_strcmp(str, "false")) + result = FALSE; + else if(!util_strcmp(str, "FALSE")) + result = FALSE; + else + result = TRUE; + + if (debug_get_option_should_print()) + debug_printf("%s: %s = %s\n", __FUNCTION__, name, result ? "TRUE" : "FALSE"); + + return result; +} + + +long +debug_get_num_option(const char *name, long dfault) +{ + long result; + const char *str; + + str = os_get_option(name); + if(!str) + result = dfault; + else { + long sign; + char c; + c = *str++; + if(c == '-') { + sign = -1; + c = *str++; + } + else { + sign = 1; + } + result = 0; + while('0' <= c && c <= '9') { + result = result*10 + (c - '0'); + c = *str++; + } + result *= sign; + } + + if (debug_get_option_should_print()) + debug_printf("%s: %s = %li\n", __FUNCTION__, name, result); + + return result; +} + +static boolean str_has_option(const char *str, const char *name) +{ + /* Empty string. */ + if (!*str) { + return FALSE; + } + + /* OPTION=all */ + if (!util_strcmp(str, "all")) { + return TRUE; + } + + /* Find 'name' in 'str' surrounded by non-alphanumeric characters. */ + { + const char *start = str; + unsigned name_len = strlen(name); + + /* 'start' is the beginning of the currently-parsed word, + * we increment 'str' each iteration. + * if we find either the end of string or a non-alphanumeric character, + * we compare 'start' up to 'str-1' with 'name'. */ + + while (1) { + if (!*str || !isalnum(*str)) { + if (str-start == name_len && + !memcmp(start, name, name_len)) { + return TRUE; + } + + if (!*str) { + return FALSE; + } + + start = str+1; + } + + str++; + } + } + + return FALSE; +} + +unsigned long +debug_get_flags_option(const char *name, + const struct debug_named_value *flags, + unsigned long dfault) +{ + unsigned long result; + const char *str; + const struct debug_named_value *orig = flags; + int namealign = 0; + + str = os_get_option(name); + if(!str) + result = dfault; + else if (!util_strcmp(str, "help")) { + result = dfault; + _debug_printf("%s: help for %s:\n", __FUNCTION__, name); + for (; flags->name; ++flags) + namealign = MAX2(namealign, strlen(flags->name)); + for (flags = orig; flags->name; ++flags) + _debug_printf("| %*s [0x%0*lx]%s%s\n", namealign, flags->name, + (int)sizeof(unsigned long)*CHAR_BIT/4, flags->value, + flags->desc ? " " : "", flags->desc ? flags->desc : ""); + } + else { + result = 0; + while( flags->name ) { + if (str_has_option(str, flags->name)) + result |= flags->value; + ++flags; + } + } + + if (debug_get_option_should_print()) { + if (str) { + debug_printf("%s: %s = 0x%lx (%s)\n", __FUNCTION__, name, result, str); + } else { + debug_printf("%s: %s = 0x%lx\n", __FUNCTION__, name, result); + } + } + + return result; +} + + +void _debug_assert_fail(const char *expr, + const char *file, + unsigned line, + const char *function) +{ + _debug_printf("%s:%u:%s: Assertion `%s' failed.\n", file, line, function, expr); +#if defined(PIPE_OS_WINDOWS) && !defined(PIPE_SUBSYSTEM_WINDOWS_USER) + if (debug_get_bool_option("GALLIUM_ABORT_ON_ASSERT", FALSE)) +#else + if (debug_get_bool_option("GALLIUM_ABORT_ON_ASSERT", TRUE)) +#endif + os_abort(); + else + _debug_printf("continuing...\n"); +} + + +const char * +debug_dump_enum(const struct debug_named_value *names, + unsigned long value) +{ + static char rest[64]; + + while(names->name) { + if(names->value == value) + return names->name; + ++names; + } + + util_snprintf(rest, sizeof(rest), "0x%08lx", value); + return rest; +} + + +const char * +debug_dump_enum_noprefix(const struct debug_named_value *names, + const char *prefix, + unsigned long value) +{ + static char rest[64]; + + while(names->name) { + if(names->value == value) { + const char *name = names->name; + while (*name == *prefix) { + name++; + prefix++; + } + return name; + } + ++names; + } + + + + util_snprintf(rest, sizeof(rest), "0x%08lx", value); + return rest; +} + + +const char * +debug_dump_flags(const struct debug_named_value *names, + unsigned long value) +{ + static char output[4096]; + static char rest[256]; + int first = 1; + + output[0] = '\0'; + + while(names->name) { + if((names->value & value) == names->value) { + if (!first) + util_strncat(output, "|", sizeof(output)); + else + first = 0; + util_strncat(output, names->name, sizeof(output) - 1); + output[sizeof(output) - 1] = '\0'; + value &= ~names->value; + } + ++names; + } + + if (value) { + if (!first) + util_strncat(output, "|", sizeof(output)); + else + first = 0; + + util_snprintf(rest, sizeof(rest), "0x%08lx", value); + util_strncat(output, rest, sizeof(output) - 1); + output[sizeof(output) - 1] = '\0'; + } + + if(first) + return "0"; + + return output; +} + + +#ifdef DEBUG +void debug_print_format(const char *msg, unsigned fmt ) +{ + debug_printf("%s: %s\n", msg, util_format_name(fmt)); +} +#endif + + + +static const struct debug_named_value pipe_prim_names[] = { +#ifdef DEBUG + DEBUG_NAMED_VALUE(PIPE_PRIM_POINTS), + DEBUG_NAMED_VALUE(PIPE_PRIM_LINES), + DEBUG_NAMED_VALUE(PIPE_PRIM_LINE_LOOP), + DEBUG_NAMED_VALUE(PIPE_PRIM_LINE_STRIP), + DEBUG_NAMED_VALUE(PIPE_PRIM_TRIANGLES), + DEBUG_NAMED_VALUE(PIPE_PRIM_TRIANGLE_STRIP), + DEBUG_NAMED_VALUE(PIPE_PRIM_TRIANGLE_FAN), + DEBUG_NAMED_VALUE(PIPE_PRIM_QUADS), + DEBUG_NAMED_VALUE(PIPE_PRIM_QUAD_STRIP), + DEBUG_NAMED_VALUE(PIPE_PRIM_POLYGON), +#endif + DEBUG_NAMED_VALUE_END +}; + + +const char *u_prim_name( unsigned prim ) +{ + return debug_dump_enum(pipe_prim_names, prim); +} + + + +#ifdef DEBUG +int fl_indent = 0; +const char* fl_function[1024]; + +int debug_funclog_enter(const char* f, const int line, const char* file) +{ + int i; + + for (i = 0; i < fl_indent; i++) + debug_printf(" "); + debug_printf("%s\n", f); + + assert(fl_indent < 1023); + fl_function[fl_indent++] = f; + + return 0; +} + +void debug_funclog_exit(const char* f, const int line, const char* file) +{ + --fl_indent; + assert(fl_indent >= 0); + assert(fl_function[fl_indent] == f); +} + +void debug_funclog_enter_exit(const char* f, const int line, const char* file) +{ + int i; + for (i = 0; i < fl_indent; i++) + debug_printf(" "); + debug_printf("%s\n", f); +} +#endif + + + +#ifdef DEBUG +/** + * Dump an image to a .raw or .ppm file (depends on OS). + * \param format PIPE_FORMAT_x + * \param cpp bytes per pixel + * \param width width in pixels + * \param height height in pixels + * \param stride row stride in bytes + */ +void debug_dump_image(const char *prefix, + unsigned format, unsigned cpp, + unsigned width, unsigned height, + unsigned stride, + const void *data) +{ +#ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY + static unsigned no = 0; + char filename[256]; + WCHAR wfilename[sizeof(filename)]; + ULONG_PTR iFile = 0; + struct { + unsigned format; + unsigned cpp; + unsigned width; + unsigned height; + } header; + unsigned char *pMap = NULL; + unsigned i; + + util_snprintf(filename, sizeof(filename), "\\??\\c:\\%03u%s.raw", ++no, prefix); + for(i = 0; i < sizeof(filename); ++i) + wfilename[i] = (WCHAR)filename[i]; + + pMap = (unsigned char *)EngMapFile(wfilename, sizeof(header) + height*width*cpp, &iFile); + if(!pMap) + return; + + header.format = format; + header.cpp = cpp; + header.width = width; + header.height = height; + memcpy(pMap, &header, sizeof(header)); + pMap += sizeof(header); + + for(i = 0; i < height; ++i) { + memcpy(pMap, (unsigned char *)data + stride*i, cpp*width); + pMap += cpp*width; + } + + EngUnmapFile(iFile); +#elif defined(PIPE_OS_UNIX) + /* write a ppm file */ + char filename[256]; + FILE *f; + + util_snprintf(filename, sizeof(filename), "%s.ppm", prefix); + + f = fopen(filename, "w"); + if (f) { + int i, x, y; + int r, g, b; + const uint8_t *ptr = (uint8_t *) data; + + /* XXX this is a hack */ + switch (format) { + case PIPE_FORMAT_B8G8R8A8_UNORM: + r = 2; + g = 1; + b = 0; + break; + default: + r = 0; + g = 1; + b = 1; + } + + fprintf(f, "P6\n"); + fprintf(f, "# ppm-file created by osdemo.c\n"); + fprintf(f, "%i %i\n", width, height); + fprintf(f, "255\n"); + fclose(f); + + f = fopen(filename, "ab"); /* reopen in binary append mode */ + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + i = y * stride + x * cpp; + fputc(ptr[i + r], f); /* write red */ + fputc(ptr[i + g], f); /* write green */ + fputc(ptr[i + b], f); /* write blue */ + } + } + fclose(f); + } + else { + fprintf(stderr, "Can't open %s for writing\n", filename); + } +#endif +} + +/* FIXME: dump resources, not surfaces... */ +void debug_dump_surface(struct pipe_context *pipe, + const char *prefix, + struct pipe_surface *surface) +{ + struct pipe_resource *texture; + struct pipe_transfer *transfer; + void *data; + + if (!surface) + return; + + /* XXX: this doesn't necessarily work, as the driver may be using + * temporary storage for the surface which hasn't been propagated + * back into the texture. Need to nail down the semantics of views + * and transfers a bit better before we can say if extra work needs + * to be done here: + */ + texture = surface->texture; + + transfer = pipe_get_transfer(pipe, texture, surface->u.tex.level, + surface->u.tex.first_layer, + PIPE_TRANSFER_READ, + 0, 0, surface->width, surface->height); + + data = pipe->transfer_map(pipe, transfer); + if(!data) + goto error; + + debug_dump_image(prefix, + texture->format, + util_format_get_blocksize(texture->format), + util_format_get_nblocksx(texture->format, surface->width), + util_format_get_nblocksy(texture->format, surface->height), + transfer->stride, + data); + + pipe->transfer_unmap(pipe, transfer); +error: + pipe->transfer_destroy(pipe, transfer); +} + + +void debug_dump_texture(struct pipe_context *pipe, + const char *prefix, + struct pipe_resource *texture) +{ + struct pipe_surface *surface, surf_tmpl; + + if (!texture) + return; + + /* XXX for now, just dump image for layer=0, level=0 */ + memset(&surf_tmpl, 0, sizeof(surf_tmpl)); + u_surface_default_template(&surf_tmpl, texture, 0 /* no bind flag - not a surface */); + surface = pipe->create_surface(pipe, texture, &surf_tmpl); + if (surface) { + debug_dump_surface(pipe, prefix, surface); + pipe->surface_destroy(pipe, surface); + } +} + + +#pragma pack(push,2) +struct bmp_file_header { + uint16_t bfType; + uint32_t bfSize; + uint16_t bfReserved1; + uint16_t bfReserved2; + uint32_t bfOffBits; +}; +#pragma pack(pop) + +struct bmp_info_header { + uint32_t biSize; + int32_t biWidth; + int32_t biHeight; + uint16_t biPlanes; + uint16_t biBitCount; + uint32_t biCompression; + uint32_t biSizeImage; + int32_t biXPelsPerMeter; + int32_t biYPelsPerMeter; + uint32_t biClrUsed; + uint32_t biClrImportant; +}; + +struct bmp_rgb_quad { + uint8_t rgbBlue; + uint8_t rgbGreen; + uint8_t rgbRed; + uint8_t rgbAlpha; +}; + +void +debug_dump_surface_bmp(struct pipe_context *pipe, + const char *filename, + struct pipe_surface *surface) +{ +#ifndef PIPE_SUBSYSTEM_WINDOWS_MINIPORT + struct pipe_transfer *transfer; + struct pipe_resource *texture = surface->texture; + + transfer = pipe_get_transfer(pipe, texture, surface->u.tex.level, + surface->u.tex.first_layer, PIPE_TRANSFER_READ, + 0, 0, surface->width, surface->height); + + debug_dump_transfer_bmp(pipe, filename, transfer); + + pipe->transfer_destroy(pipe, transfer); +#endif +} + +void +debug_dump_transfer_bmp(struct pipe_context *pipe, + const char *filename, + struct pipe_transfer *transfer) +{ +#ifndef PIPE_SUBSYSTEM_WINDOWS_MINIPORT + float *rgba; + + if (!transfer) + goto error1; + + rgba = MALLOC(transfer->box.width * + transfer->box.height * + transfer->box.depth * + 4*sizeof(float)); + if(!rgba) + goto error1; + + pipe_get_tile_rgba(pipe, transfer, 0, 0, + transfer->box.width, transfer->box.height, + rgba); + + debug_dump_float_rgba_bmp(filename, + transfer->box.width, transfer->box.height, + rgba, transfer->box.width); + + FREE(rgba); +error1: + ; +#endif +} + +void +debug_dump_float_rgba_bmp(const char *filename, + unsigned width, unsigned height, + float *rgba, unsigned stride) +{ +#ifndef PIPE_SUBSYSTEM_WINDOWS_MINIPORT + struct os_stream *stream; + struct bmp_file_header bmfh; + struct bmp_info_header bmih; + unsigned x, y; + + if(!rgba) + goto error1; + + bmfh.bfType = 0x4d42; + bmfh.bfSize = 14 + 40 + height*width*4; + bmfh.bfReserved1 = 0; + bmfh.bfReserved2 = 0; + bmfh.bfOffBits = 14 + 40; + + bmih.biSize = 40; + bmih.biWidth = width; + bmih.biHeight = height; + bmih.biPlanes = 1; + bmih.biBitCount = 32; + bmih.biCompression = 0; + bmih.biSizeImage = height*width*4; + bmih.biXPelsPerMeter = 0; + bmih.biYPelsPerMeter = 0; + bmih.biClrUsed = 0; + bmih.biClrImportant = 0; + + stream = os_file_stream_create(filename); + if(!stream) + goto error1; + + os_stream_write(stream, &bmfh, 14); + os_stream_write(stream, &bmih, 40); + + y = height; + while(y--) { + float *ptr = rgba + (stride * y * 4); + for(x = 0; x < width; ++x) + { + struct bmp_rgb_quad pixel; + pixel.rgbRed = float_to_ubyte(ptr[x*4 + 0]); + pixel.rgbGreen = float_to_ubyte(ptr[x*4 + 1]); + pixel.rgbBlue = float_to_ubyte(ptr[x*4 + 2]); + pixel.rgbAlpha = 255; + os_stream_write(stream, &pixel, 4); + } + } + + os_stream_close(stream); +error1: + ; +#endif +} + +#endif diff --git a/mesalib/src/gallium/auxiliary/util/u_debug.h b/mesalib/src/gallium/auxiliary/util/u_debug.h new file mode 100644 index 000000000..e3efac41b --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_debug.h @@ -0,0 +1,431 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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 TUNGSTEN GRAPHICS 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 + * Cross-platform debugging helpers. + * + * For now it just has assert and printf replacements, but it might be extended + * with stack trace reports and more advanced logging in the near future. + * + * @author Jose Fonseca + */ + +#ifndef U_DEBUG_H_ +#define U_DEBUG_H_ + + +#include "os/os_misc.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +#if defined(__GNUC__) +#define _util_printf_format(fmt, list) __attribute__ ((format (printf, fmt, list))) +#else +#define _util_printf_format(fmt, list) +#endif + +void _debug_vprintf(const char *format, va_list ap); + + +static INLINE void +_debug_printf(const char *format, ...) +{ + va_list ap; + va_start(ap, format); + _debug_vprintf(format, ap); + va_end(ap); +} + + +/** + * Print debug messages. + * + * The actual channel used to output debug message is platform specific. To + * avoid misformating or truncation, follow these rules of thumb: + * - output whole lines + * - avoid outputing large strings (512 bytes is the current maximum length + * that is guaranteed to be printed in all platforms) + */ +#if !defined(PIPE_OS_HAIKU) +static INLINE void +debug_printf(const char *format, ...) _util_printf_format(1,2); + +static INLINE void +debug_printf(const char *format, ...) +{ +#ifdef DEBUG + va_list ap; + va_start(ap, format); + _debug_vprintf(format, ap); + va_end(ap); +#else + (void) format; /* silence warning */ +#endif +} + +#endif /* !PIPE_OS_HAIKU */ + +/* + * ... isn't portable so we need to pass arguments in parentheses. + * + * usage: + * debug_printf_once(("awnser: %i\n", 42)); + */ +#define debug_printf_once(args) \ + do { \ + static boolean once = TRUE; \ + if (once) { \ + once = FALSE; \ + debug_printf args; \ + } \ + } while (0) + + +#ifdef DEBUG +#define debug_vprintf(_format, _ap) _debug_vprintf(_format, _ap) +#else +#define debug_vprintf(_format, _ap) ((void)0) +#endif + + +#ifdef DEBUG +/** + * Dump a blob in hex to the same place that debug_printf sends its + * messages. + */ +void debug_print_blob( const char *name, const void *blob, unsigned size ); + +/* Print a message along with a prettified format string + */ +void debug_print_format(const char *msg, unsigned fmt ); +#else +#define debug_print_blob(_name, _blob, _size) ((void)0) +#define debug_print_format(_msg, _fmt) ((void)0) +#endif + + +/** + * Hard-coded breakpoint. + */ +#ifdef DEBUG +#define debug_break() os_break() +#else /* !DEBUG */ +#define debug_break() ((void)0) +#endif /* !DEBUG */ + + +long +debug_get_num_option(const char *name, long dfault); + +void _debug_assert_fail(const char *expr, + const char *file, + unsigned line, + const char *function); + + +/** + * Assert macro + * + * Do not expect that the assert call terminates -- errors must be handled + * regardless of assert behavior. + * + * For non debug builds the assert macro will expand to a no-op, so do not + * call functions with side effects in the assert expression. + */ +#ifdef DEBUG +#define debug_assert(expr) ((expr) ? (void)0 : _debug_assert_fail(#expr, __FILE__, __LINE__, __FUNCTION__)) +#else +#define debug_assert(expr) do { } while (0 && (expr)) +#endif + + +/** Override standard assert macro */ +#ifdef assert +#undef assert +#endif +#define assert(expr) debug_assert(expr) + + +/** + * Output the current function name. + */ +#ifdef DEBUG +#define debug_checkpoint() \ + _debug_printf("%s\n", __FUNCTION__) +#else +#define debug_checkpoint() \ + ((void)0) +#endif + + +/** + * Output the full source code position. + */ +#ifdef DEBUG +#define debug_checkpoint_full() \ + _debug_printf("%s:%u:%s", __FILE__, __LINE__, __FUNCTION__) +#else +#define debug_checkpoint_full() \ + ((void)0) +#endif + + +/** + * Output a warning message. Muted on release version. + */ +#ifdef DEBUG +#define debug_warning(__msg) \ + _debug_printf("%s:%u:%s: warning: %s\n", __FILE__, __LINE__, __FUNCTION__, __msg) +#else +#define debug_warning(__msg) \ + ((void)0) +#endif + + +/** + * Output an error message. Not muted on release version. + */ +#ifdef DEBUG +#define debug_error(__msg) \ + _debug_printf("%s:%u:%s: error: %s\n", __FILE__, __LINE__, __FUNCTION__, __msg) +#else +#define debug_error(__msg) \ + _debug_printf("error: %s\n", __msg) +#endif + + +/** + * Used by debug_dump_enum and debug_dump_flags to describe symbols. + */ +struct debug_named_value +{ + const char *name; + unsigned long value; + const char *desc; +}; + + +/** + * Some C pre-processor magic to simplify creating named values. + * + * Example: + * @code + * static const debug_named_value my_names[] = { + * DEBUG_NAMED_VALUE(MY_ENUM_VALUE_X), + * DEBUG_NAMED_VALUE(MY_ENUM_VALUE_Y), + * DEBUG_NAMED_VALUE(MY_ENUM_VALUE_Z), + * DEBUG_NAMED_VALUE_END + * }; + * + * ... + * debug_printf("%s = %s\n", + * name, + * debug_dump_enum(my_names, my_value)); + * ... + * @endcode + */ +#define DEBUG_NAMED_VALUE(__symbol) DEBUG_NAMED_VALUE_WITH_DESCRIPTION(__symbol, NULL) +#define DEBUG_NAMED_VALUE_WITH_DESCRIPTION(__symbol, __desc) {#__symbol, (unsigned long)__symbol, __desc} +#define DEBUG_NAMED_VALUE_END {NULL, 0, NULL} + + +/** + * Convert a enum value to a string. + */ +const char * +debug_dump_enum(const struct debug_named_value *names, + unsigned long value); + +const char * +debug_dump_enum_noprefix(const struct debug_named_value *names, + const char *prefix, + unsigned long value); + + +/** + * Convert binary flags value to a string. + */ +const char * +debug_dump_flags(const struct debug_named_value *names, + unsigned long value); + + +/** + * Function enter exit loggers + */ +#ifdef DEBUG +int debug_funclog_enter(const char* f, const int line, const char* file); +void debug_funclog_exit(const char* f, const int line, const char* file); +void debug_funclog_enter_exit(const char* f, const int line, const char* file); + +#define DEBUG_FUNCLOG_ENTER() \ + int __debug_decleration_work_around = \ + debug_funclog_enter(__FUNCTION__, __LINE__, __FILE__) +#define DEBUG_FUNCLOG_EXIT() \ + do { \ + (void)__debug_decleration_work_around; \ + debug_funclog_exit(__FUNCTION__, __LINE__, __FILE__); \ + return; \ + } while(0) +#define DEBUG_FUNCLOG_EXIT_RET(ret) \ + do { \ + (void)__debug_decleration_work_around; \ + debug_funclog_exit(__FUNCTION__, __LINE__, __FILE__); \ + return ret; \ + } while(0) +#define DEBUG_FUNCLOG_ENTER_EXIT() \ + debug_funclog_enter_exit(__FUNCTION__, __LINE__, __FILE__) + +#else +#define DEBUG_FUNCLOG_ENTER() \ + int __debug_decleration_work_around +#define DEBUG_FUNCLOG_EXIT() \ + do { (void)__debug_decleration_work_around; return; } while(0) +#define DEBUG_FUNCLOG_EXIT_RET(ret) \ + do { (void)__debug_decleration_work_around; return ret; } while(0) +#define DEBUG_FUNCLOG_ENTER_EXIT() +#endif + + +/** + * Get option. + * + * It is an alias for getenv on Linux. + * + * On Windows it reads C:\gallium.cfg, which is a text file with CR+LF line + * endings with one option per line as + * + * NAME=value + * + * This file must be terminated with an extra empty line. + */ +const char * +debug_get_option(const char *name, const char *dfault); + +boolean +debug_get_bool_option(const char *name, boolean dfault); + +long +debug_get_num_option(const char *name, long dfault); + +unsigned long +debug_get_flags_option(const char *name, + const struct debug_named_value *flags, + unsigned long dfault); + +#define DEBUG_GET_ONCE_BOOL_OPTION(sufix, name, dfault) \ +static boolean \ +debug_get_option_ ## sufix (void) \ +{ \ + static boolean first = TRUE; \ + static boolean value; \ + if (first) { \ + first = FALSE; \ + value = debug_get_bool_option(name, dfault); \ + } \ + return value; \ +} + +#define DEBUG_GET_ONCE_NUM_OPTION(sufix, name, dfault) \ +static long \ +debug_get_option_ ## sufix (void) \ +{ \ + static boolean first = TRUE; \ + static long value; \ + if (first) { \ + first = FALSE; \ + value = debug_get_num_option(name, dfault); \ + } \ + return value; \ +} + +#define DEBUG_GET_ONCE_FLAGS_OPTION(sufix, name, flags, dfault) \ +static unsigned long \ +debug_get_option_ ## sufix (void) \ +{ \ + static boolean first = TRUE; \ + static unsigned long value; \ + if (first) { \ + first = FALSE; \ + value = debug_get_flags_option(name, flags, dfault); \ + } \ + return value; \ +} + + +unsigned long +debug_memory_begin(void); + +void +debug_memory_end(unsigned long beginning); + + +#ifdef DEBUG +struct pipe_context; +struct pipe_surface; +struct pipe_transfer; +struct pipe_resource; + +void debug_dump_image(const char *prefix, + unsigned format, unsigned cpp, + unsigned width, unsigned height, + unsigned stride, + const void *data); +void debug_dump_surface(struct pipe_context *pipe, + const char *prefix, + struct pipe_surface *surface); +void debug_dump_texture(struct pipe_context *pipe, + const char *prefix, + struct pipe_resource *texture); +void debug_dump_surface_bmp(struct pipe_context *pipe, + const char *filename, + struct pipe_surface *surface); +void debug_dump_transfer_bmp(struct pipe_context *pipe, + const char *filename, + struct pipe_transfer *transfer); +void debug_dump_float_rgba_bmp(const char *filename, + unsigned width, unsigned height, + float *rgba, unsigned stride); +#else +#define debug_dump_image(prefix, format, cpp, width, height, stride, data) ((void)0) +#define debug_dump_surface(pipe, prefix, surface) ((void)0) +#define debug_dump_surface_bmp(pipe, filename, surface) ((void)0) +#define debug_dump_transfer_bmp(filename, transfer) ((void)0) +#define debug_dump_float_rgba_bmp(filename, width, height, rgba, stride) ((void)0) +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* U_DEBUG_H_ */ diff --git a/mesalib/src/gallium/auxiliary/util/u_debug_describe.c b/mesalib/src/gallium/auxiliary/util/u_debug_describe.c new file mode 100644 index 000000000..f84f942d6 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_debug_describe.c @@ -0,0 +1,81 @@ +/************************************************************************** + * + * Copyright 2010 Luca Barbieri + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and 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 COPYRIGHT OWNER(S) 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 + +void +debug_describe_reference(char* buf, const struct pipe_reference*ptr) +{ + strcpy(buf, "pipe_object"); +} + +void +debug_describe_resource(char* buf, const struct pipe_resource *ptr) +{ + switch(ptr->target) + { + case PIPE_BUFFER: + util_sprintf(buf, "pipe_buffer<%u>", (unsigned)util_format_get_stride(ptr->format, ptr->width0)); + break; + case PIPE_TEXTURE_1D: + util_sprintf(buf, "pipe_texture1d<%u,%s,%u>", ptr->width0, util_format_short_name(ptr->format), ptr->last_level); + break; + case PIPE_TEXTURE_2D: + util_sprintf(buf, "pipe_texture2d<%u,%u,%s,%u>", ptr->width0, ptr->height0, util_format_short_name(ptr->format), ptr->last_level); + break; + case PIPE_TEXTURE_RECT: + util_sprintf(buf, "pipe_texture_rect<%u,%u,%s>", ptr->width0, ptr->height0, util_format_short_name(ptr->format)); + break; + case PIPE_TEXTURE_CUBE: + util_sprintf(buf, "pipe_texture_cube<%u,%u,%s,%u>", ptr->width0, ptr->height0, util_format_short_name(ptr->format), ptr->last_level); + break; + case PIPE_TEXTURE_3D: + util_sprintf(buf, "pipe_texture3d<%u,%u,%u,%s,%u>", ptr->width0, ptr->height0, ptr->depth0, util_format_short_name(ptr->format), ptr->last_level); + break; + default: + util_sprintf(buf, "pipe_martian_resource<%u>", ptr->target); + break; + } +} + +void +debug_describe_surface(char* buf, const struct pipe_surface *ptr) +{ + char res[128]; + debug_describe_resource(res, ptr->texture); + util_sprintf(buf, "pipe_surface<%s,%u,%u,%u>", res, ptr->u.tex.level, ptr->u.tex.first_layer, ptr->u.tex.last_layer); +} + +void +debug_describe_sampler_view(char* buf, const struct pipe_sampler_view *ptr) +{ + char res[128]; + debug_describe_resource(res, ptr->texture); + util_sprintf(buf, "pipe_sampler_view<%s,%s>", res, util_format_short_name(ptr->format)); +} diff --git a/mesalib/src/gallium/auxiliary/util/u_debug_describe.h b/mesalib/src/gallium/auxiliary/util/u_debug_describe.h new file mode 100644 index 000000000..447e838e4 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_debug_describe.h @@ -0,0 +1,49 @@ +/************************************************************************** + * + * Copyright 2010 Luca Barbieri + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and 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 COPYRIGHT OWNER(S) 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 U_DEBUG_DESCRIBE_H_ +#define U_DEBUG_DESCRIBE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +struct pipe_reference; +struct pipe_resource; +struct pipe_surface; +struct pipe_sampler_view; + +/* a 256-byte buffer is necessary and sufficient */ +void debug_describe_reference(char* buf, const struct pipe_reference*ptr); +void debug_describe_resource(char* buf, const struct pipe_resource *ptr); +void debug_describe_surface(char* buf, const struct pipe_surface *ptr); +void debug_describe_sampler_view(char* buf, const struct pipe_sampler_view *ptr); + +#ifdef __cplusplus +} +#endif + +#endif /* U_DEBUG_DESCRIBE_H_ */ diff --git a/mesalib/src/gallium/auxiliary/util/u_debug_memory.c b/mesalib/src/gallium/auxiliary/util/u_debug_memory.c new file mode 100644 index 000000000..36497921e --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_debug_memory.c @@ -0,0 +1,307 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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 TUNGSTEN GRAPHICS 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 + * Memory debugging. + * + * @author José Fonseca + */ + +#include "pipe/p_config.h" + +#define DEBUG_MEMORY_IMPLEMENTATION + +#include "os/os_memory.h" +#include "os/os_memory_debug.h" + +#include "util/u_debug.h" +#include "util/u_debug_stack.h" +#include "util/u_double_list.h" + + +#define DEBUG_MEMORY_MAGIC 0x6e34090aU +#define DEBUG_MEMORY_STACK 0 /* XXX: disabled until we have symbol lookup */ + + +struct debug_memory_header +{ + struct list_head head; + + unsigned long no; + const char *file; + unsigned line; + const char *function; +#if DEBUG_MEMORY_STACK + struct debug_stack_frame backtrace[DEBUG_MEMORY_STACK]; +#endif + size_t size; + + unsigned magic; +}; + +struct debug_memory_footer +{ + unsigned magic; +}; + + +static struct list_head list = { &list, &list }; + +static unsigned long last_no = 0; + + +static INLINE struct debug_memory_header * +header_from_data(void *data) +{ + if(data) + return (struct debug_memory_header *)((char *)data - sizeof(struct debug_memory_header)); + else + return NULL; +} + +static INLINE void * +data_from_header(struct debug_memory_header *hdr) +{ + if(hdr) + return (void *)((char *)hdr + sizeof(struct debug_memory_header)); + else + return NULL; +} + +static INLINE struct debug_memory_footer * +footer_from_header(struct debug_memory_header *hdr) +{ + if(hdr) + return (struct debug_memory_footer *)((char *)hdr + sizeof(struct debug_memory_header) + hdr->size); + else + return NULL; +} + + +void * +debug_malloc(const char *file, unsigned line, const char *function, + size_t size) +{ + struct debug_memory_header *hdr; + struct debug_memory_footer *ftr; + + hdr = os_malloc(sizeof(*hdr) + size + sizeof(*ftr)); + if(!hdr) { + debug_printf("%s:%u:%s: out of memory when trying to allocate %lu bytes\n", + file, line, function, + (long unsigned)size); + return NULL; + } + + hdr->no = last_no++; + hdr->file = file; + hdr->line = line; + hdr->function = function; + hdr->size = size; + hdr->magic = DEBUG_MEMORY_MAGIC; + +#if DEBUG_MEMORY_STACK + debug_backtrace_capture(hdr->backtrace, 0, DEBUG_MEMORY_STACK); +#endif + + ftr = footer_from_header(hdr); + ftr->magic = DEBUG_MEMORY_MAGIC; + + LIST_ADDTAIL(&hdr->head, &list); + + return data_from_header(hdr); +} + +void +debug_free(const char *file, unsigned line, const char *function, + void *ptr) +{ + struct debug_memory_header *hdr; + struct debug_memory_footer *ftr; + + if(!ptr) + return; + + hdr = header_from_data(ptr); + if(hdr->magic != DEBUG_MEMORY_MAGIC) { + debug_printf("%s:%u:%s: freeing bad or corrupted memory %p\n", + file, line, function, + ptr); + debug_assert(0); + return; + } + + ftr = footer_from_header(hdr); + if(ftr->magic != DEBUG_MEMORY_MAGIC) { + debug_printf("%s:%u:%s: buffer overflow %p\n", + hdr->file, hdr->line, hdr->function, + ptr); + debug_assert(0); + } + + LIST_DEL(&hdr->head); + hdr->magic = 0; + ftr->magic = 0; + + os_free(hdr); +} + +void * +debug_calloc(const char *file, unsigned line, const char *function, + size_t count, size_t size ) +{ + void *ptr = debug_malloc( file, line, function, count * size ); + if( ptr ) + memset( ptr, 0, count * size ); + return ptr; +} + +void * +debug_realloc(const char *file, unsigned line, const char *function, + void *old_ptr, size_t old_size, size_t new_size ) +{ + struct debug_memory_header *old_hdr, *new_hdr; + struct debug_memory_footer *old_ftr, *new_ftr; + void *new_ptr; + + if(!old_ptr) + return debug_malloc( file, line, function, new_size ); + + if(!new_size) { + debug_free( file, line, function, old_ptr ); + return NULL; + } + + old_hdr = header_from_data(old_ptr); + if(old_hdr->magic != DEBUG_MEMORY_MAGIC) { + debug_printf("%s:%u:%s: reallocating bad or corrupted memory %p\n", + file, line, function, + old_ptr); + debug_assert(0); + return NULL; + } + + old_ftr = footer_from_header(old_hdr); + if(old_ftr->magic != DEBUG_MEMORY_MAGIC) { + debug_printf("%s:%u:%s: buffer overflow %p\n", + old_hdr->file, old_hdr->line, old_hdr->function, + old_ptr); + debug_assert(0); + } + + /* alloc new */ + new_hdr = os_malloc(sizeof(*new_hdr) + new_size + sizeof(*new_ftr)); + if(!new_hdr) { + debug_printf("%s:%u:%s: out of memory when trying to allocate %lu bytes\n", + file, line, function, + (long unsigned)new_size); + return NULL; + } + new_hdr->no = old_hdr->no; + new_hdr->file = old_hdr->file; + new_hdr->line = old_hdr->line; + new_hdr->function = old_hdr->function; + new_hdr->size = new_size; + new_hdr->magic = DEBUG_MEMORY_MAGIC; + + new_ftr = footer_from_header(new_hdr); + new_ftr->magic = DEBUG_MEMORY_MAGIC; + + LIST_REPLACE(&old_hdr->head, &new_hdr->head); + + /* copy data */ + new_ptr = data_from_header(new_hdr); + memcpy( new_ptr, old_ptr, old_size < new_size ? old_size : new_size ); + + /* free old */ + old_hdr->magic = 0; + old_ftr->magic = 0; + os_free(old_hdr); + + return new_ptr; +} + +unsigned long +debug_memory_begin(void) +{ + return last_no; +} + +void +debug_memory_end(unsigned long start_no) +{ + size_t total_size = 0; + struct list_head *entry; + + if(start_no == last_no) + return; + + entry = list.prev; + for (; entry != &list; entry = entry->prev) { + struct debug_memory_header *hdr; + void *ptr; + struct debug_memory_footer *ftr; + + hdr = LIST_ENTRY(struct debug_memory_header, entry, head); + ptr = data_from_header(hdr); + ftr = footer_from_header(hdr); + + if(hdr->magic != DEBUG_MEMORY_MAGIC) { + debug_printf("%s:%u:%s: bad or corrupted memory %p\n", + hdr->file, hdr->line, hdr->function, + ptr); + debug_assert(0); + } + + if((start_no <= hdr->no && hdr->no < last_no) || + (last_no < start_no && (hdr->no < last_no || start_no <= hdr->no))) { + debug_printf("%s:%u:%s: %lu bytes at %p not freed\n", + hdr->file, hdr->line, hdr->function, + (unsigned long) hdr->size, ptr); +#if DEBUG_MEMORY_STACK + debug_backtrace_dump(hdr->backtrace, DEBUG_MEMORY_STACK); +#endif + total_size += hdr->size; + } + + if(ftr->magic != DEBUG_MEMORY_MAGIC) { + debug_printf("%s:%u:%s: buffer overflow %p\n", + hdr->file, hdr->line, hdr->function, + ptr); + debug_assert(0); + } + } + + if(total_size) { + debug_printf("Total of %lu KB of system memory apparently leaked\n", + (unsigned long) (total_size + 1023)/1024); + } + else { + debug_printf("No memory leaks detected.\n"); + } +} diff --git a/mesalib/src/gallium/auxiliary/util/u_debug_refcnt.c b/mesalib/src/gallium/auxiliary/util/u_debug_refcnt.c new file mode 100644 index 000000000..0a242e124 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_debug_refcnt.c @@ -0,0 +1,191 @@ +/************************************************************************** + * + * Copyright 2010 Luca Barbieri + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and 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 COPYRIGHT OWNER(S) 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. + * + **************************************************************************/ + +#if defined(DEBUG) && (!defined(PIPE_OS_WINDOWS) || defined(PIPE_SUBSYSTEM_WINDOWS_USER)) + +/* see http://www.mozilla.org/performance/refcnt-balancer.html for what do with the output + * on Linux, use tools/addr2line.sh to postprocess it before anything else + **/ +#include +#include +#include +#include +#include +#include +#include +#include + +int debug_refcnt_state; + +struct os_stream* stream; + +/* TODO: maybe move this serial machinery to a stand-alone module and expose it? */ +pipe_static_mutex(serials_mutex); + +static struct util_hash_table* serials_hash; +static unsigned serials_last; + +static unsigned hash_ptr(void* p) +{ + return (unsigned)(uintptr_t)p; +} + +static int compare_ptr(void* a, void* b) +{ + if(a == b) + return 0; + else if(a < b) + return -1; + else + return 1; +} + +static boolean debug_serial(void* p, unsigned* pserial) +{ + unsigned serial; + boolean found = TRUE; +#ifdef PIPE_SUBSYSTEM_WINDOWS_USER + static boolean first = TRUE; + + if (first) { + pipe_mutex_init(serials_mutex); + first = FALSE; + } +#endif + + pipe_mutex_lock(serials_mutex); + if(!serials_hash) + serials_hash = util_hash_table_create(hash_ptr, compare_ptr); + serial = (unsigned)(uintptr_t)util_hash_table_get(serials_hash, p); + if(!serial) + { + /* time to stop logging... (you'll have a 100 GB logfile at least at this point) + * TODO: avoid this + */ + serial = ++serials_last; + if(!serial) + { + debug_error("More than 2^32 objects detected, aborting.\n"); + os_abort(); + } + + util_hash_table_set(serials_hash, p, (void*)(uintptr_t)serial); + found = FALSE; + } + pipe_mutex_unlock(serials_mutex); + *pserial = serial; + return found; +} + +static void debug_serial_delete(void* p) +{ + pipe_mutex_lock(serials_mutex); + util_hash_table_remove(serials_hash, p); + pipe_mutex_unlock(serials_mutex); +} + +#define STACK_LEN 64 + +static void dump_stack(const char* symbols[STACK_LEN]) +{ + unsigned i; + for(i = 0; i < STACK_LEN; ++i) + { + if(symbols[i]) + os_stream_printf(stream, "%s\n", symbols[i]); + } + os_stream_write(stream, "\n", 1); +} + +void debug_reference_slowpath(const struct pipe_reference* p, debug_reference_descriptor get_desc, int change) +{ + if(debug_refcnt_state < 0) + return; + + if(!debug_refcnt_state) + { + const char* filename = debug_get_option("GALLIUM_REFCNT_LOG", NULL); + if(filename && filename[0]) + stream = os_file_stream_create(filename); + + if(stream) + debug_refcnt_state = 1; + else + debug_refcnt_state = -1; + } + + if(debug_refcnt_state > 0) + { + struct debug_stack_frame frames[STACK_LEN]; + const char* symbols[STACK_LEN]; + char buf[1024]; + + unsigned i; + unsigned refcnt = p->count; + unsigned serial; + boolean existing = debug_serial((void*)p, &serial); + + debug_backtrace_capture(frames, 1, STACK_LEN); + for(i = 0; i < STACK_LEN; ++i) + { + if(frames[i].function) + symbols[i] = debug_symbol_name_cached(frames[i].function); + else + symbols[i] = 0; + } + + get_desc(buf, p); + + if(!existing) + { + os_stream_printf(stream, "<%s> %p %u Create\n", buf, p, serial); + dump_stack(symbols); + + /* this is there to provide a gradual change even if we don't see the initialization */ + for(i = 1; i <= refcnt - change; ++i) + { + os_stream_printf(stream, "<%s> %p %u AddRef %u\n", buf, p, serial, i); + dump_stack(symbols); + } + } + + if(change) + { + os_stream_printf(stream, "<%s> %p %u %s %u\n", buf, p, serial, change > 0 ? "AddRef" : "Release", refcnt); + dump_stack(symbols); + } + + if(!refcnt) + { + debug_serial_delete((void*)p); + os_stream_printf(stream, "<%s> %p %u Destroy\n", buf, p, serial); + dump_stack(symbols); + } + + os_stream_flush(stream); + } +} +#endif diff --git a/mesalib/src/gallium/auxiliary/util/u_debug_refcnt.h b/mesalib/src/gallium/auxiliary/util/u_debug_refcnt.h new file mode 100644 index 000000000..61cc7122c --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_debug_refcnt.h @@ -0,0 +1,63 @@ +/************************************************************************** + * + * Copyright 2010 Luca Barbieri + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and 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 COPYRIGHT OWNER(S) 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 U_DEBUG_REFCNT_H_ +#define U_DEBUG_REFCNT_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (*debug_reference_descriptor)(char*, const struct pipe_reference*); + +#if defined(DEBUG) && (!defined(PIPE_OS_WINDOWS) || defined(PIPE_SUBSYSTEM_WINDOWS_USER)) + +extern int debug_refcnt_state; + +void debug_reference_slowpath(const struct pipe_reference* p, debug_reference_descriptor get_desc, int change); + +static INLINE void debug_reference(const struct pipe_reference* p, debug_reference_descriptor get_desc, int change) +{ + if (debug_refcnt_state >= 0) + debug_reference_slowpath(p, get_desc, change); +} + +#else + +static INLINE void debug_reference(const struct pipe_reference* p, debug_reference_descriptor get_desc, int change) +{ +} + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* U_DEBUG_REFCNT_H_ */ diff --git a/mesalib/src/gallium/auxiliary/util/u_debug_stack.c b/mesalib/src/gallium/auxiliary/util/u_debug_stack.c new file mode 100644 index 000000000..046bb43b1 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_debug_stack.c @@ -0,0 +1,110 @@ +/************************************************************************** + * + * 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. + * + **************************************************************************/ + +/** + * @file + * Stack backtracing. + * + * @author Jose Fonseca + */ + +#include "u_debug.h" +#include "u_debug_symbol.h" +#include "u_debug_stack.h" + + +void +debug_backtrace_capture(struct debug_stack_frame *backtrace, + unsigned start_frame, + unsigned nr_frames) +{ + const void **frame_pointer = NULL; + unsigned i = 0; + + if(!nr_frames) + return; + +#if defined(PIPE_CC_GCC) && defined(PIPE_ARCH_X86) + __asm__ __volatile__("mov (%%ebp),%0": "=r" (frame_pointer)); + frame_pointer = (const void **)frame_pointer[0]; +#elif defined(PIPE_CC_GCC) + frame_pointer = ((const void **)__builtin_frame_address(1)); +#elif defined(PIPE_CC_MSVC) && defined(PIPE_ARCH_X86) + __asm { + mov frame_pointer, ebp + } + frame_pointer = (const void **)frame_pointer[0]; +#else + frame_pointer = NULL; +#endif + + +#ifdef PIPE_ARCH_X86 + while(nr_frames) { + const void **next_frame_pointer; + + if(!frame_pointer) + break; + + if(start_frame) + --start_frame; + else { + backtrace[i++].function = frame_pointer[1]; + --nr_frames; + } + + next_frame_pointer = (const void **)frame_pointer[0]; + + /* Limit the stack walk to avoid referencing undefined memory */ + if((uintptr_t)next_frame_pointer <= (uintptr_t)frame_pointer || + (uintptr_t)next_frame_pointer > (uintptr_t)frame_pointer + 64*1024) + break; + + frame_pointer = next_frame_pointer; + } +#endif + + while(nr_frames) { + backtrace[i++].function = NULL; + --nr_frames; + } +} + + +void +debug_backtrace_dump(const struct debug_stack_frame *backtrace, + unsigned nr_frames) +{ + unsigned i; + + for(i = 0; i < nr_frames; ++i) { + if(!backtrace[i].function) + break; + debug_symbol_print(backtrace[i].function); + } +} + diff --git a/mesalib/src/gallium/auxiliary/util/u_debug_stack.h b/mesalib/src/gallium/auxiliary/util/u_debug_stack.h new file mode 100644 index 000000000..1d9a4a843 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_debug_stack.h @@ -0,0 +1,65 @@ +/************************************************************************** + * + * 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 U_DEBUG_STACK_H_ +#define U_DEBUG_STACK_H_ + + +/** + * @file + * Stack backtracing. + * + * @author Jose Fonseca + */ + + +#ifdef __cplusplus +extern "C" { +#endif + + +struct debug_stack_frame +{ + const void *function; +}; + + +void +debug_backtrace_capture(struct debug_stack_frame *backtrace, + unsigned start_frame, + unsigned nr_frames); + +void +debug_backtrace_dump(const struct debug_stack_frame *backtrace, + unsigned nr_frames); + + +#ifdef __cplusplus +} +#endif + +#endif /* U_DEBUG_STACK_H_ */ diff --git a/mesalib/src/gallium/auxiliary/util/u_debug_symbol.c b/mesalib/src/gallium/auxiliary/util/u_debug_symbol.c new file mode 100644 index 000000000..b2f762c66 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_debug_symbol.c @@ -0,0 +1,243 @@ +/************************************************************************** + * + * 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. + * + **************************************************************************/ + +/** + * @file + * Symbol lookup. + * + * @author Jose Fonseca + */ + +#include "pipe/p_compiler.h" +#include "os/os_thread.h" +#include "u_string.h" + +#include "u_debug.h" +#include "u_debug_symbol.h" +#include "u_hash_table.h" + +#if defined(PIPE_OS_WINDOWS) && defined(PIPE_ARCH_X86) + +#include +#include + +#include "dbghelp.h" + + +static BOOL bSymInitialized = FALSE; + +static HMODULE hModule_Dbghelp = NULL; + + +static +FARPROC WINAPI __GetProcAddress(LPCSTR lpProcName) +{ +#ifdef PIPE_CC_GCC + if (!hModule_Dbghelp) { + /* + * bfdhelp.dll is a dbghelp.dll look-alike replacement, which is able to + * understand MinGW symbols using BFD library. It is available from + * http://people.freedesktop.org/~jrfonseca/bfdhelp/ for now. + */ + hModule_Dbghelp = LoadLibraryA("bfdhelp.dll"); + } +#endif + + if (!hModule_Dbghelp) { + hModule_Dbghelp = LoadLibraryA("dbghelp.dll"); + if (!hModule_Dbghelp) { + return NULL; + } + } + + return GetProcAddress(hModule_Dbghelp, lpProcName); +} + + +typedef BOOL (WINAPI *PFNSYMINITIALIZE)(HANDLE, LPSTR, BOOL); +static PFNSYMINITIALIZE pfnSymInitialize = NULL; + +static +BOOL WINAPI j_SymInitialize(HANDLE hProcess, PSTR UserSearchPath, BOOL fInvadeProcess) +{ + if( + (pfnSymInitialize || (pfnSymInitialize = (PFNSYMINITIALIZE) __GetProcAddress("SymInitialize"))) + ) + return pfnSymInitialize(hProcess, UserSearchPath, fInvadeProcess); + else + return FALSE; +} + +typedef DWORD (WINAPI *PFNSYMSETOPTIONS)(DWORD); +static PFNSYMSETOPTIONS pfnSymSetOptions = NULL; + +static +DWORD WINAPI j_SymSetOptions(DWORD SymOptions) +{ + if( + (pfnSymSetOptions || (pfnSymSetOptions = (PFNSYMSETOPTIONS) __GetProcAddress("SymSetOptions"))) + ) + return pfnSymSetOptions(SymOptions); + else + return FALSE; +} + +typedef BOOL (WINAPI *PFNSYMGETSYMFROMADDR)(HANDLE, DWORD64, PDWORD64, PSYMBOL_INFO); +static PFNSYMGETSYMFROMADDR pfnSymFromAddr = NULL; + +static +BOOL WINAPI j_SymFromAddr(HANDLE hProcess, DWORD64 Address, PDWORD64 Displacement, PSYMBOL_INFO Symbol) +{ + if( + (pfnSymFromAddr || (pfnSymFromAddr = (PFNSYMGETSYMFROMADDR) __GetProcAddress("SymFromAddr"))) + ) + return pfnSymFromAddr(hProcess, Address, Displacement, Symbol); + else + return FALSE; +} + + +static INLINE void +debug_symbol_name_dbghelp(const void *addr, char* buf, unsigned size) +{ + HANDLE hProcess; + BYTE symbolBuffer[1024]; + PSYMBOL_INFO pSymbol = (PSYMBOL_INFO) symbolBuffer; + DWORD64 dwDisplacement = 0; /* Displacement of the input address, relative to the start of the symbol */ + + hProcess = GetCurrentProcess(); + + memset(pSymbol, 0, sizeof *pSymbol); + pSymbol->SizeOfStruct = sizeof(symbolBuffer); + pSymbol->MaxNameLen = sizeof(symbolBuffer) - offsetof(SYMBOL_INFO, Name); + + if(!bSymInitialized) { + j_SymSetOptions(/* SYMOPT_UNDNAME | */ SYMOPT_LOAD_LINES); + if(j_SymInitialize(hProcess, NULL, TRUE)) + bSymInitialized = TRUE; + } + + if(!j_SymFromAddr(hProcess, (DWORD64)(uintptr_t)addr, &dwDisplacement, pSymbol)) + buf[0] = 0; + else + { + strncpy(buf, pSymbol->Name, size); + buf[size - 1] = 0; + } +} +#endif + +#ifdef __GLIBC__ +#include + +/* This can only provide dynamic symbols, or binary offsets into a file. + * + * To fix this, post-process the output with tools/addr2line.sh + */ +static INLINE void +debug_symbol_name_glibc(const void *addr, char* buf, unsigned size) +{ + char** syms = backtrace_symbols((void**)&addr, 1); + strncpy(buf, syms[0], size); + buf[size - 1] = 0; + free(syms); +} +#endif + +void +debug_symbol_name(const void *addr, char* buf, unsigned size) +{ +#if defined(PIPE_OS_WINDOWS) && defined(PIPE_ARCH_X86) + debug_symbol_name_dbghelp(addr, buf, size); + if(buf[0]) + return; +#endif + +#ifdef __GLIBC__ + debug_symbol_name_glibc(addr, buf, size); + if(buf[0]) + return; +#endif + + util_snprintf(buf, size, "%p", addr); + buf[size - 1] = 0; +} + +void +debug_symbol_print(const void *addr) +{ + char buf[1024]; + debug_symbol_name(addr, buf, sizeof(buf)); + debug_printf("\t%s\n", buf); +} + +struct util_hash_table* symbols_hash; +pipe_static_mutex(symbols_mutex); + +static unsigned hash_ptr(void* p) +{ + return (unsigned)(uintptr_t)p; +} + +static int compare_ptr(void* a, void* b) +{ + if(a == b) + return 0; + else if(a < b) + return -1; + else + return 1; +} + +const char* +debug_symbol_name_cached(const void *addr) +{ + const char* name; +#ifdef PIPE_SUBSYSTEM_WINDOWS_USER + static boolean first = TRUE; + + if (first) { + pipe_mutex_init(symbols_mutex); + first = FALSE; + } +#endif + + pipe_mutex_lock(symbols_mutex); + if(!symbols_hash) + symbols_hash = util_hash_table_create(hash_ptr, compare_ptr); + name = util_hash_table_get(symbols_hash, (void*)addr); + if(!name) + { + char buf[1024]; + debug_symbol_name(addr, buf, sizeof(buf)); + name = strdup(buf); + + util_hash_table_set(symbols_hash, (void*)addr, (void*)name); + } + pipe_mutex_unlock(symbols_mutex); + return name; +} diff --git a/mesalib/src/gallium/auxiliary/util/u_debug_symbol.h b/mesalib/src/gallium/auxiliary/util/u_debug_symbol.h new file mode 100644 index 000000000..74285e064 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_debug_symbol.h @@ -0,0 +1,58 @@ +/************************************************************************** + * + * 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 U_DEBUG_SYMBOL_H_ +#define U_DEBUG_SYMBOL_H_ + + +/** + * @file + * Symbol lookup. + * + * @author Jose Fonseca + */ + + +#ifdef __cplusplus +extern "C" { +#endif + + +void +debug_symbol_name(const void *addr, char* buf, unsigned size); + +const char* +debug_symbol_name_cached(const void *addr); + +void +debug_symbol_print(const void *addr); + +#ifdef __cplusplus +} +#endif + +#endif /* U_DEBUG_SYMBOL_H_ */ diff --git a/mesalib/src/gallium/auxiliary/util/u_dirty_flags.h b/mesalib/src/gallium/auxiliary/util/u_dirty_flags.h new file mode 100644 index 000000000..9b509d591 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_dirty_flags.h @@ -0,0 +1,32 @@ +#ifndef U_DIRTY_FLAGS_H +#define U_DIRTY_FLAGS_H + +/* Here's a convenient list of dirty flags to use in a driver. Either + * include it directly or use it as a starting point for your own + * list. + */ +#define U_NEW_VIEWPORT 0x1 +#define U_NEW_RASTERIZER 0x2 +#define U_NEW_FS 0x4 +#define U_NEW_FS_CONSTANTS 0x8 +#define U_NEW_FS_SAMPLER_VIEW 0x10 +#define U_NEW_FS_SAMPLER_STATES 0x20 +#define U_NEW_VS 0x40 +#define U_NEW_VS_CONSTANTS 0x80 +#define U_NEW_VS_SAMPLER_VIEW 0x100 +#define U_NEW_VS_SAMPLER_STATES 0x200 +#define U_NEW_BLEND 0x400 +#define U_NEW_CLIP 0x800 +#define U_NEW_SCISSOR 0x1000 +#define U_NEW_POLYGON_STIPPLE 0x2000 +#define U_NEW_FRAMEBUFFER 0x4000 +#define U_NEW_VERTEX_ELEMENTS 0x8000 +#define U_NEW_VERTEX_BUFFER 0x10000 +#define U_NEW_QUERY 0x20000 +#define U_NEW_DEPTH_STENCIL 0x40000 +#define U_NEW_GS 0x80000 +#define U_NEW_GS_CONSTANTS 0x100000 +#define U_NEW_GS_SAMPLER_VIEW 0x200000 +#define U_NEW_GS_SAMPLER_STATES 0x400000 + +#endif diff --git a/mesalib/src/gallium/auxiliary/util/u_dirty_surfaces.h b/mesalib/src/gallium/auxiliary/util/u_dirty_surfaces.h new file mode 100644 index 000000000..bbc3179f0 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_dirty_surfaces.h @@ -0,0 +1,119 @@ +/************************************************************************** + * + * Copyright 2010 Luca Barbieri + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and 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 COPYRIGHT OWNER(S) 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 U_DIRTY_SURFACES_H_ +#define U_DIRTY_SURFACES_H_ + +#include "pipe/p_state.h" + +#include "util/u_double_list.h" +#include "util/u_math.h" + +struct pipe_context; + +typedef void (*util_dirty_surface_flush_t) (struct pipe_context *, struct pipe_surface *); + +struct util_dirty_surfaces +{ + struct list_head dirty_list; +}; + +struct util_dirty_surface +{ + struct pipe_surface base; + struct list_head dirty_list; +}; + +static INLINE void +util_dirty_surfaces_init(struct util_dirty_surfaces *ds) +{ + LIST_INITHEAD(&ds->dirty_list); +} + +static INLINE void +util_dirty_surfaces_use_for_sampling(struct pipe_context *pipe, struct util_dirty_surfaces *dss, util_dirty_surface_flush_t flush) +{ + struct list_head *p, *next; + for(p = dss->dirty_list.next; p != &dss->dirty_list; p = next) + { + struct util_dirty_surface *ds = LIST_ENTRY(struct util_dirty_surface, p, dirty_list); + next = p->next; + + flush(pipe, &ds->base); + } +} + +static INLINE void +util_dirty_surfaces_use_levels_for_sampling(struct pipe_context *pipe, struct util_dirty_surfaces *dss, unsigned first, unsigned last, util_dirty_surface_flush_t flush) +{ + struct list_head *p, *next; + if(first > last) + return; + for(p = dss->dirty_list.next; p != &dss->dirty_list; p = next) + { + struct util_dirty_surface *ds = LIST_ENTRY(struct util_dirty_surface, p, dirty_list); + next = p->next; + + if(ds->base.u.tex.level >= first && ds->base.u.tex.level <= last) + flush(pipe, &ds->base); + } +} + +static INLINE void +util_dirty_surfaces_use_for_sampling_with(struct pipe_context *pipe, struct util_dirty_surfaces *dss, struct pipe_sampler_view *psv, struct pipe_sampler_state *pss, util_dirty_surface_flush_t flush) +{ + if(!LIST_IS_EMPTY(&dss->dirty_list)) + util_dirty_surfaces_use_levels_for_sampling(pipe, dss, (unsigned)pss->min_lod + psv->u.tex.first_level, + MIN2((unsigned)ceilf(pss->max_lod) + psv->u.tex.first_level, psv->u.tex.last_level), flush); +} + +static INLINE void +util_dirty_surface_init(struct util_dirty_surface *ds) +{ + LIST_INITHEAD(&ds->dirty_list); +} + +static INLINE boolean +util_dirty_surface_is_dirty(struct util_dirty_surface *ds) +{ + return !LIST_IS_EMPTY(&ds->dirty_list); +} + +static INLINE void +util_dirty_surface_set_dirty(struct util_dirty_surfaces *dss, struct util_dirty_surface *ds) +{ + if(LIST_IS_EMPTY(&ds->dirty_list)) + LIST_ADDTAIL(&ds->dirty_list, &dss->dirty_list); +} + +static INLINE void +util_dirty_surface_set_clean(struct util_dirty_surfaces *dss, struct util_dirty_surface *ds) +{ + if(!LIST_IS_EMPTY(&ds->dirty_list)) + LIST_DELINIT(&ds->dirty_list); +} + +#endif diff --git a/mesalib/src/gallium/auxiliary/util/u_dl.c b/mesalib/src/gallium/auxiliary/util/u_dl.c new file mode 100644 index 000000000..dcdb7ebdd --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_dl.c @@ -0,0 +1,94 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * Copyright 1999-2008 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, sub license, and/or 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 "pipe/p_config.h" +#include "pipe/p_compiler.h" + +#if defined(PIPE_OS_UNIX) +#include +#endif +#if defined(PIPE_OS_WINDOWS) +#include +#endif + +#include "u_dl.h" +#include "u_pointer.h" + + +struct util_dl_library * +util_dl_open(const char *filename) +{ +#if defined(PIPE_OS_UNIX) + return (struct util_dl_library *)dlopen(filename, RTLD_LAZY | RTLD_GLOBAL); +#elif defined(PIPE_OS_WINDOWS) + return (struct util_dl_library *)LoadLibraryA(filename); +#else + return NULL; +#endif +} + + +util_dl_proc +util_dl_get_proc_address(struct util_dl_library *library, + const char *procname) +{ +#if defined(PIPE_OS_UNIX) + return (util_dl_proc) pointer_to_func(dlsym((void *)library, procname)); +#elif defined(PIPE_OS_WINDOWS) + return (util_dl_proc)GetProcAddress((HMODULE)library, procname); +#else + return (util_dl_proc)NULL; +#endif +} + + +void +util_dl_close(struct util_dl_library *library) +{ +#if defined(PIPE_OS_UNIX) + dlclose((void *)library); +#elif defined(PIPE_OS_WINDOWS) + FreeLibrary((HMODULE)library); +#else + (void)library; +#endif +} + + +const char * +util_dl_error(void) +{ +#if defined(PIPE_OS_UNIX) + return dlerror(); +#elif defined(PIPE_OS_WINDOWS) + return "unknown error"; +#else + return "unknown error"; +#endif +} diff --git a/mesalib/src/gallium/auxiliary/util/u_dl.h b/mesalib/src/gallium/auxiliary/util/u_dl.h new file mode 100644 index 000000000..b24183494 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_dl.h @@ -0,0 +1,83 @@ +/************************************************************************** + * + * 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 SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 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 U_DL_H_ +#define U_DL_H_ + + +#include "pipe/p_config.h" + + +#if defined(PIPE_OS_WINDOWS) +# define UTIL_DL_EXT ".dll" +# define UTIL_DL_PREFIX "" +#elif defined(PIPE_OS_APPLE) +# define UTIL_DL_EXT ".dylib" +# define UTIL_DL_PREFIX "lib" +#else +# define UTIL_DL_EXT ".so" +# define UTIL_DL_PREFIX "lib" +#endif + + +struct util_dl_library; + + +typedef void (*util_dl_proc)(void); + + +/** + * Open a library dynamically. + */ +struct util_dl_library * +util_dl_open(const char *filename); + + +/** + * Lookup a function in a library. + */ +util_dl_proc +util_dl_get_proc_address(struct util_dl_library *library, + const char *procname); + + +/** + * Close a library. + */ +void +util_dl_close(struct util_dl_library *library); + + +/** + * Return most recent error message. + */ +const char * +util_dl_error(void); + + +#endif /* U_DL_H_ */ diff --git a/mesalib/src/gallium/auxiliary/util/u_double_list.h b/mesalib/src/gallium/auxiliary/util/u_double_list.h new file mode 100644 index 000000000..29f0b9d09 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_double_list.h @@ -0,0 +1,141 @@ +/************************************************************************** + * + * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND. USA. + * 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 SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 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. + * + **************************************************************************/ + +/** + * \file + * List macros heavily inspired by the Linux kernel + * list handling. No list looping yet. + * + * Is not threadsafe, so common operations need to + * be protected using an external mutex. + */ + +#ifndef _U_DOUBLE_LIST_H_ +#define _U_DOUBLE_LIST_H_ + + +#include +#include "pipe/p_compiler.h" + + +struct list_head +{ + struct list_head *prev; + struct list_head *next; +}; + +static INLINE void list_inithead(struct list_head *item) +{ + item->prev = item; + item->next = item; +} + +static INLINE void list_add(struct list_head *item, struct list_head *list) +{ + item->prev = list; + item->next = list->next; + list->next->prev = item; + list->next = item; +} + +static INLINE void list_addtail(struct list_head *item, struct list_head *list) +{ + item->next = list; + item->prev = list->prev; + list->prev->next = item; + list->prev = item; +} + +static INLINE void list_replace(struct list_head *from, struct list_head *to) +{ + to->prev = from->prev; + to->next = from->next; + from->next->prev = to; + from->prev->next = to; +} + +static INLINE void list_del(struct list_head *item) +{ + item->prev->next = item->next; + item->next->prev = item->prev; +} + +static INLINE void list_delinit(struct list_head *item) +{ + item->prev->next = item->next; + item->next->prev = item->prev; + item->next = item; + item->prev = item; +} + +#define LIST_INITHEAD(__item) list_inithead(__item) +#define LIST_ADD(__item, __list) list_add(__item, __list) +#define LIST_ADDTAIL(__item, __list) list_addtail(__item, __list) +#define LIST_REPLACE(__from, __to) list_replace(__from, __to) +#define LIST_DEL(__item) list_del(__item) +#define LIST_DELINIT(__item) list_delinit(__item) + +#define LIST_ENTRY(__type, __item, __field) \ + ((__type *)(((char *)(__item)) - offsetof(__type, __field))) + +#define LIST_IS_EMPTY(__list) \ + ((__list)->next == (__list)) + +#ifndef container_of +#define container_of(ptr, sample, member) \ + (void *)((char *)(ptr) \ + - ((char *)&(sample)->member - (char *)(sample))) +#endif + +#define LIST_FOR_EACH_ENTRY(pos, head, member) \ + for (pos = container_of((head)->next, pos, member); \ + &pos->member != (head); \ + pos = container_of(pos->member.next, pos, member)) + +#define LIST_FOR_EACH_ENTRY_SAFE(pos, storage, head, member) \ + for (pos = container_of((head)->next, pos, member), \ + storage = container_of(pos->member.next, pos, member); \ + &pos->member != (head); \ + pos = storage, storage = container_of(storage->member.next, storage, member)) + +#define LIST_FOR_EACH_ENTRY_SAFE_REV(pos, storage, head, member) \ + for (pos = container_of((head)->prev, pos, member), \ + storage = container_of(pos->member.prev, pos, member); \ + &pos->member != (head); \ + pos = storage, storage = container_of(storage->member.prev, storage, member)) + +#define LIST_FOR_EACH_ENTRY_FROM(pos, start, head, member) \ + for (pos = container_of((start), pos, member); \ + &pos->member != (head); \ + pos = container_of(pos->member.next, pos, member)) + +#define LIST_FOR_EACH_ENTRY_FROM_REV(pos, start, head, member) \ + for (pos = container_of((start), pos, member); \ + &pos->member != (head); \ + pos = container_of(pos->member.prev, pos, member)) + +#endif /*_U_DOUBLE_LIST_H_*/ diff --git a/mesalib/src/gallium/auxiliary/util/u_draw.c b/mesalib/src/gallium/auxiliary/util/u_draw.c new file mode 100644 index 000000000..4f2565edb --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_draw.c @@ -0,0 +1,99 @@ +/************************************************************************** + * + * Copyright 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, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 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_debug.h" +#include "util/u_math.h" +#include "util/u_format.h" +#include "util/u_draw.h" + + +/** + * Returns the largest legal index value for the current set of bound vertex + * buffers. Regardless of any other consideration, all vertex lookups need to + * be clamped to 0..max_index to prevent an out-of-bound access. + */ +unsigned +util_draw_max_index( + const struct pipe_vertex_buffer *vertex_buffers, + unsigned nr_vertex_buffers, + const struct pipe_vertex_element *vertex_elements, + unsigned nr_vertex_elements, + const struct pipe_draw_info *info) +{ + unsigned max_index; + unsigned i; + + max_index = ~0; + for (i = 0; i < nr_vertex_elements; i++) { + const struct pipe_vertex_element *element = + &vertex_elements[i]; + const struct pipe_vertex_buffer *buffer = + &vertex_buffers[element->vertex_buffer_index]; + unsigned buffer_size; + const struct util_format_description *format_desc; + unsigned format_size; + + assert(buffer->buffer->height0 == 1); + assert(buffer->buffer->depth0 == 1); + buffer_size = buffer->buffer->width0; + + format_desc = util_format_description(element->src_format); + assert(format_desc->block.width == 1); + assert(format_desc->block.height == 1); + assert(format_desc->block.bits % 8 == 0); + format_size = format_desc->block.bits/8; + + assert(buffer_size - buffer->buffer_offset <= buffer_size); + buffer_size -= buffer->buffer_offset; + + assert(buffer_size - element->src_offset <= buffer_size); + buffer_size -= element->src_offset; + + assert(buffer_size - format_size <= buffer_size); + buffer_size -= format_size; + + if (buffer->stride != 0) { + unsigned buffer_max_index; + + buffer_max_index = buffer_size / buffer->stride; + + if (element->instance_divisor == 0) { + /* Per-vertex data */ + max_index = MIN2(max_index, buffer_max_index); + } + else { + /* Per-instance data. Simply make sure the state tracker didn't + * request more instances than those that fit in the buffer */ + assert((info->start_instance + info->instance_count)/element->instance_divisor + <= (buffer_max_index + 1)); + } + } + } + + return max_index; +} diff --git a/mesalib/src/gallium/auxiliary/util/u_draw.h b/mesalib/src/gallium/auxiliary/util/u_draw.h new file mode 100644 index 000000000..69cf25aff --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_draw.h @@ -0,0 +1,158 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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 TUNGSTEN GRAPHICS 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 U_DRAW_H +#define U_DRAW_H + + +#include "pipe/p_compiler.h" +#include "pipe/p_context.h" +#include "pipe/p_state.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +static INLINE void +util_draw_init_info(struct pipe_draw_info *info) +{ + memset(info, 0, sizeof(*info)); + info->instance_count = 1; + info->max_index = 0xffffffff; +} + + +static INLINE void +util_draw_arrays(struct pipe_context *pipe, uint mode, uint start, uint count) +{ + struct pipe_draw_info info; + + util_draw_init_info(&info); + info.mode = mode; + info.start = start; + info.count = count; + info.min_index = start; + info.max_index = start + count - 1; + + pipe->draw_vbo(pipe, &info); +} + +static INLINE void +util_draw_elements(struct pipe_context *pipe, int index_bias, + uint mode, uint start, uint count) +{ + struct pipe_draw_info info; + + util_draw_init_info(&info); + info.indexed = TRUE; + info.mode = mode; + info.start = start; + info.count = count; + info.index_bias = index_bias; + + pipe->draw_vbo(pipe, &info); +} + +static INLINE void +util_draw_arrays_instanced(struct pipe_context *pipe, + uint mode, uint start, uint count, + uint start_instance, + uint instance_count) +{ + struct pipe_draw_info info; + + util_draw_init_info(&info); + info.mode = mode; + info.start = start; + info.count = count; + info.start_instance = start_instance; + info.instance_count = instance_count; + info.min_index = start; + info.max_index = start + count - 1; + + pipe->draw_vbo(pipe, &info); +} + +static INLINE void +util_draw_elements_instanced(struct pipe_context *pipe, + int index_bias, + uint mode, uint start, uint count, + uint start_instance, + uint instance_count) +{ + struct pipe_draw_info info; + + util_draw_init_info(&info); + info.indexed = TRUE; + info.mode = mode; + info.start = start; + info.count = count; + info.index_bias = index_bias; + info.start_instance = start_instance; + info.instance_count = instance_count; + + pipe->draw_vbo(pipe, &info); +} + +static INLINE void +util_draw_range_elements(struct pipe_context *pipe, + int index_bias, + uint min_index, + uint max_index, + uint mode, uint start, uint count) +{ + struct pipe_draw_info info; + + util_draw_init_info(&info); + info.indexed = TRUE; + info.mode = mode; + info.start = start; + info.count = count; + info.index_bias = index_bias; + info.min_index = min_index; + info.max_index = max_index; + + pipe->draw_vbo(pipe, &info); +} + + +unsigned +util_draw_max_index( + const struct pipe_vertex_buffer *vertex_buffers, + unsigned nr_vertex_buffers, + const struct pipe_vertex_element *vertex_elements, + unsigned nr_vertex_elements, + const struct pipe_draw_info *info); + + +#ifdef __cplusplus +} +#endif + +#endif /* !U_DRAW_H */ diff --git a/mesalib/src/gallium/auxiliary/util/u_draw_quad.c b/mesalib/src/gallium/auxiliary/util/u_draw_quad.c new file mode 100644 index 000000000..371fefb9e --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_draw_quad.c @@ -0,0 +1,135 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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 TUNGSTEN GRAPHICS 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_context.h" +#include "pipe/p_defines.h" +#include "util/u_inlines.h" +#include "util/u_draw_quad.h" +#include "util/u_memory.h" +#include "cso_cache/cso_context.h" + + +/** + * Draw a simple vertex buffer / primitive. + * Limited to float[4] vertex attribs, tightly packed. + */ +void +util_draw_vertex_buffer(struct pipe_context *pipe, + struct cso_context *cso, + struct pipe_resource *vbuf, + uint offset, + uint prim_type, + uint num_verts, + uint num_attribs) +{ + struct pipe_vertex_buffer vbuffer; + + assert(num_attribs <= PIPE_MAX_ATTRIBS); + + /* tell pipe about the vertex buffer */ + memset(&vbuffer, 0, sizeof(vbuffer)); + vbuffer.buffer = vbuf; + vbuffer.stride = num_attribs * 4 * sizeof(float); /* vertex size */ + vbuffer.buffer_offset = offset; + + if (cso) { + cso_set_vertex_buffers(cso, 1, &vbuffer); + } else { + pipe->set_vertex_buffers(pipe, 1, &vbuffer); + } + + /* note: vertex elements already set by caller */ + + /* draw */ + util_draw_arrays(pipe, prim_type, 0, num_verts); +} + + + +/** + * Draw screen-aligned textured quad. + * Note: this isn't especially efficient. + */ +void +util_draw_texquad(struct pipe_context *pipe, struct cso_context *cso, + float x0, float y0, float x1, float y1, float z) +{ + uint numAttribs = 2, i, j; + uint vertexBytes = 4 * (4 * numAttribs * sizeof(float)); + struct pipe_resource *vbuf = NULL; + float *v = NULL; + + v = MALLOC(vertexBytes); + if (v == NULL) + goto out; + + /* + * Load vertex buffer + */ + for (i = j = 0; i < 4; i++) { + v[j + 2] = z; /* z */ + v[j + 3] = 1.0; /* w */ + v[j + 6] = 0.0; /* r */ + v[j + 7] = 1.0; /* q */ + j += 8; + } + + v[0] = x0; + v[1] = y0; + v[4] = 0.0; /*s*/ + v[5] = 0.0; /*t*/ + + v[8] = x1; + v[9] = y0; + v[12] = 1.0; + v[13] = 0.0; + + v[16] = x1; + v[17] = y1; + v[20] = 1.0; + v[21] = 1.0; + + v[24] = x0; + v[25] = y1; + v[28] = 0.0; + v[29] = 1.0; + + vbuf = pipe_user_buffer_create(pipe->screen, v, vertexBytes, + PIPE_BIND_VERTEX_BUFFER); + if (!vbuf) + goto out; + + util_draw_vertex_buffer(pipe, cso, vbuf, 0, PIPE_PRIM_TRIANGLE_FAN, 4, 2); + +out: + if (vbuf) + pipe_resource_reference(&vbuf, NULL); + + if (v) + FREE(v); +} diff --git a/mesalib/src/gallium/auxiliary/util/u_draw_quad.h b/mesalib/src/gallium/auxiliary/util/u_draw_quad.h new file mode 100644 index 000000000..997bbf060 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_draw_quad.h @@ -0,0 +1,61 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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 TUNGSTEN GRAPHICS 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 U_DRAWQUAD_H +#define U_DRAWQUAD_H + + +#include "pipe/p_compiler.h" +#include "pipe/p_context.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +struct pipe_resource; +struct cso_context; + +#include "util/u_draw.h" + +extern void +util_draw_vertex_buffer(struct pipe_context *pipe, struct cso_context *cso, + struct pipe_resource *vbuf, uint offset, + uint num_attribs, uint num_verts, uint prim_type); + + +extern void +util_draw_texquad(struct pipe_context *pipe, struct cso_context *cso, + float x0, float y0, float x1, float y1, float z); + + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/mesalib/src/gallium/auxiliary/util/u_dump.h b/mesalib/src/gallium/auxiliary/util/u_dump.h new file mode 100644 index 000000000..7d89db163 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_dump.h @@ -0,0 +1,179 @@ +/************************************************************************** + * + * 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. + * + **************************************************************************/ + +/** + * @file + * Dump data in human/machine readable format. + * + * @author Jose Fonseca + */ + +#ifndef U_DEBUG_DUMP_H_ +#define U_DEBUG_DUMP_H_ + + +#include "pipe/p_compiler.h" +#include "pipe/p_state.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +#define UTIL_DUMP_INVALID_NAME "" + + +struct os_stream; + + +/* Duplicated here for convenience */ +extern struct os_stream * +os_log_stream; + + +/* + * p_defines.h + * + * XXX: These functions don't really dump anything -- just translate into + * strings so a verb better than "dump" should be used instead, in order to + * free up the namespace to the true dumper functions. + */ + +const char * +util_dump_blend_factor(unsigned value, boolean shortened); + +const char * +util_dump_blend_func(unsigned value, boolean shortened); + +const char * +util_dump_logicop(unsigned value, boolean shortened); + +const char * +util_dump_func(unsigned value, boolean shortened); + +const char * +util_dump_stencil_op(unsigned value, boolean shortened); + +const char * +util_dump_tex_target(unsigned value, boolean shortened); + +const char * +util_dump_tex_wrap(unsigned value, boolean shortened); + +const char * +util_dump_tex_mipfilter(unsigned value, boolean shortened); + +const char * +util_dump_tex_filter(unsigned value, boolean shortened); + + +/* + * p_state.h, through an os_stream + */ + +void +util_dump_template(struct os_stream *stream, + const struct pipe_resource *templat); + +void +util_dump_rasterizer_state(struct os_stream *stream, + const struct pipe_rasterizer_state *state); + +void +util_dump_poly_stipple(struct os_stream *stream, + const struct pipe_poly_stipple *state); + +void +util_dump_viewport_state(struct os_stream *stream, + const struct pipe_viewport_state *state); + +void +util_dump_scissor_state(struct os_stream *stream, + const struct pipe_scissor_state *state); + +void +util_dump_clip_state(struct os_stream *stream, + const struct pipe_clip_state *state); + +void +util_dump_shader_state(struct os_stream *stream, + const struct pipe_shader_state *state); + +void +util_dump_depth_stencil_alpha_state(struct os_stream *stream, + const struct pipe_depth_stencil_alpha_state *state); + +void +util_dump_rt_blend_state(struct os_stream *stream, + const struct pipe_rt_blend_state *state); + +void +util_dump_blend_state(struct os_stream *stream, + const struct pipe_blend_state *state); + +void +util_dump_blend_color(struct os_stream *stream, + const struct pipe_blend_color *state); + +void +util_dump_stencil_ref(struct os_stream *stream, + const struct pipe_stencil_ref *state); + +void +util_dump_framebuffer_state(struct os_stream *stream, + const struct pipe_framebuffer_state *state); + +void +util_dump_sampler_state(struct os_stream *stream, + const struct pipe_sampler_state *state); + +void +util_dump_surface(struct os_stream *stream, + const struct pipe_surface *state); + +void +util_dump_transfer(struct os_stream *stream, + const struct pipe_transfer *state); + +void +util_dump_vertex_buffer(struct os_stream *stream, + const struct pipe_vertex_buffer *state); + +void +util_dump_vertex_element(struct os_stream *stream, + const struct pipe_vertex_element *state); + + +/* FIXME: Move the other debug_dump_xxx functions out of u_debug.h into here. */ + + +#ifdef __cplusplus +} +#endif + +#endif /* U_DEBUG_H_ */ diff --git a/mesalib/src/gallium/auxiliary/util/u_dump_defines.c b/mesalib/src/gallium/auxiliary/util/u_dump_defines.c new file mode 100644 index 000000000..0a00195aa --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_dump_defines.c @@ -0,0 +1,336 @@ +/************************************************************************** + * + * 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. + * + **************************************************************************/ + + +#include "util/u_memory.h" +#include "util/u_debug.h" +#include "util/u_dump.h" + + +#if 0 +static const char * +util_dump_strip_prefix(const char *name, + const char *prefix) +{ + const char *stripped; + assert(name); + assert(prefix); + stripped = name; + while(*prefix) { + if(*stripped != *prefix) + return name; + + ++stripped; + ++prefix; + } + return stripped; +} +#endif + +static const char * +util_dump_enum_continuous(unsigned value, + unsigned num_names, + const char **names) +{ + if (value >= num_names) + return UTIL_DUMP_INVALID_NAME; + return names[value]; +} + + +#define DEFINE_UTIL_DUMP_CONTINUOUS(_name) \ + const char * \ + util_dump_##_name(unsigned value, boolean shortened) \ + { \ + if(shortened) \ + return util_dump_enum_continuous(value, Elements(util_dump_##_name##_short_names), util_dump_##_name##_short_names); \ + else \ + return util_dump_enum_continuous(value, Elements(util_dump_##_name##_names), util_dump_##_name##_names); \ + } + + +static const char * +util_dump_blend_factor_names[] = { + UTIL_DUMP_INVALID_NAME, /* 0x0 */ + "PIPE_BLENDFACTOR_ONE", + "PIPE_BLENDFACTOR_SRC_COLOR", + "PIPE_BLENDFACTOR_SRC_ALPHA", + "PIPE_BLENDFACTOR_DST_ALPHA", + "PIPE_BLENDFACTOR_DST_COLOR", + "PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE", + "PIPE_BLENDFACTOR_CONST_COLOR", + "PIPE_BLENDFACTOR_CONST_ALPHA", + "PIPE_BLENDFACTOR_SRC1_COLOR", + "PIPE_BLENDFACTOR_SRC1_ALPHA", + UTIL_DUMP_INVALID_NAME, /* 0x0b */ + UTIL_DUMP_INVALID_NAME, /* 0x0c */ + UTIL_DUMP_INVALID_NAME, /* 0x0d */ + UTIL_DUMP_INVALID_NAME, /* 0x0e */ + UTIL_DUMP_INVALID_NAME, /* 0x0f */ + UTIL_DUMP_INVALID_NAME, /* 0x10 */ + "PIPE_BLENDFACTOR_ZERO", + "PIPE_BLENDFACTOR_INV_SRC_COLOR", + "PIPE_BLENDFACTOR_INV_SRC_ALPHA", + "PIPE_BLENDFACTOR_INV_DST_ALPHA", + "PIPE_BLENDFACTOR_INV_DST_COLOR", + UTIL_DUMP_INVALID_NAME, /* 0x16 */ + "PIPE_BLENDFACTOR_INV_CONST_COLOR", + "PIPE_BLENDFACTOR_INV_CONST_ALPHA", + "PIPE_BLENDFACTOR_INV_SRC1_COLOR", + "PIPE_BLENDFACTOR_INV_SRC1_ALPHA" +}; + +static const char * +util_dump_blend_factor_short_names[] = { + UTIL_DUMP_INVALID_NAME, /* 0x0 */ + "one", + "src_color", + "src_alpha", + "dst_alpha", + "dst_color", + "src_alpha_saturate", + "const_color", + "const_alpha", + "src1_color", + "src1_alpha", + UTIL_DUMP_INVALID_NAME, /* 0x0b */ + UTIL_DUMP_INVALID_NAME, /* 0x0c */ + UTIL_DUMP_INVALID_NAME, /* 0x0d */ + UTIL_DUMP_INVALID_NAME, /* 0x0e */ + UTIL_DUMP_INVALID_NAME, /* 0x0f */ + UTIL_DUMP_INVALID_NAME, /* 0x10 */ + "zero", + "inv_src_color", + "inv_src_alpha", + "inv_dst_alpha", + "inv_dst_color", + UTIL_DUMP_INVALID_NAME, /* 0x16 */ + "inv_const_color", + "inv_const_alpha", + "inv_src1_color", + "inv_src1_alpha" +}; + +DEFINE_UTIL_DUMP_CONTINUOUS(blend_factor) + + +static const char * +util_dump_blend_func_names[] = { + "PIPE_BLEND_ADD", + "PIPE_BLEND_SUBTRACT", + "PIPE_BLEND_REVERSE_SUBTRACT", + "PIPE_BLEND_MIN", + "PIPE_BLEND_MAX" +}; + +static const char * +util_dump_blend_func_short_names[] = { + "add", + "sub", + "rev_sub", + "min", + "max" +}; + +DEFINE_UTIL_DUMP_CONTINUOUS(blend_func) + + +static const char * +util_dump_logicop_names[] = { + "PIPE_LOGICOP_CLEAR", + "PIPE_LOGICOP_NOR", + "PIPE_LOGICOP_AND_INVERTED", + "PIPE_LOGICOP_COPY_INVERTED", + "PIPE_LOGICOP_AND_REVERSE", + "PIPE_LOGICOP_INVERT", + "PIPE_LOGICOP_XOR", + "PIPE_LOGICOP_NAND", + "PIPE_LOGICOP_AND", + "PIPE_LOGICOP_EQUIV", + "PIPE_LOGICOP_NOOP", + "PIPE_LOGICOP_OR_INVERTED", + "PIPE_LOGICOP_COPY", + "PIPE_LOGICOP_OR_REVERSE", + "PIPE_LOGICOP_OR", + "PIPE_LOGICOP_SET" +}; + +static const char * +util_dump_logicop_short_names[] = { + "clear", + "nor", + "and_inverted", + "copy_inverted", + "and_reverse", + "invert", + "xor", + "nand", + "and", + "equiv", + "noop", + "or_inverted", + "copy", + "or_reverse", + "or", + "set" +}; + +DEFINE_UTIL_DUMP_CONTINUOUS(logicop) + + +static const char * +util_dump_func_names[] = { + "PIPE_FUNC_NEVER", + "PIPE_FUNC_LESS", + "PIPE_FUNC_EQUAL", + "PIPE_FUNC_LEQUAL", + "PIPE_FUNC_GREATER", + "PIPE_FUNC_NOTEQUAL", + "PIPE_FUNC_GEQUAL", + "PIPE_FUNC_ALWAYS" +}; + +static const char * +util_dump_func_short_names[] = { + "never", + "less", + "equal", + "less_equal", + "greater", + "not_equal", + "greater_equal", + "always" +}; + +DEFINE_UTIL_DUMP_CONTINUOUS(func) + + +static const char * +util_dump_stencil_op_names[] = { + "PIPE_STENCIL_OP_KEEP", + "PIPE_STENCIL_OP_ZERO", + "PIPE_STENCIL_OP_REPLACE", + "PIPE_STENCIL_OP_INCR", + "PIPE_STENCIL_OP_DECR", + "PIPE_STENCIL_OP_INCR_WRAP", + "PIPE_STENCIL_OP_DECR_WRAP", + "PIPE_STENCIL_OP_INVERT" +}; + +static const char * +util_dump_stencil_op_short_names[] = { + "keep", + "zero", + "replace", + "incr", + "decr", + "incr_wrap", + "decr_wrap", + "invert" +}; + +DEFINE_UTIL_DUMP_CONTINUOUS(stencil_op) + + +static const char * +util_dump_tex_target_names[] = { + "PIPE_BUFFER", + "PIPE_TEXTURE_1D", + "PIPE_TEXTURE_2D", + "PIPE_TEXTURE_3D", + "PIPE_TEXTURE_CUBE" +}; + +static const char * +util_dump_tex_target_short_names[] = { + "buffer", + "1d", + "2d", + "3d", + "cube" +}; + +DEFINE_UTIL_DUMP_CONTINUOUS(tex_target) + + +static const char * +util_dump_tex_wrap_names[] = { + "PIPE_TEX_WRAP_REPEAT", + "PIPE_TEX_WRAP_CLAMP", + "PIPE_TEX_WRAP_CLAMP_TO_EDGE", + "PIPE_TEX_WRAP_CLAMP_TO_BORDER", + "PIPE_TEX_WRAP_MIRROR_REPEAT", + "PIPE_TEX_WRAP_MIRROR_CLAMP", + "PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE", + "PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER" +}; + +static const char * +util_dump_tex_wrap_short_names[] = { + "repeat", + "clamp", + "clamp_to_edge", + "clamp_to_border", + "mirror_repeat", + "mirror_clamp", + "mirror_clamp_to_edge", + "mirror_clamp_to_border" +}; + +DEFINE_UTIL_DUMP_CONTINUOUS(tex_wrap) + + +static const char * +util_dump_tex_mipfilter_names[] = { + "PIPE_TEX_MIPFILTER_NEAREST", + "PIPE_TEX_MIPFILTER_LINEAR", + "PIPE_TEX_MIPFILTER_NONE" +}; + +static const char * +util_dump_tex_mipfilter_short_names[] = { + "nearest", + "linear", + "none" +}; + +DEFINE_UTIL_DUMP_CONTINUOUS(tex_mipfilter) + + +static const char * +util_dump_tex_filter_names[] = { + "PIPE_TEX_FILTER_NEAREST", + "PIPE_TEX_FILTER_LINEAR" +}; + +static const char * +util_dump_tex_filter_short_names[] = { + "nearest", + "linear" +}; + +DEFINE_UTIL_DUMP_CONTINUOUS(tex_filter) diff --git a/mesalib/src/gallium/auxiliary/util/u_dump_state.c b/mesalib/src/gallium/auxiliary/util/u_dump_state.c new file mode 100644 index 000000000..54128e6f6 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_dump_state.c @@ -0,0 +1,708 @@ +/************************************************************************** + * + * Copyright 2008-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 "pipe/p_compiler.h" +#include "os/os_stream.h" +#include "util/u_memory.h" +#include "util/u_string.h" +#include "util/u_format.h" +#include "tgsi/tgsi_dump.h" + +#include "u_dump.h" + + +/* + * Dump primitives + */ + +static INLINE void +util_stream_writef(struct os_stream *stream, const char *format, ...) +{ + static char buf[1024]; + unsigned len; + va_list ap; + va_start(ap, format); + len = util_vsnprintf(buf, sizeof(buf), format, ap); + va_end(ap); + os_stream_write(stream, buf, len); +} + +static void +util_dump_bool(struct os_stream *stream, int value) +{ + util_stream_writef(stream, "%c", value ? '1' : '0'); +} + +static void +util_dump_int(struct os_stream *stream, long long int value) +{ + util_stream_writef(stream, "%lli", value); +} + +static void +util_dump_uint(struct os_stream *stream, long long unsigned value) +{ + util_stream_writef(stream, "%llu", value); +} + +static void +util_dump_float(struct os_stream *stream, double value) +{ + util_stream_writef(stream, "%g", value); +} + +static void +util_dump_string(struct os_stream *stream, const char *str) +{ + os_stream_write_str(stream, "\""); + os_stream_write_str(stream, str); + os_stream_write_str(stream, "\""); +} + +static void +util_dump_enum(struct os_stream *stream, const char *value) +{ + os_stream_write_str(stream, value); +} + +static void +util_dump_array_begin(struct os_stream *stream) +{ + os_stream_write_str(stream, "{"); +} + +static void +util_dump_array_end(struct os_stream *stream) +{ + os_stream_write_str(stream, "}"); +} + +static void +util_dump_elem_begin(struct os_stream *stream) +{ +} + +static void +util_dump_elem_end(struct os_stream *stream) +{ + os_stream_write_str(stream, ", "); +} + +static void +util_dump_struct_begin(struct os_stream *stream, const char *name) +{ + os_stream_write_str(stream, "{"); +} + +static void +util_dump_struct_end(struct os_stream *stream) +{ + os_stream_write_str(stream, "}"); +} + +static void +util_dump_member_begin(struct os_stream *stream, const char *name) +{ + util_stream_writef(stream, "%s = ", name); +} + +static void +util_dump_member_end(struct os_stream *stream) +{ + os_stream_write_str(stream, ", "); +} + +static void +util_dump_null(struct os_stream *stream) +{ + os_stream_write_str(stream, "NULL"); +} + +static void +util_dump_ptr(struct os_stream *stream, const void *value) +{ + if(value) + util_stream_writef(stream, "0x%08lx", (unsigned long)(uintptr_t)value); + else + util_dump_null(stream); +} + + +/* + * Code saving macros. + */ + +#define util_dump_arg(_stream, _type, _arg) \ + do { \ + util_dump_arg_begin(_stream, #_arg); \ + util_dump_##_type(_stream, _arg); \ + util_dump_arg_end(_stream); \ + } while(0) + +#define util_dump_ret(_stream, _type, _arg) \ + do { \ + util_dump_ret_begin(_stream); \ + util_dump_##_type(_stream, _arg); \ + util_dump_ret_end(_stream); \ + } while(0) + +#define util_dump_array(_stream, _type, _obj, _size) \ + do { \ + size_t idx; \ + util_dump_array_begin(_stream); \ + for(idx = 0; idx < (_size); ++idx) { \ + util_dump_elem_begin(_stream); \ + util_dump_##_type(_stream, (_obj)[idx]); \ + util_dump_elem_end(_stream); \ + } \ + util_dump_array_end(_stream); \ + } while(0) + +#define util_dump_struct_array(_stream, _type, _obj, _size) \ + do { \ + size_t idx; \ + util_dump_array_begin(_stream); \ + for(idx = 0; idx < (_size); ++idx) { \ + util_dump_elem_begin(_stream); \ + util_dump_##_type(_stream, &(_obj)[idx]); \ + util_dump_elem_end(_stream); \ + } \ + util_dump_array_end(_stream); \ + } while(0) + +#define util_dump_member(_stream, _type, _obj, _member) \ + do { \ + util_dump_member_begin(_stream, #_member); \ + util_dump_##_type(_stream, (_obj)->_member); \ + util_dump_member_end(_stream); \ + } while(0) + +#define util_dump_arg_array(_stream, _type, _arg, _size) \ + do { \ + util_dump_arg_begin(_stream, #_arg); \ + util_dump_array(_stream, _type, _arg, _size); \ + util_dump_arg_end(_stream); \ + } while(0) + +#define util_dump_member_array(_stream, _type, _obj, _member) \ + do { \ + util_dump_member_begin(_stream, #_member); \ + util_dump_array(_stream, _type, (_obj)->_member, sizeof((_obj)->_member)/sizeof((_obj)->_member[0])); \ + util_dump_member_end(_stream); \ + } while(0) + + + +/* + * Wrappers for enum -> string dumpers. + */ + + +static void +util_dump_format(struct os_stream *stream, enum pipe_format format) +{ + util_dump_enum(stream, util_format_name(format)); +} + + +static void +util_dump_enum_blend_factor(struct os_stream *stream, unsigned value) +{ + util_dump_enum(stream, util_dump_blend_factor(value, TRUE)); +} + +static void +util_dump_enum_blend_func(struct os_stream *stream, unsigned value) +{ + util_dump_enum(stream, util_dump_blend_func(value, TRUE)); +} + +static void +util_dump_enum_func(struct os_stream *stream, unsigned value) +{ + util_dump_enum(stream, util_dump_func(value, TRUE)); +} + + +/* + * Public functions + */ + + +void +util_dump_template(struct os_stream *stream, const struct pipe_resource *templat) +{ + if(!templat) { + util_dump_null(stream); + return; + } + + util_dump_struct_begin(stream, "pipe_resource"); + + util_dump_member(stream, int, templat, target); + util_dump_member(stream, format, templat, format); + + util_dump_member_begin(stream, "width"); + util_dump_uint(stream, templat->width0); + util_dump_member_end(stream); + + util_dump_member_begin(stream, "height"); + util_dump_uint(stream, templat->height0); + util_dump_member_end(stream); + + util_dump_member_begin(stream, "depth"); + util_dump_uint(stream, templat->depth0); + util_dump_member_end(stream); + + util_dump_member_begin(stream, "array_size"); + util_dump_uint(stream, templat->array_size); + util_dump_member_end(stream); + + util_dump_member(stream, uint, templat, last_level); + util_dump_member(stream, uint, templat, usage); + util_dump_member(stream, uint, templat, bind); + util_dump_member(stream, uint, templat, flags); + + util_dump_struct_end(stream); +} + + +void +util_dump_rasterizer_state(struct os_stream *stream, const struct pipe_rasterizer_state *state) +{ + if(!state) { + util_dump_null(stream); + return; + } + + util_dump_struct_begin(stream, "pipe_rasterizer_state"); + + util_dump_member(stream, bool, state, flatshade); + util_dump_member(stream, bool, state, light_twoside); + util_dump_member(stream, uint, state, front_ccw); + util_dump_member(stream, uint, state, cull_face); + util_dump_member(stream, uint, state, fill_front); + util_dump_member(stream, uint, state, fill_back); + util_dump_member(stream, bool, state, offset_point); + util_dump_member(stream, bool, state, offset_line); + util_dump_member(stream, bool, state, offset_tri); + util_dump_member(stream, bool, state, scissor); + util_dump_member(stream, bool, state, poly_smooth); + util_dump_member(stream, bool, state, poly_stipple_enable); + util_dump_member(stream, bool, state, point_smooth); + util_dump_member(stream, uint, state, sprite_coord_enable); + util_dump_member(stream, bool, state, sprite_coord_mode); + util_dump_member(stream, bool, state, point_quad_rasterization); + util_dump_member(stream, bool, state, point_size_per_vertex); + util_dump_member(stream, bool, state, multisample); + util_dump_member(stream, bool, state, line_smooth); + util_dump_member(stream, bool, state, line_stipple_enable); + util_dump_member(stream, uint, state, line_stipple_factor); + util_dump_member(stream, uint, state, line_stipple_pattern); + util_dump_member(stream, bool, state, line_last_pixel); + util_dump_member(stream, bool, state, flatshade_first); + util_dump_member(stream, bool, state, gl_rasterization_rules); + + util_dump_member(stream, float, state, line_width); + util_dump_member(stream, float, state, point_size); + util_dump_member(stream, float, state, offset_units); + util_dump_member(stream, float, state, offset_scale); + + util_dump_struct_end(stream); +} + + +void +util_dump_poly_stipple(struct os_stream *stream, const struct pipe_poly_stipple *state) +{ + if(!state) { + util_dump_null(stream); + return; + } + + util_dump_struct_begin(stream, "pipe_poly_stipple"); + + util_dump_member_begin(stream, "stipple"); + util_dump_member_array(stream, uint, state, stipple); + util_dump_member_end(stream); + + util_dump_struct_end(stream); +} + + +void +util_dump_viewport_state(struct os_stream *stream, const struct pipe_viewport_state *state) +{ + if(!state) { + util_dump_null(stream); + return; + } + + util_dump_struct_begin(stream, "pipe_viewport_state"); + + util_dump_member_array(stream, float, state, scale); + util_dump_member_array(stream, float, state, translate); + + util_dump_struct_end(stream); +} + + +void +util_dump_scissor_state(struct os_stream *stream, const struct pipe_scissor_state *state) +{ + if(!state) { + util_dump_null(stream); + return; + } + + util_dump_struct_begin(stream, "pipe_scissor_state"); + + util_dump_member(stream, uint, state, minx); + util_dump_member(stream, uint, state, miny); + util_dump_member(stream, uint, state, maxx); + util_dump_member(stream, uint, state, maxy); + + util_dump_struct_end(stream); +} + + +void +util_dump_clip_state(struct os_stream *stream, const struct pipe_clip_state *state) +{ + unsigned i; + + if(!state) { + util_dump_null(stream); + return; + } + + util_dump_struct_begin(stream, "pipe_clip_state"); + + util_dump_member_begin(stream, "ucp"); + util_dump_array_begin(stream); + for(i = 0; i < PIPE_MAX_CLIP_PLANES; ++i) { + util_dump_elem_begin(stream); + util_dump_array(stream, float, state->ucp[i], 4); + util_dump_elem_end(stream); + } + util_dump_array_end(stream); + util_dump_member_end(stream); + + util_dump_member(stream, uint, state, nr); + + util_dump_struct_end(stream); +} + + +void +util_dump_shader_state(struct os_stream *stream, const struct pipe_shader_state *state) +{ + char str[8192]; + + if(!state) { + util_dump_null(stream); + return; + } + + tgsi_dump_str(state->tokens, 0, str, sizeof(str)); + + util_dump_struct_begin(stream, "pipe_shader_state"); + + util_dump_member_begin(stream, "tokens"); + util_dump_string(stream, str); + util_dump_member_end(stream); + + util_dump_struct_end(stream); +} + + +void +util_dump_depth_stencil_alpha_state(struct os_stream *stream, const struct pipe_depth_stencil_alpha_state *state) +{ + unsigned i; + + if(!state) { + util_dump_null(stream); + return; + } + + util_dump_struct_begin(stream, "pipe_depth_stencil_alpha_state"); + + util_dump_member_begin(stream, "depth"); + util_dump_struct_begin(stream, "pipe_depth_state"); + util_dump_member(stream, bool, &state->depth, enabled); + if (state->depth.enabled) { + util_dump_member(stream, bool, &state->depth, writemask); + util_dump_member(stream, enum_func, &state->depth, func); + } + util_dump_struct_end(stream); + util_dump_member_end(stream); + + util_dump_member_begin(stream, "stencil"); + util_dump_array_begin(stream); + for(i = 0; i < Elements(state->stencil); ++i) { + util_dump_elem_begin(stream); + util_dump_struct_begin(stream, "pipe_stencil_state"); + util_dump_member(stream, bool, &state->stencil[i], enabled); + if (state->stencil[i].enabled) { + util_dump_member(stream, enum_func, &state->stencil[i], func); + util_dump_member(stream, uint, &state->stencil[i], fail_op); + util_dump_member(stream, uint, &state->stencil[i], zpass_op); + util_dump_member(stream, uint, &state->stencil[i], zfail_op); + util_dump_member(stream, uint, &state->stencil[i], valuemask); + util_dump_member(stream, uint, &state->stencil[i], writemask); + } + util_dump_struct_end(stream); + util_dump_elem_end(stream); + } + util_dump_array_end(stream); + util_dump_member_end(stream); + + util_dump_member_begin(stream, "alpha"); + util_dump_struct_begin(stream, "pipe_alpha_state"); + util_dump_member(stream, bool, &state->alpha, enabled); + if (state->alpha.enabled) { + util_dump_member(stream, enum_func, &state->alpha, func); + util_dump_member(stream, float, &state->alpha, ref_value); + } + util_dump_struct_end(stream); + util_dump_member_end(stream); + + util_dump_struct_end(stream); +} + +void +util_dump_rt_blend_state(struct os_stream *stream, const struct pipe_rt_blend_state *state) +{ + util_dump_struct_begin(stream, "pipe_rt_blend_state"); + + util_dump_member(stream, uint, state, blend_enable); + if (state->blend_enable) { + util_dump_member(stream, enum_blend_func, state, rgb_func); + util_dump_member(stream, enum_blend_factor, state, rgb_src_factor); + util_dump_member(stream, enum_blend_factor, state, rgb_dst_factor); + + util_dump_member(stream, enum_blend_func, state, alpha_func); + util_dump_member(stream, enum_blend_factor, state, alpha_src_factor); + util_dump_member(stream, enum_blend_factor, state, alpha_dst_factor); + } + + util_dump_member(stream, uint, state, colormask); + + util_dump_struct_end(stream); +} + +void +util_dump_blend_state(struct os_stream *stream, const struct pipe_blend_state *state) +{ + unsigned valid_entries = 1; + + if(!state) { + util_dump_null(stream); + return; + } + + util_dump_struct_begin(stream, "pipe_blend_state"); + + util_dump_member(stream, bool, state, dither); + + util_dump_member(stream, bool, state, logicop_enable); + if (state->logicop_enable) { + util_dump_member(stream, enum_func, state, logicop_func); + } + else { + util_dump_member(stream, bool, state, independent_blend_enable); + + util_dump_member_begin(stream, "rt"); + if (state->independent_blend_enable) + valid_entries = PIPE_MAX_COLOR_BUFS; + util_dump_struct_array(stream, rt_blend_state, state->rt, valid_entries); + util_dump_member_end(stream); + } + + util_dump_struct_end(stream); +} + + +void +util_dump_blend_color(struct os_stream *stream, const struct pipe_blend_color *state) +{ + if(!state) { + util_dump_null(stream); + return; + } + + util_dump_struct_begin(stream, "pipe_blend_color"); + + util_dump_member_array(stream, float, state, color); + + util_dump_struct_end(stream); +} + +void +util_dump_stencil_ref(struct os_stream *stream, const struct pipe_stencil_ref *state) +{ + if(!state) { + util_dump_null(stream); + return; + } + + util_dump_struct_begin(stream, "pipe_stencil_ref"); + + util_dump_member_array(stream, uint, state, ref_value); + + util_dump_struct_end(stream); +} + +void +util_dump_framebuffer_state(struct os_stream *stream, const struct pipe_framebuffer_state *state) +{ + util_dump_struct_begin(stream, "pipe_framebuffer_state"); + + util_dump_member(stream, uint, state, width); + util_dump_member(stream, uint, state, height); + util_dump_member(stream, uint, state, nr_cbufs); + util_dump_member_array(stream, ptr, state, cbufs); + util_dump_member(stream, ptr, state, zsbuf); + + util_dump_struct_end(stream); +} + + +void +util_dump_sampler_state(struct os_stream *stream, const struct pipe_sampler_state *state) +{ + if(!state) { + util_dump_null(stream); + return; + } + + util_dump_struct_begin(stream, "pipe_sampler_state"); + + util_dump_member(stream, uint, state, wrap_s); + util_dump_member(stream, uint, state, wrap_t); + util_dump_member(stream, uint, state, wrap_r); + util_dump_member(stream, uint, state, min_img_filter); + util_dump_member(stream, uint, state, min_mip_filter); + util_dump_member(stream, uint, state, mag_img_filter); + util_dump_member(stream, uint, state, compare_mode); + util_dump_member(stream, enum_func, state, compare_func); + util_dump_member(stream, bool, state, normalized_coords); + util_dump_member(stream, uint, state, max_anisotropy); + util_dump_member(stream, float, state, lod_bias); + util_dump_member(stream, float, state, min_lod); + util_dump_member(stream, float, state, max_lod); + util_dump_member_array(stream, float, state, border_color); + + util_dump_struct_end(stream); +} + + +void +util_dump_surface(struct os_stream *stream, const struct pipe_surface *state) +{ + if(!state) { + util_dump_null(stream); + return; + } + + util_dump_struct_begin(stream, "pipe_surface"); + + util_dump_member(stream, format, state, format); + util_dump_member(stream, uint, state, width); + util_dump_member(stream, uint, state, height); + + util_dump_member(stream, uint, state, usage); + + util_dump_member(stream, ptr, state, texture); + util_dump_member(stream, uint, state, u.tex.level); + util_dump_member(stream, uint, state, u.tex.first_layer); + util_dump_member(stream, uint, state, u.tex.last_layer); + + util_dump_struct_end(stream); +} + + +void +util_dump_transfer(struct os_stream *stream, const struct pipe_transfer *state) +{ + if(!state) { + util_dump_null(stream); + return; + } + + util_dump_struct_begin(stream, "pipe_transfer"); + + util_dump_member(stream, ptr, state, resource); + /*util_dump_member(stream, uint, state, box);*/ + + util_dump_member(stream, uint, state, stride); + util_dump_member(stream, uint, state, layer_stride); + + /*util_dump_member(stream, ptr, state, data);*/ + + util_dump_struct_end(stream); +} + + +void +util_dump_vertex_buffer(struct os_stream *stream, const struct pipe_vertex_buffer *state) +{ + if(!state) { + util_dump_null(stream); + return; + } + + util_dump_struct_begin(stream, "pipe_vertex_buffer"); + + util_dump_member(stream, uint, state, stride); + util_dump_member(stream, uint, state, buffer_offset); + util_dump_member(stream, ptr, state, buffer); + + util_dump_struct_end(stream); +} + + +void +util_dump_vertex_element(struct os_stream *stream, const struct pipe_vertex_element *state) +{ + if(!state) { + util_dump_null(stream); + return; + } + + util_dump_struct_begin(stream, "pipe_vertex_element"); + + util_dump_member(stream, uint, state, src_offset); + + util_dump_member(stream, uint, state, vertex_buffer_index); + + util_dump_member(stream, format, state, src_format); + + util_dump_struct_end(stream); +} diff --git a/mesalib/src/gallium/auxiliary/util/u_dynarray.h b/mesalib/src/gallium/auxiliary/util/u_dynarray.h new file mode 100644 index 000000000..4dd6c3eaa --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_dynarray.h @@ -0,0 +1,114 @@ +/************************************************************************** + * + * Copyright 2010 Luca Barbieri + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and 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 COPYRIGHT OWNER(S) 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 U_DYNARRAY_H +#define U_DYNARRAY_H + +#include "pipe/p_compiler.h" +#include "util/u_memory.h" + +/* A zero-initialized version of this is guaranteed to represent an + * empty array. + * + * Also, size <= capacity and data != 0 if and only if capacity != 0 + * capacity will always be the allocation size of data + */ +struct util_dynarray +{ + void *data; + unsigned size; + unsigned capacity; +}; + +static INLINE void +util_dynarray_init(struct util_dynarray *buf) +{ + memset(buf, 0, sizeof(*buf)); +} + +static INLINE void +util_dynarray_fini(struct util_dynarray *buf) +{ + if(buf->data) + { + FREE(buf->data); + util_dynarray_init(buf); + } +} + +/* use util_dynarray_trim to reduce the allocated storage */ +static INLINE void * +util_dynarray_resize(struct util_dynarray *buf, unsigned newsize) +{ + char *p; + if(newsize > buf->capacity) + { + unsigned newcap = buf->capacity << 1; + if(newsize > newcap) + newcap = newsize; + buf->data = REALLOC(buf->data, buf->capacity, newcap); + buf->capacity = newcap; + } + + p = (char *)buf->data + buf->size; + buf->size = newsize; + return p; +} + +static INLINE void * +util_dynarray_grow(struct util_dynarray *buf, int diff) +{ + return util_dynarray_resize(buf, buf->size + diff); +} + +static INLINE void +util_dynarray_trim(struct util_dynarray *buf) +{ + if (buf->size != buf->capacity) { + if (buf->size) { + buf->data = REALLOC(buf->data, buf->capacity, buf->size); + buf->capacity = buf->size; + } + else { + FREE(buf->data); + buf->data = 0; + buf->capacity = 0; + } + } +} + +#define util_dynarray_append(buf, type, v) do {type __v = (v); memcpy(util_dynarray_grow((buf), sizeof(type)), &__v, sizeof(type));} while(0) +#define util_dynarray_top_ptr(buf, type) (type*)((char*)(buf)->data + (buf)->size - sizeof(type)) +#define util_dynarray_top(buf, type) *util_dynarray_top_ptr(buf, type) +#define util_dynarray_pop_ptr(buf, type) (type*)((char*)(buf)->data + ((buf)->size -= sizeof(type))) +#define util_dynarray_pop(buf, type) *util_dynarray_pop_ptr(buf, type) +#define util_dynarray_contains(buf, type) ((buf)->size >= sizeof(type)) +#define util_dynarray_element(buf, type, idx) ((type*)(buf)->data + (idx)) +#define util_dynarray_begin(buf) ((buf)->data) +#define util_dynarray_end(buf) ((void*)util_dynarray_element((buf), char, (buf)->size)) + +#endif /* U_DYNARRAY_H */ + diff --git a/mesalib/src/gallium/auxiliary/util/u_fifo.h b/mesalib/src/gallium/auxiliary/util/u_fifo.h new file mode 100644 index 000000000..7c13f119e --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_fifo.h @@ -0,0 +1,94 @@ +/************************************************************************** + * + * Copyright © 2009 Jakob Bornecrantz + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and 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 U_FIFO_H +#define U_FIFO_H + +#include "util/u_memory.h" + +struct util_fifo +{ + size_t head; + size_t tail; + size_t num; + size_t size; +}; + +static INLINE struct util_fifo * +u_fifo_create(size_t size) +{ + struct util_fifo *fifo; + fifo = MALLOC(sizeof(*fifo) + size * sizeof(void*)); + + fifo->head = 0; + fifo->tail = 0; + fifo->num = 0; + fifo->size = size; + + return fifo; +} + +static INLINE boolean +u_fifo_add(struct util_fifo *fifo, void *ptr) +{ + void **array = (void**)&fifo[1]; + if (fifo->num >= fifo->size) + return FALSE; + + if (++fifo->head >= fifo->size) + fifo->head = 0; + + array[fifo->head] = ptr; + + ++fifo->num; + + return TRUE; +} + +static INLINE boolean +u_fifo_pop(struct util_fifo *fifo, void **ptr) +{ + void **array = (void**)&fifo[1]; + + if (!fifo->num) + return FALSE; + + if (++fifo->tail >= fifo->size) + fifo->tail = 0; + + *ptr = array[fifo->tail]; + + ++fifo->num; + + return TRUE; +} + +static INLINE void +u_fifo_destroy(struct util_fifo *fifo) +{ + FREE(fifo); +} + +#endif diff --git a/mesalib/src/gallium/auxiliary/util/u_format.c b/mesalib/src/gallium/auxiliary/util/u_format.c new file mode 100644 index 000000000..91485b05c --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_format.c @@ -0,0 +1,392 @@ +/************************************************************************** + * + * 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. + * + **************************************************************************/ + +/** + * @file + * Pixel format accessor functions. + * + * @author Jose Fonseca + */ + +#include "u_math.h" +#include "u_memory.h" +#include "u_rect.h" +#include "u_format.h" +#include "u_format_s3tc.h" + +#include "pipe/p_defines.h" + + +boolean +util_format_is_float(enum pipe_format format) +{ + const struct util_format_description *desc = util_format_description(format); + unsigned i; + + assert(desc); + if (!desc) { + return FALSE; + } + + /* Find the first non-void channel. */ + for (i = 0; i < 4; i++) { + if (desc->channel[i].type != UTIL_FORMAT_TYPE_VOID) { + break; + } + } + + if (i == 4) { + return FALSE; + } + + return desc->channel[i].type == UTIL_FORMAT_TYPE_FLOAT ? TRUE : FALSE; +} + + +boolean +util_format_is_supported(enum pipe_format format, unsigned bind) +{ + if (util_format_is_s3tc(format) && !util_format_s3tc_enabled) { + return FALSE; + } + +#ifndef TEXTURE_FLOAT_ENABLED + if ((bind & PIPE_BIND_RENDER_TARGET) && + format != PIPE_FORMAT_R9G9B9E5_FLOAT && + format != PIPE_FORMAT_R11G11B10_FLOAT && + util_format_is_float(format)) { + return FALSE; + } +#endif + + return TRUE; +} + + +void +util_format_read_4f(enum pipe_format format, + float *dst, unsigned dst_stride, + const void *src, unsigned src_stride, + unsigned x, unsigned y, unsigned w, unsigned h) +{ + const struct util_format_description *format_desc; + const uint8_t *src_row; + float *dst_row; + + format_desc = util_format_description(format); + + assert(x % format_desc->block.width == 0); + assert(y % format_desc->block.height == 0); + + src_row = (const uint8_t *)src + y*src_stride + x*(format_desc->block.bits/8); + dst_row = dst; + + format_desc->unpack_rgba_float(dst_row, dst_stride, src_row, src_stride, w, h); +} + + +void +util_format_write_4f(enum pipe_format format, + const float *src, unsigned src_stride, + void *dst, unsigned dst_stride, + unsigned x, unsigned y, unsigned w, unsigned h) +{ + const struct util_format_description *format_desc; + uint8_t *dst_row; + const float *src_row; + + format_desc = util_format_description(format); + + assert(x % format_desc->block.width == 0); + assert(y % format_desc->block.height == 0); + + dst_row = (uint8_t *)dst + y*dst_stride + x*(format_desc->block.bits/8); + src_row = src; + + format_desc->pack_rgba_float(dst_row, dst_stride, src_row, src_stride, w, h); +} + + +void +util_format_read_4ub(enum pipe_format format, uint8_t *dst, unsigned dst_stride, const void *src, unsigned src_stride, unsigned x, unsigned y, unsigned w, unsigned h) +{ + const struct util_format_description *format_desc; + const uint8_t *src_row; + uint8_t *dst_row; + + format_desc = util_format_description(format); + + assert(x % format_desc->block.width == 0); + assert(y % format_desc->block.height == 0); + + src_row = (const uint8_t *)src + y*src_stride + x*(format_desc->block.bits/8); + dst_row = dst; + + format_desc->unpack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, w, h); +} + + +void +util_format_write_4ub(enum pipe_format format, const uint8_t *src, unsigned src_stride, void *dst, unsigned dst_stride, unsigned x, unsigned y, unsigned w, unsigned h) +{ + const struct util_format_description *format_desc; + uint8_t *dst_row; + const uint8_t *src_row; + + format_desc = util_format_description(format); + + assert(x % format_desc->block.width == 0); + assert(y % format_desc->block.height == 0); + + dst_row = (uint8_t *)dst + y*dst_stride + x*(format_desc->block.bits/8); + src_row = src; + + format_desc->pack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, w, h); +} + + +boolean +util_is_format_compatible(const struct util_format_description *src_desc, + const struct util_format_description *dst_desc) +{ + unsigned chan; + + if (src_desc->format == dst_desc->format) { + return TRUE; + } + + if (src_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN || + dst_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN) { + return FALSE; + } + + if (src_desc->block.bits != dst_desc->block.bits || + src_desc->nr_channels != dst_desc->nr_channels || + src_desc->colorspace != dst_desc->colorspace) { + return FALSE; + } + + for (chan = 0; chan < 4; ++chan) { + if (src_desc->channel[chan].size != + dst_desc->channel[chan].size) { + return FALSE; + } + } + + for (chan = 0; chan < 4; ++chan) { + enum util_format_swizzle swizzle = dst_desc->swizzle[chan]; + + if (swizzle < 4) { + if (src_desc->swizzle[chan] != swizzle) { + return FALSE; + } + if ((src_desc->channel[swizzle].type != + dst_desc->channel[swizzle].type) || + (src_desc->channel[swizzle].normalized != + dst_desc->channel[swizzle].normalized)) { + return FALSE; + } + } + } + + return TRUE; +} + + +boolean +util_format_fits_8unorm(const struct util_format_description *format_desc) +{ + unsigned chan; + + /* + * After linearized sRGB values require more than 8bits. + */ + + if (format_desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) { + return FALSE; + } + + switch (format_desc->layout) { + + case UTIL_FORMAT_LAYOUT_S3TC: + case UTIL_FORMAT_LAYOUT_RGTC: + /* + * These are straight forward. + */ + + return TRUE; + + case UTIL_FORMAT_LAYOUT_PLAIN: + /* + * For these we can find a generic rule. + */ + + for (chan = 0; chan < format_desc->nr_channels; ++chan) { + switch (format_desc->channel[chan].type) { + case UTIL_FORMAT_TYPE_VOID: + break; + case UTIL_FORMAT_TYPE_UNSIGNED: + if (!format_desc->channel[chan].normalized || + format_desc->channel[chan].size > 8) { + return FALSE; + } + break; + default: + return FALSE; + } + } + return TRUE; + + default: + /* + * Handle all others on a case by case basis. + */ + + switch (format_desc->format) { + case PIPE_FORMAT_R1_UNORM: + case PIPE_FORMAT_UYVY: + case PIPE_FORMAT_YUYV: + case PIPE_FORMAT_R8G8_B8G8_UNORM: + case PIPE_FORMAT_G8R8_G8B8_UNORM: + return TRUE; + + default: + return FALSE; + } + } +} + + +void +util_format_translate(enum pipe_format dst_format, + void *dst, unsigned dst_stride, + unsigned dst_x, unsigned dst_y, + enum pipe_format src_format, + const void *src, unsigned src_stride, + unsigned src_x, unsigned src_y, + unsigned width, unsigned height) +{ + const struct util_format_description *dst_format_desc; + const struct util_format_description *src_format_desc; + uint8_t *dst_row; + const uint8_t *src_row; + unsigned x_step, y_step; + unsigned dst_step; + unsigned src_step; + + dst_format_desc = util_format_description(dst_format); + src_format_desc = util_format_description(src_format); + + if (util_is_format_compatible(src_format_desc, dst_format_desc)) { + /* + * Trivial case. + */ + + util_copy_rect(dst, dst_format, dst_stride, dst_x, dst_y, + width, height, src, (int)src_stride, + src_x, src_y); + return; + } + + assert(dst_x % dst_format_desc->block.width == 0); + assert(dst_y % dst_format_desc->block.height == 0); + assert(src_x % src_format_desc->block.width == 0); + assert(src_y % src_format_desc->block.height == 0); + + dst_row = (uint8_t *)dst + dst_y*dst_stride + dst_x*(dst_format_desc->block.bits/8); + src_row = (const uint8_t *)src + src_y*src_stride + src_x*(src_format_desc->block.bits/8); + + /* + * This works because all pixel formats have pixel blocks with power of two + * sizes. + */ + + y_step = MAX2(dst_format_desc->block.height, src_format_desc->block.height); + x_step = MAX2(dst_format_desc->block.width, src_format_desc->block.width); + assert(y_step % dst_format_desc->block.height == 0); + assert(y_step % src_format_desc->block.height == 0); + + dst_step = y_step / dst_format_desc->block.height * dst_stride; + src_step = y_step / src_format_desc->block.height * src_stride; + + /* + * TODO: double formats will loose precision + * TODO: Add a special case for formats that are mere swizzles of each other + */ + + if (util_format_fits_8unorm(src_format_desc) || + util_format_fits_8unorm(dst_format_desc)) { + unsigned tmp_stride; + uint8_t *tmp_row; + + tmp_stride = MAX2(width, x_step) * 4 * sizeof *tmp_row; + tmp_row = MALLOC(y_step * tmp_stride); + if (!tmp_row) + return; + + while (height >= y_step) { + src_format_desc->unpack_rgba_8unorm(tmp_row, tmp_stride, src_row, src_stride, width, y_step); + dst_format_desc->pack_rgba_8unorm(dst_row, dst_stride, tmp_row, tmp_stride, width, y_step); + + dst_row += dst_step; + src_row += src_step; + height -= y_step; + } + + if (height) { + src_format_desc->unpack_rgba_8unorm(tmp_row, tmp_stride, src_row, src_stride, width, height); + dst_format_desc->pack_rgba_8unorm(dst_row, dst_stride, tmp_row, tmp_stride, width, height); + } + + FREE(tmp_row); + } + else { + unsigned tmp_stride; + float *tmp_row; + + tmp_stride = MAX2(width, x_step) * 4 * sizeof *tmp_row; + tmp_row = MALLOC(y_step * tmp_stride); + if (!tmp_row) + return; + + while (height >= y_step) { + src_format_desc->unpack_rgba_float(tmp_row, tmp_stride, src_row, src_stride, width, y_step); + dst_format_desc->pack_rgba_float(dst_row, dst_stride, tmp_row, tmp_stride, width, y_step); + + dst_row += dst_step; + src_row += src_step; + height -= y_step; + } + + if (height) { + src_format_desc->unpack_rgba_float(tmp_row, tmp_stride, src_row, src_stride, width, height); + dst_format_desc->pack_rgba_float(dst_row, dst_stride, tmp_row, tmp_stride, width, height); + } + + FREE(tmp_row); + } +} diff --git a/mesalib/src/gallium/auxiliary/util/u_format.csv b/mesalib/src/gallium/auxiliary/util/u_format.csv new file mode 100644 index 000000000..00c24cc81 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_format.csv @@ -0,0 +1,261 @@ +########################################################################### +# +# Copyright 2009-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 THE 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. +# +########################################################################### + +# This CSV file has the input data for u_format.h's struct +# util_format_description. +# +# Each format entry contains: +# - name, per enum pipe_format +# - layout, per enum util_format_layout, in shortened lower caps +# - pixel block's width +# - pixel block's height +# - channel encoding (only meaningful for plain layout), containing for each +# channel the following information: +# - type, one of +# - 'x': void +# - 'u': unsigned +# - 's': signed +# - 'h': fixed +# - 'f': FLOAT +# - optionally followed by 'n' if it is normalized +# - number of bits +# - channel swizzle +# - color space: rgb, yub, sz +# +# See also: +# - http://msdn.microsoft.com/en-us/library/bb172558.aspx (D3D9) +# - http://msdn.microsoft.com/en-us/library/bb205073.aspx#mapping_texture_formats (D3D9 -> D3D10) +# - http://msdn.microsoft.com/en-us/library/bb173059.aspx (D3D10) +# +# Note that GL doesn't really specify the layout of internal formats. See +# OpenGL 2.1 specification, Table 3.16, on the "Correspondence of sized +# internal formats to base in- ternal formats, and desired component +# resolutions for each sized internal format." + +# None +# Described as regular uint_8 bytes, i.e. PIPE_FORMAT_R8_USCALED +PIPE_FORMAT_NONE , plain, 1, 1, u8 , , , , x001, rgb + +# Typical rendertarget formats +PIPE_FORMAT_B8G8R8A8_UNORM , plain, 1, 1, un8 , un8 , un8 , un8 , zyxw, rgb +PIPE_FORMAT_B8G8R8X8_UNORM , plain, 1, 1, un8 , un8 , un8 , x8 , zyx1, rgb +PIPE_FORMAT_A8R8G8B8_UNORM , plain, 1, 1, un8 , un8 , un8 , un8 , yzwx, rgb +PIPE_FORMAT_X8R8G8B8_UNORM , plain, 1, 1, x8 , un8 , un8 , un8 , yzw1, rgb +PIPE_FORMAT_A8B8G8R8_UNORM , plain, 1, 1, un8 , un8 , un8 , un8 , wzyx, rgb +PIPE_FORMAT_X8B8G8R8_UNORM , plain, 1, 1, x8 , un8 , un8 , un8 , wzy1, rgb +# PIPE_FORMAT_R8G8B8A8_UNORM is below +PIPE_FORMAT_R8G8B8X8_UNORM , plain, 1, 1, un8 , un8 , un8 , x8 , xyz1, rgb +PIPE_FORMAT_B5G5R5X1_UNORM , plain, 1, 1, un5 , un5 , un5 , x1 , zyx1, rgb +PIPE_FORMAT_B5G5R5A1_UNORM , plain, 1, 1, un5 , un5 , un5 , un1 , zyxw, rgb +PIPE_FORMAT_B4G4R4A4_UNORM , plain, 1, 1, un4 , un4 , un4 , un4 , zyxw, rgb +PIPE_FORMAT_B4G4R4X4_UNORM , plain, 1, 1, un4 , un4 , un4 , x4 , zyx1, rgb +PIPE_FORMAT_B5G6R5_UNORM , plain, 1, 1, un5 , un6 , un5 , , zyx1, rgb +PIPE_FORMAT_R10G10B10A2_UNORM , plain, 1, 1, un10, un10, un10, un2 , xyzw, rgb +PIPE_FORMAT_B10G10R10A2_UNORM , plain, 1, 1, un10, un10, un10, un2 , zyxw, rgb +PIPE_FORMAT_B2G3R3_UNORM , plain, 1, 1, un2 , un3 , un3 , , zyx1, rgb + +# Luminance/Intensity/Alpha formats +PIPE_FORMAT_L8_UNORM , plain, 1, 1, un8 , , , , xxx1, rgb +PIPE_FORMAT_A8_UNORM , plain, 1, 1, un8 , , , , 000x, rgb +PIPE_FORMAT_I8_UNORM , plain, 1, 1, un8 , , , , xxxx, rgb +PIPE_FORMAT_L4A4_UNORM , plain, 1, 1, un4 , un4 , , , xxxy, rgb +PIPE_FORMAT_L8A8_UNORM , plain, 1, 1, un8 , un8 , , , xxxy, rgb +PIPE_FORMAT_L16_UNORM , plain, 1, 1, un16, , , , xxx1, rgb +PIPE_FORMAT_A16_UNORM , plain, 1, 1, un16, , , , 000x, rgb +PIPE_FORMAT_I16_UNORM , plain, 1, 1, un16, , , , xxxx, rgb +PIPE_FORMAT_L16A16_UNORM , plain, 1, 1, un16, un16, , , xxxy, rgb +PIPE_FORMAT_A8_SNORM , plain, 1, 1, sn8 , , , , 000x, rgb +PIPE_FORMAT_L8_SNORM , plain, 1, 1, sn8 , , , , xxx1, rgb +PIPE_FORMAT_L8A8_SNORM , plain, 1, 1, sn8 , sn8 , , , xxxy, rgb +PIPE_FORMAT_I8_SNORM , plain, 1, 1, sn8 , , , , xxxx, rgb +PIPE_FORMAT_A16_SNORM , plain, 1, 1, sn16, , , , 000x, rgb +PIPE_FORMAT_L16_SNORM , plain, 1, 1, sn16, , , , xxx1, rgb +PIPE_FORMAT_L16A16_SNORM , plain, 1, 1, sn16, sn16, , , xxxy, rgb +PIPE_FORMAT_I16_SNORM , plain, 1, 1, sn16, , , , xxxx, rgb +PIPE_FORMAT_A16_FLOAT , plain, 1, 1, f16 , , , , 000x, rgb +PIPE_FORMAT_L16_FLOAT , plain, 1, 1, f16 , , , , xxx1, rgb +PIPE_FORMAT_L16A16_FLOAT , plain, 1, 1, f16 , f16 , , , xxxy, rgb +PIPE_FORMAT_I16_FLOAT , plain, 1, 1, f16 , , , , xxxx, rgb +PIPE_FORMAT_A32_FLOAT , plain, 1, 1, f32 , , , , 000x, rgb +PIPE_FORMAT_L32_FLOAT , plain, 1, 1, f32 , , , , xxx1, rgb +PIPE_FORMAT_L32A32_FLOAT , plain, 1, 1, f32 , f32 , , , xxxy, rgb +PIPE_FORMAT_I32_FLOAT , plain, 1, 1, f32 , , , , xxxx, rgb + +# SRGB formats +PIPE_FORMAT_L8_SRGB , plain, 1, 1, un8 , , , , xxx1, srgb +PIPE_FORMAT_L8A8_SRGB , plain, 1, 1, un8 , un8 , , , xxxy, srgb +PIPE_FORMAT_R8G8B8_SRGB , plain, 1, 1, un8 , un8 , un8 , , xyz1, srgb +PIPE_FORMAT_R8G8B8A8_SRGB , plain, 1, 1, un8 , un8 , un8 , un8 , xyzw, srgb +PIPE_FORMAT_A8B8G8R8_SRGB , plain, 1, 1, un8 , un8 , un8 , un8 , wzyx, srgb +PIPE_FORMAT_X8B8G8R8_SRGB , plain, 1, 1, x8 , un8 , un8 , un8 , wzy1, srgb +PIPE_FORMAT_B8G8R8A8_SRGB , plain, 1, 1, un8 , un8 , un8 , un8 , zyxw, srgb +PIPE_FORMAT_B8G8R8X8_SRGB , plain, 1, 1, un8 , un8 , un8 , x8 , zyx1, srgb +PIPE_FORMAT_A8R8G8B8_SRGB , plain, 1, 1, un8 , un8 , un8 , un8 , yzwx, srgb +PIPE_FORMAT_X8R8G8B8_SRGB , plain, 1, 1, x8 , un8 , un8 , un8 , yzw1, srgb + +# Mixed-sign formats (typically used for bump map textures) +PIPE_FORMAT_R8SG8SB8UX8U_NORM , plain, 1, 1, sn8 , sn8 , un8 , x8 , xyz1, rgb +PIPE_FORMAT_R10SG10SB10SA2U_NORM , plain, 1, 1, sn10, sn10, sn10, un2 , xyzw, rgb +PIPE_FORMAT_R5SG5SB6U_NORM , plain, 1, 1, sn5 , sn5 , un6 , , xyz1, rgb + +# Depth-stencil formats +PIPE_FORMAT_S8_USCALED , plain, 1, 1, u8 , , , , _x__, zs +PIPE_FORMAT_Z16_UNORM , plain, 1, 1, un16, , , , x___, zs +PIPE_FORMAT_Z32_UNORM , plain, 1, 1, un32, , , , x___, zs +PIPE_FORMAT_Z32_FLOAT , plain, 1, 1, f32 , , , , x___, zs +PIPE_FORMAT_Z24_UNORM_S8_USCALED , plain, 1, 1, un24, u8 , , , xy__, zs +PIPE_FORMAT_S8_USCALED_Z24_UNORM , plain, 1, 1, u8 , un24, , , yx__, zs +PIPE_FORMAT_X24S8_USCALED , plain, 1, 1, x24, u8 , , , _y__, zs +PIPE_FORMAT_S8X24_USCALED , plain, 1, 1, u8 , x24 , , , _x__, zs +PIPE_FORMAT_Z24X8_UNORM , plain, 1, 1, un24, x8 , , , x___, zs +PIPE_FORMAT_X8Z24_UNORM , plain, 1, 1, x8 , un24, , , y___, zs +PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED , plain, 1, 1, f32, u8 , x24 , , xy__, zs +PIPE_FORMAT_X32_S8X24_USCALED , plain, 1, 1, x32, u8 , x24 , , _y__, zs + +# YUV formats +# http://www.fourcc.org/yuv.php#UYVY +PIPE_FORMAT_UYVY , subsampled, 2, 1, x32 , , , , xyz1, yuv +# http://www.fourcc.org/yuv.php#YUYV (a.k.a http://www.fourcc.org/yuv.php#YUY2) +PIPE_FORMAT_YUYV , subsampled, 2, 1, x32 , , , , xyz1, yuv +# same subsampling but with rgb channels +PIPE_FORMAT_R8G8_B8G8_UNORM , subsampled, 2, 1, x32 , , , , xyz1, rgb +PIPE_FORMAT_G8R8_G8B8_UNORM , subsampled, 2, 1, x32 , , , , xyz1, rgb + +# some special formats not fitting anywhere else +PIPE_FORMAT_R10G10B10A2_USCALED , plain, 1, 1, u10 , u10 , u10 , u2 , xyzw, rgb +PIPE_FORMAT_R11G11B10_FLOAT , other, 1, 1, x32 , , , , xyz1, rgb +PIPE_FORMAT_R9G9B9E5_FLOAT , other, 1, 1, x32 , , , , xyz1, rgb +PIPE_FORMAT_R1_UNORM , other, 8, 1, x8 , , , , x001, rgb +# A.k.a. D3DFMT_CxV8U8 +PIPE_FORMAT_R8G8Bx_SNORM , other, 1, 1, sn8 , sn8 , , , xyz1, rgb + +# Compressed formats +# - http://en.wikipedia.org/wiki/S3_Texture_Compression +# - http://www.opengl.org/registry/specs/EXT/texture_compression_s3tc.txt +# - http://www.opengl.org/registry/specs/ARB/texture_compression_rgtc.txt +# - http://www.opengl.org/registry/specs/EXT/texture_compression_latc.txt +# - http://msdn.microsoft.com/en-us/library/bb694531.aspx +PIPE_FORMAT_DXT1_RGB , s3tc, 4, 4, x64 , , , , xyz1, rgb +PIPE_FORMAT_DXT1_RGBA , s3tc, 4, 4, x64 , , , , xyzw, rgb +PIPE_FORMAT_DXT3_RGBA , s3tc, 4, 4, x128, , , , xyzw, rgb +PIPE_FORMAT_DXT5_RGBA , s3tc, 4, 4, x128, , , , xyzw, rgb +PIPE_FORMAT_DXT1_SRGB , s3tc, 4, 4, x64 , , , , xyz1, srgb +PIPE_FORMAT_DXT1_SRGBA , s3tc, 4, 4, x64 , , , , xyzw, srgb +PIPE_FORMAT_DXT3_SRGBA , s3tc, 4, 4, x128, , , , xyzw, srgb +PIPE_FORMAT_DXT5_SRGBA , s3tc, 4, 4, x128, , , , xyzw, srgb + +PIPE_FORMAT_RGTC1_UNORM , rgtc, 4, 4, x64, , , , x001, rgb +PIPE_FORMAT_RGTC1_SNORM , rgtc, 4, 4, x64, , , , x001, rgb +PIPE_FORMAT_RGTC2_UNORM , rgtc, 4, 4, x128, , , , xy01, rgb +PIPE_FORMAT_RGTC2_SNORM , rgtc, 4, 4, x128, , , , xy01, rgb + +PIPE_FORMAT_LATC1_UNORM , rgtc, 4, 4, x64, , , , xxx1, rgb +PIPE_FORMAT_LATC1_SNORM , rgtc, 4, 4, x64, , , , xxx1, rgb +PIPE_FORMAT_LATC2_UNORM , rgtc, 4, 4, x128, , , , xxxy, rgb +PIPE_FORMAT_LATC2_SNORM , rgtc, 4, 4, x128, , , , xxxy, rgb + +# Straightforward D3D10-like formats (also used for +# vertex buffer element description) +# +# See also: +# - src/gallium/auxiliary/translate/translate_generic.c +# - src/mesa/state_tracker/st_draw.c +PIPE_FORMAT_R64_FLOAT , plain, 1, 1, f64 , , , , x001, rgb +PIPE_FORMAT_R64G64_FLOAT , plain, 1, 1, f64 , f64 , , , xy01, rgb +PIPE_FORMAT_R64G64B64_FLOAT , plain, 1, 1, f64 , f64 , f64 , , xyz1, rgb +PIPE_FORMAT_R64G64B64A64_FLOAT , plain, 1, 1, f64 , f64 , f64 , f64 , xyzw, rgb +PIPE_FORMAT_R32_FLOAT , plain, 1, 1, f32 , , , , x001, rgb +PIPE_FORMAT_R32G32_FLOAT , plain, 1, 1, f32 , f32 , , , xy01, rgb +PIPE_FORMAT_R32G32B32_FLOAT , plain, 1, 1, f32 , f32 , f32 , , xyz1, rgb +PIPE_FORMAT_R32G32B32A32_FLOAT , plain, 1, 1, f32 , f32 , f32 , f32 , xyzw, rgb +PIPE_FORMAT_R32_UNORM , plain, 1, 1, un32, , , , x001, rgb +PIPE_FORMAT_R32G32_UNORM , plain, 1, 1, un32, un32, , , xy01, rgb +PIPE_FORMAT_R32G32B32_UNORM , plain, 1, 1, un32, un32, un32, , xyz1, rgb +PIPE_FORMAT_R32G32B32A32_UNORM , plain, 1, 1, un32, un32, un32, un32, xyzw, rgb +PIPE_FORMAT_R32_USCALED , plain, 1, 1, u32 , , , , x001, rgb +PIPE_FORMAT_R32G32_USCALED , plain, 1, 1, u32 , u32 , , , xy01, rgb +PIPE_FORMAT_R32G32B32_USCALED , plain, 1, 1, u32 , u32 , u32 , , xyz1, rgb +PIPE_FORMAT_R32G32B32A32_USCALED , plain, 1, 1, u32 , u32 , u32 , u32 , xyzw, rgb +PIPE_FORMAT_R32_SNORM , plain, 1, 1, sn32, , , , x001, rgb +PIPE_FORMAT_R32G32_SNORM , plain, 1, 1, sn32, sn32, , , xy01, rgb +PIPE_FORMAT_R32G32B32_SNORM , plain, 1, 1, sn32, sn32, sn32, , xyz1, rgb +PIPE_FORMAT_R32G32B32A32_SNORM , plain, 1, 1, sn32, sn32, sn32, sn32, xyzw, rgb +PIPE_FORMAT_R32_SSCALED , plain, 1, 1, s32 , , , , x001, rgb +PIPE_FORMAT_R32G32_SSCALED , plain, 1, 1, s32 , s32 , , , xy01, rgb +PIPE_FORMAT_R32G32B32_SSCALED , plain, 1, 1, s32 , s32 , s32 , , xyz1, rgb +PIPE_FORMAT_R32G32B32A32_SSCALED , plain, 1, 1, s32 , s32 , s32 , s32 , xyzw, rgb +PIPE_FORMAT_R16_FLOAT , plain, 1, 1, f16 , , , , x001, rgb +PIPE_FORMAT_R16G16_FLOAT , plain, 1, 1, f16 , f16 , , , xy01, rgb +PIPE_FORMAT_R16G16B16_FLOAT , plain, 1, 1, f16 , f16 , f16 , , xyz1, rgb +PIPE_FORMAT_R16G16B16A16_FLOAT , plain, 1, 1, f16 , f16 , f16 , f16 , xyzw, rgb +PIPE_FORMAT_R16_UNORM , plain, 1, 1, un16, , , , x001, rgb +PIPE_FORMAT_R16G16_UNORM , plain, 1, 1, un16, un16, , , xy01, rgb +PIPE_FORMAT_R16G16B16_UNORM , plain, 1, 1, un16, un16, un16, , xyz1, rgb +PIPE_FORMAT_R16G16B16A16_UNORM , plain, 1, 1, un16, un16, un16, un16, xyzw, rgb +PIPE_FORMAT_R16_USCALED , plain, 1, 1, u16 , , , , x001, rgb +PIPE_FORMAT_R16G16_USCALED , plain, 1, 1, u16 , u16 , , , xy01, rgb +PIPE_FORMAT_R16G16B16_USCALED , plain, 1, 1, u16 , u16 , u16 , , xyz1, rgb +PIPE_FORMAT_R16G16B16A16_USCALED , plain, 1, 1, u16 , u16 , u16 , u16 , xyzw, rgb +PIPE_FORMAT_R16_SNORM , plain, 1, 1, sn16, , , , x001, rgb +PIPE_FORMAT_R16G16_SNORM , plain, 1, 1, sn16, sn16, , , xy01, rgb +PIPE_FORMAT_R16G16B16_SNORM , plain, 1, 1, sn16, sn16, sn16, , xyz1, rgb +PIPE_FORMAT_R16G16B16A16_SNORM , plain, 1, 1, sn16, sn16, sn16, sn16, xyzw, rgb +PIPE_FORMAT_R16_SSCALED , plain, 1, 1, s16 , , , , x001, rgb +PIPE_FORMAT_R16G16_SSCALED , plain, 1, 1, s16 , s16 , , , xy01, rgb +PIPE_FORMAT_R16G16B16_SSCALED , plain, 1, 1, s16 , s16 , s16 , , xyz1, rgb +PIPE_FORMAT_R16G16B16A16_SSCALED , plain, 1, 1, s16 , s16 , s16 , s16 , xyzw, rgb +PIPE_FORMAT_R8_UNORM , plain, 1, 1, un8 , , , , x001, rgb +PIPE_FORMAT_R8G8_UNORM , plain, 1, 1, un8 , un8 , , , xy01, rgb +PIPE_FORMAT_R8G8B8_UNORM , plain, 1, 1, un8 , un8 , un8 , , xyz1, rgb +PIPE_FORMAT_R8G8B8A8_UNORM , plain, 1, 1, un8 , un8 , un8 , un8 , xyzw, rgb +PIPE_FORMAT_R8_USCALED , plain, 1, 1, u8 , , , , x001, rgb +PIPE_FORMAT_R8G8_USCALED , plain, 1, 1, u8 , u8 , , , xy01, rgb +PIPE_FORMAT_R8G8B8_USCALED , plain, 1, 1, u8 , u8 , u8 , , xyz1, rgb +PIPE_FORMAT_R8G8B8A8_USCALED , plain, 1, 1, u8 , u8 , u8 , u8 , xyzw, rgb +PIPE_FORMAT_R8_SNORM , plain, 1, 1, sn8 , , , , x001, rgb +PIPE_FORMAT_R8G8_SNORM , plain, 1, 1, sn8 , sn8 , , , xy01, rgb +PIPE_FORMAT_R8G8B8_SNORM , plain, 1, 1, sn8 , sn8 , sn8 , , xyz1, rgb +PIPE_FORMAT_R8G8B8A8_SNORM , plain, 1, 1, sn8 , sn8 , sn8 , sn8 , xyzw, rgb +PIPE_FORMAT_R8_SSCALED , plain, 1, 1, s8 , , , , x001, rgb +PIPE_FORMAT_R8G8_SSCALED , plain, 1, 1, s8 , s8 , , , xy01, rgb +PIPE_FORMAT_R8G8B8_SSCALED , plain, 1, 1, s8 , s8 , s8 , , xyz1, rgb +PIPE_FORMAT_R8G8B8A8_SSCALED , plain, 1, 1, s8 , s8 , s8 , s8 , xyzw, rgb + +# GL-specific vertex buffer element formats +# A.k.a. GL_FIXED +PIPE_FORMAT_R32_FIXED , plain, 1, 1, h32 , , , , x001, rgb +PIPE_FORMAT_R32G32_FIXED , plain, 1, 1, h32 , h32 , , , xy01, rgb +PIPE_FORMAT_R32G32B32_FIXED , plain, 1, 1, h32 , h32 , h32 , , xyz1, rgb +PIPE_FORMAT_R32G32B32A32_FIXED , plain, 1, 1, h32 , h32 , h32 , h32 , xyzw, rgb + +# D3D9-specific vertex buffer element formats +# See also: +# - http://msdn.microsoft.com/en-us/library/bb172533.aspx +# A.k.a. D3DDECLTYPE_UDEC3 +PIPE_FORMAT_R10G10B10X2_USCALED , plain, 1, 1, u10 , u10 , u10 , x2 , xyz1, rgb +# A.k.a. D3DDECLTYPE_DEC3N +PIPE_FORMAT_R10G10B10X2_SNORM , plain, 1, 1, sn10, sn10, sn10 , x2 , xyz1, rgb diff --git a/mesalib/src/gallium/auxiliary/util/u_format.h b/mesalib/src/gallium/auxiliary/util/u_format.h new file mode 100644 index 000000000..6e9b6902e --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_format.h @@ -0,0 +1,822 @@ +/************************************************************************** + * + * Copyright 2009-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 U_FORMAT_H +#define U_FORMAT_H + + +#include "pipe/p_format.h" +#include "util/u_debug.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Describe how to pack/unpack pixels into/from the prescribed format. + * + * XXX: This could be renamed to something like util_format_pack, or broke down + * in flags inside util_format_block that said exactly what we want. + */ +enum util_format_layout { + /** + * Formats with util_format_block::width == util_format_block::height == 1 + * that can be described as an ordinary data structure. + */ + UTIL_FORMAT_LAYOUT_PLAIN = 0, + + /** + * Formats with sub-sampled channels. + * + * This is for formats like YV12 where there is less than one sample per + * pixel. + */ + UTIL_FORMAT_LAYOUT_SUBSAMPLED = 3, + + /** + * S3 Texture Compression formats. + */ + UTIL_FORMAT_LAYOUT_S3TC = 4, + + /** + * Red-Green Texture Compression formats. + */ + UTIL_FORMAT_LAYOUT_RGTC = 5, + + /** + * Everything else that doesn't fit in any of the above layouts. + */ + UTIL_FORMAT_LAYOUT_OTHER = 6 +}; + + +struct util_format_block +{ + /** Block width in pixels */ + unsigned width; + + /** Block height in pixels */ + unsigned height; + + /** Block size in bits */ + unsigned bits; +}; + + +enum util_format_type { + UTIL_FORMAT_TYPE_VOID = 0, + UTIL_FORMAT_TYPE_UNSIGNED = 1, + UTIL_FORMAT_TYPE_SIGNED = 2, + UTIL_FORMAT_TYPE_FIXED = 3, + UTIL_FORMAT_TYPE_FLOAT = 4 +}; + + +enum util_format_swizzle { + UTIL_FORMAT_SWIZZLE_X = 0, + UTIL_FORMAT_SWIZZLE_Y = 1, + UTIL_FORMAT_SWIZZLE_Z = 2, + UTIL_FORMAT_SWIZZLE_W = 3, + UTIL_FORMAT_SWIZZLE_0 = 4, + UTIL_FORMAT_SWIZZLE_1 = 5, + UTIL_FORMAT_SWIZZLE_NONE = 6 +}; + + +enum util_format_colorspace { + UTIL_FORMAT_COLORSPACE_RGB = 0, + UTIL_FORMAT_COLORSPACE_SRGB = 1, + UTIL_FORMAT_COLORSPACE_YUV = 2, + UTIL_FORMAT_COLORSPACE_ZS = 3 +}; + + +struct util_format_channel_description +{ + unsigned type:6; + unsigned normalized:1; + unsigned size:9; +}; + + +struct util_format_description +{ + enum pipe_format format; + + const char *name; + + /** + * Short name, striped of the prefix, lower case. + */ + const char *short_name; + + /** + * Pixel block dimensions. + */ + struct util_format_block block; + + enum util_format_layout layout; + + /** + * The number of channels. + */ + unsigned nr_channels:3; + + /** + * Whether all channels have the same number of (whole) bytes. + */ + unsigned is_array:1; + + /** + * Whether the pixel format can be described as a bitfield structure. + * + * In particular: + * - pixel depth must be 8, 16, or 32 bits; + * - all channels must be unsigned, signed, or void + */ + unsigned is_bitmask:1; + + /** + * Whether channels have mixed types (ignoring UTIL_FORMAT_TYPE_VOID). + */ + unsigned is_mixed:1; + + /** + * Input channel description. + * + * Only valid for UTIL_FORMAT_LAYOUT_PLAIN formats. + */ + struct util_format_channel_description channel[4]; + + /** + * Output channel swizzle. + * + * The order is either: + * - RGBA + * - YUV(A) + * - ZS + * depending on the colorspace. + */ + unsigned char swizzle[4]; + + /** + * Colorspace transformation. + */ + enum util_format_colorspace colorspace; + + /** + * Unpack pixel blocks to R8G8B8A8_UNORM. + * Note: strides are in bytes. + * + * Only defined for non-depth-stencil formats. + */ + void + (*unpack_rgba_8unorm)(uint8_t *dst, unsigned dst_stride, + const uint8_t *src, unsigned src_stride, + unsigned width, unsigned height); + + /** + * Pack pixel blocks from R8G8B8A8_UNORM. + * Note: strides are in bytes. + * + * Only defined for non-depth-stencil formats. + */ + void + (*pack_rgba_8unorm)(uint8_t *dst, unsigned dst_stride, + const uint8_t *src, unsigned src_stride, + unsigned width, unsigned height); + + /** + * Fetch a single pixel (i, j) from a block. + * + * XXX: Only defined for a very few select formats. + */ + void + (*fetch_rgba_8unorm)(uint8_t *dst, + const uint8_t *src, + unsigned i, unsigned j); + + /** + * Unpack pixel blocks to R32G32B32A32_FLOAT. + * Note: strides are in bytes. + * + * Only defined for non-depth-stencil formats. + */ + void + (*unpack_rgba_float)(float *dst, unsigned dst_stride, + const uint8_t *src, unsigned src_stride, + unsigned width, unsigned height); + + /** + * Pack pixel blocks from R32G32B32A32_FLOAT. + * Note: strides are in bytes. + * + * Only defined for non-depth-stencil formats. + */ + void + (*pack_rgba_float)(uint8_t *dst, unsigned dst_stride, + const float *src, unsigned src_stride, + unsigned width, unsigned height); + + /** + * Fetch a single pixel (i, j) from a block. + * + * Only defined for non-depth-stencil formats. + */ + void + (*fetch_rgba_float)(float *dst, + const uint8_t *src, + unsigned i, unsigned j); + + /** + * Unpack pixels to Z32_UNORM. + * Note: strides are in bytes. + * + * Only defined for depth formats. + */ + void + (*unpack_z_32unorm)(uint32_t *dst, unsigned dst_stride, + const uint8_t *src, unsigned src_stride, + unsigned width, unsigned height); + + /** + * Pack pixels from Z32_FLOAT. + * Note: strides are in bytes. + * + * Only defined for depth formats. + */ + void + (*pack_z_32unorm)(uint8_t *dst, unsigned dst_stride, + const uint32_t *src, unsigned src_stride, + unsigned width, unsigned height); + + /** + * Unpack pixels to Z32_FLOAT. + * Note: strides are in bytes. + * + * Only defined for depth formats. + */ + void + (*unpack_z_float)(float *dst, unsigned dst_stride, + const uint8_t *src, unsigned src_stride, + unsigned width, unsigned height); + + /** + * Pack pixels from Z32_FLOAT. + * Note: strides are in bytes. + * + * Only defined for depth formats. + */ + void + (*pack_z_float)(uint8_t *dst, unsigned dst_stride, + const float *src, unsigned src_stride, + unsigned width, unsigned height); + + /** + * Unpack pixels to S8_USCALED. + * Note: strides are in bytes. + * + * Only defined for stencil formats. + */ + void + (*unpack_s_8uscaled)(uint8_t *dst, unsigned dst_stride, + const uint8_t *src, unsigned src_stride, + unsigned width, unsigned height); + + /** + * Pack pixels from S8_USCALED. + * Note: strides are in bytes. + * + * Only defined for stencil formats. + */ + void + (*pack_s_8uscaled)(uint8_t *dst, unsigned dst_stride, + const uint8_t *src, unsigned src_stride, + unsigned width, unsigned height); + +}; + + +extern const struct util_format_description +util_format_description_table[]; + + +const struct util_format_description * +util_format_description(enum pipe_format format); + + +/* + * Format query functions. + */ + +static INLINE const char * +util_format_name(enum pipe_format format) +{ + const struct util_format_description *desc = util_format_description(format); + + assert(desc); + if (!desc) { + return "PIPE_FORMAT_???"; + } + + return desc->name; +} + +static INLINE const char * +util_format_short_name(enum pipe_format format) +{ + const struct util_format_description *desc = util_format_description(format); + + assert(desc); + if (!desc) { + return "???"; + } + + return desc->short_name; +} + +/** + * Whether this format is plain, see UTIL_FORMAT_LAYOUT_PLAIN for more info. + */ +static INLINE boolean +util_format_is_plain(enum pipe_format format) +{ + const struct util_format_description *desc = util_format_description(format); + + if (!format) { + return FALSE; + } + + return desc->layout == UTIL_FORMAT_LAYOUT_PLAIN ? TRUE : FALSE; +} + +static INLINE boolean +util_format_is_compressed(enum pipe_format format) +{ + const struct util_format_description *desc = util_format_description(format); + + assert(desc); + if (!desc) { + return FALSE; + } + + switch (desc->layout) { + case UTIL_FORMAT_LAYOUT_S3TC: + case UTIL_FORMAT_LAYOUT_RGTC: + /* XXX add other formats in the future */ + return TRUE; + default: + return FALSE; + } +} + +static INLINE boolean +util_format_is_s3tc(enum pipe_format format) +{ + const struct util_format_description *desc = util_format_description(format); + + assert(desc); + if (!desc) { + return FALSE; + } + + return desc->layout == UTIL_FORMAT_LAYOUT_S3TC ? TRUE : FALSE; +} + +static INLINE boolean +util_format_is_depth_or_stencil(enum pipe_format format) +{ + const struct util_format_description *desc = util_format_description(format); + + assert(desc); + if (!desc) { + return FALSE; + } + + return desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS ? TRUE : FALSE; +} + +static INLINE boolean +util_format_is_depth_and_stencil(enum pipe_format format) +{ + const struct util_format_description *desc = util_format_description(format); + + assert(desc); + if (!desc) { + return FALSE; + } + + if (desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS) { + return FALSE; + } + + return (desc->swizzle[0] != UTIL_FORMAT_SWIZZLE_NONE && + desc->swizzle[1] != UTIL_FORMAT_SWIZZLE_NONE) ? TRUE : FALSE; +} + + +/** + * Give the RGBA colormask of the channels that can be represented in this + * format. + * + * That is, the channels whose values are preserved. + */ +static INLINE unsigned +util_format_colormask(const struct util_format_description *desc) +{ + unsigned colormask; + unsigned chan; + + switch (desc->colorspace) { + case UTIL_FORMAT_COLORSPACE_RGB: + case UTIL_FORMAT_COLORSPACE_SRGB: + case UTIL_FORMAT_COLORSPACE_YUV: + colormask = 0; + for (chan = 0; chan < 4; ++chan) { + if (desc->swizzle[chan] < 4) { + colormask |= (1 << chan); + } + } + return colormask; + case UTIL_FORMAT_COLORSPACE_ZS: + return 0; + default: + assert(0); + return 0; + } +} + + +boolean +util_format_is_float(enum pipe_format format); + + +/** + * Whether the src format can be blitted to destation format with a simple + * memcpy. + */ +boolean +util_is_format_compatible(const struct util_format_description *src_desc, + const struct util_format_description *dst_desc); + +/** + * Whether the format is supported by Gallium for the given bindings. + * This covers S3TC textures and floating-point render targets. + */ +boolean +util_format_is_supported(enum pipe_format format, unsigned bind); + +/** + * Whether this format is a rgab8 variant. + * + * That is, any format that matches the + * + * PIPE_FORMAT_?8?8?8?8_UNORM + */ +static INLINE boolean +util_format_is_rgba8_variant(const struct util_format_description *desc) +{ + unsigned chan; + + if(desc->block.width != 1 || + desc->block.height != 1 || + desc->block.bits != 32) + return FALSE; + + for(chan = 0; chan < 4; ++chan) { + if(desc->channel[chan].type != UTIL_FORMAT_TYPE_UNSIGNED && + desc->channel[chan].type != UTIL_FORMAT_TYPE_VOID) + return FALSE; + if(desc->channel[chan].size != 8) + return FALSE; + } + + return TRUE; +} + + +/** + * Return total bits needed for the pixel format per block. + */ +static INLINE uint +util_format_get_blocksizebits(enum pipe_format format) +{ + const struct util_format_description *desc = util_format_description(format); + + assert(desc); + if (!desc) { + return 0; + } + + return desc->block.bits; +} + +/** + * Return bytes per block (not pixel) for the given format. + */ +static INLINE uint +util_format_get_blocksize(enum pipe_format format) +{ + uint bits = util_format_get_blocksizebits(format); + + assert(bits % 8 == 0); + + return bits / 8; +} + +static INLINE uint +util_format_get_blockwidth(enum pipe_format format) +{ + const struct util_format_description *desc = util_format_description(format); + + assert(desc); + if (!desc) { + return 1; + } + + return desc->block.width; +} + +static INLINE uint +util_format_get_blockheight(enum pipe_format format) +{ + const struct util_format_description *desc = util_format_description(format); + + assert(desc); + if (!desc) { + return 1; + } + + return desc->block.height; +} + +static INLINE unsigned +util_format_get_nblocksx(enum pipe_format format, + unsigned x) +{ + unsigned blockwidth = util_format_get_blockwidth(format); + return (x + blockwidth - 1) / blockwidth; +} + +static INLINE unsigned +util_format_get_nblocksy(enum pipe_format format, + unsigned y) +{ + unsigned blockheight = util_format_get_blockheight(format); + return (y + blockheight - 1) / blockheight; +} + +static INLINE unsigned +util_format_get_nblocks(enum pipe_format format, + unsigned width, + unsigned height) +{ + return util_format_get_nblocksx(format, width) * util_format_get_nblocksy(format, height); +} + +static INLINE size_t +util_format_get_stride(enum pipe_format format, + unsigned width) +{ + return util_format_get_nblocksx(format, width) * util_format_get_blocksize(format); +} + +static INLINE size_t +util_format_get_2d_size(enum pipe_format format, + size_t stride, + unsigned height) +{ + return util_format_get_nblocksy(format, height) * stride; +} + +static INLINE uint +util_format_get_component_bits(enum pipe_format format, + enum util_format_colorspace colorspace, + uint component) +{ + const struct util_format_description *desc = util_format_description(format); + enum util_format_colorspace desc_colorspace; + + assert(format); + if (!format) { + return 0; + } + + assert(component < 4); + + /* Treat RGB and SRGB as equivalent. */ + if (colorspace == UTIL_FORMAT_COLORSPACE_SRGB) { + colorspace = UTIL_FORMAT_COLORSPACE_RGB; + } + if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) { + desc_colorspace = UTIL_FORMAT_COLORSPACE_RGB; + } else { + desc_colorspace = desc->colorspace; + } + + if (desc_colorspace != colorspace) { + return 0; + } + + switch (desc->swizzle[component]) { + case UTIL_FORMAT_SWIZZLE_X: + return desc->channel[0].size; + case UTIL_FORMAT_SWIZZLE_Y: + return desc->channel[1].size; + case UTIL_FORMAT_SWIZZLE_Z: + return desc->channel[2].size; + case UTIL_FORMAT_SWIZZLE_W: + return desc->channel[3].size; + default: + return 0; + } +} + +static INLINE boolean +util_format_has_alpha(enum pipe_format format) +{ + const struct util_format_description *desc = util_format_description(format); + + assert(format); + if (!format) { + return FALSE; + } + + switch (desc->colorspace) { + case UTIL_FORMAT_COLORSPACE_RGB: + case UTIL_FORMAT_COLORSPACE_SRGB: + return desc->swizzle[3] != UTIL_FORMAT_SWIZZLE_1; + case UTIL_FORMAT_COLORSPACE_YUV: + return FALSE; + case UTIL_FORMAT_COLORSPACE_ZS: + return FALSE; + default: + assert(0); + return FALSE; + } +} + +/** + * Given a linear RGB colorspace format, return the corresponding SRGB + * format, or PIPE_FORMAT_NONE if none. + */ +static INLINE enum pipe_format +util_format_srgb(enum pipe_format format) +{ + switch (format) { + case PIPE_FORMAT_L8_UNORM: + return PIPE_FORMAT_L8_SRGB; + case PIPE_FORMAT_L8A8_UNORM: + return PIPE_FORMAT_L8A8_SRGB; + case PIPE_FORMAT_R8G8B8_UNORM: + return PIPE_FORMAT_R8G8B8_SRGB; + case PIPE_FORMAT_A8B8G8R8_UNORM: + return PIPE_FORMAT_A8B8G8R8_SRGB; + case PIPE_FORMAT_X8B8G8R8_UNORM: + return PIPE_FORMAT_X8B8G8R8_SRGB; + case PIPE_FORMAT_B8G8R8A8_UNORM: + return PIPE_FORMAT_B8G8R8A8_SRGB; + case PIPE_FORMAT_B8G8R8X8_UNORM: + return PIPE_FORMAT_B8G8R8X8_SRGB; + case PIPE_FORMAT_A8R8G8B8_UNORM: + return PIPE_FORMAT_A8R8G8B8_SRGB; + case PIPE_FORMAT_X8R8G8B8_UNORM: + return PIPE_FORMAT_X8R8G8B8_SRGB; + case PIPE_FORMAT_DXT1_RGB: + return PIPE_FORMAT_DXT1_SRGB; + case PIPE_FORMAT_DXT1_RGBA: + return PIPE_FORMAT_DXT1_SRGBA; + case PIPE_FORMAT_DXT3_RGBA: + return PIPE_FORMAT_DXT3_SRGBA; + case PIPE_FORMAT_DXT5_RGBA: + return PIPE_FORMAT_DXT5_SRGBA; + default: + return PIPE_FORMAT_NONE; + } +} + +/** + * Given an sRGB format, return the corresponding linear colorspace format. + * For non sRGB formats, return the format unchanged. + */ +static INLINE enum pipe_format +util_format_linear(enum pipe_format format) +{ + switch (format) { + case PIPE_FORMAT_L8_SRGB: + return PIPE_FORMAT_L8_UNORM; + case PIPE_FORMAT_L8A8_SRGB: + return PIPE_FORMAT_L8A8_UNORM; + case PIPE_FORMAT_R8G8B8_SRGB: + return PIPE_FORMAT_R8G8B8_UNORM; + case PIPE_FORMAT_A8B8G8R8_SRGB: + return PIPE_FORMAT_A8B8G8R8_UNORM; + case PIPE_FORMAT_X8B8G8R8_SRGB: + return PIPE_FORMAT_X8B8G8R8_UNORM; + case PIPE_FORMAT_B8G8R8A8_SRGB: + return PIPE_FORMAT_B8G8R8A8_UNORM; + case PIPE_FORMAT_B8G8R8X8_SRGB: + return PIPE_FORMAT_B8G8R8X8_UNORM; + case PIPE_FORMAT_A8R8G8B8_SRGB: + return PIPE_FORMAT_A8R8G8B8_UNORM; + case PIPE_FORMAT_X8R8G8B8_SRGB: + return PIPE_FORMAT_X8R8G8B8_UNORM; + case PIPE_FORMAT_DXT1_SRGB: + return PIPE_FORMAT_DXT1_RGB; + case PIPE_FORMAT_DXT1_SRGBA: + return PIPE_FORMAT_DXT1_RGBA; + case PIPE_FORMAT_DXT3_SRGBA: + return PIPE_FORMAT_DXT3_RGBA; + case PIPE_FORMAT_DXT5_SRGBA: + return PIPE_FORMAT_DXT5_RGBA; + default: + return format; + } +} + +/** + * Return the number of components stored. + * Formats with block size != 1x1 will always have 1 component (the block). + */ +static INLINE unsigned +util_format_get_nr_components(enum pipe_format format) +{ + const struct util_format_description *desc = util_format_description(format); + return desc->nr_channels; +} + +/* + * Format access functions. + */ + +void +util_format_read_4f(enum pipe_format format, + float *dst, unsigned dst_stride, + const void *src, unsigned src_stride, + unsigned x, unsigned y, unsigned w, unsigned h); + +void +util_format_write_4f(enum pipe_format format, + const float *src, unsigned src_stride, + void *dst, unsigned dst_stride, + unsigned x, unsigned y, unsigned w, unsigned h); + +void +util_format_read_4ub(enum pipe_format format, + uint8_t *dst, unsigned dst_stride, + const void *src, unsigned src_stride, + unsigned x, unsigned y, unsigned w, unsigned h); + +void +util_format_write_4ub(enum pipe_format format, + const uint8_t *src, unsigned src_stride, + void *dst, unsigned dst_stride, + unsigned x, unsigned y, unsigned w, unsigned h); + +/* + * Generic format conversion; + */ + +boolean +util_format_fits_8unorm(const struct util_format_description *format_desc); + +void +util_format_translate(enum pipe_format dst_format, + void *dst, unsigned dst_stride, + unsigned dst_x, unsigned dst_y, + enum pipe_format src_format, + const void *src, unsigned src_stride, + unsigned src_x, unsigned src_y, + unsigned width, unsigned height); + +#ifdef __cplusplus +} // extern "C" { +#endif + +#endif /* ! U_FORMAT_H */ diff --git a/mesalib/src/gallium/auxiliary/util/u_format_latc.c b/mesalib/src/gallium/auxiliary/util/u_format_latc.c new file mode 100644 index 000000000..a25faf5d9 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_format_latc.c @@ -0,0 +1,328 @@ +/************************************************************************** + * + * Copyright (C) 2011 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 + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include +#include "u_math.h" +#include "u_format.h" +#include "u_format_rgtc.h" +#include "u_format_latc.h" + +static void u_format_unsigned_encode_rgtc_chan(uint8_t *blkaddr, uint8_t srccolors[4][4], + int numxpixels, int numypixels); + +static void u_format_unsigned_fetch_texel_rgtc(unsigned srcRowStride, const uint8_t *pixdata, + unsigned i, unsigned j, uint8_t *value, unsigned comps); + +static void u_format_signed_encode_rgtc_chan(int8_t *blkaddr, int8_t srccolors[4][4], + int numxpixels, int numypixels); + +static void u_format_signed_fetch_texel_rgtc(unsigned srcRowStride, const int8_t *pixdata, + unsigned i, unsigned j, int8_t *value, unsigned comps); + +void +util_format_latc1_unorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j) +{ + /* Fix warnings here: */ + (void) u_format_unsigned_encode_rgtc_chan; + (void) u_format_signed_encode_rgtc_chan; + + u_format_unsigned_fetch_texel_rgtc(0, src, i, j, dst, 1); +} + +void +util_format_latc1_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + util_format_rgtc1_unorm_unpack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, width, height); +} + +void +util_format_latc1_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, + unsigned src_stride, unsigned width, unsigned height) +{ + util_format_rgtc1_unorm_pack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, width, height); +} + +void +util_format_latc1_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y, i, j; + int block_size = 8; + + for(y = 0; y < height; y += 4) { + const uint8_t *src = src_row; + for(x = 0; x < width; x += 4) { + for(j = 0; j < 4; ++j) { + for(i = 0; i < 4; ++i) { + float *dst = dst_row + (y + j)*dst_stride/sizeof(*dst_row) + (x + i)*4; + uint8_t tmp_r; + u_format_unsigned_fetch_texel_rgtc(0, src, i, j, &tmp_r, 1); + dst[0] = + dst[1] = + dst[2] = ubyte_to_float(tmp_r); + dst[3] = 1.0; + } + } + src += block_size; + } + src_row += src_stride; + } +} + +void +util_format_latc1_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + util_format_rgtc1_unorm_pack_rgba_float(dst_row, dst_stride, src_row, src_stride, width, height); +} + +void +util_format_latc1_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint8_t tmp_r; + + u_format_unsigned_fetch_texel_rgtc(0, src, i, j, &tmp_r, 1); + dst[0] = + dst[1] = + dst[2] = ubyte_to_float(tmp_r); + dst[3] = 1.0; +} + +void +util_format_latc1_snorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j) +{ + fprintf(stderr,"%s\n", __func__); +} + +void +util_format_latc1_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + fprintf(stderr,"%s\n", __func__); +} + +void +util_format_latc1_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + fprintf(stderr,"%s\n", __func__); +} + +void +util_format_latc1_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + util_format_rgtc1_snorm_pack_rgba_float(dst_row, dst_stride, src_row, src_stride, width, height); +} + +void +util_format_latc1_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y, i, j; + int block_size = 8; + + for(y = 0; y < height; y += 4) { + const int8_t *src = (int8_t *)src_row; + for(x = 0; x < width; x += 4) { + for(j = 0; j < 4; ++j) { + for(i = 0; i < 4; ++i) { + float *dst = dst_row + (y + j)*dst_stride/sizeof(*dst_row) + (x + i)*4; + int8_t tmp_r; + u_format_signed_fetch_texel_rgtc(0, src, i, j, &tmp_r, 1); + dst[0] = + dst[1] = + dst[2] = byte_to_float_tex(tmp_r); + dst[3] = 1.0; + } + } + src += block_size; + } + src_row += src_stride; + } +} + +void +util_format_latc1_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + int8_t tmp_r; + + u_format_signed_fetch_texel_rgtc(0, (int8_t *)src, i, j, &tmp_r, 1); + dst[0] = + dst[1] = + dst[2] = byte_to_float_tex(tmp_r); + dst[3] = 1.0; +} + + +void +util_format_latc2_unorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j) +{ + puts(__func__); + + u_format_unsigned_fetch_texel_rgtc(0, src, i, j, dst, 2); + u_format_unsigned_fetch_texel_rgtc(0, src + 8, i, j, dst + 1, 2); +} + +void +util_format_latc2_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + util_format_rgtc2_unorm_unpack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, width, height); +} + +void +util_format_latc2_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + util_format_rgtc2_unorm_pack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, width, height); +} + +void +util_format_latc2_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + util_format_rxtc2_unorm_pack_rgba_float(dst_row, dst_stride, src_row, src_stride, width, height, 3); +} + +void +util_format_latc2_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y, i, j; + int block_size = 16; + + for(y = 0; y < height; y += 4) { + const uint8_t *src = src_row; + for(x = 0; x < width; x += 4) { + for(j = 0; j < 4; ++j) { + for(i = 0; i < 4; ++i) { + float *dst = dst_row + (y + j)*dst_stride/sizeof(*dst_row) + (x + i)*4; + uint8_t tmp_r, tmp_g; + u_format_unsigned_fetch_texel_rgtc(0, src, i, j, &tmp_r, 2); + u_format_unsigned_fetch_texel_rgtc(0, src + 8, i, j, &tmp_g, 2); + dst[0] = + dst[1] = + dst[2] = ubyte_to_float(tmp_r); + dst[3] = ubyte_to_float(tmp_g); + } + } + src += block_size; + } + src_row += src_stride; + } +} + +void +util_format_latc2_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint8_t tmp_r, tmp_g; + + u_format_unsigned_fetch_texel_rgtc(0, src, i, j, &tmp_r, 2); + u_format_unsigned_fetch_texel_rgtc(0, src + 8, i, j, &tmp_g, 2); + dst[0] = + dst[1] = + dst[2] = ubyte_to_float(tmp_r); + dst[3] = ubyte_to_float(tmp_g); +} + + +void +util_format_latc2_snorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j) +{ + fprintf(stderr,"%s\n", __func__); +} + +void +util_format_latc2_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + fprintf(stderr,"%s\n", __func__); +} + +void +util_format_latc2_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + fprintf(stderr,"%s\n", __func__); +} + +void +util_format_latc2_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y, i, j; + int block_size = 16; + + for(y = 0; y < height; y += 4) { + const int8_t *src = (int8_t *)src_row; + for(x = 0; x < width; x += 4) { + for(j = 0; j < 4; ++j) { + for(i = 0; i < 4; ++i) { + float *dst = dst_row + (y + j)*dst_stride/sizeof(*dst_row) + (x + i)*4; + int8_t tmp_r, tmp_g; + u_format_signed_fetch_texel_rgtc(0, src, i, j, &tmp_r, 2); + u_format_signed_fetch_texel_rgtc(0, src + 8, i, j, &tmp_g, 2); + dst[0] = + dst[1] = + dst[2] = byte_to_float_tex(tmp_r); + dst[3] = byte_to_float_tex(tmp_g); + } + } + src += block_size; + } + src_row += src_stride; + } +} + +void +util_format_latc2_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + util_format_rxtc2_snorm_pack_rgba_float(dst_row, dst_stride, src_row, src_stride, width, height, 3); +} + +void +util_format_latc2_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + int8_t tmp_r, tmp_g; + + u_format_signed_fetch_texel_rgtc(0, (int8_t *)src, i, j, &tmp_r, 2); + u_format_signed_fetch_texel_rgtc(0, (int8_t *)src + 8, i, j, &tmp_g, 2); + dst[0] = + dst[1] = + dst[2] = byte_to_float_tex(tmp_r); + dst[3] = byte_to_float_tex(tmp_g); +} + + +#define TAG(x) u_format_unsigned_##x +#define TYPE uint8_t +#define T_MIN 0 +#define T_MAX 255 + +#include "../../../mesa/main/texcompress_rgtc_tmp.h" + +#undef TYPE +#undef TAG +#undef T_MIN +#undef T_MAX + + +#define TAG(x) u_format_signed_##x +#define TYPE int8_t +#define T_MIN (int8_t)-128 +#define T_MAX (int8_t)127 + +#include "../../../mesa/main/texcompress_rgtc_tmp.h" + +#undef TYPE +#undef TAG +#undef T_MIN +#undef T_MAX diff --git a/mesalib/src/gallium/auxiliary/util/u_format_latc.h b/mesalib/src/gallium/auxiliary/util/u_format_latc.h new file mode 100644 index 000000000..324717215 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_format_latc.h @@ -0,0 +1,108 @@ +/************************************************************************** + * + * Copyright 2011 Red Hat 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 SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 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 U_FORMAT_LATC_H_ +#define U_FORMAT_LATC_H_ + +void +util_format_latc1_unorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j); + +void +util_format_latc1_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_latc1_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_latc1_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_latc1_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_latc1_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j); + + + +void +util_format_latc1_snorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j); + +void +util_format_latc1_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_latc1_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_latc1_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_latc1_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_latc1_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j); + + +void +util_format_latc2_unorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j); + +void +util_format_latc2_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_latc2_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_latc2_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_latc2_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_latc2_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j); + + +void +util_format_latc2_snorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j); + +void +util_format_latc2_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_latc2_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_latc2_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_latc2_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_latc2_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j); + + +#endif diff --git a/mesalib/src/gallium/auxiliary/util/u_format_other.c b/mesalib/src/gallium/auxiliary/util/u_format_other.c new file mode 100644 index 000000000..b6173a12e --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_format_other.c @@ -0,0 +1,472 @@ +/************************************************************************** + * + * 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 SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 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 "u_math.h" +#include "u_format_other.h" +#include "u_format_rgb9e5.h" +#include "u_format_r11g11b10f.h" + + +void +util_format_r9g9b9e5_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + rgb9e5_to_float3(value, dst); + dst[3] = 1; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +void +util_format_r9g9b9e5_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, + const float *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = float3_to_rgb9e5(src); +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +void +util_format_r9g9b9e5_float_fetch_rgba_float(float *dst, const uint8_t *src, + unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + rgb9e5_to_float3(value, dst); + dst[3] = 1; /* a */ +} + + +void +util_format_r9g9b9e5_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + float p[3]; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + rgb9e5_to_float3(value, p); + dst[0] = float_to_ubyte(p[0]); /* r */ + dst[1] = float_to_ubyte(p[1]); /* g */ + dst[2] = float_to_ubyte(p[2]); /* b */ + dst[3] = 255; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + + +void +util_format_r9g9b9e5_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + float p[3]; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value; + p[0] = ubyte_to_float(src[0]); + p[1] = ubyte_to_float(src[1]); + p[2] = ubyte_to_float(src[2]); + value = float3_to_rgb9e5(p); +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + + +void +util_format_r11g11b10_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + r11g11b10f_to_float3(value, dst); + dst[3] = 1; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + +void +util_format_r11g11b10_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, + const float *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value = float3_to_r11g11b10f(src); +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + +void +util_format_r11g11b10_float_fetch_rgba_float(float *dst, const uint8_t *src, + unsigned i, unsigned j) +{ + uint32_t value = *(const uint32_t *)src; +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + r11g11b10f_to_float3(value, dst); + dst[3] = 1; /* a */ +} + + +void +util_format_r11g11b10_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + float p[3]; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row; + for(x = 0; x < width; x += 1) { + uint32_t value = *(const uint32_t *)src; +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + r11g11b10f_to_float3(value, p); + dst[0] = float_to_ubyte(p[0]); /* r */ + dst[1] = float_to_ubyte(p[1]); /* g */ + dst[2] = float_to_ubyte(p[2]); /* b */ + dst[3] = 255; /* a */ + src += 4; + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + + +void +util_format_r11g11b10_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + float p[3]; + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 1) { + uint32_t value; + p[0] = ubyte_to_float(src[0]); + p[1] = ubyte_to_float(src[1]); + p[2] = ubyte_to_float(src[2]); + value = float3_to_r11g11b10f(p); +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + *(uint32_t *)dst = value; + src += 4; + dst += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + + +void +util_format_r1_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + +} + + +void +util_format_r1_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, + const float *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + +} + + +void +util_format_r1_unorm_fetch_rgba_float(float *dst, const uint8_t *src, + unsigned i, unsigned j) +{ + +} + + +void +util_format_r1_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + +} + + +void +util_format_r1_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ +} + + +/* + * PIPE_FORMAT_R8G8Bx_SNORM + * + * A.k.a. D3DFMT_CxV8U8 + */ + +static uint8_t +r8g8bx_derive(int16_t r, int16_t g) +{ + /* Derive blue from red and green components. + * Apparently, we must always use integers to perform calculations, + * otherwise the results won't match D3D's CxV8U8 definition. + */ + return (uint8_t)sqrtf(0x7f * 0x7f - r * r - g * g) * 0xff / 0x7f; +} + +void +util_format_r8g8bx_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + + for(y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint16_t *src = (const uint16_t *)src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *src++; + int16_t r, g; + +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + + r = ((int16_t)(value << 8)) >> 8; + g = ((int16_t)(value << 0)) >> 8; + + dst[0] = (float)(r * (1.0f/0x7f)); /* r */ + dst[1] = (float)(g * (1.0f/0x7f)); /* g */ + dst[2] = r8g8bx_derive(r, g) * (1.0f/0xff); /* b */ + dst[3] = 1.0f; /* a */ + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + + +void +util_format_r8g8bx_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint16_t *src = (const uint16_t *)src_row; + for(x = 0; x < width; x += 1) { + uint16_t value = *src++; + int16_t r, g; + +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + + r = ((int16_t)(value << 8)) >> 8; + g = ((int16_t)(value << 0)) >> 8; + + dst[0] = (uint8_t)(((uint16_t)MAX2(r, 0)) * 0xff / 0x7f); /* r */ + dst[1] = (uint8_t)(((uint16_t)MAX2(g, 0)) * 0xff / 0x7f); /* g */ + dst[2] = r8g8bx_derive(r, g); /* b */ + dst[3] = 255; /* a */ + dst += 4; + } + src_row += src_stride; + dst_row += dst_stride/sizeof(*dst_row); + } +} + + +void +util_format_r8g8bx_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, + const float *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; y += 1) { + const float *src = src_row; + uint16_t *dst = (uint16_t *)dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + + value |= (uint16_t)(((int8_t)(CLAMP(src[0], -1, 1) * 0x7f)) & 0xff) ; + value |= (uint16_t)((((int8_t)(CLAMP(src[1], -1, 1) * 0x7f)) & 0xff) << 8) ; + +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + + *dst++ = value; + + src += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + + +void +util_format_r8g8bx_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + + for(y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint16_t *dst = (uint16_t *)dst_row; + for(x = 0; x < width; x += 1) { + uint16_t value = 0; + + value |= src[0] >> 1; + value |= (src[1] >> 1) << 8; + +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + + *dst++ = value; + + src += 4; + } + dst_row += dst_stride; + src_row += src_stride/sizeof(*src_row); + } +} + + +void +util_format_r8g8bx_snorm_fetch_rgba_float(float *dst, const uint8_t *src, + unsigned i, unsigned j) +{ + uint16_t value = *(const uint16_t *)src; + int16_t r, g; + +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + + r = ((int16_t)(value << 8)) >> 8; + g = ((int16_t)(value << 0)) >> 8; + + dst[0] = r * (1.0f/0x7f); /* r */ + dst[1] = g * (1.0f/0x7f); /* g */ + dst[2] = r8g8bx_derive(r, g) * (1.0f/0xff); /* b */ + dst[3] = 1.0f; /* a */ +} diff --git a/mesalib/src/gallium/auxiliary/util/u_format_other.h b/mesalib/src/gallium/auxiliary/util/u_format_other.h new file mode 100644 index 000000000..d8237da5e --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_format_other.h @@ -0,0 +1,134 @@ +/************************************************************************** + * + * 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 SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 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 U_FORMAT_OTHER_H_ +#define U_FORMAT_OTHER_H_ + + +#include "pipe/p_compiler.h" + + +void +util_format_r9g9b9e5_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); + +void +util_format_r9g9b9e5_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, + const float *src_row, unsigned src_stride, + unsigned width, unsigned height); + +void +util_format_r9g9b9e5_float_fetch_rgba_float(float *dst, const uint8_t *src, + unsigned i, unsigned j); + +void +util_format_r9g9b9e5_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); + +void +util_format_r9g9b9e5_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); + + +void +util_format_r11g11b10_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); + +void +util_format_r11g11b10_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, + const float *src_row, unsigned src_stride, + unsigned width, unsigned height); + +void +util_format_r11g11b10_float_fetch_rgba_float(float *dst, const uint8_t *src, + unsigned i, unsigned j); + +void +util_format_r11g11b10_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); + +void +util_format_r11g11b10_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); + + +void +util_format_r1_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); + +void +util_format_r1_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, + const float *src_row, unsigned src_stride, + unsigned width, unsigned height); + +void +util_format_r1_unorm_fetch_rgba_float(float *dst, const uint8_t *src, + unsigned i, unsigned j); + +void +util_format_r1_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); + +void +util_format_r1_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); + +void +util_format_r8g8bx_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); + +void +util_format_r8g8bx_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, + const float *src_row, unsigned src_stride, + unsigned width, unsigned height); + +void +util_format_r8g8bx_snorm_fetch_rgba_float(float *dst, const uint8_t *src, + unsigned i, unsigned j); + +void +util_format_r8g8bx_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); + +void +util_format_r8g8bx_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); + +#endif /* U_FORMAT_OTHER_H_ */ diff --git a/mesalib/src/gallium/auxiliary/util/u_format_pack.py b/mesalib/src/gallium/auxiliary/util/u_format_pack.py new file mode 100644 index 000000000..497efad5a --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_format_pack.py @@ -0,0 +1,670 @@ +#!/usr/bin/env python + +''' +/************************************************************************** + * + * Copyright 2009-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. + * + **************************************************************************/ + +/** + * @file + * Pixel format packing and unpacking functions. + * + * @author Jose Fonseca + */ +''' + + +from u_format_parse import * + + +def generate_format_type(format): + '''Generate a structure that describes the format.''' + + assert format.layout == PLAIN + + print 'union util_format_%s {' % format.short_name() + + if format.block_size() in (8, 16, 32, 64): + print ' uint%u_t value;' % (format.block_size(),) + + use_bitfields = False + for channel in format.channels: + if channel.size % 8 or not is_pot(channel.size): + use_bitfields = True + + print ' struct {' + for channel in format.channels: + if use_bitfields: + if channel.type == VOID: + if channel.size: + print ' unsigned %s:%u;' % (channel.name, channel.size) + elif channel.type == UNSIGNED: + print ' unsigned %s:%u;' % (channel.name, channel.size) + elif channel.type in (SIGNED, FIXED): + print ' int %s:%u;' % (channel.name, channel.size) + elif channel.type == FLOAT: + if channel.size == 64: + print ' double %s;' % (channel.name) + elif channel.size == 32: + print ' float %s;' % (channel.name) + else: + print ' unsigned %s:%u;' % (channel.name, channel.size) + else: + assert 0 + else: + assert channel.size % 8 == 0 and is_pot(channel.size) + if channel.type == VOID: + if channel.size: + print ' uint%u_t %s;' % (channel.size, channel.name) + elif channel.type == UNSIGNED: + print ' uint%u_t %s;' % (channel.size, channel.name) + elif channel.type in (SIGNED, FIXED): + print ' int%u_t %s;' % (channel.size, channel.name) + elif channel.type == FLOAT: + if channel.size == 64: + print ' double %s;' % (channel.name) + elif channel.size == 32: + print ' float %s;' % (channel.name) + elif channel.size == 16: + print ' uint16_t %s;' % (channel.name) + else: + assert 0 + else: + assert 0 + print ' } chan;' + print '};' + print + + +def bswap_format(format): + '''Generate a structure that describes the format.''' + + if format.is_bitmask() and not format.is_array() and format.block_size() > 8: + print '#ifdef PIPE_ARCH_BIG_ENDIAN' + print ' pixel.value = util_bswap%u(pixel.value);' % format.block_size() + print '#endif' + + +def is_format_supported(format): + '''Determines whether we actually have the plumbing necessary to generate the + to read/write to/from this format.''' + + # FIXME: Ideally we would support any format combination here. + + if format.layout != PLAIN: + return False + + for i in range(4): + channel = format.channels[i] + if channel.type not in (VOID, UNSIGNED, SIGNED, FLOAT, FIXED): + return False + if channel.type == FLOAT and channel.size not in (16, 32, 64): + return False + + return True + + +def native_type(format): + '''Get the native appropriate for a format.''' + + if format.layout == PLAIN: + if not format.is_array(): + # For arithmetic pixel formats return the integer type that matches the whole pixel + return 'uint%u_t' % format.block_size() + else: + # For array pixel formats return the integer type that matches the color channel + channel = format.channels[0] + if channel.type in (UNSIGNED, VOID): + return 'uint%u_t' % channel.size + elif channel.type in (SIGNED, FIXED): + return 'int%u_t' % channel.size + elif channel.type == FLOAT: + if channel.size == 16: + return 'uint16_t' + elif channel.size == 32: + return 'float' + elif channel.size == 64: + return 'double' + else: + assert False + else: + assert False + else: + assert False + + +def intermediate_native_type(bits, sign): + '''Find a native type adequate to hold intermediate results of the request bit size.''' + + bytes = 4 # don't use anything smaller than 32bits + while bytes * 8 < bits: + bytes *= 2 + bits = bytes*8 + + if sign: + return 'int%u_t' % bits + else: + return 'uint%u_t' % bits + + +def get_one_shift(type): + '''Get the number of the bit that matches unity for this type.''' + if type.type == 'FLOAT': + assert False + if not type.norm: + return 0 + if type.type == UNSIGNED: + return type.size + if type.type == SIGNED: + return type.size - 1 + if type.type == FIXED: + return type.size / 2 + assert False + + +def value_to_native(type, value): + '''Get the value of unity for this type.''' + if type.type == FLOAT: + return value + if type.type == FIXED: + return int(value * (1 << (type.size/2))) + if not type.norm: + return int(value) + if type.type == UNSIGNED: + return int(value * ((1 << type.size) - 1)) + if type.type == SIGNED: + return int(value * ((1 << (type.size - 1)) - 1)) + assert False + + +def native_to_constant(type, value): + '''Get the value of unity for this type.''' + if type.type == FLOAT: + if type.size <= 32: + return "%ff" % value + else: + return "%ff" % value + else: + return str(int(value)) + + +def get_one(type): + '''Get the value of unity for this type.''' + return value_to_native(type, 1) + + +def clamp_expr(src_channel, dst_channel, dst_native_type, value): + '''Generate the expression to clamp the value in the source type to the + destination type range.''' + + if src_channel == dst_channel: + return value + + src_min = src_channel.min() + src_max = src_channel.max() + dst_min = dst_channel.min() + dst_max = dst_channel.max() + + # Translate the destination range to the src native value + dst_min_native = value_to_native(src_channel, dst_min) + dst_max_native = value_to_native(src_channel, dst_max) + + if src_min < dst_min and src_max > dst_max: + return 'CLAMP(%s, %s, %s)' % (value, dst_min_native, dst_max_native) + + if src_max > dst_max: + return 'MIN2(%s, %s)' % (value, dst_max_native) + + if src_min < dst_min: + return 'MAX2(%s, %s)' % (value, dst_min_native) + + return value + + +def conversion_expr(src_channel, + dst_channel, dst_native_type, + value, + clamp=True, + src_colorspace = RGB, + dst_colorspace = RGB): + '''Generate the expression to convert a value between two types.''' + + if src_colorspace != dst_colorspace: + if src_colorspace == SRGB: + assert src_channel.type == UNSIGNED + assert src_channel.norm + assert src_channel.size == 8 + assert dst_colorspace == RGB + if dst_channel.type == FLOAT: + return 'util_format_srgb_8unorm_to_linear_float(%s)' % value + else: + assert dst_channel.type == UNSIGNED + assert dst_channel.norm + assert dst_channel.size == 8 + return 'util_format_srgb_to_linear_8unorm(%s)' % value + elif dst_colorspace == SRGB: + assert dst_channel.type == UNSIGNED + assert dst_channel.norm + assert dst_channel.size == 8 + assert src_colorspace == RGB + if src_channel.type == FLOAT: + return 'util_format_linear_float_to_srgb_8unorm(%s)' % value + else: + assert src_channel.type == UNSIGNED + assert src_channel.norm + assert src_channel.size == 8 + return 'util_format_linear_to_srgb_8unorm(%s)' % value + elif src_colorspace == ZS: + pass + elif dst_colorspace == ZS: + pass + else: + assert 0 + + if src_channel == dst_channel: + return value + + src_type = src_channel.type + src_size = src_channel.size + src_norm = src_channel.norm + + # Promote half to float + if src_type == FLOAT and src_size == 16: + value = 'util_half_to_float(%s)' % value + src_size = 32 + + # Special case for float <-> ubytes for more accurate results + # Done before clamping since these functions already take care of that + if src_type == UNSIGNED and src_norm and src_size == 8 and dst_channel.type == FLOAT and dst_channel.size == 32: + return 'ubyte_to_float(%s)' % value + if src_type == FLOAT and src_size == 32 and dst_channel.type == UNSIGNED and dst_channel.norm and dst_channel.size == 8: + return 'float_to_ubyte(%s)' % value + + if clamp: + if dst_channel.type != FLOAT or src_type != FLOAT: + value = clamp_expr(src_channel, dst_channel, dst_native_type, value) + + if src_type in (SIGNED, UNSIGNED) and dst_channel.type in (SIGNED, UNSIGNED): + if not src_norm and not dst_channel.norm: + # neither is normalized -- just cast + return '(%s)%s' % (dst_native_type, value) + + src_one = get_one(src_channel) + dst_one = get_one(dst_channel) + + if src_one > dst_one and src_norm and dst_channel.norm: + # We can just bitshift + src_shift = get_one_shift(src_channel) + dst_shift = get_one_shift(dst_channel) + value = '(%s >> %s)' % (value, src_shift - dst_shift) + else: + # We need to rescale using an intermediate type big enough to hold the multiplication of both + tmp_native_type = intermediate_native_type(src_size + dst_channel.size, src_channel.sign and dst_channel.sign) + value = '((%s)%s)' % (tmp_native_type, value) + value = '(%s * 0x%x / 0x%x)' % (value, dst_one, src_one) + value = '(%s)%s' % (dst_native_type, value) + return value + + # Promote to either float or double + if src_type != FLOAT: + if src_norm or src_type == FIXED: + one = get_one(src_channel) + if src_size <= 23: + value = '(%s * (1.0f/0x%x))' % (value, one) + if dst_channel.size <= 32: + value = '(float)%s' % value + src_size = 32 + else: + # bigger than single precision mantissa, use double + value = '(%s * (1.0/0x%x))' % (value, one) + src_size = 64 + src_norm = False + else: + if src_size <= 23 or dst_channel.size <= 32: + value = '(float)%s' % value + src_size = 32 + else: + # bigger than single precision mantissa, use double + value = '(double)%s' % value + src_size = 64 + src_type = FLOAT + + # Convert double or float to non-float + if dst_channel.type != FLOAT: + if dst_channel.norm or dst_channel.type == FIXED: + dst_one = get_one(dst_channel) + if dst_channel.size <= 23: + value = '(%s * 0x%x)' % (value, dst_one) + else: + # bigger than single precision mantissa, use double + value = '(%s * (double)0x%x)' % (value, dst_one) + value = '(%s)%s' % (dst_native_type, value) + else: + # Cast double to float when converting to either half or float + if dst_channel.size <= 32 and src_size > 32: + value = '(float)%s' % value + src_size = 32 + + if dst_channel.size == 16: + value = 'util_float_to_half(%s)' % value + elif dst_channel.size == 64 and src_size < 64: + value = '(double)%s' % value + + return value + + +def generate_unpack_kernel(format, dst_channel, dst_native_type): + + if not is_format_supported(format): + return + + assert format.layout == PLAIN + + src_native_type = native_type(format) + + if format.is_bitmask(): + depth = format.block_size() + print ' uint%u_t value = *(const uint%u_t *)src;' % (depth, depth) + + # Declare the intermediate variables + for i in range(format.nr_channels()): + src_channel = format.channels[i] + if src_channel.type == UNSIGNED: + print ' uint%u_t %s;' % (depth, src_channel.name) + elif src_channel.type == SIGNED: + print ' int%u_t %s;' % (depth, src_channel.name) + + if depth > 8: + print '#ifdef PIPE_ARCH_BIG_ENDIAN' + print ' value = util_bswap%u(value);' % depth + print '#endif' + + # Compute the intermediate unshifted values + shift = 0 + for i in range(format.nr_channels()): + src_channel = format.channels[i] + value = 'value' + if src_channel.type == UNSIGNED: + if shift: + value = '%s >> %u' % (value, shift) + if shift + src_channel.size < depth: + value = '(%s) & 0x%x' % (value, (1 << src_channel.size) - 1) + elif src_channel.type == SIGNED: + if shift + src_channel.size < depth: + # Align the sign bit + lshift = depth - (shift + src_channel.size) + value = '%s << %u' % (value, lshift) + # Cast to signed + value = '(int%u_t)(%s) ' % (depth, value) + if src_channel.size < depth: + # Align the LSB bit + rshift = depth - src_channel.size + value = '(%s) >> %u' % (value, rshift) + else: + value = None + + if value is not None: + print ' %s = %s;' % (src_channel.name, value) + + shift += src_channel.size + + # Convert, swizzle, and store final values + for i in range(4): + swizzle = format.swizzles[i] + if swizzle < 4: + src_channel = format.channels[swizzle] + src_colorspace = format.colorspace + if src_colorspace == SRGB and i == 3: + # Alpha channel is linear + src_colorspace = RGB + value = src_channel.name + value = conversion_expr(src_channel, + dst_channel, dst_native_type, + value, + src_colorspace = src_colorspace) + elif swizzle == SWIZZLE_0: + value = '0' + elif swizzle == SWIZZLE_1: + value = get_one(dst_channel) + elif swizzle == SWIZZLE_NONE: + value = '0' + else: + assert False + print ' dst[%u] = %s; /* %s */' % (i, value, 'rgba'[i]) + + else: + print ' union util_format_%s pixel;' % format.short_name() + print ' memcpy(&pixel, src, sizeof pixel);' + bswap_format(format) + + for i in range(4): + swizzle = format.swizzles[i] + if swizzle < 4: + src_channel = format.channels[swizzle] + src_colorspace = format.colorspace + if src_colorspace == SRGB and i == 3: + # Alpha channel is linear + src_colorspace = RGB + value = 'pixel.chan.%s' % src_channel.name + value = conversion_expr(src_channel, + dst_channel, dst_native_type, + value, + src_colorspace = src_colorspace) + elif swizzle == SWIZZLE_0: + value = '0' + elif swizzle == SWIZZLE_1: + value = get_one(dst_channel) + elif swizzle == SWIZZLE_NONE: + value = '0' + else: + assert False + print ' dst[%u] = %s; /* %s */' % (i, value, 'rgba'[i]) + + +def generate_pack_kernel(format, src_channel, src_native_type): + + if not is_format_supported(format): + return + + dst_native_type = native_type(format) + + assert format.layout == PLAIN + + inv_swizzle = format.inv_swizzles() + + if format.is_bitmask(): + depth = format.block_size() + print ' uint%u_t value = 0;' % depth + + shift = 0 + for i in range(4): + dst_channel = format.channels[i] + if inv_swizzle[i] is not None: + value ='src[%u]' % inv_swizzle[i] + dst_colorspace = format.colorspace + if dst_colorspace == SRGB and inv_swizzle[i] == 3: + # Alpha channel is linear + dst_colorspace = RGB + value = conversion_expr(src_channel, + dst_channel, dst_native_type, + value, + dst_colorspace = dst_colorspace) + if dst_channel.type in (UNSIGNED, SIGNED): + if shift + dst_channel.size < depth: + value = '(%s) & 0x%x' % (value, (1 << dst_channel.size) - 1) + if shift: + value = '(%s) << %u' % (value, shift) + if dst_channel.type == SIGNED: + # Cast to unsigned + value = '(uint%u_t)(%s) ' % (depth, value) + else: + value = None + if value is not None: + print ' value |= %s;' % (value) + + shift += dst_channel.size + + if depth > 8: + print '#ifdef PIPE_ARCH_BIG_ENDIAN' + print ' value = util_bswap%u(value);' % depth + print '#endif' + + print ' *(uint%u_t *)dst = value;' % depth + + else: + print ' union util_format_%s pixel;' % format.short_name() + + for i in range(4): + dst_channel = format.channels[i] + width = dst_channel.size + if inv_swizzle[i] is None: + continue + dst_colorspace = format.colorspace + if dst_colorspace == SRGB and inv_swizzle[i] == 3: + # Alpha channel is linear + dst_colorspace = RGB + value ='src[%u]' % inv_swizzle[i] + value = conversion_expr(src_channel, + dst_channel, dst_native_type, + value, + dst_colorspace = dst_colorspace) + print ' pixel.chan.%s = %s;' % (dst_channel.name, value) + + bswap_format(format) + print ' memcpy(dst, &pixel, sizeof pixel);' + + +def generate_format_unpack(format, dst_channel, dst_native_type, dst_suffix): + '''Generate the function to unpack pixels from a particular format''' + + name = format.short_name() + + print 'static INLINE void' + print 'util_format_%s_unpack_%s(%s *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)' % (name, dst_suffix, dst_native_type) + print '{' + + if is_format_supported(format): + print ' unsigned x, y;' + print ' for(y = 0; y < height; y += %u) {' % (format.block_height,) + print ' %s *dst = dst_row;' % (dst_native_type) + print ' const uint8_t *src = src_row;' + print ' for(x = 0; x < width; x += %u) {' % (format.block_width,) + + generate_unpack_kernel(format, dst_channel, dst_native_type) + + print ' src += %u;' % (format.block_size() / 8,) + print ' dst += 4;' + print ' }' + print ' src_row += src_stride;' + print ' dst_row += dst_stride/sizeof(*dst_row);' + print ' }' + + print '}' + print + + +def generate_format_pack(format, src_channel, src_native_type, src_suffix): + '''Generate the function to pack pixels to a particular format''' + + name = format.short_name() + + print 'static INLINE void' + print 'util_format_%s_pack_%s(uint8_t *dst_row, unsigned dst_stride, const %s *src_row, unsigned src_stride, unsigned width, unsigned height)' % (name, src_suffix, src_native_type) + print '{' + + if is_format_supported(format): + print ' unsigned x, y;' + print ' for(y = 0; y < height; y += %u) {' % (format.block_height,) + print ' const %s *src = src_row;' % (src_native_type) + print ' uint8_t *dst = dst_row;' + print ' for(x = 0; x < width; x += %u) {' % (format.block_width,) + + generate_pack_kernel(format, src_channel, src_native_type) + + print ' src += 4;' + print ' dst += %u;' % (format.block_size() / 8,) + print ' }' + print ' dst_row += dst_stride;' + print ' src_row += src_stride/sizeof(*src_row);' + print ' }' + + print '}' + print + + +def generate_format_fetch(format, dst_channel, dst_native_type, dst_suffix): + '''Generate the function to unpack pixels from a particular format''' + + name = format.short_name() + + print 'static INLINE void' + print 'util_format_%s_fetch_%s(%s *dst, const uint8_t *src, unsigned i, unsigned j)' % (name, dst_suffix, dst_native_type) + print '{' + + if is_format_supported(format): + generate_unpack_kernel(format, dst_channel, dst_native_type) + + print '}' + print + + +def is_format_hand_written(format): + return format.layout in ('s3tc', 'rgtc', 'subsampled', 'other') or format.colorspace == ZS + + +def generate(formats): + print + print '#include "pipe/p_compiler.h"' + print '#include "u_math.h"' + print '#include "u_half.h"' + print '#include "u_format.h"' + print '#include "u_format_other.h"' + print '#include "u_format_srgb.h"' + print '#include "u_format_yuv.h"' + print '#include "u_format_zs.h"' + print + + for format in formats: + if not is_format_hand_written(format): + + if is_format_supported(format): + generate_format_type(format) + + channel = Channel(FLOAT, False, 32) + native_type = 'float' + suffix = 'rgba_float' + + generate_format_unpack(format, channel, native_type, suffix) + generate_format_pack(format, channel, native_type, suffix) + generate_format_fetch(format, channel, native_type, suffix) + + channel = Channel(UNSIGNED, True, 8) + native_type = 'uint8_t' + suffix = 'rgba_8unorm' + + generate_format_unpack(format, channel, native_type, suffix) + generate_format_pack(format, channel, native_type, suffix) + diff --git a/mesalib/src/gallium/auxiliary/util/u_format_parse.py b/mesalib/src/gallium/auxiliary/util/u_format_parse.py new file mode 100644 index 000000000..f47f65d26 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_format_parse.py @@ -0,0 +1,291 @@ +#!/usr/bin/env python + +''' +/************************************************************************** + * + * 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. + * + **************************************************************************/ +''' + + +VOID, UNSIGNED, SIGNED, FIXED, FLOAT = range(5) + +SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W, SWIZZLE_0, SWIZZLE_1, SWIZZLE_NONE, = range(7) + +PLAIN = 'plain' + +RGB = 'rgb' +SRGB = 'srgb' +YUV = 'yuv' +ZS = 'zs' + + +def is_pot(x): + return (x & (x - 1)) == 0 + + +VERY_LARGE = 99999999999999999999999 + + +class Channel: + '''Describe the channel of a color channel.''' + + def __init__(self, type, norm, size, name = ''): + self.type = type + self.norm = norm + self.size = size + self.sign = type in (SIGNED, FIXED, FLOAT) + self.name = name + + def __str__(self): + s = str(self.type) + if self.norm: + s += 'n' + s += str(self.size) + return s + + def __eq__(self, other): + return self.type == other.type and self.norm == other.norm and self.size == other.size + + def max(self): + '''Maximum representable number.''' + if self.type == FLOAT: + return VERY_LARGE + if self.type == FIXED: + return (1 << (self.size/2)) - 1 + if self.norm: + return 1 + if self.type == UNSIGNED: + return (1 << self.size) - 1 + if self.type == SIGNED: + return (1 << (self.size - 1)) - 1 + assert False + + def min(self): + '''Minimum representable number.''' + if self.type == FLOAT: + return -VERY_LARGE + if self.type == FIXED: + return -(1 << (self.size/2)) + if self.type == UNSIGNED: + return 0 + if self.norm: + return -1 + if self.type == SIGNED: + return -(1 << (self.size - 1)) + assert False + + +class Format: + '''Describe a pixel format.''' + + def __init__(self, name, layout, block_width, block_height, channels, swizzles, colorspace): + self.name = name + self.layout = layout + self.block_width = block_width + self.block_height = block_height + self.channels = channels + self.swizzles = swizzles + self.name = name + self.colorspace = colorspace + + def __str__(self): + return self.name + + def short_name(self): + '''Make up a short norm for a format, suitable to be used as suffix in + function names.''' + + name = self.name + if name.startswith('PIPE_FORMAT_'): + name = name[len('PIPE_FORMAT_'):] + name = name.lower() + return name + + def block_size(self): + size = 0 + for channel in self.channels: + size += channel.size + return size + + def nr_channels(self): + nr_channels = 0 + for channel in self.channels: + if channel.size: + nr_channels += 1 + return nr_channels + + def is_array(self): + if self.layout != PLAIN: + return False + ref_channel = self.channels[0] + for channel in self.channels[1:]: + if channel.size and (channel.size != ref_channel.size or channel.size % 8): + return False + return True + + def is_mixed(self): + if self.layout != PLAIN: + return False + ref_channel = self.channels[0] + if ref_channel.type == VOID: + ref_channel = self.channels[1] + for channel in self.channels[1:]: + if channel.type != VOID: + if channel.type != ref_channel.type: + return True + if channel.norm != ref_channel.norm: + return True + return False + + def is_pot(self): + return is_pot(self.block_size()) + + def is_int(self): + if self.layout != PLAIN: + return False + for channel in self.channels: + if channel.type not in (VOID, UNSIGNED, SIGNED): + return False + return True + + def is_float(self): + if self.layout != PLAIN: + return False + for channel in self.channels: + if channel.type not in (VOID, FLOAT): + return False + return True + + def is_bitmask(self): + if self.layout != PLAIN: + return False + if self.block_size() not in (8, 16, 32): + return False + for channel in self.channels: + if channel.type not in (VOID, UNSIGNED, SIGNED): + return False + return True + + def inv_swizzles(self): + '''Return an array[4] of inverse swizzle terms''' + inv_swizzle = [None]*4 + for i in range(4): + swizzle = self.swizzles[i] + if swizzle < 4: + inv_swizzle[swizzle] = i + return inv_swizzle + + def stride(self): + return self.block_size()/8 + + +_type_parse_map = { + '': VOID, + 'x': VOID, + 'u': UNSIGNED, + 's': SIGNED, + 'h': FIXED, + 'f': FLOAT, +} + +_swizzle_parse_map = { + 'x': SWIZZLE_X, + 'y': SWIZZLE_Y, + 'z': SWIZZLE_Z, + 'w': SWIZZLE_W, + '0': SWIZZLE_0, + '1': SWIZZLE_1, + '_': SWIZZLE_NONE, +} + +def parse(filename): + '''Parse the format descrition in CSV format in terms of the + Channel and Format classes above.''' + + stream = open(filename) + formats = [] + for line in stream: + try: + comment = line.index('#') + except ValueError: + pass + else: + line = line[:comment] + line = line.strip() + if not line: + continue + + fields = [field.strip() for field in line.split(',')] + + name = fields[0] + layout = fields[1] + block_width, block_height = map(int, fields[2:4]) + + swizzles = [_swizzle_parse_map[swizzle] for swizzle in fields[8]] + colorspace = fields[9] + + if layout == PLAIN: + names = ['']*4 + if colorspace in (RGB, SRGB): + for i in range(4): + swizzle = swizzles[i] + if swizzle < 4: + names[swizzle] += 'rgba'[i] + elif colorspace == ZS: + for i in range(4): + swizzle = swizzles[i] + if swizzle < 4: + names[swizzle] += 'zs'[i] + else: + assert False + for i in range(4): + if names[i] == '': + names[i] = 'x' + else: + names = ['x', 'y', 'z', 'w'] + + channels = [] + for i in range(0, 4): + field = fields[4 + i] + if field: + type = _type_parse_map[field[0]] + if field[1] == 'n': + norm = True + size = int(field[2:]) + else: + norm = False + size = int(field[1:]) + else: + type = VOID + norm = False + size = 0 + channel = Channel(type, norm, size, names[i]) + channels.append(channel) + + format = Format(name, layout, block_width, block_height, channels, swizzles, colorspace) + formats.append(format) + return formats + diff --git a/mesalib/src/gallium/auxiliary/util/u_format_r11g11b10f.h b/mesalib/src/gallium/auxiliary/util/u_format_r11g11b10f.h new file mode 100644 index 000000000..e079b90b1 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_format_r11g11b10f.h @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2011 Marek Olšák + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and 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. + */ + +/* Based on code from The OpenGL Programming Guide / 7th Edition, Appendix J. + * Available here: http://www.opengl-redbook.com/appendices/ + * The algorithm in the book contains a bug though, which is fixed in the code + * below. + */ + +#define UF11_EXPONENT_BIAS 15 +#define UF11_EXPONENT_BITS 0x1F +#define UF11_EXPONENT_SHIFT 6 +#define UF11_MANTISSA_BITS 0x3F +#define UF11_MANTISSA_SHIFT (23 - UF11_EXPONENT_SHIFT) +#define UF11_MAX_EXPONENT (UF11_EXPONENT_BITS << UF11_EXPONENT_SHIFT) + +#define UF10_EXPONENT_BIAS 15 +#define UF10_EXPONENT_BITS 0x1F +#define UF10_EXPONENT_SHIFT 5 +#define UF10_MANTISSA_BITS 0x3F +#define UF10_MANTISSA_SHIFT (23 - UF10_EXPONENT_SHIFT) +#define UF10_MAX_EXPONENT (UF10_EXPONENT_BITS << UF10_EXPONENT_SHIFT) + +#define F32_INFINITY 0x7f800000 + +static INLINE unsigned f32_to_uf11(float val) +{ + uint32_t f32 = (*(uint32_t *) &val); + uint16_t uf11 = 0; + + /* Decode little-endian 32-bit floating-point value */ + int sign = (f32 >> 16) & 0x8000; + /* Map exponent to the range [-127,128] */ + int exponent = ((f32 >> 23) & 0xff) - 127; + int mantissa = f32 & 0x007fffff; + + if (sign) return 0; + + if (exponent == 128) { /* Infinity or NaN */ + uf11 = UF11_MAX_EXPONENT; + if (mantissa) uf11 |= (mantissa & UF11_MANTISSA_BITS); + } + else if (exponent > 15) { /* Overflow - flush to Infinity */ + uf11 = UF11_MAX_EXPONENT; + } + else if (exponent > -15) { /* Representable value */ + exponent += UF11_EXPONENT_BIAS; + mantissa >>= UF11_MANTISSA_SHIFT; + uf11 = exponent << UF11_EXPONENT_SHIFT | mantissa; + } + + return uf11; +} + +static INLINE float uf11_to_f32(uint16_t val) +{ + union { + float f; + uint32_t ui; + } f32; + + int exponent = (val & 0x07c0) >> UF11_EXPONENT_SHIFT; + int mantissa = (val & 0x003f); + + f32.f = 0.0; + + if (exponent == 0) { + if (mantissa != 0) { + const float scale = 1.0 / (1 << 20); + f32.f = scale * mantissa; + } + } + else if (exponent == 31) { + f32.ui = F32_INFINITY | mantissa; + } + else { + float scale, decimal; + exponent -= 15; + if (exponent < 0) { + scale = 1.0 / (1 << -exponent); + } + else { + scale = 1 << exponent; + } + decimal = 1.0 + (float) mantissa / 64; + f32.f = scale * decimal; + } + + return f32.f; +} + +static INLINE unsigned f32_to_uf10(float val) +{ + uint32_t f32 = (*(uint32_t *) &val); + uint16_t uf10 = 0; + + /* Decode little-endian 32-bit floating-point value */ + int sign = (f32 >> 16) & 0x8000; + /* Map exponent to the range [-127,128] */ + int exponent = ((f32 >> 23) & 0xff) - 127; + int mantissa = f32 & 0x007fffff; + + if (sign) return 0; + + if (exponent == 128) { /* Infinity or NaN */ + uf10 = UF10_MAX_EXPONENT; + if (mantissa) uf10 |= (mantissa & UF10_MANTISSA_BITS); + } + else if (exponent > 15) { /* Overflow - flush to Infinity */ + uf10 = UF10_MAX_EXPONENT; + } + else if (exponent > -15) { /* Representable value */ + exponent += UF10_EXPONENT_BIAS; + mantissa >>= UF10_MANTISSA_SHIFT; + uf10 = exponent << UF10_EXPONENT_SHIFT | mantissa; + } + + return uf10; +} + +static INLINE float uf10_to_f32(uint16_t val) +{ + union { + float f; + uint32_t ui; + } f32; + + int exponent = (val & 0x07c0) >> UF10_EXPONENT_SHIFT; + int mantissa = (val & 0x003f); + + f32.f = 0.0; + + if (exponent == 0) { + if (mantissa != 0) { + const float scale = 1.0 / (1 << 20); + f32.f = scale * mantissa; + } + } + else if (exponent == 31) { + f32.ui = F32_INFINITY | mantissa; + } + else { + float scale, decimal; + exponent -= 15; + if (exponent < 0) { + scale = 1.0 / (1 << -exponent); + } + else { + scale = 1 << exponent; + } + decimal = 1.0 + (float) mantissa / 32; + f32.f = scale * decimal; + } + + return f32.f; +} + +static INLINE unsigned float3_to_r11g11b10f(const float rgb[3]) +{ + return ( f32_to_uf11(rgb[0]) & 0x7ff) | + ((f32_to_uf11(rgb[1]) & 0x7ff) << 11) | + ((f32_to_uf10(rgb[2]) & 0x3ff) << 22); +} + +static INLINE void r11g11b10f_to_float3(unsigned rgb, float retval[3]) +{ + retval[0] = uf11_to_f32( rgb & 0x7ff); + retval[1] = uf11_to_f32((rgb >> 11) & 0x7ff); + retval[2] = uf10_to_f32((rgb >> 22) & 0x3ff); +} diff --git a/mesalib/src/gallium/auxiliary/util/u_format_rgb9e5.h b/mesalib/src/gallium/auxiliary/util/u_format_rgb9e5.h new file mode 100644 index 000000000..01f4e2108 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_format_rgb9e5.h @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2011 Marek Olšák + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and 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. + */ + +/* Copied from EXT_texture_shared_exponent and edited. */ + +#ifndef RGB9E5_H +#define RGB9E5_H + +#include +#include + +#define RGB9E5_EXPONENT_BITS 5 +#define RGB9E5_MANTISSA_BITS 9 +#define RGB9E5_EXP_BIAS 15 +#define RGB9E5_MAX_VALID_BIASED_EXP 31 + +#define MAX_RGB9E5_EXP (RGB9E5_MAX_VALID_BIASED_EXP - RGB9E5_EXP_BIAS) +#define RGB9E5_MANTISSA_VALUES (1< 0.0) { + if (x >= MAX_RGB9E5) { + return MAX_RGB9E5; + } else { + return x; + } + } else { + /* NaN gets here too since comparisons with NaN always fail! */ + return 0.0; + } +} + +/* Ok, FloorLog2 is not correct for the denorm and zero values, but we + are going to do a max of this value with the minimum rgb9e5 exponent + that will hide these problem cases. */ +static INLINE int rgb9e5_FloorLog2(float x) +{ + float754 f; + + f.value = x; + return (f.field.biasedexponent - 127); +} + +static INLINE unsigned float3_to_rgb9e5(const float rgb[3]) +{ + rgb9e5 retval; + float maxrgb; + int rm, gm, bm; + float rc, gc, bc; + int exp_shared, maxm; + double denom; + + rc = rgb9e5_ClampRange(rgb[0]); + gc = rgb9e5_ClampRange(rgb[1]); + bc = rgb9e5_ClampRange(rgb[2]); + + maxrgb = MAX3(rc, gc, bc); + exp_shared = MAX2(-RGB9E5_EXP_BIAS-1, rgb9e5_FloorLog2(maxrgb)) + 1 + RGB9E5_EXP_BIAS; + assert(exp_shared <= RGB9E5_MAX_VALID_BIASED_EXP); + assert(exp_shared >= 0); + /* This pow function could be replaced by a table. */ + denom = pow(2, exp_shared - RGB9E5_EXP_BIAS - RGB9E5_MANTISSA_BITS); + + maxm = (int) floor(maxrgb / denom + 0.5); + if (maxm == MAX_RGB9E5_MANTISSA+1) { + denom *= 2; + exp_shared += 1; + assert(exp_shared <= RGB9E5_MAX_VALID_BIASED_EXP); + } else { + assert(maxm <= MAX_RGB9E5_MANTISSA); + } + + rm = (int) floor(rc / denom + 0.5); + gm = (int) floor(gc / denom + 0.5); + bm = (int) floor(bc / denom + 0.5); + + assert(rm <= MAX_RGB9E5_MANTISSA); + assert(gm <= MAX_RGB9E5_MANTISSA); + assert(bm <= MAX_RGB9E5_MANTISSA); + assert(rm >= 0); + assert(gm >= 0); + assert(bm >= 0); + + retval.field.r = rm; + retval.field.g = gm; + retval.field.b = bm; + retval.field.biasedexponent = exp_shared; + + return retval.raw; +} + +static INLINE void rgb9e5_to_float3(unsigned rgb, float retval[3]) +{ + rgb9e5 v; + int exponent; + float scale; + + v.raw = rgb; + exponent = v.field.biasedexponent - RGB9E5_EXP_BIAS - RGB9E5_MANTISSA_BITS; + scale = (float) pow(2, exponent); + + retval[0] = v.field.r * scale; + retval[1] = v.field.g * scale; + retval[2] = v.field.b * scale; +} + +#endif diff --git a/mesalib/src/gallium/auxiliary/util/u_format_rgtc.c b/mesalib/src/gallium/auxiliary/util/u_format_rgtc.c new file mode 100644 index 000000000..c3fa54c74 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_format_rgtc.c @@ -0,0 +1,464 @@ +/************************************************************************** + * + * Copyright (C) 2011 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 + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include +#include "u_math.h" +#include "u_format.h" +#include "u_format_rgtc.h" + +static void u_format_unsigned_encode_rgtc_chan(uint8_t *blkaddr, uint8_t srccolors[4][4], + int numxpixels, int numypixels); + +static void u_format_unsigned_fetch_texel_rgtc(unsigned srcRowStride, const uint8_t *pixdata, + unsigned i, unsigned j, uint8_t *value, unsigned comps); + +static void u_format_signed_encode_rgtc_chan(int8_t *blkaddr, int8_t srccolors[4][4], + int numxpixels, int numypixels); + +static void u_format_signed_fetch_texel_rgtc(unsigned srcRowStride, const int8_t *pixdata, + unsigned i, unsigned j, int8_t *value, unsigned comps); + +void +util_format_rgtc1_unorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j) +{ + u_format_unsigned_fetch_texel_rgtc(0, src, i, j, dst, 1); +} + +void +util_format_rgtc1_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + const unsigned bw = 4, bh = 4, comps = 4; + unsigned x, y, i, j; + unsigned block_size = 8; + + for(y = 0; y < height; y += bh) { + const uint8_t *src = src_row; + for(x = 0; x < width; x += bw) { + for(j = 0; j < bh; ++j) { + for(i = 0; i < bw; ++i) { + uint8_t *dst = dst_row + (y + j)*dst_stride/sizeof(*dst_row) + (x + i)*comps; + u_format_unsigned_fetch_texel_rgtc(0, src, i, j, dst, 1); + } + } + src += block_size; + } + src_row += src_stride; + } +} + +void +util_format_rgtc1_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, + unsigned src_stride, unsigned width, unsigned height) +{ + const unsigned bw = 4, bh = 4, bytes_per_block = 8; + unsigned x, y, i, j; + + for(y = 0; y < height; y += bh) { + uint8_t *dst = dst_row; + for(x = 0; x < width; x += bw) { + uint8_t tmp[4][4]; /* [bh][bw][comps] */ + for(j = 0; j < bh; ++j) { + for(i = 0; i < bw; ++i) { + tmp[j][i] = src_row[(y + j)*src_stride/sizeof(*src_row) + (x + i)*4]; + } + } + u_format_unsigned_encode_rgtc_chan(dst, tmp, 4, 4); + dst += bytes_per_block; + } + dst_row += dst_stride / sizeof(*dst_row); + } +} + +void +util_format_rgtc1_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y, i, j; + int block_size = 8; + for(y = 0; y < height; y += 4) { + const uint8_t *src = src_row; + for(x = 0; x < width; x += 4) { + for(j = 0; j < 4; ++j) { + for(i = 0; i < 4; ++i) { + float *dst = dst_row + (y + j)*dst_stride/sizeof(*dst_row) + (x + i)*4; + uint8_t tmp_r; + u_format_unsigned_fetch_texel_rgtc(0, src, i, j, &tmp_r, 1); + dst[0] = ubyte_to_float(tmp_r); + dst[1] = 0.0; + dst[2] = 0.0; + dst[3] = 1.0; + } + } + src += block_size; + } + src_row += src_stride; + } +} + +void +util_format_rgtc1_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + const unsigned bw = 4, bh = 4, bytes_per_block = 8; + unsigned x, y, i, j; + + for(y = 0; y < height; y += bh) { + uint8_t *dst = dst_row; + for(x = 0; x < width; x += bw) { + uint8_t tmp[4][4]; /* [bh][bw][comps] */ + for(j = 0; j < bh; ++j) { + for(i = 0; i < bw; ++i) { + tmp[j][i] = float_to_ubyte(src_row[(y + j)*src_stride/sizeof(*src_row) + (x + i)*4]); + } + } + u_format_unsigned_encode_rgtc_chan(dst, tmp, 4, 4); + dst += bytes_per_block; + } + dst_row += dst_stride / sizeof(*dst_row); + } +} + +void +util_format_rgtc1_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint8_t tmp_r; + u_format_unsigned_fetch_texel_rgtc(0, src, i, j, &tmp_r, 1); + dst[0] = ubyte_to_float(tmp_r); + dst[1] = 0.0; + dst[2] = 0.0; + dst[3] = 1.0; +} + +void +util_format_rgtc1_snorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j) +{ + fprintf(stderr,"%s\n", __func__); +} + +void +util_format_rgtc1_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + fprintf(stderr,"%s\n", __func__); +} + +void +util_format_rgtc1_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + fprintf(stderr,"%s\n", __func__); +} + +void +util_format_rgtc1_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + const unsigned bw = 4, bh = 4, bytes_per_block = 8; + unsigned x, y, i, j; + + for(y = 0; y < height; y += bh) { + int8_t *dst = (int8_t *)dst_row; + for(x = 0; x < width; x += bw) { + int8_t tmp[4][4]; /* [bh][bw][comps] */ + for(j = 0; j < bh; ++j) { + for(i = 0; i < bw; ++i) { + tmp[j][i] = float_to_byte_tex(src_row[(y + j)*src_stride/sizeof(*src_row) + (x + i)*4]); + } + } + u_format_signed_encode_rgtc_chan(dst, tmp, 4, 4); + dst += bytes_per_block; + } + dst_row += dst_stride / sizeof(*dst_row); + } +} + +void +util_format_rgtc1_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y, i, j; + int block_size = 8; + for(y = 0; y < height; y += 4) { + const int8_t *src = (int8_t *)src_row; + for(x = 0; x < width; x += 4) { + for(j = 0; j < 4; ++j) { + for(i = 0; i < 4; ++i) { + float *dst = dst_row + (y + j)*dst_stride/sizeof(*dst_row) + (x + i)*4; + int8_t tmp_r; + u_format_signed_fetch_texel_rgtc(0, src, i, j, &tmp_r, 1); + dst[0] = byte_to_float_tex(tmp_r); + dst[1] = 0.0; + dst[2] = 0.0; + dst[3] = 1.0; + } + } + src += block_size; + } + src_row += src_stride; + } +} + +void +util_format_rgtc1_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + int8_t tmp_r; + u_format_signed_fetch_texel_rgtc(0, (int8_t *)src, i, j, &tmp_r, 1); + dst[0] = byte_to_float_tex(tmp_r); + dst[1] = 0.0; + dst[2] = 0.0; + dst[3] = 1.0; +} + + +void +util_format_rgtc2_unorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j) +{ + u_format_unsigned_fetch_texel_rgtc(0, src, i, j, dst, 2); + u_format_unsigned_fetch_texel_rgtc(0, src + 8, i, j, dst + 1, 2); +} + +void +util_format_rgtc2_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + const unsigned bw = 4, bh = 4, comps = 4; + unsigned x, y, i, j; + unsigned block_size = 16; + + for(y = 0; y < height; y += bh) { + const uint8_t *src = src_row; + for(x = 0; x < width; x += bw) { + for(j = 0; j < bh; ++j) { + for(i = 0; i < bw; ++i) { + uint8_t *dst = dst_row + (y + j)*dst_stride/sizeof(*dst_row) + (x + i)*comps; + u_format_unsigned_fetch_texel_rgtc(0, src, i, j, dst, 2); + u_format_unsigned_fetch_texel_rgtc(0, src + 8, i, j, dst + 1, 2); + + } + } + src += block_size; + } + src_row += src_stride; + } +} + +void +util_format_rgtc2_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + const unsigned bw = 4, bh = 4, bytes_per_block = 16; + unsigned x, y, i, j; + + for(y = 0; y < height; y += bh) { + uint8_t *dst = dst_row; + for(x = 0; x < width; x += bw) { + uint8_t tmp_r[4][4]; /* [bh][bw] */ + uint8_t tmp_g[4][4]; /* [bh][bw] */ + for(j = 0; j < bh; ++j) { + for(i = 0; i < bw; ++i) { + tmp_r[j][i] = src_row[(y + j)*src_stride/sizeof(*src_row) + (x + i)*4]; + tmp_g[j][i] = src_row[((y + j)*src_stride/sizeof(*src_row) + (x + i)*4) + 1]; + } + } + u_format_unsigned_encode_rgtc_chan(dst, tmp_r, 4, 4); + u_format_unsigned_encode_rgtc_chan(dst + 8, tmp_g, 4, 4); + dst += bytes_per_block; + } + dst_row += dst_stride / sizeof(*dst_row); + } +} + +void +util_format_rxtc2_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height, unsigned chan2off) +{ + const unsigned bw = 4, bh = 4, bytes_per_block = 16; + unsigned x, y, i, j; + + for(y = 0; y < height; y += bh) { + uint8_t *dst = dst_row; + for(x = 0; x < width; x += bw) { + uint8_t tmp_r[4][4]; /* [bh][bw][comps] */ + uint8_t tmp_g[4][4]; /* [bh][bw][comps] */ + for(j = 0; j < bh; ++j) { + for(i = 0; i < bw; ++i) { + tmp_r[j][i] = float_to_ubyte(src_row[(y + j)*src_stride/sizeof(*src_row) + (x + i)*4]); + tmp_g[j][i] = float_to_ubyte(src_row[(y + j)*src_stride/sizeof(*src_row) + (x + i)*4 + chan2off]); + } + } + u_format_unsigned_encode_rgtc_chan(dst, tmp_r, 4, 4); + u_format_unsigned_encode_rgtc_chan(dst + 8, tmp_g, 4, 4); + dst += bytes_per_block; + } + dst_row += dst_stride / sizeof(*dst_row); + } +} + +void +util_format_rgtc2_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + util_format_rxtc2_unorm_pack_rgba_float(dst_row, dst_stride, src_row, src_stride, width, height, 1); +} + +void +util_format_rgtc2_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y, i, j; + int block_size = 16; + for(y = 0; y < height; y += 4) { + const uint8_t *src = src_row; + for(x = 0; x < width; x += 4) { + for(j = 0; j < 4; ++j) { + for(i = 0; i < 4; ++i) { + float *dst = dst_row + (y + j)*dst_stride/sizeof(*dst_row) + (x + i)*4; + uint8_t tmp_r, tmp_g; + u_format_unsigned_fetch_texel_rgtc(0, src, i, j, &tmp_r, 2); + u_format_unsigned_fetch_texel_rgtc(0, src + 8, i, j, &tmp_g, 2); + dst[0] = ubyte_to_float(tmp_r); + dst[1] = ubyte_to_float(tmp_g); + dst[2] = 0.0; + dst[3] = 1.0; + } + } + src += block_size; + } + src_row += src_stride; + } +} + +void +util_format_rgtc2_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint8_t tmp_r, tmp_g; + u_format_unsigned_fetch_texel_rgtc(0, src, i, j, &tmp_r, 2); + u_format_unsigned_fetch_texel_rgtc(0, src + 8, i, j, &tmp_g, 2); + dst[0] = ubyte_to_float(tmp_r); + dst[1] = ubyte_to_float(tmp_g); + dst[2] = 0.0; + dst[3] = 1.0; +} + + +void +util_format_rgtc2_snorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j) +{ + fprintf(stderr,"%s\n", __func__); +} + +void +util_format_rgtc2_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + fprintf(stderr,"%s\n", __func__); +} + +void +util_format_rgtc2_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + fprintf(stderr,"%s\n", __func__); +} + +void +util_format_rgtc2_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + unsigned x, y, i, j; + int block_size = 16; + for(y = 0; y < height; y += 4) { + const int8_t *src = (int8_t *)src_row; + for(x = 0; x < width; x += 4) { + for(j = 0; j < 4; ++j) { + for(i = 0; i < 4; ++i) { + float *dst = dst_row + (y + j)*dst_stride/sizeof(*dst_row) + (x + i)*4; + int8_t tmp_r, tmp_g; + u_format_signed_fetch_texel_rgtc(0, src, i, j, &tmp_r, 2); + u_format_signed_fetch_texel_rgtc(0, src + 8, i, j, &tmp_g, 2); + dst[0] = byte_to_float_tex(tmp_r); + dst[1] = byte_to_float_tex(tmp_g); + dst[2] = 0.0; + dst[3] = 1.0; + } + } + src += block_size; + } + src_row += src_stride; + } +} + +void +util_format_rxtc2_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height, unsigned chan2off) +{ + const unsigned bw = 4, bh = 4, bytes_per_block = 16; + unsigned x, y, i, j; + + for(y = 0; y < height; y += bh) { + int8_t *dst = (int8_t *)dst_row; + for(x = 0; x < width; x += bw) { + int8_t tmp_r[4][4]; /* [bh][bw][comps] */ + int8_t tmp_g[4][4]; /* [bh][bw][comps] */ + for(j = 0; j < bh; ++j) { + for(i = 0; i < bw; ++i) { + tmp_r[j][i] = float_to_byte_tex(src_row[(y + j)*src_stride/sizeof(*src_row) + (x + i)*4]); + tmp_g[j][i] = float_to_byte_tex(src_row[(y + j)*src_stride/sizeof(*src_row) + (x + i)*4 + chan2off]); + } + } + u_format_signed_encode_rgtc_chan(dst, tmp_r, 4, 4); + u_format_signed_encode_rgtc_chan(dst + 8, tmp_g, 4, 4); + dst += bytes_per_block; + } + dst_row += dst_stride / sizeof(*dst_row); + } +} + +void +util_format_rgtc2_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + util_format_rxtc2_snorm_pack_rgba_float(dst_row, dst_stride, src_row, src_stride, width, height, 1); +} + +void +util_format_rgtc2_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + int8_t tmp_r, tmp_g; + u_format_signed_fetch_texel_rgtc(0, (int8_t *)src, i, j, &tmp_r, 2); + u_format_signed_fetch_texel_rgtc(0, (int8_t *)src + 8, i, j, &tmp_g, 2); + dst[0] = byte_to_float_tex(tmp_r); + dst[1] = byte_to_float_tex(tmp_g); + dst[2] = 0.0; + dst[3] = 1.0; +} + + +#define TAG(x) u_format_unsigned_##x +#define TYPE uint8_t +#define T_MIN 0 +#define T_MAX 255 + +#include "../../../mesa/main/texcompress_rgtc_tmp.h" + +#undef TYPE +#undef TAG +#undef T_MIN +#undef T_MAX + + +#define TAG(x) u_format_signed_##x +#define TYPE int8_t +#define T_MIN (int8_t)-128 +#define T_MAX (int8_t)127 + +#include "../../../mesa/main/texcompress_rgtc_tmp.h" + +#undef TYPE +#undef TAG +#undef T_MIN +#undef T_MAX diff --git a/mesalib/src/gallium/auxiliary/util/u_format_rgtc.h b/mesalib/src/gallium/auxiliary/util/u_format_rgtc.h new file mode 100644 index 000000000..723c9c89a --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_format_rgtc.h @@ -0,0 +1,114 @@ +/************************************************************************** + * + * Copyright 2011 Red Hat 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 SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 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 U_FORMAT_RGTC_H_ +#define U_FORMAT_RGTC_H_ + +void +util_format_rgtc1_unorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j); + +void +util_format_rgtc1_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_rgtc1_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_rgtc1_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_rgtc1_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_rgtc1_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j); + + + +void +util_format_rgtc1_snorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j); + +void +util_format_rgtc1_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_rgtc1_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_rgtc1_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_rgtc1_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_rgtc1_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j); + + +void +util_format_rgtc2_unorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j); + +void +util_format_rgtc2_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_rgtc2_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_rxtc2_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height, unsigned chan2off); + +void +util_format_rgtc2_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_rgtc2_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_rgtc2_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j); + + +void +util_format_rgtc2_snorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j); + +void +util_format_rgtc2_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_rgtc2_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_rgtc2_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_rxtc2_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height, unsigned chan2off); + +void +util_format_rgtc2_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_rgtc2_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j); + + +#endif diff --git a/mesalib/src/gallium/auxiliary/util/u_format_s3tc.c b/mesalib/src/gallium/auxiliary/util/u_format_s3tc.c new file mode 100644 index 000000000..f070a0cae --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_format_s3tc.c @@ -0,0 +1,728 @@ +/************************************************************************** + * + * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. + * Copyright (c) 2008 VMware, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "u_dl.h" +#include "u_math.h" +#include "u_format.h" +#include "u_format_s3tc.h" + + +#if defined(_WIN32) || defined(WIN32) +#define DXTN_LIBNAME "dxtn.dll" +#elif defined(__APPLE__) +#define DXTN_LIBNAME "libtxc_dxtn.dylib" +#else +#define DXTN_LIBNAME "libtxc_dxtn.so" +#endif + + +static void +util_format_dxt1_rgb_fetch_stub(int src_stride, + const uint8_t *src, + int col, int row, + uint8_t *dst) +{ + assert(0); +} + + +static void +util_format_dxt1_rgba_fetch_stub(int src_stride, + const uint8_t *src, + int col, int row, + uint8_t *dst ) +{ + assert(0); +} + + +static void +util_format_dxt3_rgba_fetch_stub(int src_stride, + const uint8_t *src, + int col, int row, + uint8_t *dst ) +{ + assert(0); +} + + +static void +util_format_dxt5_rgba_fetch_stub(int src_stride, + const uint8_t *src, + int col, int row, + uint8_t *dst ) +{ + assert(0); +} + + +static void +util_format_dxtn_pack_stub(int src_comps, + int width, int height, + const uint8_t *src, + enum util_format_dxtn dst_format, + uint8_t *dst, + int dst_stride) +{ + assert(0); +} + + +boolean util_format_s3tc_enabled = FALSE; + +util_format_dxtn_fetch_t util_format_dxt1_rgb_fetch = util_format_dxt1_rgb_fetch_stub; +util_format_dxtn_fetch_t util_format_dxt1_rgba_fetch = util_format_dxt1_rgba_fetch_stub; +util_format_dxtn_fetch_t util_format_dxt3_rgba_fetch = util_format_dxt3_rgba_fetch_stub; +util_format_dxtn_fetch_t util_format_dxt5_rgba_fetch = util_format_dxt5_rgba_fetch_stub; + +util_format_dxtn_pack_t util_format_dxtn_pack = util_format_dxtn_pack_stub; + + +void +util_format_s3tc_init(void) +{ + static boolean first_time = TRUE; + struct util_dl_library *library = NULL; + util_dl_proc fetch_2d_texel_rgb_dxt1; + util_dl_proc fetch_2d_texel_rgba_dxt1; + util_dl_proc fetch_2d_texel_rgba_dxt3; + util_dl_proc fetch_2d_texel_rgba_dxt5; + util_dl_proc tx_compress_dxtn; + + if (!first_time) + return; + first_time = FALSE; + + if (util_format_s3tc_enabled) + return; + + library = util_dl_open(DXTN_LIBNAME); + if (!library) { + debug_printf("couldn't open " DXTN_LIBNAME ", software DXTn " + "compression/decompression unavailable\n"); + return; + } + + fetch_2d_texel_rgb_dxt1 = + util_dl_get_proc_address(library, "fetch_2d_texel_rgb_dxt1"); + fetch_2d_texel_rgba_dxt1 = + util_dl_get_proc_address(library, "fetch_2d_texel_rgba_dxt1"); + fetch_2d_texel_rgba_dxt3 = + util_dl_get_proc_address(library, "fetch_2d_texel_rgba_dxt3"); + fetch_2d_texel_rgba_dxt5 = + util_dl_get_proc_address(library, "fetch_2d_texel_rgba_dxt5"); + tx_compress_dxtn = + util_dl_get_proc_address(library, "tx_compress_dxtn"); + + if (!util_format_dxt1_rgb_fetch || + !util_format_dxt1_rgba_fetch || + !util_format_dxt3_rgba_fetch || + !util_format_dxt5_rgba_fetch || + !util_format_dxtn_pack) { + debug_printf("couldn't reference all symbols in " DXTN_LIBNAME + ", software DXTn compression/decompression " + "unavailable\n"); + util_dl_close(library); + return; + } + + util_format_dxt1_rgb_fetch = (util_format_dxtn_fetch_t)fetch_2d_texel_rgb_dxt1; + util_format_dxt1_rgba_fetch = (util_format_dxtn_fetch_t)fetch_2d_texel_rgba_dxt1; + util_format_dxt3_rgba_fetch = (util_format_dxtn_fetch_t)fetch_2d_texel_rgba_dxt3; + util_format_dxt5_rgba_fetch = (util_format_dxtn_fetch_t)fetch_2d_texel_rgba_dxt5; + util_format_dxtn_pack = (util_format_dxtn_pack_t)tx_compress_dxtn; + util_format_s3tc_enabled = TRUE; +} + + +/* + * Pixel fetch. + */ + +void +util_format_dxt1_rgb_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j) +{ + util_format_dxt1_rgb_fetch(0, src, i, j, dst); +} + +void +util_format_dxt1_rgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j) +{ + util_format_dxt1_rgba_fetch(0, src, i, j, dst); +} + +void +util_format_dxt3_rgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j) +{ + util_format_dxt3_rgba_fetch(0, src, i, j, dst); +} + +void +util_format_dxt5_rgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j) +{ + util_format_dxt5_rgba_fetch(0, src, i, j, dst); +} + +void +util_format_dxt1_rgb_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint8_t tmp[4]; + util_format_dxt1_rgb_fetch(0, src, i, j, tmp); + dst[0] = ubyte_to_float(tmp[0]); + dst[1] = ubyte_to_float(tmp[1]); + dst[2] = ubyte_to_float(tmp[2]); + dst[3] = 1.0; +} + +void +util_format_dxt1_rgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint8_t tmp[4]; + util_format_dxt1_rgba_fetch(0, src, i, j, tmp); + dst[0] = ubyte_to_float(tmp[0]); + dst[1] = ubyte_to_float(tmp[1]); + dst[2] = ubyte_to_float(tmp[2]); + dst[3] = ubyte_to_float(tmp[3]); +} + +void +util_format_dxt3_rgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint8_t tmp[4]; + util_format_dxt3_rgba_fetch(0, src, i, j, tmp); + dst[0] = ubyte_to_float(tmp[0]); + dst[1] = ubyte_to_float(tmp[1]); + dst[2] = ubyte_to_float(tmp[2]); + dst[3] = ubyte_to_float(tmp[3]); +} + +void +util_format_dxt5_rgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + uint8_t tmp[4]; + util_format_dxt5_rgba_fetch(0, src, i, j, tmp); + dst[0] = ubyte_to_float(tmp[0]); + dst[1] = ubyte_to_float(tmp[1]); + dst[2] = ubyte_to_float(tmp[2]); + dst[3] = ubyte_to_float(tmp[3]); +} + + +/* + * Block decompression. + */ + +static INLINE void +util_format_dxtn_rgb_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height, + util_format_dxtn_fetch_t fetch, + unsigned block_size) +{ + const unsigned bw = 4, bh = 4, comps = 4; + unsigned x, y, i, j; + for(y = 0; y < height; y += bh) { + const uint8_t *src = src_row; + for(x = 0; x < width; x += bw) { + for(j = 0; j < bh; ++j) { + for(i = 0; i < bw; ++i) { + uint8_t *dst = dst_row + (y + j)*dst_stride/sizeof(*dst_row) + (x + i)*comps; + fetch(0, src, i, j, dst); + } + } + src += block_size; + } + src_row += src_stride; + } +} + +void +util_format_dxt1_rgb_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + util_format_dxtn_rgb_unpack_rgba_8unorm(dst_row, dst_stride, + src_row, src_stride, + width, height, + util_format_dxt1_rgb_fetch, 8); +} + +void +util_format_dxt1_rgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + util_format_dxtn_rgb_unpack_rgba_8unorm(dst_row, dst_stride, + src_row, src_stride, + width, height, + util_format_dxt1_rgba_fetch, 8); +} + +void +util_format_dxt3_rgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + util_format_dxtn_rgb_unpack_rgba_8unorm(dst_row, dst_stride, + src_row, src_stride, + width, height, + util_format_dxt3_rgba_fetch, 16); +} + +void +util_format_dxt5_rgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + util_format_dxtn_rgb_unpack_rgba_8unorm(dst_row, dst_stride, + src_row, src_stride, + width, height, + util_format_dxt5_rgba_fetch, 16); +} + +static INLINE void +util_format_dxtn_rgb_unpack_rgba_float(float *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height, + util_format_dxtn_fetch_t fetch, + unsigned block_size) +{ + unsigned x, y, i, j; + for(y = 0; y < height; y += 4) { + const uint8_t *src = src_row; + for(x = 0; x < width; x += 4) { + for(j = 0; j < 4; ++j) { + for(i = 0; i < 4; ++i) { + float *dst = dst_row + (y + j)*dst_stride/sizeof(*dst_row) + (x + i)*4; + uint8_t tmp[4]; + fetch(0, src, i, j, tmp); + dst[0] = ubyte_to_float(tmp[0]); + dst[1] = ubyte_to_float(tmp[1]); + dst[2] = ubyte_to_float(tmp[2]); + dst[3] = ubyte_to_float(tmp[3]); + } + } + src += block_size; + } + src_row += src_stride; + } +} + +void +util_format_dxt1_rgb_unpack_rgba_float(float *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + util_format_dxtn_rgb_unpack_rgba_float(dst_row, dst_stride, + src_row, src_stride, + width, height, + util_format_dxt1_rgb_fetch, 8); +} + +void +util_format_dxt1_rgba_unpack_rgba_float(float *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + util_format_dxtn_rgb_unpack_rgba_float(dst_row, dst_stride, + src_row, src_stride, + width, height, + util_format_dxt1_rgba_fetch, 8); +} + +void +util_format_dxt3_rgba_unpack_rgba_float(float *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + util_format_dxtn_rgb_unpack_rgba_float(dst_row, dst_stride, + src_row, src_stride, + width, height, + util_format_dxt3_rgba_fetch, 16); +} + +void +util_format_dxt5_rgba_unpack_rgba_float(float *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + util_format_dxtn_rgb_unpack_rgba_float(dst_row, dst_stride, + src_row, src_stride, + width, height, + util_format_dxt5_rgba_fetch, 16); +} + + +/* + * Block compression. + */ + +void +util_format_dxt1_rgb_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src, unsigned src_stride, + unsigned width, unsigned height) +{ + const unsigned bw = 4, bh = 4, bytes_per_block = 8; + unsigned x, y, i, j, k; + for(y = 0; y < height; y += bh) { + uint8_t *dst = dst_row; + for(x = 0; x < width; x += bw) { + uint8_t tmp[4][4][3]; /* [bh][bw][comps] */ + for(j = 0; j < bh; ++j) { + for(i = 0; i < bw; ++i) { + for(k = 0; k < 3; ++k) { + tmp[j][i][k] = src[(y + j)*src_stride/sizeof(*src) + (x + i)*4 + k]; + } + } + } + util_format_dxtn_pack(3, 4, 4, &tmp[0][0][0], UTIL_FORMAT_DXT1_RGB, dst, 0); + dst += bytes_per_block; + } + dst_row += dst_stride / sizeof(*dst_row); + } +} + +void +util_format_dxt1_rgba_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src, unsigned src_stride, + unsigned width, unsigned height) +{ + const unsigned bw = 4, bh = 4, comps = 4, bytes_per_block = 8; + unsigned x, y, i, j, k; + for(y = 0; y < height; y += bh) { + uint8_t *dst = dst_row; + for(x = 0; x < width; x += bw) { + uint8_t tmp[4][4][4]; /* [bh][bw][comps] */ + for(j = 0; j < bh; ++j) { + for(i = 0; i < bw; ++i) { + for(k = 0; k < comps; ++k) { + tmp[j][i][k] = src[(y + j)*src_stride/sizeof(*src) + (x + i)*comps + k]; + } + } + } + util_format_dxtn_pack(4, 4, 4, &tmp[0][0][0], UTIL_FORMAT_DXT1_RGBA, dst, 0); + dst += bytes_per_block; + } + dst_row += dst_stride / sizeof(*dst_row); + } +} + +void +util_format_dxt3_rgba_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src, unsigned src_stride, + unsigned width, unsigned height) +{ + const unsigned bw = 4, bh = 4, comps = 4, bytes_per_block = 16; + unsigned x, y, i, j, k; + for(y = 0; y < height; y += bh) { + uint8_t *dst = dst_row; + for(x = 0; x < width; x += bw) { + uint8_t tmp[4][4][4]; /* [bh][bw][comps] */ + for(j = 0; j < bh; ++j) { + for(i = 0; i < bw; ++i) { + for(k = 0; k < comps; ++k) { + tmp[j][i][k] = src[(y + j)*src_stride/sizeof(*src) + (x + i)*comps + k]; + } + } + } + util_format_dxtn_pack(4, 4, 4, &tmp[0][0][0], UTIL_FORMAT_DXT3_RGBA, dst, 0); + dst += bytes_per_block; + } + dst_row += dst_stride / sizeof(*dst_row); + } +} + +void +util_format_dxt5_rgba_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src, unsigned src_stride, + unsigned width, unsigned height) +{ + const unsigned bw = 4, bh = 4, comps = 4, bytes_per_block = 16; + unsigned x, y, i, j, k; + + for(y = 0; y < height; y += bh) { + uint8_t *dst = dst_row; + for(x = 0; x < width; x += bw) { + uint8_t tmp[4][4][4]; /* [bh][bw][comps] */ + for(j = 0; j < bh; ++j) { + for(i = 0; i < bw; ++i) { + for(k = 0; k < comps; ++k) { + tmp[j][i][k] = src[(y + j)*src_stride/sizeof(*src) + (x + i)*comps + k]; + } + } + } + util_format_dxtn_pack(4, 4, 4, &tmp[0][0][0], UTIL_FORMAT_DXT5_RGBA, dst, 0); + dst += bytes_per_block; + } + dst_row += dst_stride / sizeof(*dst_row); + } +} + +void +util_format_dxt1_rgb_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, + const float *src, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y, i, j, k; + for(y = 0; y < height; y += 4) { + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 4) { + uint8_t tmp[4][4][3]; + for(j = 0; j < 4; ++j) { + for(i = 0; i < 4; ++i) { + for(k = 0; k < 3; ++k) { + tmp[j][i][k] = float_to_ubyte(src[(y + j)*src_stride/sizeof(*src) + (x+i)*4 + k]); + } + } + } + util_format_dxtn_pack(3, 4, 4, &tmp[0][0][0], UTIL_FORMAT_DXT1_RGB, dst, 0); + dst += 8; + } + dst_row += 4*dst_stride/sizeof(*dst_row); + } +} + +void +util_format_dxt1_rgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, + const float *src, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y, i, j, k; + for(y = 0; y < height; y += 4) { + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 4) { + uint8_t tmp[4][4][4]; + for(j = 0; j < 4; ++j) { + for(i = 0; i < 4; ++i) { + for(k = 0; k < 4; ++k) { + tmp[j][i][k] = float_to_ubyte(src[(y + j)*src_stride/sizeof(*src) + (x+i)*4 + k]); + } + } + } + util_format_dxtn_pack(4, 4, 4, &tmp[0][0][0], UTIL_FORMAT_DXT1_RGBA, dst, 0); + dst += 8; + } + dst_row += 4*dst_stride/sizeof(*dst_row); + } +} + +void +util_format_dxt3_rgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, + const float *src, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y, i, j, k; + for(y = 0; y < height; y += 4) { + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 4) { + uint8_t tmp[4][4][4]; + for(j = 0; j < 4; ++j) { + for(i = 0; i < 4; ++i) { + for(k = 0; k < 4; ++k) { + tmp[j][i][k] = float_to_ubyte(src[(y + j)*src_stride/sizeof(*src) + (x+i)*4 + k]); + } + } + } + util_format_dxtn_pack(4, 4, 4, &tmp[0][0][0], UTIL_FORMAT_DXT3_RGBA, dst, 0); + dst += 16; + } + dst_row += 4*dst_stride/sizeof(*dst_row); + } +} + +void +util_format_dxt5_rgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, + const float *src, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y, i, j, k; + for(y = 0; y < height; y += 4) { + uint8_t *dst = dst_row; + for(x = 0; x < width; x += 4) { + uint8_t tmp[4][4][4]; + for(j = 0; j < 4; ++j) { + for(i = 0; i < 4; ++i) { + for(k = 0; k < 4; ++k) { + tmp[j][i][k] = float_to_ubyte(src[(y + j)*src_stride/sizeof(*src) + (x+i)*4 + k]); + } + } + } + util_format_dxtn_pack(4, 4, 4, &tmp[0][0][0], UTIL_FORMAT_DXT5_RGBA, dst, 0); + dst += 16; + } + dst_row += 4*dst_stride/sizeof(*dst_row); + } +} + + +/* + * SRGB variants. + * + * FIXME: shunts to RGB for now + */ + +void +util_format_dxt1_srgb_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + util_format_dxt1_rgb_unpack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, width, height); +} + +void +util_format_dxt1_srgb_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + util_format_dxt1_rgb_pack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, width, height); +} + +void +util_format_dxt1_srgb_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j) +{ + util_format_dxt1_rgb_fetch_rgba_8unorm(dst, src, i, j); +} + +void +util_format_dxt1_srgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + util_format_dxt1_rgba_unpack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, width, height); +} + +void +util_format_dxt1_srgba_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + util_format_dxt1_rgba_pack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, width, height); +} + +void +util_format_dxt1_srgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j) +{ + util_format_dxt1_rgba_fetch_rgba_8unorm(dst, src, i, j); +} + +void +util_format_dxt3_srgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + util_format_dxt3_rgba_unpack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, width, height); +} + +void +util_format_dxt3_srgba_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + util_format_dxt3_rgba_pack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, width, height); +} + +void +util_format_dxt3_srgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j) +{ + util_format_dxt3_rgba_fetch_rgba_8unorm(dst, src, i, j); +} + +void +util_format_dxt5_srgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + util_format_dxt5_rgba_unpack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, width, height); +} + +void +util_format_dxt5_srgba_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + util_format_dxt5_rgba_pack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, width, height); +} + +void +util_format_dxt5_srgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j) +{ + util_format_dxt5_rgba_fetch_rgba_8unorm(dst, src, i, j); +} + +void +util_format_dxt1_srgb_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + util_format_dxt1_rgb_unpack_rgba_float(dst_row, dst_stride, src_row, src_stride, width, height); +} + +void +util_format_dxt1_srgb_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + util_format_dxt1_rgb_pack_rgba_float(dst_row, dst_stride, src_row, src_stride, width, height); +} + +void +util_format_dxt1_srgb_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + util_format_dxt1_rgb_fetch_rgba_float(dst, src, i, j); +} + +void +util_format_dxt1_srgba_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + util_format_dxt1_rgba_unpack_rgba_float(dst_row, dst_stride, src_row, src_stride, width, height); +} + +void +util_format_dxt1_srgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + util_format_dxt1_rgba_pack_rgba_float(dst_row, dst_stride, src_row, src_stride, width, height); +} + +void +util_format_dxt1_srgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + util_format_dxt1_rgba_fetch_rgba_float(dst, src, i, j); +} + +void +util_format_dxt3_srgba_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + util_format_dxt3_rgba_unpack_rgba_float(dst_row, dst_stride, src_row, src_stride, width, height); +} + +void +util_format_dxt3_srgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + util_format_dxt3_rgba_pack_rgba_float(dst_row, dst_stride, src_row, src_stride, width, height); +} + +void +util_format_dxt3_srgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + util_format_dxt3_rgba_fetch_rgba_float(dst, src, i, j); +} + +void +util_format_dxt5_srgba_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + util_format_dxt5_rgba_unpack_rgba_float(dst_row, dst_stride, src_row, src_stride, width, height); +} + +void +util_format_dxt5_srgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + util_format_dxt5_rgba_pack_rgba_float(dst_row, dst_stride, src_row, src_stride, width, height); +} + +void +util_format_dxt5_srgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j) +{ + util_format_dxt5_rgba_fetch_rgba_float(dst, src, i, j); +} + diff --git a/mesalib/src/gallium/auxiliary/util/u_format_s3tc.h b/mesalib/src/gallium/auxiliary/util/u_format_s3tc.h new file mode 100644 index 000000000..887d11079 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_format_s3tc.h @@ -0,0 +1,218 @@ +/************************************************************************** + * + * 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 SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 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 U_FORMAT_S3TC_H_ +#define U_FORMAT_S3TC_H_ + + +#include "pipe/p_compiler.h" + + +enum util_format_dxtn { + UTIL_FORMAT_DXT1_RGB = 0x83F0, + UTIL_FORMAT_DXT1_RGBA = 0x83F1, + UTIL_FORMAT_DXT3_RGBA = 0x83F2, + UTIL_FORMAT_DXT5_RGBA = 0x83F3 +}; + + +typedef void +(*util_format_dxtn_fetch_t)( int src_stride, + const uint8_t *src, + int col, int row, + uint8_t *dst ); + +typedef void +(*util_format_dxtn_pack_t)( int src_comps, + int width, int height, + const uint8_t *src, + enum util_format_dxtn dst_format, + uint8_t *dst, + int dst_stride); + +extern boolean util_format_s3tc_enabled; + +extern util_format_dxtn_fetch_t util_format_dxt1_rgb_fetch; +extern util_format_dxtn_fetch_t util_format_dxt1_rgba_fetch; +extern util_format_dxtn_fetch_t util_format_dxt3_rgba_fetch; +extern util_format_dxtn_fetch_t util_format_dxt5_rgba_fetch; + +extern util_format_dxtn_pack_t util_format_dxtn_pack; + + +void +util_format_s3tc_init(void); + + +void +util_format_dxt1_rgb_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_dxt1_rgb_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_dxt1_rgb_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j); + +void +util_format_dxt1_rgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_dxt1_rgba_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_dxt1_rgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j); + +void +util_format_dxt3_rgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_dxt3_rgba_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_dxt3_rgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j); + +void +util_format_dxt5_rgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_dxt5_rgba_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_dxt5_rgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j); + +void +util_format_dxt1_srgb_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_dxt1_srgb_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_dxt1_srgb_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j); + +void +util_format_dxt1_srgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_dxt1_srgba_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_dxt1_srgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j); + +void +util_format_dxt3_srgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_dxt3_srgba_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_dxt3_srgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j); + +void +util_format_dxt5_srgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_dxt5_srgba_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_dxt5_srgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j); + + +void +util_format_dxt1_rgb_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_dxt1_rgb_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_dxt1_rgb_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j); + +void +util_format_dxt1_rgba_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_dxt1_rgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_dxt1_rgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j); + +void +util_format_dxt3_rgba_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_dxt3_rgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_dxt3_rgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j); + +void +util_format_dxt5_rgba_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_dxt5_rgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_dxt5_rgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j); + +void +util_format_dxt1_srgb_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_dxt1_srgb_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_dxt1_srgb_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j); + +void +util_format_dxt1_srgba_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_dxt1_srgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_dxt1_srgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j); + +void +util_format_dxt3_srgba_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_dxt3_srgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_dxt3_srgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j); + +void +util_format_dxt5_srgba_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_dxt5_srgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_dxt5_srgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j); + + +#endif /* U_FORMAT_S3TC_H_ */ diff --git a/mesalib/src/gallium/auxiliary/util/u_format_srgb.h b/mesalib/src/gallium/auxiliary/util/u_format_srgb.h new file mode 100644 index 000000000..a1b12e9de --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_format_srgb.h @@ -0,0 +1,106 @@ +/************************************************************************** + * + * 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 SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 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. + * + **************************************************************************/ + +/** + * @file + * SRGB translation. + * + * @author Brian Paul + * @author Michal Krol + * @author Jose Fonseca + */ + +#ifndef U_FORMAT_SRGB_H_ +#define U_FORMAT_SRGB_H_ + + +#include "pipe/p_compiler.h" +#include "u_math.h" + + +extern const float +util_format_srgb_8unorm_to_linear_float_table[256]; + +extern const uint8_t +util_format_srgb_to_linear_8unorm_table[256]; + +extern const uint8_t +util_format_linear_to_srgb_8unorm_table[256]; + + +/** + * Convert a unclamped linear float to srgb value in the [0,255]. + * XXX this hasn't been tested (render to srgb surface). + * XXX this needs optimization. + */ +static INLINE uint8_t +util_format_linear_float_to_srgb_8unorm(float x) +{ + if (x >= 1.0f) + return 255; + else if (x >= 0.0031308f) + return float_to_ubyte(1.055f * powf(x, 0.41666f) - 0.055f); + else if (x > 0.0f) + return float_to_ubyte(12.92f * x); + else + return 0; +} + + +/** + * Convert an 8-bit sRGB value from non-linear space to a + * linear RGB value in [0, 1]. + * Implemented with a 256-entry lookup table. + */ +static INLINE float +util_format_srgb_8unorm_to_linear_float(uint8_t x) +{ + return util_format_srgb_8unorm_to_linear_float_table[x]; +} + + +/** + * Convert a 8bit normalized value from linear to srgb. + */ +static INLINE uint8_t +util_format_linear_to_srgb_8unorm(uint8_t x) +{ + return util_format_linear_to_srgb_8unorm_table[x]; +} + + +/** + * Convert a 8bit normalized value from srgb to linear. + */ +static INLINE uint8_t +util_format_srgb_to_linear_8unorm(uint8_t x) +{ + return util_format_srgb_to_linear_8unorm_table[x]; +} + + +#endif /* U_FORMAT_SRGB_H_ */ diff --git a/mesalib/src/gallium/auxiliary/util/u_format_srgb.py b/mesalib/src/gallium/auxiliary/util/u_format_srgb.py new file mode 100644 index 000000000..c7b0464d4 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_format_srgb.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python + +CopyRight = ''' +/************************************************************************** + * + * 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. + * + **************************************************************************/ + +/** + * @file + * SRGB translation. + * + * @author Brian Paul + * @author Michal Krol + * @author Jose Fonseca + */ +''' + + +import math + + +def srgb_to_linear(x): + if x <= 0.04045: + return x / 12.92 + else: + return math.pow((x + 0.055) / 1.055, 2.4) + + +def linear_to_srgb(x): + if x >= 0.0031308: + return 1.055 * math.pow(x, 0.41666) - 0.055 + else: + return 12.92 * x + +def generate_srgb_tables(): + print 'const float' + print 'util_format_srgb_8unorm_to_linear_float_table[256] = {' + for j in range(0, 256, 4): + print ' ', + for i in range(j, j + 4): + print '%.7e,' % (srgb_to_linear(i / 255.0),), + print + print '};' + print + print 'const uint8_t' + print 'util_format_srgb_to_linear_8unorm_table[256] = {' + for j in range(0, 256, 16): + print ' ', + for i in range(j, j + 16): + print '%3u,' % (int(srgb_to_linear(i / 255.0) * 255.0 + 0.5),), + print + print '};' + print + print 'const uint8_t' + print 'util_format_linear_to_srgb_8unorm_table[256] = {' + for j in range(0, 256, 16): + print ' ', + for i in range(j, j + 16): + print '%3u,' % (int(linear_to_srgb(i / 255.0) * 255.0 + 0.5),), + print + print '};' + print + + +def main(): + print '/* This file is autogenerated by u_format_srgb.py. Do not edit directly. */' + print + # This will print the copyright message on the top of this file + print CopyRight.strip() + print + print '#include "u_format_srgb.h"' + print + generate_srgb_tables() + + +if __name__ == '__main__': + main() diff --git a/mesalib/src/gallium/auxiliary/util/u_format_table.py b/mesalib/src/gallium/auxiliary/util/u_format_table.py new file mode 100644 index 000000000..addc47481 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_format_table.py @@ -0,0 +1,197 @@ +#!/usr/bin/env python + +CopyRight = ''' +/************************************************************************** + * + * 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. + * + **************************************************************************/ +''' + + +import sys + +from u_format_parse import * +import u_format_pack + + +def layout_map(layout): + return 'UTIL_FORMAT_LAYOUT_' + str(layout).upper() + + +def colorspace_map(colorspace): + return 'UTIL_FORMAT_COLORSPACE_' + str(colorspace).upper() + + +colorspace_channels_map = { + 'rgb': ['r', 'g', 'b', 'a'], + 'srgb': ['sr', 'sg', 'sb', 'a'], + 'zs': ['z', 's'], + 'yuv': ['y', 'u', 'v'], +} + + +type_map = { + VOID: "UTIL_FORMAT_TYPE_VOID", + UNSIGNED: "UTIL_FORMAT_TYPE_UNSIGNED", + SIGNED: "UTIL_FORMAT_TYPE_SIGNED", + FIXED: "UTIL_FORMAT_TYPE_FIXED", + FLOAT: "UTIL_FORMAT_TYPE_FLOAT", +} + + +def bool_map(value): + if value: + return "TRUE" + else: + return "FALSE" + + +swizzle_map = { + SWIZZLE_X: "UTIL_FORMAT_SWIZZLE_X", + SWIZZLE_Y: "UTIL_FORMAT_SWIZZLE_Y", + SWIZZLE_Z: "UTIL_FORMAT_SWIZZLE_Z", + SWIZZLE_W: "UTIL_FORMAT_SWIZZLE_W", + SWIZZLE_0: "UTIL_FORMAT_SWIZZLE_0", + SWIZZLE_1: "UTIL_FORMAT_SWIZZLE_1", + SWIZZLE_NONE: "UTIL_FORMAT_SWIZZLE_NONE", +} + + +def write_format_table(formats): + print '/* This file is autogenerated by u_format_table.py from u_format.csv. Do not edit directly. */' + print + # This will print the copyright message on the top of this file + print CopyRight.strip() + print + print '#include "u_format.h"' + print '#include "u_format_s3tc.h"' + print '#include "u_format_rgtc.h"' + print '#include "u_format_latc.h"' + print + + u_format_pack.generate(formats) + + for format in formats: + print 'const struct util_format_description' + print 'util_format_%s_description = {' % (format.short_name(),) + print " %s," % (format.name,) + print " \"%s\"," % (format.name,) + print " \"%s\"," % (format.short_name(),) + print " {%u, %u, %u},\t/* block */" % (format.block_width, format.block_height, format.block_size()) + print " %s," % (layout_map(format.layout),) + print " %u,\t/* nr_channels */" % (format.nr_channels(),) + print " %s,\t/* is_array */" % (bool_map(format.is_array()),) + print " %s,\t/* is_bitmask */" % (bool_map(format.is_bitmask()),) + print " %s,\t/* is_mixed */" % (bool_map(format.is_mixed()),) + print " {" + for i in range(4): + channel = format.channels[i] + if i < 3: + sep = "," + else: + sep = "" + if channel.size: + print " {%s, %s, %u}%s\t/* %s = %s */" % (type_map[channel.type], bool_map(channel.norm), channel.size, sep, "xyzw"[i], channel.name) + else: + print " {0, 0, 0}%s" % (sep,) + print " }," + print " {" + for i in range(4): + swizzle = format.swizzles[i] + if i < 3: + sep = "," + else: + sep = "" + try: + comment = colorspace_channels_map[format.colorspace][i] + except (KeyError, IndexError): + comment = 'ignored' + print " %s%s\t/* %s */" % (swizzle_map[swizzle], sep, comment) + print " }," + print " %s," % (colorspace_map(format.colorspace),) + if format.colorspace != ZS: + print " &util_format_%s_unpack_rgba_8unorm," % format.short_name() + print " &util_format_%s_pack_rgba_8unorm," % format.short_name() + if format.layout == 's3tc' or format.layout == 'rgtc': + print " &util_format_%s_fetch_rgba_8unorm," % format.short_name() + else: + print " NULL, /* fetch_rgba_8unorm */" + print " &util_format_%s_unpack_rgba_float," % format.short_name() + print " &util_format_%s_pack_rgba_float," % format.short_name() + print " &util_format_%s_fetch_rgba_float," % format.short_name() + else: + print " NULL, /* unpack_rgba_8unorm */" + print " NULL, /* pack_rgba_8unorm */" + print " NULL, /* fetch_rgba_8unorm */" + print " NULL, /* unpack_rgba_float */" + print " NULL, /* pack_rgba_float */" + print " NULL, /* fetch_rgba_float */" + if format.colorspace == ZS and format.swizzles[0] != SWIZZLE_NONE: + print " &util_format_%s_unpack_z_32unorm," % format.short_name() + print " &util_format_%s_pack_z_32unorm," % format.short_name() + print " &util_format_%s_unpack_z_float," % format.short_name() + print " &util_format_%s_pack_z_float," % format.short_name() + else: + print " NULL, /* unpack_z_32unorm */" + print " NULL, /* pack_z_32unorm */" + print " NULL, /* unpack_z_float */" + print " NULL, /* pack_z_float */" + if format.colorspace == ZS and format.swizzles[1] != SWIZZLE_NONE: + print " &util_format_%s_unpack_s_8uscaled," % format.short_name() + print " &util_format_%s_pack_s_8uscaled" % format.short_name() + else: + print " NULL, /* unpack_s_8uscaled */" + print " NULL /* pack_s_8uscaled */" + print "};" + print + + print "const struct util_format_description *" + print "util_format_description(enum pipe_format format)" + print "{" + print " if (format >= PIPE_FORMAT_COUNT) {" + print " return NULL;" + print " }" + print + print " switch (format) {" + for format in formats: + print " case %s:" % format.name + print " return &util_format_%s_description;" % (format.short_name(),) + print " default:" + print " return NULL;" + print " }" + print "}" + print + + +def main(): + + formats = [] + for arg in sys.argv[1:]: + formats.extend(parse(arg)) + write_format_table(formats) + + +if __name__ == '__main__': + main() diff --git a/mesalib/src/gallium/auxiliary/util/u_format_tests.c b/mesalib/src/gallium/auxiliary/util/u_format_tests.c new file mode 100644 index 000000000..2130c49e1 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_format_tests.c @@ -0,0 +1,970 @@ +/************************************************************************** + * + * Copyright 2009-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 "u_memory.h" +#include "u_format_tests.h" + + +/* + * Helper macros to create the packed bytes for longer words. + */ + +#define PACKED_1x8(x) {x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#define PACKED_2x8(x, y) {x, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#define PACKED_3x8(x, y, z) {x, y, z, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#define PACKED_4x8(x, y, z, w) {x, y, z, w, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#define PACKED_8x8(a, b, c, d, e, f, g, h) {a, b, c, d, e, f, g, h, 0, 0, 0, 0, 0, 0, 0, 0} + +#define PACKED_1x16(x) {(x) & 0xff, (x) >> 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#define PACKED_2x16(x, y) {(x) & 0xff, (x) >> 8, (y) & 0xff, (y) >> 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#define PACKED_3x16(x, y, z) {(x) & 0xff, (x) >> 8, (y) & 0xff, (y) >> 8, (z) & 0xff, (z) >> 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#define PACKED_4x16(x, y, z, w) {(x) & 0xff, (x) >> 8, (y) & 0xff, (y) >> 8, (z) & 0xff, (z) >> 8, (w) & 0xff, (w) >> 8, 0, 0, 0, 0, 0, 0, 0, 0} + +#define PACKED_1x32(x) {(x) & 0xff, ((x) >> 8) & 0xff, ((x) >> 16) & 0xff, (x) >> 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#define PACKED_2x32(x, y) {(x) & 0xff, ((x) >> 8) & 0xff, ((x) >> 16) & 0xff, (x) >> 24, (y) & 0xff, ((y) >> 8) & 0xff, ((y) >> 16) & 0xff, (y) >> 24, 0, 0, 0, 0, 0, 0, 0, 0} +#define PACKED_3x32(x, y, z) {(x) & 0xff, ((x) >> 8) & 0xff, ((x) >> 16) & 0xff, (x) >> 24, (y) & 0xff, ((y) >> 8) & 0xff, ((y) >> 16) & 0xff, (y) >> 24, (z) & 0xff, ((z) >> 8) & 0xff, ((z) >> 16) & 0xff, (z) >> 24, 0, 0, 0, 0} +#define PACKED_4x32(x, y, z, w) {(x) & 0xff, ((x) >> 8) & 0xff, ((x) >> 16) & 0xff, (x) >> 24, (y) & 0xff, ((y) >> 8) & 0xff, ((y) >> 16) & 0xff, (y) >> 24, (z) & 0xff, ((z) >> 8) & 0xff, ((z) >> 16) & 0xff, (z) >> 24, (w) & 0xff, ((w) >> 8) & 0xff, ((w) >> 16) & 0xff, (w) >> 24} + +#define UNPACKED_1x1(r, g, b, a) \ + {{{r, g, b, a}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, \ + {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, \ + {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, \ + {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}} + +#define UNPACKED_2x1(r0, g0, b0, a0, r1, g1, b1, a1) \ + {{{r0, g0, b0, a0}, {r1, g1, b1, a1}, {0, 0, 0, 0}, {0, 0, 0, 0}}, \ + {{ 0, 0, 0, 0}, { 0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, \ + {{ 0, 0, 0, 0}, { 0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, \ + {{ 0, 0, 0, 0}, { 0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}} + + +/** + * Test cases. + * + * These were manually entered. We could generate these + * + * To keep this to a we cover only the corner cases, which should produce + * good enough coverage since that pixel format transformations are afine for + * non SRGB formats. + */ +const struct util_format_test_case +util_format_test_cases[] = +{ + + /* + * 32-bit rendertarget formats + */ + + {PIPE_FORMAT_B8G8R8A8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_B8G8R8A8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x000000ff), UNPACKED_1x1(0.0, 0.0, 1.0, 0.0)}, + {PIPE_FORMAT_B8G8R8A8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x0000ff00), UNPACKED_1x1(0.0, 1.0, 0.0, 0.0)}, + {PIPE_FORMAT_B8G8R8A8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00ff0000), UNPACKED_1x1(1.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_B8G8R8A8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xff000000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_B8G8R8A8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xffffffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)}, + + {PIPE_FORMAT_B8G8R8X8_UNORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_B8G8R8X8_UNORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0x000000ff), UNPACKED_1x1(0.0, 0.0, 1.0, 1.0)}, + {PIPE_FORMAT_B8G8R8X8_UNORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0x0000ff00), UNPACKED_1x1(0.0, 1.0, 0.0, 1.0)}, + {PIPE_FORMAT_B8G8R8X8_UNORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0x00ff0000), UNPACKED_1x1(1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_B8G8R8X8_UNORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0xff000000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_B8G8R8X8_UNORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0xffffffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)}, + + {PIPE_FORMAT_A8R8G8B8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_A8R8G8B8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x000000ff), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_A8R8G8B8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x0000ff00), UNPACKED_1x1(1.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_A8R8G8B8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00ff0000), UNPACKED_1x1(0.0, 1.0, 0.0, 0.0)}, + {PIPE_FORMAT_A8R8G8B8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xff000000), UNPACKED_1x1(0.0, 0.0, 1.0, 0.0)}, + {PIPE_FORMAT_A8R8G8B8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xffffffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)}, + + {PIPE_FORMAT_X8R8G8B8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_X8R8G8B8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0x000000ff), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_X8R8G8B8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0x0000ff00), UNPACKED_1x1(1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_X8R8G8B8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0x00ff0000), UNPACKED_1x1(0.0, 1.0, 0.0, 1.0)}, + {PIPE_FORMAT_X8R8G8B8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0xff000000), UNPACKED_1x1(0.0, 0.0, 1.0, 1.0)}, + {PIPE_FORMAT_X8R8G8B8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0xffffffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)}, + + {PIPE_FORMAT_A8B8G8R8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_A8B8G8R8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x000000ff), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_A8B8G8R8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x0000ff00), UNPACKED_1x1(0.0, 0.0, 1.0, 0.0)}, + {PIPE_FORMAT_A8B8G8R8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00ff0000), UNPACKED_1x1(0.0, 1.0, 0.0, 0.0)}, + {PIPE_FORMAT_A8B8G8R8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xff000000), UNPACKED_1x1(1.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_A8B8G8R8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xffffffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)}, + + {PIPE_FORMAT_X8B8G8R8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_X8B8G8R8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0x000000ff), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_X8B8G8R8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0x0000ff00), UNPACKED_1x1(0.0, 0.0, 1.0, 1.0)}, + {PIPE_FORMAT_X8B8G8R8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0x00ff0000), UNPACKED_1x1(0.0, 1.0, 0.0, 1.0)}, + {PIPE_FORMAT_X8B8G8R8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0xff000000), UNPACKED_1x1(1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_X8B8G8R8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0xffffffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)}, + + {PIPE_FORMAT_R8G8B8X8_UNORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8B8X8_UNORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0x000000ff), UNPACKED_1x1(1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8B8X8_UNORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0x0000ff00), UNPACKED_1x1(0.0, 1.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8B8X8_UNORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0x00ff0000), UNPACKED_1x1(0.0, 0.0, 1.0, 1.0)}, + {PIPE_FORMAT_R8G8B8X8_UNORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0xff000000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8B8X8_UNORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0xffffffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)}, + + {PIPE_FORMAT_R10G10B10A2_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R10G10B10A2_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x000003ff), UNPACKED_1x1(1.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R10G10B10A2_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x000ffc00), UNPACKED_1x1(0.0, 1.0, 0.0, 0.0)}, + {PIPE_FORMAT_R10G10B10A2_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x3ff00000), UNPACKED_1x1(0.0, 0.0, 1.0, 0.0)}, + {PIPE_FORMAT_R10G10B10A2_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xc0000000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R10G10B10A2_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xffffffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)}, + + {PIPE_FORMAT_B10G10R10A2_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_B10G10R10A2_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x000003ff), UNPACKED_1x1(0.0, 0.0, 1.0, 0.0)}, + {PIPE_FORMAT_B10G10R10A2_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x000ffc00), UNPACKED_1x1(0.0, 1.0, 0.0, 0.0)}, + {PIPE_FORMAT_B10G10R10A2_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x3ff00000), UNPACKED_1x1(1.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_B10G10R10A2_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xc0000000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_B10G10R10A2_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xffffffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)}, + + /* + * 16-bit rendertarget formats + */ + + {PIPE_FORMAT_B5G5R5X1_UNORM, PACKED_1x16(0x7fff), PACKED_1x16(0x0000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_B5G5R5X1_UNORM, PACKED_1x16(0x7fff), PACKED_1x16(0x001f), UNPACKED_1x1(0.0, 0.0, 1.0, 1.0)}, + {PIPE_FORMAT_B5G5R5X1_UNORM, PACKED_1x16(0x7fff), PACKED_1x16(0x03e0), UNPACKED_1x1(0.0, 1.0, 0.0, 1.0)}, + {PIPE_FORMAT_B5G5R5X1_UNORM, PACKED_1x16(0x7fff), PACKED_1x16(0x7c00), UNPACKED_1x1(1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_B5G5R5X1_UNORM, PACKED_1x16(0x7fff), PACKED_1x16(0x7fff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)}, + + {PIPE_FORMAT_B5G5R5A1_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x0000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_B5G5R5A1_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x001f), UNPACKED_1x1(0.0, 0.0, 1.0, 0.0)}, + {PIPE_FORMAT_B5G5R5A1_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x03e0), UNPACKED_1x1(0.0, 1.0, 0.0, 0.0)}, + {PIPE_FORMAT_B5G5R5A1_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x7c00), UNPACKED_1x1(1.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_B5G5R5A1_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x8000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_B5G5R5A1_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0xffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)}, + + {PIPE_FORMAT_B4G4R4X4_UNORM, PACKED_1x16(0x0fff), PACKED_1x16(0x0000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_B4G4R4X4_UNORM, PACKED_1x16(0x0fff), PACKED_1x16(0x000f), UNPACKED_1x1(0.0, 0.0, 1.0, 1.0)}, + {PIPE_FORMAT_B4G4R4X4_UNORM, PACKED_1x16(0x0fff), PACKED_1x16(0x00f0), UNPACKED_1x1(0.0, 1.0, 0.0, 1.0)}, + {PIPE_FORMAT_B4G4R4X4_UNORM, PACKED_1x16(0x0fff), PACKED_1x16(0x0f00), UNPACKED_1x1(1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_B4G4R4X4_UNORM, PACKED_1x16(0x0fff), PACKED_1x16(0x0fff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)}, + + {PIPE_FORMAT_B4G4R4A4_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x0000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_B4G4R4A4_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x000f), UNPACKED_1x1(0.0, 0.0, 1.0, 0.0)}, + {PIPE_FORMAT_B4G4R4A4_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x00f0), UNPACKED_1x1(0.0, 1.0, 0.0, 0.0)}, + {PIPE_FORMAT_B4G4R4A4_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x0f00), UNPACKED_1x1(1.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_B4G4R4A4_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0xf000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_B4G4R4A4_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0xffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)}, + + {PIPE_FORMAT_B5G6R5_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x0000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_B5G6R5_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x001f), UNPACKED_1x1(0.0, 0.0, 1.0, 1.0)}, + {PIPE_FORMAT_B5G6R5_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x07e0), UNPACKED_1x1(0.0, 1.0, 0.0, 1.0)}, + {PIPE_FORMAT_B5G6R5_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0xf800), UNPACKED_1x1(1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_B5G6R5_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0xffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)}, + + /* + * Luminance/intensity/alpha formats + */ + + {PIPE_FORMAT_L8_UNORM, PACKED_1x8(0xff), PACKED_1x8(0x00), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_L8_UNORM, PACKED_1x8(0xff), PACKED_1x8(0xff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)}, + + {PIPE_FORMAT_A8_UNORM, PACKED_1x8(0xff), PACKED_1x8(0x00), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_A8_UNORM, PACKED_1x8(0xff), PACKED_1x8(0xff), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + + {PIPE_FORMAT_I8_UNORM, PACKED_1x8(0xff), PACKED_1x8(0x00), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_I8_UNORM, PACKED_1x8(0xff), PACKED_1x8(0xff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)}, + + {PIPE_FORMAT_L4A4_UNORM, PACKED_1x8(0xff), PACKED_1x8(0x00), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_L4A4_UNORM, PACKED_1x8(0xff), PACKED_1x8(0x0f), UNPACKED_1x1(1.0, 1.0, 1.0, 0.0)}, + {PIPE_FORMAT_L4A4_UNORM, PACKED_1x8(0xff), PACKED_1x8(0xf0), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_L4A4_UNORM, PACKED_1x8(0xff), PACKED_1x8(0xff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)}, + + {PIPE_FORMAT_L8A8_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x0000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_L8A8_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x00ff), UNPACKED_1x1(1.0, 1.0, 1.0, 0.0)}, + {PIPE_FORMAT_L8A8_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0xff00), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_L8A8_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0xffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)}, + + {PIPE_FORMAT_L16_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x0000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_L16_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0xffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)}, + + /* + * SRGB formats + */ + + {PIPE_FORMAT_L8_SRGB, PACKED_1x8(0xff), PACKED_1x8(0x00), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_L8_SRGB, PACKED_1x8(0xff), PACKED_1x8(0xbc), UNPACKED_1x1(0.502886458033, 0.502886458033, 0.502886458033, 1.0)}, + {PIPE_FORMAT_L8_SRGB, PACKED_1x8(0xff), PACKED_1x8(0xff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)}, + + {PIPE_FORMAT_L8A8_SRGB, PACKED_1x16(0xffff), PACKED_1x16(0x0000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_L8A8_SRGB, PACKED_1x16(0xffff), PACKED_1x16(0x00bc), UNPACKED_1x1(0.502886458033, 0.502886458033, 0.502886458033, 0.0)}, + {PIPE_FORMAT_L8A8_SRGB, PACKED_1x16(0xffff), PACKED_1x16(0x00ff), UNPACKED_1x1(1.0, 1.0, 1.0, 0.0)}, + {PIPE_FORMAT_L8A8_SRGB, PACKED_1x16(0xffff), PACKED_1x16(0xcc00), UNPACKED_1x1(0.0, 0.0, 0.0, 0.8)}, + {PIPE_FORMAT_L8A8_SRGB, PACKED_1x16(0xffff), PACKED_1x16(0xff00), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_L8A8_SRGB, PACKED_1x16(0xffff), PACKED_1x16(0xffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)}, + + {PIPE_FORMAT_R8G8B8_SRGB, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0x00), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8B8_SRGB, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0xbc, 0x00, 0x00), UNPACKED_1x1(0.502886458033, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8B8_SRGB, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0xff, 0x00, 0x00), UNPACKED_1x1(1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8B8_SRGB, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0xbc, 0x00), UNPACKED_1x1(0.0, 0.502886458033, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8B8_SRGB, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0xff, 0x00), UNPACKED_1x1(0.0, 1.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8B8_SRGB, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0xbc), UNPACKED_1x1(0.0, 0.0, 0.502886458033, 1.0)}, + {PIPE_FORMAT_R8G8B8_SRGB, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0xff), UNPACKED_1x1(0.0, 0.0, 1.0, 1.0)}, + {PIPE_FORMAT_R8G8B8_SRGB, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0xff, 0xff, 0xff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)}, + + {PIPE_FORMAT_R8G8B8A8_SRGB, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0x00), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R8G8B8A8_SRGB, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0xbc, 0x00, 0x00, 0x00), UNPACKED_1x1(0.502886458033, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R8G8B8A8_SRGB, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0xff, 0x00, 0x00, 0x00), UNPACKED_1x1(1.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R8G8B8A8_SRGB, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0xbc, 0x00, 0x00), UNPACKED_1x1(0.0, 0.502886458033, 0.0, 0.0)}, + {PIPE_FORMAT_R8G8B8A8_SRGB, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0xff, 0x00, 0x00), UNPACKED_1x1(0.0, 1.0, 0.0, 0.0)}, + {PIPE_FORMAT_R8G8B8A8_SRGB, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0xbc, 0x00), UNPACKED_1x1(0.0, 0.0, 0.502886458033, 0.0)}, + {PIPE_FORMAT_R8G8B8A8_SRGB, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0xff, 0x00), UNPACKED_1x1(0.0, 0.0, 1.0, 0.0)}, + {PIPE_FORMAT_R8G8B8A8_SRGB, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0xcc), UNPACKED_1x1(0.0, 0.0, 0.0, 0.8)}, + {PIPE_FORMAT_R8G8B8A8_SRGB, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0xff), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8B8A8_SRGB, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0xff, 0xff, 0xff, 0xff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)}, + + {PIPE_FORMAT_B8G8R8A8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_B8G8R8A8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0x000000bc), UNPACKED_1x1(0.0, 0.0, 0.502886458033, 0.0)}, + {PIPE_FORMAT_B8G8R8A8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0x000000ff), UNPACKED_1x1(0.0, 0.0, 1.0, 0.0)}, + {PIPE_FORMAT_B8G8R8A8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0x0000bc00), UNPACKED_1x1(0.0, 0.502886458033, 0.0, 0.0)}, + {PIPE_FORMAT_B8G8R8A8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0x0000ff00), UNPACKED_1x1(0.0, 1.0, 0.0, 0.0)}, + {PIPE_FORMAT_B8G8R8A8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0x00bc0000), UNPACKED_1x1(0.502886458033, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_B8G8R8A8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0x00ff0000), UNPACKED_1x1(1.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_B8G8R8A8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0xcc000000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.8)}, + {PIPE_FORMAT_B8G8R8A8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0xff000000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_B8G8R8A8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0xffffffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)}, + + {PIPE_FORMAT_B8G8R8X8_SRGB, PACKED_1x32(0x00ffffff), PACKED_1x32(0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_B8G8R8X8_SRGB, PACKED_1x32(0x00ffffff), PACKED_1x32(0x000000bc), UNPACKED_1x1(0.0, 0.0, 0.502886458033, 1.0)}, + {PIPE_FORMAT_B8G8R8X8_SRGB, PACKED_1x32(0x00ffffff), PACKED_1x32(0x000000ff), UNPACKED_1x1(0.0, 0.0, 1.0, 1.0)}, + {PIPE_FORMAT_B8G8R8X8_SRGB, PACKED_1x32(0x00ffffff), PACKED_1x32(0x0000bc00), UNPACKED_1x1(0.0, 0.502886458033, 0.0, 1.0)}, + {PIPE_FORMAT_B8G8R8X8_SRGB, PACKED_1x32(0x00ffffff), PACKED_1x32(0x0000ff00), UNPACKED_1x1(0.0, 1.0, 0.0, 1.0)}, + {PIPE_FORMAT_B8G8R8X8_SRGB, PACKED_1x32(0x00ffffff), PACKED_1x32(0x00bc0000), UNPACKED_1x1(0.502886458033, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_B8G8R8X8_SRGB, PACKED_1x32(0x00ffffff), PACKED_1x32(0x00ff0000), UNPACKED_1x1(1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_B8G8R8X8_SRGB, PACKED_1x32(0x00ffffff), PACKED_1x32(0xffffffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)}, + + {PIPE_FORMAT_A8R8G8B8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_A8R8G8B8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0x000000cc), UNPACKED_1x1(0.0, 0.0, 0.0, 0.8)}, + {PIPE_FORMAT_A8R8G8B8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0x000000ff), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_A8R8G8B8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0x0000bc00), UNPACKED_1x1(0.502886458033, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_A8R8G8B8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0x0000ff00), UNPACKED_1x1(1.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_A8R8G8B8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0x00bc0000), UNPACKED_1x1(0.0, 0.502886458033, 0.0, 0.0)}, + {PIPE_FORMAT_A8R8G8B8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0x00ff0000), UNPACKED_1x1(0.0, 1.0, 0.0, 0.0)}, + {PIPE_FORMAT_A8R8G8B8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0xbc000000), UNPACKED_1x1(0.0, 0.0, 0.502886458033, 0.0)}, + {PIPE_FORMAT_A8R8G8B8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0xff000000), UNPACKED_1x1(0.0, 0.0, 1.0, 0.0)}, + {PIPE_FORMAT_A8R8G8B8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0xffffffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)}, + + {PIPE_FORMAT_X8R8G8B8_SRGB, PACKED_1x32(0xffffff00), PACKED_1x32(0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_X8R8G8B8_SRGB, PACKED_1x32(0xffffff00), PACKED_1x32(0x0000bc00), UNPACKED_1x1(0.502886458033, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_X8R8G8B8_SRGB, PACKED_1x32(0xffffff00), PACKED_1x32(0x0000ff00), UNPACKED_1x1(1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_X8R8G8B8_SRGB, PACKED_1x32(0xffffff00), PACKED_1x32(0x00bc0000), UNPACKED_1x1(0.0, 0.502886458033, 0.0, 1.0)}, + {PIPE_FORMAT_X8R8G8B8_SRGB, PACKED_1x32(0xffffff00), PACKED_1x32(0x00ff0000), UNPACKED_1x1(0.0, 1.0, 0.0, 1.0)}, + {PIPE_FORMAT_X8R8G8B8_SRGB, PACKED_1x32(0xffffff00), PACKED_1x32(0xbc000000), UNPACKED_1x1(0.0, 0.0, 0.502886458033, 1.0)}, + {PIPE_FORMAT_X8R8G8B8_SRGB, PACKED_1x32(0xffffff00), PACKED_1x32(0xff000000), UNPACKED_1x1(0.0, 0.0, 1.0, 1.0)}, + {PIPE_FORMAT_X8R8G8B8_SRGB, PACKED_1x32(0xffffff00), PACKED_1x32(0xffffffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)}, + + {PIPE_FORMAT_A8B8G8R8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_A8B8G8R8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0x000000cc), UNPACKED_1x1(0.0, 0.0, 0.0, 0.8)}, + {PIPE_FORMAT_A8B8G8R8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0x000000ff), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_A8B8G8R8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0x0000bc00), UNPACKED_1x1(0.0, 0.0, 0.502886458033, 0.0)}, + {PIPE_FORMAT_A8B8G8R8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0x0000ff00), UNPACKED_1x1(0.0, 0.0, 1.0, 0.0)}, + {PIPE_FORMAT_A8B8G8R8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0x00bc0000), UNPACKED_1x1(0.0, 0.502886458033, 0.0, 0.0)}, + {PIPE_FORMAT_A8B8G8R8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0x00ff0000), UNPACKED_1x1(0.0, 1.0, 0.0, 0.0)}, + {PIPE_FORMAT_A8B8G8R8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0xbc000000), UNPACKED_1x1(0.502886458033, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_A8B8G8R8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0xff000000), UNPACKED_1x1(1.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_A8B8G8R8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0xffffffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)}, + + {PIPE_FORMAT_X8B8G8R8_SRGB, PACKED_1x32(0xffffff00), PACKED_1x32(0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_X8B8G8R8_SRGB, PACKED_1x32(0xffffff00), PACKED_1x32(0x0000bc00), UNPACKED_1x1(0.0, 0.0, 0.502886458033, 1.0)}, + {PIPE_FORMAT_X8B8G8R8_SRGB, PACKED_1x32(0xffffff00), PACKED_1x32(0x0000ff00), UNPACKED_1x1(0.0, 0.0, 1.0, 1.0)}, + {PIPE_FORMAT_X8B8G8R8_SRGB, PACKED_1x32(0xffffff00), PACKED_1x32(0x00bc0000), UNPACKED_1x1(0.0, 0.502886458033, 0.0, 1.0)}, + {PIPE_FORMAT_X8B8G8R8_SRGB, PACKED_1x32(0xffffff00), PACKED_1x32(0x00ff0000), UNPACKED_1x1(0.0, 1.0, 0.0, 1.0)}, + {PIPE_FORMAT_X8B8G8R8_SRGB, PACKED_1x32(0xffffff00), PACKED_1x32(0xbc000000), UNPACKED_1x1(0.502886458033, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_X8B8G8R8_SRGB, PACKED_1x32(0xffffff00), PACKED_1x32(0xff000000), UNPACKED_1x1(1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_X8B8G8R8_SRGB, PACKED_1x32(0xffffff00), PACKED_1x32(0xffffffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)}, + + /* + * Mixed-signed formats + */ + + {PIPE_FORMAT_R8SG8SB8UX8U_NORM, PACKED_4x8(0xff, 0xff, 0xff, 0x00), PACKED_4x8(0x00, 0x00, 0x00, 0x00), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8SG8SB8UX8U_NORM, PACKED_4x8(0xff, 0xff, 0xff, 0x00), PACKED_4x8(0x7f, 0x00, 0x00, 0x00), UNPACKED_1x1( 1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8SG8SB8UX8U_NORM, PACKED_4x8(0xff, 0xff, 0xff, 0x00), PACKED_4x8(0x81, 0x00, 0x00, 0x00), UNPACKED_1x1(-1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8SG8SB8UX8U_NORM, PACKED_4x8(0xff, 0xff, 0xff, 0x00), PACKED_4x8(0x00, 0x7f, 0x00, 0x00), UNPACKED_1x1( 0.0, 1.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8SG8SB8UX8U_NORM, PACKED_4x8(0xff, 0xff, 0xff, 0x00), PACKED_4x8(0x00, 0x81, 0x00, 0x00), UNPACKED_1x1( 0.0, -1.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8SG8SB8UX8U_NORM, PACKED_4x8(0xff, 0xff, 0xff, 0x00), PACKED_4x8(0x00, 0x00, 0xff, 0x00), UNPACKED_1x1( 0.0, 0.0, 1.0, 1.0)}, + + {PIPE_FORMAT_R10SG10SB10SA2U_NORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R10SG10SB10SA2U_NORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x000001ff), UNPACKED_1x1( 1.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R10SG10SB10SA2U_NORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000201), UNPACKED_1x1(-1.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R10SG10SB10SA2U_NORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x0007fc00), UNPACKED_1x1( 0.0, 1.0, 0.0, 0.0)}, + {PIPE_FORMAT_R10SG10SB10SA2U_NORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00080400), UNPACKED_1x1( 0.0, -1.0, 0.0, 0.0)}, + {PIPE_FORMAT_R10SG10SB10SA2U_NORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x1ff00000), UNPACKED_1x1( 0.0, 0.0, 1.0, 0.0)}, + {PIPE_FORMAT_R10SG10SB10SA2U_NORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x20100000), UNPACKED_1x1( 0.0, 0.0, -1.0, 0.0)}, + {PIPE_FORMAT_R10SG10SB10SA2U_NORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xc0000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + + {PIPE_FORMAT_R5SG5SB6U_NORM, PACKED_1x16(0xffff), PACKED_1x16(0x0000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R5SG5SB6U_NORM, PACKED_1x16(0xffff), PACKED_1x16(0x000f), UNPACKED_1x1( 1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R5SG5SB6U_NORM, PACKED_1x16(0xffff), PACKED_1x16(0x0011), UNPACKED_1x1(-1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R5SG5SB6U_NORM, PACKED_1x16(0xffff), PACKED_1x16(0x01e0), UNPACKED_1x1( 0.0, 1.0, 0.0, 1.0)}, + {PIPE_FORMAT_R5SG5SB6U_NORM, PACKED_1x16(0xffff), PACKED_1x16(0x0220), UNPACKED_1x1( 0.0, -1.0, 0.0, 1.0)}, + {PIPE_FORMAT_R5SG5SB6U_NORM, PACKED_1x16(0xffff), PACKED_1x16(0xfc00), UNPACKED_1x1( 0.0, 0.0, 1.0, 1.0)}, + + {PIPE_FORMAT_R8G8Bx_SNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0x00), UNPACKED_1x1( 0.0, 0.0, 1.0, 1.0)}, + {PIPE_FORMAT_R8G8Bx_SNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x7f, 0x00), UNPACKED_1x1( 1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8Bx_SNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x81, 0x00), UNPACKED_1x1(-1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8Bx_SNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0x7f), UNPACKED_1x1( 0.0, 1.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8Bx_SNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0x81), UNPACKED_1x1( 0.0, -1.0, 0.0, 1.0)}, + + /* + * Depth-stencil formats + */ + + {PIPE_FORMAT_S8_USCALED, PACKED_1x8(0xff), PACKED_1x8(0x00), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_S8_USCALED, PACKED_1x8(0xff), PACKED_1x8(0xff), UNPACKED_1x1(0.0, 255.0, 0.0, 0.0)}, + + {PIPE_FORMAT_Z16_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x0000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_Z16_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0xffff), UNPACKED_1x1(1.0, 0.0, 0.0, 0.0)}, + + {PIPE_FORMAT_Z32_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_Z32_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xffffffff), UNPACKED_1x1(1.0, 0.0, 0.0, 0.0)}, + + {PIPE_FORMAT_Z32_FLOAT, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_Z32_FLOAT, PACKED_1x32(0xffffffff), PACKED_1x32(0x3f800000), UNPACKED_1x1(1.0, 0.0, 0.0, 0.0)}, + + {PIPE_FORMAT_Z24_UNORM_S8_USCALED, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_Z24_UNORM_S8_USCALED, PACKED_1x32(0xffffffff), PACKED_1x32(0x00ffffff), UNPACKED_1x1(1.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_Z24_UNORM_S8_USCALED, PACKED_1x32(0xffffffff), PACKED_1x32(0xff000000), UNPACKED_1x1(0.0, 255.0, 0.0, 0.0)}, + {PIPE_FORMAT_Z24_UNORM_S8_USCALED, PACKED_1x32(0xffffffff), PACKED_1x32(0xffffffff), UNPACKED_1x1(1.0, 255.0, 0.0, 0.0)}, + + {PIPE_FORMAT_S8_USCALED_Z24_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_S8_USCALED_Z24_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xffffff00), UNPACKED_1x1(1.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_S8_USCALED_Z24_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x000000ff), UNPACKED_1x1(0.0, 255.0, 0.0, 0.0)}, + {PIPE_FORMAT_S8_USCALED_Z24_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xffffffff), UNPACKED_1x1(1.0, 255.0, 0.0, 0.0)}, + + {PIPE_FORMAT_Z24X8_UNORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_Z24X8_UNORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0x00ffffff), UNPACKED_1x1(1.0, 0.0, 0.0, 0.0)}, + + {PIPE_FORMAT_X8Z24_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_X8Z24_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0xffffff00), UNPACKED_1x1(1.0, 0.0, 0.0, 0.0)}, + + {PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED, PACKED_2x32(0xffffffff, 0x000000ff), PACKED_2x32(0x00000000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED, PACKED_2x32(0xffffffff, 0x000000ff), PACKED_2x32(0x3f800000, 0x00000000), UNPACKED_1x1( 1.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED, PACKED_2x32(0xffffffff, 0x000000ff), PACKED_2x32(0x00000000, 0x000000ff), UNPACKED_1x1( 0.0, 255.0, 0.0, 0.0)}, + + /* + * YUV formats + */ + + {PIPE_FORMAT_R8G8_B8G8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0x00), UNPACKED_2x1(0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8_B8G8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0xff, 0x00, 0x00, 0x00), UNPACKED_2x1(1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8_B8G8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0xff, 0x00, 0x00), UNPACKED_2x1(0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8_B8G8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0xff, 0x00), UNPACKED_2x1(0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0)}, + {PIPE_FORMAT_R8G8_B8G8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0xff), UNPACKED_2x1(0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8_B8G8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0xff, 0xff, 0xff, 0xff), UNPACKED_2x1(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0)}, + + {PIPE_FORMAT_G8R8_G8B8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0x00), UNPACKED_2x1(0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_G8R8_G8B8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0xff, 0x00, 0x00, 0x00), UNPACKED_2x1(0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_G8R8_G8B8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0xff, 0x00, 0x00), UNPACKED_2x1(1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_G8R8_G8B8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0xff, 0x00), UNPACKED_2x1(0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0)}, + {PIPE_FORMAT_G8R8_G8B8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0xff), UNPACKED_2x1(0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0)}, + {PIPE_FORMAT_G8R8_G8B8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0xff, 0xff, 0xff, 0xff), UNPACKED_2x1(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0)}, + + /* + * TODO: Exercise the UV channels as well. + */ + {PIPE_FORMAT_UYVY, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x80, 0x10, 0x80, 0x10), UNPACKED_2x1(0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_UYVY, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x80, 0xeb, 0x80, 0x10), UNPACKED_2x1(1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_UYVY, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x80, 0x10, 0x80, 0xeb), UNPACKED_2x1(0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0)}, + + {PIPE_FORMAT_YUYV, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x10, 0x80, 0x10, 0x80), UNPACKED_2x1(0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_YUYV, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0xeb, 0x80, 0x10, 0x80), UNPACKED_2x1(1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_YUYV, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x10, 0x80, 0xeb, 0x80), UNPACKED_2x1(0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0)}, + + /* + * Compressed formats + */ + + { + PIPE_FORMAT_DXT1_RGB, + PACKED_8x8(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff), + PACKED_8x8(0xf2, 0xd7, 0xb0, 0x20, 0xae, 0x2c, 0x6f, 0x97), + { + { + {0x99/255.0, 0xb0/255.0, 0x8e/255.0, 0xff/255.0}, + {0x5d/255.0, 0x62/255.0, 0x89/255.0, 0xff/255.0}, + {0x99/255.0, 0xb0/255.0, 0x8e/255.0, 0xff/255.0}, + {0x99/255.0, 0xb0/255.0, 0x8e/255.0, 0xff/255.0} + }, + { + {0xd6/255.0, 0xff/255.0, 0x94/255.0, 0xff/255.0}, + {0x5d/255.0, 0x62/255.0, 0x89/255.0, 0xff/255.0}, + {0x99/255.0, 0xb0/255.0, 0x8e/255.0, 0xff/255.0}, + {0xd6/255.0, 0xff/255.0, 0x94/255.0, 0xff/255.0} + }, + { + {0x5d/255.0, 0x62/255.0, 0x89/255.0, 0xff/255.0}, + {0x5d/255.0, 0x62/255.0, 0x89/255.0, 0xff/255.0}, + {0x99/255.0, 0xb0/255.0, 0x8e/255.0, 0xff/255.0}, + {0x21/255.0, 0x14/255.0, 0x84/255.0, 0xff/255.0} + }, + { + {0x5d/255.0, 0x62/255.0, 0x89/255.0, 0xff/255.0}, + {0x21/255.0, 0x14/255.0, 0x84/255.0, 0xff/255.0}, + {0x21/255.0, 0x14/255.0, 0x84/255.0, 0xff/255.0}, + {0x99/255.0, 0xb0/255.0, 0x8e/255.0, 0xff/255.0} + } + } + }, + { + PIPE_FORMAT_DXT1_RGBA, + PACKED_8x8(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff), + PACKED_8x8(0xff, 0x2f, 0xa4, 0x72, 0xeb, 0xb2, 0xbd, 0xbe), + { + { + {0x00/255.0, 0x00/255.0, 0x00/255.0, 0x00/255.0}, + {0x4e/255.0, 0xaa/255.0, 0x90/255.0, 0xff/255.0}, + {0x4e/255.0, 0xaa/255.0, 0x90/255.0, 0xff/255.0}, + {0x00/255.0, 0x00/255.0, 0x00/255.0, 0x00/255.0} + }, + { + {0x4e/255.0, 0xaa/255.0, 0x90/255.0, 0xff/255.0}, + {0x29/255.0, 0xff/255.0, 0xff/255.0, 0xff/255.0}, + {0x00/255.0, 0x00/255.0, 0x00/255.0, 0x00/255.0}, + {0x4e/255.0, 0xaa/255.0, 0x90/255.0, 0xff/255.0} + }, + { + {0x73/255.0, 0x55/255.0, 0x21/255.0, 0xff/255.0}, + {0x00/255.0, 0x00/255.0, 0x00/255.0, 0x00/255.0}, + {0x00/255.0, 0x00/255.0, 0x00/255.0, 0x00/255.0}, + {0x4e/255.0, 0xaa/255.0, 0x90/255.0, 0xff/255.0} + }, + { + {0x4e/255.0, 0xaa/255.0, 0x90/255.0, 0xff/255.0}, + {0x00/255.0, 0x00/255.0, 0x00/255.0, 0x00/255.0}, + {0x00/255.0, 0x00/255.0, 0x00/255.0, 0x00/255.0}, + {0x4e/255.0, 0xaa/255.0, 0x90/255.0, 0xff/255.0} + } + } + }, + { + PIPE_FORMAT_DXT3_RGBA, + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + {0xe7, 0x4a, 0x8f, 0x96, 0x5b, 0xc1, 0x1c, 0x84, 0xf6, 0x8f, 0xab, 0x32, 0x2a, 0x9a, 0x95, 0x5a}, + { + { + {0x6d/255.0, 0xc6/255.0, 0x96/255.0, 0x77/255.0}, + {0x6d/255.0, 0xc6/255.0, 0x96/255.0, 0xee/255.0}, + {0x6d/255.0, 0xc6/255.0, 0x96/255.0, 0xaa/255.0}, + {0x8c/255.0, 0xff/255.0, 0xb5/255.0, 0x44/255.0} + }, + { + {0x6d/255.0, 0xc6/255.0, 0x96/255.0, 0xff/255.0}, + {0x6d/255.0, 0xc6/255.0, 0x96/255.0, 0x88/255.0}, + {0x31/255.0, 0x55/255.0, 0x5a/255.0, 0x66/255.0}, + {0x6d/255.0, 0xc6/255.0, 0x96/255.0, 0x99/255.0} + }, + { + {0x31/255.0, 0x55/255.0, 0x5a/255.0, 0xbb/255.0}, + {0x31/255.0, 0x55/255.0, 0x5a/255.0, 0x55/255.0}, + {0x31/255.0, 0x55/255.0, 0x5a/255.0, 0x11/255.0}, + {0x6d/255.0, 0xc6/255.0, 0x96/255.0, 0xcc/255.0} + }, + { + {0x6d/255.0, 0xc6/255.0, 0x96/255.0, 0xcc/255.0}, + {0x6d/255.0, 0xc6/255.0, 0x96/255.0, 0x11/255.0}, + {0x31/255.0, 0x55/255.0, 0x5a/255.0, 0x44/255.0}, + {0x31/255.0, 0x55/255.0, 0x5a/255.0, 0x88/255.0} + } + } + }, + { + PIPE_FORMAT_DXT5_RGBA, + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + {0xf8, 0x11, 0xc5, 0x0c, 0x9a, 0x73, 0xb4, 0x9c, 0xf6, 0x8f, 0xab, 0x32, 0x2a, 0x9a, 0x95, 0x5a}, + { + { + {0x6d/255.0, 0xc6/255.0, 0x96/255.0, 0x74/255.0}, + {0x6d/255.0, 0xc6/255.0, 0x96/255.0, 0xf8/255.0}, + {0x6d/255.0, 0xc6/255.0, 0x96/255.0, 0xb6/255.0}, + {0x8c/255.0, 0xff/255.0, 0xb5/255.0, 0x53/255.0} + }, + { + {0x6d/255.0, 0xc6/255.0, 0x96/255.0, 0xf8/255.0}, + {0x6d/255.0, 0xc6/255.0, 0x96/255.0, 0x95/255.0}, + {0x31/255.0, 0x55/255.0, 0x5a/255.0, 0x53/255.0}, + {0x6d/255.0, 0xc6/255.0, 0x96/255.0, 0x95/255.0} + }, + { + {0x31/255.0, 0x55/255.0, 0x5a/255.0, 0xb6/255.0}, + {0x31/255.0, 0x55/255.0, 0x5a/255.0, 0x53/255.0}, + {0x31/255.0, 0x55/255.0, 0x5a/255.0, 0x11/255.0}, + {0x6d/255.0, 0xc6/255.0, 0x96/255.0, 0xd7/255.0} + }, + { + {0x6d/255.0, 0xc6/255.0, 0x96/255.0, 0xb6/255.0}, + {0x6d/255.0, 0xc6/255.0, 0x96/255.0, 0x11/255.0}, + {0x31/255.0, 0x55/255.0, 0x5a/255.0, 0x32/255.0}, + {0x31/255.0, 0x55/255.0, 0x5a/255.0, 0x95/255.0} + } + } + }, + + + /* + * Standard 8-bit integer formats + */ + + {PIPE_FORMAT_R8_UNORM, PACKED_1x8(0xff), PACKED_1x8(0x00), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8_UNORM, PACKED_1x8(0xff), PACKED_1x8(0xff), UNPACKED_1x1(1.0, 0.0, 0.0, 1.0)}, + + {PIPE_FORMAT_R8G8_UNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0x00), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8_UNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0xff, 0x00), UNPACKED_1x1(1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8_UNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0xff), UNPACKED_1x1(0.0, 1.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8_UNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0xff, 0xff), UNPACKED_1x1(1.0, 1.0, 0.0, 1.0)}, + + {PIPE_FORMAT_R8G8B8_UNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0x00), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8B8_UNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0xff, 0x00, 0x00), UNPACKED_1x1(1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8B8_UNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0xff, 0x00), UNPACKED_1x1(0.0, 1.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8B8_UNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0xff), UNPACKED_1x1(0.0, 0.0, 1.0, 1.0)}, + {PIPE_FORMAT_R8G8B8_UNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0xff, 0xff, 0xff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)}, + + {PIPE_FORMAT_R8G8B8A8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0x00), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R8G8B8A8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0xff, 0x00, 0x00, 0x00), UNPACKED_1x1(1.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R8G8B8A8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0xff, 0x00, 0x00), UNPACKED_1x1(0.0, 1.0, 0.0, 0.0)}, + {PIPE_FORMAT_R8G8B8A8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0xff, 0x00), UNPACKED_1x1(0.0, 0.0, 1.0, 0.0)}, + {PIPE_FORMAT_R8G8B8A8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0xff), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8B8A8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0xff, 0xff, 0xff, 0xff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)}, + + {PIPE_FORMAT_R8_USCALED, PACKED_1x8(0xff), PACKED_1x8(0x00), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8_USCALED, PACKED_1x8(0xff), PACKED_1x8(0xff), UNPACKED_1x1(255.0, 0.0, 0.0, 1.0)}, + + {PIPE_FORMAT_R8G8_USCALED, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0x00), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8_USCALED, PACKED_2x8(0xff, 0xff), PACKED_2x8(0xff, 0x00), UNPACKED_1x1(255.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8_USCALED, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0xff), UNPACKED_1x1( 0.0, 255.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8_USCALED, PACKED_2x8(0xff, 0xff), PACKED_2x8(0xff, 0xff), UNPACKED_1x1(255.0, 255.0, 0.0, 1.0)}, + + {PIPE_FORMAT_R8G8B8_USCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0x00), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8B8_USCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0xff, 0x00, 0x00), UNPACKED_1x1(255.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8B8_USCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0xff, 0x00), UNPACKED_1x1( 0.0, 255.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8B8_USCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0xff), UNPACKED_1x1( 0.0, 0.0, 255.0, 1.0)}, + {PIPE_FORMAT_R8G8B8_USCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0xff, 0xff, 0xff), UNPACKED_1x1(255.0, 255.0, 255.0, 1.0)}, + + {PIPE_FORMAT_R8G8B8A8_USCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0x00), UNPACKED_1x1( 0.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R8G8B8A8_USCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0xff, 0x00, 0x00, 0x00), UNPACKED_1x1(255.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R8G8B8A8_USCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0xff, 0x00, 0x00), UNPACKED_1x1( 0.0, 255.0, 0.0, 0.0)}, + {PIPE_FORMAT_R8G8B8A8_USCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0xff, 0x00), UNPACKED_1x1( 0.0, 0.0, 255.0, 0.0)}, + {PIPE_FORMAT_R8G8B8A8_USCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0xff), UNPACKED_1x1( 0.0, 0.0, 0.0, 255.0)}, + {PIPE_FORMAT_R8G8B8A8_USCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0xff, 0xff, 0xff, 0xff), UNPACKED_1x1(255.0, 255.0, 255.0, 255.0)}, + + {PIPE_FORMAT_R8_SNORM, PACKED_1x8(0xff), PACKED_1x8(0x00), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8_SNORM, PACKED_1x8(0xff), PACKED_1x8(0x7f), UNPACKED_1x1( 1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8_SNORM, PACKED_1x8(0xff), PACKED_1x8(0x81), UNPACKED_1x1(-1.0, 0.0, 0.0, 1.0)}, + + {PIPE_FORMAT_R8G8_SNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0x00), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8_SNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x7f, 0x00), UNPACKED_1x1( 1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8_SNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x81, 0x00), UNPACKED_1x1(-1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8_SNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0x7f), UNPACKED_1x1( 0.0, 1.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8_SNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0x81), UNPACKED_1x1( 0.0, -1.0, 0.0, 1.0)}, + + {PIPE_FORMAT_R8G8B8_SNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0x00), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8B8_SNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x7f, 0x00, 0x00), UNPACKED_1x1( 1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8B8_SNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x81, 0x00, 0x00), UNPACKED_1x1(-1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8B8_SNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x7f, 0x00), UNPACKED_1x1( 0.0, 1.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8B8_SNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x81, 0x00), UNPACKED_1x1( 0.0, -1.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8B8_SNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0x7f), UNPACKED_1x1( 0.0, 0.0, 1.0, 1.0)}, + {PIPE_FORMAT_R8G8B8_SNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0x81), UNPACKED_1x1( 0.0, 0.0, -1.0, 1.0)}, + + {PIPE_FORMAT_R8G8B8A8_SNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0x00), UNPACKED_1x1( 0.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R8G8B8A8_SNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x7f, 0x00, 0x00, 0x00), UNPACKED_1x1( 1.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R8G8B8A8_SNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x81, 0x00, 0x00, 0x00), UNPACKED_1x1(-1.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R8G8B8A8_SNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x7f, 0x00, 0x00), UNPACKED_1x1( 0.0, 1.0, 0.0, 0.0)}, + {PIPE_FORMAT_R8G8B8A8_SNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x81, 0x00, 0x00), UNPACKED_1x1( 0.0, -1.0, 0.0, 0.0)}, + {PIPE_FORMAT_R8G8B8A8_SNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x7f, 0x00), UNPACKED_1x1( 0.0, 0.0, 1.0, 0.0)}, + {PIPE_FORMAT_R8G8B8A8_SNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x81, 0x00), UNPACKED_1x1( 0.0, 0.0, -1.0, 0.0)}, + {PIPE_FORMAT_R8G8B8A8_SNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0x7f), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8B8A8_SNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0x81), UNPACKED_1x1( 0.0, 0.0, 0.0, -1.0)}, + + {PIPE_FORMAT_R8_SSCALED, PACKED_1x8(0xff), PACKED_1x8(0x00), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8_SSCALED, PACKED_1x8(0xff), PACKED_1x8(0x7f), UNPACKED_1x1( 127.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8_SSCALED, PACKED_1x8(0xff), PACKED_1x8(0x80), UNPACKED_1x1(-128.0, 0.0, 0.0, 1.0)}, + + {PIPE_FORMAT_R8G8_SSCALED, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0x00), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8_SSCALED, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x7f, 0x00), UNPACKED_1x1( 127.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8_SSCALED, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x80, 0x00), UNPACKED_1x1(-128.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8_SSCALED, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0x7f), UNPACKED_1x1( 0.0, 127.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8_SSCALED, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0x80), UNPACKED_1x1( 0.0, -128.0, 0.0, 1.0)}, + + {PIPE_FORMAT_R8G8B8_SSCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0x00), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8B8_SSCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x7f, 0x00, 0x00), UNPACKED_1x1( 127.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8B8_SSCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x80, 0x00, 0x00), UNPACKED_1x1(-128.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8B8_SSCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x7f, 0x00), UNPACKED_1x1( 0.0, 127.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8B8_SSCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x80, 0x00), UNPACKED_1x1( 0.0, -128.0, 0.0, 1.0)}, + {PIPE_FORMAT_R8G8B8_SSCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0x7f), UNPACKED_1x1( 0.0, 0.0, 127.0, 1.0)}, + {PIPE_FORMAT_R8G8B8_SSCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0x80), UNPACKED_1x1( 0.0, 0.0, -128.0, 1.0)}, + + {PIPE_FORMAT_R8G8B8A8_SSCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0x00), UNPACKED_1x1( 0.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R8G8B8A8_SSCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x7f, 0x00, 0x00, 0x00), UNPACKED_1x1( 127.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R8G8B8A8_SSCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x80, 0x00, 0x00, 0x00), UNPACKED_1x1(-128.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R8G8B8A8_SSCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x7f, 0x00, 0x00), UNPACKED_1x1( 0.0, 127.0, 0.0, 0.0)}, + {PIPE_FORMAT_R8G8B8A8_SSCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x80, 0x00, 0x00), UNPACKED_1x1( 0.0, -128.0, 0.0, 0.0)}, + {PIPE_FORMAT_R8G8B8A8_SSCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x7f, 0x00), UNPACKED_1x1( 0.0, 0.0, 127.0, 0.0)}, + {PIPE_FORMAT_R8G8B8A8_SSCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x80, 0x00), UNPACKED_1x1( 0.0, 0.0, -128.0, 0.0)}, + {PIPE_FORMAT_R8G8B8A8_SSCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0x7f), UNPACKED_1x1( 0.0, 0.0, 0.0, 127.0)}, + {PIPE_FORMAT_R8G8B8A8_SSCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0x80), UNPACKED_1x1( 0.0, 0.0, 0.0, -128.0)}, + + /* + * Standard 16-bit integer formats + */ + + {PIPE_FORMAT_R16_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x0000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0xffff), UNPACKED_1x1(1.0, 0.0, 0.0, 1.0)}, + + {PIPE_FORMAT_R16G16_UNORM, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0x0000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16G16_UNORM, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0xffff, 0x0000), UNPACKED_1x1(1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16G16_UNORM, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0xffff), UNPACKED_1x1(0.0, 1.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16G16_UNORM, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0xffff, 0xffff), UNPACKED_1x1(1.0, 1.0, 0.0, 1.0)}, + + {PIPE_FORMAT_R16G16B16_UNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0x0000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16G16B16_UNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0xffff, 0x0000, 0x0000), UNPACKED_1x1(1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16G16B16_UNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0xffff, 0x0000), UNPACKED_1x1(0.0, 1.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16G16B16_UNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0xffff), UNPACKED_1x1(0.0, 0.0, 1.0, 1.0)}, + {PIPE_FORMAT_R16G16B16_UNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0xffff, 0xffff, 0xffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)}, + + {PIPE_FORMAT_R16G16B16A16_UNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0x0000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R16G16B16A16_UNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0xffff, 0x0000, 0x0000, 0x0000), UNPACKED_1x1(1.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R16G16B16A16_UNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0xffff, 0x0000, 0x0000), UNPACKED_1x1(0.0, 1.0, 0.0, 0.0)}, + {PIPE_FORMAT_R16G16B16A16_UNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0xffff, 0x0000), UNPACKED_1x1(0.0, 0.0, 1.0, 0.0)}, + {PIPE_FORMAT_R16G16B16A16_UNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0xffff), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16G16B16A16_UNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)}, + + {PIPE_FORMAT_R16_USCALED, PACKED_1x16(0xffff), PACKED_1x16(0x0000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16_USCALED, PACKED_1x16(0xffff), PACKED_1x16(0xffff), UNPACKED_1x1(65535.0, 0.0, 0.0, 1.0)}, + + {PIPE_FORMAT_R16G16_USCALED, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0x0000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16G16_USCALED, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0xffff, 0x0000), UNPACKED_1x1(65535.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16G16_USCALED, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0xffff), UNPACKED_1x1( 0.0, 65535.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16G16_USCALED, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0xffff, 0xffff), UNPACKED_1x1(65535.0, 65535.0, 0.0, 1.0)}, + + {PIPE_FORMAT_R16G16B16_USCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0x0000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16G16B16_USCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0xffff, 0x0000, 0x0000), UNPACKED_1x1(65535.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16G16B16_USCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0xffff, 0x0000), UNPACKED_1x1( 0.0, 65535.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16G16B16_USCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0xffff), UNPACKED_1x1( 0.0, 0.0, 65535.0, 1.0)}, + {PIPE_FORMAT_R16G16B16_USCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0xffff, 0xffff, 0xffff), UNPACKED_1x1(65535.0, 65535.0, 65535.0, 1.0)}, + + {PIPE_FORMAT_R16G16B16A16_USCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0x0000), UNPACKED_1x1( 0.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R16G16B16A16_USCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0xffff, 0x0000, 0x0000, 0x0000), UNPACKED_1x1(65535.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R16G16B16A16_USCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0xffff, 0x0000, 0x0000), UNPACKED_1x1( 0.0, 65535.0, 0.0, 0.0)}, + {PIPE_FORMAT_R16G16B16A16_USCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0xffff, 0x0000), UNPACKED_1x1( 0.0, 0.0, 65535.0, 0.0)}, + {PIPE_FORMAT_R16G16B16A16_USCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0xffff), UNPACKED_1x1( 0.0, 0.0, 0.0, 65535.0)}, + {PIPE_FORMAT_R16G16B16A16_USCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), UNPACKED_1x1(65535.0, 65535.0, 65535.0, 65535.0)}, + + {PIPE_FORMAT_R16_SNORM, PACKED_1x16(0xffff), PACKED_1x16(0x0000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16_SNORM, PACKED_1x16(0xffff), PACKED_1x16(0x7fff), UNPACKED_1x1( 1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16_SNORM, PACKED_1x16(0xffff), PACKED_1x16(0x8001), UNPACKED_1x1( -1.0, 0.0, 0.0, 1.0)}, + + {PIPE_FORMAT_R16G16_SNORM, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0x0000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16G16_SNORM, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x7fff, 0x0000), UNPACKED_1x1( 1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16G16_SNORM, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x8001, 0x0000), UNPACKED_1x1( -1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16G16_SNORM, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0x7fff), UNPACKED_1x1( 0.0, 1.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16G16_SNORM, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0x8001), UNPACKED_1x1( 0.0, -1.0, 0.0, 1.0)}, + + {PIPE_FORMAT_R16G16B16_SNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0x0000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16G16B16_SNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x7fff, 0x0000, 0x0000), UNPACKED_1x1( 1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16G16B16_SNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x8001, 0x0000, 0x0000), UNPACKED_1x1( -1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16G16B16_SNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x7fff, 0x0000), UNPACKED_1x1( 0.0, 1.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16G16B16_SNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x8001, 0x0000), UNPACKED_1x1( 0.0, -1.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16G16B16_SNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0x7fff), UNPACKED_1x1( 0.0, 0.0, 1.0, 1.0)}, + {PIPE_FORMAT_R16G16B16_SNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0x8001), UNPACKED_1x1( 0.0, 0.0, -1.0, 1.0)}, + + {PIPE_FORMAT_R16G16B16A16_SNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0x0000), UNPACKED_1x1( 0.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R16G16B16A16_SNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x7fff, 0x0000, 0x0000, 0x0000), UNPACKED_1x1( 1.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R16G16B16A16_SNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x8001, 0x0000, 0x0000, 0x0000), UNPACKED_1x1( -1.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R16G16B16A16_SNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x7fff, 0x0000, 0x0000), UNPACKED_1x1( 0.0, 1.0, 0.0, 0.0)}, + {PIPE_FORMAT_R16G16B16A16_SNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x8001, 0x0000, 0x0000), UNPACKED_1x1( 0.0, -1.0, 0.0, 0.0)}, + {PIPE_FORMAT_R16G16B16A16_SNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x7fff, 0x0000), UNPACKED_1x1( 0.0, 0.0, 1.0, 0.0)}, + {PIPE_FORMAT_R16G16B16A16_SNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x8001, 0x0000), UNPACKED_1x1( 0.0, 0.0, -1.0, 0.0)}, + {PIPE_FORMAT_R16G16B16A16_SNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0x7fff), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16G16B16A16_SNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0x8001), UNPACKED_1x1( 0.0, 0.0, 0.0, -1.0)}, + + {PIPE_FORMAT_R16_SSCALED, PACKED_1x16(0xffff), PACKED_1x16(0x0000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16_SSCALED, PACKED_1x16(0xffff), PACKED_1x16(0x7fff), UNPACKED_1x1( 32767.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16_SSCALED, PACKED_1x16(0xffff), PACKED_1x16(0x8000), UNPACKED_1x1(-32768.0, 0.0, 0.0, 1.0)}, + + {PIPE_FORMAT_R16G16_SSCALED, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0x0000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16G16_SSCALED, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x7fff, 0x0000), UNPACKED_1x1( 32767.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16G16_SSCALED, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x8000, 0x0000), UNPACKED_1x1(-32768.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16G16_SSCALED, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0x7fff), UNPACKED_1x1( 0.0, 32767.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16G16_SSCALED, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0x8000), UNPACKED_1x1( 0.0, -32768.0, 0.0, 1.0)}, + + {PIPE_FORMAT_R16G16B16_SSCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0x0000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16G16B16_SSCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x7fff, 0x0000, 0x0000), UNPACKED_1x1( 32767.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16G16B16_SSCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x8000, 0x0000, 0x0000), UNPACKED_1x1(-32768.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16G16B16_SSCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x7fff, 0x0000), UNPACKED_1x1( 0.0, 32767.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16G16B16_SSCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x8000, 0x0000), UNPACKED_1x1( 0.0, -32768.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16G16B16_SSCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0x7fff), UNPACKED_1x1( 0.0, 0.0, 32767.0, 1.0)}, + {PIPE_FORMAT_R16G16B16_SSCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0x8000), UNPACKED_1x1( 0.0, 0.0, -32768.0, 1.0)}, + + {PIPE_FORMAT_R16G16B16A16_SSCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0x0000), UNPACKED_1x1( 0.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R16G16B16A16_SSCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x7fff, 0x0000, 0x0000, 0x0000), UNPACKED_1x1( 32767.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R16G16B16A16_SSCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x8000, 0x0000, 0x0000, 0x0000), UNPACKED_1x1(-32768.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R16G16B16A16_SSCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x7fff, 0x0000, 0x0000), UNPACKED_1x1( 0.0, 32767.0, 0.0, 0.0)}, + {PIPE_FORMAT_R16G16B16A16_SSCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x8000, 0x0000, 0x0000), UNPACKED_1x1( 0.0, -32768.0, 0.0, 0.0)}, + {PIPE_FORMAT_R16G16B16A16_SSCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x7fff, 0x0000), UNPACKED_1x1( 0.0, 0.0, 32767.0, 0.0)}, + {PIPE_FORMAT_R16G16B16A16_SSCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x8000, 0x0000), UNPACKED_1x1( 0.0, 0.0, -32768.0, 0.0)}, + {PIPE_FORMAT_R16G16B16A16_SSCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0x7fff), UNPACKED_1x1( 0.0, 0.0, 0.0, 32767.0)}, + {PIPE_FORMAT_R16G16B16A16_SSCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0x8000), UNPACKED_1x1( 0.0, 0.0, 0.0, -32768.0)}, + + /* + * Standard 32-bit integer formats + * + * NOTE: We can't accurately represent integers larger than +/-0x1000000 + * with single precision floats, so that's as far as we test. + */ + + {PIPE_FORMAT_R32_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xffffffff), UNPACKED_1x1(1.0, 0.0, 0.0, 1.0)}, + + {PIPE_FORMAT_R32G32_UNORM, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32_UNORM, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0xffffffff, 0x00000000), UNPACKED_1x1(1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32_UNORM, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0xffffffff), UNPACKED_1x1(0.0, 1.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32_UNORM, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0xffffffff, 0xffffffff), UNPACKED_1x1(1.0, 1.0, 0.0, 1.0)}, + + {PIPE_FORMAT_R32G32B32_UNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32B32_UNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0xffffffff, 0x00000000, 0x00000000), UNPACKED_1x1(1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32B32_UNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0xffffffff, 0x00000000), UNPACKED_1x1(0.0, 1.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32B32_UNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0xffffffff), UNPACKED_1x1(0.0, 0.0, 1.0, 1.0)}, + {PIPE_FORMAT_R32G32B32_UNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)}, + + {PIPE_FORMAT_R32G32B32A32_UNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R32G32B32A32_UNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0xffffffff, 0x00000000, 0x00000000, 0x00000000), UNPACKED_1x1(1.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R32G32B32A32_UNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0xffffffff, 0x00000000, 0x00000000), UNPACKED_1x1(0.0, 1.0, 0.0, 0.0)}, + {PIPE_FORMAT_R32G32B32A32_UNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0xffffffff, 0x00000000), UNPACKED_1x1(0.0, 0.0, 1.0, 0.0)}, + {PIPE_FORMAT_R32G32B32A32_UNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0xffffffff), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32B32A32_UNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)}, + + {PIPE_FORMAT_R32_USCALED, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32_USCALED, PACKED_1x32(0xffffffff), PACKED_1x32(0x01000000), UNPACKED_1x1(16777216.0, 0.0, 0.0, 1.0)}, + + {PIPE_FORMAT_R32G32_USCALED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32_USCALED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x01000000, 0x00000000), UNPACKED_1x1(16777216.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32_USCALED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0x01000000), UNPACKED_1x1( 0.0, 16777216.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32_USCALED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x01000000, 0x01000000), UNPACKED_1x1(16777216.0, 16777216.0, 0.0, 1.0)}, + + {PIPE_FORMAT_R32G32B32_USCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32B32_USCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x01000000, 0x00000000, 0x00000000), UNPACKED_1x1(16777216.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32B32_USCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x01000000, 0x00000000), UNPACKED_1x1( 0.0, 16777216.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32B32_USCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0x01000000), UNPACKED_1x1( 0.0, 0.0, 16777216.0, 1.0)}, + {PIPE_FORMAT_R32G32B32_USCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x01000000, 0x01000000, 0x01000000), UNPACKED_1x1(16777216.0, 16777216.0, 16777216.0, 1.0)}, + + {PIPE_FORMAT_R32G32B32A32_USCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R32G32B32A32_USCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x01000000, 0x00000000, 0x00000000, 0x00000000), UNPACKED_1x1(16777216.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R32G32B32A32_USCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x01000000, 0x00000000, 0x00000000), UNPACKED_1x1( 0.0, 16777216.0, 0.0, 0.0)}, + {PIPE_FORMAT_R32G32B32A32_USCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x01000000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, 16777216.0, 0.0)}, + {PIPE_FORMAT_R32G32B32A32_USCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0x01000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 16777216.0)}, + {PIPE_FORMAT_R32G32B32A32_USCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x01000000, 0x01000000, 0x01000000, 0x01000000), UNPACKED_1x1(16777216.0, 16777216.0, 16777216.0, 16777216.0)}, + + {PIPE_FORMAT_R32_SNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32_SNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x7fffffff), UNPACKED_1x1( 1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32_SNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x80000001), UNPACKED_1x1( -1.0, 0.0, 0.0, 1.0)}, + + {PIPE_FORMAT_R32G32_SNORM, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32_SNORM, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x7fffffff, 0x00000000), UNPACKED_1x1( 1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32_SNORM, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x80000001, 0x00000000), UNPACKED_1x1( -1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32_SNORM, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0x7fffffff), UNPACKED_1x1( 0.0, 1.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32_SNORM, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0x80000001), UNPACKED_1x1( 0.0, -1.0, 0.0, 1.0)}, + + {PIPE_FORMAT_R32G32B32_SNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32B32_SNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x7fffffff, 0x00000000, 0x00000000), UNPACKED_1x1( 1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32B32_SNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x80000001, 0x00000000, 0x00000000), UNPACKED_1x1( -1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32B32_SNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x7fffffff, 0x00000000), UNPACKED_1x1( 0.0, 1.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32B32_SNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x80000001, 0x00000000), UNPACKED_1x1( 0.0, -1.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32B32_SNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0x7fffffff), UNPACKED_1x1( 0.0, 0.0, 1.0, 1.0)}, + {PIPE_FORMAT_R32G32B32_SNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0x80000001), UNPACKED_1x1( 0.0, 0.0, -1.0, 1.0)}, + + {PIPE_FORMAT_R32G32B32A32_SNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R32G32B32A32_SNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x7fffffff, 0x00000000, 0x00000000, 0x00000000), UNPACKED_1x1( 1.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R32G32B32A32_SNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x80000001, 0x00000000, 0x00000000, 0x00000000), UNPACKED_1x1( -1.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R32G32B32A32_SNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x7fffffff, 0x00000000, 0x00000000), UNPACKED_1x1( 0.0, 1.0, 0.0, 0.0)}, + {PIPE_FORMAT_R32G32B32A32_SNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x80000001, 0x00000000, 0x00000000), UNPACKED_1x1( 0.0, -1.0, 0.0, 0.0)}, + {PIPE_FORMAT_R32G32B32A32_SNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x7fffffff, 0x00000000), UNPACKED_1x1( 0.0, 0.0, 1.0, 0.0)}, + {PIPE_FORMAT_R32G32B32A32_SNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x80000001, 0x00000000), UNPACKED_1x1( 0.0, 0.0, -1.0, 0.0)}, + {PIPE_FORMAT_R32G32B32A32_SNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0x7fffffff), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32B32A32_SNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0x80000001), UNPACKED_1x1( 0.0, 0.0, 0.0, -1.0)}, + + {PIPE_FORMAT_R32_SSCALED, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32_SSCALED, PACKED_1x32(0xffffffff), PACKED_1x32(0x01000000), UNPACKED_1x1( 16777216.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32_SSCALED, PACKED_1x32(0xffffffff), PACKED_1x32(0xff000000), UNPACKED_1x1(-16777216.0, 0.0, 0.0, 1.0)}, + + {PIPE_FORMAT_R32G32_SSCALED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32_SSCALED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x01000000, 0x00000000), UNPACKED_1x1( 16777216.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32_SSCALED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0xff000000, 0x00000000), UNPACKED_1x1(-16777216.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32_SSCALED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0x01000000), UNPACKED_1x1( 0.0, 16777216.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32_SSCALED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0xff000000), UNPACKED_1x1( 0.0, -16777216.0, 0.0, 1.0)}, + + {PIPE_FORMAT_R32G32B32_SSCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32B32_SSCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x01000000, 0x00000000, 0x00000000), UNPACKED_1x1( 16777216.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32B32_SSCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0xff000000, 0x00000000, 0x00000000), UNPACKED_1x1(-16777216.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32B32_SSCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x01000000, 0x00000000), UNPACKED_1x1( 0.0, 16777216.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32B32_SSCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0xff000000, 0x00000000), UNPACKED_1x1( 0.0, -16777216.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32B32_SSCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0x01000000), UNPACKED_1x1( 0.0, 0.0, 16777216.0, 1.0)}, + {PIPE_FORMAT_R32G32B32_SSCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0xff000000), UNPACKED_1x1( 0.0, 0.0, -16777216.0, 1.0)}, + + {PIPE_FORMAT_R32G32B32A32_SSCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R32G32B32A32_SSCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x01000000, 0x00000000, 0x00000000, 0x00000000), UNPACKED_1x1( 16777216.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R32G32B32A32_SSCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0xff000000, 0x00000000, 0x00000000, 0x00000000), UNPACKED_1x1(-16777216.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R32G32B32A32_SSCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x01000000, 0x00000000, 0x00000000), UNPACKED_1x1( 0.0, 16777216.0, 0.0, 0.0)}, + {PIPE_FORMAT_R32G32B32A32_SSCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0xff000000, 0x00000000, 0x00000000), UNPACKED_1x1( 0.0, -16777216.0, 0.0, 0.0)}, + {PIPE_FORMAT_R32G32B32A32_SSCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x01000000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, 16777216.0, 0.0)}, + {PIPE_FORMAT_R32G32B32A32_SSCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0xff000000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, -16777216.0, 0.0)}, + {PIPE_FORMAT_R32G32B32A32_SSCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0x01000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 16777216.0)}, + {PIPE_FORMAT_R32G32B32A32_SSCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0xff000000), UNPACKED_1x1( 0.0, 0.0, 0.0, -16777216.0)}, + + /* + * Standard 32-bit float formats + */ + + {PIPE_FORMAT_R32_FLOAT, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32_FLOAT, PACKED_1x32(0xffffffff), PACKED_1x32(0x3f800000), UNPACKED_1x1( 1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32_FLOAT, PACKED_1x32(0xffffffff), PACKED_1x32(0xbf800000), UNPACKED_1x1( -1.0, 0.0, 0.0, 1.0)}, + + {PIPE_FORMAT_R32G32_FLOAT, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32_FLOAT, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x3f800000, 0x00000000), UNPACKED_1x1( 1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32_FLOAT, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0xbf800000, 0x00000000), UNPACKED_1x1(-1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32_FLOAT, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0x3f800000), UNPACKED_1x1( 0.0, 1.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32_FLOAT, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0xbf800000), UNPACKED_1x1( 0.0, -1.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32_FLOAT, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x3f800000, 0x3f800000), UNPACKED_1x1( 1.0, 1.0, 0.0, 1.0)}, + + {PIPE_FORMAT_R32G32B32_FLOAT, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32B32_FLOAT, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x3f800000, 0x00000000, 0x00000000), UNPACKED_1x1( 1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32B32_FLOAT, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0xbf800000, 0x00000000, 0x00000000), UNPACKED_1x1(-1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32B32_FLOAT, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x3f800000, 0x00000000), UNPACKED_1x1( 0.0, 1.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32B32_FLOAT, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0xbf800000, 0x00000000), UNPACKED_1x1( 0.0, -1.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32B32_FLOAT, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0x3f800000), UNPACKED_1x1( 0.0, 0.0, 1.0, 1.0)}, + {PIPE_FORMAT_R32G32B32_FLOAT, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0xbf800000), UNPACKED_1x1( 0.0, 0.0, -1.0, 1.0)}, + {PIPE_FORMAT_R32G32B32_FLOAT, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x3f800000, 0x3f800000, 0x3f800000), UNPACKED_1x1( 1.0, 1.0, 1.0, 1.0)}, + + {PIPE_FORMAT_R32G32B32A32_FLOAT, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R32G32B32A32_FLOAT, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x3f800000, 0x00000000, 0x00000000, 0x00000000), UNPACKED_1x1( 1.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R32G32B32A32_FLOAT, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0xbf800000, 0x00000000, 0x00000000, 0x00000000), UNPACKED_1x1(-1.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R32G32B32A32_FLOAT, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x3f800000, 0x00000000, 0x00000000), UNPACKED_1x1( 0.0, 1.0, 0.0, 0.0)}, + {PIPE_FORMAT_R32G32B32A32_FLOAT, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0xbf800000, 0x00000000, 0x00000000), UNPACKED_1x1( 0.0, -1.0, 0.0, 0.0)}, + {PIPE_FORMAT_R32G32B32A32_FLOAT, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x3f800000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, 1.0, 0.0)}, + {PIPE_FORMAT_R32G32B32A32_FLOAT, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0xbf800000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, -1.0, 0.0)}, + {PIPE_FORMAT_R32G32B32A32_FLOAT, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0x3f800000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32B32A32_FLOAT, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0xbf800000), UNPACKED_1x1( 0.0, 0.0, 0.0, -1.0)}, + {PIPE_FORMAT_R32G32B32A32_FLOAT, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000), UNPACKED_1x1( 1.0, 1.0, 1.0, 1.0)}, + + /* + * Half float formats + */ + + {PIPE_FORMAT_R16_FLOAT, PACKED_1x16(0xffff), PACKED_1x16(0x0000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16_FLOAT, PACKED_1x16(0xffff), PACKED_1x16(0x3c00), UNPACKED_1x1( 1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16_FLOAT, PACKED_1x16(0xffff), PACKED_1x16(0xbc00), UNPACKED_1x1( -1.0, 0.0, 0.0, 1.0)}, + + {PIPE_FORMAT_R16G16_FLOAT, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0x0000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16G16_FLOAT, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x3c00, 0x0000), UNPACKED_1x1( 1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16G16_FLOAT, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0xbc00, 0x0000), UNPACKED_1x1(-1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16G16_FLOAT, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0x3c00), UNPACKED_1x1( 0.0, 1.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16G16_FLOAT, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0xbc00), UNPACKED_1x1( 0.0, -1.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16G16_FLOAT, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x3c00, 0x3c00), UNPACKED_1x1( 1.0, 1.0, 0.0, 1.0)}, + + {PIPE_FORMAT_R16G16B16_FLOAT, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0x0000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16G16B16_FLOAT, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x3c00, 0x0000, 0x0000), UNPACKED_1x1( 1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16G16B16_FLOAT, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0xbc00, 0x0000, 0x0000), UNPACKED_1x1(-1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16G16B16_FLOAT, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x3c00, 0x0000), UNPACKED_1x1( 0.0, 1.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16G16B16_FLOAT, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0xbc00, 0x0000), UNPACKED_1x1( 0.0, -1.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16G16B16_FLOAT, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0x3c00), UNPACKED_1x1( 0.0, 0.0, 1.0, 1.0)}, + {PIPE_FORMAT_R16G16B16_FLOAT, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0xbc00), UNPACKED_1x1( 0.0, 0.0, -1.0, 1.0)}, + {PIPE_FORMAT_R16G16B16_FLOAT, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x3c00, 0x3c00, 0x3c00), UNPACKED_1x1( 1.0, 1.0, 1.0, 1.0)}, + + {PIPE_FORMAT_R16G16B16A16_FLOAT, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0x0000), UNPACKED_1x1( 0.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R16G16B16A16_FLOAT, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x3c00, 0x0000, 0x0000, 0x0000), UNPACKED_1x1( 1.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R16G16B16A16_FLOAT, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0xbc00, 0x0000, 0x0000, 0x0000), UNPACKED_1x1(-1.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R16G16B16A16_FLOAT, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x3c00, 0x0000, 0x0000), UNPACKED_1x1( 0.0, 1.0, 0.0, 0.0)}, + {PIPE_FORMAT_R16G16B16A16_FLOAT, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0xbc00, 0x0000, 0x0000), UNPACKED_1x1( 0.0, -1.0, 0.0, 0.0)}, + {PIPE_FORMAT_R16G16B16A16_FLOAT, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x3c00, 0x0000), UNPACKED_1x1( 0.0, 0.0, 1.0, 0.0)}, + {PIPE_FORMAT_R16G16B16A16_FLOAT, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0xbc00, 0x0000), UNPACKED_1x1( 0.0, 0.0, -1.0, 0.0)}, + {PIPE_FORMAT_R16G16B16A16_FLOAT, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0x3c00), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R16G16B16A16_FLOAT, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0xbc00), UNPACKED_1x1( 0.0, 0.0, 0.0, -1.0)}, + {PIPE_FORMAT_R16G16B16A16_FLOAT, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x3c00, 0x3c00, 0x3c00, 0x3c00), UNPACKED_1x1( 1.0, 1.0, 1.0, 1.0)}, + + /* + * 32-bit fixed point formats + */ + + {PIPE_FORMAT_R32_FIXED, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32_FIXED, PACKED_1x32(0xffffffff), PACKED_1x32(0x00010000), UNPACKED_1x1( 1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32_FIXED, PACKED_1x32(0xffffffff), PACKED_1x32(0xffff0000), UNPACKED_1x1( -1.0, 0.0, 0.0, 1.0)}, + + {PIPE_FORMAT_R32G32_FIXED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32_FIXED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00010000, 0x00000000), UNPACKED_1x1( 1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32_FIXED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0xffff0000, 0x00000000), UNPACKED_1x1(-1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32_FIXED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0x00010000), UNPACKED_1x1( 0.0, 1.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32_FIXED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0xffff0000), UNPACKED_1x1( 0.0, -1.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32_FIXED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00010000, 0x00010000), UNPACKED_1x1( 1.0, 1.0, 0.0, 1.0)}, + + {PIPE_FORMAT_R32G32B32_FIXED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32B32_FIXED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00010000, 0x00000000, 0x00000000), UNPACKED_1x1( 1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32B32_FIXED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0xffff0000, 0x00000000, 0x00000000), UNPACKED_1x1(-1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32B32_FIXED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00010000, 0x00000000), UNPACKED_1x1( 0.0, 1.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32B32_FIXED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0xffff0000, 0x00000000), UNPACKED_1x1( 0.0, -1.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32B32_FIXED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0x00010000), UNPACKED_1x1( 0.0, 0.0, 1.0, 1.0)}, + {PIPE_FORMAT_R32G32B32_FIXED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0xffff0000), UNPACKED_1x1( 0.0, 0.0, -1.0, 1.0)}, + {PIPE_FORMAT_R32G32B32_FIXED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00010000, 0x00010000, 0x00010000), UNPACKED_1x1( 1.0, 1.0, 1.0, 1.0)}, + + {PIPE_FORMAT_R32G32B32A32_FIXED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R32G32B32A32_FIXED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00010000, 0x00000000, 0x00000000, 0x00000000), UNPACKED_1x1( 1.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R32G32B32A32_FIXED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0xffff0000, 0x00000000, 0x00000000, 0x00000000), UNPACKED_1x1(-1.0, 0.0, 0.0, 0.0)}, + {PIPE_FORMAT_R32G32B32A32_FIXED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00010000, 0x00000000, 0x00000000), UNPACKED_1x1( 0.0, 1.0, 0.0, 0.0)}, + {PIPE_FORMAT_R32G32B32A32_FIXED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0xffff0000, 0x00000000, 0x00000000), UNPACKED_1x1( 0.0, -1.0, 0.0, 0.0)}, + {PIPE_FORMAT_R32G32B32A32_FIXED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00010000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, 1.0, 0.0)}, + {PIPE_FORMAT_R32G32B32A32_FIXED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0xffff0000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, -1.0, 0.0)}, + {PIPE_FORMAT_R32G32B32A32_FIXED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0x00010000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R32G32B32A32_FIXED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0xffff0000), UNPACKED_1x1( 0.0, 0.0, 0.0, -1.0)}, + {PIPE_FORMAT_R32G32B32A32_FIXED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00010000, 0x00010000, 0x00010000, 0x00010000), UNPACKED_1x1( 1.0, 1.0, 1.0, 1.0)}, + + /* + * D3D9 specific vertex formats + */ + + {PIPE_FORMAT_R10G10B10X2_USCALED, PACKED_1x32(0x3fffffff), PACKED_1x32(0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R10G10B10X2_USCALED, PACKED_1x32(0x3fffffff), PACKED_1x32(0x000003ff), UNPACKED_1x1(1023.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R10G10B10X2_USCALED, PACKED_1x32(0x3fffffff), PACKED_1x32(0x000ffc00), UNPACKED_1x1( 0.0, 1023.0, 0.0, 1.0)}, + {PIPE_FORMAT_R10G10B10X2_USCALED, PACKED_1x32(0x3fffffff), PACKED_1x32(0x3ff00000), UNPACKED_1x1( 0.0, 0.0, 1023.0, 1.0)}, + {PIPE_FORMAT_R10G10B10X2_USCALED, PACKED_1x32(0x3fffffff), PACKED_1x32(0x3fffffff), UNPACKED_1x1(1023.0, 1023.0, 1023.0, 1.0)}, + + {PIPE_FORMAT_R10G10B10X2_SNORM, PACKED_1x32(0x3fffffff), PACKED_1x32(0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R10G10B10X2_SNORM, PACKED_1x32(0x3fffffff), PACKED_1x32(0x000001ff), UNPACKED_1x1( 1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R10G10B10X2_SNORM, PACKED_1x32(0x3fffffff), PACKED_1x32(0x00000201), UNPACKED_1x1(-1.0, 0.0, 0.0, 1.0)}, + {PIPE_FORMAT_R10G10B10X2_SNORM, PACKED_1x32(0x3fffffff), PACKED_1x32(0x0007fc00), UNPACKED_1x1( 0.0, 1.0, 0.0, 1.0)}, + {PIPE_FORMAT_R10G10B10X2_SNORM, PACKED_1x32(0x3fffffff), PACKED_1x32(0x00080400), UNPACKED_1x1( 0.0, -1.0, 0.0, 1.0)}, + {PIPE_FORMAT_R10G10B10X2_SNORM, PACKED_1x32(0x3fffffff), PACKED_1x32(0x1ff00000), UNPACKED_1x1( 0.0, 0.0, 1.0, 1.0)}, + {PIPE_FORMAT_R10G10B10X2_SNORM, PACKED_1x32(0x3fffffff), PACKED_1x32(0x20100000), UNPACKED_1x1( 0.0, 0.0, -1.0, 1.0)}, + + /* + * Special formats that not fit anywhere else + */ + +}; + + +const unsigned util_format_nr_test_cases = Elements(util_format_test_cases); diff --git a/mesalib/src/gallium/auxiliary/util/u_format_tests.h b/mesalib/src/gallium/auxiliary/util/u_format_tests.h new file mode 100644 index 000000000..5de1cb237 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_format_tests.h @@ -0,0 +1,71 @@ +/************************************************************************** + * + * 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 SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 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 U_FORMAT_TESTS_H_ +#define U_FORMAT_TESTS_H_ + + +#include "pipe/p_compiler.h" +#include "pipe/p_format.h" + + +#define UTIL_FORMAT_MAX_PACKED_BYTES 16 +#define UTIL_FORMAT_MAX_UNPACKED_WIDTH 4 +#define UTIL_FORMAT_MAX_UNPACKED_HEIGHT 4 + + +/** + * A (packed, unpacked) color pair. + */ +struct util_format_test_case +{ + enum pipe_format format; + + /** + * Mask of the bits that actually meaningful data. Used to mask out the + * "X" channels. + */ + uint8_t mask[UTIL_FORMAT_MAX_PACKED_BYTES]; + + uint8_t packed[UTIL_FORMAT_MAX_PACKED_BYTES]; + + /** + * RGBA. + */ + double unpacked[UTIL_FORMAT_MAX_UNPACKED_HEIGHT][UTIL_FORMAT_MAX_UNPACKED_WIDTH][4]; +}; + + +extern const struct util_format_test_case +util_format_test_cases[]; + + +extern const unsigned util_format_nr_test_cases; + + +#endif /* U_FORMAT_TESTS_H_ */ diff --git a/mesalib/src/gallium/auxiliary/util/u_format_yuv.c b/mesalib/src/gallium/auxiliary/util/u_format_yuv.c new file mode 100644 index 000000000..d1852af2d --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_format_yuv.c @@ -0,0 +1,1047 @@ +/************************************************************************** + * + * 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 SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 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. + * + **************************************************************************/ + + +/** + * @file + * YUV and RGB subsampled formats conversion. + * + * @author Jose Fonseca + */ + + +#include "util/u_format_yuv.h" + + +void +util_format_r8g8_b8g8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + + for (y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint32_t *src = (const uint32_t *)src_row; + uint32_t value; + float r, g0, g1, b; + + for (x = 0; x + 1 < width; x += 2) { + value = *src++; + +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + + r = ubyte_to_float((value >> 0) & 0xff); + g0 = ubyte_to_float((value >> 8) & 0xff); + b = ubyte_to_float((value >> 16) & 0xff); + g1 = ubyte_to_float((value >> 24) & 0xff); + + dst[0] = r; /* r */ + dst[1] = g0; /* g */ + dst[2] = b; /* b */ + dst[3] = 1.0f; /* a */ + dst += 4; + + dst[0] = r; /* r */ + dst[1] = g1; /* g */ + dst[2] = b; /* b */ + dst[3] = 1.0f; /* a */ + dst += 4; + } + + if (x < width) { + value = *src; + +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + + r = ubyte_to_float((value >> 0) & 0xff); + g0 = ubyte_to_float((value >> 8) & 0xff); + b = ubyte_to_float((value >> 16) & 0xff); + g1 = ubyte_to_float((value >> 24) & 0xff); + + dst[0] = r; /* r */ + dst[1] = g0; /* g */ + dst[2] = b; /* b */ + dst[3] = 1.0f; /* a */ + } + + src_row += src_stride/sizeof(*src_row); + dst_row += dst_stride/sizeof(*dst_row); + } +} + + +void +util_format_r8g8_b8g8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + + for (y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint32_t *src = (const uint32_t *)src_row; + uint32_t value; + uint8_t r, g0, g1, b; + + for (x = 0; x + 1 < width; x += 2) { + value = *src++; + +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + + r = (value >> 0) & 0xff; + g0 = (value >> 8) & 0xff; + b = (value >> 16) & 0xff; + g1 = (value >> 24) & 0xff; + + dst[0] = r; /* r */ + dst[1] = g0; /* g */ + dst[2] = b; /* b */ + dst[3] = 0xff; /* a */ + dst += 4; + + dst[0] = r; /* r */ + dst[1] = g1; /* g */ + dst[2] = b; /* b */ + dst[3] = 0xff; /* a */ + dst += 4; + } + + if (x < width) { + value = *src; + +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + + r = (value >> 0) & 0xff; + g0 = (value >> 8) & 0xff; + b = (value >> 16) & 0xff; + g1 = (value >> 24) & 0xff; + + dst[0] = r; /* r */ + dst[1] = g0; /* g */ + dst[2] = b; /* b */ + dst[3] = 0xff; /* a */ + } + + src_row += src_stride/sizeof(*src_row); + dst_row += dst_stride/sizeof(*dst_row); + } +} + + +void +util_format_r8g8_b8g8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, + const float *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + + for (y = 0; y < height; y += 1) { + const float *src = src_row; + uint32_t *dst = (uint32_t *)dst_row; + float r, g0, g1, b; + uint32_t value; + + for (x = 0; x + 1 < width; x += 2) { + r = 0.5f*(src[0] + src[4]); + g0 = src[1]; + g1 = src[5]; + b = 0.5f*(src[2] + src[6]); + + value = float_to_ubyte(r); + value |= float_to_ubyte(g0) << 8; + value |= float_to_ubyte(b) << 16; + value |= float_to_ubyte(g1) << 24; + +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + + *dst++ = value; + + src += 8; + } + + if (x < width) { + r = src[0]; + g0 = src[1]; + g1 = 0; + b = src[2]; + + value = float_to_ubyte(r); + value |= float_to_ubyte(g0) << 8; + value |= float_to_ubyte(b) << 16; + value |= float_to_ubyte(g1) << 24; + +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + + *dst = value; + } + + dst_row += dst_stride/sizeof(*dst_row); + src_row += src_stride/sizeof(*src_row); + } +} + + +void +util_format_r8g8_b8g8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + + for (y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint32_t *dst = (uint32_t *)dst_row; + uint32_t r, g0, g1, b; + uint32_t value; + + for (x = 0; x + 1 < width; x += 2) { + r = (src[0] + src[4] + 1) >> 1; + g0 = src[1]; + g1 = src[5]; + b = (src[2] + src[6] + 1) >> 1; + + value = r; + value |= g0 << 8; + value |= b << 16; + value |= g1 << 24; + +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + + *dst++ = value; + + src += 8; + } + + if (x < width) { + r = src[0]; + g0 = src[1]; + g1 = 0; + b = src[2]; + + value = r; + value |= g0 << 8; + value |= b << 16; + value |= g1 << 24; + +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + + *dst = value; + } + + dst_row += dst_stride/sizeof(*dst_row); + src_row += src_stride/sizeof(*src_row); + } +} + + +void +util_format_r8g8_b8g8_unorm_fetch_rgba_float(float *dst, const uint8_t *src, + unsigned i, unsigned j) +{ + assert(i < 2); + assert(j < 1); + + dst[0] = ubyte_to_float(src[0]); /* r */ + dst[1] = ubyte_to_float(src[1 + 2*i]); /* g */ + dst[2] = ubyte_to_float(src[2]); /* b */ + dst[3] = 1.0f; /* a */ +} + + +void +util_format_g8r8_g8b8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + + for (y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint32_t *src = (const uint32_t *)src_row; + uint32_t value; + float r, g0, g1, b; + + for (x = 0; x + 1 < width; x += 2) { + value = *src++; + +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + + g0 = ubyte_to_float((value >> 0) & 0xff); + r = ubyte_to_float((value >> 8) & 0xff); + g1 = ubyte_to_float((value >> 16) & 0xff); + b = ubyte_to_float((value >> 24) & 0xff); + + dst[0] = r; /* r */ + dst[1] = g0; /* g */ + dst[2] = b; /* b */ + dst[3] = 1.0f; /* a */ + dst += 4; + + dst[0] = r; /* r */ + dst[1] = g1; /* g */ + dst[2] = b; /* b */ + dst[3] = 1.0f; /* a */ + dst += 4; + } + + if (x < width) { + value = *src; + +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + + g0 = ubyte_to_float((value >> 0) & 0xff); + r = ubyte_to_float((value >> 8) & 0xff); + g1 = ubyte_to_float((value >> 16) & 0xff); + b = ubyte_to_float((value >> 24) & 0xff); + + dst[0] = r; /* r */ + dst[1] = g0; /* g */ + dst[2] = b; /* b */ + dst[3] = 1.0f; /* a */ + } + + src_row += src_stride/sizeof(*src_row); + dst_row += dst_stride/sizeof(*dst_row); + } +} + + +void +util_format_g8r8_g8b8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + + for (y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint32_t *src = (const uint32_t *)src_row; + uint32_t value; + uint8_t r, g0, g1, b; + + for (x = 0; x + 1 < width; x += 2) { + value = *src++; + +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + + g0 = (value >> 0) & 0xff; + r = (value >> 8) & 0xff; + g1 = (value >> 16) & 0xff; + b = (value >> 24) & 0xff; + + dst[0] = r; /* r */ + dst[1] = g0; /* g */ + dst[2] = b; /* b */ + dst[3] = 0xff; /* a */ + dst += 4; + + dst[0] = r; /* r */ + dst[1] = g1; /* g */ + dst[2] = b; /* b */ + dst[3] = 0xff; /* a */ + dst += 4; + } + + if (x < width) { + value = *src; + +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + + g0 = (value >> 0) & 0xff; + r = (value >> 8) & 0xff; + g1 = (value >> 16) & 0xff; + b = (value >> 24) & 0xff; + + dst[0] = r; /* r */ + dst[1] = g0; /* g */ + dst[2] = b; /* b */ + dst[3] = 0xff; /* a */ + } + + src_row += src_stride/sizeof(*src_row); + dst_row += dst_stride/sizeof(*dst_row); + } +} + + +void +util_format_g8r8_g8b8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, + const float *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + + for (y = 0; y < height; y += 1) { + const float *src = src_row; + uint32_t *dst = (uint32_t *)dst_row; + float r, g0, g1, b; + uint32_t value; + + for (x = 0; x + 1 < width; x += 2) { + r = 0.5f*(src[0] + src[4]); + g0 = src[1]; + g1 = src[5]; + b = 0.5f*(src[2] + src[6]); + + value = float_to_ubyte(g0); + value |= float_to_ubyte(r) << 8; + value |= float_to_ubyte(g1) << 16; + value |= float_to_ubyte(b) << 24; + +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + + *dst++ = value; + + src += 8; + } + + if (x < width) { + r = src[0]; + g0 = src[1]; + g1 = 0; + b = src[2]; + + value = float_to_ubyte(g0); + value |= float_to_ubyte(r) << 8; + value |= float_to_ubyte(g1) << 16; + value |= float_to_ubyte(b) << 24; + +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + + *dst = value; + } + + dst_row += dst_stride/sizeof(*dst_row); + src_row += src_stride/sizeof(*src_row); + } +} + + +void +util_format_g8r8_g8b8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + + for (y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint32_t *dst = (uint32_t *)dst_row; + uint32_t r, g0, g1, b; + uint32_t value; + + for (x = 0; x + 1 < width; x += 2) { + r = (src[0] + src[4] + 1) >> 1; + g0 = src[1]; + g1 = src[5]; + b = (src[2] + src[6] + 1) >> 1; + + value = g0; + value |= r << 8; + value |= g1 << 16; + value |= b << 24; + +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + + *dst++ = value; + + src += 8; + } + + if (x < width) { + r = src[0]; + g0 = src[1]; + g1 = 0; + b = src[2]; + + value = g0; + value |= r << 8; + value |= g1 << 16; + value |= b << 24; + +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + + *dst = value; + } + + dst_row += dst_stride/sizeof(*dst_row); + src_row += src_stride/sizeof(*src_row); + } +} + + +void +util_format_g8r8_g8b8_unorm_fetch_rgba_float(float *dst, const uint8_t *src, + unsigned i, unsigned j) +{ + assert(i < 2); + assert(j < 1); + + dst[0] = ubyte_to_float(src[1]); /* r */ + dst[1] = ubyte_to_float(src[0 + 2*i]); /* g */ + dst[2] = ubyte_to_float(src[3]); /* b */ + dst[3] = 1.0f; /* a */ +} + + +void +util_format_uyvy_unpack_rgba_float(float *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + + for (y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint32_t *src = (const uint32_t *)src_row; + uint32_t value; + uint8_t y0, y1, u, v; + + for (x = 0; x + 1 < width; x += 2) { + value = *src++; + +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + + u = (value >> 0) & 0xff; + y0 = (value >> 8) & 0xff; + v = (value >> 16) & 0xff; + y1 = (value >> 24) & 0xff; + + util_format_yuv_to_rgb_float(y0, u, v, &dst[0], &dst[1], &dst[2]); + dst[3] = 1.0f; /* a */ + dst += 4; + + util_format_yuv_to_rgb_float(y1, u, v, &dst[0], &dst[1], &dst[2]); + dst[3] = 1.0f; /* a */ + dst += 4; + } + + if (x < width) { + value = *src; + +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + + u = (value >> 0) & 0xff; + y0 = (value >> 8) & 0xff; + v = (value >> 16) & 0xff; + y1 = (value >> 24) & 0xff; + + util_format_yuv_to_rgb_float(y0, u, v, &dst[0], &dst[1], &dst[2]); + dst[3] = 1.0f; /* a */ + } + + src_row += src_stride/sizeof(*src_row); + dst_row += dst_stride/sizeof(*dst_row); + } +} + + +void +util_format_uyvy_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + + for (y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint32_t *src = (const uint32_t *)src_row; + uint32_t value; + uint8_t y0, y1, u, v; + + for (x = 0; x + 1 < width; x += 2) { + value = *src++; + +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + + u = (value >> 0) & 0xff; + y0 = (value >> 8) & 0xff; + v = (value >> 16) & 0xff; + y1 = (value >> 24) & 0xff; + + util_format_yuv_to_rgb_8unorm(y0, u, v, &dst[0], &dst[1], &dst[2]); + dst[3] = 0xff; /* a */ + dst += 4; + + util_format_yuv_to_rgb_8unorm(y1, u, v, &dst[0], &dst[1], &dst[2]); + dst[3] = 0xff; /* a */ + dst += 4; + } + + if (x < width) { + value = *src; + +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + + u = (value >> 0) & 0xff; + y0 = (value >> 8) & 0xff; + v = (value >> 16) & 0xff; + y1 = (value >> 24) & 0xff; + + util_format_yuv_to_rgb_8unorm(y0, u, v, &dst[0], &dst[1], &dst[2]); + dst[3] = 0xff; /* a */ + } + + src_row += src_stride/sizeof(*src_row); + dst_row += dst_stride/sizeof(*dst_row); + } +} + + +void +util_format_uyvy_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, + const float *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + + for (y = 0; y < height; y += 1) { + const float *src = src_row; + uint32_t *dst = (uint32_t *)dst_row; + uint8_t y0, y1, u, v; + uint32_t value; + + for (x = 0; x + 1 < width; x += 2) { + uint8_t y0, y1, u0, u1, v0, v1, u, v; + + util_format_rgb_float_to_yuv(src[0], src[1], src[2], + &y0, &u0, &v0); + util_format_rgb_float_to_yuv(src[4], src[5], src[6], + &y1, &u1, &v1); + + u = (u0 + u1 + 1) >> 1; + v = (v0 + v1 + 1) >> 1; + + value = u; + value |= y0 << 8; + value |= v << 16; + value |= y1 << 24; + +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + + *dst++ = value; + + src += 8; + } + + if (x < width) { + util_format_rgb_float_to_yuv(src[0], src[1], src[2], + &y0, &u, &v); + y1 = 0; + + value = u; + value |= y0 << 8; + value |= v << 16; + value |= y1 << 24; + +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + + *dst = value; + } + + dst_row += dst_stride/sizeof(*dst_row); + src_row += src_stride/sizeof(*src_row); + } +} + + +void +util_format_uyvy_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + + for (y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint32_t *dst = (uint32_t *)dst_row; + uint8_t y0, y1, u, v; + uint32_t value; + + for (x = 0; x + 1 < width; x += 2) { + uint8_t y0, y1, u0, u1, v0, v1, u, v; + + util_format_rgb_8unorm_to_yuv(src[0], src[1], src[2], + &y0, &u0, &v0); + util_format_rgb_8unorm_to_yuv(src[4], src[5], src[6], + &y1, &u1, &v1); + + u = (u0 + u1 + 1) >> 1; + v = (v0 + v1 + 1) >> 1; + + value = u; + value |= y0 << 8; + value |= v << 16; + value |= y1 << 24; + +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + + *dst++ = value; + + src += 8; + } + + if (x < width) { + util_format_rgb_8unorm_to_yuv(src[0], src[1], src[2], + &y0, &u, &v); + y1 = 0; + + value = u; + value |= y0 << 8; + value |= v << 16; + value |= y1 << 24; + +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + + *dst = value; + } + + dst_row += dst_stride/sizeof(*dst_row); + src_row += src_stride/sizeof(*src_row); + } +} + + +void +util_format_uyvy_fetch_rgba_float(float *dst, const uint8_t *src, + unsigned i, unsigned j) +{ + uint8_t y, u, v; + + assert(i < 2); + assert(j < 1); + + y = src[1 + i*2]; + u = src[0]; + v = src[2]; + + util_format_yuv_to_rgb_float(y, u, v, &dst[0], &dst[1], &dst[2]); + + dst[3] = 1.0f; +} + + +void +util_format_yuyv_unpack_rgba_float(float *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + + for (y = 0; y < height; y += 1) { + float *dst = dst_row; + const uint32_t *src = (const uint32_t *)src_row; + uint32_t value; + uint8_t y0, y1, u, v; + + for (x = 0; x + 1 < width; x += 2) { + value = *src++; + +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + + y0 = (value >> 0) & 0xff; + u = (value >> 8) & 0xff; + y1 = (value >> 16) & 0xff; + v = (value >> 24) & 0xff; + + util_format_yuv_to_rgb_float(y0, u, v, &dst[0], &dst[1], &dst[2]); + dst[3] = 1.0f; /* a */ + dst += 4; + + util_format_yuv_to_rgb_float(y1, u, v, &dst[0], &dst[1], &dst[2]); + dst[3] = 1.0f; /* a */ + dst += 4; + } + + if (x < width) { + value = *src; + +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + + y0 = (value >> 0) & 0xff; + u = (value >> 8) & 0xff; + y1 = (value >> 16) & 0xff; + v = (value >> 24) & 0xff; + + util_format_yuv_to_rgb_float(y0, u, v, &dst[0], &dst[1], &dst[2]); + dst[3] = 1.0f; /* a */ + } + + src_row += src_stride/sizeof(*src_row); + dst_row += dst_stride/sizeof(*dst_row); + } +} + + +void +util_format_yuyv_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + + for (y = 0; y < height; y += 1) { + uint8_t *dst = dst_row; + const uint32_t *src = (const uint32_t *)src_row; + uint32_t value; + uint8_t y0, y1, u, v; + + for (x = 0; x + 1 < width; x += 2) { + value = *src++; + +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + + y0 = (value >> 0) & 0xff; + u = (value >> 8) & 0xff; + y1 = (value >> 16) & 0xff; + v = (value >> 24) & 0xff; + + util_format_yuv_to_rgb_8unorm(y0, u, v, &dst[0], &dst[1], &dst[2]); + dst[3] = 0xff; /* a */ + dst += 4; + + util_format_yuv_to_rgb_8unorm(y1, u, v, &dst[0], &dst[1], &dst[2]); + dst[3] = 0xff; /* a */ + dst += 4; + } + + if (x < width) { + value = *src; + +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + + y0 = (value >> 0) & 0xff; + u = (value >> 8) & 0xff; + y1 = (value >> 16) & 0xff; + v = (value >> 24) & 0xff; + + util_format_yuv_to_rgb_8unorm(y0, u, v, &dst[0], &dst[1], &dst[2]); + dst[3] = 0xff; /* a */ + } + + src_row += src_stride/sizeof(*src_row); + dst_row += dst_stride/sizeof(*dst_row); + } +} + + +void +util_format_yuyv_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, + const float *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + + for (y = 0; y < height; y += 1) { + const float *src = src_row; + uint32_t *dst = (uint32_t *)dst_row; + uint8_t y0, y1, u, v; + uint32_t value; + + for (x = 0; x + 1 < width; x += 2) { + uint8_t y0, y1, u0, u1, v0, v1, u, v; + + util_format_rgb_float_to_yuv(src[0], src[1], src[2], + &y0, &u0, &v0); + util_format_rgb_float_to_yuv(src[4], src[5], src[6], + &y1, &u1, &v1); + + u = (u0 + u1 + 1) >> 1; + v = (v0 + v1 + 1) >> 1; + + value = y0; + value |= u << 8; + value |= y1 << 16; + value |= v << 24; + +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + + *dst++ = value; + + src += 8; + } + + if (x < width) { + util_format_rgb_float_to_yuv(src[0], src[1], src[2], + &y0, &u, &v); + y1 = 0; + + value = y0; + value |= u << 8; + value |= y1 << 16; + value |= v << 24; + +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + + *dst = value; + } + + dst_row += dst_stride/sizeof(*dst_row); + src_row += src_stride/sizeof(*src_row); + } +} + + +void +util_format_yuyv_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + + for (y = 0; y < height; y += 1) { + const uint8_t *src = src_row; + uint32_t *dst = (uint32_t *)dst_row; + uint8_t y0, y1, u, v; + uint32_t value; + + for (x = 0; x + 1 < width; x += 2) { + uint8_t y0, y1, u0, u1, v0, v1, u, v; + + util_format_rgb_8unorm_to_yuv(src[0], src[1], src[2], + &y0, &u0, &v0); + util_format_rgb_8unorm_to_yuv(src[4], src[5], src[6], + &y1, &u1, &v1); + + u = (u0 + u1 + 1) >> 1; + v = (v0 + v1 + 1) >> 1; + + value = y0; + value |= u << 8; + value |= y1 << 16; + value |= v << 24; + +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + + *dst++ = value; + + src += 8; + } + + if (x < width) { + util_format_rgb_8unorm_to_yuv(src[0], src[1], src[2], + &y0, &u, &v); + y1 = 0; + + value = y0; + value |= u << 8; + value |= y1 << 16; + value |= v << 24; + +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + + *dst = value; + } + + dst_row += dst_stride/sizeof(*dst_row); + src_row += src_stride/sizeof(*src_row); + } +} + + +void +util_format_yuyv_fetch_rgba_float(float *dst, const uint8_t *src, + unsigned i, unsigned j) +{ + uint8_t y, u, v; + + assert(i < 2); + assert(j < 1); + + y = src[0 + i*2]; + u = src[1]; + v = src[3]; + + util_format_yuv_to_rgb_float(y, u, v, &dst[0], &dst[1], &dst[2]); + + dst[3] = 1.0f; +} diff --git a/mesalib/src/gallium/auxiliary/util/u_format_yuv.h b/mesalib/src/gallium/auxiliary/util/u_format_yuv.h new file mode 100644 index 000000000..d2c403ded --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_format_yuv.h @@ -0,0 +1,223 @@ +/************************************************************************** + * + * 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 SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 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. + * + **************************************************************************/ + + +/** + * @file + * YUV colorspace conversion. + * + * @author Brian Paul + * @author Michal Krol + * @author Jose Fonseca + * + * See also: + * - http://www.fourcc.org/fccyvrgb.php + * - http://msdn.microsoft.com/en-us/library/ms893078 + * - http://en.wikipedia.org/wiki/YUV + */ + + +#ifndef U_FORMAT_YUV_H_ +#define U_FORMAT_YUV_H_ + + +#include "pipe/p_compiler.h" +#include "u_math.h" + + +/* + * TODO: Ensure we use consistent and right floating formulas, with enough + * precision in the coefficients. + */ + +static INLINE void +util_format_rgb_float_to_yuv(float r, float g, float b, + uint8_t *y, uint8_t *u, uint8_t *v) +{ + const float _r = CLAMP(r, 0.0f, 1.0f); + const float _g = CLAMP(g, 0.0f, 1.0f); + const float _b = CLAMP(b, 0.0f, 1.0f); + + const float scale = 255.0f; + + const int _y = scale * ( (0.257f * _r) + (0.504f * _g) + (0.098f * _b)); + const int _u = scale * (-(0.148f * _r) - (0.291f * _g) + (0.439f * _b)); + const int _v = scale * ( (0.439f * _r) - (0.368f * _g) - (0.071f * _b)); + + *y = _y + 16; + *u = _u + 128; + *v = _v + 128; +} + + +static INLINE void +util_format_yuv_to_rgb_float(uint8_t y, uint8_t u, uint8_t v, + float *r, float *g, float *b) +{ + const int _y = y - 16; + const int _u = u - 128; + const int _v = v - 128; + + const float y_factor = 255.0f / 219.0f; + + const float scale = 1.0f / 255.0f; + + *r = scale * (y_factor * _y + 1.596f * _v); + *g = scale * (y_factor * _y - 0.391f * _u - 0.813f * _v); + *b = scale * (y_factor * _y + 2.018f * _u ); +} + + +static INLINE void +util_format_rgb_8unorm_to_yuv(uint8_t r, uint8_t g, uint8_t b, + uint8_t *y, uint8_t *u, uint8_t *v) +{ + *y = (( 66 * r + 129 * g + 25 * b + 128) >> 8) + 16; + *u = (( -38 * r - 74 * g + 112 * b + 128) >> 8) + 128; + *v = (( 112 * r - 94 * g - 18 * b + 128) >> 8) + 128; +} + + +static INLINE void +util_format_yuv_to_rgb_8unorm(uint8_t y, uint8_t u, uint8_t v, + uint8_t *r, uint8_t *g, uint8_t *b) +{ + const int _y = y - 16; + const int _u = u - 128; + const int _v = v - 128; + + const int _r = (298 * _y + 409 * _v + 128) >> 8; + const int _g = (298 * _y - 100 * _u - 208 * _v + 128) >> 8; + const int _b = (298 * _y + 516 * _u + 128) >> 8; + + *r = CLAMP(_r, 0, 255); + *g = CLAMP(_g, 0, 255); + *b = CLAMP(_b, 0, 255); +} + + + +void +util_format_uyvy_unpack_rgba_float(float *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); + +void +util_format_uyvy_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); + +void +util_format_uyvy_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, + const float *src_row, unsigned src_stride, + unsigned width, unsigned height); + +void +util_format_uyvy_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); + +void +util_format_uyvy_fetch_rgba_float(float *dst, const uint8_t *src, + unsigned i, unsigned j); + +void +util_format_yuyv_unpack_rgba_float(float *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); + +void +util_format_yuyv_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); + +void +util_format_yuyv_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, + const float *src_row, unsigned src_stride, + unsigned width, unsigned height); + +void +util_format_yuyv_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); + +void +util_format_yuyv_fetch_rgba_float(float *dst, const uint8_t *src, + unsigned i, unsigned j); + + +void +util_format_r8g8_b8g8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); + +void +util_format_r8g8_b8g8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); + +void +util_format_r8g8_b8g8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, + const float *src_row, unsigned src_stride, + unsigned width, unsigned height); + +void +util_format_r8g8_b8g8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); + +void +util_format_r8g8_b8g8_unorm_fetch_rgba_float(float *dst, const uint8_t *src, + unsigned i, unsigned j); + +void +util_format_g8r8_g8b8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); + +void +util_format_g8r8_g8b8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); + +void +util_format_g8r8_g8b8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, + const float *src_row, unsigned src_stride, + unsigned width, unsigned height); + +void +util_format_g8r8_g8b8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height); + +void +util_format_g8r8_g8b8_unorm_fetch_rgba_float(float *dst, const uint8_t *src, + unsigned i, unsigned j); + + + +#endif /* U_FORMAT_YUV_H_ */ diff --git a/mesalib/src/gallium/auxiliary/util/u_format_zs.c b/mesalib/src/gallium/auxiliary/util/u_format_zs.c new file mode 100644 index 000000000..7fdaf626e --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_format_zs.c @@ -0,0 +1,973 @@ +/************************************************************************** + * + * 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 SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 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 "u_debug.h" +#include "u_math.h" +#include "u_format_zs.h" + + +/* + * z32_unorm conversion functions + */ + +static INLINE uint16_t +z32_unorm_to_z16_unorm(uint32_t z) +{ + /* z * 0xffff / 0xffffffff */ + return z >> 16; +} + +static INLINE uint32_t +z16_unorm_to_z32_unorm(uint16_t z) +{ + /* z * 0xffffffff / 0xffff */ + return (z << 16) | z; +} + +static INLINE uint32_t +z32_unorm_to_z24_unorm(uint32_t z) +{ + /* z * 0xffffff / 0xffffffff */ + return z >> 8; +} + +static INLINE uint32_t +z24_unorm_to_z32_unorm(uint32_t z) +{ + /* z * 0xffffffff / 0xffffff */ + return (z << 8) | (z >> 16); +} + + +/* + * z32_float conversion functions + */ + +static INLINE uint16_t +z32_float_to_z16_unorm(float z) +{ + const float scale = 0xffff; + return (uint16_t)(z * scale); +} + +static INLINE float +z16_unorm_to_z32_float(uint16_t z) +{ + const float scale = 1.0 / 0xffff; + return (float)(z * scale); +} + +static INLINE uint32_t +z32_float_to_z24_unorm(float z) +{ + const double scale = 0xffffff; + return (uint32_t)(z * scale) & 0xffffff; +} + +static INLINE float +z24_unorm_to_z32_float(uint32_t z) +{ + const double scale = 1.0 / 0xffffff; + return (float)(z * scale); +} + +static INLINE uint32_t +z32_float_to_z32_unorm(float z) +{ + const double scale = 0xffffffff; + return (uint32_t)(z * scale); +} + +static INLINE float +z32_unorm_to_z32_float(uint32_t z) +{ + const double scale = 1.0 / 0xffffffff; + return (float)(z * scale); +} + + +void +util_format_s8_uscaled_unpack_s_8uscaled(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned y; + for(y = 0; y < height; ++y) { + memcpy(dst_row, src_row, width); + src_row += src_stride/sizeof(*src_row); + dst_row += dst_stride/sizeof(*dst_row); + } +} + +void +util_format_s8_uscaled_pack_s_8uscaled(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned y; + for(y = 0; y < height; ++y) { + memcpy(dst_row, src_row, width); + src_row += src_stride/sizeof(*src_row); + dst_row += dst_stride/sizeof(*dst_row); + } +} + +void +util_format_z16_unorm_unpack_z_float(float *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; ++y) { + float *dst = dst_row; + const uint16_t *src = (const uint16_t *)src_row; + for(x = 0; x < width; ++x) { + uint16_t value = *src++; +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap16(value); +#endif + *dst++ = z16_unorm_to_z32_float(value); + } + src_row += src_stride/sizeof(*src_row); + dst_row += dst_stride/sizeof(*dst_row); + } +} + +void +util_format_z16_unorm_pack_z_float(uint8_t *dst_row, unsigned dst_stride, + const float *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; ++y) { + const float *src = src_row; + uint16_t *dst = (uint16_t *)dst_row; + for(x = 0; x < width; ++x) { + uint16_t value; + value = z32_float_to_z16_unorm(*src++); +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap16(value); +#endif + *dst++ = value; + } + dst_row += dst_stride/sizeof(*dst_row); + src_row += src_stride/sizeof(*src_row); + } +} + +void +util_format_z16_unorm_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; ++y) { + uint32_t *dst = dst_row; + const uint16_t *src = (const uint16_t *)src_row; + for(x = 0; x < width; ++x) { + uint16_t value = *src++; +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap16(value); +#endif + *dst++ = z16_unorm_to_z32_unorm(value); + } + src_row += src_stride/sizeof(*src_row); + dst_row += dst_stride/sizeof(*dst_row); + } +} + +void +util_format_z16_unorm_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride, + const uint32_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; ++y) { + const uint32_t *src = src_row; + uint16_t *dst = (uint16_t *)dst_row; + for(x = 0; x < width; ++x) { + uint16_t value; + value = z32_unorm_to_z16_unorm(*src++); +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap16(value); +#endif + *dst++ = value; + } + dst_row += dst_stride/sizeof(*dst_row); + src_row += src_stride/sizeof(*src_row); + } +} + +void +util_format_z32_unorm_unpack_z_float(float *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; ++y) { + float *dst = dst_row; + const uint32_t *src = (const uint32_t *)src_row; + for(x = 0; x < width; ++x) { + uint32_t value = *src++; +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + *dst++ = z32_unorm_to_z32_float(value); + } + src_row += src_stride/sizeof(*src_row); + dst_row += dst_stride/sizeof(*dst_row); + } +} + +void +util_format_z32_unorm_pack_z_float(uint8_t *dst_row, unsigned dst_stride, + const float *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; ++y) { + const float *src = src_row; + uint32_t *dst = (uint32_t *)dst_row; + for(x = 0; x < width; ++x) { + uint32_t value; + value = z32_float_to_z32_unorm(*src++); +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + *dst++ = value; + } + dst_row += dst_stride/sizeof(*dst_row); + src_row += src_stride/sizeof(*src_row); + } +} + +void +util_format_z32_unorm_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned y; + for(y = 0; y < height; ++y) { + memcpy(dst_row, src_row, width * 4); + src_row += src_stride/sizeof(*src_row); + dst_row += dst_stride/sizeof(*dst_row); + } +} + +void +util_format_z32_unorm_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride, + const uint32_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned y; + for(y = 0; y < height; ++y) { + memcpy(dst_row, src_row, width * 4); + src_row += src_stride/sizeof(*src_row); + dst_row += dst_stride/sizeof(*dst_row); + } +} + +void +util_format_z32_float_unpack_z_float(float *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned y; + for(y = 0; y < height; ++y) { + memcpy(dst_row, src_row, width * 4); + src_row += src_stride/sizeof(*src_row); + dst_row += dst_stride/sizeof(*dst_row); + } +} + +void +util_format_z32_float_pack_z_float(uint8_t *dst_row, unsigned dst_stride, + const float *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned y; + for(y = 0; y < height; ++y) { + memcpy(dst_row, src_row, width * 4); + src_row += src_stride/sizeof(*src_row); + dst_row += dst_stride/sizeof(*dst_row); + } +} + +void +util_format_z32_float_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; ++y) { + uint32_t *dst = dst_row; + const float *src = (const float *)src_row; + for(x = 0; x < width; ++x) { + *dst++ = z32_float_to_z32_unorm(*src++); + } + src_row += src_stride/sizeof(*src_row); + dst_row += dst_stride/sizeof(*dst_row); + } +} + +void +util_format_z32_float_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride, + const uint32_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; ++y) { + const uint32_t *src = src_row; + float *dst = (float *)dst_row; + for(x = 0; x < width; ++x) { + *dst++ = z32_unorm_to_z32_float(*src++); + } + dst_row += dst_stride/sizeof(*dst_row); + src_row += src_stride/sizeof(*src_row); + } +} + +void +util_format_z24_unorm_s8_uscaled_unpack_z_float(float *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; ++y) { + float *dst = dst_row; + const uint32_t *src = (const uint32_t *)src_row; + for(x = 0; x < width; ++x) { + uint32_t value = *src++; +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + *dst++ = z24_unorm_to_z32_float(value & 0xffffff); + } + src_row += src_stride/sizeof(*src_row); + dst_row += dst_stride/sizeof(*dst_row); + } +} + +void +util_format_z24_unorm_s8_uscaled_pack_z_float(uint8_t *dst_row, unsigned dst_stride, + const float *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; ++y) { + const float *src = src_row; + uint32_t *dst = (uint32_t *)dst_row; + for(x = 0; x < width; ++x) { + uint32_t value = *dst; +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + value &= 0xff000000; + value |= z32_float_to_z24_unorm(*src++); +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + *dst++ = value; + } + dst_row += dst_stride/sizeof(*dst_row); + src_row += src_stride/sizeof(*src_row); + } +} + +void +util_format_z24_unorm_s8_uscaled_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; ++y) { + uint32_t *dst = dst_row; + const uint32_t *src = (const uint32_t *)src_row; + for(x = 0; x < width; ++x) { + uint32_t value = *src++; +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + *dst++ = z24_unorm_to_z32_unorm(value & 0xffffff); + } + src_row += src_stride/sizeof(*src_row); + dst_row += dst_stride/sizeof(*dst_row); + } +} + +void +util_format_z24_unorm_s8_uscaled_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride, + const uint32_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; ++y) { + const uint32_t *src = src_row; + uint32_t *dst = (uint32_t *)dst_row; + for(x = 0; x < width; ++x) { + uint32_t value= *dst; +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + value &= 0xff000000; + value |= z32_unorm_to_z24_unorm(*src++); +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + *dst++ = value; + } + dst_row += dst_stride/sizeof(*dst_row); + src_row += src_stride/sizeof(*src_row); + } +} + +void +util_format_z24_unorm_s8_uscaled_unpack_s_8uscaled(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; ++y) { + uint8_t *dst = dst_row; + const uint32_t *src = (const uint32_t *)src_row; + for(x = 0; x < width; ++x) { + uint32_t value = *src++; +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + *dst++ = value >> 24; + } + src_row += src_stride/sizeof(*src_row); + dst_row += dst_stride/sizeof(*dst_row); + } +} + +void +util_format_z24_unorm_s8_uscaled_pack_s_8uscaled(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; ++y) { + const uint8_t *src = src_row; + uint32_t *dst = (uint32_t *)dst_row; + for(x = 0; x < width; ++x) { + uint32_t value = *dst; +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + value &= 0x00ffffff; + value |= *src++ << 24; +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + *dst++ = value; + } + dst_row += dst_stride/sizeof(*dst_row); + src_row += src_stride/sizeof(*src_row); + } +} + +void +util_format_s8_uscaled_z24_unorm_unpack_z_float(float *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; ++y) { + float *dst = dst_row; + const uint32_t *src = (const uint32_t *)src_row; + for(x = 0; x < width; ++x) { + uint32_t value = *src++; +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + *dst++ = z24_unorm_to_z32_float(value >> 8); + } + src_row += src_stride/sizeof(*src_row); + dst_row += dst_stride/sizeof(*dst_row); + } +} + +void +util_format_s8_uscaled_z24_unorm_pack_z_float(uint8_t *dst_row, unsigned dst_stride, + const float *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; ++y) { + const float *src = src_row; + uint32_t *dst = (uint32_t *)dst_row; + for(x = 0; x < width; ++x) { + uint32_t value = *dst; +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + value &= 0x000000ff; + value |= z32_float_to_z24_unorm(*src++) << 8; +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + *dst++ = value; + } + dst_row += dst_stride/sizeof(*dst_row); + src_row += src_stride/sizeof(*src_row); + } +} + +void +util_format_s8_uscaled_z24_unorm_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; ++y) { + uint32_t *dst = dst_row; + const uint32_t *src = (const uint32_t *)src_row; + for(x = 0; x < width; ++x) { + uint32_t value = *src++; +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + *dst++ = z24_unorm_to_z32_unorm(value >> 8); + } + src_row += src_stride/sizeof(*src_row); + dst_row += dst_stride/sizeof(*dst_row); + } +} + +void +util_format_s8_uscaled_z24_unorm_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride, + const uint32_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; ++y) { + const uint32_t *src = src_row; + uint32_t *dst = (uint32_t *)dst_row; + for(x = 0; x < width; ++x) { + uint32_t value = *dst; +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + value &= 0x000000ff; + value |= *src++ & 0xffffff00; +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + *dst++ = value; + } + dst_row += dst_stride/sizeof(*dst_row); + src_row += src_stride/sizeof(*src_row); + } +} + +void +util_format_s8_uscaled_z24_unorm_unpack_s_8uscaled(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; ++y) { + uint8_t *dst = dst_row; + const uint32_t *src = (const uint32_t *)src_row; + for(x = 0; x < width; ++x) { + uint32_t value = *src++; +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + *dst++ = value & 0xff; + } + src_row += src_stride/sizeof(*src_row); + dst_row += dst_stride/sizeof(*dst_row); + } +} + +void +util_format_s8_uscaled_z24_unorm_pack_s_8uscaled(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; ++y) { + const uint8_t *src = src_row; + uint32_t *dst = (uint32_t *)dst_row; + for(x = 0; x < width; ++x) { + uint32_t value = *dst; +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + value &= 0xffffff00; + value |= *src++; +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + *dst++ = value; + } + dst_row += dst_stride/sizeof(*dst_row); + src_row += src_stride/sizeof(*src_row); + } +} + +void +util_format_z24x8_unorm_unpack_z_float(float *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; ++y) { + float *dst = dst_row; + const uint32_t *src = (const uint32_t *)src_row; + for(x = 0; x < width; ++x) { + uint32_t value = *src++; +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + *dst++ = z24_unorm_to_z32_float(value & 0xffffff); + } + src_row += src_stride/sizeof(*src_row); + dst_row += dst_stride/sizeof(*dst_row); + } +} + +void +util_format_z24x8_unorm_pack_z_float(uint8_t *dst_row, unsigned dst_stride, + const float *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; ++y) { + const float *src = src_row; + uint32_t *dst = (uint32_t *)dst_row; + for(x = 0; x < width; ++x) { + uint32_t value; + value = z32_float_to_z24_unorm(*src++); +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + *dst++ = value; + } + dst_row += dst_stride/sizeof(*dst_row); + src_row += src_stride/sizeof(*src_row); + } +} + +void +util_format_z24x8_unorm_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; ++y) { + uint32_t *dst = dst_row; + const uint32_t *src = (const uint32_t *)src_row; + for(x = 0; x < width; ++x) { + uint32_t value = *src++; +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + *dst++ = z24_unorm_to_z32_unorm(value & 0xffffff); + } + src_row += src_stride/sizeof(*src_row); + dst_row += dst_stride/sizeof(*dst_row); + } +} + +void +util_format_z24x8_unorm_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride, + const uint32_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; ++y) { + const uint32_t *src = src_row; + uint32_t *dst = (uint32_t *)dst_row; + for(x = 0; x < width; ++x) { + uint32_t value; + value = z32_unorm_to_z24_unorm(*src++); +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + *dst++ = value; + } + dst_row += dst_stride/sizeof(*dst_row); + src_row += src_stride/sizeof(*src_row); + } +} + +void +util_format_x8z24_unorm_unpack_z_float(float *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; ++y) { + float *dst = dst_row; + const uint32_t *src = (uint32_t *)src_row; + for(x = 0; x < width; ++x) { + uint32_t value = *src++; +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + *dst++ = z24_unorm_to_z32_float(value >> 8); + } + src_row += src_stride/sizeof(*src_row); + dst_row += dst_stride/sizeof(*dst_row); + } +} + +void +util_format_x8z24_unorm_pack_z_float(uint8_t *dst_row, unsigned dst_stride, + const float *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; ++y) { + const float *src = src_row; + uint32_t *dst = (uint32_t *)dst_row; + for(x = 0; x < width; ++x) { + uint32_t value; + value = z32_float_to_z24_unorm(*src++) << 8; +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + *dst++ = value; + } + dst_row += dst_stride/sizeof(*dst_row); + src_row += src_stride/sizeof(*src_row); + } +} + +void +util_format_x8z24_unorm_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; ++y) { + uint32_t *dst = dst_row; + const uint32_t *src = (const uint32_t *)src_row; + for(x = 0; x < width; ++x) { + uint32_t value = *src++; +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + *dst++ = z24_unorm_to_z32_unorm(value >> 8); + } + src_row += src_stride/sizeof(*src_row); + dst_row += dst_stride/sizeof(*dst_row); + } +} + +void +util_format_x8z24_unorm_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride, + const uint32_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; ++y) { + const uint32_t *src = src_row; + uint32_t *dst = (uint32_t *)dst_row; + for(x = 0; x < width; ++x) { + uint32_t value; + value = z32_unorm_to_z24_unorm(*src++) << 8; +#ifdef PIPE_ARCH_BIG_ENDIAN + value = util_bswap32(value); +#endif + *dst++ = value; + } + dst_row += dst_stride/sizeof(*dst_row); + src_row += src_stride/sizeof(*src_row); + } +} + +void +util_format_z32_float_s8x24_uscaled_unpack_z_float(float *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; ++y) { + float *dst = dst_row; + const float *src = (const float *)src_row; + for(x = 0; x < width; ++x) { + *dst = *src; + src += 2; + dst += 1; + } + src_row += src_stride/sizeof(*src_row); + dst_row += dst_stride/sizeof(*dst_row); + } +} + +void +util_format_z32_float_s8x24_uscaled_pack_z_float(uint8_t *dst_row, unsigned dst_stride, + const float *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; ++y) { + const float *src = src_row; + float *dst = (float *)dst_row; + for(x = 0; x < width; ++x) { + *dst = *src; + src += 1; + dst += 2; + } + dst_row += dst_stride/sizeof(*dst_row); + src_row += src_stride/sizeof(*src_row); + } +} + +void +util_format_z32_float_s8x24_uscaled_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; ++y) { + uint32_t *dst = dst_row; + const float *src = (const float *)src_row; + for(x = 0; x < width; ++x) { + *dst = z32_float_to_z32_unorm(*src); + src += 2; + dst += 1; + } + src_row += src_stride/sizeof(*src_row); + dst_row += dst_stride/sizeof(*dst_row); + } +} + +void +util_format_z32_float_s8x24_uscaled_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride, + const uint32_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; ++y) { + const uint32_t *src = src_row; + float *dst = (float *)dst_row; + for(x = 0; x < width; ++x) { + *dst++ = z32_unorm_to_z32_float(*src++); + } + dst_row += dst_stride/sizeof(*dst_row); + src_row += src_stride/sizeof(*src_row); + } +} + +void +util_format_z32_float_s8x24_uscaled_unpack_s_8uscaled(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; ++y) { + uint8_t *dst = dst_row; + const uint8_t *src = src_row + 4; + for(x = 0; x < width; ++x) { + *dst = *src; + src += 8; + dst += 1; + } + src_row += src_stride/sizeof(*src_row); + dst_row += dst_stride/sizeof(*dst_row); + } +} + +void +util_format_z32_float_s8x24_uscaled_pack_s_8uscaled(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + unsigned x, y; + for(y = 0; y < height; ++y) { + const uint8_t *src = src_row; + uint8_t *dst = dst_row + 4; + for(x = 0; x < width; ++x) { + *dst = *src; + src += 1; + dst += 8; + } + dst_row += dst_stride/sizeof(*dst_row); + src_row += src_stride/sizeof(*src_row); + } +} + + +void +util_format_x24s8_uscaled_unpack_s_8uscaled(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + util_format_z24_unorm_s8_uscaled_unpack_s_8uscaled(dst_row, dst_stride, + src_row, src_stride, + width, height); +} + +void +util_format_x24s8_uscaled_pack_s_8uscaled(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + util_format_z24_unorm_s8_uscaled_pack_s_8uscaled(dst_row, dst_stride, + src_row, src_stride, + width, height); +} + +void +util_format_s8x24_uscaled_unpack_s_8uscaled(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + util_format_s8_uscaled_z24_unorm_unpack_s_8uscaled(dst_row, dst_stride, + src_row, src_stride, + width, height); +} + +void +util_format_s8x24_uscaled_pack_s_8uscaled(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) +{ + util_format_s8_uscaled_z24_unorm_pack_s_8uscaled(dst_row, dst_stride, + src_row, src_stride, + width, height); +} + +void +util_format_x32_s8x24_uscaled_unpack_s_8uscaled(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + util_format_z32_float_s8x24_uscaled_unpack_s_8uscaled(dst_row, dst_stride, + src_row, src_stride, + width, height); + +} + +void +util_format_x32_s8x24_uscaled_pack_s_8uscaled(uint8_t *dst_row, unsigned dst_stride, + const uint8_t *src_row, unsigned src_stride, + unsigned width, unsigned height) +{ + util_format_z32_float_s8x24_uscaled_pack_s_8uscaled(dst_row, dst_stride, + src_row, src_stride, + width, height); +} diff --git a/mesalib/src/gallium/auxiliary/util/u_format_zs.h b/mesalib/src/gallium/auxiliary/util/u_format_zs.h new file mode 100644 index 000000000..c3d9f484f --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_format_zs.h @@ -0,0 +1,212 @@ +/************************************************************************** + * + * 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 SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 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 U_FORMAT_ZS_H_ +#define U_FORMAT_ZS_H_ + + +#include "pipe/p_compiler.h" + + +void +util_format_s8_uscaled_unpack_s_8uscaled(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + + +void +util_format_s8_uscaled_pack_s_8uscaled(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + + +void +util_format_z16_unorm_unpack_z_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + + +void +util_format_z16_unorm_pack_z_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); + + +void +util_format_z16_unorm_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + + +void +util_format_z16_unorm_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride, const uint32_t *src_row, unsigned src_stride, unsigned width, unsigned height); + + +void +util_format_z32_unorm_unpack_z_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + + +void +util_format_z32_unorm_pack_z_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); + + +void +util_format_z32_unorm_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + + +void +util_format_z32_unorm_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride, const uint32_t *src_row, unsigned src_stride, unsigned width, unsigned height); + + +void +util_format_z32_float_unpack_z_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + + +void +util_format_z32_float_pack_z_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); + + +void +util_format_z32_float_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + + +void +util_format_z32_float_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride, const uint32_t *src_row, unsigned src_stride, unsigned width, unsigned height); + + +void +util_format_z24_unorm_s8_uscaled_unpack_z_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + + +void +util_format_z24_unorm_s8_uscaled_pack_z_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); + + +void +util_format_z24_unorm_s8_uscaled_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + + +void +util_format_z24_unorm_s8_uscaled_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride, const uint32_t *src_row, unsigned src_stride, unsigned width, unsigned height); + + +void +util_format_z24_unorm_s8_uscaled_unpack_s_8uscaled(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + + +void +util_format_z24_unorm_s8_uscaled_pack_s_8uscaled(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + + +void +util_format_s8_uscaled_z24_unorm_unpack_z_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + + +void +util_format_s8_uscaled_z24_unorm_pack_z_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); + + +void +util_format_s8_uscaled_z24_unorm_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + + +void +util_format_s8_uscaled_z24_unorm_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride, const uint32_t *src_row, unsigned src_stride, unsigned width, unsigned height); + + +void +util_format_s8_uscaled_z24_unorm_unpack_s_8uscaled(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + + +void +util_format_s8_uscaled_z24_unorm_pack_s_8uscaled(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + + +void +util_format_z24x8_unorm_unpack_z_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + + +void +util_format_z24x8_unorm_pack_z_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); + + +void +util_format_z24x8_unorm_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + + +void +util_format_z24x8_unorm_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride, const uint32_t *src_row, unsigned src_stride, unsigned width, unsigned height); + + +void +util_format_x8z24_unorm_unpack_z_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + + +void +util_format_x8z24_unorm_pack_z_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); + + +void +util_format_x8z24_unorm_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + + +void +util_format_x8z24_unorm_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride, const uint32_t *src_row, unsigned src_stride, unsigned width, unsigned height); + + +void +util_format_z32_float_s8x24_uscaled_unpack_z_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + + +void +util_format_z32_float_s8x24_uscaled_pack_z_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height); + + +void +util_format_z32_float_s8x24_uscaled_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + + +void +util_format_z32_float_s8x24_uscaled_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride, const uint32_t *src_row, unsigned src_stride, unsigned width, unsigned height); + + +void +util_format_z32_float_s8x24_uscaled_unpack_s_8uscaled(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + + +void +util_format_z32_float_s8x24_uscaled_pack_s_8uscaled(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_x24s8_uscaled_unpack_s_8uscaled(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_x24s8_uscaled_pack_s_8uscaled(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_s8x24_uscaled_unpack_s_8uscaled(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_s8x24_uscaled_pack_s_8uscaled(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_x32_s8x24_uscaled_unpack_s_8uscaled(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); + +void +util_format_x32_s8x24_uscaled_pack_s_8uscaled(uint8_t *dst_row, unsigned dst_sride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height); +#endif /* U_FORMAT_ZS_H_ */ diff --git a/mesalib/src/gallium/auxiliary/util/u_framebuffer.c b/mesalib/src/gallium/auxiliary/util/u_framebuffer.c new file mode 100644 index 000000000..8d89c81c7 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_framebuffer.c @@ -0,0 +1,148 @@ +/************************************************************************** + * + * Copyright 2009-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. + * + **************************************************************************/ + +/** + * @file + * Framebuffer utility functions. + * + * @author Brian Paul + */ + + +#include "pipe/p_screen.h" +#include "pipe/p_state.h" +#include "pipe/p_defines.h" +#include "util/u_inlines.h" + +#include "util/u_memory.h" +#include "util/u_framebuffer.h" + + +/** + * Compare pipe_framebuffer_state objects. + * \return TRUE if same, FALSE if different + */ +boolean +util_framebuffer_state_equal(const struct pipe_framebuffer_state *dst, + const struct pipe_framebuffer_state *src) +{ + unsigned i; + + if (dst->width != src->width || + dst->height != src->height) + return FALSE; + + for (i = 0; i < Elements(src->cbufs); i++) { + if (dst->cbufs[i] != src->cbufs[i]) { + return FALSE; + } + } + + if (dst->nr_cbufs != src->nr_cbufs) { + return FALSE; + } + + if (dst->zsbuf != src->zsbuf) { + return FALSE; + } + + return TRUE; +} + + +/** + * Copy framebuffer state from src to dst, updating refcounts. + */ +void +util_copy_framebuffer_state(struct pipe_framebuffer_state *dst, + const struct pipe_framebuffer_state *src) +{ + unsigned i; + + dst->width = src->width; + dst->height = src->height; + + for (i = 0; i < src->nr_cbufs; i++) + pipe_surface_reference(&dst->cbufs[i], src->cbufs[i]); + + for (i = src->nr_cbufs; i < dst->nr_cbufs; i++) + pipe_surface_reference(&dst->cbufs[i], NULL); + + dst->nr_cbufs = src->nr_cbufs; + + pipe_surface_reference(&dst->zsbuf, src->zsbuf); +} + + +void +util_unreference_framebuffer_state(struct pipe_framebuffer_state *fb) +{ + unsigned i; + + for (i = 0; i < fb->nr_cbufs; i++) { + pipe_surface_reference(&fb->cbufs[i], NULL); + } + + pipe_surface_reference(&fb->zsbuf, NULL); + + fb->width = fb->height = 0; + fb->nr_cbufs = 0; +} + + +/* Where multiple sizes are allowed for framebuffer surfaces, find the + * minimum width and height of all bound surfaces. + */ +boolean +util_framebuffer_min_size(const struct pipe_framebuffer_state *fb, + unsigned *width, + unsigned *height) +{ + unsigned w = ~0; + unsigned h = ~0; + unsigned i; + + for (i = 0; i < fb->nr_cbufs; i++) { + w = MIN2(w, fb->cbufs[i]->width); + h = MIN2(h, fb->cbufs[i]->height); + } + + if (fb->zsbuf) { + w = MIN2(w, fb->zsbuf->width); + h = MIN2(h, fb->zsbuf->height); + } + + if (w == ~0) { + *width = 0; + *height = 0; + return FALSE; + } + else { + *width = w; + *height = h; + return TRUE; + } +} diff --git a/mesalib/src/gallium/auxiliary/util/u_framebuffer.h b/mesalib/src/gallium/auxiliary/util/u_framebuffer.h new file mode 100644 index 000000000..346672bc7 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_framebuffer.h @@ -0,0 +1,54 @@ +/************************************************************************** + * + * Copyright 2009-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 U_FRAMEBUFFER_H +#define U_FRAMEBUFFER_H + + +#include "pipe/p_compiler.h" +#include "pipe/p_state.h" + + +extern boolean +util_framebuffer_state_equal(const struct pipe_framebuffer_state *dst, + const struct pipe_framebuffer_state *src); + +extern void +util_copy_framebuffer_state(struct pipe_framebuffer_state *dst, + const struct pipe_framebuffer_state *src); + + +extern void +util_unreference_framebuffer_state(struct pipe_framebuffer_state *fb); + + +extern boolean +util_framebuffer_min_size(const struct pipe_framebuffer_state *fb, + unsigned *width, + unsigned *height); + +#endif /* U_FRAMEBUFFER_H */ diff --git a/mesalib/src/gallium/auxiliary/util/u_gen_mipmap.c b/mesalib/src/gallium/auxiliary/util/u_gen_mipmap.c new file mode 100644 index 000000000..c04e3645e --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_gen_mipmap.c @@ -0,0 +1,1688 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * 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 TUNGSTEN GRAPHICS 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 + * Mipmap generation utility + * + * @author Brian Paul + */ + + +#include "pipe/p_context.h" +#include "util/u_debug.h" +#include "pipe/p_defines.h" +#include "util/u_inlines.h" +#include "pipe/p_shader_tokens.h" +#include "pipe/p_state.h" + +#include "util/u_format.h" +#include "util/u_memory.h" +#include "util/u_draw_quad.h" +#include "util/u_gen_mipmap.h" +#include "util/u_simple_shaders.h" +#include "util/u_math.h" +#include "util/u_texture.h" +#include "util/u_half.h" +#include "util/u_surface.h" + +#include "cso_cache/cso_context.h" + + +struct gen_mipmap_state +{ + struct pipe_context *pipe; + struct cso_context *cso; + + struct pipe_blend_state blend; + struct pipe_depth_stencil_alpha_state depthstencil; + struct pipe_rasterizer_state rasterizer; + struct pipe_sampler_state sampler; + struct pipe_clip_state clip; + struct pipe_vertex_element velem[2]; + + void *vs; + void *fs[TGSI_TEXTURE_COUNT]; /**< Not all are used, but simplifies code */ + + struct pipe_resource *vbuf; /**< quad vertices */ + unsigned vbuf_slot; + + float vertices[4][2][4]; /**< vertex/texcoords for quad */ +}; + + + +enum dtype +{ + DTYPE_UBYTE, + DTYPE_UBYTE_3_3_2, + DTYPE_USHORT, + DTYPE_USHORT_4_4_4_4, + DTYPE_USHORT_5_6_5, + DTYPE_USHORT_1_5_5_5_REV, + DTYPE_UINT, + DTYPE_FLOAT, + DTYPE_HALF_FLOAT +}; + + +typedef uint16_t half_float; + + +/** + * \name Support macros for do_row and do_row_3d + * + * The macro madness is here for two reasons. First, it compacts the code + * slightly. Second, it makes it much easier to adjust the specifics of the + * filter to tune the rounding characteristics. + */ +/*@{*/ +#define DECLARE_ROW_POINTERS(t, e) \ + const t(*rowA)[e] = (const t(*)[e]) srcRowA; \ + const t(*rowB)[e] = (const t(*)[e]) srcRowB; \ + const t(*rowC)[e] = (const t(*)[e]) srcRowC; \ + const t(*rowD)[e] = (const t(*)[e]) srcRowD; \ + t(*dst)[e] = (t(*)[e]) dstRow + +#define DECLARE_ROW_POINTERS0(t) \ + const t *rowA = (const t *) srcRowA; \ + const t *rowB = (const t *) srcRowB; \ + const t *rowC = (const t *) srcRowC; \ + const t *rowD = (const t *) srcRowD; \ + t *dst = (t *) dstRow + +#define FILTER_SUM_3D(Aj, Ak, Bj, Bk, Cj, Ck, Dj, Dk) \ + ((unsigned) Aj + (unsigned) Ak \ + + (unsigned) Bj + (unsigned) Bk \ + + (unsigned) Cj + (unsigned) Ck \ + + (unsigned) Dj + (unsigned) Dk \ + + 4) >> 3 + +#define FILTER_3D(e) \ + do { \ + dst[i][e] = FILTER_SUM_3D(rowA[j][e], rowA[k][e], \ + rowB[j][e], rowB[k][e], \ + rowC[j][e], rowC[k][e], \ + rowD[j][e], rowD[k][e]); \ + } while(0) + +#define FILTER_F_3D(e) \ + do { \ + dst[i][e] = (rowA[j][e] + rowA[k][e] \ + + rowB[j][e] + rowB[k][e] \ + + rowC[j][e] + rowC[k][e] \ + + rowD[j][e] + rowD[k][e]) * 0.125F; \ + } while(0) + +#define FILTER_HF_3D(e) \ + do { \ + const float aj = util_half_to_float(rowA[j][e]); \ + const float ak = util_half_to_float(rowA[k][e]); \ + const float bj = util_half_to_float(rowB[j][e]); \ + const float bk = util_half_to_float(rowB[k][e]); \ + const float cj = util_half_to_float(rowC[j][e]); \ + const float ck = util_half_to_float(rowC[k][e]); \ + const float dj = util_half_to_float(rowD[j][e]); \ + const float dk = util_half_to_float(rowD[k][e]); \ + dst[i][e] = util_float_to_half((aj + ak + bj + bk + cj + ck + dj + dk) \ + * 0.125F); \ + } while(0) +/*@}*/ + + +/** + * Average together two rows of a source image to produce a single new + * row in the dest image. It's legal for the two source rows to point + * to the same data. The source width must be equal to either the + * dest width or two times the dest width. + * \param datatype GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_FLOAT, etc. + * \param comps number of components per pixel (1..4) + */ +static void +do_row(enum dtype datatype, uint comps, int srcWidth, + const void *srcRowA, const void *srcRowB, + int dstWidth, void *dstRow) +{ + const uint k0 = (srcWidth == dstWidth) ? 0 : 1; + const uint colStride = (srcWidth == dstWidth) ? 1 : 2; + + assert(comps >= 1); + assert(comps <= 4); + + /* This assertion is no longer valid with non-power-of-2 textures + assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth); + */ + + if (datatype == DTYPE_UBYTE && comps == 4) { + uint i, j, k; + const ubyte(*rowA)[4] = (const ubyte(*)[4]) srcRowA; + const ubyte(*rowB)[4] = (const ubyte(*)[4]) srcRowB; + ubyte(*dst)[4] = (ubyte(*)[4]) dstRow; + for (i = j = 0, k = k0; i < (uint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; + dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; + dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4; + dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4; + } + } + else if (datatype == DTYPE_UBYTE && comps == 3) { + uint i, j, k; + const ubyte(*rowA)[3] = (const ubyte(*)[3]) srcRowA; + const ubyte(*rowB)[3] = (const ubyte(*)[3]) srcRowB; + ubyte(*dst)[3] = (ubyte(*)[3]) dstRow; + for (i = j = 0, k = k0; i < (uint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; + dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; + dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4; + } + } + else if (datatype == DTYPE_UBYTE && comps == 2) { + uint i, j, k; + const ubyte(*rowA)[2] = (const ubyte(*)[2]) srcRowA; + const ubyte(*rowB)[2] = (const ubyte(*)[2]) srcRowB; + ubyte(*dst)[2] = (ubyte(*)[2]) dstRow; + for (i = j = 0, k = k0; i < (uint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) >> 2; + dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) >> 2; + } + } + else if (datatype == DTYPE_UBYTE && comps == 1) { + uint i, j, k; + const ubyte *rowA = (const ubyte *) srcRowA; + const ubyte *rowB = (const ubyte *) srcRowB; + ubyte *dst = (ubyte *) dstRow; + for (i = j = 0, k = k0; i < (uint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) >> 2; + } + } + + else if (datatype == DTYPE_USHORT && comps == 4) { + uint i, j, k; + const ushort(*rowA)[4] = (const ushort(*)[4]) srcRowA; + const ushort(*rowB)[4] = (const ushort(*)[4]) srcRowB; + ushort(*dst)[4] = (ushort(*)[4]) dstRow; + for (i = j = 0, k = k0; i < (uint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; + dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; + dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4; + dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4; + } + } + else if (datatype == DTYPE_USHORT && comps == 3) { + uint i, j, k; + const ushort(*rowA)[3] = (const ushort(*)[3]) srcRowA; + const ushort(*rowB)[3] = (const ushort(*)[3]) srcRowB; + ushort(*dst)[3] = (ushort(*)[3]) dstRow; + for (i = j = 0, k = k0; i < (uint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; + dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; + dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4; + } + } + else if (datatype == DTYPE_USHORT && comps == 2) { + uint i, j, k; + const ushort(*rowA)[2] = (const ushort(*)[2]) srcRowA; + const ushort(*rowB)[2] = (const ushort(*)[2]) srcRowB; + ushort(*dst)[2] = (ushort(*)[2]) dstRow; + for (i = j = 0, k = k0; i < (uint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4; + dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4; + } + } + else if (datatype == DTYPE_USHORT && comps == 1) { + uint i, j, k; + const ushort *rowA = (const ushort *) srcRowA; + const ushort *rowB = (const ushort *) srcRowB; + ushort *dst = (ushort *) dstRow; + for (i = j = 0, k = k0; i < (uint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4; + } + } + + else if (datatype == DTYPE_FLOAT && comps == 4) { + uint i, j, k; + const float(*rowA)[4] = (const float(*)[4]) srcRowA; + const float(*rowB)[4] = (const float(*)[4]) srcRowB; + float(*dst)[4] = (float(*)[4]) dstRow; + for (i = j = 0, k = k0; i < (uint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i][0] = (rowA[j][0] + rowA[k][0] + + rowB[j][0] + rowB[k][0]) * 0.25F; + dst[i][1] = (rowA[j][1] + rowA[k][1] + + rowB[j][1] + rowB[k][1]) * 0.25F; + dst[i][2] = (rowA[j][2] + rowA[k][2] + + rowB[j][2] + rowB[k][2]) * 0.25F; + dst[i][3] = (rowA[j][3] + rowA[k][3] + + rowB[j][3] + rowB[k][3]) * 0.25F; + } + } + else if (datatype == DTYPE_FLOAT && comps == 3) { + uint i, j, k; + const float(*rowA)[3] = (const float(*)[3]) srcRowA; + const float(*rowB)[3] = (const float(*)[3]) srcRowB; + float(*dst)[3] = (float(*)[3]) dstRow; + for (i = j = 0, k = k0; i < (uint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i][0] = (rowA[j][0] + rowA[k][0] + + rowB[j][0] + rowB[k][0]) * 0.25F; + dst[i][1] = (rowA[j][1] + rowA[k][1] + + rowB[j][1] + rowB[k][1]) * 0.25F; + dst[i][2] = (rowA[j][2] + rowA[k][2] + + rowB[j][2] + rowB[k][2]) * 0.25F; + } + } + else if (datatype == DTYPE_FLOAT && comps == 2) { + uint i, j, k; + const float(*rowA)[2] = (const float(*)[2]) srcRowA; + const float(*rowB)[2] = (const float(*)[2]) srcRowB; + float(*dst)[2] = (float(*)[2]) dstRow; + for (i = j = 0, k = k0; i < (uint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i][0] = (rowA[j][0] + rowA[k][0] + + rowB[j][0] + rowB[k][0]) * 0.25F; + dst[i][1] = (rowA[j][1] + rowA[k][1] + + rowB[j][1] + rowB[k][1]) * 0.25F; + } + } + else if (datatype == DTYPE_FLOAT && comps == 1) { + uint i, j, k; + const float *rowA = (const float *) srcRowA; + const float *rowB = (const float *) srcRowB; + float *dst = (float *) dstRow; + for (i = j = 0, k = k0; i < (uint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) * 0.25F; + } + } + + else if (datatype == DTYPE_HALF_FLOAT && comps == 4) { + uint i, j, k, comp; + const half_float(*rowA)[4] = (const half_float(*)[4]) srcRowA; + const half_float(*rowB)[4] = (const half_float(*)[4]) srcRowB; + half_float(*dst)[4] = (half_float(*)[4]) dstRow; + for (i = j = 0, k = k0; i < (uint) dstWidth; + i++, j += colStride, k += colStride) { + for (comp = 0; comp < 4; comp++) { + float aj, ak, bj, bk; + aj = util_half_to_float(rowA[j][comp]); + ak = util_half_to_float(rowA[k][comp]); + bj = util_half_to_float(rowB[j][comp]); + bk = util_half_to_float(rowB[k][comp]); + dst[i][comp] = util_float_to_half((aj + ak + bj + bk) * 0.25F); + } + } + } + else if (datatype == DTYPE_HALF_FLOAT && comps == 3) { + uint i, j, k, comp; + const half_float(*rowA)[3] = (const half_float(*)[3]) srcRowA; + const half_float(*rowB)[3] = (const half_float(*)[3]) srcRowB; + half_float(*dst)[3] = (half_float(*)[3]) dstRow; + for (i = j = 0, k = k0; i < (uint) dstWidth; + i++, j += colStride, k += colStride) { + for (comp = 0; comp < 3; comp++) { + float aj, ak, bj, bk; + aj = util_half_to_float(rowA[j][comp]); + ak = util_half_to_float(rowA[k][comp]); + bj = util_half_to_float(rowB[j][comp]); + bk = util_half_to_float(rowB[k][comp]); + dst[i][comp] = util_float_to_half((aj + ak + bj + bk) * 0.25F); + } + } + } + else if (datatype == DTYPE_HALF_FLOAT && comps == 2) { + uint i, j, k, comp; + const half_float(*rowA)[2] = (const half_float(*)[2]) srcRowA; + const half_float(*rowB)[2] = (const half_float(*)[2]) srcRowB; + half_float(*dst)[2] = (half_float(*)[2]) dstRow; + for (i = j = 0, k = k0; i < (uint) dstWidth; + i++, j += colStride, k += colStride) { + for (comp = 0; comp < 2; comp++) { + float aj, ak, bj, bk; + aj = util_half_to_float(rowA[j][comp]); + ak = util_half_to_float(rowA[k][comp]); + bj = util_half_to_float(rowB[j][comp]); + bk = util_half_to_float(rowB[k][comp]); + dst[i][comp] = util_float_to_half((aj + ak + bj + bk) * 0.25F); + } + } + } + else if (datatype == DTYPE_HALF_FLOAT && comps == 1) { + uint i, j, k; + const half_float *rowA = (const half_float *) srcRowA; + const half_float *rowB = (const half_float *) srcRowB; + half_float *dst = (half_float *) dstRow; + for (i = j = 0, k = k0; i < (uint) dstWidth; + i++, j += colStride, k += colStride) { + float aj, ak, bj, bk; + aj = util_half_to_float(rowA[j]); + ak = util_half_to_float(rowA[k]); + bj = util_half_to_float(rowB[j]); + bk = util_half_to_float(rowB[k]); + dst[i] = util_float_to_half((aj + ak + bj + bk) * 0.25F); + } + } + + else if (datatype == DTYPE_UINT && comps == 1) { + uint i, j, k; + const uint *rowA = (const uint *) srcRowA; + const uint *rowB = (const uint *) srcRowB; + uint *dst = (uint *) dstRow; + for (i = j = 0, k = k0; i < (uint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i] = rowA[j] / 4 + rowA[k] / 4 + rowB[j] / 4 + rowB[k] / 4; + } + } + + else if (datatype == DTYPE_USHORT_5_6_5 && comps == 3) { + uint i, j, k; + const ushort *rowA = (const ushort *) srcRowA; + const ushort *rowB = (const ushort *) srcRowB; + ushort *dst = (ushort *) dstRow; + for (i = j = 0, k = k0; i < (uint) dstWidth; + i++, j += colStride, k += colStride) { + const int rowAr0 = rowA[j] & 0x1f; + const int rowAr1 = rowA[k] & 0x1f; + const int rowBr0 = rowB[j] & 0x1f; + const int rowBr1 = rowB[k] & 0x1f; + const int rowAg0 = (rowA[j] >> 5) & 0x3f; + const int rowAg1 = (rowA[k] >> 5) & 0x3f; + const int rowBg0 = (rowB[j] >> 5) & 0x3f; + const int rowBg1 = (rowB[k] >> 5) & 0x3f; + const int rowAb0 = (rowA[j] >> 11) & 0x1f; + const int rowAb1 = (rowA[k] >> 11) & 0x1f; + const int rowBb0 = (rowB[j] >> 11) & 0x1f; + const int rowBb1 = (rowB[k] >> 11) & 0x1f; + const int red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; + const int green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; + const int blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; + dst[i] = (blue << 11) | (green << 5) | red; + } + } + else if (datatype == DTYPE_USHORT_4_4_4_4 && comps == 4) { + uint i, j, k; + const ushort *rowA = (const ushort *) srcRowA; + const ushort *rowB = (const ushort *) srcRowB; + ushort *dst = (ushort *) dstRow; + for (i = j = 0, k = k0; i < (uint) dstWidth; + i++, j += colStride, k += colStride) { + const int rowAr0 = rowA[j] & 0xf; + const int rowAr1 = rowA[k] & 0xf; + const int rowBr0 = rowB[j] & 0xf; + const int rowBr1 = rowB[k] & 0xf; + const int rowAg0 = (rowA[j] >> 4) & 0xf; + const int rowAg1 = (rowA[k] >> 4) & 0xf; + const int rowBg0 = (rowB[j] >> 4) & 0xf; + const int rowBg1 = (rowB[k] >> 4) & 0xf; + const int rowAb0 = (rowA[j] >> 8) & 0xf; + const int rowAb1 = (rowA[k] >> 8) & 0xf; + const int rowBb0 = (rowB[j] >> 8) & 0xf; + const int rowBb1 = (rowB[k] >> 8) & 0xf; + const int rowAa0 = (rowA[j] >> 12) & 0xf; + const int rowAa1 = (rowA[k] >> 12) & 0xf; + const int rowBa0 = (rowB[j] >> 12) & 0xf; + const int rowBa1 = (rowB[k] >> 12) & 0xf; + const int red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; + const int green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; + const int blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; + const int alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2; + dst[i] = (alpha << 12) | (blue << 8) | (green << 4) | red; + } + } + else if (datatype == DTYPE_USHORT_1_5_5_5_REV && comps == 4) { + uint i, j, k; + const ushort *rowA = (const ushort *) srcRowA; + const ushort *rowB = (const ushort *) srcRowB; + ushort *dst = (ushort *) dstRow; + for (i = j = 0, k = k0; i < (uint) dstWidth; + i++, j += colStride, k += colStride) { + const int rowAr0 = rowA[j] & 0x1f; + const int rowAr1 = rowA[k] & 0x1f; + const int rowBr0 = rowB[j] & 0x1f; + const int rowBr1 = rowB[k] & 0x1f; + const int rowAg0 = (rowA[j] >> 5) & 0x1f; + const int rowAg1 = (rowA[k] >> 5) & 0x1f; + const int rowBg0 = (rowB[j] >> 5) & 0x1f; + const int rowBg1 = (rowB[k] >> 5) & 0x1f; + const int rowAb0 = (rowA[j] >> 10) & 0x1f; + const int rowAb1 = (rowA[k] >> 10) & 0x1f; + const int rowBb0 = (rowB[j] >> 10) & 0x1f; + const int rowBb1 = (rowB[k] >> 10) & 0x1f; + const int rowAa0 = (rowA[j] >> 15) & 0x1; + const int rowAa1 = (rowA[k] >> 15) & 0x1; + const int rowBa0 = (rowB[j] >> 15) & 0x1; + const int rowBa1 = (rowB[k] >> 15) & 0x1; + const int red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; + const int green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; + const int blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; + const int alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2; + dst[i] = (alpha << 15) | (blue << 10) | (green << 5) | red; + } + } + else if (datatype == DTYPE_UBYTE_3_3_2 && comps == 3) { + uint i, j, k; + const ubyte *rowA = (const ubyte *) srcRowA; + const ubyte *rowB = (const ubyte *) srcRowB; + ubyte *dst = (ubyte *) dstRow; + for (i = j = 0, k = k0; i < (uint) dstWidth; + i++, j += colStride, k += colStride) { + const int rowAr0 = rowA[j] & 0x3; + const int rowAr1 = rowA[k] & 0x3; + const int rowBr0 = rowB[j] & 0x3; + const int rowBr1 = rowB[k] & 0x3; + const int rowAg0 = (rowA[j] >> 2) & 0x7; + const int rowAg1 = (rowA[k] >> 2) & 0x7; + const int rowBg0 = (rowB[j] >> 2) & 0x7; + const int rowBg1 = (rowB[k] >> 2) & 0x7; + const int rowAb0 = (rowA[j] >> 5) & 0x7; + const int rowAb1 = (rowA[k] >> 5) & 0x7; + const int rowBb0 = (rowB[j] >> 5) & 0x7; + const int rowBb1 = (rowB[k] >> 5) & 0x7; + const int red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; + const int green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; + const int blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; + dst[i] = (blue << 5) | (green << 2) | red; + } + } + else { + debug_printf("bad format in do_row()"); + } +} + + +/** + * Average together four rows of a source image to produce a single new + * row in the dest image. It's legal for the two source rows to point + * to the same data. The source width must be equal to either the + * dest width or two times the dest width. + * + * \param datatype GL pixel type \c GL_UNSIGNED_BYTE, \c GL_UNSIGNED_SHORT, + * \c GL_FLOAT, etc. + * \param comps number of components per pixel (1..4) + * \param srcWidth Width of a row in the source data + * \param srcRowA Pointer to one of the rows of source data + * \param srcRowB Pointer to one of the rows of source data + * \param srcRowC Pointer to one of the rows of source data + * \param srcRowD Pointer to one of the rows of source data + * \param dstWidth Width of a row in the destination data + * \param srcRowA Pointer to the row of destination data + */ +static void +do_row_3D(enum dtype datatype, uint comps, int srcWidth, + const void *srcRowA, const void *srcRowB, + const void *srcRowC, const void *srcRowD, + int dstWidth, void *dstRow) +{ + const uint k0 = (srcWidth == dstWidth) ? 0 : 1; + const uint colStride = (srcWidth == dstWidth) ? 1 : 2; + uint i, j, k; + + assert(comps >= 1); + assert(comps <= 4); + + if ((datatype == DTYPE_UBYTE) && (comps == 4)) { + DECLARE_ROW_POINTERS(ubyte, 4); + + for (i = j = 0, k = k0; i < (uint) dstWidth; + i++, j += colStride, k += colStride) { + FILTER_3D(0); + FILTER_3D(1); + FILTER_3D(2); + FILTER_3D(3); + } + } + else if ((datatype == DTYPE_UBYTE) && (comps == 3)) { + DECLARE_ROW_POINTERS(ubyte, 3); + + for (i = j = 0, k = k0; i < (uint) dstWidth; + i++, j += colStride, k += colStride) { + FILTER_3D(0); + FILTER_3D(1); + FILTER_3D(2); + } + } + else if ((datatype == DTYPE_UBYTE) && (comps == 2)) { + DECLARE_ROW_POINTERS(ubyte, 2); + + for (i = j = 0, k = k0; i < (uint) dstWidth; + i++, j += colStride, k += colStride) { + FILTER_3D(0); + FILTER_3D(1); + } + } + else if ((datatype == DTYPE_UBYTE) && (comps == 1)) { + DECLARE_ROW_POINTERS(ubyte, 1); + + for (i = j = 0, k = k0; i < (uint) dstWidth; + i++, j += colStride, k += colStride) { + FILTER_3D(0); + } + } + else if ((datatype == DTYPE_USHORT) && (comps == 4)) { + DECLARE_ROW_POINTERS(ushort, 4); + + for (i = j = 0, k = k0; i < (uint) dstWidth; + i++, j += colStride, k += colStride) { + FILTER_3D(0); + FILTER_3D(1); + FILTER_3D(2); + FILTER_3D(3); + } + } + else if ((datatype == DTYPE_USHORT) && (comps == 3)) { + DECLARE_ROW_POINTERS(ushort, 3); + + for (i = j = 0, k = k0; i < (uint) dstWidth; + i++, j += colStride, k += colStride) { + FILTER_3D(0); + FILTER_3D(1); + FILTER_3D(2); + } + } + else if ((datatype == DTYPE_USHORT) && (comps == 2)) { + DECLARE_ROW_POINTERS(ushort, 2); + + for (i = j = 0, k = k0; i < (uint) dstWidth; + i++, j += colStride, k += colStride) { + FILTER_3D(0); + FILTER_3D(1); + } + } + else if ((datatype == DTYPE_USHORT) && (comps == 1)) { + DECLARE_ROW_POINTERS(ushort, 1); + + for (i = j = 0, k = k0; i < (uint) dstWidth; + i++, j += colStride, k += colStride) { + FILTER_3D(0); + } + } + else if ((datatype == DTYPE_FLOAT) && (comps == 4)) { + DECLARE_ROW_POINTERS(float, 4); + + for (i = j = 0, k = k0; i < (uint) dstWidth; + i++, j += colStride, k += colStride) { + FILTER_F_3D(0); + FILTER_F_3D(1); + FILTER_F_3D(2); + FILTER_F_3D(3); + } + } + else if ((datatype == DTYPE_FLOAT) && (comps == 3)) { + DECLARE_ROW_POINTERS(float, 3); + + for (i = j = 0, k = k0; i < (uint) dstWidth; + i++, j += colStride, k += colStride) { + FILTER_F_3D(0); + FILTER_F_3D(1); + FILTER_F_3D(2); + } + } + else if ((datatype == DTYPE_FLOAT) && (comps == 2)) { + DECLARE_ROW_POINTERS(float, 2); + + for (i = j = 0, k = k0; i < (uint) dstWidth; + i++, j += colStride, k += colStride) { + FILTER_F_3D(0); + FILTER_F_3D(1); + } + } + else if ((datatype == DTYPE_FLOAT) && (comps == 1)) { + DECLARE_ROW_POINTERS(float, 1); + + for (i = j = 0, k = k0; i < (uint) dstWidth; + i++, j += colStride, k += colStride) { + FILTER_F_3D(0); + } + } + else if ((datatype == DTYPE_HALF_FLOAT) && (comps == 4)) { + DECLARE_ROW_POINTERS(half_float, 4); + + for (i = j = 0, k = k0; i < (uint) dstWidth; + i++, j += colStride, k += colStride) { + FILTER_HF_3D(0); + FILTER_HF_3D(1); + FILTER_HF_3D(2); + FILTER_HF_3D(3); + } + } + else if ((datatype == DTYPE_HALF_FLOAT) && (comps == 3)) { + DECLARE_ROW_POINTERS(half_float, 4); + + for (i = j = 0, k = k0; i < (uint) dstWidth; + i++, j += colStride, k += colStride) { + FILTER_HF_3D(0); + FILTER_HF_3D(1); + FILTER_HF_3D(2); + } + } + else if ((datatype == DTYPE_HALF_FLOAT) && (comps == 2)) { + DECLARE_ROW_POINTERS(half_float, 4); + + for (i = j = 0, k = k0; i < (uint) dstWidth; + i++, j += colStride, k += colStride) { + FILTER_HF_3D(0); + FILTER_HF_3D(1); + } + } + else if ((datatype == DTYPE_HALF_FLOAT) && (comps == 1)) { + DECLARE_ROW_POINTERS(half_float, 4); + + for (i = j = 0, k = k0; i < (uint) dstWidth; + i++, j += colStride, k += colStride) { + FILTER_HF_3D(0); + } + } + else if ((datatype == DTYPE_UINT) && (comps == 1)) { + const uint *rowA = (const uint *) srcRowA; + const uint *rowB = (const uint *) srcRowB; + const uint *rowC = (const uint *) srcRowC; + const uint *rowD = (const uint *) srcRowD; + float *dst = (float *) dstRow; + + for (i = j = 0, k = k0; i < (uint) dstWidth; + i++, j += colStride, k += colStride) { + const uint64_t tmp = (((uint64_t) rowA[j] + (uint64_t) rowA[k]) + + ((uint64_t) rowB[j] + (uint64_t) rowB[k]) + + ((uint64_t) rowC[j] + (uint64_t) rowC[k]) + + ((uint64_t) rowD[j] + (uint64_t) rowD[k])); + dst[i] = (float)((double) tmp * 0.125); + } + } + else if ((datatype == DTYPE_USHORT_5_6_5) && (comps == 3)) { + DECLARE_ROW_POINTERS0(ushort); + + for (i = j = 0, k = k0; i < (uint) dstWidth; + i++, j += colStride, k += colStride) { + const int rowAr0 = rowA[j] & 0x1f; + const int rowAr1 = rowA[k] & 0x1f; + const int rowBr0 = rowB[j] & 0x1f; + const int rowBr1 = rowB[k] & 0x1f; + const int rowCr0 = rowC[j] & 0x1f; + const int rowCr1 = rowC[k] & 0x1f; + const int rowDr0 = rowD[j] & 0x1f; + const int rowDr1 = rowD[k] & 0x1f; + const int rowAg0 = (rowA[j] >> 5) & 0x3f; + const int rowAg1 = (rowA[k] >> 5) & 0x3f; + const int rowBg0 = (rowB[j] >> 5) & 0x3f; + const int rowBg1 = (rowB[k] >> 5) & 0x3f; + const int rowCg0 = (rowC[j] >> 5) & 0x3f; + const int rowCg1 = (rowC[k] >> 5) & 0x3f; + const int rowDg0 = (rowD[j] >> 5) & 0x3f; + const int rowDg1 = (rowD[k] >> 5) & 0x3f; + const int rowAb0 = (rowA[j] >> 11) & 0x1f; + const int rowAb1 = (rowA[k] >> 11) & 0x1f; + const int rowBb0 = (rowB[j] >> 11) & 0x1f; + const int rowBb1 = (rowB[k] >> 11) & 0x1f; + const int rowCb0 = (rowC[j] >> 11) & 0x1f; + const int rowCb1 = (rowC[k] >> 11) & 0x1f; + const int rowDb0 = (rowD[j] >> 11) & 0x1f; + const int rowDb1 = (rowD[k] >> 11) & 0x1f; + const int r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1, + rowCr0, rowCr1, rowDr0, rowDr1); + const int g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1, + rowCg0, rowCg1, rowDg0, rowDg1); + const int b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1, + rowCb0, rowCb1, rowDb0, rowDb1); + dst[i] = (b << 11) | (g << 5) | r; + } + } + else if ((datatype == DTYPE_USHORT_4_4_4_4) && (comps == 4)) { + DECLARE_ROW_POINTERS0(ushort); + + for (i = j = 0, k = k0; i < (uint) dstWidth; + i++, j += colStride, k += colStride) { + const int rowAr0 = rowA[j] & 0xf; + const int rowAr1 = rowA[k] & 0xf; + const int rowBr0 = rowB[j] & 0xf; + const int rowBr1 = rowB[k] & 0xf; + const int rowCr0 = rowC[j] & 0xf; + const int rowCr1 = rowC[k] & 0xf; + const int rowDr0 = rowD[j] & 0xf; + const int rowDr1 = rowD[k] & 0xf; + const int rowAg0 = (rowA[j] >> 4) & 0xf; + const int rowAg1 = (rowA[k] >> 4) & 0xf; + const int rowBg0 = (rowB[j] >> 4) & 0xf; + const int rowBg1 = (rowB[k] >> 4) & 0xf; + const int rowCg0 = (rowC[j] >> 4) & 0xf; + const int rowCg1 = (rowC[k] >> 4) & 0xf; + const int rowDg0 = (rowD[j] >> 4) & 0xf; + const int rowDg1 = (rowD[k] >> 4) & 0xf; + const int rowAb0 = (rowA[j] >> 8) & 0xf; + const int rowAb1 = (rowA[k] >> 8) & 0xf; + const int rowBb0 = (rowB[j] >> 8) & 0xf; + const int rowBb1 = (rowB[k] >> 8) & 0xf; + const int rowCb0 = (rowC[j] >> 8) & 0xf; + const int rowCb1 = (rowC[k] >> 8) & 0xf; + const int rowDb0 = (rowD[j] >> 8) & 0xf; + const int rowDb1 = (rowD[k] >> 8) & 0xf; + const int rowAa0 = (rowA[j] >> 12) & 0xf; + const int rowAa1 = (rowA[k] >> 12) & 0xf; + const int rowBa0 = (rowB[j] >> 12) & 0xf; + const int rowBa1 = (rowB[k] >> 12) & 0xf; + const int rowCa0 = (rowC[j] >> 12) & 0xf; + const int rowCa1 = (rowC[k] >> 12) & 0xf; + const int rowDa0 = (rowD[j] >> 12) & 0xf; + const int rowDa1 = (rowD[k] >> 12) & 0xf; + const int r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1, + rowCr0, rowCr1, rowDr0, rowDr1); + const int g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1, + rowCg0, rowCg1, rowDg0, rowDg1); + const int b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1, + rowCb0, rowCb1, rowDb0, rowDb1); + const int a = FILTER_SUM_3D(rowAa0, rowAa1, rowBa0, rowBa1, + rowCa0, rowCa1, rowDa0, rowDa1); + + dst[i] = (a << 12) | (b << 8) | (g << 4) | r; + } + } + else if ((datatype == DTYPE_USHORT_1_5_5_5_REV) && (comps == 4)) { + DECLARE_ROW_POINTERS0(ushort); + + for (i = j = 0, k = k0; i < (uint) dstWidth; + i++, j += colStride, k += colStride) { + const int rowAr0 = rowA[j] & 0x1f; + const int rowAr1 = rowA[k] & 0x1f; + const int rowBr0 = rowB[j] & 0x1f; + const int rowBr1 = rowB[k] & 0x1f; + const int rowCr0 = rowC[j] & 0x1f; + const int rowCr1 = rowC[k] & 0x1f; + const int rowDr0 = rowD[j] & 0x1f; + const int rowDr1 = rowD[k] & 0x1f; + const int rowAg0 = (rowA[j] >> 5) & 0x1f; + const int rowAg1 = (rowA[k] >> 5) & 0x1f; + const int rowBg0 = (rowB[j] >> 5) & 0x1f; + const int rowBg1 = (rowB[k] >> 5) & 0x1f; + const int rowCg0 = (rowC[j] >> 5) & 0x1f; + const int rowCg1 = (rowC[k] >> 5) & 0x1f; + const int rowDg0 = (rowD[j] >> 5) & 0x1f; + const int rowDg1 = (rowD[k] >> 5) & 0x1f; + const int rowAb0 = (rowA[j] >> 10) & 0x1f; + const int rowAb1 = (rowA[k] >> 10) & 0x1f; + const int rowBb0 = (rowB[j] >> 10) & 0x1f; + const int rowBb1 = (rowB[k] >> 10) & 0x1f; + const int rowCb0 = (rowC[j] >> 10) & 0x1f; + const int rowCb1 = (rowC[k] >> 10) & 0x1f; + const int rowDb0 = (rowD[j] >> 10) & 0x1f; + const int rowDb1 = (rowD[k] >> 10) & 0x1f; + const int rowAa0 = (rowA[j] >> 15) & 0x1; + const int rowAa1 = (rowA[k] >> 15) & 0x1; + const int rowBa0 = (rowB[j] >> 15) & 0x1; + const int rowBa1 = (rowB[k] >> 15) & 0x1; + const int rowCa0 = (rowC[j] >> 15) & 0x1; + const int rowCa1 = (rowC[k] >> 15) & 0x1; + const int rowDa0 = (rowD[j] >> 15) & 0x1; + const int rowDa1 = (rowD[k] >> 15) & 0x1; + const int r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1, + rowCr0, rowCr1, rowDr0, rowDr1); + const int g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1, + rowCg0, rowCg1, rowDg0, rowDg1); + const int b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1, + rowCb0, rowCb1, rowDb0, rowDb1); + const int a = FILTER_SUM_3D(rowAa0, rowAa1, rowBa0, rowBa1, + rowCa0, rowCa1, rowDa0, rowDa1); + + dst[i] = (a << 15) | (b << 10) | (g << 5) | r; + } + } + else if ((datatype == DTYPE_UBYTE_3_3_2) && (comps == 3)) { + DECLARE_ROW_POINTERS0(ushort); + + for (i = j = 0, k = k0; i < (uint) dstWidth; + i++, j += colStride, k += colStride) { + const int rowAr0 = rowA[j] & 0x3; + const int rowAr1 = rowA[k] & 0x3; + const int rowBr0 = rowB[j] & 0x3; + const int rowBr1 = rowB[k] & 0x3; + const int rowCr0 = rowC[j] & 0x3; + const int rowCr1 = rowC[k] & 0x3; + const int rowDr0 = rowD[j] & 0x3; + const int rowDr1 = rowD[k] & 0x3; + const int rowAg0 = (rowA[j] >> 2) & 0x7; + const int rowAg1 = (rowA[k] >> 2) & 0x7; + const int rowBg0 = (rowB[j] >> 2) & 0x7; + const int rowBg1 = (rowB[k] >> 2) & 0x7; + const int rowCg0 = (rowC[j] >> 2) & 0x7; + const int rowCg1 = (rowC[k] >> 2) & 0x7; + const int rowDg0 = (rowD[j] >> 2) & 0x7; + const int rowDg1 = (rowD[k] >> 2) & 0x7; + const int rowAb0 = (rowA[j] >> 5) & 0x7; + const int rowAb1 = (rowA[k] >> 5) & 0x7; + const int rowBb0 = (rowB[j] >> 5) & 0x7; + const int rowBb1 = (rowB[k] >> 5) & 0x7; + const int rowCb0 = (rowC[j] >> 5) & 0x7; + const int rowCb1 = (rowC[k] >> 5) & 0x7; + const int rowDb0 = (rowD[j] >> 5) & 0x7; + const int rowDb1 = (rowD[k] >> 5) & 0x7; + const int r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1, + rowCr0, rowCr1, rowDr0, rowDr1); + const int g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1, + rowCg0, rowCg1, rowDg0, rowDg1); + const int b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1, + rowCb0, rowCb1, rowDb0, rowDb1); + dst[i] = (b << 5) | (g << 2) | r; + } + } + else { + debug_printf("bad format in do_row_3D()"); + } +} + + + +static void +format_to_type_comps(enum pipe_format pformat, + enum dtype *datatype, uint *comps) +{ + /* XXX I think this could be implemented in terms of the pf_*() functions */ + switch (pformat) { + case PIPE_FORMAT_B8G8R8A8_UNORM: + case PIPE_FORMAT_B8G8R8X8_UNORM: + case PIPE_FORMAT_A8R8G8B8_UNORM: + case PIPE_FORMAT_X8R8G8B8_UNORM: + case PIPE_FORMAT_A8B8G8R8_SRGB: + case PIPE_FORMAT_X8B8G8R8_SRGB: + case PIPE_FORMAT_B8G8R8A8_SRGB: + case PIPE_FORMAT_B8G8R8X8_SRGB: + case PIPE_FORMAT_A8R8G8B8_SRGB: + case PIPE_FORMAT_X8R8G8B8_SRGB: + case PIPE_FORMAT_R8G8B8_SRGB: + *datatype = DTYPE_UBYTE; + *comps = 4; + return; + case PIPE_FORMAT_B5G5R5X1_UNORM: + case PIPE_FORMAT_B5G5R5A1_UNORM: + *datatype = DTYPE_USHORT_1_5_5_5_REV; + *comps = 4; + return; + case PIPE_FORMAT_B4G4R4A4_UNORM: + *datatype = DTYPE_USHORT_4_4_4_4; + *comps = 4; + return; + case PIPE_FORMAT_B5G6R5_UNORM: + *datatype = DTYPE_USHORT_5_6_5; + *comps = 3; + return; + case PIPE_FORMAT_L8_UNORM: + case PIPE_FORMAT_L8_SRGB: + case PIPE_FORMAT_A8_UNORM: + case PIPE_FORMAT_I8_UNORM: + *datatype = DTYPE_UBYTE; + *comps = 1; + return; + case PIPE_FORMAT_L8A8_UNORM: + case PIPE_FORMAT_L8A8_SRGB: + *datatype = DTYPE_UBYTE; + *comps = 2; + return; + default: + assert(0); + *datatype = DTYPE_UBYTE; + *comps = 0; + break; + } +} + + +static void +reduce_1d(enum pipe_format pformat, + int srcWidth, const ubyte *srcPtr, + int dstWidth, ubyte *dstPtr) +{ + enum dtype datatype; + uint comps; + + format_to_type_comps(pformat, &datatype, &comps); + + /* we just duplicate the input row, kind of hack, saves code */ + do_row(datatype, comps, + srcWidth, srcPtr, srcPtr, + dstWidth, dstPtr); +} + + +/** + * Strides are in bytes. If zero, it'll be computed as width * bpp. + */ +static void +reduce_2d(enum pipe_format pformat, + int srcWidth, int srcHeight, + int srcRowStride, const ubyte *srcPtr, + int dstWidth, int dstHeight, + int dstRowStride, ubyte *dstPtr) +{ + enum dtype datatype; + uint comps; + const int bpt = util_format_get_blocksize(pformat); + const ubyte *srcA, *srcB; + ubyte *dst; + int row; + + format_to_type_comps(pformat, &datatype, &comps); + + if (!srcRowStride) + srcRowStride = bpt * srcWidth; + + if (!dstRowStride) + dstRowStride = bpt * dstWidth; + + /* Compute src and dst pointers */ + srcA = srcPtr; + if (srcHeight > 1) + srcB = srcA + srcRowStride; + else + srcB = srcA; + dst = dstPtr; + + for (row = 0; row < dstHeight; row++) { + do_row(datatype, comps, + srcWidth, srcA, srcB, + dstWidth, dst); + srcA += 2 * srcRowStride; + srcB += 2 * srcRowStride; + dst += dstRowStride; + } +} + + +static void +reduce_3d(enum pipe_format pformat, + int srcWidth, int srcHeight, int srcDepth, + int srcRowStride, int srcImageStride, const ubyte *srcPtr, + int dstWidth, int dstHeight, int dstDepth, + int dstRowStride, int dstImageStride, ubyte *dstPtr) +{ + const int bpt = util_format_get_blocksize(pformat); + int img, row; + int srcImageOffset, srcRowOffset; + enum dtype datatype; + uint comps; + + format_to_type_comps(pformat, &datatype, &comps); + + /* XXX I think we should rather assert those strides */ + if (!srcImageStride) + srcImageStride = srcWidth * srcHeight * bpt; + if (!dstImageStride) + dstImageStride = dstWidth * dstHeight * bpt; + + if (!srcRowStride) + srcRowStride = srcWidth * bpt; + if (!dstRowStride) + dstRowStride = dstWidth * bpt; + + /* Offset between adjacent src images to be averaged together */ + srcImageOffset = (srcDepth == dstDepth) ? 0 : srcImageStride; + + /* Offset between adjacent src rows to be averaged together */ + srcRowOffset = (srcHeight == dstHeight) ? 0 : srcRowStride; + + /* + * Need to average together up to 8 src pixels for each dest pixel. + * Break that down into 3 operations: + * 1. take two rows from source image and average them together. + * 2. take two rows from next source image and average them together. + * 3. take the two averaged rows and average them for the final dst row. + */ + + /* + printf("mip3d %d x %d x %d -> %d x %d x %d\n", + srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth); + */ + + for (img = 0; img < dstDepth; img++) { + /* first source image pointer */ + const ubyte *imgSrcA = srcPtr + + img * (srcImageStride + srcImageOffset); + /* second source image pointer */ + const ubyte *imgSrcB = imgSrcA + srcImageOffset; + /* address of the dest image */ + ubyte *imgDst = dstPtr + img * dstImageStride; + + /* setup the four source row pointers and the dest row pointer */ + const ubyte *srcImgARowA = imgSrcA; + const ubyte *srcImgARowB = imgSrcA + srcRowOffset; + const ubyte *srcImgBRowA = imgSrcB; + const ubyte *srcImgBRowB = imgSrcB + srcRowOffset; + ubyte *dstImgRow = imgDst; + + for (row = 0; row < dstHeight; row++) { + do_row_3D(datatype, comps, srcWidth, + srcImgARowA, srcImgARowB, + srcImgBRowA, srcImgBRowB, + dstWidth, dstImgRow); + + /* advance to next rows */ + srcImgARowA += srcRowStride + srcRowOffset; + srcImgARowB += srcRowStride + srcRowOffset; + srcImgBRowA += srcRowStride + srcRowOffset; + srcImgBRowB += srcRowStride + srcRowOffset; + dstImgRow += dstImageStride; + } + } +} + + + + +static void +make_1d_mipmap(struct gen_mipmap_state *ctx, + struct pipe_resource *pt, + uint layer, uint baseLevel, uint lastLevel) +{ + struct pipe_context *pipe = ctx->pipe; + uint dstLevel; + + for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) { + const uint srcLevel = dstLevel - 1; + struct pipe_transfer *srcTrans, *dstTrans; + void *srcMap, *dstMap; + + srcTrans = pipe_get_transfer(pipe, pt, srcLevel, layer, + PIPE_TRANSFER_READ, 0, 0, + u_minify(pt->width0, srcLevel), + u_minify(pt->height0, srcLevel)); + dstTrans = pipe_get_transfer(pipe, pt, dstLevel, layer, + PIPE_TRANSFER_WRITE, 0, 0, + u_minify(pt->width0, dstLevel), + u_minify(pt->height0, dstLevel)); + + srcMap = (ubyte *) pipe->transfer_map(pipe, srcTrans); + dstMap = (ubyte *) pipe->transfer_map(pipe, dstTrans); + + reduce_1d(pt->format, + srcTrans->box.width, srcMap, + dstTrans->box.width, dstMap); + + pipe->transfer_unmap(pipe, srcTrans); + pipe->transfer_unmap(pipe, dstTrans); + + pipe->transfer_destroy(pipe, srcTrans); + pipe->transfer_destroy(pipe, dstTrans); + } +} + + +static void +make_2d_mipmap(struct gen_mipmap_state *ctx, + struct pipe_resource *pt, + uint layer, uint baseLevel, uint lastLevel) +{ + struct pipe_context *pipe = ctx->pipe; + uint dstLevel; + + assert(util_format_get_blockwidth(pt->format) == 1); + assert(util_format_get_blockheight(pt->format) == 1); + + for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) { + const uint srcLevel = dstLevel - 1; + struct pipe_transfer *srcTrans, *dstTrans; + ubyte *srcMap, *dstMap; + + srcTrans = pipe_get_transfer(pipe, pt, srcLevel, layer, + PIPE_TRANSFER_READ, 0, 0, + u_minify(pt->width0, srcLevel), + u_minify(pt->height0, srcLevel)); + dstTrans = pipe_get_transfer(pipe, pt, dstLevel, layer, + PIPE_TRANSFER_WRITE, 0, 0, + u_minify(pt->width0, dstLevel), + u_minify(pt->height0, dstLevel)); + + srcMap = (ubyte *) pipe->transfer_map(pipe, srcTrans); + dstMap = (ubyte *) pipe->transfer_map(pipe, dstTrans); + + reduce_2d(pt->format, + srcTrans->box.width, srcTrans->box.height, + srcTrans->stride, srcMap, + dstTrans->box.width, dstTrans->box.height, + dstTrans->stride, dstMap); + + pipe->transfer_unmap(pipe, srcTrans); + pipe->transfer_unmap(pipe, dstTrans); + + pipe->transfer_destroy(pipe, srcTrans); + pipe->transfer_destroy(pipe, dstTrans); + } +} + + +/* XXX looks a bit more like it could work now but need to test */ +static void +make_3d_mipmap(struct gen_mipmap_state *ctx, + struct pipe_resource *pt, + uint face, uint baseLevel, uint lastLevel) +{ + struct pipe_context *pipe = ctx->pipe; + uint dstLevel; + struct pipe_box src_box, dst_box; + + assert(util_format_get_blockwidth(pt->format) == 1); + assert(util_format_get_blockheight(pt->format) == 1); + + src_box.x = src_box.y = src_box.z = 0; + dst_box.x = dst_box.y = dst_box.z = 0; + + for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) { + const uint srcLevel = dstLevel - 1; + struct pipe_transfer *srcTrans, *dstTrans; + ubyte *srcMap, *dstMap; + struct pipe_box src_box, dst_box; + src_box.width = u_minify(pt->width0, srcLevel); + src_box.height = u_minify(pt->height0, srcLevel); + src_box.depth = u_minify(pt->depth0, srcLevel); + dst_box.width = u_minify(pt->width0, dstLevel); + dst_box.height = u_minify(pt->height0, dstLevel); + dst_box.depth = u_minify(pt->depth0, dstLevel); + + srcTrans = pipe->get_transfer(pipe, pt, srcLevel, + PIPE_TRANSFER_READ, + &src_box); + dstTrans = pipe->get_transfer(pipe, pt, dstLevel, + PIPE_TRANSFER_WRITE, + &dst_box); + + srcMap = (ubyte *) pipe->transfer_map(pipe, srcTrans); + dstMap = (ubyte *) pipe->transfer_map(pipe, dstTrans); + + reduce_3d(pt->format, + srcTrans->box.width, srcTrans->box.height, srcTrans->box.depth, + srcTrans->stride, srcTrans->layer_stride, srcMap, + dstTrans->box.width, dstTrans->box.height, dstTrans->box.depth, + dstTrans->stride, dstTrans->layer_stride, dstMap); + + pipe->transfer_unmap(pipe, srcTrans); + pipe->transfer_unmap(pipe, dstTrans); + + pipe->transfer_destroy(pipe, srcTrans); + pipe->transfer_destroy(pipe, dstTrans); + } +} + + +static void +fallback_gen_mipmap(struct gen_mipmap_state *ctx, + struct pipe_resource *pt, + uint layer, uint baseLevel, uint lastLevel) +{ + switch (pt->target) { + case PIPE_TEXTURE_1D: + make_1d_mipmap(ctx, pt, layer, baseLevel, lastLevel); + break; + case PIPE_TEXTURE_2D: + case PIPE_TEXTURE_RECT: + case PIPE_TEXTURE_CUBE: + make_2d_mipmap(ctx, pt, layer, baseLevel, lastLevel); + break; + case PIPE_TEXTURE_3D: + make_3d_mipmap(ctx, pt, layer, baseLevel, lastLevel); + break; + default: + assert(0); + } +} + + +/** + * Create a mipmap generation context. + * The idea is to create one of these and re-use it each time we need to + * generate a mipmap. + */ +struct gen_mipmap_state * +util_create_gen_mipmap(struct pipe_context *pipe, + struct cso_context *cso) +{ + struct gen_mipmap_state *ctx; + uint i; + + ctx = CALLOC_STRUCT(gen_mipmap_state); + if (!ctx) + return NULL; + + ctx->pipe = pipe; + ctx->cso = cso; + + /* disabled blending/masking */ + memset(&ctx->blend, 0, sizeof(ctx->blend)); + ctx->blend.rt[0].colormask = PIPE_MASK_RGBA; + + /* no-op depth/stencil/alpha */ + memset(&ctx->depthstencil, 0, sizeof(ctx->depthstencil)); + + /* rasterizer */ + memset(&ctx->rasterizer, 0, sizeof(ctx->rasterizer)); + ctx->rasterizer.cull_face = PIPE_FACE_NONE; + ctx->rasterizer.gl_rasterization_rules = 1; + + /* sampler state */ + memset(&ctx->sampler, 0, sizeof(ctx->sampler)); + ctx->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + ctx->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + ctx->sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + ctx->sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST; + ctx->sampler.normalized_coords = 1; + + /* vertex elements state */ + memset(&ctx->velem[0], 0, sizeof(ctx->velem[0]) * 2); + for (i = 0; i < 2; i++) { + ctx->velem[i].src_offset = i * 4 * sizeof(float); + ctx->velem[i].instance_divisor = 0; + ctx->velem[i].vertex_buffer_index = 0; + ctx->velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + } + + /* vertex data that doesn't change */ + for (i = 0; i < 4; i++) { + ctx->vertices[i][0][2] = 0.0f; /* z */ + ctx->vertices[i][0][3] = 1.0f; /* w */ + ctx->vertices[i][1][3] = 1.0f; /* q */ + } + + /* Note: the actual vertex buffer is allocated as needed below */ + + return ctx; +} + + +/** + * Helper function to set the fragment shaders. + */ +static INLINE void +set_fragment_shader(struct gen_mipmap_state *ctx, uint type) +{ + if (!ctx->fs[type]) + ctx->fs[type] = + util_make_fragment_tex_shader(ctx->pipe, type, + TGSI_INTERPOLATE_LINEAR); + + cso_set_fragment_shader_handle(ctx->cso, ctx->fs[type]); +} + + +/** + * Helper function to set the vertex shader. + */ +static INLINE void +set_vertex_shader(struct gen_mipmap_state *ctx) +{ + /* vertex shader - still required to provide the linkage between + * fragment shader input semantics and vertex_element/buffers. + */ + if (!ctx->vs) + { + const uint semantic_names[] = { TGSI_SEMANTIC_POSITION, + TGSI_SEMANTIC_GENERIC }; + const uint semantic_indexes[] = { 0, 0 }; + ctx->vs = util_make_vertex_passthrough_shader(ctx->pipe, 2, + semantic_names, + semantic_indexes); + } + + cso_set_vertex_shader_handle(ctx->cso, ctx->vs); +} + + +/** + * Get next "slot" of vertex space in the vertex buffer. + * We're allocating one large vertex buffer and using it piece by piece. + */ +static unsigned +get_next_slot(struct gen_mipmap_state *ctx) +{ + const unsigned max_slots = 4096 / sizeof ctx->vertices; + + if (ctx->vbuf_slot >= max_slots) + util_gen_mipmap_flush( ctx ); + + if (!ctx->vbuf) { + ctx->vbuf = pipe_buffer_create(ctx->pipe->screen, + PIPE_BIND_VERTEX_BUFFER, + PIPE_USAGE_STREAM, + max_slots * sizeof ctx->vertices); + } + + return ctx->vbuf_slot++ * sizeof ctx->vertices; +} + + +static unsigned +set_vertex_data(struct gen_mipmap_state *ctx, + enum pipe_texture_target tex_target, + uint layer, float r) +{ + unsigned offset; + + /* vert[0].position */ + ctx->vertices[0][0][0] = -1.0f; /*x*/ + ctx->vertices[0][0][1] = -1.0f; /*y*/ + + /* vert[1].position */ + ctx->vertices[1][0][0] = 1.0f; + ctx->vertices[1][0][1] = -1.0f; + + /* vert[2].position */ + ctx->vertices[2][0][0] = 1.0f; + ctx->vertices[2][0][1] = 1.0f; + + /* vert[3].position */ + ctx->vertices[3][0][0] = -1.0f; + ctx->vertices[3][0][1] = 1.0f; + + /* Setup vertex texcoords. This is a little tricky for cube maps. */ + if (tex_target == PIPE_TEXTURE_CUBE) { + static const float st[4][2] = { + {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f} + }; + + util_map_texcoords2d_onto_cubemap(layer, &st[0][0], 2, + &ctx->vertices[0][1][0], 8); + } + else if (tex_target == PIPE_TEXTURE_1D_ARRAY) { + /* 1D texture array */ + ctx->vertices[0][1][0] = 0.0f; /*s*/ + ctx->vertices[0][1][1] = r; /*t*/ + ctx->vertices[0][1][2] = 0.0f; /*r*/ + + ctx->vertices[1][1][0] = 1.0f; + ctx->vertices[1][1][1] = r; + ctx->vertices[1][1][2] = 0.0f; + + ctx->vertices[2][1][0] = 1.0f; + ctx->vertices[2][1][1] = r; + ctx->vertices[2][1][2] = 0.0f; + + ctx->vertices[3][1][0] = 0.0f; + ctx->vertices[3][1][1] = r; + ctx->vertices[3][1][2] = 0.0f; + } else { + /* 1D/2D/3D/2D array */ + ctx->vertices[0][1][0] = 0.0f; /*s*/ + ctx->vertices[0][1][1] = 0.0f; /*t*/ + ctx->vertices[0][1][2] = r; /*r*/ + + ctx->vertices[1][1][0] = 1.0f; + ctx->vertices[1][1][1] = 0.0f; + ctx->vertices[1][1][2] = r; + + ctx->vertices[2][1][0] = 1.0f; + ctx->vertices[2][1][1] = 1.0f; + ctx->vertices[2][1][2] = r; + + ctx->vertices[3][1][0] = 0.0f; + ctx->vertices[3][1][1] = 1.0f; + ctx->vertices[3][1][2] = r; + } + + offset = get_next_slot( ctx ); + + pipe_buffer_write_nooverlap(ctx->pipe, ctx->vbuf, + offset, sizeof(ctx->vertices), ctx->vertices); + + return offset; +} + + + +/** + * Destroy a mipmap generation context + */ +void +util_destroy_gen_mipmap(struct gen_mipmap_state *ctx) +{ + struct pipe_context *pipe = ctx->pipe; + unsigned i; + + for (i = 0; i < Elements(ctx->fs); i++) + if (ctx->fs[i]) + pipe->delete_fs_state(pipe, ctx->fs[i]); + + if (ctx->vs) + pipe->delete_vs_state(pipe, ctx->vs); + + pipe_resource_reference(&ctx->vbuf, NULL); + + FREE(ctx); +} + + + +/* Release vertex buffer at end of frame to avoid synchronous + * rendering. + */ +void util_gen_mipmap_flush( struct gen_mipmap_state *ctx ) +{ + pipe_resource_reference(&ctx->vbuf, NULL); + ctx->vbuf_slot = 0; +} + + +/** + * Generate mipmap images. It's assumed all needed texture memory is + * already allocated. + * + * \param psv the sampler view to the texture to generate mipmap levels for + * \param face which cube face to generate mipmaps for (0 for non-cube maps) + * \param baseLevel the first mipmap level to use as a src + * \param lastLevel the last mipmap level to generate + * \param filter the minification filter used to generate mipmap levels with + * \param filter one of PIPE_TEX_FILTER_LINEAR, PIPE_TEX_FILTER_NEAREST + */ +void +util_gen_mipmap(struct gen_mipmap_state *ctx, + struct pipe_sampler_view *psv, + uint face, uint baseLevel, uint lastLevel, uint filter) +{ + struct pipe_context *pipe = ctx->pipe; + struct pipe_screen *screen = pipe->screen; + struct pipe_framebuffer_state fb; + struct pipe_resource *pt = psv->texture; + uint dstLevel; + uint offset; + uint type; + + /* The texture object should have room for the levels which we're + * about to generate. + */ + assert(lastLevel <= pt->last_level); + + /* If this fails, why are we here? */ + assert(lastLevel > baseLevel); + + assert(filter == PIPE_TEX_FILTER_LINEAR || + filter == PIPE_TEX_FILTER_NEAREST); + + switch (pt->target) { + case PIPE_TEXTURE_1D: + type = TGSI_TEXTURE_1D; + break; + case PIPE_TEXTURE_2D: + type = TGSI_TEXTURE_2D; + break; + case PIPE_TEXTURE_3D: + type = TGSI_TEXTURE_3D; + break; + case PIPE_TEXTURE_CUBE: + type = TGSI_TEXTURE_CUBE; + break; + case PIPE_TEXTURE_1D_ARRAY: + type = TGSI_TEXTURE_1D_ARRAY; + break; + case PIPE_TEXTURE_2D_ARRAY: + type = TGSI_TEXTURE_2D_ARRAY; + break; + default: + assert(0); + type = TGSI_TEXTURE_2D; + } + + /* check if we can render in the texture's format */ + if (!screen->is_format_supported(screen, psv->format, pt->target, + pt->nr_samples, PIPE_BIND_RENDER_TARGET)) { + fallback_gen_mipmap(ctx, pt, face, baseLevel, lastLevel); + return; + } + + /* save state (restored below) */ + cso_save_blend(ctx->cso); + cso_save_depth_stencil_alpha(ctx->cso); + cso_save_rasterizer(ctx->cso); + cso_save_samplers(ctx->cso); + cso_save_fragment_sampler_views(ctx->cso); + cso_save_framebuffer(ctx->cso); + cso_save_fragment_shader(ctx->cso); + cso_save_vertex_shader(ctx->cso); + cso_save_viewport(ctx->cso); + cso_save_clip(ctx->cso); + cso_save_vertex_elements(ctx->cso); + + /* bind our state */ + cso_set_blend(ctx->cso, &ctx->blend); + cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil); + cso_set_rasterizer(ctx->cso, &ctx->rasterizer); + cso_set_clip(ctx->cso, &ctx->clip); + cso_set_vertex_elements(ctx->cso, 2, ctx->velem); + + set_fragment_shader(ctx, type); + set_vertex_shader(ctx); + + /* init framebuffer state */ + memset(&fb, 0, sizeof(fb)); + fb.nr_cbufs = 1; + + /* set min/mag to same filter for faster sw speed */ + ctx->sampler.mag_img_filter = filter; + ctx->sampler.min_img_filter = filter; + + /* + * XXX for small mipmap levels, it may be faster to use the software + * fallback path... + */ + for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) { + const uint srcLevel = dstLevel - 1; + struct pipe_viewport_state vp; + unsigned nr_layers, layer, i; + float rcoord = 0.0f; + + if (pt->target == PIPE_TEXTURE_3D) + nr_layers = u_minify(pt->depth0, dstLevel); + else if (pt->target == PIPE_TEXTURE_2D_ARRAY || pt->target == PIPE_TEXTURE_1D_ARRAY) + nr_layers = pt->array_size; + else + nr_layers = 1; + + for (i = 0; i < nr_layers; i++) { + struct pipe_surface *surf, surf_templ; + if (pt->target == PIPE_TEXTURE_3D) { + /* in theory with geom shaders and driver with full layer support + could do that in one go. */ + layer = i; + /* XXX hmm really? */ + rcoord = (float)layer / (float)nr_layers + 1.0f / (float)(nr_layers * 2); + } else if (pt->target == PIPE_TEXTURE_2D_ARRAY || pt->target == PIPE_TEXTURE_1D_ARRAY) { + layer = i; + rcoord = (float)layer; + } else + layer = face; + + memset(&surf_templ, 0, sizeof(surf_templ)); + u_surface_default_template(&surf_templ, pt, PIPE_BIND_RENDER_TARGET); + surf_templ.u.tex.level = dstLevel; + surf_templ.u.tex.first_layer = layer; + surf_templ.u.tex.last_layer = layer; + surf = pipe->create_surface(pipe, pt, &surf_templ); + + /* + * Setup framebuffer / dest surface + */ + fb.cbufs[0] = surf; + fb.width = u_minify(pt->width0, dstLevel); + fb.height = u_minify(pt->height0, dstLevel); + cso_set_framebuffer(ctx->cso, &fb); + + /* viewport */ + vp.scale[0] = 0.5f * fb.width; + vp.scale[1] = 0.5f * fb.height; + vp.scale[2] = 1.0f; + vp.scale[3] = 1.0f; + vp.translate[0] = 0.5f * fb.width; + vp.translate[1] = 0.5f * fb.height; + vp.translate[2] = 0.0f; + vp.translate[3] = 0.0f; + cso_set_viewport(ctx->cso, &vp); + + /* + * Setup sampler state + * Note: we should only have to set the min/max LOD clamps to ensure + * we grab texels from the right mipmap level. But some hardware + * has trouble with min clamping so we also set the lod_bias to + * try to work around that. + */ + ctx->sampler.min_lod = ctx->sampler.max_lod = (float) srcLevel; + ctx->sampler.lod_bias = (float) srcLevel; + cso_single_sampler(ctx->cso, 0, &ctx->sampler); + cso_single_sampler_done(ctx->cso); + + cso_set_fragment_sampler_views(ctx->cso, 1, &psv); + + /* quad coords in clip coords */ + offset = set_vertex_data(ctx, + pt->target, + face, + rcoord); + + util_draw_vertex_buffer(ctx->pipe, + ctx->cso, + ctx->vbuf, + offset, + PIPE_PRIM_TRIANGLE_FAN, + 4, /* verts */ + 2); /* attribs/vert */ + + /* need to signal that the texture has changed _after_ rendering to it */ + pipe_surface_reference( &surf, NULL ); + } + } + + /* restore state we changed */ + cso_restore_blend(ctx->cso); + cso_restore_depth_stencil_alpha(ctx->cso); + cso_restore_rasterizer(ctx->cso); + cso_restore_samplers(ctx->cso); + cso_restore_fragment_sampler_views(ctx->cso); + cso_restore_framebuffer(ctx->cso); + cso_restore_fragment_shader(ctx->cso); + cso_restore_vertex_shader(ctx->cso); + cso_restore_viewport(ctx->cso); + cso_restore_clip(ctx->cso); + cso_restore_vertex_elements(ctx->cso); +} diff --git a/mesalib/src/gallium/auxiliary/util/u_gen_mipmap.h b/mesalib/src/gallium/auxiliary/util/u_gen_mipmap.h new file mode 100644 index 000000000..e4670a43c --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_gen_mipmap.h @@ -0,0 +1,70 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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 TUNGSTEN GRAPHICS 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 U_GENMIPMAP_H +#define U_GENMIPMAP_H + +#include "pipe/p_state.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +struct pipe_context; +struct pipe_resource; +struct cso_context; + +struct gen_mipmap_state; + + +extern struct gen_mipmap_state * +util_create_gen_mipmap(struct pipe_context *pipe, struct cso_context *cso); + + +extern void +util_destroy_gen_mipmap(struct gen_mipmap_state *ctx); + +/* Release vertex buffer at end of frame to avoid synchronous + * rendering. + */ +extern void +util_gen_mipmap_flush( struct gen_mipmap_state *ctx ); + + +extern void +util_gen_mipmap(struct gen_mipmap_state *ctx, + struct pipe_sampler_view *psv, + uint layer, uint baseLevel, uint lastLevel, uint filter); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/mesalib/src/gallium/auxiliary/util/u_half.h b/mesalib/src/gallium/auxiliary/util/u_half.h new file mode 100644 index 000000000..b19527981 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_half.h @@ -0,0 +1,90 @@ +/************************************************************************** + * + * Copyright 2010 Luca Barbieri + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and 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 COPYRIGHT OWNER(S) 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 U_HALF_H +#define U_HALF_H + +#include "pipe/p_compiler.h" +#include "util/u_math.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const uint32_t util_half_to_float_mantissa_table[2048]; +extern const uint32_t util_half_to_float_exponent_table[64]; +extern const uint32_t util_half_to_float_offset_table[64]; +extern const uint16_t util_float_to_half_base_table[512]; +extern const uint8_t util_float_to_half_shift_table[512]; + +/* + * Note that if the half float is a signaling NaN, the x87 FPU will turn + * it into a quiet NaN immediately upon loading into a float. + * + * Additionally, denormals may be flushed to zero. + * + * To avoid this, use the floatui functions instead of the float ones + * when just doing conversion rather than computation on the resulting + * floats. + */ + +static INLINE uint32_t +util_half_to_floatui(uint16_t h) +{ + unsigned exp = h >> 10; + return util_half_to_float_mantissa_table[util_half_to_float_offset_table[exp] + (h & 0x3ff)] + util_half_to_float_exponent_table[exp]; +} + +static INLINE float +util_half_to_float(uint16_t h) +{ + union fi r; + r.ui = util_half_to_floatui(h); + return r.f; +} + +static INLINE uint16_t +util_floatui_to_half(uint32_t v) +{ + unsigned signexp = v >> 23; + return util_float_to_half_base_table[signexp] + ((v & 0x007fffff) >> util_float_to_half_shift_table[signexp]); +} + +static INLINE uint16_t +util_float_to_half(float f) +{ + union fi i; + i.f = f; + return util_floatui_to_half(i.ui); +} + +#ifdef __cplusplus +} +#endif + +#endif /* U_HALF_H */ + diff --git a/mesalib/src/gallium/auxiliary/util/u_half.py b/mesalib/src/gallium/auxiliary/util/u_half.py new file mode 100644 index 000000000..88ee43c25 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_half.py @@ -0,0 +1,179 @@ +# Copyright 2010 Luca Barbieri +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and 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 COPYRIGHT OWNER(S) 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 code is a reimplementation of the algorithm in +# www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf +# "Fast Half Float Conversions" by Jeroen van der Zijp, Nov 2008 +# +# The table contents have been slightly changed so that the exponent +# bias is now in the exponent table instead of the mantissa table (mostly +# for cosmetic reasons, and because it theoretically allows a variant +# that flushes denormal to zero but uses a mantissa table with 24-bit +# entries). +# +# The tables are also constructed slightly differently. +# + +# Note that using a 64K * 4 table is a terrible idea since it will not fit +# in the L1 cache and will massively pollute the L2 cache as well +# +# These should instead fit in the L1 cache. +# +# TODO: we could use a denormal bias table instead of the mantissa/offset +# tables: this would reduce the L1 cache usage from 8704 to 2304 bytes +# but would involve more computation +# +# Note however that if denormals are never encountered, the L1 cache usage +# is only about 4608 bytes anyway. + +table_index = None +table_length = None + +def begin(t, n, l): + global table_length + global table_index + table_index = 0 + table_length = l + print + print "const " + t + " " + n + "[" + str(l) + "] = {" + +def value(v): + global table_index + table_index += 1 + print "\t" + hex(v) + "," + +def end(): + global table_length + global table_index + print "};" + assert table_index == table_length + +print "/* This file is autogenerated by u_half.py. Do not edit directly. */" +print "#include \"util/u_half.h\"" + +begin("uint32_t", "util_half_to_float_mantissa_table", 2048) +# zero +value(0) + +# denormals +for i in xrange(1, 1024): + m = i << 13 + e = 0 + + # normalize number + while (m & 0x00800000) == 0: + e -= 0x00800000 + m <<= 1 + + m &= ~0x00800000 + e += 0x38800000 + value(m | e) + +# normals +for i in xrange(1024, 2048): + value((i - 1024) << 13) +end() + +begin("uint32_t", "util_half_to_float_exponent_table", 64) +# positive zero or denormals +value(0) + +# positive numbers +for i in xrange(1, 31): + value(0x38000000 + (i << 23)) + +# positive infinity/NaN +value(0x7f800000) + +# negative zero or denormals +value(0x80000000) + +# negative numbers +for i in range(33, 63): + value(0xb8000000 + ((i - 32) << 23)) + +# negative infinity/NaN +value(0xff800000) +end() + +begin("uint32_t", "util_half_to_float_offset_table", 64) +# positive zero or denormals +value(0) + +# positive normals +for i in range(1, 32): + value(1024) + +# negative zero or denormals +value(0) + +# negative normals +for i in xrange(33, 64): + value(1024) +end() + +begin("uint16_t", "util_float_to_half_base_table", 512) +for sign in (0, 0x8000): + # very small numbers mapping to zero + for i in xrange(-127, -24): + value(sign | 0) + + # small numbers mapping to denormals + for i in xrange(-24, -14): + value(sign | (0x400 >> (-14 -i))) + + # normal numbers + for i in xrange(-14, 16): + value(sign | ((i + 15) << 10)) + + # large numbers mapping to infinity + for i in xrange(16, 128): + value(sign | 0x7c00) + + # infinity and NaNs + value(sign | 0x7c00) +end() + +begin("uint8_t", "util_float_to_half_shift_table", 512) +for sign in (0, 0x8000): + # very small numbers mapping to zero + for i in xrange(-127, -24): + value(24) + + # small numbers mapping to denormals + for i in xrange(-24, -14): + value(-1 - i) + + # normal numbers + for i in xrange(-14, 16): + value(13) + + # large numbers mapping to infinity + for i in xrange(16, 128): + value(24) + + # infinity and NaNs + value(13) +end() + diff --git a/mesalib/src/gallium/auxiliary/util/u_handle_table.c b/mesalib/src/gallium/auxiliary/util/u_handle_table.c new file mode 100644 index 000000000..532d1ea6c --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_handle_table.c @@ -0,0 +1,298 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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 TUNGSTEN GRAPHICS 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 + * Generic handle table implementation. + * + * @author José Fonseca + */ + + +#include "pipe/p_compiler.h" +#include "util/u_debug.h" + +#include "util/u_memory.h" +#include "util/u_handle_table.h" + + +#define HANDLE_TABLE_INITIAL_SIZE 16 + + +struct handle_table +{ + /** Object array. Empty handles have a null object */ + void **objects; + + /** Number of objects the handle can currently hold */ + unsigned size; + /** Number of consecutive objects allocated at the start of the table */ + unsigned filled; + + /** Optional object destructor */ + void (*destroy)(void *object); +}; + + +struct handle_table * +handle_table_create(void) +{ + struct handle_table *ht; + + ht = MALLOC_STRUCT(handle_table); + if(!ht) + return NULL; + + ht->objects = (void **)CALLOC(HANDLE_TABLE_INITIAL_SIZE, sizeof(void *)); + if(!ht->objects) { + FREE(ht); + return NULL; + } + + ht->size = HANDLE_TABLE_INITIAL_SIZE; + ht->filled = 0; + + ht->destroy = NULL; + + return ht; +} + + +void +handle_table_set_destroy(struct handle_table *ht, + void (*destroy)(void *object)) +{ + assert(ht); + if (!ht) + return; + ht->destroy = destroy; +} + + +/** + * Resize the table if necessary + */ +static INLINE int +handle_table_resize(struct handle_table *ht, + unsigned minimum_size) +{ + unsigned new_size; + void **new_objects; + + if(ht->size > minimum_size) + return ht->size; + + new_size = ht->size; + while(!(new_size > minimum_size)) + new_size *= 2; + assert(new_size); + + new_objects = (void **)REALLOC((void *)ht->objects, + ht->size*sizeof(void *), + new_size*sizeof(void *)); + if(!new_objects) + return 0; + + memset(new_objects + ht->size, 0, (new_size - ht->size)*sizeof(void *)); + + ht->size = new_size; + ht->objects = new_objects; + + return ht->size; +} + + +static INLINE void +handle_table_clear(struct handle_table *ht, + unsigned index) +{ + void *object; + + /* The order here is important so that the object being destroyed is not + * present in the table when seen by the destroy callback, because the + * destroy callback may directly or indirectly call the other functions in + * this module. + */ + + object = ht->objects[index]; + if(object) { + ht->objects[index] = NULL; + + if(ht->destroy) + ht->destroy(object); + } +} + + +unsigned +handle_table_add(struct handle_table *ht, + void *object) +{ + unsigned index; + unsigned handle; + + assert(ht); + assert(object); + if(!object || !ht) + return 0; + + /* linear search for an empty handle */ + while(ht->filled < ht->size) { + if(!ht->objects[ht->filled]) + break; + ++ht->filled; + } + + index = ht->filled; + handle = index + 1; + + /* check integer overflow */ + if(!handle) + return 0; + + /* grow the table if necessary */ + if(!handle_table_resize(ht, index)) + return 0; + + assert(!ht->objects[index]); + ht->objects[index] = object; + ++ht->filled; + + return handle; +} + + +unsigned +handle_table_set(struct handle_table *ht, + unsigned handle, + void *object) +{ + unsigned index; + + assert(ht); + assert(handle); + if(!handle || !ht) + return 0; + + assert(object); + if(!object) + return 0; + + index = handle - 1; + + /* grow the table if necessary */ + if(!handle_table_resize(ht, index)) + return 0; + + handle_table_clear(ht, index); + + ht->objects[index] = object; + + return handle; +} + + +void * +handle_table_get(struct handle_table *ht, + unsigned handle) +{ + void *object; + + assert(ht); + assert(handle); + if(!handle || !ht || handle > ht->size) + return NULL; + + object = ht->objects[handle - 1]; + + return object; +} + + +void +handle_table_remove(struct handle_table *ht, + unsigned handle) +{ + void *object; + unsigned index; + + assert(ht); + assert(handle); + if(!handle || !ht || handle > ht->size) + return; + + index = handle - 1; + object = ht->objects[index]; + if(!object) + return; + + handle_table_clear(ht, index); + + if(index < ht->filled) + ht->filled = index; +} + + +unsigned +handle_table_get_next_handle(struct handle_table *ht, + unsigned handle) +{ + unsigned index; + + for(index = handle; index < ht->size; ++index) { + if(ht->objects[index]) + return index + 1; + } + + return 0; +} + + +unsigned +handle_table_get_first_handle(struct handle_table *ht) +{ + return handle_table_get_next_handle(ht, 0); +} + + +void +handle_table_destroy(struct handle_table *ht) +{ + unsigned index; + assert(ht); + + if (!ht) + return; + + if(ht->destroy) + for(index = 0; index < ht->size; ++index) + handle_table_clear(ht, index); + + FREE(ht->objects); + FREE(ht); +} + diff --git a/mesalib/src/gallium/auxiliary/util/u_handle_table.h b/mesalib/src/gallium/auxiliary/util/u_handle_table.h new file mode 100644 index 000000000..a7320830e --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_handle_table.h @@ -0,0 +1,116 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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 TUNGSTEN GRAPHICS 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 + * Generic handle table. + * + * @author José Fonseca + */ + +#ifndef U_HANDLE_TABLE_H_ +#define U_HANDLE_TABLE_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Abstract data type to map integer handles to objects. + * + * Also referred as "pointer array". + */ +struct handle_table; + + +struct handle_table * +handle_table_create(void); + + +/** + * Set an optional destructor callback. + * + * If set, it will be called during handle_table_remove and + * handle_table_destroy calls. + */ +void +handle_table_set_destroy(struct handle_table *ht, + void (*destroy)(void *object)); + + +/** + * Add a new object. + * + * Returns a zero handle on failure (out of memory). + */ +unsigned +handle_table_add(struct handle_table *ht, + void *object); + +/** + * Returns zero on failure (out of memory). + */ +unsigned +handle_table_set(struct handle_table *ht, + unsigned handle, + void *object); + +/** + * Fetch an existing object. + * + * Returns NULL for an invalid handle. + */ +void * +handle_table_get(struct handle_table *ht, + unsigned handle); + + +void +handle_table_remove(struct handle_table *ht, + unsigned handle); + + +void +handle_table_destroy(struct handle_table *ht); + + +unsigned +handle_table_get_first_handle(struct handle_table *ht); + + +unsigned +handle_table_get_next_handle(struct handle_table *ht, + unsigned handle); + + +#ifdef __cplusplus +} +#endif + +#endif /* U_HANDLE_TABLE_H_ */ diff --git a/mesalib/src/gallium/auxiliary/util/u_hash.c b/mesalib/src/gallium/auxiliary/util/u_hash.c new file mode 100644 index 000000000..e0400c277 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_hash.c @@ -0,0 +1,121 @@ +/************************************************************************** + * + * 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 + * Hash functions implementation. + * + * @author Jose Fonseca + */ + + +#include "u_hash.h" + + +static const uint32_t +util_crc32_table[256] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, + 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, + 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, + 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, + 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, + 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, + 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, + 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, + 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, + 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, + 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, + 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, + 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, + 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, + 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, + 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, + 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, + 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +}; + + +/** + * @sa http://www.w3.org/TR/PNG/#D-CRCAppendix + */ +uint32_t +util_hash_crc32(const void *data, size_t size) +{ + uint8_t *p = (uint8_t *)data; + uint32_t crc = 0xffffffff; + + while (size--) + crc = util_crc32_table[(crc ^ *p++) & 0xff] ^ (crc >> 8); + + return crc; +} diff --git a/mesalib/src/gallium/auxiliary/util/u_hash.h b/mesalib/src/gallium/auxiliary/util/u_hash.h new file mode 100644 index 000000000..feda08217 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_hash.h @@ -0,0 +1,55 @@ +/************************************************************************** + * + * 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 + * Hash functions. + * + * @author Jose Fonseca + */ + +#ifndef U_HASH_H_ +#define U_HASH_H_ + + +#include "pipe/p_compiler.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +uint32_t +util_hash_crc32(const void *data, size_t size); + + +#ifdef __cplusplus +} +#endif + +#endif /* U_HASH_H_ */ diff --git a/mesalib/src/gallium/auxiliary/util/u_hash_table.c b/mesalib/src/gallium/auxiliary/util/u_hash_table.c new file mode 100644 index 000000000..417cc15be --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_hash_table.c @@ -0,0 +1,293 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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 TUNGSTEN GRAPHICS 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 + * General purpose hash table implementation. + * + * Just uses the cso_hash for now, but it might be better switch to a linear + * probing hash table implementation at some point -- as it is said they have + * better lookup and cache performance and it appears to be possible to write + * a lock-free implementation of such hash tables . + * + * @author José Fonseca + */ + + +#include "pipe/p_compiler.h" +#include "util/u_debug.h" + +#include "cso_cache/cso_hash.h" + +#include "util/u_memory.h" +#include "util/u_hash_table.h" + + +struct util_hash_table +{ + struct cso_hash *cso; + + /** Hash function */ + unsigned (*hash)(void *key); + + /** Compare two keys */ + int (*compare)(void *key1, void *key2); + + /* TODO: key, value destructors? */ +}; + + +struct util_hash_table_item +{ + void *key; + void *value; +}; + + +static INLINE struct util_hash_table_item * +util_hash_table_item(struct cso_hash_iter iter) +{ + return (struct util_hash_table_item *)cso_hash_iter_data(iter); +} + + +struct util_hash_table * +util_hash_table_create(unsigned (*hash)(void *key), + int (*compare)(void *key1, void *key2)) +{ + struct util_hash_table *ht; + + ht = MALLOC_STRUCT(util_hash_table); + if(!ht) + return NULL; + + ht->cso = cso_hash_create(); + if(!ht->cso) { + FREE(ht); + return NULL; + } + + ht->hash = hash; + ht->compare = compare; + + return ht; +} + + +static INLINE struct cso_hash_iter +util_hash_table_find_iter(struct util_hash_table *ht, + void *key, + unsigned key_hash) +{ + struct cso_hash_iter iter; + struct util_hash_table_item *item; + + iter = cso_hash_find(ht->cso, key_hash); + while (!cso_hash_iter_is_null(iter)) { + item = (struct util_hash_table_item *)cso_hash_iter_data(iter); + if (!ht->compare(item->key, key)) + break; + iter = cso_hash_iter_next(iter); + } + + return iter; +} + + +static INLINE struct util_hash_table_item * +util_hash_table_find_item(struct util_hash_table *ht, + void *key, + unsigned key_hash) +{ + struct cso_hash_iter iter; + struct util_hash_table_item *item; + + iter = cso_hash_find(ht->cso, key_hash); + while (!cso_hash_iter_is_null(iter)) { + item = (struct util_hash_table_item *)cso_hash_iter_data(iter); + if (!ht->compare(item->key, key)) + return item; + iter = cso_hash_iter_next(iter); + } + + return NULL; +} + + +enum pipe_error +util_hash_table_set(struct util_hash_table *ht, + void *key, + void *value) +{ + unsigned key_hash; + struct util_hash_table_item *item; + struct cso_hash_iter iter; + + assert(ht); + if (!ht) + return PIPE_ERROR_BAD_INPUT; + + key_hash = ht->hash(key); + + item = util_hash_table_find_item(ht, key, key_hash); + if(item) { + /* TODO: key/value destruction? */ + item->value = value; + return PIPE_OK; + } + + item = MALLOC_STRUCT(util_hash_table_item); + if(!item) + return PIPE_ERROR_OUT_OF_MEMORY; + + item->key = key; + item->value = value; + + iter = cso_hash_insert(ht->cso, key_hash, item); + if(cso_hash_iter_is_null(iter)) { + FREE(item); + return PIPE_ERROR_OUT_OF_MEMORY; + } + + return PIPE_OK; +} + + +void * +util_hash_table_get(struct util_hash_table *ht, + void *key) +{ + unsigned key_hash; + struct util_hash_table_item *item; + + assert(ht); + if (!ht) + return NULL; + + key_hash = ht->hash(key); + + item = util_hash_table_find_item(ht, key, key_hash); + if(!item) + return NULL; + + return item->value; +} + + +void +util_hash_table_remove(struct util_hash_table *ht, + void *key) +{ + unsigned key_hash; + struct cso_hash_iter iter; + struct util_hash_table_item *item; + + assert(ht); + if (!ht) + return; + + key_hash = ht->hash(key); + + iter = util_hash_table_find_iter(ht, key, key_hash); + if(cso_hash_iter_is_null(iter)) + return; + + item = util_hash_table_item(iter); + assert(item); + FREE(item); + + cso_hash_erase(ht->cso, iter); +} + + +void +util_hash_table_clear(struct util_hash_table *ht) +{ + struct cso_hash_iter iter; + struct util_hash_table_item *item; + + assert(ht); + if (!ht) + return; + + iter = cso_hash_first_node(ht->cso); + while (!cso_hash_iter_is_null(iter)) { + item = (struct util_hash_table_item *)cso_hash_take(ht->cso, cso_hash_iter_key(iter)); + FREE(item); + iter = cso_hash_first_node(ht->cso); + } +} + + +enum pipe_error +util_hash_table_foreach(struct util_hash_table *ht, + enum pipe_error (*callback) + (void *key, void *value, void *data), + void *data) +{ + struct cso_hash_iter iter; + struct util_hash_table_item *item; + enum pipe_error result; + + assert(ht); + if (!ht) + return PIPE_ERROR_BAD_INPUT; + + iter = cso_hash_first_node(ht->cso); + while (!cso_hash_iter_is_null(iter)) { + item = (struct util_hash_table_item *)cso_hash_iter_data(iter); + result = callback(item->key, item->value, data); + if(result != PIPE_OK) + return result; + iter = cso_hash_iter_next(iter); + } + + return PIPE_OK; +} + + +void +util_hash_table_destroy(struct util_hash_table *ht) +{ + struct cso_hash_iter iter; + struct util_hash_table_item *item; + + assert(ht); + if (!ht) + return; + + iter = cso_hash_first_node(ht->cso); + while (!cso_hash_iter_is_null(iter)) { + item = (struct util_hash_table_item *)cso_hash_iter_data(iter); + FREE(item); + iter = cso_hash_iter_next(iter); + } + + cso_hash_delete(ht->cso); + + FREE(ht); +} diff --git a/mesalib/src/gallium/auxiliary/util/u_hash_table.h b/mesalib/src/gallium/auxiliary/util/u_hash_table.h new file mode 100644 index 000000000..5b14ff72d --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_hash_table.h @@ -0,0 +1,96 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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 TUNGSTEN GRAPHICS 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. + * + **************************************************************************/ + +/** + * General purpose hash table. + * + * @author José Fonseca + */ + +#ifndef U_HASH_TABLE_H_ +#define U_HASH_TABLE_H_ + + +#include "pipe/p_defines.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Generic purpose hash table. + */ +struct util_hash_table; + + +/** + * Create an hash table. + * + * @param hash hash function + * @param compare should return 0 for two equal keys. + */ +struct util_hash_table * +util_hash_table_create(unsigned (*hash)(void *key), + int (*compare)(void *key1, void *key2)); + + +enum pipe_error +util_hash_table_set(struct util_hash_table *ht, + void *key, + void *value); + +void * +util_hash_table_get(struct util_hash_table *ht, + void *key); + + +void +util_hash_table_remove(struct util_hash_table *ht, + void *key); + + +void +util_hash_table_clear(struct util_hash_table *ht); + + +enum pipe_error +util_hash_table_foreach(struct util_hash_table *ht, + enum pipe_error (*callback) + (void *key, void *value, void *data), + void *data); + +void +util_hash_table_destroy(struct util_hash_table *ht); + + +#ifdef __cplusplus +} +#endif + +#endif /* U_HASH_TABLE_H_ */ diff --git a/mesalib/src/gallium/auxiliary/util/u_index_modify.c b/mesalib/src/gallium/auxiliary/util/u_index_modify.c new file mode 100644 index 000000000..38e9b3700 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_index_modify.c @@ -0,0 +1,182 @@ +/* + * Copyright 2010 Marek Olšák + * + * Permission is hereby granted, free of charge, to 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 "pipe/p_context.h" +#include "util/u_index_modify.h" +#include "util/u_inlines.h" + +/* Ubyte indices. */ + +void util_shorten_ubyte_elts_to_userptr(struct pipe_context *context, + struct pipe_resource *elts, + int index_bias, + unsigned start, + unsigned count, + void *out) +{ + struct pipe_transfer *src_transfer; + unsigned char *in_map; + unsigned short *out_map = out; + unsigned i; + + in_map = pipe_buffer_map(context, elts, + PIPE_TRANSFER_READ | + PIPE_TRANSFER_UNSYNCHRONIZED, + &src_transfer); + in_map += start; + + for (i = 0; i < count; i++) { + *out_map = (unsigned short)(*in_map + index_bias); + in_map++; + out_map++; + } + + pipe_buffer_unmap(context, src_transfer); +} + +void util_shorten_ubyte_elts(struct pipe_context *context, + struct pipe_resource **elts, + int index_bias, + unsigned start, + unsigned count) +{ + struct pipe_resource* new_elts; + unsigned short *out_map; + struct pipe_transfer *dst_transfer; + + new_elts = pipe_buffer_create(context->screen, + PIPE_BIND_INDEX_BUFFER, + PIPE_USAGE_STATIC, + 2 * count); + + out_map = pipe_buffer_map(context, new_elts, PIPE_TRANSFER_WRITE, + &dst_transfer); + util_shorten_ubyte_elts_to_userptr(context, *elts, index_bias, + start, count, out_map); + pipe_buffer_unmap(context, dst_transfer); + + *elts = new_elts; +} + + +/* Ushort indices. */ + +void util_rebuild_ushort_elts_to_userptr(struct pipe_context *context, + struct pipe_resource *elts, + int index_bias, + unsigned start, unsigned count, + void *out) +{ + struct pipe_transfer *in_transfer = NULL; + unsigned short *in_map; + unsigned short *out_map = out; + unsigned i; + + in_map = pipe_buffer_map(context, elts, + PIPE_TRANSFER_READ | + PIPE_TRANSFER_UNSYNCHRONIZED, + &in_transfer); + in_map += start; + + for (i = 0; i < count; i++) { + *out_map = (unsigned short)(*in_map + index_bias); + in_map++; + out_map++; + } + + pipe_buffer_unmap(context, in_transfer); +} + +void util_rebuild_ushort_elts(struct pipe_context *context, + struct pipe_resource **elts, + int index_bias, + unsigned start, unsigned count) +{ + struct pipe_transfer *out_transfer = NULL; + struct pipe_resource *new_elts; + unsigned short *out_map; + + new_elts = pipe_buffer_create(context->screen, + PIPE_BIND_INDEX_BUFFER, + PIPE_USAGE_STATIC, + 2 * count); + + out_map = pipe_buffer_map(context, new_elts, + PIPE_TRANSFER_WRITE, &out_transfer); + util_rebuild_ushort_elts_to_userptr(context, *elts, index_bias, + start, count, out_map); + pipe_buffer_unmap(context, out_transfer); + + *elts = new_elts; +} + + +/* Uint indices. */ + +void util_rebuild_uint_elts_to_userptr(struct pipe_context *context, + struct pipe_resource *elts, + int index_bias, + unsigned start, unsigned count, + void *out) +{ + struct pipe_transfer *in_transfer = NULL; + unsigned int *in_map; + unsigned int *out_map = out; + unsigned i; + + in_map = pipe_buffer_map(context, elts, + PIPE_TRANSFER_READ | + PIPE_TRANSFER_UNSYNCHRONIZED, + &in_transfer); + in_map += start; + + for (i = 0; i < count; i++) { + *out_map = (unsigned int)(*in_map + index_bias); + in_map++; + out_map++; + } + + pipe_buffer_unmap(context, in_transfer); +} + +void util_rebuild_uint_elts(struct pipe_context *context, + struct pipe_resource **elts, + int index_bias, + unsigned start, unsigned count) +{ + struct pipe_transfer *out_transfer = NULL; + struct pipe_resource *new_elts; + unsigned int *out_map; + + new_elts = pipe_buffer_create(context->screen, + PIPE_BIND_INDEX_BUFFER, + PIPE_USAGE_STATIC, + 2 * count); + + out_map = pipe_buffer_map(context, new_elts, + PIPE_TRANSFER_WRITE, &out_transfer); + util_rebuild_uint_elts_to_userptr(context, *elts, index_bias, + start, count, out_map); + pipe_buffer_unmap(context, out_transfer); + + *elts = new_elts; +} diff --git a/mesalib/src/gallium/auxiliary/util/u_index_modify.h b/mesalib/src/gallium/auxiliary/util/u_index_modify.h new file mode 100644 index 000000000..3e5520b18 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_index_modify.h @@ -0,0 +1,68 @@ +/* + * Copyright 2010 Marek Olšák + * + * Permission is hereby granted, free of charge, to 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 UTIL_INDEX_MODIFY_H +#define UTIL_INDEX_MODIFY_H + +struct pipe_context; +struct pipe_resource; + +void util_shorten_ubyte_elts_to_userptr(struct pipe_context *context, + struct pipe_resource *elts, + int index_bias, + unsigned start, + unsigned count, + void *out); + +void util_shorten_ubyte_elts(struct pipe_context *context, + struct pipe_resource **elts, + int index_bias, + unsigned start, + unsigned count); + + + +void util_rebuild_ushort_elts_to_userptr(struct pipe_context *context, + struct pipe_resource *elts, + int index_bias, + unsigned start, unsigned count, + void *out); + +void util_rebuild_ushort_elts(struct pipe_context *context, + struct pipe_resource **elts, + int index_bias, + unsigned start, unsigned count); + + + +void util_rebuild_uint_elts_to_userptr(struct pipe_context *context, + struct pipe_resource *elts, + int index_bias, + unsigned start, unsigned count, + void *out); + +void util_rebuild_uint_elts(struct pipe_context *context, + struct pipe_resource **elts, + int index_bias, + unsigned start, unsigned count); + +#endif diff --git a/mesalib/src/gallium/auxiliary/util/u_init.h b/mesalib/src/gallium/auxiliary/util/u_init.h new file mode 100644 index 000000000..a1d4f1b04 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_init.h @@ -0,0 +1,52 @@ +/* + * Copyright 2010 Luca Barbieri + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and 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 COPYRIGHT OWNER(S) 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 U_INIT_H +#define U_INIT_H + +/* Use UTIL_INIT(f) to have f called at program initialization. + Note that it is only guaranteed to be called if any symbol in the + .c file it is in sis referenced by the program. + + UTIL_INIT functions are called in arbitrary order. +*/ + +#ifdef __cplusplus +/* use a C++ global constructor */ +#define UTIL_INIT(f) struct f##__gctor_t {f##__gctor_t() {x();}} f##__gctor; +#elif defined(_MSC_VER) +/* add a pointer to the section where MSVC stores global constructor pointers */ +/* see http://blogs.msdn.com/vcblog/archive/2006/10/20/crt-initialization.aspx and + http://stackoverflow.com/questions/1113409/attribute-constructor-equivalent-in-vc */ +#pragma section(".CRT$XCU",read) +#define UTIL_INIT(f) static void __cdecl f##__init(void) {f();}; __declspec(allocate(".CRT$XCU")) void (__cdecl* f##__xcu)(void) = f##__init; +#elif defined(__GNUC__) +#define UTIL_INIT(f) static void f##__init(void) __attribute__((constructor)); static void f##__init(void) {f();} +#else +#error Unsupported compiler: please find out how to implement global initializers in C on it +#endif + +#endif + diff --git a/mesalib/src/gallium/auxiliary/util/u_inlines.h b/mesalib/src/gallium/auxiliary/util/u_inlines.h new file mode 100644 index 000000000..ad47439d0 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_inlines.h @@ -0,0 +1,459 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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 TUNGSTEN GRAPHICS 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 U_INLINES_H +#define U_INLINES_H + +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_state.h" +#include "pipe/p_screen.h" +#include "util/u_debug.h" +#include "util/u_debug_describe.h" +#include "util/u_debug_refcnt.h" +#include "util/u_atomic.h" +#include "util/u_box.h" +#include "util/u_math.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* + * Reference counting helper functions. + */ + + +static INLINE void +pipe_reference_init(struct pipe_reference *reference, unsigned count) +{ + p_atomic_set(&reference->count, count); +} + +static INLINE boolean +pipe_is_referenced(struct pipe_reference *reference) +{ + return p_atomic_read(&reference->count) != 0; +} + +/** + * Update reference counting. + * The old thing pointed to, if any, will be unreferenced. + * Both 'ptr' and 'reference' may be NULL. + * \return TRUE if the object's refcount hits zero and should be destroyed. + */ +static INLINE boolean +pipe_reference_described(struct pipe_reference *ptr, + struct pipe_reference *reference, + debug_reference_descriptor get_desc) +{ + boolean destroy = FALSE; + + if(ptr != reference) { + /* bump the reference.count first */ + if (reference) { + assert(pipe_is_referenced(reference)); + p_atomic_inc(&reference->count); + debug_reference(reference, get_desc, 1); + } + + if (ptr) { + assert(pipe_is_referenced(ptr)); + if (p_atomic_dec_zero(&ptr->count)) { + destroy = TRUE; + } + debug_reference(ptr, get_desc, -1); + } + } + + return destroy; +} + +static INLINE boolean +pipe_reference(struct pipe_reference *ptr, struct pipe_reference *reference) +{ + return pipe_reference_described(ptr, reference, + (debug_reference_descriptor)debug_describe_reference); +} + +static INLINE void +pipe_surface_reference(struct pipe_surface **ptr, struct pipe_surface *surf) +{ + struct pipe_surface *old_surf = *ptr; + + if (pipe_reference_described(&(*ptr)->reference, &surf->reference, + (debug_reference_descriptor)debug_describe_surface)) + old_surf->context->surface_destroy(old_surf->context, old_surf); + *ptr = surf; +} + +static INLINE void +pipe_resource_reference(struct pipe_resource **ptr, struct pipe_resource *tex) +{ + struct pipe_resource *old_tex = *ptr; + + if (pipe_reference_described(&(*ptr)->reference, &tex->reference, + (debug_reference_descriptor)debug_describe_resource)) + old_tex->screen->resource_destroy(old_tex->screen, old_tex); + *ptr = tex; +} + +static INLINE void +pipe_sampler_view_reference(struct pipe_sampler_view **ptr, struct pipe_sampler_view *view) +{ + struct pipe_sampler_view *old_view = *ptr; + + if (pipe_reference_described(&(*ptr)->reference, &view->reference, + (debug_reference_descriptor)debug_describe_sampler_view)) + old_view->context->sampler_view_destroy(old_view->context, old_view); + *ptr = view; +} + +static INLINE void +pipe_surface_reset(struct pipe_context *ctx, struct pipe_surface* ps, + struct pipe_resource *pt, unsigned level, unsigned layer, + unsigned flags) +{ + pipe_resource_reference(&ps->texture, pt); + ps->format = pt->format; + ps->width = u_minify(pt->width0, level); + ps->height = u_minify(pt->height0, level); + ps->usage = flags; + ps->u.tex.level = level; + ps->u.tex.first_layer = ps->u.tex.last_layer = layer; + ps->context = ctx; +} + +static INLINE void +pipe_surface_init(struct pipe_context *ctx, struct pipe_surface* ps, + struct pipe_resource *pt, unsigned level, unsigned layer, + unsigned flags) +{ + ps->texture = 0; + pipe_reference_init(&ps->reference, 1); + pipe_surface_reset(ctx, ps, pt, level, layer, flags); +} + +/* Return true if the surfaces are equal. */ +static INLINE boolean +pipe_surface_equal(struct pipe_surface *s1, struct pipe_surface *s2) +{ + return s1->texture == s2->texture && + s1->format == s2->format && + (s1->texture->target != PIPE_BUFFER || + (s1->u.buf.first_element == s2->u.buf.first_element && + s1->u.buf.last_element == s2->u.buf.last_element)) && + (s1->texture->target == PIPE_BUFFER || + (s1->u.tex.level == s2->u.tex.level && + s1->u.tex.first_layer == s2->u.tex.first_layer && + s1->u.tex.last_layer == s2->u.tex.last_layer)); +} + +/* + * Convenience wrappers for screen buffer functions. + */ + +static INLINE struct pipe_resource * +pipe_buffer_create( struct pipe_screen *screen, + unsigned bind, + unsigned usage, + unsigned size ) +{ + struct pipe_resource buffer; + memset(&buffer, 0, sizeof buffer); + buffer.target = PIPE_BUFFER; + buffer.format = PIPE_FORMAT_R8_UNORM; /* want TYPELESS or similar */ + buffer.bind = bind; + buffer.usage = usage; + buffer.flags = 0; + buffer.width0 = size; + buffer.height0 = 1; + buffer.depth0 = 1; + buffer.array_size = 1; + return screen->resource_create(screen, &buffer); +} + + +static INLINE struct pipe_resource * +pipe_user_buffer_create( struct pipe_screen *screen, void *ptr, unsigned size, + unsigned usage ) +{ + return screen->user_buffer_create(screen, ptr, size, usage); +} + +static INLINE void * +pipe_buffer_map_range(struct pipe_context *pipe, + struct pipe_resource *buffer, + unsigned offset, + unsigned length, + unsigned usage, + struct pipe_transfer **transfer) +{ + struct pipe_box box; + void *map; + + assert(offset < buffer->width0); + assert(offset + length <= buffer->width0); + assert(length); + + u_box_1d(offset, length, &box); + + *transfer = pipe->get_transfer( pipe, + buffer, + 0, + usage, + &box); + + if (*transfer == NULL) + return NULL; + + map = pipe->transfer_map( pipe, *transfer ); + if (map == NULL) { + pipe->transfer_destroy( pipe, *transfer ); + *transfer = NULL; + return NULL; + } + + /* Match old screen->buffer_map_range() behaviour, return pointer + * to where the beginning of the buffer would be: + */ + return (void *)((char *)map - offset); +} + + +static INLINE void * +pipe_buffer_map(struct pipe_context *pipe, + struct pipe_resource *buffer, + unsigned usage, + struct pipe_transfer **transfer) +{ + return pipe_buffer_map_range(pipe, buffer, 0, buffer->width0, usage, transfer); +} + + +static INLINE void +pipe_buffer_unmap(struct pipe_context *pipe, + struct pipe_transfer *transfer) +{ + if (transfer) { + pipe->transfer_unmap(pipe, transfer); + pipe->transfer_destroy(pipe, transfer); + } +} + +static INLINE void +pipe_buffer_flush_mapped_range(struct pipe_context *pipe, + struct pipe_transfer *transfer, + unsigned offset, + unsigned length) +{ + struct pipe_box box; + int transfer_offset; + + assert(length); + assert(transfer->box.x <= offset); + assert(offset + length <= transfer->box.x + transfer->box.width); + + /* Match old screen->buffer_flush_mapped_range() behaviour, where + * offset parameter is relative to the start of the buffer, not the + * mapped range. + */ + transfer_offset = offset - transfer->box.x; + + u_box_1d(transfer_offset, length, &box); + + pipe->transfer_flush_region(pipe, transfer, &box); +} + +static INLINE void +pipe_buffer_write(struct pipe_context *pipe, + struct pipe_resource *buf, + unsigned offset, + unsigned size, + const void *data) +{ + struct pipe_box box; + unsigned usage = PIPE_TRANSFER_WRITE; + + if (offset == 0 && size == buf->width0) { + usage |= PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE; + } else { + usage |= PIPE_TRANSFER_DISCARD_RANGE; + } + + u_box_1d(offset, size, &box); + + pipe->transfer_inline_write( pipe, + buf, + 0, + usage, + &box, + data, + size, + 0); +} + +/** + * Special case for writing non-overlapping ranges. + * + * We can avoid GPU/CPU synchronization when writing range that has never + * been written before. + */ +static INLINE void +pipe_buffer_write_nooverlap(struct pipe_context *pipe, + struct pipe_resource *buf, + unsigned offset, unsigned size, + const void *data) +{ + struct pipe_box box; + + u_box_1d(offset, size, &box); + + pipe->transfer_inline_write(pipe, + buf, + 0, + (PIPE_TRANSFER_WRITE | + PIPE_TRANSFER_NOOVERWRITE), + &box, + data, + 0, 0); +} + +static INLINE void +pipe_buffer_read(struct pipe_context *pipe, + struct pipe_resource *buf, + unsigned offset, + unsigned size, + void *data) +{ + struct pipe_transfer *src_transfer; + ubyte *map; + + map = (ubyte *) pipe_buffer_map_range(pipe, + buf, + offset, size, + PIPE_TRANSFER_READ, + &src_transfer); + + if (map) + memcpy(data, map + offset, size); + + pipe_buffer_unmap(pipe, src_transfer); +} + +static INLINE struct pipe_transfer * +pipe_get_transfer( struct pipe_context *context, + struct pipe_resource *resource, + unsigned level, unsigned layer, + enum pipe_transfer_usage usage, + unsigned x, unsigned y, + unsigned w, unsigned h) +{ + struct pipe_box box; + u_box_2d_zslice( x, y, layer, w, h, &box ); + return context->get_transfer( context, + resource, + level, + usage, + &box ); +} + +static INLINE void * +pipe_transfer_map( struct pipe_context *context, + struct pipe_transfer *transfer ) +{ + return context->transfer_map( context, transfer ); +} + +static INLINE void +pipe_transfer_unmap( struct pipe_context *context, + struct pipe_transfer *transfer ) +{ + context->transfer_unmap( context, transfer ); +} + + +static INLINE void +pipe_transfer_destroy( struct pipe_context *context, + struct pipe_transfer *transfer ) +{ + context->transfer_destroy(context, transfer); +} + + +static INLINE boolean util_get_offset( + const struct pipe_rasterizer_state *templ, + unsigned fill_mode) +{ + switch(fill_mode) { + case PIPE_POLYGON_MODE_POINT: + return templ->offset_point; + case PIPE_POLYGON_MODE_LINE: + return templ->offset_line; + case PIPE_POLYGON_MODE_FILL: + return templ->offset_tri; + default: + assert(0); + return FALSE; + } +} + +/** + * This function is used to copy an array of pipe_vertex_buffer structures, + * while properly referencing the pipe_vertex_buffer::buffer member. + * + * \sa util_copy_framebuffer_state + */ +static INLINE void util_copy_vertex_buffers(struct pipe_vertex_buffer *dst, + unsigned *dst_count, + const struct pipe_vertex_buffer *src, + unsigned src_count) +{ + unsigned i; + + /* Reference the buffers of 'src' in 'dst'. */ + for (i = 0; i < src_count; i++) { + pipe_resource_reference(&dst[i].buffer, src[i].buffer); + } + /* Unreference the rest of the buffers in 'dst'. */ + for (; i < *dst_count; i++) { + pipe_resource_reference(&dst[i].buffer, NULL); + } + + /* Update the size of 'dst' and copy over the other members + * of pipe_vertex_buffer. */ + *dst_count = src_count; + memcpy(dst, src, src_count * sizeof(struct pipe_vertex_buffer)); +} + +#ifdef __cplusplus +} +#endif + +#endif /* U_INLINES_H */ diff --git a/mesalib/src/gallium/auxiliary/util/u_keymap.c b/mesalib/src/gallium/auxiliary/util/u_keymap.c new file mode 100644 index 000000000..a06478b21 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_keymap.c @@ -0,0 +1,318 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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 TUNGSTEN GRAPHICS 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. + * + **************************************************************************/ + +/** + * Key lookup/associative container. + * + * Like Jose's util_hash_table, based on CSO cache code for now. + * + * Author: Brian Paul + */ + + +#include "pipe/p_compiler.h" +#include "util/u_debug.h" + +#include "cso_cache/cso_hash.h" + +#include "util/u_memory.h" +#include "util/u_keymap.h" + + +struct keymap +{ + struct cso_hash *cso; + unsigned key_size; + unsigned max_entries; /* XXX not obeyed net */ + unsigned num_entries; + keymap_delete_func delete_func; +}; + + +struct keymap_item +{ + void *key, *value; +}; + + +/** + * This the default key-delete function used when the client doesn't + * provide one. + */ +static void +default_delete_func(const struct keymap *map, + const void *key, void *data, void *user) +{ + FREE((void*) data); +} + + +static INLINE struct keymap_item * +hash_table_item(struct cso_hash_iter iter) +{ + return (struct keymap_item *) cso_hash_iter_data(iter); +} + + +/** + * Return 4-byte hash key for a block of bytes. + */ +static unsigned +hash(const void *key, unsigned keySize) +{ + unsigned i, hash; + + keySize /= 4; /* convert from bytes to uints */ + + hash = 0; + for (i = 0; i < keySize; i++) { + hash ^= (i + 1) * ((const unsigned *) key)[i]; + } + + /*hash = hash ^ (hash >> 11) ^ (hash >> 22);*/ + + return hash; +} + + +/** + * Create a new map. + * \param keySize size of the keys in bytes + * \param maxEntries max number of entries to allow (~0 = infinity) + * \param deleteFunc optional callback to call when entries + * are deleted/replaced + */ +struct keymap * +util_new_keymap(unsigned keySize, unsigned maxEntries, + keymap_delete_func deleteFunc) +{ + struct keymap *map = MALLOC_STRUCT(keymap); + if (!map) + return NULL; + + map->cso = cso_hash_create(); + if (!map->cso) { + FREE(map); + return NULL; + } + + map->max_entries = maxEntries; + map->num_entries = 0; + map->key_size = keySize; + map->delete_func = deleteFunc ? deleteFunc : default_delete_func; + + return map; +} + + +/** + * Delete/free a keymap and all entries. The deleteFunc that was given at + * create time will be called for each entry. + * \param user user-provided pointer passed through to the delete callback + */ +void +util_delete_keymap(struct keymap *map, void *user) +{ + util_keymap_remove_all(map, user); + cso_hash_delete(map->cso); + FREE(map); +} + + +static INLINE struct cso_hash_iter +hash_table_find_iter(const struct keymap *map, const void *key, + unsigned key_hash) +{ + struct cso_hash_iter iter; + struct keymap_item *item; + + iter = cso_hash_find(map->cso, key_hash); + while (!cso_hash_iter_is_null(iter)) { + item = (struct keymap_item *) cso_hash_iter_data(iter); + if (!memcmp(item->key, key, map->key_size)) + break; + iter = cso_hash_iter_next(iter); + } + + return iter; +} + + +static INLINE struct keymap_item * +hash_table_find_item(const struct keymap *map, const void *key, + unsigned key_hash) +{ + struct cso_hash_iter iter = hash_table_find_iter(map, key, key_hash); + if (cso_hash_iter_is_null(iter)) { + return NULL; + } + else { + return hash_table_item(iter); + } +} + + +/** + * Insert a new key + data pointer into the table. + * Note: we create a copy of the key, but not the data! + * If the key is already present in the table, replace the existing + * entry (calling the delete callback on the previous entry). + * If the maximum capacity of the map is reached an old entry + * will be deleted (the delete callback will be called). + */ +boolean +util_keymap_insert(struct keymap *map, const void *key, + const void *data, void *user) +{ + unsigned key_hash; + struct keymap_item *item; + struct cso_hash_iter iter; + + assert(map); + if (!map) + return FALSE; + + key_hash = hash(key, map->key_size); + + item = hash_table_find_item(map, key, key_hash); + if (item) { + /* call delete callback for old entry/item */ + map->delete_func(map, item->key, item->value, user); + item->value = (void *) data; + return TRUE; + } + + item = MALLOC_STRUCT(keymap_item); + if (!item) + return FALSE; + + item->key = mem_dup(key, map->key_size); + item->value = (void *) data; + + iter = cso_hash_insert(map->cso, key_hash, item); + if (cso_hash_iter_is_null(iter)) { + FREE(item); + return FALSE; + } + + map->num_entries++; + + return TRUE; +} + + +/** + * Look up a key in the map and return the associated data pointer. + */ +const void * +util_keymap_lookup(const struct keymap *map, const void *key) +{ + unsigned key_hash; + struct keymap_item *item; + + assert(map); + if (!map) + return NULL; + + key_hash = hash(key, map->key_size); + + item = hash_table_find_item(map, key, key_hash); + if (!item) + return NULL; + + return item->value; +} + + +/** + * Remove an entry from the map. + * The delete callback will be called if the given key/entry is found. + * \param user passed to the delete callback as the last param. + */ +void +util_keymap_remove(struct keymap *map, const void *key, void *user) +{ + unsigned key_hash; + struct cso_hash_iter iter; + struct keymap_item *item; + + assert(map); + if (!map) + return; + + key_hash = hash(key, map->key_size); + + iter = hash_table_find_iter(map, key, key_hash); + if (cso_hash_iter_is_null(iter)) + return; + + item = hash_table_item(iter); + assert(item); + if (!item) + return; + map->delete_func(map, item->key, item->value, user); + FREE(item->key); + FREE(item); + + map->num_entries--; + + cso_hash_erase(map->cso, iter); +} + + +/** + * Remove all entries from the map, calling the delete callback for each. + * \param user passed to the delete callback as the last param. + */ +void +util_keymap_remove_all(struct keymap *map, void *user) +{ + struct cso_hash_iter iter; + struct keymap_item *item; + + assert(map); + if (!map) + return; + + iter = cso_hash_first_node(map->cso); + while (!cso_hash_iter_is_null(iter)) { + item = (struct keymap_item *) + cso_hash_take(map->cso, cso_hash_iter_key(iter)); + map->delete_func(map, item->key, item->value, user); + FREE(item->key); + FREE(item); + iter = cso_hash_first_node(map->cso); + } +} + + +extern void +util_keymap_info(const struct keymap *map) +{ + debug_printf("Keymap %p: %u of max %u entries\n", + (void *) map, map->num_entries, map->max_entries); +} diff --git a/mesalib/src/gallium/auxiliary/util/u_keymap.h b/mesalib/src/gallium/auxiliary/util/u_keymap.h new file mode 100644 index 000000000..e38e6fec6 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_keymap.h @@ -0,0 +1,68 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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 TUNGSTEN GRAPHICS 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 U_KEYMAP_H +#define U_KEYMAP_H + +#include "pipe/p_compiler.h" + + +/** opaque keymap type */ +struct keymap; + + +/** Delete/callback function type */ +typedef void (*keymap_delete_func)(const struct keymap *map, + const void *key, void *data, + void *user); + + +extern struct keymap * +util_new_keymap(unsigned keySize, unsigned maxEntries, + keymap_delete_func deleteFunc); + +extern void +util_delete_keymap(struct keymap *map, void *user); + +extern boolean +util_keymap_insert(struct keymap *map, const void *key, + const void *data, void *user); + +extern const void * +util_keymap_lookup(const struct keymap *map, const void *key); + +extern void +util_keymap_remove(struct keymap *map, const void *key, void *user); + +extern void +util_keymap_remove_all(struct keymap *map, void *user); + +extern void +util_keymap_info(const struct keymap *map); + + +#endif /* U_KEYMAP_H */ diff --git a/mesalib/src/gallium/auxiliary/util/u_linear.c b/mesalib/src/gallium/auxiliary/util/u_linear.c new file mode 100644 index 000000000..8f8935d8a --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_linear.c @@ -0,0 +1,101 @@ +/************************************************************************** + * + * 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. + * + **************************************************************************/ + +/** + * Functions for converting tiled data to linear and vice versa. + */ + + +#include "util/u_debug.h" +#include "u_linear.h" + +void +pipe_linear_to_tile(size_t src_stride, const void *src_ptr, + struct pipe_tile_info *t, void *dst_ptr) +{ + int x, y, z; + char *ptr; + size_t bytes = t->cols * t->block.size; + char *dst_ptr2 = (char *) dst_ptr; + + assert(pipe_linear_check_tile(t)); + + /* lets write lineary to the tiled buffer */ + for (y = 0; y < t->tiles_y; y++) { + for (x = 0; x < t->tiles_x; x++) { + /* this inner loop could be replace with SSE magic */ + ptr = (char*)src_ptr + src_stride * t->rows * y + bytes * x; + for (z = 0; z < t->rows; z++) { + memcpy(dst_ptr2, ptr, bytes); + dst_ptr2 += bytes; + ptr += src_stride; + } + } + } +} + +void pipe_linear_from_tile(struct pipe_tile_info *t, const void *src_ptr, + size_t dst_stride, void *dst_ptr) +{ + int x, y, z; + char *ptr; + size_t bytes = t->cols * t->block.size; + const char *src_ptr2 = (const char *) src_ptr; + + /* lets read lineary from the tiled buffer */ + for (y = 0; y < t->tiles_y; y++) { + for (x = 0; x < t->tiles_x; x++) { + /* this inner loop could be replace with SSE magic */ + ptr = (char*)dst_ptr + dst_stride * t->rows * y + bytes * x; + for (z = 0; z < t->rows; z++) { + memcpy(ptr, src_ptr2, bytes); + src_ptr2 += bytes; + ptr += dst_stride; + } + } + } +} + +void +pipe_linear_fill_info(struct pipe_tile_info *t, + const struct u_linear_format_block *block, + unsigned tile_width, unsigned tile_height, + unsigned tiles_x, unsigned tiles_y) +{ + t->block = *block; + + t->tile.width = tile_width; + t->tile.height = tile_height; + t->cols = t->tile.width / t->block.width; + t->rows = t->tile.height / t->block.height; + t->tile.size = t->cols * t->rows * t->block.size; + + t->tiles_x = tiles_x; + t->tiles_y = tiles_y; + t->stride = t->cols * t->tiles_x * t->block.size; + t->size = t->tiles_x * t->tiles_y * t->tile.size; +} diff --git a/mesalib/src/gallium/auxiliary/util/u_linear.h b/mesalib/src/gallium/auxiliary/util/u_linear.h new file mode 100644 index 000000000..38a790e3f --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_linear.h @@ -0,0 +1,106 @@ +/************************************************************************** + * + * 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. + * + **************************************************************************/ + +/** + * Functions for converting tiled data to linear and vice versa. + */ + + +#ifndef U_LINEAR_H +#define U_LINEAR_H + +#include "pipe/p_compiler.h" +#include "pipe/p_format.h" + +struct u_linear_format_block +{ + /** Block size in bytes */ + unsigned size; + + /** Block width in pixels */ + unsigned width; + + /** Block height in pixels */ + unsigned height; +}; + + +struct pipe_tile_info +{ + unsigned size; + unsigned stride; + + /* The number of tiles */ + unsigned tiles_x; + unsigned tiles_y; + + /* size of each tile expressed in blocks */ + unsigned cols; + unsigned rows; + + /* Describe the tile in pixels */ + struct u_linear_format_block tile; + + /* Describe each block within the tile */ + struct u_linear_format_block block; +}; + +void pipe_linear_to_tile(size_t src_stride, const void *src_ptr, + struct pipe_tile_info *t, void *dst_ptr); + +void pipe_linear_from_tile(struct pipe_tile_info *t, const void *src_ptr, + size_t dst_stride, void *dst_ptr); + +/** + * Convenience function to fillout a pipe_tile_info struct. + * @t info to fill out. + * @block block info about pixel layout + * @tile_width the width of the tile in pixels + * @tile_height the height of the tile in pixels + * @tiles_x number of tiles in x axis + * @tiles_y number of tiles in y axis + */ +void pipe_linear_fill_info(struct pipe_tile_info *t, + const struct u_linear_format_block *block, + unsigned tile_width, unsigned tile_height, + unsigned tiles_x, unsigned tiles_y); + +static INLINE boolean pipe_linear_check_tile(const struct pipe_tile_info *t) +{ + if (t->tile.size != t->block.size * t->cols * t->rows) + return FALSE; + + if (t->stride != t->block.size * t->cols * t->tiles_x) + return FALSE; + + if (t->size < t->stride * t->rows * t->tiles_y) + return FALSE; + + return TRUE; +} + +#endif /* U_LINEAR_H */ diff --git a/mesalib/src/gallium/auxiliary/util/u_linkage.c b/mesalib/src/gallium/auxiliary/util/u_linkage.c new file mode 100644 index 000000000..89d67accc --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_linkage.c @@ -0,0 +1,149 @@ +/************************************************************************** + * + * Copyright 2010 Luca Barbieri + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and 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 COPYRIGHT OWNER(S) 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_debug.h" +#include "pipe/p_shader_tokens.h" +#include "tgsi/tgsi_parse.h" +#include "tgsi/tgsi_scan.h" +#include "util/u_linkage.h" + +/* we must only record the registers that are actually used, not just declared */ +static INLINE boolean +util_semantic_set_test_and_set(struct util_semantic_set *set, unsigned value) +{ + unsigned mask = 1 << (value % (sizeof(long) * 8)); + unsigned long *p = &set->masks[value / (sizeof(long) * 8)]; + unsigned long v = *p & mask; + *p |= mask; + return !!v; +} + +unsigned +util_semantic_set_from_program_file(struct util_semantic_set *set, const struct tgsi_token *tokens, enum tgsi_file_type file) +{ + struct tgsi_shader_info info; + struct tgsi_parse_context parse; + unsigned count = 0; + ubyte *semantic_name; + ubyte *semantic_index; + + tgsi_scan_shader(tokens, &info); + + if(file == TGSI_FILE_INPUT) + { + semantic_name = info.input_semantic_name; + semantic_index = info.input_semantic_index; + } + else if(file == TGSI_FILE_OUTPUT) + { + semantic_name = info.output_semantic_name; + semantic_index = info.output_semantic_index; + } + else + { + assert(0); + semantic_name = NULL; + semantic_index = NULL; + } + + tgsi_parse_init(&parse, tokens); + + memset(set->masks, 0, sizeof(set->masks)); + while(!tgsi_parse_end_of_tokens(&parse)) + { + tgsi_parse_token(&parse); + + if(parse.FullToken.Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION) + { + const struct tgsi_full_instruction *finst = &parse.FullToken.FullInstruction; + unsigned i; + for(i = 0; i < finst->Instruction.NumDstRegs; ++i) + { + if(finst->Dst[i].Register.File == file) + { + unsigned idx = finst->Dst[i].Register.Index; + if(semantic_name[idx] == TGSI_SEMANTIC_GENERIC) + { + if(!util_semantic_set_test_and_set(set, semantic_index[idx])) + ++count; + } + } + } + + for(i = 0; i < finst->Instruction.NumSrcRegs; ++i) + { + if(finst->Src[i].Register.File == file) + { + unsigned idx = finst->Src[i].Register.Index; + if(semantic_name[idx] == TGSI_SEMANTIC_GENERIC) + { + if(!util_semantic_set_test_and_set(set, semantic_index[idx])) + ++count; + } + } + } + } + } + tgsi_parse_free(&parse); + + return count; +} + +#define UTIL_SEMANTIC_SET_FOR_EACH(i, set) for(i = 0; i < 256; ++i) if(set->masks[i / (sizeof(long) * 8)] & (1 << (i % (sizeof(long) * 8)))) + +void +util_semantic_layout_from_set(unsigned char *layout, const struct util_semantic_set *set, unsigned efficient_slots, unsigned num_slots) +{ + int first = -1; + int last = -1; + unsigned i; + + memset(layout, 0xff, num_slots); + + UTIL_SEMANTIC_SET_FOR_EACH(i, set) + { + if(first < 0) + first = i; + last = i; + } + + if(last < efficient_slots) + { + UTIL_SEMANTIC_SET_FOR_EACH(i, set) + layout[i] = i; + } + else if((last - first) < efficient_slots) + { + UTIL_SEMANTIC_SET_FOR_EACH(i, set) + layout[i - first] = i; + } + else + { + unsigned idx = 0; + UTIL_SEMANTIC_SET_FOR_EACH(i, set) + layout[idx++] = i; + } +} diff --git a/mesalib/src/gallium/auxiliary/util/u_linkage.h b/mesalib/src/gallium/auxiliary/util/u_linkage.h new file mode 100644 index 000000000..bca4d3b4a --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_linkage.h @@ -0,0 +1,66 @@ +/************************************************************************** + * + * Copyright 2010 Luca Barbieri + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and 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 COPYRIGHT OWNER(S) 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 U_LINKAGE_H_ +#define U_LINKAGE_H_ + +#include "pipe/p_compiler.h" +#include "pipe/p_shader_tokens.h" + +struct util_semantic_set +{ + unsigned long masks[256 / 8 / sizeof(unsigned long)]; +}; + +static INLINE bool +util_semantic_set_contains(struct util_semantic_set *set, unsigned char value) +{ + return !!(set->masks[value / (sizeof(long) * 8)] & (1 << (value / (sizeof(long) * 8)))); +} + +unsigned util_semantic_set_from_program_file(struct util_semantic_set *set, const struct tgsi_token *tokens, enum tgsi_file_type file); + +/* efficient_slots is the number of slots such that hardware performance is + * the same for using that amount, with holes, or less slots but with less + * holes. + * + * num_slots is the size of the layout array and hardware limit instead. + * + * efficient_slots == 0 or efficient_solts == num_slots are typical settings. + */ +void util_semantic_layout_from_set(unsigned char *layout, const struct util_semantic_set *set, unsigned efficient_slots, unsigned num_slots); + +static INLINE void +util_semantic_table_from_layout(unsigned char *table, unsigned char *layout, unsigned char first_slot_value, unsigned char num_slots) +{ + int i; + memset(table, 0xff, sizeof(table)); + + for(i = 0; i < num_slots; ++i) + table[layout[i]] = first_slot_value + i; +} + +#endif /* U_LINKAGE_H_ */ diff --git a/mesalib/src/gallium/auxiliary/util/u_math.c b/mesalib/src/gallium/auxiliary/util/u_math.c new file mode 100644 index 000000000..3044f5da8 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_math.c @@ -0,0 +1,73 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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 TUNGSTEN GRAPHICS 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_math.h" + + +/** 2^x, for x in [-1.0, 1.0) */ +float pow2_table[POW2_TABLE_SIZE]; + + +static void +init_pow2_table(void) +{ + int i; + for (i = 0; i < POW2_TABLE_SIZE; i++) + pow2_table[i] = (float) pow(2.0, (i - POW2_TABLE_OFFSET) / POW2_TABLE_SCALE); +} + + +/** log2(x), for x in [1.0, 2.0) */ +float log2_table[LOG2_TABLE_SIZE]; + + +static void +init_log2_table(void) +{ + unsigned i; + for (i = 0; i < LOG2_TABLE_SIZE; i++) + log2_table[i] = (float) log2(1.0 + i * (1.0 / LOG2_TABLE_SCALE)); +} + + +/** + * One time init for math utilities. + */ +void +util_init_math(void) +{ + static boolean initialized = FALSE; + if (!initialized) { + init_pow2_table(); + init_log2_table(); + initialized = TRUE; + } +} + + diff --git a/mesalib/src/gallium/auxiliary/util/u_math.h b/mesalib/src/gallium/auxiliary/util/u_math.h new file mode 100644 index 000000000..16a9eab6d --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_math.h @@ -0,0 +1,660 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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 TUNGSTEN GRAPHICS 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. + * + **************************************************************************/ + + +/** + * Math utilities and approximations for common math functions. + * Reduced precision is usually acceptable in shaders... + * + * "fast" is used in the names of functions which are low-precision, + * or at least lower-precision than the normal C lib functions. + */ + + +#ifndef U_MATH_H +#define U_MATH_H + + +#include "pipe/p_compiler.h" +#include "util/u_debug.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +#if defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT) +__inline double ceil(double val) +{ + double ceil_val; + + if ((val - (long) val) == 0) { + ceil_val = val; + } + else { + if (val > 0) { + ceil_val = (long) val + 1; + } + else { + ceil_val = (long) val; + } + } + + return ceil_val; +} + +#ifndef PIPE_SUBSYSTEM_WINDOWS_CE_OGL +__inline double floor(double val) +{ + double floor_val; + + if ((val - (long) val) == 0) { + floor_val = val; + } + else { + if (val > 0) { + floor_val = (long) val; + } + else { + floor_val = (long) val - 1; + } + } + + return floor_val; +} +#endif + +#pragma function(pow) +__inline double __cdecl pow(double val, double exponent) +{ + /* XXX */ + assert(0); + return 0; +} + +#pragma function(log) +__inline double __cdecl log(double val) +{ + /* XXX */ + assert(0); + return 0; +} + +#pragma function(atan2) +__inline double __cdecl atan2(double val) +{ + /* XXX */ + assert(0); + return 0; +} +#else +#include +#include +#endif + + +#ifndef M_SQRT2 +#define M_SQRT2 1.41421356237309504880 +#endif + + +#if defined(_MSC_VER) + +#if _MSC_VER < 1400 && !defined(__cplusplus) || defined(PIPE_SUBSYSTEM_WINDOWS_CE) + +static INLINE float cosf( float f ) +{ + return (float) cos( (double) f ); +} + +static INLINE float sinf( float f ) +{ + return (float) sin( (double) f ); +} + +static INLINE float ceilf( float f ) +{ + return (float) ceil( (double) f ); +} + +static INLINE float floorf( float f ) +{ + return (float) floor( (double) f ); +} + +static INLINE float powf( float f, float g ) +{ + return (float) pow( (double) f, (double) g ); +} + +static INLINE float sqrtf( float f ) +{ + return (float) sqrt( (double) f ); +} + +static INLINE float fabsf( float f ) +{ + return (float) fabs( (double) f ); +} + +static INLINE float logf( float f ) +{ + return (float) log( (double) f ); +} + +#else +/* Work-around an extra semi-colon in VS 2005 logf definition */ +#ifdef logf +#undef logf +#define logf(x) ((float)log((double)(x))) +#endif /* logf */ + +#define isfinite(x) _finite((double)(x)) +#define isnan(x) _isnan((double)(x)) +#endif /* _MSC_VER < 1400 && !defined(__cplusplus) */ + +static INLINE double log2( double x ) +{ + const double invln2 = 1.442695041; + return log( x ) * invln2; +} + +static INLINE double +round(double x) +{ + return x >= 0.0 ? floor(x + 0.5) : ceil(x - 0.5); +} + +static INLINE float +roundf(float x) +{ + return x >= 0.0f ? floorf(x + 0.5f) : ceilf(x - 0.5f); +} + +#endif /* _MSC_VER */ + + + + + +#define POW2_TABLE_SIZE_LOG2 9 +#define POW2_TABLE_SIZE (1 << POW2_TABLE_SIZE_LOG2) +#define POW2_TABLE_OFFSET (POW2_TABLE_SIZE/2) +#define POW2_TABLE_SCALE ((float)(POW2_TABLE_SIZE/2)) +extern float pow2_table[POW2_TABLE_SIZE]; + + +/** + * Initialize math module. This should be called before using any + * other functions in this module. + */ +extern void +util_init_math(void); + + +union fi { + float f; + int32_t i; + uint32_t ui; +}; + + +/** + * Fast version of 2^x + * Identity: exp2(a + b) = exp2(a) * exp2(b) + * Let ipart = int(x) + * Let fpart = x - ipart; + * So, exp2(x) = exp2(ipart) * exp2(fpart) + * Compute exp2(ipart) with i << ipart + * Compute exp2(fpart) with lookup table. + */ +static INLINE float +util_fast_exp2(float x) +{ + int32_t ipart; + float fpart, mpart; + union fi epart; + + if(x > 129.00000f) + return 3.402823466e+38f; + + if (x < -126.99999f) + return 0.0f; + + ipart = (int32_t) x; + fpart = x - (float) ipart; + + /* same as + * epart.f = (float) (1 << ipart) + * but faster and without integer overflow for ipart > 31 + */ + epart.i = (ipart + 127 ) << 23; + + mpart = pow2_table[POW2_TABLE_OFFSET + (int)(fpart * POW2_TABLE_SCALE)]; + + return epart.f * mpart; +} + + +/** + * Fast approximation to exp(x). + */ +static INLINE float +util_fast_exp(float x) +{ + const float k = 1.44269f; /* = log2(e) */ + return util_fast_exp2(k * x); +} + + +#define LOG2_TABLE_SIZE_LOG2 16 +#define LOG2_TABLE_SCALE (1 << LOG2_TABLE_SIZE_LOG2) +#define LOG2_TABLE_SIZE (LOG2_TABLE_SCALE + 1) +extern float log2_table[LOG2_TABLE_SIZE]; + + +/** + * Fast approximation to log2(x). + */ +static INLINE float +util_fast_log2(float x) +{ + union fi num; + float epart, mpart; + num.f = x; + epart = (float)(((num.i & 0x7f800000) >> 23) - 127); + /* mpart = log2_table[mantissa*LOG2_TABLE_SCALE + 0.5] */ + mpart = log2_table[((num.i & 0x007fffff) + (1 << (22 - LOG2_TABLE_SIZE_LOG2))) >> (23 - LOG2_TABLE_SIZE_LOG2)]; + return epart + mpart; +} + + +/** + * Fast approximation to x^y. + */ +static INLINE float +util_fast_pow(float x, float y) +{ + return util_fast_exp2(util_fast_log2(x) * y); +} + +/* Note that this counts zero as a power of two. + */ +static INLINE boolean +util_is_power_of_two( unsigned v ) +{ + return (v & (v-1)) == 0; +} + + +/** + * Floor(x), returned as int. + */ +static INLINE int +util_ifloor(float f) +{ + int ai, bi; + double af, bf; + union fi u; + af = (3 << 22) + 0.5 + (double) f; + bf = (3 << 22) + 0.5 - (double) f; + u.f = (float) af; ai = u.i; + u.f = (float) bf; bi = u.i; + return (ai - bi) >> 1; +} + + +/** + * Round float to nearest int. + */ +static INLINE int +util_iround(float f) +{ +#if defined(PIPE_CC_GCC) && defined(PIPE_ARCH_X86) + int r; + __asm__ ("fistpl %0" : "=m" (r) : "t" (f) : "st"); + return r; +#elif defined(PIPE_CC_MSVC) && defined(PIPE_ARCH_X86) + int r; + _asm { + fld f + fistp r + } + return r; +#else + if (f >= 0.0f) + return (int) (f + 0.5f); + else + return (int) (f - 0.5f); +#endif +} + + +/** + * Approximate floating point comparison + */ +static INLINE boolean +util_is_approx(float a, float b, float tol) +{ + return fabs(b - a) <= tol; +} + + +/** + * Test if x is NaN or +/- infinity. + */ +static INLINE boolean +util_is_inf_or_nan(float x) +{ + union fi tmp; + tmp.f = x; + return !(int)((unsigned int)((tmp.i & 0x7fffffff)-0x7f800000) >> 31); +} + + +/** + * Find first bit set in word. Least significant bit is 1. + * Return 0 if no bits set. + */ +#if defined(_MSC_VER) && _MSC_VER >= 1300 && (_M_IX86 || _M_AMD64 || _M_IA64) +unsigned char _BitScanForward(unsigned long* Index, unsigned long Mask); +#pragma intrinsic(_BitScanForward) +static INLINE +unsigned long ffs( unsigned long u ) +{ + unsigned long i; + if (_BitScanForward(&i, u)) + return i + 1; + else + return 0; +} +#elif defined(PIPE_CC_MSVC) && defined(PIPE_ARCH_X86) +static INLINE +unsigned ffs( unsigned u ) +{ + unsigned i; + + if (u == 0) { + return 0; + } + + __asm bsf eax, [u] + __asm inc eax + __asm mov [i], eax + + return i; +} +#elif defined(__MINGW32__) +#define ffs __builtin_ffs +#endif + +#ifdef __MINGW32__ +#define ffs __builtin_ffs +#endif + + +/* Could also binary search for the highest bit. + */ +static INLINE unsigned +util_unsigned_logbase2(unsigned n) +{ + unsigned log2 = 0; + while (n >>= 1) + ++log2; + return log2; +} + + +/** + * Return float bits. + */ +static INLINE unsigned +fui( float f ) +{ + union fi fi; + fi.f = f; + return fi.ui; +} + + +/** + * Convert ubyte to float in [0, 1]. + * XXX a 256-entry lookup table would be slightly faster. + */ +static INLINE float +ubyte_to_float(ubyte ub) +{ + return (float) ub * (1.0f / 255.0f); +} + + +/** + * Convert float in [0,1] to ubyte in [0,255] with clamping. + */ +static INLINE ubyte +float_to_ubyte(float f) +{ + const int ieee_0996 = 0x3f7f0000; /* 0.996 or so */ + union fi tmp; + + tmp.f = f; + if (tmp.i < 0) { + return (ubyte) 0; + } + else if (tmp.i >= ieee_0996) { + return (ubyte) 255; + } + else { + tmp.f = tmp.f * (255.0f/256.0f) + 32768.0f; + return (ubyte) tmp.i; + } +} + +static INLINE float +byte_to_float_tex(int8_t b) +{ + return (b == -128) ? -1.0F : b * 1.0F / 127.0F; +} + +static INLINE int8_t +float_to_byte_tex(float f) +{ + return (int8_t) (127.0F * f); +} + +/** + * Calc log base 2 + */ +static INLINE unsigned +util_logbase2(unsigned n) +{ + unsigned log2 = 0; + while (n >>= 1) + ++log2; + return log2; +} + + +/** + * Returns the smallest power of two >= x + */ +static INLINE unsigned +util_next_power_of_two(unsigned x) +{ + unsigned i; + + if (x == 0) + return 1; + + --x; + + for (i = 1; i < sizeof(unsigned) * 8; i <<= 1) + x |= x >> i; + + return x + 1; +} + + +/** + * Return number of bits set in n. + */ +static INLINE unsigned +util_bitcount(unsigned n) +{ +#if defined(PIPE_CC_GCC) + return __builtin_popcount(n); +#else + /* K&R classic bitcount. + * + * For each iteration, clear the LSB from the bitfield. + * Requires only one iteration per set bit, instead of + * one iteration per bit less than highest set bit. + */ + unsigned bits = 0; + for (bits; n; bits++) { + n &= n - 1; + } + return bits; +#endif +} + + +/** + * Reverse byte order of a 32 bit word. + */ +static INLINE uint32_t +util_bswap32(uint32_t n) +{ +#if defined(PIPE_CC_GCC) && (PIPE_CC_GCC_VERSION >= 403) + return __builtin_bswap32(n); +#else + return (n >> 24) | + ((n >> 8) & 0x0000ff00) | + ((n << 8) & 0x00ff0000) | + (n << 24); +#endif +} + + +/** + * Reverse byte order of a 16 bit word. + */ +static INLINE uint16_t +util_bswap16(uint16_t n) +{ + return (n >> 8) | + (n << 8); +} + + +/** + * Clamp X to [MIN, MAX]. + * This is a macro to allow float, int, uint, etc. types. + */ +#define CLAMP( X, MIN, MAX ) ( (X)<(MIN) ? (MIN) : ((X)>(MAX) ? (MAX) : (X)) ) + +#define MIN2( A, B ) ( (A)<(B) ? (A) : (B) ) +#define MAX2( A, B ) ( (A)>(B) ? (A) : (B) ) + +#define MIN3( A, B, C ) ((A) < (B) ? MIN2(A, C) : MIN2(B, C)) +#define MAX3( A, B, C ) ((A) > (B) ? MAX2(A, C) : MAX2(B, C)) + +#define MIN4( A, B, C, D ) ((A) < (B) ? MIN3(A, C, D) : MIN3(B, C, D)) +#define MAX4( A, B, C, D ) ((A) > (B) ? MAX3(A, C, D) : MAX3(B, C, D)) + + +/** + * Align a value, only works pot alignemnts. + */ +static INLINE int +align(int value, int alignment) +{ + return (value + alignment - 1) & ~(alignment - 1); +} + +/** + * Works like align but on npot alignments. + */ +static INLINE size_t +util_align_npot(size_t value, size_t alignment) +{ + if (value % alignment) + return value + (alignment - (value % alignment)); + return value; +} + +static INLINE unsigned +u_minify(unsigned value, unsigned levels) +{ + return MAX2(1, value >> levels); +} + +#ifndef COPY_4V +#define COPY_4V( DST, SRC ) \ +do { \ + (DST)[0] = (SRC)[0]; \ + (DST)[1] = (SRC)[1]; \ + (DST)[2] = (SRC)[2]; \ + (DST)[3] = (SRC)[3]; \ +} while (0) +#endif + + +#ifndef COPY_4FV +#define COPY_4FV( DST, SRC ) COPY_4V(DST, SRC) +#endif + + +#ifndef ASSIGN_4V +#define ASSIGN_4V( DST, V0, V1, V2, V3 ) \ +do { \ + (DST)[0] = (V0); \ + (DST)[1] = (V1); \ + (DST)[2] = (V2); \ + (DST)[3] = (V3); \ +} while (0) +#endif + + +static INLINE uint32_t util_unsigned_fixed(float value, unsigned frac_bits) +{ + return value < 0 ? 0 : (uint32_t)(value * (1<MEMBER)) + + + +#ifdef __cplusplus +} +#endif + + +#endif /* U_MEMORY_H */ diff --git a/mesalib/src/gallium/auxiliary/util/u_mm.c b/mesalib/src/gallium/auxiliary/util/u_mm.c new file mode 100644 index 000000000..874f1f40f --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_mm.c @@ -0,0 +1,296 @@ +/************************************************************************** + * + * Copyright (C) 1999 Wittawat Yamwong + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and 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 + * WITTAWAT YAMWONG, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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_debug.h" + +#include "util/u_memory.h" +#include "util/u_mm.h" + + +void +u_mmDumpMemInfo(const struct mem_block *heap) +{ + debug_printf("Memory heap %p:\n", (void *) heap); + if (heap == 0) { + debug_printf(" heap == 0\n"); + } + else { + const struct mem_block *p; + int total_used = 0, total_free = 0; + + for (p = heap->next; p != heap; p = p->next) { + debug_printf(" Offset:%08x, Size:%08x, %c%c\n", p->ofs, p->size, + p->free ? 'F':'.', + p->reserved ? 'R':'.'); + if (p->free) + total_free += p->size; + else + total_used += p->size; + } + + debug_printf("'\nMemory stats: total = %d, used = %d, free = %d\n", + total_used + total_free, total_used, total_free); + debug_printf("\nFree list:\n"); + + for (p = heap->next_free; p != heap; p = p->next_free) { + debug_printf(" FREE Offset:%08x, Size:%08x, %c%c\n", p->ofs, p->size, + p->free ? 'F':'.', + p->reserved ? 'R':'.'); + } + + } + debug_printf("End of memory blocks\n"); +} + + +struct mem_block * +u_mmInit(int ofs, int size) +{ + struct mem_block *heap, *block; + + if (size <= 0) + return NULL; + + heap = CALLOC_STRUCT(mem_block); + if (!heap) + return NULL; + + block = CALLOC_STRUCT(mem_block); + if (!block) { + FREE(heap); + return NULL; + } + + heap->next = block; + heap->prev = block; + heap->next_free = block; + heap->prev_free = block; + + block->heap = heap; + block->next = heap; + block->prev = heap; + block->next_free = heap; + block->prev_free = heap; + + block->ofs = ofs; + block->size = size; + block->free = 1; + + return heap; +} + + +static struct mem_block * +SliceBlock(struct mem_block *p, + int startofs, int size, + int reserved, int alignment) +{ + struct mem_block *newblock; + + /* break left [p, newblock, p->next], then p = newblock */ + if (startofs > p->ofs) { + newblock = CALLOC_STRUCT(mem_block); + if (!newblock) + return NULL; + newblock->ofs = startofs; + newblock->size = p->size - (startofs - p->ofs); + newblock->free = 1; + newblock->heap = p->heap; + + newblock->next = p->next; + newblock->prev = p; + p->next->prev = newblock; + p->next = newblock; + + newblock->next_free = p->next_free; + newblock->prev_free = p; + p->next_free->prev_free = newblock; + p->next_free = newblock; + + p->size -= newblock->size; + p = newblock; + } + + /* break right, also [p, newblock, p->next] */ + if (size < p->size) { + newblock = CALLOC_STRUCT(mem_block); + if (!newblock) + return NULL; + newblock->ofs = startofs + size; + newblock->size = p->size - size; + newblock->free = 1; + newblock->heap = p->heap; + + newblock->next = p->next; + newblock->prev = p; + p->next->prev = newblock; + p->next = newblock; + + newblock->next_free = p->next_free; + newblock->prev_free = p; + p->next_free->prev_free = newblock; + p->next_free = newblock; + + p->size = size; + } + + /* p = middle block */ + p->free = 0; + + /* Remove p from the free list: + */ + p->next_free->prev_free = p->prev_free; + p->prev_free->next_free = p->next_free; + + p->next_free = 0; + p->prev_free = 0; + + p->reserved = reserved; + return p; +} + + +struct mem_block * +u_mmAllocMem(struct mem_block *heap, int size, int align2, int startSearch) +{ + struct mem_block *p; + const int mask = (1 << align2)-1; + int startofs = 0; + int endofs; + + assert(size >= 0); + assert(align2 >= 0); + assert(align2 <= 12); /* sanity check, 2^12 (4KB) enough? */ + + if (!heap || align2 < 0 || size <= 0) + return NULL; + + for (p = heap->next_free; p != heap; p = p->next_free) { + assert(p->free); + + startofs = (p->ofs + mask) & ~mask; + if ( startofs < startSearch ) { + startofs = startSearch; + } + endofs = startofs+size; + if (endofs <= (p->ofs+p->size)) + break; + } + + if (p == heap) + return NULL; + + assert(p->free); + p = SliceBlock(p,startofs,size,0,mask+1); + + return p; +} + + +struct mem_block * +u_mmFindBlock(struct mem_block *heap, int start) +{ + struct mem_block *p; + + for (p = heap->next; p != heap; p = p->next) { + if (p->ofs == start) + return p; + } + + return NULL; +} + + +static INLINE int +Join2Blocks(struct mem_block *p) +{ + /* XXX there should be some assertions here */ + + /* NOTE: heap->free == 0 */ + + if (p->free && p->next->free) { + struct mem_block *q = p->next; + + assert(p->ofs + p->size == q->ofs); + p->size += q->size; + + p->next = q->next; + q->next->prev = p; + + q->next_free->prev_free = q->prev_free; + q->prev_free->next_free = q->next_free; + + FREE(q); + return 1; + } + return 0; +} + +int +u_mmFreeMem(struct mem_block *b) +{ + if (!b) + return 0; + + if (b->free) { + debug_printf("block already free\n"); + return -1; + } + if (b->reserved) { + debug_printf("block is reserved\n"); + return -1; + } + + b->free = 1; + b->next_free = b->heap->next_free; + b->prev_free = b->heap; + b->next_free->prev_free = b; + b->prev_free->next_free = b; + + Join2Blocks(b); + if (b->prev != b->heap) + Join2Blocks(b->prev); + + return 0; +} + + +void +u_mmDestroy(struct mem_block *heap) +{ + struct mem_block *p; + + if (!heap) + return; + + for (p = heap->next; p != heap; ) { + struct mem_block *next = p->next; + FREE(p); + p = next; + } + + FREE(heap); +} diff --git a/mesalib/src/gallium/auxiliary/util/u_mm.h b/mesalib/src/gallium/auxiliary/util/u_mm.h new file mode 100644 index 000000000..3818181db --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_mm.h @@ -0,0 +1,91 @@ +/************************************************************************** + * + * Copyright (C) 1999 Wittawat Yamwong + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and 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 + * KEITH WHITWELL, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 + * Memory manager code. Primarily used by device drivers to manage texture + * heaps, etc. + */ + + +#ifndef _U_MM_H_ +#define _U_MM_H_ + + +struct mem_block { + struct mem_block *next, *prev; + struct mem_block *next_free, *prev_free; + struct mem_block *heap; + int ofs,size; + unsigned int free:1; + unsigned int reserved:1; +}; + + + +/** + * input: total size in bytes + * return: a heap pointer if OK, NULL if error + */ +extern struct mem_block *u_mmInit(int ofs, int size); + +/** + * Allocate 'size' bytes with 2^align2 bytes alignment, + * restrict the search to free memory after 'startSearch' + * depth and back buffers should be in different 4mb banks + * to get better page hits if possible + * input: size = size of block + * align2 = 2^align2 bytes alignment + * startSearch = linear offset from start of heap to begin search + * return: pointer to the allocated block, 0 if error + */ +extern struct mem_block *u_mmAllocMem(struct mem_block *heap, int size, int align2, + int startSearch); + +/** + * Free block starts at offset + * input: pointer to a block + * return: 0 if OK, -1 if error + */ +extern int u_mmFreeMem(struct mem_block *b); + +/** + * Free block starts at offset + * input: pointer to a heap, start offset + * return: pointer to a block + */ +extern struct mem_block *u_mmFindBlock(struct mem_block *heap, int start); + +/** + * destroy MM + */ +extern void u_mmDestroy(struct mem_block *mmInit); + +/** + * For debugging purposes. + */ +extern void u_mmDumpMemInfo(const struct mem_block *mmInit); + +#endif diff --git a/mesalib/src/gallium/auxiliary/util/u_network.c b/mesalib/src/gallium/auxiliary/util/u_network.c new file mode 100644 index 000000000..d135b590f --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_network.c @@ -0,0 +1,188 @@ + +#include "pipe/p_compiler.h" +#include "util/u_network.h" +#include "util/u_debug.h" + +#if defined(PIPE_SUBSYSTEM_WINDOWS_USER) +# include +# include +#elif defined(PIPE_OS_LINUX) || defined(PIPE_OS_HAIKU) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_CYGWIN) +# include +# include +# include +# include +# include +#else +# warning "No socket implementation" +#endif + +boolean +u_socket_init() +{ +#if defined(PIPE_SUBSYSTEM_WINDOWS_USER) + WORD wVersionRequested; + WSADATA wsaData; + int err; + + /* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */ + wVersionRequested = MAKEWORD(1, 1); + + err = WSAStartup(wVersionRequested, &wsaData); + if (err != 0) { + debug_printf("WSAStartup failed with error: %d\n", err); + return FALSE; + } + return TRUE; +#elif defined(PIPE_HAVE_SOCKETS) + return TRUE; +#else + return FALSE; +#endif +} + +void +u_socket_stop() +{ +#if defined(PIPE_SUBSYSTEM_WINDOWS_USER) + WSACleanup(); +#endif +} + +void +u_socket_close(int s) +{ + if (s < 0) + return; + +#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_HAIKU) || defined(PIPE_OS_APPLE) + shutdown(s, SHUT_RDWR); + close(s); +#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER) + shutdown(s, SD_BOTH); + closesocket(s); +#else + assert(0); +#endif +} + +int u_socket_accept(int s) +{ +#if defined(PIPE_HAVE_SOCKETS) + return accept(s, NULL, NULL); +#else + return -1; +#endif +} + +int +u_socket_send(int s, void *data, size_t size) +{ +#if defined(PIPE_HAVE_SOCKETS) + return send(s, data, size, 0); +#else + return -1; +#endif +} + +int +u_socket_peek(int s, void *data, size_t size) +{ +#if defined(PIPE_HAVE_SOCKETS) + return recv(s, data, size, MSG_PEEK); +#else + return -1; +#endif +} + +int +u_socket_recv(int s, void *data, size_t size) +{ +#if defined(PIPE_HAVE_SOCKETS) + return recv(s, data, size, 0); +#else + return -1; +#endif +} + +int +u_socket_connect(const char *hostname, uint16_t port) +{ +#if defined(PIPE_HAVE_SOCKETS) + int s; + struct sockaddr_in sa; + struct hostent *host = NULL; + + memset(&sa, 0, sizeof(struct sockaddr_in)); + host = gethostbyname(hostname); + if (!host) + return -1; + + memcpy((char *)&sa.sin_addr,host->h_addr_list[0],host->h_length); + sa.sin_family= host->h_addrtype; + sa.sin_port = htons(port); + + s = socket(host->h_addrtype, SOCK_STREAM, IPPROTO_TCP); + if (s < 0) + return -1; + + if (connect(s, (struct sockaddr *)&sa, sizeof(sa))) { + u_socket_close(s); + return -1; + } + + return s; +#else + assert(0); + return -1; +#endif +} + +int +u_socket_listen_on_port(uint16_t portnum) +{ +#if defined(PIPE_HAVE_SOCKETS) + int s; + struct sockaddr_in sa; + memset(&sa, 0, sizeof(struct sockaddr_in)); + + sa.sin_family = AF_INET; + sa.sin_port = htons(portnum); + + s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (s < 0) + return -1; + + if (bind(s, (struct sockaddr *)&sa, sizeof(struct sockaddr_in)) == -1) { + u_socket_close(s); + return -1; + } + + listen(s, 0); + + return s; +#else + assert(0); + return -1; +#endif +} + +void +u_socket_block(int s, boolean block) +{ +#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_HAIKU) || defined(PIPE_OS_APPLE) + int old = fcntl(s, F_GETFL, 0); + if (old == -1) + return; + + /* TODO obey block */ + if (block) + fcntl(s, F_SETFL, old & ~O_NONBLOCK); + else + fcntl(s, F_SETFL, old | O_NONBLOCK); +#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER) + u_long iMode = block ? 0 : 1; + ioctlsocket(s, FIONBIO, &iMode); +#else + assert(0); +#endif +} diff --git a/mesalib/src/gallium/auxiliary/util/u_network.h b/mesalib/src/gallium/auxiliary/util/u_network.h new file mode 100644 index 000000000..5bf18c542 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_network.h @@ -0,0 +1,24 @@ + +#ifndef _U_NETWORK_H_ +#define _U_NETWORK_H_ + +#include "pipe/p_compiler.h" + +#if defined(PIPE_SUBSYSTEM_WINDOWS_USER) +# define PIPE_HAVE_SOCKETS +#elif defined(PIPE_OS_LINUX) || defined(PIPE_OS_HAIKU) || defined(PIPE_OS_APPLE) +# define PIPE_HAVE_SOCKETS +#endif + +boolean u_socket_init(void); +void u_socket_stop(void); +void u_socket_close(int s); +int u_socket_listen_on_port(uint16_t portnum); +int u_socket_accept(int s); +int u_socket_connect(const char *host, uint16_t port); +int u_socket_send(int s, void *data, size_t size); +int u_socket_peek(int s, void *data, size_t size); +int u_socket_recv(int s, void *data, size_t size); +void u_socket_block(int s, boolean block); + +#endif diff --git a/mesalib/src/gallium/auxiliary/util/u_pack_color.h b/mesalib/src/gallium/auxiliary/util/u_pack_color.h new file mode 100644 index 000000000..c51cc7bcb --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_pack_color.h @@ -0,0 +1,584 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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 TUNGSTEN GRAPHICS 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 + * Functions to produce packed colors/Z from floats. + */ + + +#ifndef U_PACK_COLOR_H +#define U_PACK_COLOR_H + + +#include "pipe/p_compiler.h" +#include "pipe/p_format.h" +#include "util/u_debug.h" +#include "util/u_format.h" +#include "util/u_math.h" + + +/** + * Helper union for packing pixel values. + * Will often contain values in formats which are too complex to be described + * in simple terms, hence might just effectively contain a number of bytes. + * Must be big enough to hold data for all formats (currently 256 bits). + */ +union util_color { + ubyte ub; + ushort us; + uint ui; + float f[4]; + double d[4]; +}; + +/** + * Pack ubyte R,G,B,A into dest pixel. + */ +static INLINE void +util_pack_color_ub(ubyte r, ubyte g, ubyte b, ubyte a, + enum pipe_format format, union util_color *uc) +{ + switch (format) { + case PIPE_FORMAT_A8B8G8R8_UNORM: + { + uc->ui = (r << 24) | (g << 16) | (b << 8) | a; + } + return; + case PIPE_FORMAT_X8B8G8R8_UNORM: + { + uc->ui = (r << 24) | (g << 16) | (b << 8) | 0xff; + } + return; + case PIPE_FORMAT_B8G8R8A8_UNORM: + { + uc->ui = (a << 24) | (r << 16) | (g << 8) | b; + } + return; + case PIPE_FORMAT_B8G8R8X8_UNORM: + { + uc->ui = (0xff << 24) | (r << 16) | (g << 8) | b; + } + return; + case PIPE_FORMAT_A8R8G8B8_UNORM: + { + uc->ui = (b << 24) | (g << 16) | (r << 8) | a; + } + return; + case PIPE_FORMAT_X8R8G8B8_UNORM: + { + uc->ui = (b << 24) | (g << 16) | (r << 8) | 0xff; + } + return; + case PIPE_FORMAT_B5G6R5_UNORM: + { + uc->us = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3); + } + return; + case PIPE_FORMAT_B5G5R5X1_UNORM: + { + uc->us = ((0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3); + } + return; + case PIPE_FORMAT_B5G5R5A1_UNORM: + { + uc->us = ((a & 0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3); + } + return; + case PIPE_FORMAT_B4G4R4A4_UNORM: + { + uc->us = ((a & 0xf0) << 8) | ((r & 0xf0) << 4) | ((g & 0xf0) << 0) | (b >> 4); + } + return; + case PIPE_FORMAT_A8_UNORM: + { + uc->ub = a; + } + return; + case PIPE_FORMAT_L8_UNORM: + case PIPE_FORMAT_I8_UNORM: + { + uc->ub = a; + } + return; + case PIPE_FORMAT_R32G32B32A32_FLOAT: + { + uc->f[0] = (float)r / 255.0f; + uc->f[1] = (float)g / 255.0f; + uc->f[2] = (float)b / 255.0f; + uc->f[3] = (float)a / 255.0f; + } + return; + case PIPE_FORMAT_R32G32B32_FLOAT: + { + uc->f[0] = (float)r / 255.0f; + uc->f[1] = (float)g / 255.0f; + uc->f[2] = (float)b / 255.0f; + } + return; + + /* Handle other cases with a generic function. + */ + default: + { + ubyte src[4]; + + src[0] = r; + src[1] = g; + src[2] = b; + src[3] = a; + util_format_write_4ub(format, src, 0, uc, 0, 0, 0, 1, 1); + } + } +} + + +/** + * Unpack RGBA from a packed pixel, returning values as ubytes in [0,255]. + */ +static INLINE void +util_unpack_color_ub(enum pipe_format format, union util_color *uc, + ubyte *r, ubyte *g, ubyte *b, ubyte *a) +{ + switch (format) { + case PIPE_FORMAT_A8B8G8R8_UNORM: + { + uint p = uc->ui; + *r = (ubyte) ((p >> 24) & 0xff); + *g = (ubyte) ((p >> 16) & 0xff); + *b = (ubyte) ((p >> 8) & 0xff); + *a = (ubyte) ((p >> 0) & 0xff); + } + return; + case PIPE_FORMAT_X8B8G8R8_UNORM: + { + uint p = uc->ui; + *r = (ubyte) ((p >> 24) & 0xff); + *g = (ubyte) ((p >> 16) & 0xff); + *b = (ubyte) ((p >> 8) & 0xff); + *a = (ubyte) 0xff; + } + return; + case PIPE_FORMAT_B8G8R8A8_UNORM: + { + uint p = uc->ui; + *r = (ubyte) ((p >> 16) & 0xff); + *g = (ubyte) ((p >> 8) & 0xff); + *b = (ubyte) ((p >> 0) & 0xff); + *a = (ubyte) ((p >> 24) & 0xff); + } + return; + case PIPE_FORMAT_B8G8R8X8_UNORM: + { + uint p = uc->ui; + *r = (ubyte) ((p >> 16) & 0xff); + *g = (ubyte) ((p >> 8) & 0xff); + *b = (ubyte) ((p >> 0) & 0xff); + *a = (ubyte) 0xff; + } + return; + case PIPE_FORMAT_A8R8G8B8_UNORM: + { + uint p = uc->ui; + *r = (ubyte) ((p >> 8) & 0xff); + *g = (ubyte) ((p >> 16) & 0xff); + *b = (ubyte) ((p >> 24) & 0xff); + *a = (ubyte) ((p >> 0) & 0xff); + } + return; + case PIPE_FORMAT_X8R8G8B8_UNORM: + { + uint p = uc->ui; + *r = (ubyte) ((p >> 8) & 0xff); + *g = (ubyte) ((p >> 16) & 0xff); + *b = (ubyte) ((p >> 24) & 0xff); + *a = (ubyte) 0xff; + } + return; + case PIPE_FORMAT_B5G6R5_UNORM: + { + ushort p = uc->us; + *r = (ubyte) (((p >> 8) & 0xf8) | ((p >> 13) & 0x7)); + *g = (ubyte) (((p >> 3) & 0xfc) | ((p >> 9) & 0x3)); + *b = (ubyte) (((p << 3) & 0xf8) | ((p >> 2) & 0x7)); + *a = (ubyte) 0xff; + } + return; + case PIPE_FORMAT_B5G5R5X1_UNORM: + { + ushort p = uc->us; + *r = (ubyte) (((p >> 7) & 0xf8) | ((p >> 12) & 0x7)); + *g = (ubyte) (((p >> 2) & 0xf8) | ((p >> 7) & 0x7)); + *b = (ubyte) (((p << 3) & 0xf8) | ((p >> 2) & 0x7)); + *a = (ubyte) 0xff; + } + return; + case PIPE_FORMAT_B5G5R5A1_UNORM: + { + ushort p = uc->us; + *r = (ubyte) (((p >> 7) & 0xf8) | ((p >> 12) & 0x7)); + *g = (ubyte) (((p >> 2) & 0xf8) | ((p >> 7) & 0x7)); + *b = (ubyte) (((p << 3) & 0xf8) | ((p >> 2) & 0x7)); + *a = (ubyte) (0xff * (p >> 15)); + } + return; + case PIPE_FORMAT_B4G4R4A4_UNORM: + { + ushort p = uc->us; + *r = (ubyte) (((p >> 4) & 0xf0) | ((p >> 8) & 0xf)); + *g = (ubyte) (((p >> 0) & 0xf0) | ((p >> 4) & 0xf)); + *b = (ubyte) (((p << 4) & 0xf0) | ((p >> 0) & 0xf)); + *a = (ubyte) (((p >> 8) & 0xf0) | ((p >> 12) & 0xf)); + } + return; + case PIPE_FORMAT_A8_UNORM: + { + ubyte p = uc->ub; + *r = *g = *b = (ubyte) 0xff; + *a = p; + } + return; + case PIPE_FORMAT_L8_UNORM: + { + ubyte p = uc->ub; + *r = *g = *b = p; + *a = (ubyte) 0xff; + } + return; + case PIPE_FORMAT_I8_UNORM: + { + ubyte p = uc->ub; + *r = *g = *b = *a = p; + } + return; + case PIPE_FORMAT_R32G32B32A32_FLOAT: + { + const float *p = &uc->f[0]; + *r = float_to_ubyte(p[0]); + *g = float_to_ubyte(p[1]); + *b = float_to_ubyte(p[2]); + *a = float_to_ubyte(p[3]); + } + return; + case PIPE_FORMAT_R32G32B32_FLOAT: + { + const float *p = &uc->f[0]; + *r = float_to_ubyte(p[0]); + *g = float_to_ubyte(p[1]); + *b = float_to_ubyte(p[2]); + *a = (ubyte) 0xff; + } + return; + + case PIPE_FORMAT_R32G32_FLOAT: + { + const float *p = &uc->f[0]; + *r = float_to_ubyte(p[0]); + *g = float_to_ubyte(p[1]); + *b = *a = (ubyte) 0xff; + } + return; + + case PIPE_FORMAT_R32_FLOAT: + { + const float *p = &uc->f[0]; + *r = float_to_ubyte(p[0]); + *g = *b = *a = (ubyte) 0xff; + } + return; + + /* Handle other cases with a generic function. + */ + default: + { + ubyte dst[4]; + + util_format_read_4ub(format, dst, 0, uc, 0, 0, 0, 1, 1); + *r = dst[0]; + *g = dst[1]; + *b = dst[2]; + *a = dst[3]; + } + } +} + + +/** + * Note rgba outside [0,1] will be clamped for int pixel formats. + */ +static INLINE void +util_pack_color(const float rgba[4], enum pipe_format format, union util_color *uc) +{ + ubyte r = 0; + ubyte g = 0; + ubyte b = 0; + ubyte a = 0; + + if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 0) <= 8) { + /* format uses 8-bit components or less */ + r = float_to_ubyte(rgba[0]); + g = float_to_ubyte(rgba[1]); + b = float_to_ubyte(rgba[2]); + a = float_to_ubyte(rgba[3]); + } + + switch (format) { + case PIPE_FORMAT_A8B8G8R8_UNORM: + { + uc->ui = (r << 24) | (g << 16) | (b << 8) | a; + } + return; + case PIPE_FORMAT_X8B8G8R8_UNORM: + { + uc->ui = (r << 24) | (g << 16) | (b << 8) | 0xff; + } + return; + case PIPE_FORMAT_B8G8R8A8_UNORM: + { + uc->ui = (a << 24) | (r << 16) | (g << 8) | b; + } + return; + case PIPE_FORMAT_B8G8R8X8_UNORM: + { + uc->ui = (0xff << 24) | (r << 16) | (g << 8) | b; + } + return; + case PIPE_FORMAT_A8R8G8B8_UNORM: + { + uc->ui = (b << 24) | (g << 16) | (r << 8) | a; + } + return; + case PIPE_FORMAT_X8R8G8B8_UNORM: + { + uc->ui = (b << 24) | (g << 16) | (r << 8) | 0xff; + } + return; + case PIPE_FORMAT_B5G6R5_UNORM: + { + uc->us = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3); + } + return; + case PIPE_FORMAT_B5G5R5X1_UNORM: + { + uc->us = ((0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3); + } + return; + case PIPE_FORMAT_B5G5R5A1_UNORM: + { + uc->us = ((a & 0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3); + } + return; + case PIPE_FORMAT_B4G4R4A4_UNORM: + { + uc->us = ((a & 0xf0) << 8) | ((r & 0xf0) << 4) | ((g & 0xf0) << 0) | (b >> 4); + } + return; + case PIPE_FORMAT_A8_UNORM: + { + uc->ub = a; + } + return; + case PIPE_FORMAT_L8_UNORM: + case PIPE_FORMAT_I8_UNORM: + { + uc->ub = r; + } + return; + case PIPE_FORMAT_R32G32B32A32_FLOAT: + { + uc->f[0] = rgba[0]; + uc->f[1] = rgba[1]; + uc->f[2] = rgba[2]; + uc->f[3] = rgba[3]; + } + return; + case PIPE_FORMAT_R32G32B32_FLOAT: + { + uc->f[0] = rgba[0]; + uc->f[1] = rgba[1]; + uc->f[2] = rgba[2]; + } + return; + + /* Handle other cases with a generic function. + */ + default: + util_format_write_4f(format, rgba, 0, uc, 0, 0, 0, 1, 1); + } +} + +/* Integer versions of util_pack_z and util_pack_z_stencil - useful for + * constructing clear masks. + */ +static INLINE uint32_t +util_pack_mask_z(enum pipe_format format, uint32_t z) +{ + switch (format) { + case PIPE_FORMAT_Z16_UNORM: + return z & 0xffff; + case PIPE_FORMAT_Z32_UNORM: + case PIPE_FORMAT_Z32_FLOAT: + return z; + case PIPE_FORMAT_Z24_UNORM_S8_USCALED: + case PIPE_FORMAT_Z24X8_UNORM: + return z & 0xffffff; + case PIPE_FORMAT_S8_USCALED_Z24_UNORM: + case PIPE_FORMAT_X8Z24_UNORM: + return (z & 0xffffff) << 8; + case PIPE_FORMAT_S8_USCALED: + return 0; + default: + debug_print_format("gallium: unhandled format in util_pack_mask_z()", format); + assert(0); + return 0; + } +} + +static INLINE uint32_t +util_pack_mask_z_stencil(enum pipe_format format, uint32_t z, uint8_t s) +{ + uint32_t packed = util_pack_mask_z(format, z); + + switch (format) { + case PIPE_FORMAT_Z24_UNORM_S8_USCALED: + packed |= (uint32_t)s << 24; + break; + case PIPE_FORMAT_S8_USCALED_Z24_UNORM: + packed |= s; + break; + case PIPE_FORMAT_S8_USCALED: + packed |= s; + break; + default: + break; + } + + return packed; +} + + + +/** + * Note: it's assumed that z is in [0,1] + */ +static INLINE uint32_t +util_pack_z(enum pipe_format format, double z) +{ + union fi fui; + + if (z == 0.0) + return 0; + + switch (format) { + case PIPE_FORMAT_Z16_UNORM: + if (z == 1.0) + return 0xffff; + return (uint32_t) (z * 0xffff); + case PIPE_FORMAT_Z32_UNORM: + /* special-case to avoid overflow */ + if (z == 1.0) + return 0xffffffff; + return (uint32_t) (z * 0xffffffff); + case PIPE_FORMAT_Z32_FLOAT: + fui.f = (float)z; + return fui.ui; + case PIPE_FORMAT_Z24_UNORM_S8_USCALED: + case PIPE_FORMAT_Z24X8_UNORM: + if (z == 1.0) + return 0xffffff; + return (uint32_t) (z * 0xffffff); + case PIPE_FORMAT_S8_USCALED_Z24_UNORM: + case PIPE_FORMAT_X8Z24_UNORM: + if (z == 1.0) + return 0xffffff00; + return ((uint32_t) (z * 0xffffff)) << 8; + case PIPE_FORMAT_S8_USCALED: + /* this case can get it via util_pack_z_stencil() */ + return 0; + default: + debug_print_format("gallium: unhandled format in util_pack_z()", format); + assert(0); + return 0; + } +} + + +/** + * Pack Z and/or stencil values into a 32-bit value described by format. + * Note: it's assumed that z is in [0,1] and s in [0,255] + */ +static INLINE uint32_t +util_pack_z_stencil(enum pipe_format format, double z, uint8_t s) +{ + uint32_t packed = util_pack_z(format, z); + + switch (format) { + case PIPE_FORMAT_Z24_UNORM_S8_USCALED: + packed |= (uint32_t)s << 24; + break; + case PIPE_FORMAT_S8_USCALED_Z24_UNORM: + packed |= s; + break; + case PIPE_FORMAT_S8_USCALED: + packed |= s; + break; + default: + break; + } + + return packed; +} + + +/** + * Pack 4 ubytes into a 4-byte word + */ +static INLINE unsigned +pack_ub4(ubyte b0, ubyte b1, ubyte b2, ubyte b3) +{ + return ((((unsigned int)b0) << 0) | + (((unsigned int)b1) << 8) | + (((unsigned int)b2) << 16) | + (((unsigned int)b3) << 24)); +} + + +/** + * Pack/convert 4 floats into one 4-byte word. + */ +static INLINE unsigned +pack_ui32_float4(float a, float b, float c, float d) +{ + return pack_ub4( float_to_ubyte(a), + float_to_ubyte(b), + float_to_ubyte(c), + float_to_ubyte(d) ); +} + + + +#endif /* U_PACK_COLOR_H */ diff --git a/mesalib/src/gallium/auxiliary/util/u_pointer.h b/mesalib/src/gallium/auxiliary/util/u_pointer.h new file mode 100644 index 000000000..f75ce012b --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_pointer.h @@ -0,0 +1,130 @@ +/************************************************************************** + * + * Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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 TUNGSTEN GRAPHICS 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 U_POINTER_H +#define U_POINTER_H + +#include "pipe/p_compiler.h" + +#ifdef __cplusplus +extern "C" { +#endif + +static INLINE intptr_t +pointer_to_intptr( const void *p ) +{ + union { + const void *p; + intptr_t i; + } pi; + pi.p = p; + return pi.i; +} + +static INLINE void * +intptr_to_pointer( intptr_t i ) +{ + union { + void *p; + intptr_t i; + } pi; + pi.i = i; + return pi.p; +} + +static INLINE uintptr_t +pointer_to_uintptr( const void *ptr ) +{ + union { + const void *p; + uintptr_t u; + } pu; + pu.p = ptr; + return pu.u; +} + +static INLINE void * +uintptr_to_pointer( uintptr_t u ) +{ + union { + void *p; + uintptr_t u; + } pu; + pu.u = u; + return pu.p; +} + +/** + * Return a pointer aligned to next multiple of N bytes. + */ +static INLINE void * +align_pointer( const void *unaligned, uintptr_t alignment ) +{ + uintptr_t aligned = (pointer_to_uintptr( unaligned ) + alignment - 1) & ~(alignment - 1); + return uintptr_to_pointer( aligned ); +} + + +/** + * Return a pointer aligned to next multiple of 16 bytes. + */ +static INLINE void * +align16( void *unaligned ) +{ + return align_pointer( unaligned, 16 ); +} + +typedef void (*func_pointer)(void); + +static INLINE func_pointer +pointer_to_func( void *p ) +{ + union { + void *p; + func_pointer f; + } pf; + pf.p = p; + return pf.f; +} + +static INLINE void * +func_to_pointer( func_pointer f ) +{ + union { + void *p; + func_pointer f; + } pf; + pf.f = f; + return pf.p; +} + + +#ifdef __cplusplus +} +#endif + +#endif /* U_POINTER_H */ diff --git a/mesalib/src/gallium/auxiliary/util/u_prim.h b/mesalib/src/gallium/auxiliary/util/u_prim.h new file mode 100644 index 000000000..519820e1b --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_prim.h @@ -0,0 +1,234 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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 TUNGSTEN GRAPHICS 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 U_BLIT_H +#define U_BLIT_H + + +#include "pipe/p_defines.h" +#include "util/u_debug.h" + +#ifdef __cplusplus +extern "C" { +#endif + +static INLINE boolean u_validate_pipe_prim( unsigned pipe_prim, unsigned nr ) +{ + boolean ok = TRUE; + + switch (pipe_prim) { + case PIPE_PRIM_POINTS: + ok = (nr >= 1); + break; + case PIPE_PRIM_LINES: + ok = (nr >= 2); + break; + case PIPE_PRIM_LINE_STRIP: + case PIPE_PRIM_LINE_LOOP: + ok = (nr >= 2); + break; + case PIPE_PRIM_TRIANGLES: + ok = (nr >= 3); + break; + case PIPE_PRIM_TRIANGLE_STRIP: + case PIPE_PRIM_TRIANGLE_FAN: + case PIPE_PRIM_POLYGON: + ok = (nr >= 3); + break; + case PIPE_PRIM_QUADS: + ok = (nr >= 4); + break; + case PIPE_PRIM_QUAD_STRIP: + ok = (nr >= 4); + break; + default: + ok = 0; + break; + } + + return ok; +} + + +static INLINE boolean u_trim_pipe_prim( unsigned pipe_prim, unsigned *nr ) +{ + boolean ok = TRUE; + + switch (pipe_prim) { + case PIPE_PRIM_POINTS: + ok = (*nr >= 1); + break; + case PIPE_PRIM_LINES: + ok = (*nr >= 2); + *nr -= (*nr % 2); + break; + case PIPE_PRIM_LINE_STRIP: + case PIPE_PRIM_LINE_LOOP: + ok = (*nr >= 2); + break; + case PIPE_PRIM_TRIANGLES: + ok = (*nr >= 3); + *nr -= (*nr % 3); + break; + case PIPE_PRIM_TRIANGLE_STRIP: + case PIPE_PRIM_TRIANGLE_FAN: + case PIPE_PRIM_POLYGON: + ok = (*nr >= 3); + break; + case PIPE_PRIM_QUADS: + ok = (*nr >= 4); + *nr -= (*nr % 4); + break; + case PIPE_PRIM_QUAD_STRIP: + ok = (*nr >= 4); + *nr -= (*nr % 2); + break; + case PIPE_PRIM_LINES_ADJACENCY: + ok = (*nr >= 4); + *nr -= (*nr % 4); + break; + case PIPE_PRIM_LINE_STRIP_ADJACENCY: + ok = (*nr >= 4); + break; + case PIPE_PRIM_TRIANGLES_ADJACENCY: + ok = (*nr >= 6); + *nr -= (*nr % 5); + break; + case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY: + ok = (*nr >= 4); + break; + default: + ok = 0; + break; + } + + if (!ok) + *nr = 0; + + return ok; +} + + +static INLINE unsigned u_reduced_prim( unsigned pipe_prim ) +{ + switch (pipe_prim) { + case PIPE_PRIM_POINTS: + return PIPE_PRIM_POINTS; + + case PIPE_PRIM_LINES: + case PIPE_PRIM_LINE_STRIP: + case PIPE_PRIM_LINE_LOOP: + return PIPE_PRIM_LINES; + + default: + return PIPE_PRIM_TRIANGLES; + } +} + +static INLINE unsigned +u_vertices_per_prim(int primitive) +{ + switch(primitive) { + case PIPE_PRIM_POINTS: + return 1; + case PIPE_PRIM_LINES: + case PIPE_PRIM_LINE_LOOP: + case PIPE_PRIM_LINE_STRIP: + return 2; + case PIPE_PRIM_TRIANGLES: + case PIPE_PRIM_TRIANGLE_STRIP: + case PIPE_PRIM_TRIANGLE_FAN: + return 3; + case PIPE_PRIM_LINES_ADJACENCY: + case PIPE_PRIM_LINE_STRIP_ADJACENCY: + return 4; + case PIPE_PRIM_TRIANGLES_ADJACENCY: + case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY: + return 6; + + /* following primitives should never be used + * with geometry shaders abd their size is + * undefined */ + case PIPE_PRIM_POLYGON: + case PIPE_PRIM_QUADS: + case PIPE_PRIM_QUAD_STRIP: + default: + debug_printf("Unrecognized geometry shader primitive"); + return 3; + } +} + +/** + * Returns the number of decomposed primitives for the given + * vertex count. + * Geometry shader is invoked once for each triangle in + * triangle strip, triangle fans and triangles and once + * for each line in line strip, line loop, lines. + */ +static INLINE unsigned +u_gs_prims_for_vertices(int primitive, int vertices) +{ + switch(primitive) { + case PIPE_PRIM_POINTS: + return vertices; + case PIPE_PRIM_LINES: + return vertices / 2; + case PIPE_PRIM_LINE_LOOP: + return vertices; + case PIPE_PRIM_LINE_STRIP: + return vertices - 1; + case PIPE_PRIM_TRIANGLES: + return vertices / 3; + case PIPE_PRIM_TRIANGLE_STRIP: + return vertices - 2; + case PIPE_PRIM_TRIANGLE_FAN: + return vertices - 2; + case PIPE_PRIM_LINES_ADJACENCY: + return vertices / 2; + case PIPE_PRIM_LINE_STRIP_ADJACENCY: + return vertices - 1; + case PIPE_PRIM_TRIANGLES_ADJACENCY: + return vertices / 3; + case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY: + return vertices - 2; + + /* following primitives should never be used + * with geometry shaders abd their size is + * undefined */ + case PIPE_PRIM_POLYGON: + case PIPE_PRIM_QUADS: + case PIPE_PRIM_QUAD_STRIP: + default: + debug_printf("Unrecognized geometry shader primitive"); + return 3; + } +} + +const char *u_prim_name( unsigned pipe_prim ); + +#endif diff --git a/mesalib/src/gallium/auxiliary/util/u_pstipple.c b/mesalib/src/gallium/auxiliary/util/u_pstipple.c new file mode 100644 index 000000000..27f72e967 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_pstipple.c @@ -0,0 +1,434 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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 TUNGSTEN GRAPHICS 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. + * + **************************************************************************/ + +/** + * Polygon stipple helper module. Drivers/GPUs which don't support polygon + * stipple natively can use this module to simulate it. + * + * Basically, modify fragment shader to sample the 32x32 stipple pattern + * texture and do a fragment kill for the 'off' bits. + * + * This was originally a 'draw' module stage, but since we don't need + * vertex window coords or anything, it can be a stand-alone utility module. + * + * Authors: Brian Paul + */ + + +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_shader_tokens.h" +#include "util/u_inlines.h" + +#include "util/u_format.h" +#include "util/u_memory.h" +#include "util/u_pstipple.h" +#include "util/u_sampler.h" + +#include "tgsi/tgsi_transform.h" +#include "tgsi/tgsi_dump.h" + +/** Approx number of new tokens for instructions in pstip_transform_inst() */ +#define NUM_NEW_TOKENS 50 + + +static void +util_pstipple_update_stipple_texture(struct pipe_context *pipe, + struct pipe_resource *tex, + const uint32_t pattern[32]) +{ + static const uint bit31 = 1 << 31; + struct pipe_transfer *transfer; + ubyte *data; + int i, j; + + /* map texture memory */ + transfer = pipe_get_transfer(pipe, tex, 0, 0, + PIPE_TRANSFER_WRITE, 0, 0, 32, 32); + data = pipe->transfer_map(pipe, transfer); + + /* + * Load alpha texture. + * Note: 0 means keep the fragment, 255 means kill it. + * We'll negate the texel value and use KILP which kills if value + * is negative. + */ + for (i = 0; i < 32; i++) { + for (j = 0; j < 32; j++) { + if (pattern[i] & (bit31 >> j)) { + /* fragment "on" */ + data[i * transfer->stride + j] = 0; + } + else { + /* fragment "off" */ + data[i * transfer->stride + j] = 255; + } + } + } + + /* unmap */ + pipe->transfer_unmap(pipe, transfer); + pipe->transfer_destroy(pipe, transfer); +} + + +/** + * Create a 32x32 alpha8 texture that encodes the given stipple pattern. + */ +struct pipe_resource * +util_pstipple_create_stipple_texture(struct pipe_context *pipe, + const uint32_t pattern[32]) +{ + struct pipe_screen *screen = pipe->screen; + struct pipe_resource templat, *tex; + + memset(&templat, 0, sizeof(templat)); + templat.target = PIPE_TEXTURE_2D; + templat.format = PIPE_FORMAT_A8_UNORM; + templat.last_level = 0; + templat.width0 = 32; + templat.height0 = 32; + templat.depth0 = 1; + templat.array_size = 1; + templat.bind = PIPE_BIND_SAMPLER_VIEW; + + tex = screen->resource_create(screen, &templat); + + if (tex) + util_pstipple_update_stipple_texture(pipe, tex, pattern); + + return tex; +} + + +/** + * Create sampler view to sample the stipple texture. + */ +struct pipe_sampler_view * +util_pstipple_create_sampler_view(struct pipe_context *pipe, + struct pipe_resource *tex) +{ + struct pipe_sampler_view templat, *sv; + + u_sampler_view_default_template(&templat, tex, tex->format); + sv = pipe->create_sampler_view(pipe, tex, &templat); + + return sv; +} + + +/** + * Create the sampler CSO that'll be used for stippling. + */ +void * +util_pstipple_create_sampler(struct pipe_context *pipe) +{ + struct pipe_sampler_state templat; + void *s; + + memset(&templat, 0, sizeof(templat)); + templat.wrap_s = PIPE_TEX_WRAP_REPEAT; + templat.wrap_t = PIPE_TEX_WRAP_REPEAT; + templat.wrap_r = PIPE_TEX_WRAP_REPEAT; + templat.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; + templat.min_img_filter = PIPE_TEX_FILTER_NEAREST; + templat.mag_img_filter = PIPE_TEX_FILTER_NEAREST; + templat.normalized_coords = 1; + templat.min_lod = 0.0f; + templat.max_lod = 0.0f; + + s = pipe->create_sampler_state(pipe, &templat); + return s; +} + + + +/** + * Subclass of tgsi_transform_context, used for transforming the + * user's fragment shader to add the extra texture sample and fragment kill + * instructions. + */ +struct pstip_transform_context { + struct tgsi_transform_context base; + uint tempsUsed; /**< bitmask */ + int wincoordInput; + int maxInput; + uint samplersUsed; /**< bitfield of samplers used */ + int freeSampler; /** an available sampler for the pstipple */ + int texTemp; /**< temp registers */ + int numImmed; + boolean firstInstruction; +}; + + +/** + * TGSI declaration transform callback. + * Look for a free sampler, a free input attrib, and two free temp regs. + */ +static void +pstip_transform_decl(struct tgsi_transform_context *ctx, + struct tgsi_full_declaration *decl) +{ + struct pstip_transform_context *pctx = + (struct pstip_transform_context *) ctx; + + if (decl->Declaration.File == TGSI_FILE_SAMPLER) { + uint i; + for (i = decl->Range.First; + i <= decl->Range.Last; i++) { + pctx->samplersUsed |= 1 << i; + } + } + else if (decl->Declaration.File == TGSI_FILE_INPUT) { + pctx->maxInput = MAX2(pctx->maxInput, (int) decl->Range.Last); + if (decl->Semantic.Name == TGSI_SEMANTIC_POSITION) + pctx->wincoordInput = (int) decl->Range.First; + } + else if (decl->Declaration.File == TGSI_FILE_TEMPORARY) { + uint i; + for (i = decl->Range.First; + i <= decl->Range.Last; i++) { + pctx->tempsUsed |= (1 << i); + } + } + + ctx->emit_declaration(ctx, decl); +} + + +static void +pstip_transform_immed(struct tgsi_transform_context *ctx, + struct tgsi_full_immediate *immed) +{ + struct pstip_transform_context *pctx = + (struct pstip_transform_context *) ctx; + pctx->numImmed++; +} + + +/** + * Find the lowest zero bit in the given word, or -1 if bitfield is all ones. + */ +static int +free_bit(uint bitfield) +{ + return ffs(~bitfield) - 1; +} + + +/** + * TGSI instruction transform callback. + * Replace writes to result.color w/ a temp reg. + * Upon END instruction, insert texture sampling code for antialiasing. + */ +static void +pstip_transform_inst(struct tgsi_transform_context *ctx, + struct tgsi_full_instruction *inst) +{ + struct pstip_transform_context *pctx = + (struct pstip_transform_context *) ctx; + + if (pctx->firstInstruction) { + /* emit our new declarations before the first instruction */ + + struct tgsi_full_declaration decl; + struct tgsi_full_instruction newInst; + uint i; + int wincoordInput; + + /* find free sampler */ + pctx->freeSampler = free_bit(pctx->samplersUsed); + if (pctx->freeSampler >= PIPE_MAX_SAMPLERS) + pctx->freeSampler = PIPE_MAX_SAMPLERS - 1; + + if (pctx->wincoordInput < 0) + wincoordInput = pctx->maxInput + 1; + else + wincoordInput = pctx->wincoordInput; + + /* find one free temp reg */ + for (i = 0; i < 32; i++) { + if ((pctx->tempsUsed & (1 << i)) == 0) { + /* found a free temp */ + if (pctx->texTemp < 0) + pctx->texTemp = i; + else + break; + } + } + assert(pctx->texTemp >= 0); + + if (pctx->wincoordInput < 0) { + /* declare new position input reg */ + decl = tgsi_default_full_declaration(); + decl.Declaration.File = TGSI_FILE_INPUT; + decl.Declaration.Interpolate = TGSI_INTERPOLATE_LINEAR; + decl.Declaration.Semantic = 1; + decl.Semantic.Name = TGSI_SEMANTIC_POSITION; + decl.Semantic.Index = 0; + decl.Range.First = + decl.Range.Last = wincoordInput; + ctx->emit_declaration(ctx, &decl); + } + + /* declare new sampler */ + decl = tgsi_default_full_declaration(); + decl.Declaration.File = TGSI_FILE_SAMPLER; + decl.Range.First = + decl.Range.Last = pctx->freeSampler; + ctx->emit_declaration(ctx, &decl); + + /* declare new temp regs */ + decl = tgsi_default_full_declaration(); + decl.Declaration.File = TGSI_FILE_TEMPORARY; + decl.Range.First = + decl.Range.Last = pctx->texTemp; + ctx->emit_declaration(ctx, &decl); + + /* emit immediate = {1/32, 1/32, 1, 1} + * The index/position of this immediate will be pctx->numImmed + */ + { + static const float value[4] = { 1.0/32, 1.0/32, 1.0, 1.0 }; + struct tgsi_full_immediate immed; + uint size = 4; + immed = tgsi_default_full_immediate(); + immed.Immediate.NrTokens = 1 + size; /* one for the token itself */ + immed.u[0].Float = value[0]; + immed.u[1].Float = value[1]; + immed.u[2].Float = value[2]; + immed.u[3].Float = value[3]; + ctx->emit_immediate(ctx, &immed); + } + + pctx->firstInstruction = FALSE; + + + /* + * Insert new MUL/TEX/KILP instructions at start of program + * Take gl_FragCoord, divide by 32 (stipple size), sample the + * texture and kill fragment if needed. + * + * We'd like to use non-normalized texcoords to index into a RECT + * texture, but we can only use REPEAT wrap mode with normalized + * texcoords. Darn. + */ + + /* XXX invert wincoord if origin isn't lower-left... */ + + /* MUL texTemp, INPUT[wincoord], 1/32; */ + newInst = tgsi_default_full_instruction(); + newInst.Instruction.Opcode = TGSI_OPCODE_MUL; + newInst.Instruction.NumDstRegs = 1; + newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; + newInst.Dst[0].Register.Index = pctx->texTemp; + newInst.Instruction.NumSrcRegs = 2; + newInst.Src[0].Register.File = TGSI_FILE_INPUT; + newInst.Src[0].Register.Index = wincoordInput; + newInst.Src[1].Register.File = TGSI_FILE_IMMEDIATE; + newInst.Src[1].Register.Index = pctx->numImmed; + ctx->emit_instruction(ctx, &newInst); + + /* TEX texTemp, texTemp, sampler; */ + newInst = tgsi_default_full_instruction(); + newInst.Instruction.Opcode = TGSI_OPCODE_TEX; + newInst.Instruction.NumDstRegs = 1; + newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; + newInst.Dst[0].Register.Index = pctx->texTemp; + newInst.Instruction.NumSrcRegs = 2; + newInst.Instruction.Texture = TRUE; + newInst.Texture.Texture = TGSI_TEXTURE_2D; + newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY; + newInst.Src[0].Register.Index = pctx->texTemp; + newInst.Src[1].Register.File = TGSI_FILE_SAMPLER; + newInst.Src[1].Register.Index = pctx->freeSampler; + ctx->emit_instruction(ctx, &newInst); + + /* KIL -texTemp; # if -texTemp < 0, KILL fragment */ + newInst = tgsi_default_full_instruction(); + newInst.Instruction.Opcode = TGSI_OPCODE_KIL; + newInst.Instruction.NumDstRegs = 0; + newInst.Instruction.NumSrcRegs = 1; + newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY; + newInst.Src[0].Register.Index = pctx->texTemp; + newInst.Src[0].Register.Negate = 1; + ctx->emit_instruction(ctx, &newInst); + } + + /* emit this instruction */ + ctx->emit_instruction(ctx, inst); +} + + +/** + * Given a fragment shader, return a new fragment shader which + * samples a stipple texture and executes KILL. + */ +struct pipe_shader_state * +util_pstipple_create_fragment_shader(struct pipe_context *pipe, + struct pipe_shader_state *fs, + unsigned *samplerUnitOut) +{ + struct pipe_shader_state *new_fs; + struct pstip_transform_context transform; + const uint newLen = tgsi_num_tokens(fs->tokens) + NUM_NEW_TOKENS; + + new_fs = MALLOC(sizeof(*new_fs)); + if (!new_fs) + return NULL; + + new_fs->tokens = tgsi_alloc_tokens(newLen); + if (!new_fs->tokens) { + FREE(new_fs); + return NULL; + } + + memset(&transform, 0, sizeof(transform)); + transform.wincoordInput = -1; + transform.maxInput = -1; + transform.texTemp = -1; + transform.firstInstruction = TRUE; + transform.base.transform_instruction = pstip_transform_inst; + transform.base.transform_declaration = pstip_transform_decl; + transform.base.transform_immediate = pstip_transform_immed; + + tgsi_transform_shader(fs->tokens, + (struct tgsi_token *) new_fs->tokens, + newLen, &transform.base); + +#if 0 /* DEBUG */ + tgsi_dump(fs->tokens, 0); + tgsi_dump(pstip_fs.tokens, 0); +#endif + + assert(transform.freeSampler < PIPE_MAX_SAMPLERS); + *samplerUnitOut = transform.freeSampler; + + return new_fs; +} + diff --git a/mesalib/src/gallium/auxiliary/util/u_pstipple.h b/mesalib/src/gallium/auxiliary/util/u_pstipple.h new file mode 100644 index 000000000..451e37417 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_pstipple.h @@ -0,0 +1,56 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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 TUNGSTEN GRAPHICS 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 U_PSTIPPLE_H +#define U_PSTIPPLE_H + +#include "pipe/p_compiler.h" + +struct pipe_context; +struct pipe_resource; +struct pipe_shader_state; + + +extern struct pipe_resource * +util_pstipple_create_stipple_texture(struct pipe_context *pipe, + const uint32_t pattern[32]); + +extern struct pipe_sampler_view * +util_pstipple_create_sampler_view(struct pipe_context *pipe, + struct pipe_resource *tex); + +extern void * +util_pstipple_create_sampler(struct pipe_context *pipe); + +extern struct pipe_shader_state * +util_pstipple_create_fragment_shader(struct pipe_context *pipe, + struct pipe_shader_state *fs, + unsigned *samplerUnitOut); + + +#endif diff --git a/mesalib/src/gallium/auxiliary/util/u_rect.c b/mesalib/src/gallium/auxiliary/util/u_rect.c new file mode 100644 index 000000000..b11fff791 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_rect.c @@ -0,0 +1,164 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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 TUNGSTEN GRAPHICS 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. + * + **************************************************************************/ + +/** + * Rectangle-related helper functions. + */ + + +#include "util/u_format.h" +#include "util/u_rect.h" +#include "util/u_pack_color.h" + + +/** + * Copy 2D rect from one place to another. + * Position and sizes are in pixels. + * src_stride may be negative to do vertical flip of pixels from source. + */ +void +util_copy_rect(ubyte * dst, + enum pipe_format format, + unsigned dst_stride, + unsigned dst_x, + unsigned dst_y, + unsigned width, + unsigned height, + const ubyte * src, + int src_stride, + unsigned src_x, + unsigned src_y) +{ + unsigned i; + int src_stride_pos = src_stride < 0 ? -src_stride : src_stride; + int blocksize = util_format_get_blocksize(format); + int blockwidth = util_format_get_blockwidth(format); + int blockheight = util_format_get_blockheight(format); + + assert(blocksize > 0); + assert(blockwidth > 0); + assert(blockheight > 0); + + dst_x /= blockwidth; + dst_y /= blockheight; + width = (width + blockwidth - 1)/blockwidth; + height = (height + blockheight - 1)/blockheight; + src_x /= blockwidth; + src_y /= blockheight; + + dst += dst_x * blocksize; + src += src_x * blocksize; + dst += dst_y * dst_stride; + src += src_y * src_stride_pos; + width *= blocksize; + + if (width == dst_stride && width == src_stride) + memcpy(dst, src, height * width); + else { + for (i = 0; i < height; i++) { + memcpy(dst, src, width); + dst += dst_stride; + src += src_stride; + } + } +} + +void +util_fill_rect(ubyte * dst, + enum pipe_format format, + unsigned dst_stride, + unsigned dst_x, + unsigned dst_y, + unsigned width, + unsigned height, + union util_color *uc) +{ + unsigned i, j; + unsigned width_size; + int blocksize = util_format_get_blocksize(format); + int blockwidth = util_format_get_blockwidth(format); + int blockheight = util_format_get_blockheight(format); + + assert(blocksize > 0); + assert(blockwidth > 0); + assert(blockheight > 0); + + dst_x /= blockwidth; + dst_y /= blockheight; + width = (width + blockwidth - 1)/blockwidth; + height = (height + blockheight - 1)/blockheight; + + dst += dst_x * blocksize; + dst += dst_y * dst_stride; + width_size = width * blocksize; + + switch (blocksize) { + case 1: + if(dst_stride == width_size) + memset(dst, uc->ub, height * width_size); + else { + for (i = 0; i < height; i++) { + memset(dst, uc->ub, width_size); + dst += dst_stride; + } + } + break; + case 2: + for (i = 0; i < height; i++) { + uint16_t *row = (uint16_t *)dst; + for (j = 0; j < width; j++) + *row++ = uc->us; + dst += dst_stride; + } + break; + case 4: + for (i = 0; i < height; i++) { + uint32_t *row = (uint32_t *)dst; + for (j = 0; j < width; j++) + *row++ = uc->ui; + dst += dst_stride; + } + break; + case 8: + case 12: + case 16: + case 24: + case 32: + for (i = 0; i < height; i++) { + ubyte *row = dst; + for (j = 0; j < width; j++) { + memcpy(row, uc, blocksize); + row += blocksize; + } + dst += dst_stride; + } + break; + default: + assert(0); + break; + } +} diff --git a/mesalib/src/gallium/auxiliary/util/u_rect.h b/mesalib/src/gallium/auxiliary/util/u_rect.h new file mode 100644 index 000000000..d16f106bf --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_rect.h @@ -0,0 +1,103 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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 TUNGSTEN GRAPHICS 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 U_RECT_H +#define U_RECT_H + +#include "pipe/p_compiler.h" + +struct u_rect { + int x0, x1; + int y0, y1; +}; + +/* Do two rectangles intersect? + */ +static INLINE boolean +u_rect_test_intersection(const struct u_rect *a, + const struct u_rect *b) +{ + return (!(a->x1 < b->x0 || + b->x1 < a->x0 || + a->y1 < b->y0 || + b->y1 < a->y0)); +} + +/* Find the intersection of two rectangles known to intersect. + */ +static INLINE void +u_rect_find_intersection(const struct u_rect *a, + struct u_rect *b) +{ + /* Caller should verify intersection exists before calling. + */ + if (b->x0 < a->x0) b->x0 = a->x0; + if (b->x1 > a->x1) b->x1 = a->x1; + if (b->y0 < a->y0) b->y0 = a->y0; + if (b->y1 > a->y1) b->y1 = a->y1; +} + + +static INLINE void +u_rect_possible_intersection(const struct u_rect *a, + struct u_rect *b) +{ + if (u_rect_test_intersection(a,b)) { + u_rect_find_intersection(a,b); + } + else { + b->x0 = b->x1 = b->y0 = b->y1 = 0; + } +} + +#include "pipe/p_format.h" +#include "util/u_pack_color.h" + + + +/********************************************************************** + * Pipe copy/fill rect helpers. + */ + +/* These really should move to a different file: + */ +#include "pipe/p_format.h" + +extern void +util_copy_rect(ubyte * dst, enum pipe_format format, + unsigned dst_stride, unsigned dst_x, unsigned dst_y, + unsigned width, unsigned height, const ubyte * src, + int src_stride, unsigned src_x, unsigned src_y); + +extern void +util_fill_rect(ubyte * dst, enum pipe_format format, + unsigned dst_stride, unsigned dst_x, unsigned dst_y, + unsigned width, unsigned height, union util_color *uc); + + +#endif /* U_RECT_H */ diff --git a/mesalib/src/gallium/auxiliary/util/u_resource.c b/mesalib/src/gallium/auxiliary/util/u_resource.c new file mode 100644 index 000000000..7efedef07 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_resource.c @@ -0,0 +1,88 @@ + + +#include "util/u_inlines.h" +#include "util/u_transfer.h" + +static INLINE struct u_resource * +u_resource( struct pipe_resource *res ) +{ + return (struct u_resource *)res; +} + +boolean u_resource_get_handle_vtbl(struct pipe_screen *screen, + struct pipe_resource *resource, + struct winsys_handle *handle) +{ + struct u_resource *ur = u_resource(resource); + return ur->vtbl->resource_get_handle(screen, resource, handle); +} + +void u_resource_destroy_vtbl(struct pipe_screen *screen, + struct pipe_resource *resource) +{ + struct u_resource *ur = u_resource(resource); + ur->vtbl->resource_destroy(screen, resource); +} + +struct pipe_transfer *u_get_transfer_vtbl(struct pipe_context *context, + struct pipe_resource *resource, + unsigned level, + unsigned usage, + const struct pipe_box *box) +{ + struct u_resource *ur = u_resource(resource); + return ur->vtbl->get_transfer(context, resource, level, usage, box); +} + +void u_transfer_destroy_vtbl(struct pipe_context *pipe, + struct pipe_transfer *transfer) +{ + struct u_resource *ur = u_resource(transfer->resource); + ur->vtbl->transfer_destroy(pipe, transfer); +} + +void *u_transfer_map_vtbl( struct pipe_context *pipe, + struct pipe_transfer *transfer ) +{ + struct u_resource *ur = u_resource(transfer->resource); + return ur->vtbl->transfer_map(pipe, transfer); +} + +void u_transfer_flush_region_vtbl( struct pipe_context *pipe, + struct pipe_transfer *transfer, + const struct pipe_box *box) +{ + struct u_resource *ur = u_resource(transfer->resource); + ur->vtbl->transfer_flush_region(pipe, transfer, box); +} + +void u_transfer_unmap_vtbl( struct pipe_context *pipe, + struct pipe_transfer *transfer ) +{ + struct u_resource *ur = u_resource(transfer->resource); + ur->vtbl->transfer_unmap(pipe, transfer); +} + +void u_transfer_inline_write_vtbl( struct pipe_context *pipe, + struct pipe_resource *resource, + unsigned level, + unsigned usage, + const struct pipe_box *box, + const void *data, + unsigned stride, + unsigned layer_stride) +{ + struct u_resource *ur = u_resource(resource); + ur->vtbl->transfer_inline_write(pipe, + resource, + level, + usage, + box, + data, + stride, + layer_stride); +} + + + + diff --git a/mesalib/src/gallium/auxiliary/util/u_ringbuffer.c b/mesalib/src/gallium/auxiliary/util/u_ringbuffer.c new file mode 100644 index 000000000..ad4066aa1 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_ringbuffer.c @@ -0,0 +1,160 @@ + +#include "os/os_thread.h" +#include "pipe/p_defines.h" +#include "util/u_ringbuffer.h" +#include "util/u_math.h" +#include "util/u_memory.h" + +/* Generic ringbuffer: + */ +struct util_ringbuffer +{ + struct util_packet *buf; + unsigned mask; + + /* Can this be done with atomic variables?? + */ + unsigned head; + unsigned tail; + pipe_condvar change; + pipe_mutex mutex; +}; + + +struct util_ringbuffer *util_ringbuffer_create( unsigned dwords ) +{ + struct util_ringbuffer *ring = CALLOC_STRUCT(util_ringbuffer); + if (ring == NULL) + return NULL; + + assert(util_is_power_of_two(dwords)); + + ring->buf = MALLOC( dwords * sizeof(unsigned) ); + if (ring->buf == NULL) + goto fail; + + ring->mask = dwords - 1; + + pipe_condvar_init(ring->change); + pipe_mutex_init(ring->mutex); + return ring; + +fail: + FREE(ring->buf); + FREE(ring); + return NULL; +} + +void util_ringbuffer_destroy( struct util_ringbuffer *ring ) +{ + pipe_condvar_destroy(ring->change); + pipe_mutex_destroy(ring->mutex); + FREE(ring->buf); + FREE(ring); +} + +/** + * Return number of free entries in the ring + */ +static INLINE unsigned util_ringbuffer_space( const struct util_ringbuffer *ring ) +{ + return (ring->tail - (ring->head + 1)) & ring->mask; +} + +/** + * Is the ring buffer empty? + */ +static INLINE boolean util_ringbuffer_empty( const struct util_ringbuffer *ring ) +{ + return util_ringbuffer_space(ring) == ring->mask; +} + +void util_ringbuffer_enqueue( struct util_ringbuffer *ring, + const struct util_packet *packet ) +{ + unsigned i; + + /* XXX: over-reliance on mutexes, etc: + */ + pipe_mutex_lock(ring->mutex); + + /* make sure we don't request an impossible amount of space + */ + assert(packet->dwords <= ring->mask); + + /* Wait for free space: + */ + while (util_ringbuffer_space(ring) < packet->dwords) + pipe_condvar_wait(ring->change, ring->mutex); + + /* Copy data to ring: + */ + for (i = 0; i < packet->dwords; i++) { + + /* Copy all dwords of the packet. Note we're abusing the + * typesystem a little - we're being passed a pointer to + * something, but probably not an array of packet structs: + */ + ring->buf[ring->head] = packet[i]; + ring->head++; + ring->head &= ring->mask; + } + + /* Signal change: + */ + pipe_condvar_signal(ring->change); + pipe_mutex_unlock(ring->mutex); +} + +enum pipe_error util_ringbuffer_dequeue( struct util_ringbuffer *ring, + struct util_packet *packet, + unsigned max_dwords, + boolean wait ) +{ + const struct util_packet *ring_packet; + unsigned i; + int ret = PIPE_OK; + + /* XXX: over-reliance on mutexes, etc: + */ + pipe_mutex_lock(ring->mutex); + + /* Get next ring entry: + */ + if (wait) { + while (util_ringbuffer_empty(ring)) + pipe_condvar_wait(ring->change, ring->mutex); + } + else { + if (util_ringbuffer_empty(ring)) { + ret = PIPE_ERROR_OUT_OF_MEMORY; + goto out; + } + } + + ring_packet = &ring->buf[ring->tail]; + + /* Both of these are considered bugs. Raise an assert on debug builds. + */ + if (ring_packet->dwords > ring->mask + 1 - util_ringbuffer_space(ring) || + ring_packet->dwords > max_dwords) { + assert(0); + ret = PIPE_ERROR_BAD_INPUT; + goto out; + } + + /* Copy data from ring: + */ + for (i = 0; i < ring_packet->dwords; i++) { + packet[i] = ring->buf[ring->tail]; + ring->tail++; + ring->tail &= ring->mask; + } + +out: + /* Signal change: + */ + pipe_condvar_signal(ring->change); + pipe_mutex_unlock(ring->mutex); + return ret; +} diff --git a/mesalib/src/gallium/auxiliary/util/u_ringbuffer.h b/mesalib/src/gallium/auxiliary/util/u_ringbuffer.h new file mode 100644 index 000000000..177199e94 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_ringbuffer.h @@ -0,0 +1,29 @@ + +#ifndef UTIL_RINGBUFFER_H +#define UTIL_RINGBUFFER_H + +#include "pipe/p_compiler.h" +#include "pipe/p_defines.h" /* only for pipe_error! */ + +/* Generic header + */ +struct util_packet { + unsigned dwords:8; + unsigned data24:24; +}; + +struct util_ringbuffer; + +struct util_ringbuffer *util_ringbuffer_create( unsigned dwords ); + +void util_ringbuffer_destroy( struct util_ringbuffer *ring ); + +void util_ringbuffer_enqueue( struct util_ringbuffer *ring, + const struct util_packet *packet ); + +enum pipe_error util_ringbuffer_dequeue( struct util_ringbuffer *ring, + struct util_packet *packet, + unsigned max_dwords, + boolean wait ); + +#endif diff --git a/mesalib/src/gallium/auxiliary/util/u_sampler.c b/mesalib/src/gallium/auxiliary/util/u_sampler.c new file mode 100644 index 000000000..3dcf4fcd0 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_sampler.c @@ -0,0 +1,103 @@ +/************************************************************************** + * + * 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 "u_format.h" +#include "u_sampler.h" + + +static void +default_template(struct pipe_sampler_view *view, + const struct pipe_resource *texture, + enum pipe_format format, + unsigned expand_green_blue) +{ + /* XXX: Check if format is compatible with texture->format. + */ + + view->format = format; + view->u.tex.first_level = 0; + view->u.tex.last_level = texture->last_level; + view->u.tex.first_layer = 0; + view->u.tex.last_layer = texture->target == PIPE_TEXTURE_3D ? + texture->depth0 - 1 : texture->array_size - 1; + view->swizzle_r = PIPE_SWIZZLE_RED; + view->swizzle_g = PIPE_SWIZZLE_GREEN; + view->swizzle_b = PIPE_SWIZZLE_BLUE; + view->swizzle_a = PIPE_SWIZZLE_ALPHA; + + /* Override default green and blue component expansion to the requested + * one. + * + * Gallium expands nonexistent components to (0,0,0,1), DX9 expands + * to (1,1,1,1). Since alpha is always expanded to 1, and red is + * always present, we only really care about green and blue + * components. + * + * To make it look less hackish, one would have to add + * UTIL_FORMAT_SWIZZLE_EXPAND to indicate components for expansion + * and then override without exceptions or favoring one component + * over another. + */ + if (format != PIPE_FORMAT_A8_UNORM) { + const struct util_format_description *desc = util_format_description(format); + + assert(desc); + if (desc) { + if (desc->swizzle[1] == UTIL_FORMAT_SWIZZLE_0) { + view->swizzle_g = expand_green_blue; + } + if (desc->swizzle[2] == UTIL_FORMAT_SWIZZLE_0) { + view->swizzle_b = expand_green_blue; + } + } + } +} + +void +u_sampler_view_default_template(struct pipe_sampler_view *view, + const struct pipe_resource *texture, + enum pipe_format format) +{ + /* Expand to (0, 0, 0, 1) */ + default_template(view, + texture, + format, + PIPE_SWIZZLE_ZERO); +} + +void +u_sampler_view_default_dx9_template(struct pipe_sampler_view *view, + const struct pipe_resource *texture, + enum pipe_format format) +{ + /* Expand to (1, 1, 1, 1) */ + default_template(view, + texture, + format, + PIPE_SWIZZLE_ONE); +} diff --git a/mesalib/src/gallium/auxiliary/util/u_sampler.h b/mesalib/src/gallium/auxiliary/util/u_sampler.h new file mode 100644 index 000000000..c7dc03c2f --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_sampler.h @@ -0,0 +1,57 @@ +/************************************************************************** + * + * 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 U_SAMPLER_H +#define U_SAMPLER_H + + +#include "pipe/p_defines.h" +#include "pipe/p_format.h" +#include "pipe/p_state.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +void +u_sampler_view_default_template(struct pipe_sampler_view *view, + const struct pipe_resource *texture, + enum pipe_format format); + +void +u_sampler_view_default_dx9_template(struct pipe_sampler_view *view, + const struct pipe_resource *texture, + enum pipe_format format); + + +#ifdef __cplusplus +} /* extern "C" { */ +#endif + +#endif /* U_SAMPLER_H */ diff --git a/mesalib/src/gallium/auxiliary/util/u_simple_list.h b/mesalib/src/gallium/auxiliary/util/u_simple_list.h new file mode 100644 index 000000000..e8d12cced --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_simple_list.h @@ -0,0 +1,199 @@ +/** + * \file simple_list.h + * Simple macros for type-safe, intrusive lists. + * + * Intended to work with a list sentinal which is created as an empty + * list. Insert & delete are O(1). + * + * \author + * (C) 1997, Keith Whitwell + */ + +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2001 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 + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef _U_SIMPLE_LIST_H_ +#define _U_SIMPLE_LIST_H_ + +/** + * Remove an element from list. + * + * \param elem element to remove. + */ +#define remove_from_list(elem) \ +do { \ + (elem)->next->prev = (elem)->prev; \ + (elem)->prev->next = (elem)->next; \ + (elem)->next = elem; \ + (elem)->prev = elem; \ +} while (0) + +/** + * Insert an element to the list head. + * + * \param list list. + * \param elem element to insert. + */ +#define insert_at_head(list, elem) \ +do { \ + (elem)->prev = list; \ + (elem)->next = (list)->next; \ + (list)->next->prev = elem; \ + (list)->next = elem; \ +} while(0) + +/** + * Insert an element to the list tail. + * + * \param list list. + * \param elem element to insert. + */ +#define insert_at_tail(list, elem) \ +do { \ + (elem)->next = list; \ + (elem)->prev = (list)->prev; \ + (list)->prev->next = elem; \ + (list)->prev = elem; \ +} while(0) + +/** + * Move an element to the list head. + * + * \param list list. + * \param elem element to move. + */ +#define move_to_head(list, elem) \ +do { \ + remove_from_list(elem); \ + insert_at_head(list, elem); \ +} while (0) + +/** + * Move an element to the list tail. + * + * \param list list. + * \param elem element to move. + */ +#define move_to_tail(list, elem) \ +do { \ + remove_from_list(elem); \ + insert_at_tail(list, elem); \ +} while (0) + +/** + * Make a empty list empty. + * + * \param sentinal list (sentinal element). + */ +#define make_empty_list(sentinal) \ +do { \ + (sentinal)->next = sentinal; \ + (sentinal)->prev = sentinal; \ +} while (0) + +/** + * Get list first element. + * + * \param list list. + * + * \return pointer to first element. + */ +#define first_elem(list) ((list)->next) + +/** + * Get list last element. + * + * \param list list. + * + * \return pointer to last element. + */ +#define last_elem(list) ((list)->prev) + +/** + * Get next element. + * + * \param elem element. + * + * \return pointer to next element. + */ +#define next_elem(elem) ((elem)->next) + +/** + * Get previous element. + * + * \param elem element. + * + * \return pointer to previous element. + */ +#define prev_elem(elem) ((elem)->prev) + +/** + * Test whether element is at end of the list. + * + * \param list list. + * \param elem element. + * + * \return non-zero if element is at end of list, or zero otherwise. + */ +#define at_end(list, elem) ((elem) == (list)) + +/** + * Test if a list is empty. + * + * \param list list. + * + * \return non-zero if list empty, or zero otherwise. + */ +#define is_empty_list(list) ((list)->next == (list)) + +/** + * Walk through the elements of a list. + * + * \param ptr pointer to the current element. + * \param list list. + * + * \note It should be followed by a { } block or a single statement, as in a \c + * for loop. + */ +#define foreach(ptr, list) \ + for( ptr=(list)->next ; ptr!=list ; ptr=(ptr)->next ) + +/** + * Walk through the elements of a list. + * + * Same as #foreach but lets you unlink the current value during a list + * traversal. Useful for freeing a list, element by element. + * + * \param ptr pointer to the current element. + * \param t temporary pointer. + * \param list list. + * + * \note It should be followed by a { } block or a single statement, as in a \c + * for loop. + */ +#define foreach_s(ptr, t, list) \ + for(ptr=(list)->next,t=(ptr)->next; list != ptr; ptr=t, t=(t)->next) + +#endif /* _U_SIMPLE_LIST_H_ */ diff --git a/mesalib/src/gallium/auxiliary/util/u_simple_screen.h b/mesalib/src/gallium/auxiliary/util/u_simple_screen.h new file mode 100644 index 000000000..d81ecee7e --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_simple_screen.h @@ -0,0 +1,180 @@ +/************************************************************************** + * + * 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 TUNGSTEN GRAPHICS 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 U_SIMPLE_SCREEN_H +#define U_SIMPLE_SCREEN_H + +#include "pipe/p_format.h" + +struct pipe_screen; +struct pipe_fence_handle; +struct pipe_surface; +struct pipe_resource; + +/** + * Gallium3D drivers are (meant to be!) independent of both GL and the + * window system. The window system provides a buffer manager and a + * set of additional hooks for things like command buffer submission, + * etc. + * + * There clearly has to be some agreement between the window system + * driver and the hardware driver about the format of command buffers, + * etc. + */ +struct pipe_winsys +{ + void (*destroy)( struct pipe_winsys *ws ); + + /** Returns name of this winsys interface */ + const char *(*get_name)( struct pipe_winsys *ws ); + + /** + * Do any special operations to ensure frontbuffer contents are + * displayed, eg copy fake frontbuffer. + */ + void (*flush_frontbuffer)( struct pipe_winsys *ws, + struct pipe_resource *resource, + unsigned level, unsigned layer, + void *context_private ); + + + /** + * Buffer management. Buffer attributes are mostly fixed over its lifetime. + * + * Remember that gallium gets to choose the interface it needs, and the + * window systems must then implement that interface (rather than the + * other way around...). + * + * usage is a bitmask of PIPE_BIND_*. + * All possible usages must be present. + * + * alignment indicates the client's alignment requirements, eg for + * SSE instructions. + */ + struct pipe_resource *(*buffer_create)( struct pipe_winsys *ws, + unsigned alignment, + unsigned usage, + unsigned size ); + + /** + * Create a buffer that wraps user-space data. + * + * Effectively this schedules a delayed call to buffer_create + * followed by an upload of the data at *some point in the future*, + * or perhaps never. Basically the allocate/upload is delayed + * until the buffer is actually passed to hardware. + * + * The intention is to provide a quick way to turn regular data + * into a buffer, and secondly to avoid a copy operation if that + * data subsequently turns out to be only accessed by the CPU. + * + * Common example is OpenGL vertex buffers that are subsequently + * processed either by software TNL in the driver or by passing to + * hardware. + * + * XXX: What happens if the delayed call to buffer_create() fails? + * + * Note that ptr may be accessed at any time upto the time when the + * buffer is destroyed, so the data must not be freed before then. + */ + struct pipe_resource *(*user_buffer_create)(struct pipe_winsys *ws, + void *ptr, + unsigned bytes); + + /** + * Allocate storage for a display target surface. + * + * 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 + * buffer storage. + */ + struct pipe_resource *(*surface_buffer_create)(struct pipe_winsys *ws, + unsigned width, unsigned height, + enum pipe_format format, + unsigned usage, + unsigned tex_usage, + unsigned *stride); + + + /** + * Map the entire data store of a buffer object into the client's address. + * flags is bitmask of PIPE_BUFFER_USAGE_CPU_READ/WRITE flags. + */ + void *(*buffer_map)( struct pipe_winsys *ws, + struct pipe_resource *buf, + unsigned usage ); + + void (*buffer_unmap)( struct pipe_winsys *ws, + struct pipe_resource *buf ); + + void (*buffer_destroy)( struct pipe_resource *buf ); + + + /** Set ptr = fence, with reference counting */ + void (*fence_reference)( struct pipe_winsys *ws, + struct pipe_fence_handle **ptr, + struct pipe_fence_handle *fence ); + + /** + * Checks whether the fence has been signalled. + * \param flags driver-specific meaning + * \return zero on success. + */ + int (*fence_signalled)( struct pipe_winsys *ws, + struct pipe_fence_handle *fence, + unsigned flag ); + + /** + * Wait for the fence to finish. + * \param flags driver-specific meaning + * \return zero on success. + */ + int (*fence_finish)( struct pipe_winsys *ws, + struct pipe_fence_handle *fence, + unsigned flags, + uint64_t timeout ); + +}; + +/** + * The following function initializes a simple passthrough screen. + * + * All the relevant screen function pointers will forwarded to the + * winsys. + */ +void u_simple_screen_init(struct pipe_screen *screen); + +/** + * Returns the name of the winsys associated with this screen. + */ +const char* u_simple_screen_winsys_name(struct pipe_screen *screen); + +#endif diff --git a/mesalib/src/gallium/auxiliary/util/u_simple_shaders.c b/mesalib/src/gallium/auxiliary/util/u_simple_shaders.c new file mode 100644 index 000000000..141763190 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_simple_shaders.c @@ -0,0 +1,243 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * Copyright 2009 Marek Olšák + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and 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 TUNGSTEN GRAPHICS 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 + * Simple vertex/fragment shader generators. + * + * @author Brian Paul + Marek Olšák + */ + + +#include "pipe/p_context.h" +#include "pipe/p_shader_tokens.h" +#include "pipe/p_state.h" +#include "util/u_simple_shaders.h" +#include "util/u_debug.h" +#include "tgsi/tgsi_ureg.h" + + + +/** + * Make simple vertex pass-through shader. + * \param num_attribs number of attributes to pass through + * \param semantic_names array of semantic names for each attribute + * \param semantic_indexes array of semantic indexes for each attribute + */ +void * +util_make_vertex_passthrough_shader(struct pipe_context *pipe, + uint num_attribs, + const uint *semantic_names, + const uint *semantic_indexes) +{ + struct ureg_program *ureg; + uint i; + + ureg = ureg_create( TGSI_PROCESSOR_VERTEX ); + if (ureg == NULL) + return NULL; + + for (i = 0; i < num_attribs; i++) { + struct ureg_src src; + struct ureg_dst dst; + + src = ureg_DECL_vs_input( ureg, i ); + + dst = ureg_DECL_output( ureg, + semantic_names[i], + semantic_indexes[i]); + + ureg_MOV( ureg, dst, src ); + } + + ureg_END( ureg ); + + return ureg_create_shader_and_destroy( ureg, pipe ); +} + + +/** + * Make simple fragment texture shader: + * IMM {0,0,0,1} // (if writemask != 0xf) + * MOV OUT[0], IMM[0] // (if writemask != 0xf) + * TEX OUT[0].writemask, IN[0], SAMP[0], 2D; + * END; + * + * \param tex_target one of PIPE_TEXTURE_x + * \parma interp_mode either TGSI_INTERPOLATE_LINEAR or PERSPECTIVE + * \param writemask mask of TGSI_WRITEMASK_x + */ +void * +util_make_fragment_tex_shader_writemask(struct pipe_context *pipe, + unsigned tex_target, + unsigned interp_mode, + unsigned writemask ) +{ + struct ureg_program *ureg; + struct ureg_src sampler; + struct ureg_src tex; + struct ureg_dst out; + + assert(interp_mode == TGSI_INTERPOLATE_LINEAR || + interp_mode == TGSI_INTERPOLATE_PERSPECTIVE); + + ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT ); + if (ureg == NULL) + return NULL; + + sampler = ureg_DECL_sampler( ureg, 0 ); + + tex = ureg_DECL_fs_input( ureg, + TGSI_SEMANTIC_GENERIC, 0, + interp_mode ); + + out = ureg_DECL_output( ureg, + TGSI_SEMANTIC_COLOR, + 0 ); + + if (writemask != TGSI_WRITEMASK_XYZW) { + struct ureg_src imm = ureg_imm4f( ureg, 0, 0, 0, 1 ); + + ureg_MOV( ureg, out, imm ); + } + + ureg_TEX( ureg, + ureg_writemask(out, writemask), + tex_target, tex, sampler ); + ureg_END( ureg ); + + return ureg_create_shader_and_destroy( ureg, pipe ); +} + + +/** + * Make a simple fragment shader that sets the output color to a color + * taken from a texture. + * \param tex_target one of PIPE_TEXTURE_x + */ +void * +util_make_fragment_tex_shader(struct pipe_context *pipe, unsigned tex_target, + unsigned interp_mode) +{ + return util_make_fragment_tex_shader_writemask( pipe, + tex_target, + interp_mode, + TGSI_WRITEMASK_XYZW ); +} + + +/** + * Make a simple fragment texture shader which reads an X component from + * a texture and writes it as depth. + */ +void * +util_make_fragment_tex_shader_writedepth(struct pipe_context *pipe, + unsigned tex_target, + unsigned interp_mode) +{ + struct ureg_program *ureg; + struct ureg_src sampler; + struct ureg_src tex; + struct ureg_dst out, depth; + struct ureg_src imm; + + ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT ); + if (ureg == NULL) + return NULL; + + sampler = ureg_DECL_sampler( ureg, 0 ); + + tex = ureg_DECL_fs_input( ureg, + TGSI_SEMANTIC_GENERIC, 0, + interp_mode ); + + out = ureg_DECL_output( ureg, + TGSI_SEMANTIC_COLOR, + 0 ); + + depth = ureg_DECL_output( ureg, + TGSI_SEMANTIC_POSITION, + 0 ); + + imm = ureg_imm4f( ureg, 0, 0, 0, 1 ); + + ureg_MOV( ureg, out, imm ); + + ureg_TEX( ureg, + ureg_writemask(depth, TGSI_WRITEMASK_Z), + tex_target, tex, sampler ); + ureg_END( ureg ); + + return ureg_create_shader_and_destroy( ureg, pipe ); +} + + +/** + * Make simple fragment color pass-through shader. + */ +void * +util_make_fragment_passthrough_shader(struct pipe_context *pipe) +{ + return util_make_fragment_cloneinput_shader(pipe, 1, TGSI_SEMANTIC_COLOR, + TGSI_INTERPOLATE_PERSPECTIVE); +} + + +/** + * Make a fragment shader that copies the input color to N output colors. + */ +void * +util_make_fragment_cloneinput_shader(struct pipe_context *pipe, int num_cbufs, + int input_semantic, + int input_interpolate) +{ + struct ureg_program *ureg; + struct ureg_src src; + struct ureg_dst dst[PIPE_MAX_COLOR_BUFS]; + int i; + + assert(num_cbufs <= PIPE_MAX_COLOR_BUFS); + + ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT ); + if (ureg == NULL) + return NULL; + + src = ureg_DECL_fs_input( ureg, input_semantic, 0, + input_interpolate ); + + for (i = 0; i < num_cbufs; i++) + dst[i] = ureg_DECL_output( ureg, TGSI_SEMANTIC_COLOR, i ); + + for (i = 0; i < num_cbufs; i++) + ureg_MOV( ureg, dst[i], src ); + + ureg_END( ureg ); + + return ureg_create_shader_and_destroy( ureg, pipe ); +} diff --git a/mesalib/src/gallium/auxiliary/util/u_simple_shaders.h b/mesalib/src/gallium/auxiliary/util/u_simple_shaders.h new file mode 100644 index 000000000..9a0fe6375 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_simple_shaders.h @@ -0,0 +1,83 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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 TUNGSTEN GRAPHICS 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 U_SIMPLE_SHADERS_H +#define U_SIMPLE_SHADERS_H + + +#include "pipe/p_compiler.h" + + +struct pipe_context; +struct pipe_shader_state; + + +#ifdef __cplusplus +extern "C" { +#endif + + +extern void * +util_make_vertex_passthrough_shader(struct pipe_context *pipe, + uint num_attribs, + const uint *semantic_names, + const uint *semantic_indexes); + + +extern void * +util_make_fragment_tex_shader_writemask(struct pipe_context *pipe, + unsigned tex_target, + unsigned interp_mode, + unsigned writemask); + +extern void * +util_make_fragment_tex_shader(struct pipe_context *pipe, unsigned tex_target, + unsigned interp_mode); + + +extern void * +util_make_fragment_tex_shader_writedepth(struct pipe_context *pipe, + unsigned tex_target, + unsigned interp_mode); + + +extern void * +util_make_fragment_passthrough_shader(struct pipe_context *pipe); + + +extern void * +util_make_fragment_cloneinput_shader(struct pipe_context *pipe, int num_cbufs, + int input_semantic, + int input_interpolate); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/mesalib/src/gallium/auxiliary/util/u_slab.c b/mesalib/src/gallium/auxiliary/util/u_slab.c new file mode 100644 index 000000000..2c2175fea --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_slab.c @@ -0,0 +1,169 @@ +/* + * Copyright 2010 Marek Olšák + * + * Permission is hereby granted, free of charge, to 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 "util/u_slab.h" + +#include "util/u_math.h" +#include "util/u_memory.h" +#include "util/u_simple_list.h" + +#include + +#define UTIL_SLAB_MAGIC 0xcafe4321 + +/* The block is either allocated memory or free space. */ +struct util_slab_block { + /* The header. */ + /* The first next free block. */ + struct util_slab_block *next_free; + + intptr_t magic; + + /* Memory after the last member is dedicated to the block itself. + * The allocated size is always larger than this structure. */ +}; + +static struct util_slab_block * +util_slab_get_block(struct util_slab_mempool *pool, + struct util_slab_page *page, unsigned index) +{ + return (struct util_slab_block*) + ((uint8_t*)page + sizeof(struct util_slab_page) + + (pool->block_size * index)); +} + +static void util_slab_add_new_page(struct util_slab_mempool *pool) +{ + struct util_slab_page *page; + struct util_slab_block *block; + int i; + + page = MALLOC(pool->page_size); + insert_at_tail(&pool->list, page); + + /* Mark all blocks as free. */ + for (i = 0; i < pool->num_blocks-1; i++) { + block = util_slab_get_block(pool, page, i); + block->next_free = util_slab_get_block(pool, page, i+1); + block->magic = UTIL_SLAB_MAGIC; + } + + block = util_slab_get_block(pool, page, pool->num_blocks-1); + block->next_free = pool->first_free; + block->magic = UTIL_SLAB_MAGIC; + pool->first_free = util_slab_get_block(pool, page, 0); + pool->num_pages++; + +#if 0 + fprintf(stderr, "New page! Num of pages: %i\n", pool->num_pages); +#endif +} + +static void *util_slab_alloc_st(struct util_slab_mempool *pool) +{ + struct util_slab_block *block; + + if (!pool->first_free) + util_slab_add_new_page(pool); + + block = pool->first_free; + assert(block->magic == UTIL_SLAB_MAGIC); + pool->first_free = block->next_free; + + return (uint8_t*)block + sizeof(struct util_slab_block); +} + +static void util_slab_free_st(struct util_slab_mempool *pool, void *ptr) +{ + struct util_slab_block *block = + (struct util_slab_block*) + ((uint8_t*)ptr - sizeof(struct util_slab_block)); + + assert(block->magic == UTIL_SLAB_MAGIC); + block->next_free = pool->first_free; + pool->first_free = block; +} + +static void *util_slab_alloc_mt(struct util_slab_mempool *pool) +{ + void *mem; + + pipe_mutex_lock(pool->mutex); + mem = util_slab_alloc_st(pool); + pipe_mutex_unlock(pool->mutex); + return mem; +} + +static void util_slab_free_mt(struct util_slab_mempool *pool, void *ptr) +{ + pipe_mutex_lock(pool->mutex); + util_slab_free_st(pool, ptr); + pipe_mutex_unlock(pool->mutex); +} + +void util_slab_set_thread_safety(struct util_slab_mempool *pool, + enum util_slab_threading threading) +{ + pool->threading = threading; + + if (threading) { + pool->alloc = util_slab_alloc_mt; + pool->free = util_slab_free_mt; + } else { + pool->alloc = util_slab_alloc_st; + pool->free = util_slab_free_st; + } +} + +void util_slab_create(struct util_slab_mempool *pool, + unsigned item_size, + unsigned num_blocks, + enum util_slab_threading threading) +{ + item_size = align(item_size, sizeof(intptr_t)); + + pool->num_pages = 0; + pool->num_blocks = num_blocks; + pool->block_size = sizeof(struct util_slab_block) + item_size; + pool->block_size = align(pool->block_size, sizeof(intptr_t)); + pool->page_size = sizeof(struct util_slab_page) + + num_blocks * pool->block_size; + pool->first_free = NULL; + + make_empty_list(&pool->list); + + pipe_mutex_init(pool->mutex); + + util_slab_set_thread_safety(pool, threading); +} + +void util_slab_destroy(struct util_slab_mempool *pool) +{ + struct util_slab_page *page, *temp; + + foreach_s(page, temp, &pool->list) { + remove_from_list(page); + FREE(page); + } + + pipe_mutex_destroy(pool->mutex); +} diff --git a/mesalib/src/gallium/auxiliary/util/u_slab.h b/mesalib/src/gallium/auxiliary/util/u_slab.h new file mode 100644 index 000000000..f49dca27d --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_slab.h @@ -0,0 +1,87 @@ +/* + * Copyright 2010 Marek Olšák + * + * Permission is hereby granted, free of charge, to 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. */ + +/** + * @file + * Simple slab allocator for equally sized memory allocations. + * util_slab_alloc and util_slab_free have time complexity in O(1). + * + * Good for allocations which have very low lifetime and are allocated + * and freed very often. Use a profiler first to know if it's worth using it! + * + * Candidates: get_transfer, user_buffer_create + * + * @author Marek Olšák + */ + +#ifndef U_SLAB_H +#define U_SLAB_H + +#include "os/os_thread.h" + +enum util_slab_threading { + UTIL_SLAB_SINGLETHREADED = FALSE, + UTIL_SLAB_MULTITHREADED = TRUE +}; + +/* The page is an array of blocks (allocations). */ +struct util_slab_page { + /* The header (linked-list pointers). */ + struct util_slab_page *prev, *next; + + /* Memory after the last member is dedicated to the page itself. + * The allocated size is always larger than this structure. */ +}; + +struct util_slab_mempool { + /* Public members. */ + void *(*alloc)(struct util_slab_mempool *pool); + void (*free)(struct util_slab_mempool *pool, void *ptr); + + /* Private members. */ + struct util_slab_block *first_free; + + struct util_slab_page list; + + unsigned block_size; + unsigned page_size; + unsigned num_blocks; + unsigned num_pages; + enum util_slab_threading threading; + + pipe_mutex mutex; +}; + +void util_slab_create(struct util_slab_mempool *pool, + unsigned item_size, + unsigned num_blocks, + enum util_slab_threading threading); + +void util_slab_destroy(struct util_slab_mempool *pool); + +void util_slab_set_thread_safety(struct util_slab_mempool *pool, + enum util_slab_threading threading); + +#define util_slab_alloc(pool) (pool)->alloc(pool) +#define util_slab_free(pool, ptr) (pool)->free(pool, ptr) + +#endif diff --git a/mesalib/src/gallium/auxiliary/util/u_snprintf.c b/mesalib/src/gallium/auxiliary/util/u_snprintf.c new file mode 100644 index 000000000..a601df4e5 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_snprintf.c @@ -0,0 +1,1497 @@ +/* + * Copyright (c) 1995 Patrick Powell. + * + * This code is based on code written by Patrick Powell . + * It may be used for any purpose as long as this notice remains intact on all + * source code distributions. + */ + +/* + * Copyright (c) 2008 Holger Weiss. + * + * This version of the code is maintained by Holger Weiss . + * My changes to the code may freely be used, modified and/or redistributed for + * any purpose. It would be nice if additions and fixes to this file (including + * trivial code cleanups) would be sent back in order to let me include them in + * the version available at . + * However, this is not a requirement for using or redistributing (possibly + * modified) versions of this file, nor is leaving this notice intact mandatory. + */ + +/* + * History + * + * 2008-01-20 Holger Weiss for C99-snprintf 1.1: + * + * Fixed the detection of infinite floating point values on IRIX (and + * possibly other systems) and applied another few minor cleanups. + * + * 2008-01-06 Holger Weiss for C99-snprintf 1.0: + * + * Added a lot of new features, fixed many bugs, and incorporated various + * improvements done by Andrew Tridgell , Russ Allbery + * , Hrvoje Niksic , Damien Miller + * , and others for the Samba, INN, Wget, and OpenSSH + * projects. The additions include: support the "e", "E", "g", "G", and + * "F" conversion specifiers (and use conversion style "f" or "F" for the + * still unsupported "a" and "A" specifiers); support the "hh", "ll", "j", + * "t", and "z" length modifiers; support the "#" flag and the (non-C99) + * "'" flag; use localeconv(3) (if available) to get both the current + * locale's decimal point character and the separator between groups of + * digits; fix the handling of various corner cases of field width and + * precision specifications; fix various floating point conversion bugs; + * handle infinite and NaN floating point values; don't attempt to write to + * the output buffer (which may be NULL) if a size of zero was specified; + * check for integer overflow of the field width, precision, and return + * values and during the floating point conversion; use the OUTCHAR() macro + * instead of a function for better performance; provide asprintf(3) and + * vasprintf(3) functions; add new test cases. The replacement functions + * have been renamed to use an "rpl_" prefix, the function calls in the + * main project (and in this file) must be redefined accordingly for each + * replacement function which is needed (by using Autoconf or other means). + * Various other minor improvements have been applied and the coding style + * was cleaned up for consistency. + * + * 2007-07-23 Holger Weiss for Mutt 1.5.13: + * + * C99 compliant snprintf(3) and vsnprintf(3) functions return the number + * of characters that would have been written to a sufficiently sized + * buffer (excluding the '\0'). The original code simply returned the + * length of the resulting output string, so that's been fixed. + * + * 1998-03-05 Michael Elkins for Mutt 0.90.8: + * + * The original code assumed that both snprintf(3) and vsnprintf(3) were + * missing. Some systems only have snprintf(3) but not vsnprintf(3), so + * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF. + * + * 1998-01-27 Thomas Roessler for Mutt 0.89i: + * + * The PGP code was using unsigned hexadecimal formats. Unfortunately, + * unsigned formats simply didn't work. + * + * 1997-10-22 Brandon Long for Mutt 0.87.1: + * + * Ok, added some minimal floating point support, which means this probably + * requires libm on most operating systems. Don't yet support the exponent + * (e,E) and sigfig (g,G). Also, fmtint() was pretty badly broken, it just + * wasn't being exercised in ways which showed it, so that's been fixed. + * Also, formatted the code to Mutt conventions, and removed dead code left + * over from the original. Also, there is now a builtin-test, run with: + * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm && ./snprintf + * + * 2996-09-15 Brandon Long for Mutt 0.43: + * + * This was ugly. It is still ugly. I opted out of floating point + * numbers, but the formatter understands just about everything from the + * normal C string format, at least as far as I can tell from the Solaris + * 2.5 printf(3S) man page. + */ + +/* + * ToDo + * + * - Add wide character support. + * - Add support for "%a" and "%A" conversions. + * - Create test routines which predefine the expected results. Our test cases + * usually expose bugs in system implementations rather than in ours :-) + */ + +/* + * Usage + * + * 1) The following preprocessor macros should be defined to 1 if the feature or + * file in question is available on the target system (by using Autoconf or + * other means), though basic functionality should be available as long as + * HAVE_STDARG_H and HAVE_STDLIB_H are defined correctly: + * + * HAVE_VSNPRINTF + * HAVE_SNPRINTF + * HAVE_VASPRINTF + * HAVE_ASPRINTF + * HAVE_STDARG_H + * HAVE_STDDEF_H + * HAVE_STDINT_H + * HAVE_STDLIB_H + * HAVE_INTTYPES_H + * HAVE_LOCALE_H + * HAVE_LOCALECONV + * HAVE_LCONV_DECIMAL_POINT + * HAVE_LCONV_THOUSANDS_SEP + * HAVE_LONG_DOUBLE + * HAVE_LONG_LONG_INT + * HAVE_UNSIGNED_LONG_LONG_INT + * HAVE_INTMAX_T + * HAVE_UINTMAX_T + * HAVE_UINTPTR_T + * HAVE_PTRDIFF_T + * HAVE_VA_COPY + * HAVE___VA_COPY + * + * 2) The calls to the functions which should be replaced must be redefined + * throughout the project files (by using Autoconf or other means): + * + * #define vsnprintf rpl_vsnprintf + * #define snprintf rpl_snprintf + * #define vasprintf rpl_vasprintf + * #define asprintf rpl_asprintf + * + * 3) The required replacement functions should be declared in some header file + * included throughout the project files: + * + * #if HAVE_CONFIG_H + * #include + * #endif + * #if HAVE_STDARG_H + * #include + * #if !HAVE_VSNPRINTF + * int rpl_vsnprintf(char *, size_t, const char *, va_list); + * #endif + * #if !HAVE_SNPRINTF + * int rpl_snprintf(char *, size_t, const char *, ...); + * #endif + * #if !HAVE_VASPRINTF + * int rpl_vasprintf(char **, const char *, va_list); + * #endif + * #if !HAVE_ASPRINTF + * int rpl_asprintf(char **, const char *, ...); + * #endif + * #endif + * + * Autoconf macros for handling step 1 and step 2 are available at + * . + */ + +#include "pipe/p_config.h" + +#if HAVE_CONFIG_H +#include +#else +#ifdef WIN32 +#define vsnprintf util_vsnprintf +#define snprintf util_snprintf +#define HAVE_VSNPRINTF 0 +#define HAVE_SNPRINTF 0 +#define HAVE_VASPRINTF 1 /* not needed */ +#define HAVE_ASPRINTF 1 /* not needed */ +#define HAVE_STDARG_H 1 +#define HAVE_STDDEF_H 1 +#define HAVE_STDINT_H 0 +#define HAVE_STDLIB_H 1 +#define HAVE_INTTYPES_H 0 +#define HAVE_LOCALE_H 0 +#define HAVE_LOCALECONV 0 +#define HAVE_LCONV_DECIMAL_POINT 0 +#define HAVE_LCONV_THOUSANDS_SEP 0 +#define HAVE_LONG_DOUBLE 0 +#define HAVE_LONG_LONG_INT 1 +#define HAVE_UNSIGNED_LONG_LONG_INT 1 +#define HAVE_INTMAX_T 0 +#define HAVE_UINTMAX_T 0 +#define HAVE_UINTPTR_T 1 +#define HAVE_PTRDIFF_T 1 +#define HAVE_VA_COPY 0 +#define HAVE___VA_COPY 0 +#else +#define HAVE_VSNPRINTF 1 +#define HAVE_SNPRINTF 1 +#define HAVE_VASPRINTF 1 +#define HAVE_ASPRINTF 1 +#endif +#endif /* HAVE_CONFIG_H */ + +#if !HAVE_SNPRINTF || !HAVE_VSNPRINTF || !HAVE_ASPRINTF || !HAVE_VASPRINTF +#include /* For NULL, size_t, vsnprintf(3), and vasprintf(3). */ +#ifdef VA_START +#undef VA_START +#endif /* defined(VA_START) */ +#ifdef VA_SHIFT +#undef VA_SHIFT +#endif /* defined(VA_SHIFT) */ +#if HAVE_STDARG_H +#include +#define VA_START(ap, last) va_start(ap, last) +#define VA_SHIFT(ap, value, type) /* No-op for ANSI C. */ +#else /* Assume is available. */ +#include +#define VA_START(ap, last) va_start(ap) /* "last" is ignored. */ +#define VA_SHIFT(ap, value, type) value = va_arg(ap, type) +#endif /* HAVE_STDARG_H */ + +#if !HAVE_VASPRINTF +#if HAVE_STDLIB_H +#include /* For malloc(3). */ +#endif /* HAVE_STDLIB_H */ +#ifdef VA_COPY +#undef VA_COPY +#endif /* defined(VA_COPY) */ +#ifdef VA_END_COPY +#undef VA_END_COPY +#endif /* defined(VA_END_COPY) */ +#if HAVE_VA_COPY +#define VA_COPY(dest, src) va_copy(dest, src) +#define VA_END_COPY(ap) va_end(ap) +#elif HAVE___VA_COPY +#define VA_COPY(dest, src) __va_copy(dest, src) +#define VA_END_COPY(ap) va_end(ap) +#else +#define VA_COPY(dest, src) (void)mymemcpy(&dest, &src, sizeof(va_list)) +#define VA_END_COPY(ap) /* No-op. */ +#define NEED_MYMEMCPY 1 +static void *mymemcpy(void *, void *, size_t); +#endif /* HAVE_VA_COPY */ +#endif /* !HAVE_VASPRINTF */ + +#if !HAVE_VSNPRINTF +#include /* For *_MAX. */ +#if HAVE_INTTYPES_H +#include /* For intmax_t (if not defined in ). */ +#endif /* HAVE_INTTYPES_H */ +#if HAVE_LOCALE_H +#include /* For localeconv(3). */ +#endif /* HAVE_LOCALE_H */ +#if HAVE_STDDEF_H +#include /* For ptrdiff_t. */ +#endif /* HAVE_STDDEF_H */ +#if HAVE_STDINT_H +#include /* For intmax_t. */ +#endif /* HAVE_STDINT_H */ + +/* Support for unsigned long long int. We may also need ULLONG_MAX. */ +#ifndef ULONG_MAX /* We may need ULONG_MAX as a fallback. */ +#ifdef UINT_MAX +#define ULONG_MAX UINT_MAX +#else +#define ULONG_MAX INT_MAX +#endif /* defined(UINT_MAX) */ +#endif /* !defined(ULONG_MAX) */ +#ifdef ULLONG +#undef ULLONG +#endif /* defined(ULLONG) */ +#if HAVE_UNSIGNED_LONG_LONG_INT +#define ULLONG unsigned long long int +#ifndef ULLONG_MAX +#define ULLONG_MAX ULONG_MAX +#endif /* !defined(ULLONG_MAX) */ +#else +#define ULLONG unsigned long int +#ifdef ULLONG_MAX +#undef ULLONG_MAX +#endif /* defined(ULLONG_MAX) */ +#define ULLONG_MAX ULONG_MAX +#endif /* HAVE_LONG_LONG_INT */ + +/* Support for uintmax_t. We also need UINTMAX_MAX. */ +#ifdef UINTMAX_T +#undef UINTMAX_T +#endif /* defined(UINTMAX_T) */ +#if HAVE_UINTMAX_T || defined(uintmax_t) +#define UINTMAX_T uintmax_t +#ifndef UINTMAX_MAX +#define UINTMAX_MAX ULLONG_MAX +#endif /* !defined(UINTMAX_MAX) */ +#else +#define UINTMAX_T ULLONG +#ifdef UINTMAX_MAX +#undef UINTMAX_MAX +#endif /* defined(UINTMAX_MAX) */ +#define UINTMAX_MAX ULLONG_MAX +#endif /* HAVE_UINTMAX_T || defined(uintmax_t) */ + +/* Support for long double. */ +#ifndef LDOUBLE +#if HAVE_LONG_DOUBLE +#define LDOUBLE long double +#else +#define LDOUBLE double +#endif /* HAVE_LONG_DOUBLE */ +#endif /* !defined(LDOUBLE) */ + +/* Support for long long int. */ +#ifndef LLONG +#if HAVE_LONG_LONG_INT +#define LLONG long long int +#else +#define LLONG long int +#endif /* HAVE_LONG_LONG_INT */ +#endif /* !defined(LLONG) */ + +/* Support for intmax_t. */ +#ifndef INTMAX_T +#if HAVE_INTMAX_T || defined(intmax_t) +#define INTMAX_T intmax_t +#else +#define INTMAX_T LLONG +#endif /* HAVE_INTMAX_T || defined(intmax_t) */ +#endif /* !defined(INTMAX_T) */ + +/* Support for uintptr_t. */ +#ifndef UINTPTR_T +#if HAVE_UINTPTR_T || defined(uintptr_t) +#define UINTPTR_T uintptr_t +#else +#define UINTPTR_T unsigned long int +#endif /* HAVE_UINTPTR_T || defined(uintptr_t) */ +#endif /* !defined(UINTPTR_T) */ + +/* WinCE5.0 does not have uintptr_t defined */ +#if (_WIN32_WCE < 600) +#ifdef UINTPTR_T +#undef UINTPTR_T +#endif +#define UINTPTR_T unsigned long int +#endif + + +/* Support for ptrdiff_t. */ +#ifndef PTRDIFF_T +#if HAVE_PTRDIFF_T || defined(ptrdiff_t) +#define PTRDIFF_T ptrdiff_t +#else +#define PTRDIFF_T long int +#endif /* HAVE_PTRDIFF_T || defined(ptrdiff_t) */ +#endif /* !defined(PTRDIFF_T) */ + +/* + * We need an unsigned integer type corresponding to ptrdiff_t (cf. C99: + * 7.19.6.1, 7). However, we'll simply use PTRDIFF_T and convert it to an + * unsigned type if necessary. This should work just fine in practice. + */ +#ifndef UPTRDIFF_T +#define UPTRDIFF_T PTRDIFF_T +#endif /* !defined(UPTRDIFF_T) */ + +/* + * We need a signed integer type corresponding to size_t (cf. C99: 7.19.6.1, 7). + * However, we'll simply use size_t and convert it to a signed type if + * necessary. This should work just fine in practice. + */ +#ifndef SSIZE_T +#define SSIZE_T size_t +#endif /* !defined(SSIZE_T) */ + +/* Either ERANGE or E2BIG should be available everywhere. */ +#ifndef ERANGE +#define ERANGE E2BIG +#endif /* !defined(ERANGE) */ +#ifndef EOVERFLOW +#define EOVERFLOW ERANGE +#endif /* !defined(EOVERFLOW) */ + +/* + * Buffer size to hold the octal string representation of UINT128_MAX without + * nul-termination ("3777777777777777777777777777777777777777777"). + */ +#ifdef MAX_CONVERT_LENGTH +#undef MAX_CONVERT_LENGTH +#endif /* defined(MAX_CONVERT_LENGTH) */ +#define MAX_CONVERT_LENGTH 43 + +/* Format read states. */ +#define PRINT_S_DEFAULT 0 +#define PRINT_S_FLAGS 1 +#define PRINT_S_WIDTH 2 +#define PRINT_S_DOT 3 +#define PRINT_S_PRECISION 4 +#define PRINT_S_MOD 5 +#define PRINT_S_CONV 6 + +/* Format flags. */ +#define PRINT_F_MINUS (1 << 0) +#define PRINT_F_PLUS (1 << 1) +#define PRINT_F_SPACE (1 << 2) +#define PRINT_F_NUM (1 << 3) +#define PRINT_F_ZERO (1 << 4) +#define PRINT_F_QUOTE (1 << 5) +#define PRINT_F_UP (1 << 6) +#define PRINT_F_UNSIGNED (1 << 7) +#define PRINT_F_TYPE_G (1 << 8) +#define PRINT_F_TYPE_E (1 << 9) + +/* Conversion flags. */ +#define PRINT_C_CHAR 1 +#define PRINT_C_SHORT 2 +#define PRINT_C_LONG 3 +#define PRINT_C_LLONG 4 +#define PRINT_C_LDOUBLE 5 +#define PRINT_C_SIZE 6 +#define PRINT_C_PTRDIFF 7 +#define PRINT_C_INTMAX 8 + +#ifndef MAX +#define MAX(x, y) ((x >= y) ? x : y) +#endif /* !defined(MAX) */ +#ifndef CHARTOINT +#define CHARTOINT(ch) (ch - '0') +#endif /* !defined(CHARTOINT) */ +#ifndef ISDIGIT +#define ISDIGIT(ch) ('0' <= (unsigned char)ch && (unsigned char)ch <= '9') +#endif /* !defined(ISDIGIT) */ +#ifndef ISNAN +#define ISNAN(x) (x != x) +#endif /* !defined(ISNAN) */ +#ifndef ISINF +#define ISINF(x) (x != 0.0 && x + x == x) +#endif /* !defined(ISINF) */ + +#ifdef OUTCHAR +#undef OUTCHAR +#endif /* defined(OUTCHAR) */ +#define OUTCHAR(str, len, size, ch) \ +do { \ + if (len + 1 < size) \ + str[len] = ch; \ + (len)++; \ +} while (/* CONSTCOND */ 0) + +static void fmtstr(char *, size_t *, size_t, const char *, int, int, int); +static void fmtint(char *, size_t *, size_t, INTMAX_T, int, int, int, int); +static void fmtflt(char *, size_t *, size_t, LDOUBLE, int, int, int, int *); +static void printsep(char *, size_t *, size_t); +static int getnumsep(int); +static int getexponent(LDOUBLE); +static int convert(UINTMAX_T, char *, size_t, int, int); +static UINTMAX_T cast(LDOUBLE); +static UINTMAX_T myround(LDOUBLE); +static LDOUBLE mypow10(int); + +int +util_vsnprintf(char *str, size_t size, const char *format, va_list args) +{ + LDOUBLE fvalue; + INTMAX_T value; + unsigned char cvalue; + const char *strvalue; + INTMAX_T *intmaxptr; + PTRDIFF_T *ptrdiffptr; + SSIZE_T *sizeptr; + LLONG *llongptr; + long int *longptr; + int *intptr; + short int *shortptr; + signed char *charptr; + size_t len = 0; + int overflow = 0; + int base = 0; + int cflags = 0; + int flags = 0; + int width = 0; + int precision = -1; + int state = PRINT_S_DEFAULT; + char ch = *format++; + + /* + * C99 says: "If `n' is zero, nothing is written, and `s' may be a null + * pointer." (7.19.6.5, 2) We're forgiving and allow a NULL pointer + * even if a size larger than zero was specified. At least NetBSD's + * snprintf(3) does the same, as well as other versions of this file. + * (Though some of these versions will write to a non-NULL buffer even + * if a size of zero was specified, which violates the standard.) + */ + if (str == NULL && size != 0) + size = 0; + + while (ch != '\0') + switch (state) { + case PRINT_S_DEFAULT: + if (ch == '%') + state = PRINT_S_FLAGS; + else + OUTCHAR(str, len, size, ch); + ch = *format++; + break; + case PRINT_S_FLAGS: + switch (ch) { + case '-': + flags |= PRINT_F_MINUS; + ch = *format++; + break; + case '+': + flags |= PRINT_F_PLUS; + ch = *format++; + break; + case ' ': + flags |= PRINT_F_SPACE; + ch = *format++; + break; + case '#': + flags |= PRINT_F_NUM; + ch = *format++; + break; + case '0': + flags |= PRINT_F_ZERO; + ch = *format++; + break; + case '\'': /* SUSv2 flag (not in C99). */ + flags |= PRINT_F_QUOTE; + ch = *format++; + break; + default: + state = PRINT_S_WIDTH; + break; + } + break; + case PRINT_S_WIDTH: + if (ISDIGIT(ch)) { + ch = CHARTOINT(ch); + if (width > (INT_MAX - ch) / 10) { + overflow = 1; + goto out; + } + width = 10 * width + ch; + ch = *format++; + } else if (ch == '*') { + /* + * C99 says: "A negative field width argument is + * taken as a `-' flag followed by a positive + * field width." (7.19.6.1, 5) + */ + if ((width = va_arg(args, int)) < 0) { + flags |= PRINT_F_MINUS; + width = -width; + } + ch = *format++; + state = PRINT_S_DOT; + } else + state = PRINT_S_DOT; + break; + case PRINT_S_DOT: + if (ch == '.') { + state = PRINT_S_PRECISION; + ch = *format++; + } else + state = PRINT_S_MOD; + break; + case PRINT_S_PRECISION: + if (precision == -1) + precision = 0; + if (ISDIGIT(ch)) { + ch = CHARTOINT(ch); + if (precision > (INT_MAX - ch) / 10) { + overflow = 1; + goto out; + } + precision = 10 * precision + ch; + ch = *format++; + } else if (ch == '*') { + /* + * C99 says: "A negative precision argument is + * taken as if the precision were omitted." + * (7.19.6.1, 5) + */ + if ((precision = va_arg(args, int)) < 0) + precision = -1; + ch = *format++; + state = PRINT_S_MOD; + } else + state = PRINT_S_MOD; + break; + case PRINT_S_MOD: + switch (ch) { + case 'h': + ch = *format++; + if (ch == 'h') { /* It's a char. */ + ch = *format++; + cflags = PRINT_C_CHAR; + } else + cflags = PRINT_C_SHORT; + break; + case 'l': + ch = *format++; + if (ch == 'l') { /* It's a long long. */ + ch = *format++; + cflags = PRINT_C_LLONG; + } else + cflags = PRINT_C_LONG; + break; + case 'L': + cflags = PRINT_C_LDOUBLE; + ch = *format++; + break; + case 'j': + cflags = PRINT_C_INTMAX; + ch = *format++; + break; + case 't': + cflags = PRINT_C_PTRDIFF; + ch = *format++; + break; + case 'z': + cflags = PRINT_C_SIZE; + ch = *format++; + break; + } + state = PRINT_S_CONV; + break; + case PRINT_S_CONV: + switch (ch) { + case 'd': + /* FALLTHROUGH */ + case 'i': + switch (cflags) { + case PRINT_C_CHAR: + value = (signed char)va_arg(args, int); + break; + case PRINT_C_SHORT: + value = (short int)va_arg(args, int); + break; + case PRINT_C_LONG: + value = va_arg(args, long int); + break; + case PRINT_C_LLONG: + value = va_arg(args, LLONG); + break; + case PRINT_C_SIZE: + value = va_arg(args, SSIZE_T); + break; + case PRINT_C_INTMAX: + value = va_arg(args, INTMAX_T); + break; + case PRINT_C_PTRDIFF: + value = va_arg(args, PTRDIFF_T); + break; + default: + value = va_arg(args, int); + break; + } + fmtint(str, &len, size, value, 10, width, + precision, flags); + break; + case 'X': + flags |= PRINT_F_UP; + /* FALLTHROUGH */ + case 'x': + base = 16; + /* FALLTHROUGH */ + case 'o': + if (base == 0) + base = 8; + /* FALLTHROUGH */ + case 'u': + if (base == 0) + base = 10; + flags |= PRINT_F_UNSIGNED; + switch (cflags) { + case PRINT_C_CHAR: + value = (unsigned char)va_arg(args, + unsigned int); + break; + case PRINT_C_SHORT: + value = (unsigned short int)va_arg(args, + unsigned int); + break; + case PRINT_C_LONG: + value = va_arg(args, unsigned long int); + break; + case PRINT_C_LLONG: + value = va_arg(args, ULLONG); + break; + case PRINT_C_SIZE: + value = va_arg(args, size_t); + break; + case PRINT_C_INTMAX: + value = va_arg(args, UINTMAX_T); + break; + case PRINT_C_PTRDIFF: + value = va_arg(args, UPTRDIFF_T); + break; + default: + value = va_arg(args, unsigned int); + break; + } + fmtint(str, &len, size, value, base, width, + precision, flags); + break; + case 'A': + /* Not yet supported, we'll use "%F". */ + /* FALLTHROUGH */ + case 'F': + flags |= PRINT_F_UP; + case 'a': + /* Not yet supported, we'll use "%f". */ + /* FALLTHROUGH */ + case 'f': + if (cflags == PRINT_C_LDOUBLE) + fvalue = va_arg(args, LDOUBLE); + else + fvalue = va_arg(args, double); + fmtflt(str, &len, size, fvalue, width, + precision, flags, &overflow); + if (overflow) + goto out; + break; + case 'E': + flags |= PRINT_F_UP; + /* FALLTHROUGH */ + case 'e': + flags |= PRINT_F_TYPE_E; + if (cflags == PRINT_C_LDOUBLE) + fvalue = va_arg(args, LDOUBLE); + else + fvalue = va_arg(args, double); + fmtflt(str, &len, size, fvalue, width, + precision, flags, &overflow); + if (overflow) + goto out; + break; + case 'G': + flags |= PRINT_F_UP; + /* FALLTHROUGH */ + case 'g': + flags |= PRINT_F_TYPE_G; + if (cflags == PRINT_C_LDOUBLE) + fvalue = va_arg(args, LDOUBLE); + else + fvalue = va_arg(args, double); + /* + * If the precision is zero, it is treated as + * one (cf. C99: 7.19.6.1, 8). + */ + if (precision == 0) + precision = 1; + fmtflt(str, &len, size, fvalue, width, + precision, flags, &overflow); + if (overflow) + goto out; + break; + case 'c': + cvalue = (unsigned char)va_arg(args, int); + OUTCHAR(str, len, size, cvalue); + break; + case 's': + strvalue = va_arg(args, char *); + fmtstr(str, &len, size, strvalue, width, + precision, flags); + break; + case 'p': + /* + * C99 says: "The value of the pointer is + * converted to a sequence of printing + * characters, in an implementation-defined + * manner." (C99: 7.19.6.1, 8) + */ + if ((strvalue = va_arg(args, void *)) == NULL) + /* + * We use the glibc format. BSD prints + * "0x0", SysV "0". + */ + fmtstr(str, &len, size, "(nil)", width, + -1, flags); + else { + /* + * We use the BSD/glibc format. SysV + * omits the "0x" prefix (which we emit + * using the PRINT_F_NUM flag). + */ + flags |= PRINT_F_NUM; + flags |= PRINT_F_UNSIGNED; + fmtint(str, &len, size, + (UINTPTR_T)strvalue, 16, width, + precision, flags); + } + break; + case 'n': + switch (cflags) { + case PRINT_C_CHAR: + charptr = va_arg(args, signed char *); + *charptr = (signed char)len; + break; + case PRINT_C_SHORT: + shortptr = va_arg(args, short int *); + *shortptr = (short int)len; + break; + case PRINT_C_LONG: + longptr = va_arg(args, long int *); + *longptr = (long int)len; + break; + case PRINT_C_LLONG: + llongptr = va_arg(args, LLONG *); + *llongptr = (LLONG)len; + break; + case PRINT_C_SIZE: + /* + * C99 says that with the "z" length + * modifier, "a following `n' conversion + * specifier applies to a pointer to a + * signed integer type corresponding to + * size_t argument." (7.19.6.1, 7) + */ + sizeptr = va_arg(args, SSIZE_T *); + *sizeptr = len; + break; + case PRINT_C_INTMAX: + intmaxptr = va_arg(args, INTMAX_T *); + *intmaxptr = len; + break; + case PRINT_C_PTRDIFF: + ptrdiffptr = va_arg(args, PTRDIFF_T *); + *ptrdiffptr = len; + break; + default: + intptr = va_arg(args, int *); + *intptr = (int)len; + break; + } + break; + case '%': /* Print a "%" character verbatim. */ + OUTCHAR(str, len, size, ch); + break; + default: /* Skip other characters. */ + break; + } + ch = *format++; + state = PRINT_S_DEFAULT; + base = cflags = flags = width = 0; + precision = -1; + break; + } +out: + if (len < size) + str[len] = '\0'; + else if (size > 0) + str[size - 1] = '\0'; + + if (overflow || len >= INT_MAX) { + return -1; + } + return (int)len; +} + +static void +fmtstr(char *str, size_t *len, size_t size, const char *value, int width, + int precision, int flags) +{ + int padlen, strln; /* Amount to pad. */ + int noprecision = (precision == -1); + + if (value == NULL) /* We're forgiving. */ + value = "(null)"; + + /* If a precision was specified, don't read the string past it. */ + for (strln = 0; value[strln] != '\0' && + (noprecision || strln < precision); strln++) + continue; + + if ((padlen = width - strln) < 0) + padlen = 0; + if (flags & PRINT_F_MINUS) /* Left justify. */ + padlen = -padlen; + + while (padlen > 0) { /* Leading spaces. */ + OUTCHAR(str, *len, size, ' '); + padlen--; + } + while (*value != '\0' && (noprecision || precision-- > 0)) { + OUTCHAR(str, *len, size, *value); + value++; + } + while (padlen < 0) { /* Trailing spaces. */ + OUTCHAR(str, *len, size, ' '); + padlen++; + } +} + +static void +fmtint(char *str, size_t *len, size_t size, INTMAX_T value, int base, int width, + int precision, int flags) +{ + UINTMAX_T uvalue; + char iconvert[MAX_CONVERT_LENGTH]; + char sign = 0; + char hexprefix = 0; + int spadlen = 0; /* Amount to space pad. */ + int zpadlen = 0; /* Amount to zero pad. */ + int pos; + int separators = (flags & PRINT_F_QUOTE); + int noprecision = (precision == -1); + + if (flags & PRINT_F_UNSIGNED) + uvalue = value; + else { + uvalue = (value >= 0) ? value : -value; + if (value < 0) + sign = '-'; + else if (flags & PRINT_F_PLUS) /* Do a sign. */ + sign = '+'; + else if (flags & PRINT_F_SPACE) + sign = ' '; + } + + pos = convert(uvalue, iconvert, sizeof(iconvert), base, + flags & PRINT_F_UP); + + if (flags & PRINT_F_NUM && uvalue != 0) { + /* + * C99 says: "The result is converted to an `alternative form'. + * For `o' conversion, it increases the precision, if and only + * if necessary, to force the first digit of the result to be a + * zero (if the value and precision are both 0, a single 0 is + * printed). For `x' (or `X') conversion, a nonzero result has + * `0x' (or `0X') prefixed to it." (7.19.6.1, 6) + */ + switch (base) { + case 8: + if (precision <= pos) + precision = pos + 1; + break; + case 16: + hexprefix = (flags & PRINT_F_UP) ? 'X' : 'x'; + break; + } + } + + if (separators) /* Get the number of group separators we'll print. */ + separators = getnumsep(pos); + + zpadlen = precision - pos - separators; + spadlen = width /* Minimum field width. */ + - separators /* Number of separators. */ + - MAX(precision, pos) /* Number of integer digits. */ + - ((sign != 0) ? 1 : 0) /* Will we print a sign? */ + - ((hexprefix != 0) ? 2 : 0); /* Will we print a prefix? */ + + if (zpadlen < 0) + zpadlen = 0; + if (spadlen < 0) + spadlen = 0; + + /* + * C99 says: "If the `0' and `-' flags both appear, the `0' flag is + * ignored. For `d', `i', `o', `u', `x', and `X' conversions, if a + * precision is specified, the `0' flag is ignored." (7.19.6.1, 6) + */ + if (flags & PRINT_F_MINUS) /* Left justify. */ + spadlen = -spadlen; + else if (flags & PRINT_F_ZERO && noprecision) { + zpadlen += spadlen; + spadlen = 0; + } + while (spadlen > 0) { /* Leading spaces. */ + OUTCHAR(str, *len, size, ' '); + spadlen--; + } + if (sign != 0) /* Sign. */ + OUTCHAR(str, *len, size, sign); + if (hexprefix != 0) { /* A "0x" or "0X" prefix. */ + OUTCHAR(str, *len, size, '0'); + OUTCHAR(str, *len, size, hexprefix); + } + while (zpadlen > 0) { /* Leading zeros. */ + OUTCHAR(str, *len, size, '0'); + zpadlen--; + } + while (pos > 0) { /* The actual digits. */ + pos--; + OUTCHAR(str, *len, size, iconvert[pos]); + if (separators > 0 && pos > 0 && pos % 3 == 0) + printsep(str, len, size); + } + while (spadlen < 0) { /* Trailing spaces. */ + OUTCHAR(str, *len, size, ' '); + spadlen++; + } +} + +static void +fmtflt(char *str, size_t *len, size_t size, LDOUBLE fvalue, int width, + int precision, int flags, int *overflow) +{ + LDOUBLE ufvalue; + UINTMAX_T intpart; + UINTMAX_T fracpart; + UINTMAX_T mask; + const char *infnan = NULL; + char iconvert[MAX_CONVERT_LENGTH]; + char fconvert[MAX_CONVERT_LENGTH]; + char econvert[4]; /* "e-12" (without nul-termination). */ + char esign = 0; + char sign = 0; + int leadfraczeros = 0; + int exponent = 0; + int emitpoint = 0; + int omitzeros = 0; + int omitcount = 0; + int padlen = 0; + int epos = 0; + int fpos = 0; + int ipos = 0; + int separators = (flags & PRINT_F_QUOTE); + int estyle = (flags & PRINT_F_TYPE_E); +#if HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT + struct lconv *lc = localeconv(); +#endif /* HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT */ + + /* + * AIX' man page says the default is 0, but C99 and at least Solaris' + * and NetBSD's man pages say the default is 6, and sprintf(3) on AIX + * defaults to 6. + */ + if (precision == -1) + precision = 6; + + if (fvalue < 0.0) + sign = '-'; + else if (flags & PRINT_F_PLUS) /* Do a sign. */ + sign = '+'; + else if (flags & PRINT_F_SPACE) + sign = ' '; + + if (ISNAN(fvalue)) + infnan = (flags & PRINT_F_UP) ? "NAN" : "nan"; + else if (ISINF(fvalue)) + infnan = (flags & PRINT_F_UP) ? "INF" : "inf"; + + if (infnan != NULL) { + if (sign != 0) + iconvert[ipos++] = sign; + while (*infnan != '\0') + iconvert[ipos++] = *infnan++; + fmtstr(str, len, size, iconvert, width, ipos, flags); + return; + } + + /* "%e" (or "%E") or "%g" (or "%G") conversion. */ + if (flags & PRINT_F_TYPE_E || flags & PRINT_F_TYPE_G) { + if (flags & PRINT_F_TYPE_G) { + /* + * For "%g" (and "%G") conversions, the precision + * specifies the number of significant digits, which + * includes the digits in the integer part. The + * conversion will or will not be using "e-style" (like + * "%e" or "%E" conversions) depending on the precision + * and on the exponent. However, the exponent can be + * affected by rounding the converted value, so we'll + * leave this decision for later. Until then, we'll + * assume that we're going to do an "e-style" conversion + * (in order to get the exponent calculated). For + * "e-style", the precision must be decremented by one. + */ + precision--; + /* + * For "%g" (and "%G") conversions, trailing zeros are + * removed from the fractional portion of the result + * unless the "#" flag was specified. + */ + if (!(flags & PRINT_F_NUM)) + omitzeros = 1; + } + exponent = getexponent(fvalue); + estyle = 1; + } + +again: + /* + * Sorry, we only support 9, 19, or 38 digits (that is, the number of + * digits of the 32-bit, the 64-bit, or the 128-bit UINTMAX_MAX value + * minus one) past the decimal point due to our conversion method. + */ + switch (sizeof(UINTMAX_T)) { + case 16: + if (precision > 38) + precision = 38; + break; + case 8: + if (precision > 19) + precision = 19; + break; + default: + if (precision > 9) + precision = 9; + break; + } + + ufvalue = (fvalue >= 0.0) ? fvalue : -fvalue; + if (estyle) /* We want exactly one integer digit. */ + ufvalue /= mypow10(exponent); + + if ((intpart = cast(ufvalue)) == UINTMAX_MAX) { + *overflow = 1; + return; + } + + /* + * Factor of ten with the number of digits needed for the fractional + * part. For example, if the precision is 3, the mask will be 1000. + */ +#if defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT) + mask = (unsigned long)mypow10(precision); +#else + mask = (UINTMAX_T)mypow10(precision); +#endif + /* + * We "cheat" by converting the fractional part to integer by + * multiplying by a factor of ten. + */ + if ((fracpart = myround(mask * (ufvalue - intpart))) >= mask) { + /* + * For example, ufvalue = 2.99962, intpart = 2, and mask = 1000 + * (because precision = 3). Now, myround(1000 * 0.99962) will + * return 1000. So, the integer part must be incremented by one + * and the fractional part must be set to zero. + */ + intpart++; + fracpart = 0; + if (estyle && intpart == 10) { + /* + * The value was rounded up to ten, but we only want one + * integer digit if using "e-style". So, the integer + * part must be set to one and the exponent must be + * incremented by one. + */ + intpart = 1; + exponent++; + } + } + + /* + * Now that we know the real exponent, we can check whether or not to + * use "e-style" for "%g" (and "%G") conversions. If we don't need + * "e-style", the precision must be adjusted and the integer and + * fractional parts must be recalculated from the original value. + * + * C99 says: "Let P equal the precision if nonzero, 6 if the precision + * is omitted, or 1 if the precision is zero. Then, if a conversion + * with style `E' would have an exponent of X: + * + * - if P > X >= -4, the conversion is with style `f' (or `F') and + * precision P - (X + 1). + * + * - otherwise, the conversion is with style `e' (or `E') and precision + * P - 1." (7.19.6.1, 8) + * + * Note that we had decremented the precision by one. + */ + if (flags & PRINT_F_TYPE_G && estyle && + precision + 1 > exponent && exponent >= -4) { + precision -= exponent; + estyle = 0; + goto again; + } + + if (estyle) { + if (exponent < 0) { + exponent = -exponent; + esign = '-'; + } else + esign = '+'; + + /* + * Convert the exponent. The sizeof(econvert) is 4. So, the + * econvert buffer can hold e.g. "e+99" and "e-99". We don't + * support an exponent which contains more than two digits. + * Therefore, the following stores are safe. + */ + epos = convert(exponent, econvert, 2, 10, 0); + /* + * C99 says: "The exponent always contains at least two digits, + * and only as many more digits as necessary to represent the + * exponent." (7.19.6.1, 8) + */ + if (epos == 1) + econvert[epos++] = '0'; + econvert[epos++] = esign; + econvert[epos++] = (flags & PRINT_F_UP) ? 'E' : 'e'; + } + + /* Convert the integer part and the fractional part. */ + ipos = convert(intpart, iconvert, sizeof(iconvert), 10, 0); + if (fracpart != 0) /* convert() would return 1 if fracpart == 0. */ + fpos = convert(fracpart, fconvert, sizeof(fconvert), 10, 0); + + leadfraczeros = precision - fpos; + + if (omitzeros) { + if (fpos > 0) /* Omit trailing fractional part zeros. */ + while (omitcount < fpos && fconvert[omitcount] == '0') + omitcount++; + else { /* The fractional part is zero, omit it completely. */ + omitcount = precision; + leadfraczeros = 0; + } + precision -= omitcount; + } + + /* + * Print a decimal point if either the fractional part is non-zero + * and/or the "#" flag was specified. + */ + if (precision > 0 || flags & PRINT_F_NUM) + emitpoint = 1; + if (separators) /* Get the number of group separators we'll print. */ + separators = getnumsep(ipos); + + padlen = width /* Minimum field width. */ + - ipos /* Number of integer digits. */ + - epos /* Number of exponent characters. */ + - precision /* Number of fractional digits. */ + - separators /* Number of group separators. */ + - (emitpoint ? 1 : 0) /* Will we print a decimal point? */ + - ((sign != 0) ? 1 : 0); /* Will we print a sign character? */ + + if (padlen < 0) + padlen = 0; + + /* + * C99 says: "If the `0' and `-' flags both appear, the `0' flag is + * ignored." (7.19.6.1, 6) + */ + if (flags & PRINT_F_MINUS) /* Left justifty. */ + padlen = -padlen; + else if (flags & PRINT_F_ZERO && padlen > 0) { + if (sign != 0) { /* Sign. */ + OUTCHAR(str, *len, size, sign); + sign = 0; + } + while (padlen > 0) { /* Leading zeros. */ + OUTCHAR(str, *len, size, '0'); + padlen--; + } + } + while (padlen > 0) { /* Leading spaces. */ + OUTCHAR(str, *len, size, ' '); + padlen--; + } + if (sign != 0) /* Sign. */ + OUTCHAR(str, *len, size, sign); + while (ipos > 0) { /* Integer part. */ + ipos--; + OUTCHAR(str, *len, size, iconvert[ipos]); + if (separators > 0 && ipos > 0 && ipos % 3 == 0) + printsep(str, len, size); + } + if (emitpoint) { /* Decimal point. */ +#if HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT + if (lc->decimal_point != NULL && *lc->decimal_point != '\0') + OUTCHAR(str, *len, size, *lc->decimal_point); + else /* We'll always print some decimal point character. */ +#endif /* HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT */ + OUTCHAR(str, *len, size, '.'); + } + while (leadfraczeros > 0) { /* Leading fractional part zeros. */ + OUTCHAR(str, *len, size, '0'); + leadfraczeros--; + } + while (fpos > omitcount) { /* The remaining fractional part. */ + fpos--; + OUTCHAR(str, *len, size, fconvert[fpos]); + } + while (epos > 0) { /* Exponent. */ + epos--; + OUTCHAR(str, *len, size, econvert[epos]); + } + while (padlen < 0) { /* Trailing spaces. */ + OUTCHAR(str, *len, size, ' '); + padlen++; + } +} + +static void +printsep(char *str, size_t *len, size_t size) +{ +#if HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP + struct lconv *lc = localeconv(); + int i; + + if (lc->thousands_sep != NULL) + for (i = 0; lc->thousands_sep[i] != '\0'; i++) + OUTCHAR(str, *len, size, lc->thousands_sep[i]); + else +#endif /* HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP */ + OUTCHAR(str, *len, size, ','); +} + +static int +getnumsep(int digits) +{ + int separators = (digits - ((digits % 3 == 0) ? 1 : 0)) / 3; +#if HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP + int strln; + struct lconv *lc = localeconv(); + + /* We support an arbitrary separator length (including zero). */ + if (lc->thousands_sep != NULL) { + for (strln = 0; lc->thousands_sep[strln] != '\0'; strln++) + continue; + separators *= strln; + } +#endif /* HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP */ + return separators; +} + +static int +getexponent(LDOUBLE value) +{ + LDOUBLE tmp = (value >= 0.0) ? value : -value; + int exponent = 0; + + /* + * We check for 99 > exponent > -99 in order to work around possible + * endless loops which could happen (at least) in the second loop (at + * least) if we're called with an infinite value. However, we checked + * for infinity before calling this function using our ISINF() macro, so + * this might be somewhat paranoid. + */ + while (tmp < 1.0 && tmp > 0.0 && --exponent > -99) + tmp *= 10; + while (tmp >= 10.0 && ++exponent < 99) + tmp /= 10; + + return exponent; +} + +static int +convert(UINTMAX_T value, char *buf, size_t size, int base, int caps) +{ + const char *digits = caps ? "0123456789ABCDEF" : "0123456789abcdef"; + size_t pos = 0; + + /* We return an unterminated buffer with the digits in reverse order. */ + do { + buf[pos++] = digits[value % base]; + value /= base; + } while (value != 0 && pos < size); + + return (int)pos; +} + +static UINTMAX_T +cast(LDOUBLE value) +{ + UINTMAX_T result; + + /* + * We check for ">=" and not for ">" because if UINTMAX_MAX cannot be + * represented exactly as an LDOUBLE value (but is less than LDBL_MAX), + * it may be increased to the nearest higher representable value for the + * comparison (cf. C99: 6.3.1.4, 2). It might then equal the LDOUBLE + * value although converting the latter to UINTMAX_T would overflow. + */ + if (value >= UINTMAX_MAX) + return UINTMAX_MAX; + +#if defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT) + result = (unsigned long)value; +#else + result = (UINTMAX_T)value; +#endif + /* + * At least on NetBSD/sparc64 3.0.2 and 4.99.30, casting long double to + * an integer type converts e.g. 1.9 to 2 instead of 1 (which violates + * the standard). Sigh. + */ + return (result <= value) ? result : result - 1; +} + +static UINTMAX_T +myround(LDOUBLE value) +{ + UINTMAX_T intpart = cast(value); + + return ((value -= intpart) < 0.5) ? intpart : intpart + 1; +} + +static LDOUBLE +mypow10(int exponent) +{ + LDOUBLE result = 1; + + while (exponent > 0) { + result *= 10; + exponent--; + } + while (exponent < 0) { + result /= 10; + exponent++; + } + return result; +} +#endif /* !HAVE_VSNPRINTF */ + +#if !HAVE_VASPRINTF +#if NEED_MYMEMCPY +void * +mymemcpy(void *dst, void *src, size_t len) +{ + const char *from = src; + char *to = dst; + + /* No need for optimization, we use this only to replace va_copy(3). */ + while (len-- > 0) + *to++ = *from++; + return dst; +} +#endif /* NEED_MYMEMCPY */ + +int +util_vasprintf(char **ret, const char *format, va_list ap) +{ + size_t size; + int len; + va_list aq; + + VA_COPY(aq, ap); + len = vsnprintf(NULL, 0, format, aq); + VA_END_COPY(aq); + if (len < 0 || (*ret = malloc(size = len + 1)) == NULL) + return -1; + return vsnprintf(*ret, size, format, ap); +} +#endif /* !HAVE_VASPRINTF */ + +#if !HAVE_SNPRINTF +#if HAVE_STDARG_H +int +util_snprintf(char *str, size_t size, const char *format, ...) +#else +int +util_snprintf(va_alist) va_dcl +#endif /* HAVE_STDARG_H */ +{ +#if !HAVE_STDARG_H + char *str; + size_t size; + char *format; +#endif /* HAVE_STDARG_H */ + va_list ap; + int len; + + VA_START(ap, format); + VA_SHIFT(ap, str, char *); + VA_SHIFT(ap, size, size_t); + VA_SHIFT(ap, format, const char *); + len = vsnprintf(str, size, format, ap); + va_end(ap); + return len; +} +#endif /* !HAVE_SNPRINTF */ + +#if !HAVE_ASPRINTF +#if HAVE_STDARG_H +int +util_asprintf(char **ret, const char *format, ...) +#else +int +util_asprintf(va_alist) va_dcl +#endif /* HAVE_STDARG_H */ +{ +#if !HAVE_STDARG_H + char **ret; + char *format; +#endif /* HAVE_STDARG_H */ + va_list ap; + int len; + + VA_START(ap, format); + VA_SHIFT(ap, ret, char **); + VA_SHIFT(ap, format, const char *); + len = vasprintf(ret, format, ap); + va_end(ap); + return len; +} +#endif /* !HAVE_ASPRINTF */ +#else /* Dummy declaration to avoid empty translation unit warnings. */ +int main(void); +#endif /* !HAVE_SNPRINTF || !HAVE_VSNPRINTF || !HAVE_ASPRINTF || [...] */ + + +/* vim: set joinspaces textwidth=80: */ diff --git a/mesalib/src/gallium/auxiliary/util/u_split_prim.h b/mesalib/src/gallium/auxiliary/util/u_split_prim.h new file mode 100644 index 000000000..9c83d6461 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_split_prim.h @@ -0,0 +1,114 @@ +/* Originally written by Ben Skeggs for the nv50 driver*/ + +#ifndef U_SPLIT_PRIM_H +#define U_SPLIT_PRIM_H + +#include "pipe/p_defines.h" +#include "pipe/p_compiler.h" + +#include "util/u_debug.h" + +struct util_split_prim { + void *priv; + void (*emit)(void *priv, unsigned start, unsigned count); + void (*edge)(void *priv, boolean enabled); + + unsigned mode; + unsigned start; + unsigned p_start; + unsigned p_end; + + uint repeat_first:1; + uint close_first:1; + uint edgeflag_off:1; +}; + +static INLINE void +util_split_prim_init(struct util_split_prim *s, + unsigned mode, unsigned start, unsigned count) +{ + if (mode == PIPE_PRIM_LINE_LOOP) { + s->mode = PIPE_PRIM_LINE_STRIP; + s->close_first = 1; + } else { + s->mode = mode; + s->close_first = 0; + } + s->start = start; + s->p_start = start; + s->p_end = start + count; + s->edgeflag_off = 0; + s->repeat_first = 0; +} + +static INLINE boolean +util_split_prim_next(struct util_split_prim *s, unsigned max_verts) +{ + int repeat = 0; + + if (s->repeat_first) { + s->emit(s->priv, s->start, 1); + max_verts--; + if (s->edgeflag_off) { + s->edge(s->priv, TRUE); + s->edgeflag_off = FALSE; + } + } + + if ((s->p_end - s->p_start) + s->close_first <= max_verts) { + s->emit(s->priv, s->p_start, s->p_end - s->p_start); + if (s->close_first) + s->emit(s->priv, s->start, 1); + return TRUE; + } + + switch (s->mode) { + case PIPE_PRIM_LINES: + max_verts &= ~1; + break; + case PIPE_PRIM_LINE_STRIP: + repeat = 1; + break; + case PIPE_PRIM_POLYGON: + max_verts--; + s->emit(s->priv, s->p_start, max_verts); + s->edge(s->priv, FALSE); + s->emit(s->priv, s->p_start + max_verts, 1); + s->p_start += max_verts; + s->repeat_first = TRUE; + s->edgeflag_off = TRUE; + return FALSE; + case PIPE_PRIM_TRIANGLES: + max_verts = max_verts - (max_verts % 3); + break; + case PIPE_PRIM_TRIANGLE_STRIP: + /* to ensure winding stays correct, always split + * on an even number of generated triangles + */ + max_verts = max_verts & ~1; + repeat = 2; + break; + case PIPE_PRIM_TRIANGLE_FAN: + s->repeat_first = TRUE; + repeat = 1; + break; + case PIPE_PRIM_QUADS: + max_verts &= ~3; + break; + case PIPE_PRIM_QUAD_STRIP: + max_verts &= ~1; + repeat = 2; + break; + case PIPE_PRIM_POINTS: + break; + default: + /* TODO: implement adjacency primitives */ + assert(0); + } + + s->emit (s->priv, s->p_start, max_verts); + s->p_start += (max_verts - repeat); + return FALSE; +} + +#endif /* U_SPLIT_PRIM_H */ diff --git a/mesalib/src/gallium/auxiliary/util/u_sse.h b/mesalib/src/gallium/auxiliary/util/u_sse.h new file mode 100644 index 000000000..d000c0fd7 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_sse.h @@ -0,0 +1,255 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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 TUNGSTEN GRAPHICS 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 + * SSE intrinsics portability header. + * + * Although the SSE intrinsics are support by all modern x86 and x86-64 + * compilers, there are some intrisincs missing in some implementations + * (especially older MSVC versions). This header abstracts that away. + */ + +#ifndef U_SSE_H_ +#define U_SSE_H_ + +#include "pipe/p_config.h" + +#if defined(PIPE_ARCH_SSE) + +#include + + +/* MSVC before VC8 does not support the _mm_castxxx_yyy */ +#if defined(_MSC_VER) && _MSC_VER < 1500 + +union __declspec(align(16)) m128_types { + __m128 m128; + __m128i m128i; + __m128d m128d; +}; + +static __inline __m128 +_mm_castsi128_ps(__m128i a) +{ + union m128_types u; + u.m128i = a; + return u.m128; +} + +static __inline __m128i +_mm_castps_si128(__m128 a) +{ + union m128_types u; + u.m128 = a; + return u.m128i; +} + +#endif /* defined(_MSC_VER) && _MSC_VER < 1500 */ + +union m128i { + __m128i m; + ubyte ub[16]; + ushort us[8]; + uint ui[4]; +}; + +static INLINE void u_print_epi8(const char *name, __m128i r) +{ + union { __m128i m; ubyte ub[16]; } u; + u.m = r; + + debug_printf("%s: " + "%02x/" + "%02x/" + "%02x/" + "%02x/" + "%02x/" + "%02x/" + "%02x/" + "%02x/" + "%02x/" + "%02x/" + "%02x/" + "%02x/" + "%02x/" + "%02x/" + "%02x/" + "%02x\n", + name, + u.ub[0], u.ub[1], u.ub[2], u.ub[3], + u.ub[4], u.ub[5], u.ub[6], u.ub[7], + u.ub[8], u.ub[9], u.ub[10], u.ub[11], + u.ub[12], u.ub[13], u.ub[14], u.ub[15]); +} + +static INLINE void u_print_epi16(const char *name, __m128i r) +{ + union { __m128i m; ushort us[8]; } u; + u.m = r; + + debug_printf("%s: " + "%04x/" + "%04x/" + "%04x/" + "%04x/" + "%04x/" + "%04x/" + "%04x/" + "%04x\n", + name, + u.us[0], u.us[1], u.us[2], u.us[3], + u.us[4], u.us[5], u.us[6], u.us[7]); +} + +static INLINE void u_print_epi32(const char *name, __m128i r) +{ + union { __m128i m; uint ui[4]; } u; + u.m = r; + + debug_printf("%s: " + "%08x/" + "%08x/" + "%08x/" + "%08x\n", + name, + u.ui[0], u.ui[1], u.ui[2], u.ui[3]); +} + +static INLINE void u_print_ps(const char *name, __m128 r) +{ + union { __m128 m; float f[4]; } u; + u.m = r; + + debug_printf("%s: " + "%f/" + "%f/" + "%f/" + "%f\n", + name, + u.f[0], u.f[1], u.f[2], u.f[3]); +} + + +#define U_DUMP_EPI32(a) u_print_epi32(#a, a) +#define U_DUMP_EPI16(a) u_print_epi16(#a, a) +#define U_DUMP_EPI8(a) u_print_epi8(#a, a) +#define U_DUMP_PS(a) u_print_ps(#a, a) + + + +#if defined(PIPE_ARCH_SSSE3) + +#include + +#else /* !PIPE_ARCH_SSSE3 */ + +/** + * Describe _mm_shuffle_epi8() with gcc extended inline assembly, for cases + * where -mssse3 is not supported/enabled. + * + * MSVC will never get in here as its intrinsics support do not rely on + * compiler command line options. + */ +static __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_shuffle_epi8(__m128i a, __m128i mask) +{ + __m128i result; + __asm__("pshufb %1, %0" + : "=x" (result) + : "xm" (mask), "0" (a)); + return result; +} + +#endif /* !PIPE_ARCH_SSSE3 */ + + + + +/* Provide an SSE2 implementation of _mm_mullo_epi32() in terms of + * _mm_mul_epu32(). + * + * I suspect this works fine for us because one of our operands is + * always positive, but not sure that this can be used for general + * signed integer multiplication. + * + * This seems close enough to the speed of SSE4 and the real + * _mm_mullo_epi32() intrinsic as to not justify adding an sse4 + * dependency at this point. + */ +static INLINE __m128i mm_mullo_epi32(const __m128i a, const __m128i b) +{ + __m128i a4 = _mm_srli_epi64(a, 32); /* shift by one dword */ + __m128i b4 = _mm_srli_epi64(b, 32); /* shift by one dword */ + __m128i ba = _mm_mul_epu32(b, a); /* multply dwords 0, 2 */ + __m128i b4a4 = _mm_mul_epu32(b4, a4); /* multiply dwords 1, 3 */ + + /* Interleave the results, either with shuffles or (slightly + * faster) direct bit operations: + */ +#if 0 + __m128i ba8 = _mm_shuffle_epi32(ba, 8); + __m128i b4a48 = _mm_shuffle_epi32(b4a4, 8); + __m128i result = _mm_unpacklo_epi32(ba8, b4a48); +#else + __m128i mask = _mm_setr_epi32(~0,0,~0,0); + __m128i ba_mask = _mm_and_si128(ba, mask); + __m128i b4a4_mask_shift = _mm_slli_epi64(b4a4, 32); + __m128i result = _mm_or_si128(ba_mask, b4a4_mask_shift); +#endif + + return result; +} + + +static INLINE void +transpose4_epi32(const __m128i * restrict a, + const __m128i * restrict b, + const __m128i * restrict c, + const __m128i * restrict d, + __m128i * restrict o, + __m128i * restrict p, + __m128i * restrict q, + __m128i * restrict r) +{ + __m128i t0 = _mm_unpacklo_epi32(*a, *b); + __m128i t1 = _mm_unpacklo_epi32(*c, *d); + __m128i t2 = _mm_unpackhi_epi32(*a, *b); + __m128i t3 = _mm_unpackhi_epi32(*c, *d); + + *o = _mm_unpacklo_epi64(t0, t1); + *p = _mm_unpackhi_epi64(t0, t1); + *q = _mm_unpacklo_epi64(t2, t3); + *r = _mm_unpackhi_epi64(t2, t3); +} + +#define SCALAR_EPI32(m, i) _mm_shuffle_epi32((m), _MM_SHUFFLE(i,i,i,i)) + + +#endif /* PIPE_ARCH_SSE */ + +#endif /* U_SSE_H_ */ diff --git a/mesalib/src/gallium/auxiliary/util/u_staging.c b/mesalib/src/gallium/auxiliary/util/u_staging.c new file mode 100644 index 000000000..030ee4718 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_staging.c @@ -0,0 +1,132 @@ +/************************************************************************** + * + * Copyright 2010 Luca Barbieri + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and 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 COPYRIGHT OWNER(S) 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_staging.h" +#include "pipe/p_context.h" +#include "util/u_memory.h" +#include "util/u_inlines.h" + +static void +util_staging_resource_template(struct pipe_resource *pt, unsigned width, unsigned height, unsigned depth, struct pipe_resource *template) +{ + memset(template, 0, sizeof(struct pipe_resource)); + if(pt->target != PIPE_BUFFER && depth <= 1) + template->target = PIPE_TEXTURE_RECT; + else + template->target = pt->target; + template->format = pt->format; + template->width0 = width; + template->height0 = height; + template->depth0 = depth; + template->array_size = 1; + template->last_level = 0; + template->nr_samples = pt->nr_samples; + template->bind = 0; + template->usage = PIPE_USAGE_STAGING; + template->flags = 0; +} + +struct util_staging_transfer * +util_staging_transfer_init(struct pipe_context *pipe, + struct pipe_resource *pt, + unsigned level, + unsigned usage, + const struct pipe_box *box, + bool direct, struct util_staging_transfer *tx) +{ + struct pipe_screen *pscreen = pipe->screen; + + struct pipe_resource staging_resource_template; + + pipe_resource_reference(&tx->base.resource, pt); + tx->base.level = level; + tx->base.usage = usage; + tx->base.box = *box; + + if (direct) + { + tx->staging_resource = pt; + return tx; + } + + util_staging_resource_template(pt, box->width, box->height, box->depth, &staging_resource_template); + tx->staging_resource = pscreen->resource_create(pscreen, &staging_resource_template); + if (!tx->staging_resource) + { + pipe_resource_reference(&tx->base.resource, NULL); + FREE(tx); + return NULL; + } + + if (usage & PIPE_TRANSFER_READ) + { + /* XXX this looks wrong dst is always the same but looping over src z? */ + unsigned zi; + struct pipe_box sbox; + sbox.x = box->x; + sbox.y = box->y; + sbox.z = box->z; + sbox.width = box->width; + sbox.height = box->height; + sbox.depth = 1; + for(zi = 0; zi < box->depth; ++zi) { + sbox.z = sbox.z + zi; + pipe->resource_copy_region(pipe, tx->staging_resource, 0, 0, 0, 0, + tx->base.resource, level, &sbox); + } + } + + return tx; +} + +void +util_staging_transfer_destroy(struct pipe_context *pipe, struct pipe_transfer *ptx) +{ + struct util_staging_transfer *tx = (struct util_staging_transfer *)ptx; + + if (tx->staging_resource != tx->base.resource) + { + if(tx->base.usage & PIPE_TRANSFER_WRITE) { + /* XXX this looks wrong src is always the same but looping over dst z? */ + unsigned zi; + struct pipe_box sbox; + sbox.x = 0; + sbox.y = 0; + sbox.z = 0; + sbox.width = tx->base.box.width; + sbox.height = tx->base.box.height; + sbox.depth = 1; + for(zi = 0; zi < tx->base.box.depth; ++zi) + pipe->resource_copy_region(pipe, tx->base.resource, tx->base.level, tx->base.box.x, tx->base.box.y, tx->base.box.z + zi, + tx->staging_resource, 0, &sbox); + } + + pipe_resource_reference(&tx->staging_resource, NULL); + } + + pipe_resource_reference(&ptx->resource, NULL); + FREE(ptx); +} diff --git a/mesalib/src/gallium/auxiliary/util/u_staging.h b/mesalib/src/gallium/auxiliary/util/u_staging.h new file mode 100644 index 000000000..87eb5a1da --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_staging.h @@ -0,0 +1,63 @@ +/************************************************************************** + * + * Copyright 2010 Luca Barbieri + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and 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 COPYRIGHT OWNER(S) 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. + * + **************************************************************************/ + +/* Direct3D 10/11 has no concept of transfers. Applications instead + * create resources with a STAGING or DYNAMIC usage, copy between them + * and the real resource and use Map to map the STAGING/DYNAMIC resource. + * + * This util module allows to implement Gallium drivers as a Direct3D + * driver would be implemented: transfers allocate a resource with + * PIPE_USAGE_STAGING, and copy the data between it and the real resource + * with resource_copy_region. + */ + +#ifndef U_STAGING_H +#define U_STAGING_H + +#include "pipe/p_state.h" + +struct util_staging_transfer { + struct pipe_transfer base; + + /* if direct, same as base.resource, otherwise the temporary staging resource */ + struct pipe_resource *staging_resource; +}; + +/* user must be stride, slice_stride and offset */ +/* pt->usage == PIPE_USAGE_DYNAMIC || pt->usage == PIPE_USAGE_STAGING should be a good value to pass for direct */ +/* staging resource is currently created with PIPE_USAGE_STAGING */ +struct util_staging_transfer * +util_staging_transfer_init(struct pipe_context *pipe, + struct pipe_resource *pt, + unsigned level, + unsigned usage, + const struct pipe_box *box, + bool direct, struct util_staging_transfer *tx); + +void +util_staging_transfer_destroy(struct pipe_context *pipe, struct pipe_transfer *ptx); + +#endif diff --git a/mesalib/src/gallium/auxiliary/util/u_string.h b/mesalib/src/gallium/auxiliary/util/u_string.h new file mode 100644 index 000000000..52e380698 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_string.h @@ -0,0 +1,220 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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 TUNGSTEN GRAPHICS 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 + * Platform independent functions for string manipulation. + * + * @author Jose Fonseca + */ + +#ifndef U_STRING_H_ +#define U_STRING_H_ + +#if !defined(WIN32) && !defined(XF86_LIBC_H) +#include +#endif +#include +#include + +#include "pipe/p_compiler.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifdef WIN32 + +int util_vsnprintf(char *, size_t, const char *, va_list); +int util_snprintf(char *str, size_t size, const char *format, ...); + +static INLINE void +util_vsprintf(char *str, const char *format, va_list ap) +{ + util_vsnprintf(str, (size_t)-1, format, ap); +} + +static INLINE void +util_sprintf(char *str, const char *format, ...) +{ + va_list ap; + va_start(ap, format); + util_vsnprintf(str, (size_t)-1, format, ap); + va_end(ap); +} + +static INLINE char * +util_strchr(const char *s, char c) +{ + while(*s) { + if(*s == c) + return (char *)s; + ++s; + } + return NULL; +} + +static INLINE char* +util_strncat(char *dst, const char *src, size_t n) +{ + char *p = dst + strlen(dst); + const char *q = src; + size_t i; + + for (i = 0; i < n && *q != '\0'; ++i) + *p++ = *q++; + *p = '\0'; + + return dst; +} + +static INLINE int +util_strcmp(const char *s1, const char *s2) +{ + unsigned char u1, u2; + + while (1) { + u1 = (unsigned char) *s1++; + u2 = (unsigned char) *s2++; + if (u1 != u2) + return u1 - u2; + if (u1 == '\0') + return 0; + } + return 0; +} + +static INLINE int +util_strncmp(const char *s1, const char *s2, size_t n) +{ + unsigned char u1, u2; + + while (n-- > 0) { + u1 = (unsigned char) *s1++; + u2 = (unsigned char) *s2++; + if (u1 != u2) + return u1 - u2; + if (u1 == '\0') + return 0; + } + return 0; +} + +static INLINE char * +util_strstr(const char *haystack, const char *needle) +{ + const char *p = haystack; + size_t len = strlen(needle); + + for (; (p = util_strchr(p, *needle)) != 0; p++) { + if (util_strncmp(p, needle, len) == 0) { + return (char *)p; + } + } + return NULL; +} + +static INLINE void * +util_memmove(void *dest, const void *src, size_t n) +{ + char *p = (char *)dest; + const char *q = (const char *)src; + if (dest < src) { + while (n--) + *p++ = *q++; + } + else + { + p += n; + q += n; + while (n--) + *--p = *--q; + } + return dest; +} + + +#else + +#define util_vsnprintf vsnprintf +#define util_snprintf snprintf +#define util_vsprintf vsprintf +#define util_sprintf sprintf +#define util_strchr strchr +#define util_strcmp strcmp +#define util_strncmp strncmp +#define util_strncat strncat +#define util_strstr strstr +#define util_memmove memmove + +#endif + + +/** + * Printable string buffer + */ +struct util_strbuf +{ + char *str; + char *ptr; + size_t left; +}; + + +static INLINE void +util_strbuf_init(struct util_strbuf *sbuf, char *str, size_t size) +{ + sbuf->str = str; + sbuf->str[0] = 0; + sbuf->ptr = sbuf->str; + sbuf->left = size; +} + + +static INLINE void +util_strbuf_printf(struct util_strbuf *sbuf, const char *format, ...) +{ + if(sbuf->left > 1) { + size_t written; + va_list ap; + va_start(ap, format); + written = util_vsnprintf(sbuf->ptr, sbuf->left, format, ap); + va_end(ap); + sbuf->ptr += written; + sbuf->left -= written; + } +} + + + +#ifdef __cplusplus +} +#endif + +#endif /* U_STRING_H_ */ diff --git a/mesalib/src/gallium/auxiliary/util/u_surface.c b/mesalib/src/gallium/auxiliary/util/u_surface.c new file mode 100644 index 000000000..26f2aee99 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_surface.c @@ -0,0 +1,371 @@ +/************************************************************************** + * + * 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. + * + **************************************************************************/ + +/** + * @file + * Surface utility functions. + * + * @author Brian Paul + */ + + +#include "pipe/p_defines.h" +#include "pipe/p_screen.h" +#include "pipe/p_state.h" + +#include "util/u_format.h" +#include "util/u_inlines.h" +#include "util/u_rect.h" +#include "util/u_surface.h" +#include "util/u_pack_color.h" + +void +u_surface_default_template(struct pipe_surface *view, + const struct pipe_resource *texture, + unsigned bind) +{ + view->format = texture->format; + view->u.tex.level = 0; + view->u.tex.first_layer = 0; + view->u.tex.last_layer = 0; + /* XXX should filter out all non-rt/ds bind flags ? */ + view->usage = bind; +} + +/** + * Helper to quickly create an RGBA rendering surface of a certain size. + * \param textureOut returns the new texture + * \param surfaceOut returns the new surface + * \return TRUE for success, FALSE if failure + */ +boolean +util_create_rgba_surface(struct pipe_context *pipe, + uint width, uint height, + uint bind, + struct pipe_resource **textureOut, + struct pipe_surface **surfaceOut) +{ + static const enum pipe_format rgbaFormats[] = { + PIPE_FORMAT_B8G8R8A8_UNORM, + PIPE_FORMAT_A8R8G8B8_UNORM, + PIPE_FORMAT_A8B8G8R8_UNORM, + PIPE_FORMAT_NONE + }; + const uint target = PIPE_TEXTURE_2D; + enum pipe_format format = PIPE_FORMAT_NONE; + struct pipe_resource templ; + struct pipe_surface surf_templ; + struct pipe_screen *screen = pipe->screen; + uint i; + + /* Choose surface format */ + for (i = 0; rgbaFormats[i]; i++) { + if (screen->is_format_supported(screen, rgbaFormats[i], + target, 0, bind)) { + format = rgbaFormats[i]; + break; + } + } + if (format == PIPE_FORMAT_NONE) + return FALSE; /* unable to get an rgba format!?! */ + + /* create texture */ + memset(&templ, 0, sizeof(templ)); + templ.target = target; + templ.format = format; + templ.last_level = 0; + templ.width0 = width; + templ.height0 = height; + templ.depth0 = 1; + templ.array_size = 1; + templ.bind = bind; + + *textureOut = screen->resource_create(screen, &templ); + if (!*textureOut) + return FALSE; + + /* create surface */ + memset(&surf_templ, 0, sizeof(surf_templ)); + u_surface_default_template(&surf_templ, *textureOut, bind); + /* create surface / view into texture */ + *surfaceOut = pipe->create_surface(pipe, + *textureOut, + &surf_templ); + if (!*surfaceOut) { + pipe_resource_reference(textureOut, NULL); + return FALSE; + } + + return TRUE; +} + + +/** + * Release the surface and texture from util_create_rgba_surface(). + */ +void +util_destroy_rgba_surface(struct pipe_resource *texture, + struct pipe_surface *surface) +{ + pipe_surface_reference(&surface, NULL); + pipe_resource_reference(&texture, NULL); +} + + + +/** + * Fallback function for pipe->resource_copy_region(). + * Note: (X,Y)=(0,0) is always the upper-left corner. + */ +void +util_resource_copy_region(struct pipe_context *pipe, + struct pipe_resource *dst, + unsigned dst_level, + unsigned dst_x, unsigned dst_y, unsigned dst_z, + struct pipe_resource *src, + unsigned src_level, + const struct pipe_box *src_box) +{ + struct pipe_transfer *src_trans, *dst_trans; + void *dst_map; + const void *src_map; + enum pipe_format src_format, dst_format; + unsigned w = src_box->width; + unsigned h = src_box->height; + + assert(src && dst); + assert((src->target == PIPE_BUFFER && dst->target == PIPE_BUFFER) || + (src->target != PIPE_BUFFER && dst->target != PIPE_BUFFER)); + + if (!src || !dst) + return; + + src_format = src->format; + dst_format = dst->format; + + src_trans = pipe_get_transfer(pipe, + src, + src_level, + src_box->z, + PIPE_TRANSFER_READ, + src_box->x, src_box->y, w, h); + + dst_trans = pipe_get_transfer(pipe, + dst, + dst_level, + dst_z, + PIPE_TRANSFER_WRITE, + dst_x, dst_y, w, h); + + assert(util_format_get_blocksize(dst_format) == util_format_get_blocksize(src_format)); + assert(util_format_get_blockwidth(dst_format) == util_format_get_blockwidth(src_format)); + assert(util_format_get_blockheight(dst_format) == util_format_get_blockheight(src_format)); + + src_map = pipe->transfer_map(pipe, src_trans); + dst_map = pipe->transfer_map(pipe, dst_trans); + + assert(src_map); + assert(dst_map); + + if (src_map && dst_map) { + if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) { + memcpy(dst_map, src_map, w); + } else { + util_copy_rect(dst_map, + dst_format, + dst_trans->stride, + 0, 0, + w, h, + src_map, + src_trans->stride, + 0, + 0); + } + } + + pipe->transfer_unmap(pipe, src_trans); + pipe->transfer_unmap(pipe, dst_trans); + + pipe->transfer_destroy(pipe, src_trans); + pipe->transfer_destroy(pipe, dst_trans); +} + + + +#define UBYTE_TO_USHORT(B) ((B) | ((B) << 8)) + + +/** + * Fallback for pipe->clear_render_target() function. + * XXX this looks too hackish to be really useful. + * cpp > 4 looks like a gross hack at best... + * Plus can't use these transfer fallbacks when clearing + * multisampled surfaces for instance. + */ +void +util_clear_render_target(struct pipe_context *pipe, + struct pipe_surface *dst, + const float *rgba, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height) +{ + struct pipe_transfer *dst_trans; + void *dst_map; + union util_color uc; + + assert(dst->texture); + if (!dst->texture) + return; + /* XXX: should handle multiple layers */ + dst_trans = pipe_get_transfer(pipe, + dst->texture, + dst->u.tex.level, + dst->u.tex.first_layer, + PIPE_TRANSFER_WRITE, + dstx, dsty, width, height); + + dst_map = pipe->transfer_map(pipe, dst_trans); + + assert(dst_map); + + if (dst_map) { + assert(dst_trans->stride > 0); + + util_pack_color(rgba, dst->texture->format, &uc); + util_fill_rect(dst_map, dst->texture->format, + dst_trans->stride, + 0, 0, width, height, &uc); + } + + pipe->transfer_unmap(pipe, dst_trans); + pipe->transfer_destroy(pipe, dst_trans); +} + +/** + * Fallback for pipe->clear_stencil() function. + * sw fallback doesn't look terribly useful here. + * Plus can't use these transfer fallbacks when clearing + * multisampled surfaces for instance. + */ +void +util_clear_depth_stencil(struct pipe_context *pipe, + struct pipe_surface *dst, + unsigned clear_flags, + double depth, + unsigned stencil, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height) +{ + struct pipe_transfer *dst_trans; + ubyte *dst_map; + boolean need_rmw = FALSE; + + if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) && + ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) && + util_format_is_depth_and_stencil(dst->format)) + need_rmw = TRUE; + + assert(dst->texture); + if (!dst->texture) + return; + dst_trans = pipe_get_transfer(pipe, + dst->texture, + dst->u.tex.level, + dst->u.tex.first_layer, + (need_rmw ? PIPE_TRANSFER_READ_WRITE : + PIPE_TRANSFER_WRITE), + dstx, dsty, width, height); + + dst_map = pipe->transfer_map(pipe, dst_trans); + + assert(dst_map); + + if (dst_map) { + unsigned dst_stride = dst_trans->stride; + unsigned zstencil = util_pack_z_stencil(dst->texture->format, depth, stencil); + unsigned i, j; + assert(dst_trans->stride > 0); + + switch (util_format_get_blocksize(dst->format)) { + case 1: + assert(dst->format == PIPE_FORMAT_S8_USCALED); + if(dst_stride == width) + memset(dst_map, (ubyte) zstencil, height * width); + else { + for (i = 0; i < height; i++) { + memset(dst_map, (ubyte) zstencil, width); + dst_map += dst_stride; + } + } + break; + case 2: + assert(dst->format == PIPE_FORMAT_Z16_UNORM); + for (i = 0; i < height; i++) { + uint16_t *row = (uint16_t *)dst_map; + for (j = 0; j < width; j++) + *row++ = (uint16_t) zstencil; + dst_map += dst_stride; + } + break; + case 4: + if (!need_rmw) { + for (i = 0; i < height; i++) { + uint32_t *row = (uint32_t *)dst_map; + for (j = 0; j < width; j++) + *row++ = zstencil; + dst_map += dst_stride; + } + } + else { + uint32_t dst_mask; + if (dst->format == PIPE_FORMAT_Z24_UNORM_S8_USCALED) + dst_mask = 0xffffff00; + else { + assert(dst->format == PIPE_FORMAT_S8_USCALED_Z24_UNORM); + dst_mask = 0xffffff; + } + if (clear_flags & PIPE_CLEAR_DEPTH) + dst_mask = ~dst_mask; + for (i = 0; i < height; i++) { + uint32_t *row = (uint32_t *)dst_map; + for (j = 0; j < width; j++) { + uint32_t tmp = *row & dst_mask; + *row++ = tmp | (zstencil & ~dst_mask); + } + dst_map += dst_stride; + } + } + break; + case 8: + default: + assert(0); + break; + } + } + + pipe->transfer_unmap(pipe, dst_trans); + pipe->transfer_destroy(pipe, dst_trans); +} diff --git a/mesalib/src/gallium/auxiliary/util/u_surface.h b/mesalib/src/gallium/auxiliary/util/u_surface.h new file mode 100644 index 000000000..e02931bbe --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_surface.h @@ -0,0 +1,90 @@ +/************************************************************************** + * + * 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 U_SURFACE_H +#define U_SURFACE_H + + +#include "pipe/p_compiler.h" +#include "pipe/p_state.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +extern void +u_surface_default_template(struct pipe_surface *view, + const struct pipe_resource *texture, + unsigned bind); + +extern boolean +util_create_rgba_surface(struct pipe_context *ctx, + uint width, uint height, uint bind, + struct pipe_resource **textureOut, + struct pipe_surface **surfaceOut); + + +extern void +util_destroy_rgba_surface(struct pipe_resource *texture, + struct pipe_surface *surface); + + + +extern void +util_resource_copy_region(struct pipe_context *pipe, + struct pipe_resource *dst, + unsigned dst_level, + unsigned dst_x, unsigned dst_y, unsigned dst_z, + struct pipe_resource *src, + unsigned src_level, + const struct pipe_box *src_box); + +extern void +util_clear_render_target(struct pipe_context *pipe, + struct pipe_surface *dst, + const float *rgba, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height); + +extern void +util_clear_depth_stencil(struct pipe_context *pipe, + struct pipe_surface *dst, + unsigned clear_flags, + double depth, + unsigned stencil, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height); + + +#ifdef __cplusplus +} +#endif + + +#endif /* U_SURFACE_H */ diff --git a/mesalib/src/gallium/auxiliary/util/u_surfaces.c b/mesalib/src/gallium/auxiliary/util/u_surfaces.c new file mode 100644 index 000000000..9a42c9d29 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_surfaces.c @@ -0,0 +1,124 @@ +/************************************************************************** + * + * Copyright 2010 Luca Barbieri + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and 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 COPYRIGHT OWNER(S) 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 "u_surfaces.h" +#include "util/u_hash_table.h" +#include "util/u_inlines.h" +#include "util/u_memory.h" + +boolean +util_surfaces_do_get(struct util_surfaces *us, unsigned surface_struct_size, + struct pipe_context *ctx, struct pipe_resource *pt, + unsigned level, unsigned layer, unsigned flags, + struct pipe_surface **res) +{ + struct pipe_surface *ps; + + if(pt->target == PIPE_TEXTURE_3D || pt->target == PIPE_TEXTURE_CUBE) + { /* or 2D array */ + if(!us->u.hash) + us->u.hash = cso_hash_create(); + + ps = cso_hash_iter_data(cso_hash_find(us->u.hash, (layer << 8) | level)); + } + else + { + if(!us->u.array) + us->u.array = CALLOC(pt->last_level + 1, sizeof(struct pipe_surface *)); + ps = us->u.array[level]; + } + + if(ps && ps->context == ctx) + { + p_atomic_inc(&ps->reference.count); + *res = ps; + return FALSE; + } + + ps = (struct pipe_surface *)CALLOC(1, surface_struct_size); + if(!ps) + { + *res = NULL; + return FALSE; + } + + pipe_surface_init(ctx, ps, pt, level, layer, flags); + + if(pt->target == PIPE_TEXTURE_3D || pt->target == PIPE_TEXTURE_CUBE) + cso_hash_insert(us->u.hash, (layer << 8) | level, ps); + else + us->u.array[level] = ps; + + *res = ps; + return TRUE; +} + +void +util_surfaces_do_detach(struct util_surfaces *us, struct pipe_surface *ps) +{ + struct pipe_resource *pt = ps->texture; + if(pt->target == PIPE_TEXTURE_3D || pt->target == PIPE_TEXTURE_CUBE) + { /* or 2D array */ + cso_hash_erase(us->u.hash, cso_hash_find(us->u.hash, (ps->u.tex.first_layer << 8) | ps->u.tex.level)); + } + else + us->u.array[ps->u.tex.level] = 0; +} + +void +util_surfaces_destroy(struct util_surfaces *us, struct pipe_resource *pt, void (*destroy_surface) (struct pipe_surface *)) +{ + if(pt->target == PIPE_TEXTURE_3D || pt->target == PIPE_TEXTURE_CUBE) + { /* or 2D array */ + if(us->u.hash) + { + struct cso_hash_iter iter; + iter = cso_hash_first_node(us->u.hash); + while (!cso_hash_iter_is_null(iter)) { + destroy_surface(cso_hash_iter_data(iter)); + iter = cso_hash_iter_next(iter); + } + + cso_hash_delete(us->u.hash); + us->u.hash = NULL; + } + } + else + { + if(us->u.array) + { + unsigned i; + for(i = 0; i <= pt->last_level; ++i) + { + struct pipe_surface *ps = us->u.array[i]; + if(ps) + destroy_surface(ps); + } + FREE(us->u.array); + us->u.array = NULL; + } + } +} diff --git a/mesalib/src/gallium/auxiliary/util/u_surfaces.h b/mesalib/src/gallium/auxiliary/util/u_surfaces.h new file mode 100644 index 000000000..2402e8841 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_surfaces.h @@ -0,0 +1,101 @@ +/************************************************************************** + * + * Copyright 2010 Luca Barbieri + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and 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 COPYRIGHT OWNER(S) 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 U_SURFACES_H_ +#define U_SURFACES_H_ + +#include "pipe/p_compiler.h" +#include "pipe/p_state.h" +#include "util/u_atomic.h" +#include "cso_cache/cso_hash.h" + +struct util_surfaces +{ + union + { + struct cso_hash *hash; + struct pipe_surface **array; + void* pv; + } u; +}; + +/* Return value indicates if the pipe surface result is new */ +boolean +util_surfaces_do_get(struct util_surfaces *us, unsigned surface_struct_size, + struct pipe_context *ctx, struct pipe_resource *pt, + unsigned level, unsigned layer, unsigned flags, + struct pipe_surface **res); + +/* fast inline path for the very common case */ +static INLINE boolean +util_surfaces_get(struct util_surfaces *us, unsigned surface_struct_size, + struct pipe_context *ctx, struct pipe_resource *pt, + unsigned level, unsigned layer, unsigned flags, + struct pipe_surface **res) +{ + if(likely((pt->target == PIPE_TEXTURE_2D || pt->target == PIPE_TEXTURE_RECT) && us->u.array)) + { + struct pipe_surface *ps = us->u.array[level]; + if(ps && ps->context == ctx) + { + p_atomic_inc(&ps->reference.count); + *res = ps; + return FALSE; + } + } + + return util_surfaces_do_get(us, surface_struct_size, ctx, pt, level, layer, flags, res); +} + +static INLINE struct pipe_surface * +util_surfaces_peek(struct util_surfaces *us, struct pipe_resource *pt, unsigned level, unsigned layer) +{ + if(!us->u.pv) + return 0; + + if(unlikely(pt->target == PIPE_TEXTURE_3D || pt->target == PIPE_TEXTURE_CUBE)) + return cso_hash_iter_data(cso_hash_find(us->u.hash, (layer << 8) | level)); + else + return us->u.array[level]; +} + +void util_surfaces_do_detach(struct util_surfaces *us, struct pipe_surface *ps); + +static INLINE void +util_surfaces_detach(struct util_surfaces *us, struct pipe_surface *ps) +{ + if(likely(ps->texture->target == PIPE_TEXTURE_2D || ps->texture->target == PIPE_TEXTURE_RECT)) + { + us->u.array[ps->u.tex.level] = 0; + return; + } + + util_surfaces_do_detach(us, ps); +} + +void util_surfaces_destroy(struct util_surfaces *us, struct pipe_resource *pt, void (*destroy_surface) (struct pipe_surface *)); + +#endif diff --git a/mesalib/src/gallium/auxiliary/util/u_texture.c b/mesalib/src/gallium/auxiliary/util/u_texture.c new file mode 100644 index 000000000..1e72843f0 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_texture.c @@ -0,0 +1,103 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * Copyright 2008 VMware, Inc. All rights reserved. + * Copyright 2009 Marek Olšák + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and 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 TUNGSTEN GRAPHICS 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 + * Texture mapping utility functions. + * + * @author Brian Paul + * Marek Olšák + */ + +#include "pipe/p_defines.h" + +#include "util/u_debug.h" +#include "util/u_texture.h" + +void util_map_texcoords2d_onto_cubemap(unsigned face, + const float *in_st, unsigned in_stride, + float *out_str, unsigned out_stride) +{ + int i; + float rx, ry, rz; + + /* loop over quad verts */ + for (i = 0; i < 4; i++) { + /* Compute sc = +/-scale and tc = +/-scale. + * Not +/-1 to avoid cube face selection ambiguity near the edges, + * though that can still sometimes happen with this scale factor... + */ + const float scale = 0.9999f; + const float sc = (2 * in_st[0] - 1) * scale; + const float tc = (2 * in_st[1] - 1) * scale; + + switch (face) { + case PIPE_TEX_FACE_POS_X: + rx = 1; + ry = -tc; + rz = -sc; + break; + case PIPE_TEX_FACE_NEG_X: + rx = -1; + ry = -tc; + rz = sc; + break; + case PIPE_TEX_FACE_POS_Y: + rx = sc; + ry = 1; + rz = tc; + break; + case PIPE_TEX_FACE_NEG_Y: + rx = sc; + ry = -1; + rz = -tc; + break; + case PIPE_TEX_FACE_POS_Z: + rx = sc; + ry = -tc; + rz = 1; + break; + case PIPE_TEX_FACE_NEG_Z: + rx = -sc; + ry = -tc; + rz = -1; + break; + default: + rx = ry = rz = 0; + assert(0); + } + + out_str[0] = rx; /*s*/ + out_str[1] = ry; /*t*/ + out_str[2] = rz; /*r*/ + + in_st += in_stride; + out_str += out_stride; + } +} diff --git a/mesalib/src/gallium/auxiliary/util/u_texture.h b/mesalib/src/gallium/auxiliary/util/u_texture.h new file mode 100644 index 000000000..3e03911ec --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_texture.h @@ -0,0 +1,54 @@ +/************************************************************************** + * + * Copyright 2009 Marek Olšák + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and 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 TUNGSTEN GRAPHICS 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 U_TEXTURE_H +#define U_TEXTURE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Convert 2D texture coordinates of 4 vertices into cubemap coordinates + * in the given face. + * Coordinates must be in the range [0,1]. + * + * \param face Cubemap face. + * \param in_st 4 pairs of 2D texture coordinates to convert. + * \param in_stride Stride of in_st in floats. + * \param out_str STR cubemap texture coordinates to compute. + * \param out_stride Stride of out_str in floats. + */ +void util_map_texcoords2d_onto_cubemap(unsigned face, + const float *in_st, unsigned in_stride, + float *out_str, unsigned out_stride); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/mesalib/src/gallium/auxiliary/util/u_tile.c b/mesalib/src/gallium/auxiliary/util/u_tile.c new file mode 100644 index 000000000..54f634948 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_tile.c @@ -0,0 +1,655 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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 TUNGSTEN GRAPHICS 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. + * + **************************************************************************/ + +/** + * RGBA/float tile get/put functions. + * Usable both by drivers and state trackers. + */ + + +#include "pipe/p_defines.h" +#include "util/u_inlines.h" + +#include "util/u_format.h" +#include "util/u_math.h" +#include "util/u_memory.h" +#include "util/u_rect.h" +#include "util/u_tile.h" + + +/** + * Move raw block of pixels from transfer object to user memory. + */ +void +pipe_get_tile_raw(struct pipe_context *pipe, + struct pipe_transfer *pt, + uint x, uint y, uint w, uint h, + void *dst, int dst_stride) +{ + const void *src; + + if (dst_stride == 0) + dst_stride = util_format_get_stride(pt->resource->format, w); + + if (u_clip_tile(x, y, &w, &h, &pt->box)) + return; + + src = pipe->transfer_map(pipe, pt); + assert(src); + if(!src) + return; + + util_copy_rect(dst, pt->resource->format, dst_stride, 0, 0, w, h, src, pt->stride, x, y); + + pipe->transfer_unmap(pipe, pt); +} + + +/** + * Move raw block of pixels from user memory to transfer object. + */ +void +pipe_put_tile_raw(struct pipe_context *pipe, + struct pipe_transfer *pt, + uint x, uint y, uint w, uint h, + const void *src, int src_stride) +{ + void *dst; + enum pipe_format format = pt->resource->format; + + if (src_stride == 0) + src_stride = util_format_get_stride(format, w); + + if (u_clip_tile(x, y, &w, &h, &pt->box)) + return; + + dst = pipe->transfer_map(pipe, pt); + assert(dst); + if(!dst) + return; + + util_copy_rect(dst, format, pt->stride, x, y, w, h, src, src_stride, 0, 0); + + pipe->transfer_unmap(pipe, pt); +} + + + + +/** Convert short in [-32768,32767] to GLfloat in [-1.0,1.0] */ +#define SHORT_TO_FLOAT(S) ((2.0F * (S) + 1.0F) * (1.0F/65535.0F)) + +#define UNCLAMPED_FLOAT_TO_SHORT(us, f) \ + us = ( (short) ( CLAMP((f), -1.0, 1.0) * 32767.0F) ) + + + +/*** PIPE_FORMAT_Z16_UNORM ***/ + +/** + * Return each Z value as four floats in [0,1]. + */ +static void +z16_get_tile_rgba(const ushort *src, + unsigned w, unsigned h, + float *p, + unsigned dst_stride) +{ + const float scale = 1.0f / 65535.0f; + unsigned i, j; + + for (i = 0; i < h; i++) { + float *pRow = p; + for (j = 0; j < w; j++, pRow += 4) { + pRow[0] = + pRow[1] = + pRow[2] = + pRow[3] = *src++ * scale; + } + p += dst_stride; + } +} + + + + +/*** PIPE_FORMAT_Z32_UNORM ***/ + +/** + * Return each Z value as four floats in [0,1]. + */ +static void +z32_get_tile_rgba(const unsigned *src, + unsigned w, unsigned h, + float *p, + unsigned dst_stride) +{ + const double scale = 1.0 / (double) 0xffffffff; + unsigned i, j; + + for (i = 0; i < h; i++) { + float *pRow = p; + for (j = 0; j < w; j++, pRow += 4) { + pRow[0] = + pRow[1] = + pRow[2] = + pRow[3] = (float) (*src++ * scale); + } + p += dst_stride; + } +} + + +/*** PIPE_FORMAT_Z24_UNORM_S8_USCALED ***/ + +/** + * Return Z component as four float in [0,1]. Stencil part ignored. + */ +static void +s8z24_get_tile_rgba(const unsigned *src, + unsigned w, unsigned h, + float *p, + unsigned dst_stride) +{ + const double scale = 1.0 / ((1 << 24) - 1); + unsigned i, j; + + for (i = 0; i < h; i++) { + float *pRow = p; + for (j = 0; j < w; j++, pRow += 4) { + pRow[0] = + pRow[1] = + pRow[2] = + pRow[3] = (float) (scale * (*src++ & 0xffffff)); + } + p += dst_stride; + } +} + + +/*** PIPE_FORMAT_S8_USCALED_Z24_UNORM ***/ + +/** + * Return Z component as four float in [0,1]. Stencil part ignored. + */ +static void +z24s8_get_tile_rgba(const unsigned *src, + unsigned w, unsigned h, + float *p, + unsigned dst_stride) +{ + const double scale = 1.0 / ((1 << 24) - 1); + unsigned i, j; + + for (i = 0; i < h; i++) { + float *pRow = p; + for (j = 0; j < w; j++, pRow += 4) { + pRow[0] = + pRow[1] = + pRow[2] = + pRow[3] = (float) (scale * (*src++ >> 8)); + } + p += dst_stride; + } +} + +/*** PIPE_FORMAT_S8X24_USCALED ***/ + +/** + * Return S component as four uint32_t in [0..255]. Z part ignored. + */ +static void +s8x24_get_tile_rgba(const unsigned *src, + unsigned w, unsigned h, + float *p, + unsigned dst_stride) +{ + unsigned i, j; + + for (i = 0; i < h; i++) { + float *pRow = p; + + for (j = 0; j < w; j++, pRow += 4) { + pRow[0] = + pRow[1] = + pRow[2] = + pRow[3] = (float)((*src++ >> 24) & 0xff); + } + + p += dst_stride; + } +} + +/*** PIPE_FORMAT_X24S8_USCALED ***/ + +/** + * Return S component as four uint32_t in [0..255]. Z part ignored. + */ +static void +x24s8_get_tile_rgba(const unsigned *src, + unsigned w, unsigned h, + float *p, + unsigned dst_stride) +{ + unsigned i, j; + + for (i = 0; i < h; i++) { + float *pRow = p; + for (j = 0; j < w; j++, pRow += 4) { + pRow[0] = + pRow[1] = + pRow[2] = + pRow[3] = (float)(*src++ & 0xff); + } + p += dst_stride; + } +} + + +/** + * Return S component as four uint32_t in [0..255]. Z part ignored. + */ +static void +s8_get_tile_rgba(const unsigned char *src, + unsigned w, unsigned h, + float *p, + unsigned dst_stride) +{ + unsigned i, j; + + for (i = 0; i < h; i++) { + float *pRow = p; + for (j = 0; j < w; j++, pRow += 4) { + pRow[0] = + pRow[1] = + pRow[2] = + pRow[3] = (float)(*src++ & 0xff); + } + p += dst_stride; + } +} + +/*** PIPE_FORMAT_Z32_FLOAT ***/ + +/** + * Return each Z value as four floats in [0,1]. + */ +static void +z32f_get_tile_rgba(const float *src, + unsigned w, unsigned h, + float *p, + unsigned dst_stride) +{ + unsigned i, j; + + for (i = 0; i < h; i++) { + float *pRow = p; + for (j = 0; j < w; j++, pRow += 4) { + pRow[0] = + pRow[1] = + pRow[2] = + pRow[3] = *src++; + } + p += dst_stride; + } +} + + +void +pipe_tile_raw_to_rgba(enum pipe_format format, + void *src, + uint w, uint h, + float *dst, unsigned dst_stride) +{ + switch (format) { + case PIPE_FORMAT_Z16_UNORM: + z16_get_tile_rgba((ushort *) src, w, h, dst, dst_stride); + break; + case PIPE_FORMAT_Z32_UNORM: + z32_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride); + break; + case PIPE_FORMAT_Z24_UNORM_S8_USCALED: + case PIPE_FORMAT_Z24X8_UNORM: + s8z24_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride); + break; + case PIPE_FORMAT_S8_USCALED: + s8_get_tile_rgba((unsigned char *) src, w, h, dst, dst_stride); + break; + case PIPE_FORMAT_X24S8_USCALED: + s8x24_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride); + break; + case PIPE_FORMAT_S8_USCALED_Z24_UNORM: + case PIPE_FORMAT_X8Z24_UNORM: + z24s8_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride); + break; + case PIPE_FORMAT_S8X24_USCALED: + x24s8_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride); + break; + case PIPE_FORMAT_Z32_FLOAT: + z32f_get_tile_rgba((float *) src, w, h, dst, dst_stride); + break; + default: + util_format_read_4f(format, + dst, dst_stride * sizeof(float), + src, util_format_get_stride(format, w), + 0, 0, w, h); + } +} + + +void +pipe_get_tile_rgba(struct pipe_context *pipe, + struct pipe_transfer *pt, + uint x, uint y, uint w, uint h, + float *p) +{ + pipe_get_tile_rgba_format(pipe, pt, x, y, w, h, pt->resource->format, p); +} + + +void +pipe_get_tile_rgba_format(struct pipe_context *pipe, + struct pipe_transfer *pt, + uint x, uint y, uint w, uint h, + enum pipe_format format, + float *p) +{ + unsigned dst_stride = w * 4; + void *packed; + + if (u_clip_tile(x, y, &w, &h, &pt->box)) { + return; + } + + packed = MALLOC(util_format_get_nblocks(format, w, h) * util_format_get_blocksize(format)); + if (!packed) { + return; + } + + if (format == PIPE_FORMAT_UYVY || format == PIPE_FORMAT_YUYV) { + assert((x & 1) == 0); + } + + pipe_get_tile_raw(pipe, pt, x, y, w, h, packed, 0); + + pipe_tile_raw_to_rgba(format, packed, w, h, p, dst_stride); + + FREE(packed); +} + + +void +pipe_put_tile_rgba(struct pipe_context *pipe, + struct pipe_transfer *pt, + uint x, uint y, uint w, uint h, + const float *p) +{ + pipe_put_tile_rgba_format(pipe, pt, x, y, w, h, pt->resource->format, p); +} + + +void +pipe_put_tile_rgba_format(struct pipe_context *pipe, + struct pipe_transfer *pt, + uint x, uint y, uint w, uint h, + enum pipe_format format, + const float *p) +{ + unsigned src_stride = w * 4; + void *packed; + + if (u_clip_tile(x, y, &w, &h, &pt->box)) + return; + + packed = MALLOC(util_format_get_nblocks(format, w, h) * util_format_get_blocksize(format)); + + if (!packed) + return; + + switch (format) { + case PIPE_FORMAT_Z16_UNORM: + /*z16_put_tile_rgba((ushort *) packed, w, h, p, src_stride);*/ + break; + case PIPE_FORMAT_Z32_UNORM: + /*z32_put_tile_rgba((unsigned *) packed, w, h, p, src_stride);*/ + break; + case PIPE_FORMAT_Z24_UNORM_S8_USCALED: + case PIPE_FORMAT_Z24X8_UNORM: + /*s8z24_put_tile_rgba((unsigned *) packed, w, h, p, src_stride);*/ + break; + case PIPE_FORMAT_S8_USCALED_Z24_UNORM: + case PIPE_FORMAT_X8Z24_UNORM: + /*z24s8_put_tile_rgba((unsigned *) packed, w, h, p, src_stride);*/ + break; + default: + util_format_write_4f(format, + p, src_stride * sizeof(float), + packed, util_format_get_stride(format, w), + 0, 0, w, h); + } + + pipe_put_tile_raw(pipe, pt, x, y, w, h, packed, 0); + + FREE(packed); +} + + +/** + * Get a block of Z values, converted to 32-bit range. + */ +void +pipe_get_tile_z(struct pipe_context *pipe, + struct pipe_transfer *pt, + uint x, uint y, uint w, uint h, + uint *z) +{ + const uint dstStride = w; + ubyte *map; + uint *pDest = z; + uint i, j; + enum pipe_format format = pt->resource->format; + + if (u_clip_tile(x, y, &w, &h, &pt->box)) + return; + + map = (ubyte *)pipe->transfer_map(pipe, pt); + if (!map) { + assert(0); + return; + } + + switch (format) { + case PIPE_FORMAT_Z32_UNORM: + { + const uint *ptrc + = (const uint *)(map + y * pt->stride + x*4); + for (i = 0; i < h; i++) { + memcpy(pDest, ptrc, 4 * w); + pDest += dstStride; + ptrc += pt->stride/4; + } + } + break; + case PIPE_FORMAT_Z24_UNORM_S8_USCALED: + case PIPE_FORMAT_Z24X8_UNORM: + { + const uint *ptrc + = (const uint *)(map + y * pt->stride + x*4); + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + /* convert 24-bit Z to 32-bit Z */ + pDest[j] = (ptrc[j] << 8) | ((ptrc[j] >> 16) & 0xff); + } + pDest += dstStride; + ptrc += pt->stride/4; + } + } + break; + case PIPE_FORMAT_S8_USCALED_Z24_UNORM: + case PIPE_FORMAT_X8Z24_UNORM: + { + const uint *ptrc + = (const uint *)(map + y * pt->stride + x*4); + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + /* convert 24-bit Z to 32-bit Z */ + pDest[j] = (ptrc[j] & 0xffffff00) | ((ptrc[j] >> 24) & 0xff); + } + pDest += dstStride; + ptrc += pt->stride/4; + } + } + break; + case PIPE_FORMAT_Z16_UNORM: + { + const ushort *ptrc + = (const ushort *)(map + y * pt->stride + x*2); + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + /* convert 16-bit Z to 32-bit Z */ + pDest[j] = (ptrc[j] << 16) | ptrc[j]; + } + pDest += dstStride; + ptrc += pt->stride/2; + } + } + break; + default: + assert(0); + } + + pipe->transfer_unmap(pipe, pt); +} + + +void +pipe_put_tile_z(struct pipe_context *pipe, + struct pipe_transfer *pt, + uint x, uint y, uint w, uint h, + const uint *zSrc) +{ + const uint srcStride = w; + const uint *ptrc = zSrc; + ubyte *map; + uint i, j; + enum pipe_format format = pt->resource->format; + + if (u_clip_tile(x, y, &w, &h, &pt->box)) + return; + + map = (ubyte *)pipe->transfer_map(pipe, pt); + if (!map) { + assert(0); + return; + } + + switch (format) { + case PIPE_FORMAT_Z32_UNORM: + { + uint *pDest = (uint *) (map + y * pt->stride + x*4); + for (i = 0; i < h; i++) { + memcpy(pDest, ptrc, 4 * w); + pDest += pt->stride/4; + ptrc += srcStride; + } + } + break; + case PIPE_FORMAT_Z24_UNORM_S8_USCALED: + { + uint *pDest = (uint *) (map + y * pt->stride + x*4); + /*assert((pt->usage & PIPE_TRANSFER_READ_WRITE) == PIPE_TRANSFER_READ_WRITE);*/ + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + /* convert 32-bit Z to 24-bit Z, preserve stencil */ + pDest[j] = (pDest[j] & 0xff000000) | ptrc[j] >> 8; + } + pDest += pt->stride/4; + ptrc += srcStride; + } + } + break; + case PIPE_FORMAT_Z24X8_UNORM: + { + uint *pDest = (uint *) (map + y * pt->stride + x*4); + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + /* convert 32-bit Z to 24-bit Z (0 stencil) */ + pDest[j] = ptrc[j] >> 8; + } + pDest += pt->stride/4; + ptrc += srcStride; + } + } + break; + case PIPE_FORMAT_S8_USCALED_Z24_UNORM: + { + uint *pDest = (uint *) (map + y * pt->stride + x*4); + /*assert((pt->usage & PIPE_TRANSFER_READ_WRITE) == PIPE_TRANSFER_READ_WRITE);*/ + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + /* convert 32-bit Z to 24-bit Z, preserve stencil */ + pDest[j] = (pDest[j] & 0xff) | (ptrc[j] & 0xffffff00); + } + pDest += pt->stride/4; + ptrc += srcStride; + } + } + break; + case PIPE_FORMAT_X8Z24_UNORM: + { + uint *pDest = (uint *) (map + y * pt->stride + x*4); + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + /* convert 32-bit Z to 24-bit Z (0 stencil) */ + pDest[j] = ptrc[j] & 0xffffff00; + } + pDest += pt->stride/4; + ptrc += srcStride; + } + } + break; + case PIPE_FORMAT_Z16_UNORM: + { + ushort *pDest = (ushort *) (map + y * pt->stride + x*2); + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + /* convert 32-bit Z to 16-bit Z */ + pDest[j] = ptrc[j] >> 16; + } + pDest += pt->stride/2; + ptrc += srcStride; + } + } + break; + default: + assert(0); + } + + pipe->transfer_unmap(pipe, pt); +} + + diff --git a/mesalib/src/gallium/auxiliary/util/u_tile.h b/mesalib/src/gallium/auxiliary/util/u_tile.h new file mode 100644 index 000000000..0abc95e2b --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_tile.h @@ -0,0 +1,126 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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 TUNGSTEN GRAPHICS 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 P_TILE_H +#define P_TILE_H + +#include "pipe/p_compiler.h" +#include "pipe/p_format.h" +#include "pipe/p_state.h" + +struct pipe_context; +struct pipe_transfer; + +/** + * Clip tile against transfer dims. + * + * XXX: this only clips width and height! + * + * \return TRUE if tile is totally clipped, FALSE otherwise + */ +static INLINE boolean +u_clip_tile(uint x, uint y, uint *w, uint *h, const struct pipe_box *box) +{ + if (x >= box->width) + return TRUE; + if (y >= box->height) + return TRUE; + if (x + *w > box->width) + *w = box->width - x; + if (y + *h > box->height) + *h = box->height - y; + return FALSE; +} + +#ifdef __cplusplus +extern "C" { +#endif + +void +pipe_get_tile_raw(struct pipe_context *pipe, + struct pipe_transfer *pt, + uint x, uint y, uint w, uint h, + void *p, int dst_stride); + +void +pipe_put_tile_raw(struct pipe_context *pipe, + struct pipe_transfer *pt, + uint x, uint y, uint w, uint h, + const void *p, int src_stride); + + +void +pipe_get_tile_rgba(struct pipe_context *pipe, + struct pipe_transfer *pt, + uint x, uint y, uint w, uint h, + float *p); + +void +pipe_get_tile_rgba_format(struct pipe_context *pipe, + struct pipe_transfer *pt, + uint x, uint y, uint w, uint h, + enum pipe_format format, + float *p); + +void +pipe_put_tile_rgba(struct pipe_context *pipe, + struct pipe_transfer *pt, + uint x, uint y, uint w, uint h, + const float *p); + +void +pipe_put_tile_rgba_format(struct pipe_context *pipe, + struct pipe_transfer *pt, + uint x, uint y, uint w, uint h, + enum pipe_format format, + const float *p); + + +void +pipe_get_tile_z(struct pipe_context *pipe, + struct pipe_transfer *pt, + uint x, uint y, uint w, uint h, + uint *z); + +void +pipe_put_tile_z(struct pipe_context *pipe, + struct pipe_transfer *pt, + uint x, uint y, uint w, uint h, + const uint *z); + +void +pipe_tile_raw_to_rgba(enum pipe_format format, + void *src, + uint w, uint h, + float *dst, unsigned dst_stride); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/mesalib/src/gallium/auxiliary/util/u_time.h b/mesalib/src/gallium/auxiliary/util/u_time.h new file mode 100644 index 000000000..a65cd59fe --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_time.h @@ -0,0 +1,150 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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 TUNGSTEN GRAPHICS 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 + * OS independent time-manipulation functions. + * + * @author Jose Fonseca + */ + +#ifndef U_TIME_H_ +#define U_TIME_H_ + + +#include "pipe/p_config.h" + +#include "os/os_time.h" + +#include "pipe/p_compiler.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Time abstraction. + * + * Do not access this structure directly. Use the provided function instead. + */ +struct util_time +{ + int64_t counter; +}; + + +PIPE_DEPRECATED +static INLINE void +util_time_get(struct util_time *t) +{ + t->counter = os_time_get(); +} + + +/** + * Return t2 = t1 + usecs + */ +PIPE_DEPRECATED +static INLINE void +util_time_add(const struct util_time *t1, + int64_t usecs, + struct util_time *t2) +{ + t2->counter = t1->counter + usecs; +} + + +/** + * Return difference between times, in microseconds + */ +PIPE_DEPRECATED +static INLINE int64_t +util_time_diff(const struct util_time *t1, + const struct util_time *t2) +{ + return t2->counter - t1->counter; +} + + +/** + * Compare two time values. + * + * Not publicly available because it does not take in account wrap-arounds. + * Use util_time_timeout instead. + */ +static INLINE int +_util_time_compare(const struct util_time *t1, + const struct util_time *t2) +{ + if (t1->counter < t2->counter) + return -1; + else if(t1->counter > t2->counter) + return 1; + else + return 0; +} + + +/** + * Returns non-zero when the timeout expires. + */ +PIPE_DEPRECATED +static INLINE boolean +util_time_timeout(const struct util_time *start, + const struct util_time *end, + const struct util_time *curr) +{ + return os_time_timeout(start->counter, end->counter, curr->counter); +} + + +/** + * Return current time in microseconds + */ +PIPE_DEPRECATED +static INLINE int64_t +util_time_micros(void) +{ + return os_time_get(); +} + + +PIPE_DEPRECATED +static INLINE void +util_time_sleep(int64_t usecs) +{ + os_time_sleep(usecs); +} + + +#ifdef __cplusplus +} +#endif + +#endif /* U_TIME_H_ */ diff --git a/mesalib/src/gallium/auxiliary/util/u_transfer.c b/mesalib/src/gallium/auxiliary/util/u_transfer.c new file mode 100644 index 000000000..772b6d269 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_transfer.c @@ -0,0 +1,114 @@ +#include "pipe/p_context.h" +#include "util/u_rect.h" +#include "util/u_inlines.h" +#include "util/u_transfer.h" +#include "util/u_memory.h" + +/* One-shot transfer operation with data supplied in a user + * pointer. XXX: strides?? + */ +void u_default_transfer_inline_write( struct pipe_context *pipe, + struct pipe_resource *resource, + unsigned level, + unsigned usage, + const struct pipe_box *box, + const void *data, + unsigned stride, + unsigned layer_stride) +{ + struct pipe_transfer *transfer = NULL; + uint8_t *map = NULL; + const uint8_t *src_data = data; + unsigned i; + + transfer = pipe->get_transfer(pipe, + resource, + level, + usage, + box ); + if (transfer == NULL) + goto out; + + map = pipe_transfer_map(pipe, transfer); + if (map == NULL) + goto out; + + for (i = 0; i < box->depth; i++) { + util_copy_rect(map, + resource->format, + transfer->stride, /* bytes */ + 0, 0, + box->width, + box->height, + src_data, + stride, /* bytes */ + 0, 0); + map += transfer->layer_stride; + src_data += layer_stride; + } + +out: + if (map) + pipe_transfer_unmap(pipe, transfer); + + if (transfer) + pipe_transfer_destroy(pipe, transfer); +} + + +boolean u_default_resource_get_handle(struct pipe_screen *screen, + struct pipe_resource *resource, + struct winsys_handle *handle) +{ + return FALSE; +} + + + +void u_default_transfer_flush_region( struct pipe_context *pipe, + struct pipe_transfer *transfer, + const struct pipe_box *box) +{ + /* This is a no-op implementation, nothing to do. + */ +} + +struct pipe_transfer * u_default_get_transfer(struct pipe_context *context, + struct pipe_resource *resource, + unsigned level, + unsigned usage, + const struct pipe_box *box) +{ + struct pipe_transfer *transfer = CALLOC_STRUCT(pipe_transfer); + if (transfer == NULL) + return NULL; + + transfer->resource = resource; + transfer->level = level; + transfer->usage = usage; + transfer->box = *box; + + /* Note strides are zero, this is ok for buffers, but not for + * textures 2d & higher at least. + */ + return transfer; +} + +void u_default_transfer_unmap( struct pipe_context *pipe, + struct pipe_transfer *transfer ) +{ +} + +void u_default_transfer_destroy(struct pipe_context *pipe, + struct pipe_transfer *transfer) +{ + FREE(transfer); +} + +void u_default_redefine_user_buffer(struct pipe_context *ctx, + struct pipe_resource *resource, + unsigned offset, + unsigned size) +{ + resource->width0 = MAX2(resource->width0, offset + size); +} diff --git a/mesalib/src/gallium/auxiliary/util/u_transfer.h b/mesalib/src/gallium/auxiliary/util/u_transfer.h new file mode 100644 index 000000000..79e2d13a4 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_transfer.h @@ -0,0 +1,132 @@ + +#ifndef U_TRANSFER_H +#define U_TRANSFER_H + +/* Fallback implementations for inline read/writes which just go back + * to the regular transfer behaviour. + */ +#include "pipe/p_state.h" + +struct pipe_context; +struct winsys_handle; + +boolean u_default_resource_get_handle(struct pipe_screen *screen, + struct pipe_resource *resource, + struct winsys_handle *handle); + +void u_default_transfer_inline_write( struct pipe_context *pipe, + struct pipe_resource *resource, + unsigned level, + unsigned usage, + const struct pipe_box *box, + const void *data, + unsigned stride, + unsigned layer_stride); + +void u_default_transfer_flush_region( struct pipe_context *pipe, + struct pipe_transfer *transfer, + const struct pipe_box *box); + +struct pipe_transfer * u_default_get_transfer(struct pipe_context *context, + struct pipe_resource *resource, + unsigned level, + unsigned usage, + const struct pipe_box *box); + +void u_default_transfer_unmap( struct pipe_context *pipe, + struct pipe_transfer *transfer ); + +void u_default_transfer_destroy(struct pipe_context *pipe, + struct pipe_transfer *transfer); + + + +/* Useful helper to allow >1 implementation of resource functionality + * to exist in a single driver. This is intended to be transitionary! + */ +struct u_resource_vtbl { + + boolean (*resource_get_handle)(struct pipe_screen *, + struct pipe_resource *tex, + struct winsys_handle *handle); + + void (*resource_destroy)(struct pipe_screen *, + struct pipe_resource *pt); + + struct pipe_transfer *(*get_transfer)(struct pipe_context *, + struct pipe_resource *resource, + unsigned level, + unsigned usage, + const struct pipe_box *); + + void (*transfer_destroy)(struct pipe_context *, + struct pipe_transfer *); + + void *(*transfer_map)( struct pipe_context *, + struct pipe_transfer *transfer ); + + void (*transfer_flush_region)( struct pipe_context *, + struct pipe_transfer *transfer, + const struct pipe_box *); + + void (*transfer_unmap)( struct pipe_context *, + struct pipe_transfer *transfer ); + + void (*transfer_inline_write)( struct pipe_context *pipe, + struct pipe_resource *resource, + unsigned level, + unsigned usage, + const struct pipe_box *box, + const void *data, + unsigned stride, + unsigned layer_stride); +}; + + +struct u_resource { + struct pipe_resource b; + const struct u_resource_vtbl *vtbl; +}; + + +boolean u_resource_get_handle_vtbl(struct pipe_screen *screen, + struct pipe_resource *resource, + struct winsys_handle *handle); + +void u_resource_destroy_vtbl(struct pipe_screen *screen, + struct pipe_resource *resource); + +struct pipe_transfer *u_get_transfer_vtbl(struct pipe_context *context, + struct pipe_resource *resource, + unsigned level, + unsigned usage, + const struct pipe_box *box); + +void u_transfer_destroy_vtbl(struct pipe_context *pipe, + struct pipe_transfer *transfer); + +void *u_transfer_map_vtbl( struct pipe_context *pipe, + struct pipe_transfer *transfer ); + +void u_transfer_flush_region_vtbl( struct pipe_context *pipe, + struct pipe_transfer *transfer, + const struct pipe_box *box); + +void u_transfer_unmap_vtbl( struct pipe_context *rm_ctx, + struct pipe_transfer *transfer ); + +void u_transfer_inline_write_vtbl( struct pipe_context *rm_ctx, + struct pipe_resource *resource, + unsigned level, + unsigned usage, + const struct pipe_box *box, + const void *data, + unsigned stride, + unsigned layer_stride); + +void u_default_redefine_user_buffer(struct pipe_context *ctx, + struct pipe_resource *resource, + unsigned offset, + unsigned size); + +#endif diff --git a/mesalib/src/gallium/auxiliary/util/u_upload_mgr.c b/mesalib/src/gallium/auxiliary/util/u_upload_mgr.c new file mode 100644 index 000000000..e2e7829fb --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_upload_mgr.c @@ -0,0 +1,251 @@ +/************************************************************************** + * + * 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. + * + **************************************************************************/ + +/* Helper utility for uploading user buffers & other data, and + * coalescing small buffers into larger ones. + */ + +#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 "u_upload_mgr.h" + + +struct u_upload_mgr { + struct pipe_context *pipe; + + unsigned default_size; /* Minimum size of the upload buffer, in bytes. */ + unsigned alignment; /* Alignment of each sub-allocation. */ + unsigned bind; /* Bitmask of PIPE_BIND_* flags. */ + + struct pipe_resource *buffer; /* Upload buffer. */ + struct pipe_transfer *transfer; /* Transfer object for the upload buffer. */ + uint8_t *map; /* Pointer to the mapped upload buffer. */ + unsigned size; /* Actual size of the upload buffer. */ + unsigned offset; /* Aligned offset to the upload buffer, pointing + * at the first unused byte. */ +}; + + +struct u_upload_mgr *u_upload_create( struct pipe_context *pipe, + unsigned default_size, + unsigned alignment, + unsigned bind ) +{ + struct u_upload_mgr *upload = CALLOC_STRUCT( u_upload_mgr ); + if (!upload) + return NULL; + + upload->pipe = pipe; + upload->default_size = default_size; + upload->alignment = alignment; + upload->bind = bind; + upload->buffer = NULL; + + return upload; +} + +/* Release old buffer. + * + * This must usually be called prior to firing the command stream + * which references the upload buffer, as many memory managers will + * cause subsequent maps of a fired buffer to wait. + * + * Can improve this with a change to pipe_buffer_write to use the + * DONT_WAIT bit, but for now, it's easiest just to grab a new buffer. + */ +void u_upload_flush( struct u_upload_mgr *upload ) +{ + /* Unmap and unreference the upload buffer. */ + if (upload->transfer) { + if (upload->offset) { + pipe_buffer_flush_mapped_range(upload->pipe, upload->transfer, + 0, upload->offset); + } + pipe_transfer_unmap(upload->pipe, upload->transfer); + pipe_transfer_destroy(upload->pipe, upload->transfer); + upload->transfer = NULL; + } + pipe_resource_reference( &upload->buffer, NULL ); + upload->size = 0; +} + + +void u_upload_destroy( struct u_upload_mgr *upload ) +{ + u_upload_flush( upload ); + FREE( upload ); +} + + +static enum pipe_error +u_upload_alloc_buffer( struct u_upload_mgr *upload, + unsigned min_size ) +{ + unsigned size; + + /* Release the old buffer, if present: + */ + u_upload_flush( upload ); + + /* Allocate a new one: + */ + size = align(MAX2(upload->default_size, min_size), 4096); + + upload->buffer = pipe_buffer_create( upload->pipe->screen, + upload->bind, + PIPE_USAGE_STREAM, + size ); + if (upload->buffer == NULL) + goto fail; + + /* Map the new buffer. */ + upload->map = pipe_buffer_map_range(upload->pipe, upload->buffer, + 0, size, + PIPE_TRANSFER_WRITE | + PIPE_TRANSFER_FLUSH_EXPLICIT, + &upload->transfer); + + upload->size = size; + + upload->offset = 0; + return 0; + +fail: + if (upload->buffer) + pipe_resource_reference( &upload->buffer, NULL ); + + return PIPE_ERROR_OUT_OF_MEMORY; +} + +enum pipe_error u_upload_alloc( struct u_upload_mgr *upload, + unsigned min_out_offset, + unsigned size, + unsigned *out_offset, + struct pipe_resource **outbuf, + boolean *flushed, + void **ptr ) +{ + unsigned alloc_size = align( size, upload->alignment ); + unsigned alloc_offset = align(min_out_offset, upload->alignment); + unsigned offset; + + /* Make sure we have enough space in the upload buffer + * for the sub-allocation. */ + if (MAX2(upload->offset, alloc_offset) + alloc_size > upload->size) { + enum pipe_error ret = u_upload_alloc_buffer(upload, + alloc_offset + alloc_size); + if (ret) + return ret; + + *flushed = TRUE; + } else { + *flushed = FALSE; + } + + offset = MAX2(upload->offset, alloc_offset); + + assert(offset < upload->buffer->width0); + assert(offset + size <= upload->buffer->width0); + assert(size); + + /* Emit the return values: */ + *ptr = upload->map + offset; + pipe_resource_reference( outbuf, upload->buffer ); + *out_offset = offset; + + upload->offset = offset + alloc_size; + return PIPE_OK; +} + +enum pipe_error u_upload_data( struct u_upload_mgr *upload, + unsigned min_out_offset, + unsigned size, + const void *data, + unsigned *out_offset, + struct pipe_resource **outbuf, + boolean *flushed ) +{ + uint8_t *ptr; + enum pipe_error ret = u_upload_alloc(upload, min_out_offset, size, + out_offset, outbuf, flushed, + (void**)&ptr); + if (ret) + return ret; + + memcpy(ptr, data, size); + return PIPE_OK; +} + + +/* As above, but upload the full contents of a buffer. Useful for + * uploading user buffers, avoids generating an explosion of GPU + * buffers if you have an app that does lots of small vertex buffer + * renders or DrawElements calls. + */ +enum pipe_error u_upload_buffer( struct u_upload_mgr *upload, + unsigned min_out_offset, + unsigned offset, + unsigned size, + struct pipe_resource *inbuf, + unsigned *out_offset, + struct pipe_resource **outbuf, + boolean *flushed ) +{ + enum pipe_error ret = PIPE_OK; + struct pipe_transfer *transfer = NULL; + const char *map = NULL; + + map = (const char *)pipe_buffer_map(upload->pipe, + inbuf, + PIPE_TRANSFER_READ, + &transfer); + + if (map == NULL) { + ret = PIPE_ERROR_OUT_OF_MEMORY; + goto done; + } + + if (0) + debug_printf("upload ptr %p ofs %d sz %d\n", map, offset, size); + + ret = u_upload_data( upload, + min_out_offset, + size, + map + offset, + out_offset, + outbuf, flushed ); + +done: + if (map) + pipe_buffer_unmap( upload->pipe, transfer ); + + return ret; +} diff --git a/mesalib/src/gallium/auxiliary/util/u_upload_mgr.h b/mesalib/src/gallium/auxiliary/util/u_upload_mgr.h new file mode 100644 index 000000000..ed13fbe82 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_upload_mgr.h @@ -0,0 +1,122 @@ +/************************************************************************** + * + * 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. + * + **************************************************************************/ + +/* Helper utility for uploading user buffers & other data, and + * coalescing small buffers into larger ones. + */ + +#ifndef U_UPLOAD_MGR_H +#define U_UPLOAD_MGR_H + +#include "pipe/p_compiler.h" + +struct pipe_context; +struct pipe_resource; + + +/** + * Create the upload manager. + * + * \param pipe Pipe driver. + * \param default_size Minimum size of the upload buffer, in bytes. + * \param alignment Alignment of each suballocation in the upload buffer. + * \param bind Bitmask of PIPE_BIND_* flags. + */ +struct u_upload_mgr *u_upload_create( struct pipe_context *pipe, + unsigned default_size, + unsigned alignment, + unsigned bind ); + +/** + * Destroy the upload manager. + */ +void u_upload_destroy( struct u_upload_mgr *upload ); + +/* Unmap and release old buffer. + * + * This must usually be called prior to firing the command stream + * which references the upload buffer, as many memory managers either + * don't like firing a mapped buffer or cause subsequent maps of a + * fired buffer to wait. For now, it's easiest just to grab a new + * buffer. + */ +void u_upload_flush( struct u_upload_mgr *upload ); + +/** + * Sub-allocate new memory from the upload buffer. + * + * \param upload Upload manager + * \param min_out_offset Minimum offset that should be returned in out_offset. + * \param size Size of the allocation. + * \param out_offset Pointer to where the new buffer offset will be returned. + * \param outbuf Pointer to where the upload buffer will be returned. + * \param flushed Whether the upload buffer was flushed. + * \param ptr Pointer to the allocated memory that is returned. + */ +enum pipe_error u_upload_alloc( struct u_upload_mgr *upload, + unsigned min_out_offset, + unsigned size, + unsigned *out_offset, + struct pipe_resource **outbuf, + boolean *flushed, + void **ptr ); + + +/** + * Allocate and write data to the upload buffer. + * + * Same as u_upload_alloc, but in addition to that, it copies "data" + * to the pointer returned from u_upload_alloc. + */ +enum pipe_error u_upload_data( struct u_upload_mgr *upload, + unsigned min_out_offset, + unsigned size, + const void *data, + unsigned *out_offset, + struct pipe_resource **outbuf, + boolean *flushed ); + + +/** + * Allocate and copy an input buffer to the upload buffer. + * + * Same as u_upload_data, except that the input data comes from a buffer + * instead of a user pointer. + */ +enum pipe_error u_upload_buffer( struct u_upload_mgr *upload, + unsigned min_out_offset, + unsigned offset, + unsigned size, + struct pipe_resource *inbuf, + unsigned *out_offset, + struct pipe_resource **outbuf, + boolean *flushed ); + + + +#endif + diff --git a/mesalib/src/gallium/auxiliary/util/u_vbuf_mgr.c b/mesalib/src/gallium/auxiliary/util/u_vbuf_mgr.c new file mode 100644 index 000000000..9306fcd5c --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_vbuf_mgr.c @@ -0,0 +1,613 @@ +/************************************************************************** + * + * Copyright 2011 Marek Olšák + * 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 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. + * + **************************************************************************/ + +#include "util/u_vbuf_mgr.h" + +#include "util/u_format.h" +#include "util/u_inlines.h" +#include "util/u_memory.h" +#include "util/u_upload_mgr.h" +#include "translate/translate.h" +#include "translate/translate_cache.h" + +/* Hardware vertex fetcher limitations can be described by this structure. */ +struct u_vbuf_caps { + /* Vertex format CAPs. */ + /* TRUE if hardware supports it. */ + unsigned format_fixed32:1; /* PIPE_FORMAT_*32*_FIXED */ + unsigned format_float16:1; /* PIPE_FORMAT_*16*_FLOAT */ + unsigned format_float64:1; /* PIPE_FORMAT_*64*_FLOAT */ + unsigned format_norm32:1; /* PIPE_FORMAT_*32*NORM */ + unsigned format_scaled32:1; /* PIPE_FORMAT_*32*SCALED */ + + /* Whether vertex fetches don't have to be dword-aligned. */ + /* TRUE if hardware supports it. */ + unsigned fetch_dword_unaligned:1; +}; + +struct u_vbuf_mgr_elements { + unsigned count; + struct pipe_vertex_element ve[PIPE_MAX_ATTRIBS]; + + /* If (velem[i].src_format != real_format[i]), the vertex buffer + * referenced by the vertex element cannot be used for rendering and + * its vertex data must be translated to real_format[i]. */ + enum pipe_format native_format[PIPE_MAX_ATTRIBS]; + unsigned native_format_size[PIPE_MAX_ATTRIBS]; + + /* This might mean two things: + * - src_format != native_format, as discussed above. + * - src_offset % 4 != 0 (if the caps don't allow such an offset). */ + boolean incompatible_layout; +}; + +struct u_vbuf_mgr_priv { + struct u_vbuf_mgr b; + struct u_vbuf_caps caps; + struct pipe_context *pipe; + + struct translate_cache *translate_cache; + unsigned translate_vb_slot; + + struct u_vbuf_mgr_elements *ve; + void *saved_ve, *fallback_ve; + boolean ve_binding_lock; + + boolean any_user_vbs; + boolean incompatible_vb_layout; +}; + +static void u_vbuf_mgr_init_format_caps(struct u_vbuf_mgr_priv *mgr) +{ + struct pipe_screen *screen = mgr->pipe->screen; + + mgr->caps.format_fixed32 = + screen->is_format_supported(screen, PIPE_FORMAT_R32_FIXED, PIPE_BUFFER, + 0, PIPE_BIND_VERTEX_BUFFER); + + mgr->caps.format_float16 = + screen->is_format_supported(screen, PIPE_FORMAT_R16_FLOAT, PIPE_BUFFER, + 0, PIPE_BIND_VERTEX_BUFFER); + + mgr->caps.format_float64 = + screen->is_format_supported(screen, PIPE_FORMAT_R64_FLOAT, PIPE_BUFFER, + 0, PIPE_BIND_VERTEX_BUFFER); + + mgr->caps.format_norm32 = + screen->is_format_supported(screen, PIPE_FORMAT_R32_UNORM, PIPE_BUFFER, + 0, PIPE_BIND_VERTEX_BUFFER) && + screen->is_format_supported(screen, PIPE_FORMAT_R32_SNORM, PIPE_BUFFER, + 0, PIPE_BIND_VERTEX_BUFFER); + + mgr->caps.format_scaled32 = + screen->is_format_supported(screen, PIPE_FORMAT_R32_USCALED, PIPE_BUFFER, + 0, PIPE_BIND_VERTEX_BUFFER) && + screen->is_format_supported(screen, PIPE_FORMAT_R32_SSCALED, PIPE_BUFFER, + 0, PIPE_BIND_VERTEX_BUFFER); +} + +struct u_vbuf_mgr * +u_vbuf_mgr_create(struct pipe_context *pipe, + unsigned upload_buffer_size, + unsigned upload_buffer_alignment, + unsigned upload_buffer_bind, + enum u_fetch_alignment fetch_alignment) +{ + struct u_vbuf_mgr_priv *mgr = CALLOC_STRUCT(u_vbuf_mgr_priv); + + mgr->pipe = pipe; + mgr->translate_cache = translate_cache_create(); + + mgr->b.uploader = u_upload_create(pipe, upload_buffer_size, + upload_buffer_alignment, + upload_buffer_bind); + + mgr->caps.fetch_dword_unaligned = + fetch_alignment == U_VERTEX_FETCH_BYTE_ALIGNED; + + u_vbuf_mgr_init_format_caps(mgr); + + return &mgr->b; +} + +void u_vbuf_mgr_destroy(struct u_vbuf_mgr *mgrb) +{ + struct u_vbuf_mgr_priv *mgr = (struct u_vbuf_mgr_priv*)mgrb; + unsigned i; + + for (i = 0; i < mgr->b.nr_real_vertex_buffers; i++) { + pipe_resource_reference(&mgr->b.vertex_buffer[i].buffer, NULL); + pipe_resource_reference(&mgr->b.real_vertex_buffer[i], NULL); + } + + translate_cache_destroy(mgr->translate_cache); + u_upload_destroy(mgr->b.uploader); + FREE(mgr); +} + + +static void u_vbuf_translate_begin(struct u_vbuf_mgr_priv *mgr, + int min_index, int max_index, + boolean *upload_flushed) +{ + struct translate_key key; + struct translate_element *te; + unsigned tr_elem_index[PIPE_MAX_ATTRIBS]; + struct translate *tr; + boolean vb_translated[PIPE_MAX_ATTRIBS] = {0}; + uint8_t *vb_map[PIPE_MAX_ATTRIBS] = {0}, *out_map; + struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS] = {0}; + struct pipe_resource *out_buffer = NULL; + unsigned i, num_verts, out_offset; + struct pipe_vertex_element new_velems[PIPE_MAX_ATTRIBS]; + + memset(&key, 0, sizeof(key)); + memset(tr_elem_index, 0xff, sizeof(tr_elem_index)); + + /* Initialize the translate key, i.e. the recipe how vertices should be + * translated. */ + memset(&key, 0, sizeof key); + for (i = 0; i < mgr->ve->count; i++) { + struct pipe_vertex_buffer *vb = + &mgr->b.vertex_buffer[mgr->ve->ve[i].vertex_buffer_index]; + enum pipe_format output_format = mgr->ve->native_format[i]; + unsigned output_format_size = mgr->ve->native_format_size[i]; + + /* Check for support. */ + if (mgr->ve->ve[i].src_format == mgr->ve->native_format[i] && + (mgr->caps.fetch_dword_unaligned || + (vb->buffer_offset % 4 == 0 && + vb->stride % 4 == 0 && + mgr->ve->ve[i].src_offset % 4 == 0))) { + continue; + } + + /* Workaround for translate: output floats instead of halfs. */ + switch (output_format) { + case PIPE_FORMAT_R16_FLOAT: + output_format = PIPE_FORMAT_R32_FLOAT; + output_format_size = 4; + break; + case PIPE_FORMAT_R16G16_FLOAT: + output_format = PIPE_FORMAT_R32G32_FLOAT; + output_format_size = 8; + break; + case PIPE_FORMAT_R16G16B16_FLOAT: + output_format = PIPE_FORMAT_R32G32B32_FLOAT; + output_format_size = 12; + break; + case PIPE_FORMAT_R16G16B16A16_FLOAT: + output_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + output_format_size = 16; + break; + default:; + } + + /* Add this vertex element. */ + te = &key.element[key.nr_elements]; + /*te->type; + te->instance_divisor;*/ + te->input_buffer = mgr->ve->ve[i].vertex_buffer_index; + te->input_format = mgr->ve->ve[i].src_format; + te->input_offset = mgr->ve->ve[i].src_offset; + te->output_format = output_format; + te->output_offset = key.output_stride; + + key.output_stride += output_format_size; + vb_translated[mgr->ve->ve[i].vertex_buffer_index] = TRUE; + tr_elem_index[i] = key.nr_elements; + key.nr_elements++; + } + + /* Get a translate object. */ + tr = translate_cache_find(mgr->translate_cache, &key); + + /* Map buffers we want to translate. */ + for (i = 0; i < mgr->b.nr_vertex_buffers; i++) { + if (vb_translated[i]) { + struct pipe_vertex_buffer *vb = &mgr->b.vertex_buffer[i]; + + vb_map[i] = pipe_buffer_map(mgr->pipe, vb->buffer, + PIPE_TRANSFER_READ, &vb_transfer[i]); + + tr->set_buffer(tr, i, + vb_map[i] + vb->buffer_offset + vb->stride * min_index, + vb->stride, ~0); + } + } + + /* Create and map the output buffer. */ + num_verts = max_index + 1 - min_index; + + u_upload_alloc(mgr->b.uploader, + key.output_stride * min_index, + key.output_stride * num_verts, + &out_offset, &out_buffer, upload_flushed, + (void**)&out_map); + + out_offset -= key.output_stride * min_index; + + /* Translate. */ + tr->run(tr, 0, num_verts, 0, out_map); + + /* Unmap all buffers. */ + for (i = 0; i < mgr->b.nr_vertex_buffers; i++) { + if (vb_translated[i]) { + pipe_buffer_unmap(mgr->pipe, vb_transfer[i]); + } + } + + /* Setup the new vertex buffer in the first free slot. */ + mgr->translate_vb_slot = ~0; + for (i = 0; i < PIPE_MAX_ATTRIBS; i++) { + if (!mgr->b.vertex_buffer[i].buffer) { + mgr->translate_vb_slot = i; + + if (i >= mgr->b.nr_vertex_buffers) { + mgr->b.nr_real_vertex_buffers = i+1; + } + break; + } + } + + if (mgr->translate_vb_slot != ~0) { + /* Setup the new vertex buffer. */ + pipe_resource_reference( + &mgr->b.real_vertex_buffer[mgr->translate_vb_slot], out_buffer); + mgr->b.vertex_buffer[mgr->translate_vb_slot].buffer_offset = out_offset; + mgr->b.vertex_buffer[mgr->translate_vb_slot].stride = key.output_stride; + + /* Setup new vertex elements. */ + for (i = 0; i < mgr->ve->count; i++) { + if (tr_elem_index[i] < key.nr_elements) { + te = &key.element[tr_elem_index[i]]; + new_velems[i].instance_divisor = mgr->ve->ve[i].instance_divisor; + new_velems[i].src_format = te->output_format; + new_velems[i].src_offset = te->output_offset; + new_velems[i].vertex_buffer_index = mgr->translate_vb_slot; + } else { + memcpy(&new_velems[i], &mgr->ve->ve[i], + sizeof(struct pipe_vertex_element)); + } + } + + mgr->fallback_ve = + mgr->pipe->create_vertex_elements_state(mgr->pipe, mgr->ve->count, + new_velems); + + /* Preserve saved_ve. */ + mgr->ve_binding_lock = TRUE; + mgr->pipe->bind_vertex_elements_state(mgr->pipe, mgr->fallback_ve); + mgr->ve_binding_lock = FALSE; + } + + pipe_resource_reference(&out_buffer, NULL); +} + +static void u_vbuf_translate_end(struct u_vbuf_mgr_priv *mgr) +{ + if (mgr->fallback_ve == NULL) { + return; + } + + /* Restore vertex elements. */ + /* Note that saved_ve will be overwritten in bind_vertex_elements_state. */ + mgr->pipe->bind_vertex_elements_state(mgr->pipe, mgr->saved_ve); + mgr->pipe->delete_vertex_elements_state(mgr->pipe, mgr->fallback_ve); + mgr->fallback_ve = NULL; + + /* Delete the now-unused VBO. */ + pipe_resource_reference(&mgr->b.real_vertex_buffer[mgr->translate_vb_slot], + NULL); + mgr->b.nr_real_vertex_buffers = mgr->b.nr_vertex_buffers; +} + +#define FORMAT_REPLACE(what, withwhat) \ + case PIPE_FORMAT_##what: format = PIPE_FORMAT_##withwhat; break + +struct u_vbuf_mgr_elements * +u_vbuf_mgr_create_vertex_elements(struct u_vbuf_mgr *mgrb, + unsigned count, + const struct pipe_vertex_element *attribs, + struct pipe_vertex_element *native_attribs) +{ + struct u_vbuf_mgr_priv *mgr = (struct u_vbuf_mgr_priv*)mgrb; + unsigned i; + struct u_vbuf_mgr_elements *ve = CALLOC_STRUCT(u_vbuf_mgr_elements); + + ve->count = count; + + if (!count) { + return ve; + } + + memcpy(ve->ve, attribs, sizeof(struct pipe_vertex_element) * count); + memcpy(native_attribs, attribs, sizeof(struct pipe_vertex_element) * count); + + /* Set the best native format in case the original format is not + * supported. */ + for (i = 0; i < count; i++) { + enum pipe_format format = ve->ve[i].src_format; + + /* Choose a native format. + * For now we don't care about the alignment, that's going to + * be sorted out later. */ + if (!mgr->caps.format_fixed32) { + switch (format) { + FORMAT_REPLACE(R32_FIXED, R32_FLOAT); + FORMAT_REPLACE(R32G32_FIXED, R32G32_FLOAT); + FORMAT_REPLACE(R32G32B32_FIXED, R32G32B32_FLOAT); + FORMAT_REPLACE(R32G32B32A32_FIXED, R32G32B32A32_FLOAT); + default:; + } + } + if (!mgr->caps.format_float16) { + switch (format) { + FORMAT_REPLACE(R16_FLOAT, R32_FLOAT); + FORMAT_REPLACE(R16G16_FLOAT, R32G32_FLOAT); + FORMAT_REPLACE(R16G16B16_FLOAT, R32G32B32_FLOAT); + FORMAT_REPLACE(R16G16B16A16_FLOAT, R32G32B32A32_FLOAT); + default:; + } + } + if (!mgr->caps.format_float64) { + switch (format) { + FORMAT_REPLACE(R64_FLOAT, R32_FLOAT); + FORMAT_REPLACE(R64G64_FLOAT, R32G32_FLOAT); + FORMAT_REPLACE(R64G64B64_FLOAT, R32G32B32_FLOAT); + FORMAT_REPLACE(R64G64B64A64_FLOAT, R32G32B32A32_FLOAT); + default:; + } + } + if (!mgr->caps.format_norm32) { + switch (format) { + FORMAT_REPLACE(R32_UNORM, R32_FLOAT); + FORMAT_REPLACE(R32G32_UNORM, R32G32_FLOAT); + FORMAT_REPLACE(R32G32B32_UNORM, R32G32B32_FLOAT); + FORMAT_REPLACE(R32G32B32A32_UNORM, R32G32B32A32_FLOAT); + FORMAT_REPLACE(R32_SNORM, R32_FLOAT); + FORMAT_REPLACE(R32G32_SNORM, R32G32_FLOAT); + FORMAT_REPLACE(R32G32B32_SNORM, R32G32B32_FLOAT); + FORMAT_REPLACE(R32G32B32A32_SNORM, R32G32B32A32_FLOAT); + default:; + } + } + if (!mgr->caps.format_scaled32) { + switch (format) { + FORMAT_REPLACE(R32_USCALED, R32_FLOAT); + FORMAT_REPLACE(R32G32_USCALED, R32G32_FLOAT); + FORMAT_REPLACE(R32G32B32_USCALED, R32G32B32_FLOAT); + FORMAT_REPLACE(R32G32B32A32_USCALED,R32G32B32A32_FLOAT); + FORMAT_REPLACE(R32_SSCALED, R32_FLOAT); + FORMAT_REPLACE(R32G32_SSCALED, R32G32_FLOAT); + FORMAT_REPLACE(R32G32B32_SSCALED, R32G32B32_FLOAT); + FORMAT_REPLACE(R32G32B32A32_SSCALED,R32G32B32A32_FLOAT); + default:; + } + } + + native_attribs[i].src_format = format; + ve->native_format[i] = format; + ve->native_format_size[i] = + util_format_get_blocksize(ve->native_format[i]); + + ve->incompatible_layout = + ve->incompatible_layout || + ve->ve[i].src_format != ve->native_format[i] || + (!mgr->caps.fetch_dword_unaligned && ve->ve[i].src_offset % 4 != 0); + } + + /* Align the formats to the size of DWORD if needed. */ + if (!mgr->caps.fetch_dword_unaligned) { + for (i = 0; i < count; i++) { + ve->native_format_size[i] = align(ve->native_format_size[i], 4); + } + } + + return ve; +} + +void u_vbuf_mgr_bind_vertex_elements(struct u_vbuf_mgr *mgrb, + void *cso, + struct u_vbuf_mgr_elements *ve) +{ + struct u_vbuf_mgr_priv *mgr = (struct u_vbuf_mgr_priv*)mgrb; + + if (!cso) { + return; + } + + if (!mgr->ve_binding_lock) { + mgr->saved_ve = cso; + mgr->ve = ve; + } +} + +void u_vbuf_mgr_destroy_vertex_elements(struct u_vbuf_mgr *mgr, + struct u_vbuf_mgr_elements *ve) +{ + FREE(ve); +} + +void u_vbuf_mgr_set_vertex_buffers(struct u_vbuf_mgr *mgrb, + unsigned count, + const struct pipe_vertex_buffer *bufs) +{ + struct u_vbuf_mgr_priv *mgr = (struct u_vbuf_mgr_priv*)mgrb; + unsigned i; + + mgr->b.max_index = ~0; + mgr->any_user_vbs = FALSE; + mgr->incompatible_vb_layout = FALSE; + + if (!mgr->caps.fetch_dword_unaligned) { + /* Check if the strides and offsets are aligned to the size of DWORD. */ + for (i = 0; i < count; i++) { + if (bufs[i].buffer) { + if (bufs[i].stride % 4 != 0 || + bufs[i].buffer_offset % 4 != 0) { + mgr->incompatible_vb_layout = TRUE; + break; + } + } + } + } + + for (i = 0; i < count; i++) { + const struct pipe_vertex_buffer *vb = &bufs[i]; + + pipe_resource_reference(&mgr->b.vertex_buffer[i].buffer, vb->buffer); + pipe_resource_reference(&mgr->b.real_vertex_buffer[i], NULL); + + if (u_vbuf_resource(vb->buffer)->user_ptr) { + mgr->any_user_vbs = TRUE; + continue; + } + + pipe_resource_reference(&mgr->b.real_vertex_buffer[i], vb->buffer); + + /* The stride of zero means we will be fetching only the first + * vertex, so don't care about max_index. */ + if (!vb->stride) { + continue; + } + + /* Update the maximum index. */ + mgr->b.max_index = + MIN2(mgr->b.max_index, + (vb->buffer->width0 - vb->buffer_offset) / vb->stride - 1); + } + + for (; i < mgr->b.nr_real_vertex_buffers; i++) { + pipe_resource_reference(&mgr->b.vertex_buffer[i].buffer, NULL); + pipe_resource_reference(&mgr->b.real_vertex_buffer[i], NULL); + } + + memcpy(mgr->b.vertex_buffer, bufs, + sizeof(struct pipe_vertex_buffer) * count); + + mgr->b.nr_vertex_buffers = count; + mgr->b.nr_real_vertex_buffers = count; +} + +static void u_vbuf_upload_buffers(struct u_vbuf_mgr_priv *mgr, + int min_index, int max_index, + unsigned instance_count, + boolean *upload_flushed) +{ + int i, nr = mgr->ve->count; + unsigned count = max_index + 1 - min_index; + boolean uploaded[PIPE_MAX_ATTRIBS] = {0}; + + for (i = 0; i < nr; i++) { + unsigned index = mgr->ve->ve[i].vertex_buffer_index; + struct pipe_vertex_buffer *vb = &mgr->b.vertex_buffer[index]; + + if (vb->buffer && + u_vbuf_resource(vb->buffer)->user_ptr && + !uploaded[index]) { + unsigned first, size; + boolean flushed; + unsigned instance_div = mgr->ve->ve[i].instance_divisor; + + if (instance_div) { + first = 0; + size = vb->stride * + ((instance_count + instance_div - 1) / instance_div); + } else if (vb->stride) { + first = vb->stride * min_index; + size = vb->stride * count; + } else { + first = 0; + size = mgr->ve->native_format_size[i]; + } + + u_upload_data(mgr->b.uploader, first, size, + u_vbuf_resource(vb->buffer)->user_ptr + first, + &vb->buffer_offset, + &mgr->b.real_vertex_buffer[index], + &flushed); + + vb->buffer_offset -= first; + + uploaded[index] = TRUE; + *upload_flushed = *upload_flushed || flushed; + } else { + assert(mgr->b.real_vertex_buffer[index]); + } + } +} + +void u_vbuf_mgr_draw_begin(struct u_vbuf_mgr *mgrb, + const struct pipe_draw_info *info, + boolean *buffers_updated, + boolean *uploader_flushed) +{ + struct u_vbuf_mgr_priv *mgr = (struct u_vbuf_mgr_priv*)mgrb; + boolean bufs_updated = FALSE, upload_flushed = FALSE; + int min_index, max_index; + + min_index = info->min_index - info->index_bias; + if (info->max_index == ~0) { + max_index = mgr->b.max_index; + } else { + max_index = MIN2(info->max_index - info->index_bias, mgr->b.max_index); + } + + /* Translate vertices with non-native layouts or formats. */ + if (mgr->incompatible_vb_layout || mgr->ve->incompatible_layout) { + u_vbuf_translate_begin(mgr, min_index, max_index, &upload_flushed); + + if (mgr->fallback_ve) { + bufs_updated = TRUE; + } + } + + /* Upload user buffers. */ + if (mgr->any_user_vbs) { + u_vbuf_upload_buffers(mgr, min_index, max_index, info->instance_count, + &upload_flushed); + bufs_updated = TRUE; + } + + /* Set the return values. */ + if (buffers_updated) { + *buffers_updated = bufs_updated; + } + if (uploader_flushed) { + *uploader_flushed = upload_flushed; + } +} + +void u_vbuf_mgr_draw_end(struct u_vbuf_mgr *mgrb) +{ + struct u_vbuf_mgr_priv *mgr = (struct u_vbuf_mgr_priv*)mgrb; + + if (mgr->fallback_ve) { + u_vbuf_translate_end(mgr); + } +} diff --git a/mesalib/src/gallium/auxiliary/util/u_vbuf_mgr.h b/mesalib/src/gallium/auxiliary/util/u_vbuf_mgr.h new file mode 100644 index 000000000..0ef27744c --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_vbuf_mgr.h @@ -0,0 +1,121 @@ +/************************************************************************** + * + * Copyright 2011 Marek Olšák + * 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 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. + * + **************************************************************************/ + +#ifndef U_VBUF_MGR_H +#define U_VBUF_MGR_H + +/* This module builds upon u_upload_mgr and translate_cache and takes care of + * user buffer uploads and vertex format fallbacks. It's designed + * for the drivers which don't always use the Draw module. (e.g. for HWTCL) + */ + +#include "pipe/p_context.h" +#include "pipe/p_state.h" +#include "util/u_transfer.h" + +/* The manager. + * This structure should also be used to access vertex buffers + * from a driver. */ +struct u_vbuf_mgr { + /* This is what was set in set_vertex_buffers. + * May contain user buffers. */ + struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS]; + unsigned nr_vertex_buffers; + + /* Contains only real vertex buffers. + * Hardware drivers should use real_vertex_buffers[i] + * instead of vertex_buffers[i].buffer. */ + struct pipe_resource *real_vertex_buffer[PIPE_MAX_ATTRIBS]; + int nr_real_vertex_buffers; + + /* Precomputed max_index for hardware vertex buffers. */ + unsigned max_index; + + /* This uploader can optionally be used by the driver. + * + * Allowed functions: + * - u_upload_alloc + * - u_upload_data + * - u_upload_buffer + * - u_upload_flush */ + struct u_upload_mgr *uploader; +}; + +struct u_vbuf_resource { + struct u_resource b; + uint8_t *user_ptr; +}; + +/* Opaque type containing information about vertex elements for the manager. */ +struct u_vbuf_mgr_elements; + +enum u_fetch_alignment { + U_VERTEX_FETCH_BYTE_ALIGNED, + U_VERTEX_FETCH_DWORD_ALIGNED +}; + + +struct u_vbuf_mgr * +u_vbuf_mgr_create(struct pipe_context *pipe, + unsigned upload_buffer_size, + unsigned upload_buffer_alignment, + unsigned upload_buffer_bind, + enum u_fetch_alignment fetch_alignment); + +void u_vbuf_mgr_destroy(struct u_vbuf_mgr *mgr); + +struct u_vbuf_mgr_elements * +u_vbuf_mgr_create_vertex_elements(struct u_vbuf_mgr *mgr, + unsigned count, + const struct pipe_vertex_element *attrs, + struct pipe_vertex_element *native_attrs); + +void u_vbuf_mgr_bind_vertex_elements(struct u_vbuf_mgr *mgr, + void *cso, + struct u_vbuf_mgr_elements *ve); + +void u_vbuf_mgr_destroy_vertex_elements(struct u_vbuf_mgr *mgr, + struct u_vbuf_mgr_elements *ve); + +void u_vbuf_mgr_set_vertex_buffers(struct u_vbuf_mgr *mgr, + unsigned count, + const struct pipe_vertex_buffer *bufs); + +void u_vbuf_mgr_draw_begin(struct u_vbuf_mgr *mgr, + const struct pipe_draw_info *info, + boolean *buffers_updated, + boolean *uploader_flushed); + +void u_vbuf_mgr_draw_end(struct u_vbuf_mgr *mgr); + + +static INLINE struct u_vbuf_resource *u_vbuf_resource(struct pipe_resource *r) +{ + return (struct u_vbuf_resource*)r; +} + +#endif -- cgit v1.2.3